1 25 26 package org.objectweb.easybeans.xmlconfig; 27 28 import java.lang.reflect.InvocationTargetException ; 29 import java.lang.reflect.Method ; 30 import java.lang.reflect.ParameterizedType ; 31 import java.lang.reflect.Type ; 32 import java.net.URL ; 33 import java.util.ArrayList ; 34 import java.util.HashMap ; 35 import java.util.List ; 36 import java.util.Map ; 37 38 import org.objectweb.easybeans.log.JLog; 39 import org.objectweb.easybeans.log.JLogFactory; 40 import org.objectweb.easybeans.util.xml.DocumentParser; 41 import org.objectweb.easybeans.util.xml.DocumentParserException; 42 import org.objectweb.easybeans.xmlconfig.mapping.AttributeMapping; 43 import org.objectweb.easybeans.xmlconfig.mapping.ClassMapping; 44 import org.objectweb.easybeans.xmlconfig.mapping.XMLMapping; 45 import org.objectweb.easybeans.xmlconfig.mapping.XMLMappingBuilder; 46 import org.w3c.dom.Document ; 47 import org.w3c.dom.Element ; 48 import org.w3c.dom.NamedNodeMap ; 49 import org.w3c.dom.Node ; 50 import org.w3c.dom.NodeList ; 51 52 59 public class XMLConfiguration { 60 61 64 private static final String HTTP_NAMESPACE = "http://"; 65 66 69 private static final boolean VALIDATING_OFF = false; 70 71 74 private static final String MAPPING_SUFFIX = "-mapping.xml"; 75 76 79 private JLog logger = JLogFactory.getLog(XMLConfiguration.class); 80 81 84 private boolean validating = VALIDATING_OFF; 85 86 89 private URL xmlConfigurationURL; 90 91 94 private Map <String , XMLMapping> mappings = null; 95 96 99 private HashMap <String , Object > configuredElements = null; 100 101 102 106 public XMLConfiguration(final URL xmlConfigurationURL) { 107 this.xmlConfigurationURL = xmlConfigurationURL; 108 this.mappings = new HashMap <String , XMLMapping>(); 109 configuredElements = new HashMap <String , Object >(); 110 } 111 112 117 public void configure(final Object object) throws XMLConfigurationException { 118 Element rootElement = analyzeXmlFile(); 119 configure(object, rootElement); 120 } 121 122 127 private Element analyzeXmlFile() throws XMLConfigurationException { 128 Document xmlConfigurationDocument = null; 130 try { 131 xmlConfigurationDocument = DocumentParser.getDocument(xmlConfigurationURL, validating, null); 132 } catch (DocumentParserException e) { 133 throw new XMLConfigurationException("Cannot get a document on the given url '" + xmlConfigurationURL + "'.", e); 134 } 135 136 Element rootElement = xmlConfigurationDocument.getDocumentElement(); 138 139 String nameSpace = rootElement.getNamespaceURI(); 141 String nodeName = rootElement.getNodeName(); 143 144 getXMLMapping(nameSpace, nodeName); 146 147 return rootElement; 148 149 } 150 151 157 public void configure(final Object object, final Element element) throws XMLConfigurationException { 158 159 NodeList nodeList = element.getChildNodes(); 161 162 int length = nodeList.getLength(); 164 for (int i = 0; i < length; i++) { 165 Node node = nodeList.item(i); 166 167 if (Node.ELEMENT_NODE == node.getNodeType()) { 169 ClassMapping classMapping = getClassMapping(node.getNamespaceURI(), node.getNodeName()); 170 171 Object newObject = newInstance(node, classMapping); 172 173 NamedNodeMap attributes = ((Element ) node).getAttributes(); 175 int attributesLength = attributes.getLength(); 176 for (int a = 0; a < attributesLength; a++) { 177 Node nodeAttribute = attributes.item(a); 178 if (nodeAttribute.getNamespaceURI() == null) { 179 String propertyName = nodeAttribute.getNodeName(); 180 String propertyValue = nodeAttribute.getNodeValue(); 181 setAttribute(newObject, propertyName, propertyValue, classMapping); 182 } 183 } 184 addSetElement(object, newObject); 186 187 configuredElements.put(node.getNodeName(), newObject); 189 190 configure(newObject, (Element ) node); 192 } 193 } 194 } 195 196 203 private ClassMapping getClassMapping(final String nameSpaceURI, final String name) throws XMLConfigurationException { 204 XMLMapping xmlMapping = mappings.get(nameSpaceURI); 206 if (xmlMapping == null) { 207 throw new XMLConfigurationException("No mapping found for namespace '" + nameSpaceURI + "'."); 208 } 209 210 ClassMapping classMapping = xmlMapping.getClassMapping(name); 212 213 if (classMapping == null) { 215 throw new XMLConfigurationException("No class found for element '" + name + "' withing xmlmapping '" + xmlMapping 216 + "'."); 217 } 218 return classMapping; 219 } 220 221 228 private Object newInstance(final Node node, final ClassMapping classMapping) throws XMLConfigurationException { 229 String className = classMapping.getName(); 231 232 Class clazz; 234 try { 235 clazz = Thread.currentThread().getContextClassLoader().loadClass(className); 236 } catch (ClassNotFoundException e) { 237 throw new XMLConfigurationException("Cannot load the class '" + className + "'."); 238 } 239 logger.debug("Building instance of the class {0}", className); 240 try { 242 return clazz.newInstance(); 243 } catch (InstantiationException e) { 244 throw new XMLConfigurationException("Cannot build an instance of class '" + className + "'.", e); 245 } catch (IllegalAccessException e) { 246 throw new XMLConfigurationException("Cannot build an instance of class '" + className + "'.", e); 247 } 248 } 249 250 258 private void setAttribute(final Object configuringObject, final String propertyName, final String propertyValue, 259 final ClassMapping classMapping) throws XMLConfigurationException { 260 261 Class configuringClass = configuringObject.getClass(); 263 264 Method [] methods = configuringClass.getMethods(); 266 267 String updatedPropertyName = propertyName; 268 269 AttributeMapping attributeMapping = classMapping.getAttributeMapping(propertyName); 271 if (attributeMapping != null) { 272 String name = attributeMapping.getName(); 273 if (name != null) { 274 updatedPropertyName = name; 275 } 276 } 277 278 String setterName = "set" + updatedPropertyName.substring(0, 1).toUpperCase() + updatedPropertyName.substring(1); 279 280 Object paramObject = null; 281 Method findedMethod = null; 283 if (methods != null) { 284 for (Method m : methods) { 285 if (m.getName().startsWith(setterName)) { 287 Class [] parameters = m.getParameterTypes(); 289 if (parameters.length == 1) { 290 findedMethod = m; 291 Class parameterClass = parameters[0]; 292 293 if (propertyValue.startsWith("#") && propertyValue.length() >= 2) { 295 paramObject = configuredElements.get(propertyValue.substring(1)); 296 } else if (String .class.equals(parameterClass)) { 297 paramObject = propertyValue; 298 } else if (Integer.TYPE.equals(parameterClass)) { 299 paramObject = new Integer (propertyValue); 300 } else if (Boolean.TYPE.equals(parameterClass)) { 301 paramObject = new Boolean (propertyValue); 302 } 303 304 break; 305 } 306 } 307 } 308 } 309 310 if (findedMethod != null && paramObject != null) { 312 logger.debug("Calling {0} on object {1} with value {2}", setterName, configuringObject, paramObject); 313 try { 314 findedMethod.invoke(configuringObject, paramObject); 315 } catch (IllegalArgumentException e) { 316 e.printStackTrace(); 318 } catch (IllegalAccessException e) { 319 e.printStackTrace(); 321 } catch (InvocationTargetException e) { 322 e.printStackTrace(); 324 } 325 } else { 326 327 throw new XMLConfigurationException("No setter method found for parameter '" + propertyName + "' on class '" 328 + configuringClass + "'."); 329 330 } 331 332 } 333 334 341 private Method findSingleSetterMethod(final Object configuringObject, final Object paramObject) { 342 Method setterMethod = null; 343 344 Class configuringClass = configuringObject.getClass(); 346 347 Method [] methods = configuringClass.getMethods(); 349 350 Class parameterClass = paramObject.getClass(); 352 String className = parameterClass.getSimpleName(); 353 354 if (methods != null) { 356 for (Method m : methods) { 357 if (m.getName().startsWith("set" + className) || m.getName().startsWith("add" + className)) { 359 Class [] parameters = m.getParameterTypes(); 361 if (parameters.length == 1) { 362 if (parameters[0].equals(parameterClass)) { 364 setterMethod = m; 365 break; 366 } 367 } 368 } 369 } 370 } 371 return setterMethod; 372 } 373 374 381 private Method [] findListGetterSetterMethod(final Object configuringObject, final Object paramObject) { 382 383 Class configuringClass = configuringObject.getClass(); 385 386 Method [] methods = configuringClass.getMethods(); 388 389 Class parameterClass = paramObject.getClass(); 391 392 String className = parameterClass.getSimpleName(); 394 String argName = className + "s"; 396 Method [] searchMethods = searchListGetterSetterMethod(methods, argName, parameterClass); 397 398 return searchMethods; 399 } 400 401 408 private Method [] searchListGetterSetterMethod(final Method [] methods, final String argName, final Class parameterClass) { 409 Method [] returnedMethods = null; 410 411 Method getterMethod = null; 412 Method setterMethod = null; 413 if (methods != null) { 415 for (Method m : methods) { 416 if (m.getName().startsWith("set" + argName)) { 418 Class [] parameters = m.getParameterTypes(); 420 421 if (parameters.length == 1) { 423 if (parameters[0].equals(List .class)) { 425 Type [] types = m.getGenericParameterTypes(); 426 if (types.length == 1) { 428 if (types[0] instanceof ParameterizedType ) { 429 ParameterizedType parameterizedType = (ParameterizedType ) types[0]; 430 Type [] typeArguments = parameterizedType.getActualTypeArguments(); 431 if (typeArguments.length == 1) { 432 if (typeArguments[0].equals(parameterClass)) { 433 setterMethod = m; 435 } 436 } 437 438 } 439 } 440 } 441 } 442 } else if (m.getName().startsWith("get" + argName)) { 443 Class returnTypeClass = m.getReturnType(); 444 if (returnTypeClass != null && returnTypeClass.equals(List .class)) { 445 446 Class [] parameters = m.getParameterTypes(); 448 if (parameters.length == 0) { 449 Type type = m.getGenericReturnType(); 450 if (type instanceof ParameterizedType ) { 451 ParameterizedType parameterizedType = (ParameterizedType ) type; 452 Type [] typeArguments = parameterizedType.getActualTypeArguments(); 453 if (typeArguments.length == 1) { 454 if (typeArguments[0].equals(parameterClass)) { 455 getterMethod = m; 457 } 458 } 459 } 460 } 461 } 462 } 463 } 464 } 465 Class [] interfaces = parameterClass.getInterfaces(); 467 if (interfaces != null) { 468 for (Class itf : interfaces) { 469 String itfName = itf.getSimpleName(); 470 String argItfName = itfName + "s"; 471 returnedMethods = searchListGetterSetterMethod(methods, argItfName, itf); 472 if (returnedMethods != null) { 473 break; 474 } 475 } 476 } 477 478 if (getterMethod != null && setterMethod != null) { 479 returnedMethods = new Method [2]; 480 returnedMethods[0] = getterMethod; 481 returnedMethods[1] = setterMethod; 482 } 483 return returnedMethods; 484 } 485 486 492 @SuppressWarnings ("unchecked") 493 private void addSetElement(final Object configuringObject, final Object newObject) throws XMLConfigurationException { 494 Method findedMethod = findSingleSetterMethod(configuringObject, newObject); 495 if (findedMethod != null) { 497 logger.debug("Calling method {0} on object {1} with value {2}", findedMethod, configuringObject, newObject); 498 try { 499 findedMethod.invoke(configuringObject, newObject); 500 } catch (IllegalArgumentException e) { 501 e.printStackTrace(); 503 } catch (IllegalAccessException e) { 504 e.printStackTrace(); 506 } catch (InvocationTargetException e) { 507 e.printStackTrace(); 509 } 510 } else { 511 Method [] getterAndSetter = findListGetterSetterMethod(configuringObject, newObject); 513 if (getterAndSetter != null) { 514 Method getterMethod = getterAndSetter[0]; 515 Method setterMethod = getterAndSetter[1]; 516 517 List currentList = null; 519 try { 520 logger.debug("Calling method {0} on object {1}", getterMethod, configuringObject); 521 currentList = (List ) getterMethod.invoke(configuringObject); 522 } catch (IllegalArgumentException e) { 523 e.printStackTrace(); 525 } catch (IllegalAccessException e) { 526 e.printStackTrace(); 528 } catch (InvocationTargetException e) { 529 e.printStackTrace(); 531 } 532 533 if (currentList == null) { 535 currentList = new ArrayList (); 536 } 537 538 logger.debug("Adding element {0} to the list {1}", newObject, currentList); 540 currentList.add(newObject); 541 542 try { 544 logger.debug("Calling method {0} on object {1} with value {2}", setterMethod, configuringObject, currentList); 545 setterMethod.invoke(configuringObject, currentList); 546 } catch (IllegalArgumentException e) { 547 e.printStackTrace(); 549 } catch (IllegalAccessException e) { 550 e.printStackTrace(); 552 } catch (InvocationTargetException e) { 553 e.printStackTrace(); 555 } 556 557 } else { 558 try { 559 throw new Exception ("No setter method found for parameter '" + configuringObject.getClass() + "' on class '" 560 + newObject.getClass() + "'."); 561 } catch (Exception e) { 562 e.printStackTrace(); 564 } 565 } 566 } 567 568 } 569 570 577 private XMLMapping getXMLMapping(final String nameSpace, final String nodeName) throws XMLConfigurationException { 578 if (mappings.containsKey(nameSpace)) { 580 return mappings.get(nameSpace); 581 } 582 583 XMLMapping xmlMapping = null; 584 if (nameSpace != null) { 587 if (nameSpace.startsWith(HTTP_NAMESPACE)) { 588 String packageName = nameSpace.substring(HTTP_NAMESPACE.length()); 590 String resourceName = packageName.replaceAll("\\.", "/") + "/" + nodeName + MAPPING_SUFFIX; 592 593 URL mappingURL = Thread.currentThread().getContextClassLoader().getResource(resourceName); 594 if (mappingURL != null) { 596 xmlMapping = createXMLMapping(nameSpace, mappingURL); 597 } 598 } else { 599 logger.warn("Namespace found ''{0}}''for node ''{1}'' but this is not an HTTP namespace", nameSpace, nodeName); 600 } 601 } else { 602 logger.warn("No namespace found for node ''{0}''.", nodeName); 603 } 604 mappings.put(nameSpace, xmlMapping); 606 return xmlMapping; 607 608 } 609 610 617 private XMLMapping createXMLMapping(final String nameSpace, final URL mappingURL) throws XMLConfigurationException { 618 XMLMappingBuilder xmlMappingBuilder = new XMLMappingBuilder(mappingURL); 619 xmlMappingBuilder.build(); 620 return xmlMappingBuilder.getXmlMapping(); 621 } 622 } 623 | Popular Tags |