1 16 package scriptella.configuration; 17 18 import org.w3c.dom.Document ; 19 import org.xml.sax.EntityResolver ; 20 import org.xml.sax.ErrorHandler ; 21 import org.xml.sax.InputSource ; 22 import org.xml.sax.SAXParseException ; 23 import scriptella.core.ThreadSafe; 24 25 import javax.xml.parsers.DocumentBuilder ; 26 import javax.xml.parsers.DocumentBuilderFactory ; 27 import java.io.IOException ; 28 import java.net.URL ; 29 import java.util.LinkedHashMap ; 30 import java.util.Map ; 31 import java.util.logging.Logger ; 32 33 34 40 public class ConfigurationFactory { 41 private static final Logger LOG = Logger.getLogger(ConfigurationFactory.class.getName()); 42 private static final DocumentBuilderFactory DBF = DocumentBuilderFactory.newInstance(); 43 private static final String DTD_NAME = "etl.dtd"; 44 private URL resourceURL; 45 private Map <String , ?> externalProperties; 46 47 static { 48 setValidating(true); 49 } 50 51 52 57 public static void setValidating(boolean validating) { 58 DBF.setValidating(validating); 59 } 60 61 public ConfigurationFactory() { 62 } 63 64 public URL getResourceURL() { 65 return resourceURL; 66 } 67 68 public void setResourceURL(final URL resourceURL) { 69 this.resourceURL = resourceURL; 70 } 71 72 77 @ThreadSafe 78 public Map <String , ?> getExternalProperties() { 79 return externalProperties; 80 } 81 82 90 @ThreadSafe 91 public void setExternalProperties(final Map <String , ?> externalProperties) { 92 if (externalProperties == null) { 93 this.externalProperties = null; 94 } else { 95 this.externalProperties = new LinkedHashMap <String , Object >(externalProperties); 96 } 97 } 98 99 public ConfigurationEl createConfiguration() { 100 if (resourceURL == null) { 101 throw new ConfigurationException("Configuration URL is required"); 102 } 103 try { 104 DocumentBuilder db = DBF.newDocumentBuilder(); 105 db.setEntityResolver(new EntityResolver () { 106 public InputSource resolveEntity(final String publicId, 107 final String systemId) { 108 if (systemId != null && systemId.trim().endsWith(DTD_NAME)) { 109 return new InputSource (ConfigurationFactory.class.getResourceAsStream( 110 "/scriptella/dtd/" + DTD_NAME)); 111 } 112 113 return null; 114 } 115 }); 116 db.setErrorHandler(new ErrorHandler () { 117 public void warning(final SAXParseException exception) { 118 LOG.warning(messageFor(exception)); 119 } 120 121 public void error(final SAXParseException exception) { 122 LOG.warning(messageFor(exception)); 123 } 124 125 private String messageFor(final SAXParseException exception) { 126 StringBuilder sb = new StringBuilder (32); 127 sb.append("XML configuration warning in "); 128 129 final String sid = exception.getSystemId(); 130 131 if (sid != null) { 132 sb.append(sid); 133 } else { 134 sb.append("the document"); 135 } 136 137 sb.append('('); 138 sb.append(exception.getLineNumber()); 139 sb.append(':'); 140 sb.append(exception.getColumnNumber()); 141 sb.append("): "); 142 sb.append(exception.getMessage()); 143 144 return sb.toString(); 145 } 146 147 public void fatalError(final SAXParseException exception) { 148 LOG.severe(messageFor(exception)); 149 } 150 }); 151 152 final InputSource inputSource = new InputSource (resourceURL.toString()); 153 final Document document = db.parse(inputSource); 154 PropertiesMerger merger = externalProperties == null ? 155 new PropertiesMerger() : new PropertiesMerger(externalProperties); 156 157 return new ConfigurationEl(new XmlElement( 158 document.getDocumentElement(), resourceURL, merger.getSubstitutor()), merger); 159 } catch (IOException e) { 160 throw new ConfigurationException("Unable to load document: " + e.getMessage(), e); 161 } catch (Exception e) { 162 throw new ConfigurationException("Unable to parse document: " + e.getMessage(), e); 163 } 164 } 165 } 166 | Popular Tags |