at.spardat.xma.boot.comp.data.XMAAppParser Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2003, 2007 s IT Solutions AT Spardat GmbH .
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* s IT Solutions AT Spardat GmbH - initial API and implementation
*******************************************************************************/
/*
* Created on : 04.2003
* Created by : s3595
*/
package at.spardat.xma.boot.comp.data;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Locale;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.DTDHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import at.spardat.xma.boot.comp.DTDStatics;
import at.spardat.xma.boot.logger.ILogger;
import at.spardat.xma.boot.logger.LogLevel;
import at.spardat.xma.boot.util.Util;
/**
*
* class: XMAAppParser
*
* @author s3595 Chris Sch?fer (CGS)
* @version $Id: XMAAppParser.java 10853 2013-06-28 12:02:20Z dschwarz $
*/
public class XMAAppParser extends DefaultHandler implements DTDHandler {
private static String DEFAULT_DTD = "xma-app.dtd"; //$NON-NLS-1$
private static String DEFAULT_DTD_PACKAGE = "at/spardat/xma/boot/comp/"; // "at.spardat.xma.boot.comp."; //$NON-NLS-1$
private static String DTD_PUBLIC_ID = "-//Spardat//IMC-XMA//EN"; //$NON-NLS-1$
/** validate xml */
private static boolean validation_ = false;
/** parser */
private javax.xml.parsers.SAXParser parser_;
/** logger */
private ILogger log_;
/** parsed application */
private XMAApp xmaApp_;
/** current component */
private XMAComponent currentComponent;
/** current plugin */
private XMAPluginImpl currentPluginImpl_;
/** current SWT description */
private XMASWTDescription currentSWTDescription;
/** supported tags (must be sorted) */
private static final String[] tags = {
DTDStatics.CERTIFICATE,
DTDStatics.COMPONENT,
DTDStatics.ISSUER,
DTDStatics.PLUGIN_IMPL,
DTDStatics.PLUGIN_SPEC,
DTDStatics.PREINSTALL,
DTDStatics.RESOURCE,
DTDStatics.RESOURCE_LINK,
DTDStatics.SSL_RESTRICTION,
DTDStatics.SUBJECT,
DTDStatics.SWT_DESCRIPTION,
DTDStatics.XMA_Application,
};
private static final int TAG_CERTIFICATE = 0;
private static final int TAG_COMPONENT = 1;
private static final int TAG_ISSUER = 2;
private static final int TAG_PLUGIN_IMPL = 3;
private static final int TAG_PLUGIN_SPEC = 4;
private static final int TAG_PREINSTALL = 5;
private static final int TAG_RESOURCE = 6;
private static final int TAG_RESOURCELINK = 7;
private static final int TAG_SSL_RESTRICTION = 8;
private static final int TAG_SUBJECT = 9;
private static final int TAG_SWT_DESCRIPTION = 10;
private static final int TAG_APP = 11;
private int countUnknownTag = 0;
public XMAAppParser( ILogger log_, boolean bValidation) {
init( log_, bValidation);
}
/** constructor */
public XMAAppParser( ILogger log_ ) {
init(log_, false );
}
private void init( ILogger log_, boolean bValidation) {
validation_ = bValidation;
if( log_ == null ) throw new NullPointerException();
this.log_ = log_;
currentComponent = null;
currentPluginImpl_ = null;
xmaApp_ = null;
try {
initParser();
} catch (Exception e) {
log_.log(LogLevel.SEVERE,"XML parser configuration error: ",e);
throw new RuntimeException("XML parser configuration error: ",e);
}
}
/** initialize parser
* @throws SAXException
* @throws ParserConfigurationException*/
protected void initParser() throws ParserConfigurationException, SAXException {
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setValidating(validation_);
parser_ = spf.newSAXParser();
XMLReader xmlreader = parser_.getXMLReader();
xmlreader.setDTDHandler(this);
xmlreader.setEntityResolver( this );
}
/**
* get the dtd out of the classloader.
* on development, if class-directory is seperated, build should copy the dtd into the classes dir.
*/
public InputSource resolveEntity(String publicId, String systemId) {
log_.log(LogLevel.INFO, "resolvedEntity: \"{0}\" with sysid: \"{1}\"", new Object[] {publicId,systemId} ); //$NON-NLS-1$
if (XMAAppParser.DTD_PUBLIC_ID.equals(publicId) ) {
String strClass = XMAAppParser.DEFAULT_DTD_PACKAGE + XMAAppParser.DEFAULT_DTD;
InputStream in = getClass().getClassLoader().getResourceAsStream( strClass );
return new InputSource( in );
}
return null;
}
/**
* parse is the main method for parsing configuration files
* @param is the input stream to the data to parse
* @throws IOException
* @throws SAXException
*/
public XMAApp parse( InputStream is ) throws IOException, SAXException {
try {
parser_.parse( new InputSource(is), this );
XMAApp ret = this.xmaApp_;
this.xmaApp_ = null;
return ret;
} catch( IOException e ) {
log_.log(LogLevel.SEVERE, "parser error: ", e); //$NON-NLS-1$
throw e;
} catch (SAXException e) {
log_.log(LogLevel.SEVERE, "parser error: ", e); //$NON-NLS-1$
throw e;
}
}
/**
* parse is the main method for parsing configuration files
* @param strURI Is a String parameter. It is used as a URI to the XML-file location.
*/
public XMAApp parse( String strURI ) throws IOException, SAXException {
try {
parser_.parse( strURI, this );
XMAApp ret = this.xmaApp_;
this.xmaApp_ = null;
return ret;
} catch( IOException e ) {
log_.log(LogLevel.SEVERE, "parser error: ", e); //$NON-NLS-1$
throw e;
} catch (SAXException e) {
log_.log(LogLevel.SEVERE, "parser error: ", e); //$NON-NLS-1$
throw e;
}
}
/** @see org.xml.sax.ContentHandler#startDocument() */
public void startDocument() throws SAXException { }
/** @see org.xml.sax.ContentHandler#endDocument() */
public void endDocument() throws SAXException { }
/** @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes) */
public void startElement(String nsURI, String localName, String qName, Attributes attrs)
throws SAXException {
this.switchElementHandler( nsURI,localName,qName,attrs);
}
/** @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, java.lang.String) */
public void endElement(String nsURI, String localName, String qName)
throws SAXException {
this.switchElementHandler( nsURI,localName, qName, null);
}
/**
* see element dispatcher
*/
protected void switchElementHandler(String nsURI, String localName, String qName, Attributes attrs)
throws SAXException {
switch (Arrays.binarySearch(tags, qName )) {
case TAG_APP: handleApp(attrs); break;
case TAG_COMPONENT: handleComponent(attrs); break;
case TAG_PLUGIN_IMPL: handlePluginImpl(attrs); break;
case TAG_PLUGIN_SPEC: handlePluginSpec(attrs); break;
case TAG_RESOURCE: handleResource(attrs); break;
case TAG_RESOURCELINK: handleResLink(attrs); break;
case TAG_SWT_DESCRIPTION: handleSWTDescription(attrs); break;
case TAG_PREINSTALL: handlePreinstall(attrs); break;
case TAG_SSL_RESTRICTION: handleSSLRestriction(attrs); break;
case TAG_CERTIFICATE: handleCertificate(attrs); break;
case TAG_SUBJECT: handleSubject(attrs); break;
case TAG_ISSUER: handleIssuer(attrs); break;
default: handleUnknownTag(attrs);
}
}
protected void handleUnknownTag(Attributes attrs)
throws SAXException {
if (attrs != null) {
countUnknownTag++;
} else { /* tag close */
countUnknownTag--;
}
}
private XMASSLRestriction currentSSLRestriction = null;
boolean isSubject = false;
boolean isIssuer = false;
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (isSubject) {
currentSSLRestriction.setSubject(new String(ch, start, length));
} else if (isIssuer) {
currentSSLRestriction.setIssuer(new String(ch, start, length));
}
}
/**
*
* @param attrs Attributes to this element
* @throws SAXException
*/
protected void handleSSLRestriction(Attributes attrs)
throws SAXException {
if(isUnknownTag()) return;
if (attrs != null) {
currentSSLRestriction = new XMASSLRestriction();
currentSSLRestriction.setHostname(attrs.getValue( DTDStatics.SSL_RESTRICTION_HOSTNAME ));
} else {
xmaApp_.addSSLRestriction(currentSSLRestriction);
currentSSLRestriction = null;
}
}
/**
*
* @param attrs Attributes to this element
* @throws SAXException
*/
protected void handleCertificate(Attributes attrs)
throws SAXException {
if(isUnknownTag()) return;
}
/**
*
* @param attrs Attributes to this element
* @throws SAXException
*/
protected void handleSubject(Attributes attrs)
throws SAXException {
if(isUnknownTag()) return;
isSubject = attrs != null;
}
/**
*
* @param attrs Attributes to this element
* @throws SAXException
*/
protected void handleIssuer(Attributes attrs)
throws SAXException {
if(isUnknownTag()) return;
isIssuer = attrs != null;
}
/**
*
* @param attrs Attributes to this element
* @throws SAXException
*/
protected void handleApp(Attributes attrs)
throws SAXException {
if(isUnknownTag()) return;
if (attrs != null) {
this.xmaApp_ = new XMAApp( );
} else { /* tag close */
}
}
/**
* handle component parsing
*/
protected void handleComponent(Attributes attrs) throws SAXException {
if(isUnknownTag()) return;
if (attrs != null) {
String name = attrs.getValue( DTDStatics.COMPONENT_NAME );
String impl = attrs.getValue( DTDStatics.COMPONENT_IMPLPACKAGE );
if( xmaApp_ == null )
throw new SAXException( "parser error"); //$NON-NLS-1$
currentComponent = new XMAComponent(name, impl);
currentComponent.setApplication(xmaApp_);
xmaApp_.addComponent(currentComponent);
} else { /* tag close */
this.currentComponent = null ;
}
}
/**
* e.g.:
*
* @param attrs Attributes to this element
* @throws SAXException
*/
protected void handleResource(Attributes attrs) throws SAXException {
if(isUnknownTag()) return;
if (attrs != null) {
Locale locale = null;
Version version = null;
String strHref = attrs.getValue( DTDStatics.RESOURCE_HREF );
String strVersion = attrs.getValue( DTDStatics.RESOURCE_VERSION );
String strType = attrs.getValue( DTDStatics.RESOURCE_TYPE );
String strLocale = attrs.getValue( DTDStatics.RESOURCE_LOCALE );
String strShared = attrs.getValue( DTDStatics.RESOURCE_SHARED );
String strFdmLoad = attrs.getValue(DTDStatics.RESOURCE_FDMLOAD );
String os = attrs.getValue( DTDStatics.RESOURCE_OSNAME);
String arch = attrs.getValue(DTDStatics.RESOURCE_OSARCH);
XMAResource.TypeID tid = XMAResource.TypeID.getID(strType);
if( strLocale != null ) {
locale = Util.getInstance().getLocale(strLocale);
}
if(strVersion == null ) {
throw new SAXException( "missing version"); //$NON-NLS-1$
} else {
version = new Version(strVersion);
}
boolean shared=false;
if("true".equalsIgnoreCase(strShared)) {
shared=true;
}
XMAResource res = new XMAResource( strHref, version, tid, locale, shared,os, arch);
if("true".equalsIgnoreCase(strFdmLoad)) {
res.setFdmload(true);
}
if( currentComponent != null ) {
currentComponent.addResource(res);
} else if( currentPluginImpl_ != null ) {
currentPluginImpl_.addResource(res);
} else if(currentSWTDescription != null) {
currentSWTDescription.addResource(res);
} else
xmaApp_.addResource( res );
}// end if
}
/**
* handle parsing of resource links
*/
protected void handleResLink(Attributes attrs)
throws SAXException {
if(isUnknownTag()) return;
if (attrs != null) {
String strHref = attrs.getValue( DTDStatics.RESOURCE_HREF );
XMAResourceLink rl = new XMAResourceLink( strHref );
if( currentComponent != null ) {
currentComponent.addResourceLink(rl);
} else if( currentPluginImpl_ != null ) {
currentPluginImpl_.addResourceLink( rl );
} else
throw new SAXException( "parser error. resource link not in component or plugin"); //$NON-NLS-1$
}
}
/**
* handles parsing of plug in impl info
*/
protected void handlePluginImpl(Attributes attrs)
throws SAXException {
if(isUnknownTag()) return;
if (attrs != null) {
String implClient = attrs.getValue( DTDStatics.PLUGIN_IMPL_CLIENT );
String implServer = attrs.getValue( DTDStatics.PLUGIN_IMPL_SERVER );
String strImplements = attrs.getValue( DTDStatics.PLUGIN_IMPL_IMPLEMENTS );
XMAPluginImpl pi = new XMAPluginImpl( implClient, implServer, strImplements);
xmaApp_.addPluginImpl(pi);
currentPluginImpl_ = pi;
} else {
currentPluginImpl_ = null;
}
}
/**
* handles parsing of tag plugin spec
*/
protected void handlePluginSpec(Attributes attrs)
throws SAXException {
if(isUnknownTag()) return;
if (attrs != null) {
String strRequires = attrs.getValue( DTDStatics.PLUGIN_SPEC_REQUIRES );
XMAPluginSpec pis = new XMAPluginSpec( strRequires );
xmaApp_.addPluginSpec( pis );
}
}
/**
* handles parsing of tag swt-description
*/
protected void handleSWTDescription(Attributes attrs) throws SAXException {
if(isUnknownTag()) return;
if(attrs!=null) {
XMASWTDescription swtDescription = new XMASWTDescription();
if(xmaApp_.getSwtDescription()!=null) {
throw new SAXException("parser error. duplicate <"+DTDStatics.SWT_DESCRIPTION+"> tag detected. Only one <"+DTDStatics.SWT_DESCRIPTION+"> tag is allowed.");
}
xmaApp_.setSwtDescription(swtDescription);
currentSWTDescription=swtDescription;
} else {
currentSWTDescription=null;
}
}
/**
* handles parsing of tag preinstall
*/
protected void handlePreinstall(Attributes attrs) throws SAXException {
if(isUnknownTag()) return;
if(attrs!=null) {
String version = attrs.getValue(DTDStatics.PREINSTALL_VERSION);
SWTPreinstall preinstall = new SWTPreinstall(version);
if(currentSWTDescription!=null) {
currentSWTDescription.addPreinstall(preinstall);
} else {
throw new SAXException("parser error. preinstall not in <"+DTDStatics.SWT_DESCRIPTION+"> tag");
}
}
}
/**
* This is a helper method to make sure a codebase string will work as a codebase URL
* by forcing a "/" on the end of the string.
*/
protected static final String fixCodebaseString(String s) {
if (s == null || s.endsWith("/")) { //$NON-NLS-1$
return s; }
return (s + "/"); //$NON-NLS-1$
}
/**
* @see org.xml.sax.ErrorHandler#fatalError(org.xml.sax.SAXParseException)
*/
public void fatalError(SAXParseException e)
throws SAXParseException {
log_.log(LogLevel.SEVERE, "XML parse error at line: {0} with public-id: \"{1}\"", new Object[] { new Integer(e.getLineNumber()),e.getPublicId() } ); //$NON-NLS-1$
throw (SAXParseException) e;
}
/**
* @see org.xml.sax.ErrorHandler#warning(org.xml.sax.SAXParseException)
*/
public void warning(SAXParseException e) {
log_.log(LogLevel.WARNING, "XML parse-warning at line: {0} with public-id: \"{1}\"", new Object[] { new Integer(e.getLineNumber()),e.getPublicId() } ); //$NON-NLS-1$
}
/**
* @see org.xml.sax.ErrorHandler#error(org.xml.sax.SAXParseException)
*/
public void error(SAXParseException e)
throws SAXParseException {
log_.log(LogLevel.SEVERE, "XML parse error at line: {0} with public-id: \"{1}\"", new Object[] { new Integer(e.getLineNumber()),e.getPublicId() } ); //$NON-NLS-1$
throw (SAXParseException) e;
}
/**
* Returns true if the parser stands in an unknown tag.
* Needed as an unknown tag and anything in it is ignored.
* @return true if the parser stands in an unknown tag, otherwise false
*/
private boolean isUnknownTag(){
return countUnknownTag > 0;
}
}