1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.xbean.spring.context.v2c;
18
19 import java.beans.BeanInfo;
20 import java.beans.PropertyDescriptor;
21 import java.beans.PropertyEditor;
22 import java.io.ByteArrayInputStream;
23 import java.io.File;
24 import java.io.FileInputStream;
25 import java.io.FileNotFoundException;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.util.Arrays;
29 import java.util.Collection;
30 import java.util.Enumeration;
31 import java.util.HashSet;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Properties;
35 import java.util.Set;
36
37 import javax.xml.XMLConstants;
38
39 import org.apache.commons.logging.Log;
40 import org.apache.commons.logging.LogFactory;
41 import org.apache.xbean.spring.context.impl.MappingMetaData;
42 import org.apache.xbean.spring.context.impl.NamedConstructorArgs;
43 import org.apache.xbean.spring.context.impl.NamespaceHelper;
44 import org.springframework.beans.PropertyValue;
45 import org.springframework.beans.PropertyEditorRegistrar;
46 import org.springframework.beans.PropertyEditorRegistry;
47 import org.springframework.beans.factory.BeanDefinitionStoreException;
48 import org.springframework.beans.factory.config.BeanDefinition;
49 import org.springframework.beans.factory.config.BeanDefinitionHolder;
50 import org.springframework.beans.factory.config.RuntimeBeanReference;
51 import org.springframework.beans.factory.parsing.BeanComponentDefinition;
52 import org.springframework.beans.factory.support.AbstractBeanDefinition;
53 import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
54 import org.springframework.beans.factory.support.DefaultListableBeanFactory;
55 import org.springframework.beans.factory.support.ManagedList;
56 import org.springframework.beans.factory.support.ManagedMap;
57 import org.springframework.beans.factory.support.RootBeanDefinition;
58 import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
59 import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate;
60 import org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader;
61 import org.springframework.beans.factory.xml.NamespaceHandler;
62 import org.springframework.beans.factory.xml.ParserContext;
63 import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
64 import org.springframework.context.support.AbstractApplicationContext;
65 import org.springframework.util.StringUtils;
66 import org.springframework.core.io.ResourceLoader;
67
68 import org.w3c.dom.Attr;
69 import org.w3c.dom.Element;
70 import org.w3c.dom.NamedNodeMap;
71 import org.w3c.dom.Node;
72 import org.w3c.dom.NodeList;
73 import org.w3c.dom.Text;
74
75
76
77
78
79
80
81
82 public class XBeanNamespaceHandler implements NamespaceHandler {
83
84 public static final String SPRING_SCHEMA = "http://xbean.apache.org/schemas/spring/1.0";
85 public static final String SPRING_SCHEMA_COMPAT = "http://xbean.org/schemas/spring/1.0";
86
87 private static final Log log = LogFactory.getLog(XBeanNamespaceHandler.class);
88
89 private static final String QNAME_ELEMENT = "qname";
90
91 private static final String DESCRIPTION_ELEMENT = "description";
92
93
94
95
96
97 protected static final String[] RESERVED_ELEMENT_NAMES = {
98 "beans",
99 DESCRIPTION_ELEMENT,
100 DefaultBeanDefinitionDocumentReader.IMPORT_ELEMENT,
101 DefaultBeanDefinitionDocumentReader.ALIAS_ELEMENT,
102 DefaultBeanDefinitionDocumentReader.BEAN_ELEMENT,
103 BeanDefinitionParserDelegate.CONSTRUCTOR_ARG_ELEMENT,
104 BeanDefinitionParserDelegate.PROPERTY_ELEMENT,
105 BeanDefinitionParserDelegate.LOOKUP_METHOD_ELEMENT,
106 BeanDefinitionParserDelegate.REPLACED_METHOD_ELEMENT,
107 BeanDefinitionParserDelegate.ARG_TYPE_ELEMENT,
108 BeanDefinitionParserDelegate.REF_ELEMENT,
109 BeanDefinitionParserDelegate.IDREF_ELEMENT,
110 BeanDefinitionParserDelegate.VALUE_ELEMENT,
111 BeanDefinitionParserDelegate.NULL_ELEMENT,
112 BeanDefinitionParserDelegate.LIST_ELEMENT,
113 BeanDefinitionParserDelegate.SET_ELEMENT,
114 BeanDefinitionParserDelegate.MAP_ELEMENT,
115 BeanDefinitionParserDelegate.ENTRY_ELEMENT,
116 BeanDefinitionParserDelegate.KEY_ELEMENT,
117 BeanDefinitionParserDelegate.PROPS_ELEMENT,
118 BeanDefinitionParserDelegate.PROP_ELEMENT,
119 QNAME_ELEMENT };
120
121 protected static final String[] RESERVED_BEAN_ATTRIBUTE_NAMES = {
122 AbstractBeanDefinitionParser.ID_ATTRIBUTE,
123 BeanDefinitionParserDelegate.NAME_ATTRIBUTE,
124 BeanDefinitionParserDelegate.CLASS_ATTRIBUTE,
125 BeanDefinitionParserDelegate.PARENT_ATTRIBUTE,
126 BeanDefinitionParserDelegate.DEPENDS_ON_ATTRIBUTE,
127 BeanDefinitionParserDelegate.FACTORY_METHOD_ATTRIBUTE,
128 BeanDefinitionParserDelegate.FACTORY_BEAN_ATTRIBUTE,
129 BeanDefinitionParserDelegate.DEPENDENCY_CHECK_ATTRIBUTE,
130 BeanDefinitionParserDelegate.AUTOWIRE_ATTRIBUTE,
131 BeanDefinitionParserDelegate.INIT_METHOD_ATTRIBUTE,
132 BeanDefinitionParserDelegate.DESTROY_METHOD_ATTRIBUTE,
133 BeanDefinitionParserDelegate.ABSTRACT_ATTRIBUTE,
134 BeanDefinitionParserDelegate.SINGLETON_ATTRIBUTE,
135 BeanDefinitionParserDelegate.LAZY_INIT_ATTRIBUTE };
136
137 private static final String JAVA_PACKAGE_PREFIX = "java://";
138
139 private static final String BEAN_REFERENCE_PREFIX = "#";
140 private static final String NULL_REFERENCE = "#null";
141
142 private Set reservedElementNames = new HashSet(Arrays.asList(RESERVED_ELEMENT_NAMES));
143 private Set reservedBeanAttributeNames = new HashSet(Arrays.asList(RESERVED_BEAN_ATTRIBUTE_NAMES));
144 protected final NamedConstructorArgs namedConstructorArgs = new NamedConstructorArgs();
145
146 private ParserContext parserContext;
147
148 private XBeanQNameHelper qnameHelper;
149
150 public void init() {
151 }
152
153 public BeanDefinition parse(Element element, ParserContext parserContext) {
154 this.parserContext = parserContext;
155 this.qnameHelper = new XBeanQNameHelper(parserContext.getReaderContext());
156 BeanDefinitionHolder holder = parseBeanFromExtensionElement(element);
157
158 if (element.getParentNode() == element.getOwnerDocument() ||
159 element.getParentNode().getParentNode() == element.getOwnerDocument()) {
160 BeanDefinitionReaderUtils.registerBeanDefinition(holder, parserContext.getRegistry());
161 BeanComponentDefinition componentDefinition = new BeanComponentDefinition(holder);
162 parserContext.getReaderContext().fireComponentRegistered(componentDefinition);
163 }
164 return holder.getBeanDefinition();
165 }
166
167 public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
168 if (node instanceof org.w3c.dom.Attr && XMLConstants.XMLNS_ATTRIBUTE.equals(node.getLocalName())) {
169 return definition;
170 }
171 throw new IllegalArgumentException("Cannot locate BeanDefinitionDecorator for "
172 + (node instanceof Element ? "element" : "attribute") + " [" +
173 node.getLocalName() + "].");
174 }
175
176
177
178
179
180 public static void configure(AbstractApplicationContext context, XmlBeanDefinitionReader reader) {
181 reader.setNamespaceAware(true);
182 reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_XSD);
183 }
184
185
186
187
188 public static void registerCustomEditors(DefaultListableBeanFactory beanFactory) {
189 PropertyEditorRegistrar registrar = new PropertyEditorRegistrar() {
190 public void registerCustomEditors(PropertyEditorRegistry registry) {
191 registry.registerCustomEditor(java.io.File.class, new org.apache.xbean.spring.context.impl.FileEditor());
192 registry.registerCustomEditor(java.net.URI.class, new org.apache.xbean.spring.context.impl.URIEditor());
193 registry.registerCustomEditor(java.util.Date.class, new org.apache.xbean.spring.context.impl.DateEditor());
194 registry.registerCustomEditor(javax.management.ObjectName.class, new org.apache.xbean.spring.context.impl.ObjectNameEditor());
195 }
196 };
197
198 beanFactory.addPropertyEditorRegistrar(registrar);
199 }
200
201
202
203
204 protected BeanDefinitionHolder parseBeanFromExtensionElement(Element element, String parentClass, String property) {
205 String uri = element.getNamespaceURI();
206 String localName = getLocalName(element);
207
208 MappingMetaData metadata = findNamespaceProperties(uri, localName);
209 if (metadata != null) {
210
211 String className = getPropertyDescriptor(parentClass, property).getPropertyType().getName();
212 if (className != null) {
213 return parseBeanFromExtensionElement(element, metadata, className);
214 }
215 }
216 return null;
217 }
218
219 private BeanDefinitionHolder parseBeanFromExtensionElement(Element element, MappingMetaData metadata, String className) {
220 Element original = cloneElement(element);
221
222 element.setAttributeNS(null, "class", className);
223 addSpringAttributeValues(className, element);
224 BeanDefinitionHolder definition = parserContext.getDelegate().parseBeanDefinitionElement(element, null);
225 addAttributeProperties(definition, metadata, className, original);
226 addContentProperty(definition, metadata, element);
227 addNestedPropertyElements(definition, metadata, className, element);
228 qnameHelper.coerceNamespaceAwarePropertyValues(definition.getBeanDefinition(), element);
229 declareLifecycleMethods(definition, metadata, element);
230 resolveBeanClass((AbstractBeanDefinition) definition.getBeanDefinition(), definition.getBeanName());
231 namedConstructorArgs.processParameters(definition, metadata);
232 return definition;
233 }
234
235 protected Class resolveBeanClass(AbstractBeanDefinition bd, String beanName) {
236 if (bd.hasBeanClass()) {
237 return bd.getBeanClass();
238 }
239 try {
240 ResourceLoader rl = parserContext.getReaderContext().getResourceLoader();
241 ClassLoader cl = rl != null ? rl.getClassLoader() : null;
242 if (cl == null) {
243 cl = parserContext.getReaderContext().getReader().getBeanClassLoader();
244 }
245 if (cl == null) {
246 cl = Thread.currentThread().getContextClassLoader();
247 }
248 if (cl == null) {
249 cl = getClass().getClassLoader();
250 }
251 return bd.resolveBeanClass(cl);
252 }
253 catch (ClassNotFoundException ex) {
254 throw new BeanDefinitionStoreException(bd.getResourceDescription(),
255 beanName, "Bean class [" + bd.getBeanClassName() + "] not found", ex);
256 }
257 catch (NoClassDefFoundError err) {
258 throw new BeanDefinitionStoreException(bd.getResourceDescription(),
259 beanName, "Class that bean class [" + bd.getBeanClassName() + "] depends on not found", err);
260 }
261 }
262
263
264
265
266
267 protected BeanDefinitionHolder parseBeanFromExtensionElement(Element element) {
268 String uri = element.getNamespaceURI();
269 String localName = getLocalName(element);
270
271 MappingMetaData metadata = findNamespaceProperties(uri, localName);
272 if (metadata != null) {
273
274 String className = metadata.getClassName(localName);
275 if (className != null) {
276 return parseBeanFromExtensionElement(element, metadata, className);
277 } else {
278 throw new BeanDefinitionStoreException("Unrecognized xbean element mapping: " + localName + " in namespace " + uri);
279 }
280 } else {
281 if (uri == null) throw new BeanDefinitionStoreException("Unrecognized Spring element: " + localName);
282 else throw new BeanDefinitionStoreException("Unrecognized xbean namespace mapping: " + uri);
283 }
284 }
285
286 protected void addSpringAttributeValues(String className, Element element) {
287 NamedNodeMap attributes = element.getAttributes();
288 for (int i = 0, size = attributes.getLength(); i < size; i++) {
289 Attr attribute = (Attr) attributes.item(i);
290 String uri = attribute.getNamespaceURI();
291 String localName = attribute.getLocalName();
292
293 if (uri != null && (uri.equals(SPRING_SCHEMA) || uri.equals(SPRING_SCHEMA_COMPAT))) {
294 element.setAttributeNS(null, localName, attribute.getNodeValue());
295 }
296 }
297 }
298
299
300
301
302 protected Element cloneElement(Element element) {
303 Element answer = element.getOwnerDocument().createElementNS(element.getNamespaceURI(), element.getNodeName());
304 NamedNodeMap attributes = element.getAttributes();
305 for (int i = 0, size = attributes.getLength(); i < size; i++) {
306 Attr attribute = (Attr) attributes.item(i);
307 String uri = attribute.getNamespaceURI();
308 answer.setAttributeNS(uri, attribute.getName(), attribute.getNodeValue());
309 }
310 return answer;
311 }
312
313
314
315
316 protected void addAttributeProperties(BeanDefinitionHolder definition, MappingMetaData metadata, String className,
317 Element element) {
318 NamedNodeMap attributes = element.getAttributes();
319
320 for (int i = 0, size = attributes.getLength(); i < size; i++) {
321 Attr attribute = (Attr) attributes.item(i);
322 String uri = attribute.getNamespaceURI();
323 String localName = attribute.getLocalName();
324
325 if (localName == null || localName.equals("xmlns") || localName.startsWith("xmlns:")) {
326 continue;
327 }
328
329 if (isEmpty(uri) && !localName.equals("class")) {
330 boolean addProperty = true;
331 if (reservedBeanAttributeNames.contains(localName)) {
332
333 PropertyDescriptor descriptor = getPropertyDescriptor(className, localName);
334 addProperty = descriptor != null;
335 }
336 if (addProperty) {
337 addAttributeProperty(definition, metadata, element, attribute);
338 }
339 }
340 }
341
342 for (int i = 0, size = attributes.getLength(); i < size; i++) {
343 Attr attribute = (Attr) attributes.item(i);
344 String uri = attribute.getNamespaceURI();
345 String localName = attribute.getLocalName();
346
347 if (localName == null || localName.equals("xmlns") || localName.startsWith("xmlns:")) {
348 continue;
349 }
350
351 if (!isEmpty(uri) && uri.equals(element.getNamespaceURI())) {
352 boolean addProperty = true;
353 if (reservedBeanAttributeNames.contains(localName)) {
354
355 PropertyDescriptor descriptor = getPropertyDescriptor(className, localName);
356 addProperty = descriptor != null;
357 }
358 if (addProperty) {
359 addAttributeProperty(definition, metadata, element, attribute);
360 }
361 }
362 }
363 }
364
365 protected void addContentProperty(BeanDefinitionHolder definition, MappingMetaData metadata, Element element) {
366 String name = metadata.getContentProperty(getLocalName(element));
367 if (name != null) {
368 String value = getElementText(element);
369 addProperty(definition, metadata, element, name, value);
370 }
371 else {
372 StringBuffer buffer = new StringBuffer();
373 NodeList childNodes = element.getChildNodes();
374 for (int i = 0, size = childNodes.getLength(); i < size; i++) {
375 Node node = childNodes.item(i);
376 if (node instanceof Text) {
377 buffer.append(((Text) node).getData());
378 }
379 }
380
381 ByteArrayInputStream in = new ByteArrayInputStream(buffer.toString().getBytes());
382 Properties properties = new Properties();
383 try {
384 properties.load(in);
385 }
386 catch (IOException e) {
387 return;
388 }
389 Enumeration enumeration = properties.propertyNames();
390 while (enumeration.hasMoreElements()) {
391 String propertyName = (String) enumeration.nextElement();
392 String propertyEditor = metadata.getPropertyEditor(getLocalName(element), propertyName);
393
394 Object value = getValue(properties.getProperty(propertyName), propertyEditor);
395 definition.getBeanDefinition().getPropertyValues().addPropertyValue(propertyName, value);
396 }
397 }
398 }
399
400 protected void addAttributeProperty(BeanDefinitionHolder definition, MappingMetaData metadata, Element element,
401 Attr attribute) {
402 String localName = attribute.getLocalName();
403 String value = attribute.getValue();
404 addProperty(definition, metadata, element, localName, value);
405 }
406
407
408
409
410 protected void addProperty(BeanDefinitionHolder definition, MappingMetaData metadata, Element element,
411 String localName, String value) {
412 String propertyName = metadata.getPropertyName(getLocalName(element), localName);
413 String propertyEditor = metadata.getPropertyEditor(getLocalName(element), propertyName);
414 if (propertyName != null) {
415 definition.getBeanDefinition().getPropertyValues().addPropertyValue(
416 propertyName, getValue(value,propertyEditor));
417 }
418 }
419
420 protected Object getValue(String value, String propertyEditor) {
421 if (value == null) return null;
422
423
424
425
426 if (NULL_REFERENCE.equals(value)) {
427 return null;
428 }
429
430
431
432
433 if (value.startsWith(BEAN_REFERENCE_PREFIX)) {
434
435 value = value.substring(BEAN_REFERENCE_PREFIX.length());
436
437
438 if (!value.startsWith(BEAN_REFERENCE_PREFIX)) {
439 return new RuntimeBeanReference(value);
440 }
441 }
442
443 if( propertyEditor!=null ) {
444 PropertyEditor p = createPropertyEditor(propertyEditor);
445
446 RootBeanDefinition def = new RootBeanDefinition();
447 def.setBeanClass(PropertyEditorFactory.class);
448 def.getPropertyValues().addPropertyValue("propertyEditor", p);
449 def.getPropertyValues().addPropertyValue("value", value);
450
451 return def;
452 }
453
454
455
456
457 return value;
458 }
459
460 protected PropertyEditor createPropertyEditor(String propertyEditor) {
461 ClassLoader cl = Thread.currentThread().getContextClassLoader();
462 if( cl==null ) {
463 cl = XBeanNamespaceHandler.class.getClassLoader();
464 }
465
466 try {
467 return (PropertyEditor)cl.loadClass(propertyEditor).newInstance();
468 } catch (Throwable e){
469 throw (IllegalArgumentException)new IllegalArgumentException("Could not load property editor: "+propertyEditor).initCause(e);
470 }
471 }
472
473 protected String getLocalName(Element element) {
474 String localName = element.getLocalName();
475 if (localName == null) {
476 localName = element.getNodeName();
477 }
478 return localName;
479 }
480
481
482
483
484
485 protected void addNestedPropertyElements(BeanDefinitionHolder definition, MappingMetaData metadata,
486 String className, Element element) {
487 NodeList nl = element.getChildNodes();
488
489 for (int i = 0; i < nl.getLength(); i++) {
490 Node node = nl.item(i);
491 if (node instanceof Element) {
492 Element childElement = (Element) node;
493 String uri = childElement.getNamespaceURI();
494 String localName = childElement.getLocalName();
495
496 if (!isDefaultNamespace(uri) || !reservedElementNames.contains(localName)) {
497
498
499
500
501
502
503
504
505
506 Object value = null;
507 String propertyName = metadata.getNestedListProperty(getLocalName(element), localName);
508 if (propertyName != null) {
509 value = parseListElement(childElement, propertyName);
510 }
511 else {
512 propertyName = metadata.getFlatCollectionProperty(getLocalName(element), localName);
513 if (propertyName != null) {
514 Object def = parserContext.getDelegate().parseCustomElement(childElement);
515 PropertyValue pv = definition.getBeanDefinition().getPropertyValues().getPropertyValue(propertyName);
516 if (pv != null) {
517 Collection l = (Collection) pv.getValue();
518 l.add(def);
519 continue;
520 } else {
521 ManagedList l = new ManagedList();
522 l.add(def);
523 value = l;
524 }
525 } else {
526 propertyName = metadata.getNestedProperty(getLocalName(element), localName);
527 if (propertyName != null) {
528
529 value = parseChildExtensionBean(childElement);
530 }
531 }
532 }
533
534 if (propertyName == null && metadata.isFlatProperty(getLocalName(element), localName)) {
535 value = parseBeanFromExtensionElement(childElement, className, localName);
536 propertyName = localName;
537 }
538
539 if (propertyName == null) {
540 value = tryParseNestedPropertyViaIntrospection(metadata, className, childElement);
541 propertyName = localName;
542 }
543
544 if (value != null) {
545 definition.getBeanDefinition().getPropertyValues().addPropertyValue(propertyName, value);
546 }
547 else
548 {
549
550
551
552
553 String text = getElementText(childElement);
554
555 if (text != null) {
556 addProperty(definition, metadata, element, localName, text);
557 }
558 }
559 }
560 }
561 }
562 }
563
564
565
566
567 protected Object tryParseNestedPropertyViaIntrospection(MappingMetaData metadata, String className, Element element) {
568 String localName = getLocalName(element);
569 PropertyDescriptor descriptor = getPropertyDescriptor(className, localName);
570 if (descriptor != null) {
571 return parseNestedPropertyViaIntrospection(metadata, element, descriptor.getName(), descriptor.getPropertyType());
572 } else {
573 return parseNestedPropertyViaIntrospection(metadata, element, localName, Object.class);
574 }
575 }
576
577
578
579
580 protected PropertyDescriptor getPropertyDescriptor(String className, String localName) {
581 BeanInfo beanInfo = qnameHelper.getBeanInfo(className);
582 if (beanInfo != null) {
583 PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
584 for (int i = 0; i < descriptors.length; i++) {
585 PropertyDescriptor descriptor = descriptors[i];
586 String name = descriptor.getName();
587 if (name.equals(localName)) {
588 return descriptor;
589 }
590 }
591 }
592 return null;
593 }
594
595
596
597
598 private Object parseNestedPropertyViaIntrospection(MappingMetaData metadata, Element element, String propertyName, Class propertyType) {
599 if (isMap(propertyType)) {
600 return parseCustomMapElement(metadata, element, propertyName);
601 } else if (isCollection(propertyType)) {
602 return parseListElement(element, propertyName);
603 } else {
604 return parseChildExtensionBean(element);
605 }
606 }
607
608 protected Object parseListElement(Element element, String name) {
609 return parserContext.getDelegate().parseListElement(element, null);
610 }
611
612 protected Object parseCustomMapElement(MappingMetaData metadata, Element element, String name) {
613 Map map = new ManagedMap();
614
615 Element parent = (Element) element.getParentNode();
616 String entryName = metadata.getMapEntryName(getLocalName(parent), name);
617 String keyName = metadata.getMapKeyName(getLocalName(parent), name);
618 String dups = metadata.getMapDupsMode(getLocalName(parent), name);
619 boolean flat = metadata.isFlatMap(getLocalName(parent), name);
620 String defaultKey = metadata.getMapDefaultKey(getLocalName(parent), name);
621
622 if (entryName == null) entryName = "property";
623 if (keyName == null) keyName = "key";
624 if (dups == null) dups = "replace";
625
626
627
628
629
630 NodeList nl = element.getChildNodes();
631 for (int i = 0; i < nl.getLength(); i++) {
632 Node node = nl.item(i);
633 if (node instanceof Element) {
634 Element childElement = (Element) node;
635
636 String localName = childElement.getLocalName();
637 String uri = childElement.getNamespaceURI();
638 if (localName == null || localName.equals("xmlns") || localName.startsWith("xmlns:")) {
639 continue;
640 }
641
642
643
644 if (!flat && !isEmpty(uri) && localName.equals(entryName)) {
645 String key = childElement.getAttribute(keyName);
646 if (key == null || key.length() == 0) {
647 key = defaultKey;
648 }
649 if (key == null) {
650 throw new RuntimeException("No key defined for map " + entryName);
651 }
652
653 Object keyValue = getValue(key, null);
654
655 Element valueElement = getFirstChildElement(childElement);
656 Object value;
657 if (valueElement != null) {
658 String valueElUri = valueElement.getNamespaceURI();
659 String valueElLocalName = valueElement.getLocalName();
660 if (valueElUri == null ||
661 valueElUri.equals(SPRING_SCHEMA) ||
662 valueElUri.equals(SPRING_SCHEMA_COMPAT) ||
663 valueElUri.equals(BeanDefinitionParserDelegate.BEANS_NAMESPACE_URI)) {
664 if (BeanDefinitionParserDelegate.BEAN_ELEMENT.equals(valueElLocalName)) {
665 value = parserContext.getDelegate().parseBeanDefinitionElement(valueElement, null);
666 } else {
667 value = parserContext.getDelegate().parsePropertySubElement(valueElement, null);
668 }
669 } else {
670 value = parserContext.getDelegate().parseCustomElement(valueElement);
671 }
672 } else {
673 value = getElementText(childElement);
674 }
675
676 addValueToMap(map, keyValue, value, dups);
677 } else if (flat && !isEmpty(uri)) {
678 String key = childElement.getAttribute(keyName);
679 if (key == null || key.length() == 0) {
680 key = defaultKey;
681 }
682 if (key == null) {
683 throw new RuntimeException("No key defined for map entry " + entryName);
684 }
685 Object keyValue = getValue(key, null);
686 childElement.removeAttribute(keyName);
687 BeanDefinitionHolder bdh = parseBeanFromExtensionElement(childElement);
688 addValueToMap(map, keyValue, bdh, dups);
689 }
690 }
691 }
692 return map;
693 }
694
695 protected void addValueToMap(Map map, Object keyValue, Object value, String dups) {
696 if (map.containsKey(keyValue)) {
697 if ("discard".equalsIgnoreCase(dups)) {
698
699 } else if ("replace".equalsIgnoreCase(dups)) {
700 map.put(keyValue, value);
701 } else if ("allow".equalsIgnoreCase(dups)) {
702 List l = new ManagedList();
703 l.add(map.get(keyValue));
704 l.add(value);
705 map.put(keyValue, l);
706 } else if ("always".equalsIgnoreCase(dups)) {
707 List l = (List) map.get(keyValue);
708 l.add(value);
709 }
710 } else {
711 if ("always".equalsIgnoreCase(dups)) {
712 List l = (List) map.get(keyValue);
713 if (l == null) {
714 l = new ManagedList();
715 map.put(keyValue, l);
716 }
717 l.add(value);
718 } else {
719 map.put(keyValue, value);
720 }
721 }
722 }
723
724 protected Element getFirstChildElement(Element element) {
725 NodeList nl = element.getChildNodes();
726 for (int i = 0; i < nl.getLength(); i++) {
727 Node node = nl.item(i);
728 if (node instanceof Element) {
729 return (Element) node;
730 }
731 }
732 return null;
733 }
734
735 protected boolean isMap(Class type) {
736 return Map.class.isAssignableFrom(type);
737 }
738
739
740
741
742 protected boolean isCollection(Class type) {
743 return type.isArray() || Collection.class.isAssignableFrom(type);
744 }
745
746
747
748
749 protected Object parseChildExtensionBean(Element element) {
750 NodeList nl = element.getChildNodes();
751 for (int i = 0; i < nl.getLength(); i++) {
752 Node node = nl.item(i);
753 if (node instanceof Element) {
754 Element childElement = (Element) node;
755 String uri = childElement.getNamespaceURI();
756 String localName = childElement.getLocalName();
757
758 if (uri == null ||
759 uri.equals(SPRING_SCHEMA) ||
760 uri.equals(SPRING_SCHEMA_COMPAT) ||
761 uri.equals(BeanDefinitionParserDelegate.BEANS_NAMESPACE_URI)) {
762 if (BeanDefinitionParserDelegate.BEAN_ELEMENT.equals(localName)) {
763 return parserContext.getDelegate().parseBeanDefinitionElement(childElement, null);
764 } else {
765 return parserContext.getDelegate().parsePropertySubElement(childElement, null);
766 }
767 } else {
768 Object value = parserContext.getDelegate().parseCustomElement(childElement);
769 if (value != null) {
770 return value;
771 }
772 }
773 }
774 }
775 return null;
776 }
777
778
779
780
781
782
783
784
785
786
787
788
789 protected MappingMetaData findNamespaceProperties(String namespaceURI, String localName) {
790
791 if (namespaceURI != null && namespaceURI.startsWith(JAVA_PACKAGE_PREFIX)) {
792 String packageName = namespaceURI.substring(JAVA_PACKAGE_PREFIX.length());
793 return new MappingMetaData(packageName);
794 }
795
796 String uri = NamespaceHelper.createDiscoveryPathName(namespaceURI, localName);
797 InputStream in = loadResource(uri);
798 if (in == null) {
799 if (namespaceURI != null && namespaceURI.length() > 0) {
800 uri = NamespaceHelper.createDiscoveryPathName(namespaceURI);
801 in = loadResource(uri);
802 if (in == null) {
803 uri = NamespaceHelper.createDiscoveryOldPathName(namespaceURI);
804 in = loadResource(uri);
805 }
806 }
807 }
808
809 if (in != null) {
810 try {
811 Properties properties = new Properties();
812 properties.load(in);
813 return new MappingMetaData(properties);
814 }
815 catch (IOException e) {
816 log.warn("Failed to load resource from uri: " + uri, e);
817 }
818 }
819 return null;
820 }
821
822
823
824
825 protected InputStream loadResource(String uri) {
826 if (System.getProperty("xbean.dir") != null) {
827 File f = new File(System.getProperty("xbean.dir") + uri);
828 try {
829 return new FileInputStream(f);
830 } catch (FileNotFoundException e) {
831
832 }
833 }
834
835 InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(uri);
836 if (in == null) {
837 ClassLoader cl = parserContext.getReaderContext().getReader().getBeanClassLoader();
838 if (cl != null) {
839 in = cl.getResourceAsStream(uri);
840 }
841 if (in == null) {
842 in = getClass().getClassLoader().getResourceAsStream(uri);
843 if (in == null) {
844 log.debug("Could not find resource: " + uri);
845 }
846 }
847 }
848 return in;
849 }
850
851 protected boolean isEmpty(String uri) {
852 return uri == null || uri.length() == 0;
853 }
854
855 protected boolean isDefaultNamespace(String namespaceUri) {
856 return (!StringUtils.hasLength(namespaceUri) ||
857 BeanDefinitionParserDelegate.BEANS_NAMESPACE_URI.equals(namespaceUri)) ||
858 SPRING_SCHEMA.equals(namespaceUri) ||
859 SPRING_SCHEMA_COMPAT.equals(namespaceUri);
860 }
861
862 protected void declareLifecycleMethods(BeanDefinitionHolder definitionHolder, MappingMetaData metaData,
863 Element element) {
864 BeanDefinition definition = definitionHolder.getBeanDefinition();
865 if (definition instanceof AbstractBeanDefinition) {
866 AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) definition;
867 if (beanDefinition.getInitMethodName() == null) {
868 beanDefinition.setInitMethodName(metaData.getInitMethodName(getLocalName(element)));
869 }
870 if (beanDefinition.getDestroyMethodName() == null) {
871 beanDefinition.setDestroyMethodName(metaData.getDestroyMethodName(getLocalName(element)));
872 }
873 if (beanDefinition.getFactoryMethodName() == null) {
874 beanDefinition.setFactoryMethodName(metaData.getFactoryMethodName(getLocalName(element)));
875 }
876 }
877 }
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971 protected String getElementText(Element element) {
972 StringBuffer buffer = new StringBuffer();
973 NodeList nodeList = element.getChildNodes();
974 for (int i = 0, size = nodeList.getLength(); i < size; i++) {
975 Node node = nodeList.item(i);
976 if (node.getNodeType() == Node.TEXT_NODE || node.getNodeType() == Node.CDATA_SECTION_NODE) {
977 buffer.append(node.getNodeValue());
978 }
979 }
980 return buffer.toString();
981 }
982 }