1 package org.objectweb.celtix.configuration.impl; 2 3 import java.io.IOException ; 4 import java.io.InputStream ; 5 import java.util.logging.Level ; 6 import java.util.logging.Logger ; 7 8 import javax.xml.XMLConstants ; 9 import javax.xml.namespace.QName ; 10 import javax.xml.parsers.DocumentBuilder ; 11 import javax.xml.parsers.DocumentBuilderFactory ; 12 import javax.xml.parsers.ParserConfigurationException ; 13 import javax.xml.transform.Source ; 14 import javax.xml.transform.dom.DOMSource ; 15 import javax.xml.transform.stream.StreamSource ; 16 import javax.xml.validation.Schema ; 17 import javax.xml.validation.SchemaFactory ; 18 import javax.xml.validation.Validator ; 19 20 import org.w3c.dom.Document ; 21 import org.w3c.dom.Element ; 22 import org.w3c.dom.Node ; 23 24 import org.xml.sax.ErrorHandler ; 25 import org.xml.sax.InputSource ; 26 import org.xml.sax.SAXException ; 27 import org.xml.sax.SAXParseException ; 28 29 import org.objectweb.celtix.common.i18n.Message; 30 import org.objectweb.celtix.common.logging.LogUtils; 31 import org.objectweb.celtix.configuration.ConfigurationException; 32 import org.objectweb.celtix.configuration.ConfigurationItemMetadata.LifecyclePolicy; 33 import org.objectweb.celtix.configuration.ConfigurationMetadata; 34 import org.objectweb.celtix.resource.DefaultResourceManager; 35 36 37 public class ConfigurationMetadataBuilder { 38 39 final class ValidatorErrorHandler implements ErrorHandler { 40 41 public void error(SAXParseException exception) throws SAXException { 42 throw exception; 43 } 44 45 public void fatalError(SAXParseException exception) throws SAXException { 46 throw exception; 47 } 48 49 public void warning(SAXParseException exception) throws SAXException { 50 throw exception; 51 } 52 } 53 private static final Logger LOG = LogUtils.getL7dLogger(ConfigurationMetadataBuilder.class); 54 private static final String MEATADATA_NAMESPACE_URI = 55 "http://celtix.objectweb.org/configuration/metadata"; 56 private static Schema metadataSchema; 57 private static Validator metadataValidator; 58 59 private static ErrorHandler validatorErrorHandler; 60 61 private final ConfigurationMetadataImpl model; 62 private final boolean forceDefaults; 63 private boolean doValidate; 64 65 public ConfigurationMetadataBuilder(boolean fd) { 66 model = new ConfigurationMetadataImpl(); 67 forceDefaults = fd; 68 } 69 70 public void setValidation(boolean onOff) { 71 doValidate = onOff; 72 } 73 74 public ConfigurationMetadata build(InputSource is) throws IOException { 75 parseXML(is); 76 return model; 77 } 78 79 public ConfigurationMetadata build(InputStream is) throws IOException { 80 return build(new InputSource (is)); 81 } 82 83 private void deserializeConfig(Document document) { 84 Element root = document.getDocumentElement(); 85 model.setNamespaceURI(root.getAttribute("namespace")); 86 model.setParentNamespaceURI(root.getAttribute("parentNamespace")); 87 } 88 89 private void deserializeConfigItem(Document document, Element configItemElement) { 90 91 ConfigurationItemMetadataImpl item = new ConfigurationItemMetadataImpl(); 92 93 for (Node nd = configItemElement.getFirstChild(); nd != null; nd = nd.getNextSibling()) { 94 if (Node.ELEMENT_NODE != nd.getNodeType()) { 95 continue; 96 } else if ("name".equals(nd.getLocalName())) { 97 item.setName(ConfigurationMetadataUtils.getElementValue(nd)); 98 } else if ("type".equals(nd.getLocalName())) { 99 QName type = ConfigurationMetadataUtils.elementValueToQName(document, 100 (Element )nd); 101 item.setType(type); 102 if (doValidate) { 103 if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(type.getNamespaceURI())) { 104 continue; 105 } 106 TypeSchema ts = new TypeSchemaHelper(forceDefaults).get(type.getNamespaceURI()); 107 if (ts == null) { 108 throw new ConfigurationException (new Message("NO_TYPESCHEMA_FOR_NAMESPACE_EXC", LOG, 109 type.getNamespaceURI())); 110 } 111 if (!ts.hasType(type.getLocalPart())) { 112 throw new ConfigurationException (new Message("TYPE_NOT_DEFINED_IN_NAMESPACE_EXC", 113 LOG, type.getLocalPart(), type 114 .getNamespaceURI())); 115 } 116 } 117 } else if ("description".equals(nd.getLocalName())) { 118 } else if ("lifecyclePolicy".equals(nd.getLocalName())) { 120 String value = ConfigurationMetadataUtils.getElementValue(nd); 121 if (null != value) { 122 if ("static".equals(value)) { 123 item.setLifecyclePolicy(LifecyclePolicy.STATIC); 124 } else if ("process".equals(value)) { 125 item.setLifecyclePolicy(LifecyclePolicy.PROCESS); 126 } else if ("bus".equals(value)) { 127 item.setLifecyclePolicy(LifecyclePolicy.BUS); 128 } else { 129 item.setLifecyclePolicy(LifecyclePolicy.DYNAMIC); 130 } 131 } 132 } else { 133 deserializeDefaultValue(item, (Element )nd); 135 } 136 } 137 138 model.addItem(item); 139 } 140 141 private void deserializeConfigItems(Document document) { 142 for (Node nd = document.getDocumentElement().getFirstChild(); nd != null; nd = nd.getNextSibling()) { 143 if (Node.ELEMENT_NODE == nd.getNodeType() 144 && "configItem".equals(nd.getLocalName()) 145 && MEATADATA_NAMESPACE_URI.equals(nd.getNamespaceURI())) { 146 Element configItemElement = (Element )nd; 147 deserializeConfigItem(document, configItemElement); 148 } 149 } 150 } 151 152 private void deserializeDefaultValue(ConfigurationItemMetadataImpl item, Element data) { 153 176 String elementName = data.getLocalName(); 177 String namespaceURI = data.getNamespaceURI(); 178 TypeSchema ts = new TypeSchemaHelper(forceDefaults).get(namespaceURI); 179 QName type = null; 180 if (null != ts) { 181 type = ts.getDeclaredType(elementName); 182 } 183 if (null == ts || null == type) { 184 System.err.println(elementName); 185 System.err.println(namespaceURI); 186 System.err.println(ts); 187 System.err.println(type); 188 throw new ConfigurationException (new Message("INVALID_ELEMENT_FOR_DEFAULT_VALUE_EXC", LOG, 189 item.getName(), item.getType())); 190 } 191 if (!type.equals(item.getType())) { 192 throw new ConfigurationException (new Message("INVALID_TYPE_FOR_DEFAULT_VALUE_EXC", LOG, 193 item.getName(), item.getType())); 194 } 195 unmarshalDefaultValue(item, data); 196 } 197 198 private void deserializeImports(Document document) { 199 TypeSchemaHelper tsh = new TypeSchemaHelper(forceDefaults); 200 for (Node nd = document.getDocumentElement().getFirstChild(); nd != null; nd = nd.getNextSibling()) { 201 if (Node.ELEMENT_NODE == nd.getNodeType() 202 && "configImport".equals(nd.getLocalName()) 203 && MEATADATA_NAMESPACE_URI.equals(nd.getNamespaceURI())) { 204 Element importElement = (Element )nd; 205 String location = importElement.getAttribute("location"); 206 String namespaceURI = importElement.getAttribute("namespace"); 207 if (null == tsh.get(namespaceURI)) { 208 tsh.get(namespaceURI, document.getDocumentURI(), location); 209 } 210 } 211 } 212 } 213 214 222 223 private Schema getMetadataSchema() { 224 if (null == metadataSchema) { 225 InputStream is = 226 DefaultResourceManager.instance() 227 .getResourceAsStream("schemas/configuration/metadata.xsd"); 228 229 if (null == is) { 230 throw new ConfigurationException (new Message("CANNOT_FIND_CONFIG_METADATA_SCHEMA_MSG", LOG)); 231 } 232 233 try { 234 metadataSchema = getSchema(is); 235 } catch (ConfigurationException ex) { 236 LOG.log(Level.SEVERE, "CANNOT_CREATE_CONFIG_METADATA_SCHEMA_MSG", ex); 238 } 239 } 240 return metadataSchema; 241 } 242 243 private Validator getMetadataValidator() { 244 if (null == metadataValidator) { 245 Schema schema = getMetadataSchema(); 246 metadataValidator = schema.newValidator(); 248 if (null == validatorErrorHandler) { 249 validatorErrorHandler = new ValidatorErrorHandler(); 250 } 251 metadataValidator.setErrorHandler(validatorErrorHandler); 252 } 254 return metadataValidator; 255 } 256 257 private Schema getSchema(InputStream is) { 258 Source schemaFile = new StreamSource (is); 259 260 SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 261 Schema schema = null; 262 try { 263 schema = factory.newSchema(schemaFile); 264 } catch (SAXException ex) { 265 throw new ConfigurationException (new Message("SCHEMA_CREATION_ERROR_EXC", LOG), ex); 266 } 267 return schema; 268 } 269 270 private void parseXML(InputSource is) throws IOException { 271 272 Document document = null; 274 try { 275 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 276 factory.setNamespaceAware(true); 277 DocumentBuilder parser = factory.newDocumentBuilder(); 278 document = parser.parse(is); 279 } catch (ParserConfigurationException ex) { 280 throw new ConfigurationException (new Message("PARSER_CONFIGURATION_ERROR_EXC", LOG), ex); 281 } catch (SAXException ex) { 282 throw new ConfigurationException (new Message("PARSE_ERROR_EXC", LOG), ex); 283 } 284 285 if (doValidate) { 286 try { 287 Validator v = getMetadataValidator(); 288 v.validate(new DOMSource (document)); 289 } catch (SAXException ex) { 290 Message msg = new Message("METADATA_VALIDATION_ERROR_EXC", LOG); 291 throw new ConfigurationException (msg, ex); 292 } 293 } 294 295 deserializeImports(document); 296 deserializeConfig(document); 297 deserializeConfigItems(document); 298 } 299 300 private void unmarshalDefaultValue(ConfigurationItemMetadataImpl item, Element data) { 301 TypeSchema ts = new TypeSchemaHelper(forceDefaults).get(data.getNamespaceURI()); 302 Object obj = ts.unmarshalDefaultValue(item, data, doValidate); 303 if (null != obj) { 304 item.setDefaultValue(obj); 305 } 306 } 307 } 308 | Popular Tags |