package org.mobicents.slee.container.component.deployment.jaxb.descriptors;
import java.io.InputStream;
import javax.slee.management.DeploymentException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.log4j.Logger;
import org.mobicents.slee.container.component.deployment.xml.DefaultSleeEntityResolver;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
public abstract class AbstractDescriptorFactory {
private static final Logger logger = Logger.getLogger(AbstractDescriptorFactory.class);
private static final DocumentBuilder documentBuilder = initDocumentBuilder();
private static final JAXBContext jaxbContext10 = initJAXBContext10();
private static final JAXBContext jaxbContext11 = initJAXBContext11();
private static JAXBContext initJAXBContext10() {
try {
return JAXBContext.newInstance("org.mobicents.slee.container.component.deployment.jaxb.slee.du"
+ ":org.mobicents.slee.container.component.deployment.jaxb.slee.event"
+ ":org.mobicents.slee.container.component.deployment.jaxb.slee.ratype"
+ ":org.mobicents.slee.container.component.deployment.jaxb.slee.ra"
+ ":org.mobicents.slee.container.component.deployment.jaxb.slee.sbb"
+ ":org.mobicents.slee.container.component.deployment.jaxb.slee.service"
+ ":org.mobicents.slee.container.component.deployment.jaxb.slee.profile");
} catch (Exception e) {
logger.error("Failed to create jaxb context", e);
//we cant throw exception
return null;
}
}
private static DocumentBuilder initDocumentBuilder() {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(true);
DocumentBuilder builder = factory.newDocumentBuilder();
builder.setEntityResolver(new DefaultSleeEntityResolver(Thread.currentThread().getContextClassLoader()));
builder.setErrorHandler(new PrivateErrorHandler());
return builder;
} catch (Exception e) {
logger.error("Failed to create DOM builder", e);
return null;
}
}
private static JAXBContext initJAXBContext11() {
try {
return JAXBContext
.newInstance(":org.mobicents.slee.container.component.deployment.jaxb.slee11.du"
+ ":org.mobicents.slee.container.component.deployment.jaxb.slee11.event"
+ ":org.mobicents.slee.container.component.deployment.jaxb.slee11.ratype"
+ ":org.mobicents.slee.container.component.deployment.jaxb.slee11.ra"
+ ":org.mobicents.slee.container.component.deployment.jaxb.slee11.sbb"
+ ":org.mobicents.slee.container.component.deployment.jaxb.slee11.service"
+ ":org.mobicents.slee.container.component.deployment.jaxb.slee11.profile"
+ ":org.mobicents.slee.container.component.deployment.jaxb.slee11.library");
} catch (Exception e) {
logger.error("failed to create jaxb context"+e);
//we cant throw exception
return null;
}
}
protected Object buildJAXBPojo(InputStream inputStream) throws DeploymentException {
if (inputStream == null) {
throw new NullPointerException("null input stream");
}
// first we parse into dom, which validates dtd
Document document = null;
try {
document = documentBuilder.parse(inputStream);
// trim text nodes in parsed document
trimTextChildNodes(document.getDocumentElement());
} catch (SAXException e) {
throw new DeploymentException("Failed to parse descriptor into dom document cause: \""+e.getMessage()+"\"");
}catch (Exception e) {
throw new DeploymentException("Failed to parse descriptor into dom document",e);
}
finally {
try {
inputStream.close();
} catch (Exception e) {
logger.error("failed to close inputstream ",e);
}
}
//By default this is: http://java.sun.com/dtd/slee-deployable-unit_1_1.dtd
DocumentType documentType = document.getDoctype();
if(documentType==null || documentType.getSystemId()==null)
{
throw new DeploymentException("Doctype not present in xml file or invalid. Document can not be recognized as valid descriptor nor parsed");
}
boolean isSlee11 = documentType.getSystemId().endsWith("_1_1.dtd");
// now we build the descriptor pojo with jaxb
Unmarshaller unmarshaller = getUnmarshaller(!isSlee11);
try {
return unmarshaller.unmarshal(document);
} catch (JAXBException e) {
throw new DeploymentException("failed to unmarshall descriptor with jaxb",e);
}
}
private void trimTextChildNodes(Node node) {
if (node.getNodeType() == Node.TEXT_NODE) {
node.setNodeValue(node.getNodeValue().trim());
}
else {
NodeList childNodesList = node.getChildNodes();
for (int i=0;i< childNodesList.getLength();i++) {
trimTextChildNodes(childNodesList.item(i));
}
}
}
private Unmarshaller getUnmarshaller(boolean isV10) throws DeploymentException {
try {
if(isV10)
{
return jaxbContext10.createUnmarshaller();
}
else
{
return jaxbContext11.createUnmarshaller();
}
}catch(NullPointerException npe) {
throw new DeploymentException("Failed to create unmarshaler, probably context has not been create, see console for error.", npe);
} catch (Exception e) {
throw new DeploymentException("Failed to create unmarshaler!",e);
}
}
static class PrivateErrorHandler implements ErrorHandler
{
public void error(SAXParseException e) throws SAXException {
throw new SAXException("Error. Failed to parse due to: "+e.getMessage());
}
public void fatalError(SAXParseException e) throws SAXException {
throw new SAXException("Fatal error. Failed to parse due to: "+e.getMessage());
}
public void warning(SAXParseException e) throws SAXException {
logger.error(e.getMessage());
}
}
}