package org.jboss.metadata;
import org.jboss.deployment.DeploymentException;
import org.jboss.logging.Logger;
import org.jboss.util.xml.JBossEntityResolver;
import org.w3c.dom.Document;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
public class XmlFileLoader
{
private static boolean defaultValidateDTDs = false;
private static Logger log = Logger.getLogger(XmlFileLoader.class);
private URLClassLoader classLoader;
private ApplicationMetaData metaData;
private boolean validateDTDs;
public static boolean getDefaultValidateDTDs()
{
return defaultValidateDTDs;
}
public static void setDefaultValidateDTDs(boolean validate)
{
defaultValidateDTDs = validate;
}
public XmlFileLoader()
{
this(defaultValidateDTDs);
}
public XmlFileLoader(boolean validateDTDs)
{
this.validateDTDs = validateDTDs;
}
public ApplicationMetaData getMetaData()
{
return metaData;
}
public void setClassLoader(URLClassLoader cl)
{
classLoader = cl;
}
public ClassLoader getClassLoader()
{
return classLoader;
}
public boolean getValidateDTDs()
{
return validateDTDs;
}
public void setValidateDTDs(boolean validate)
{
this.validateDTDs = validate;
}
public ApplicationMetaData load(URL alternativeDD) throws Exception
{
URL ejbjarUrl = null;
if (alternativeDD != null)
{
log.debug("Using alternativeDD: " + alternativeDD);
ejbjarUrl = alternativeDD;
}
else
{
ejbjarUrl = getClassLoader().getResource("META-INF/ejb-jar.xml");
}
if (ejbjarUrl == null)
{
throw new DeploymentException("no ejb-jar.xml found");
}
metaData = new ApplicationMetaData();
metaData.setResourceClassLoader(classLoader);
Document ejbjarDocument = getDocumentFromURL(ejbjarUrl);
metaData.setUrl(ejbjarUrl);
metaData.importEjbJarXml(ejbjarDocument.getDocumentElement());
URL defaultJbossUrl = Thread.currentThread().getContextClassLoader().getResource("standardjboss.xml");
if (defaultJbossUrl == null)
{
throw new DeploymentException("no standardjboss.xml found");
}
Document defaultJbossDocument = null;
try
{
defaultJbossDocument = getDocumentFromURL(defaultJbossUrl);
metaData.setUrl(defaultJbossUrl);
metaData.importJbossXml(defaultJbossDocument.getDocumentElement());
}
catch (Exception ex)
{
log.error("failed to load standardjboss.xml. There could be a syntax error.", ex);
throw ex;
}
try
{
URL jbossUrl = getClassLoader().getResource("META-INF/jboss.xml");
if (jbossUrl != null)
{
Document jbossDocument = getDocumentFromURL(jbossUrl);
metaData.setUrl(jbossUrl);
metaData.importJbossXml(jbossDocument.getDocumentElement());
}
}
catch (Exception ex)
{
log.error("failed to load jboss.xml. There could be a syntax error.", ex);
throw ex;
}
return metaData;
}
public static Document getDocument(URL url) throws DeploymentException
{
return getDocument(url, defaultValidateDTDs);
}
public static Document getDocument(URL url, boolean validateDTDs) throws DeploymentException
{
XmlFileLoader loader = new XmlFileLoader(validateDTDs);
return loader.getDocumentFromURL(url);
}
public Document getDocumentFromURL(URL url) throws DeploymentException
{
InputStream is = null;
try
{
is = url.openStream();
return getDocument(is, url.toExternalForm());
}
catch (IOException e)
{
throw new DeploymentException("Failed to obtain xml doc from URL", e);
}
}
public Document getDocument(InputStream is, String inPath)
throws DeploymentException
{
InputSource is2 = new InputSource(is);
is2.setSystemId(inPath);
Document doc = null;
try
{
doc = getDocument(is2, inPath);
}
finally
{
try
{
if( is != null )
is.close();
}
catch (Exception e)
{
}
}
return doc;
}
public Document getDocument(InputSource is, String inPath)
throws DeploymentException
{
try
{
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
docBuilderFactory.setValidating(validateDTDs);
docBuilderFactory.setNamespaceAware(true);
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
JBossEntityResolver lr = new JBossEntityResolver();
LocalErrorHandler eh = new LocalErrorHandler( inPath, lr );
docBuilder.setEntityResolver(lr);
docBuilder.setErrorHandler(eh );
Document doc = docBuilder.parse(is);
if(validateDTDs && eh.hadError())
{
throw new DeploymentException("Invalid XML: file=" + inPath);
}
return doc;
}
catch (DeploymentException e)
{
throw e;
}
catch (SAXParseException e)
{
String msg = "Invalid XML: file=" + inPath+"@"+e.getColumnNumber()+":"+e.getLineNumber();
log.error(msg, e);
throw new DeploymentException(msg, e);
}
catch (SAXException e)
{
System.out.println(e.getException());
throw new DeploymentException("Invalid XML: file=" + inPath, e);
}
catch (Exception e)
{
throw new DeploymentException("Invalid XML: file=" + inPath, e);
}
}
private static class LocalErrorHandler implements ErrorHandler
{
private String theFileName;
private JBossEntityResolver localResolver;
private boolean error;
public LocalErrorHandler( String inFileName, JBossEntityResolver localResolver )
{
this.theFileName = inFileName;
this.localResolver = localResolver;
this.error = false;
}
public void error(SAXParseException exception)
{
if ( localResolver.isEntityResolved() )
{
this.error = true;
log.error("XmlFileLoader: File "
+ theFileName
+ " process error. Line: "
+ String.valueOf(exception.getLineNumber())
+ ". Error message: "
+ exception.getMessage()
);
} }
public void fatalError(SAXParseException exception)
{
if ( localResolver.isEntityResolved() )
{
this.error = true;
log.error("XmlFileLoader: File "
+ theFileName
+ " process fatal error. Line: "
+ String.valueOf(exception.getLineNumber())
+ ". Error message: "
+ exception.getMessage()
);
} }
public void warning(SAXParseException exception)
{
if ( localResolver.isEntityResolved() )
{
this.error = true;
log.error("XmlFileLoader: File "
+ theFileName
+ " process warning. Line: "
+ String.valueOf(exception.getLineNumber())
+ ". Error message: "
+ exception.getMessage()
);
} }
public boolean hadError() {
return error;
}
}}