Source Code Cross Referenced for BeanDefinitionParserDelegate.java in  » J2EE » spring-framework-2.0.6 » org » springframework » beans » factory » xml » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » J2EE » spring framework 2.0.6 » org.springframework.beans.factory.xml 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2002-2007 the original author or authors.
0003:         *
0004:         * Licensed under the Apache License, Version 2.0 (the "License");
0005:         * you may not use this file except in compliance with the License.
0006:         * You may obtain a copy of the License at
0007:         *
0008:         *      http://www.apache.org/licenses/LICENSE-2.0
0009:         *
0010:         * Unless required by applicable law or agreed to in writing, software
0011:         * distributed under the License is distributed on an "AS IS" BASIS,
0012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013:         * See the License for the specific language governing permissions and
0014:         * limitations under the License.
0015:         */
0016:
0017:        package org.springframework.beans.factory.xml;
0018:
0019:        import java.util.ArrayList;
0020:        import java.util.Arrays;
0021:        import java.util.HashSet;
0022:        import java.util.Iterator;
0023:        import java.util.List;
0024:        import java.util.Map;
0025:        import java.util.Properties;
0026:        import java.util.Set;
0027:
0028:        import org.apache.commons.logging.Log;
0029:        import org.apache.commons.logging.LogFactory;
0030:        import org.w3c.dom.Element;
0031:        import org.w3c.dom.NamedNodeMap;
0032:        import org.w3c.dom.Node;
0033:        import org.w3c.dom.NodeList;
0034:
0035:        import org.springframework.beans.PropertyValue;
0036:        import org.springframework.beans.factory.BeanDefinitionStoreException;
0037:        import org.springframework.beans.factory.config.BeanDefinition;
0038:        import org.springframework.beans.factory.config.BeanDefinitionHolder;
0039:        import org.springframework.beans.factory.config.ConstructorArgumentValues;
0040:        import org.springframework.beans.factory.config.RuntimeBeanNameReference;
0041:        import org.springframework.beans.factory.config.RuntimeBeanReference;
0042:        import org.springframework.beans.factory.config.TypedStringValue;
0043:        import org.springframework.beans.factory.parsing.BeanEntry;
0044:        import org.springframework.beans.factory.parsing.ConstructorArgumentEntry;
0045:        import org.springframework.beans.factory.parsing.ParseState;
0046:        import org.springframework.beans.factory.parsing.PropertyEntry;
0047:        import org.springframework.beans.factory.support.AbstractBeanDefinition;
0048:        import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
0049:        import org.springframework.beans.factory.support.LookupOverride;
0050:        import org.springframework.beans.factory.support.ManagedList;
0051:        import org.springframework.beans.factory.support.ManagedMap;
0052:        import org.springframework.beans.factory.support.ManagedProperties;
0053:        import org.springframework.beans.factory.support.ManagedSet;
0054:        import org.springframework.beans.factory.support.MethodOverrides;
0055:        import org.springframework.beans.factory.support.ReplaceOverride;
0056:        import org.springframework.core.AttributeAccessor;
0057:        import org.springframework.util.Assert;
0058:        import org.springframework.util.ClassUtils;
0059:        import org.springframework.util.CollectionUtils;
0060:        import org.springframework.util.ObjectUtils;
0061:        import org.springframework.util.StringUtils;
0062:        import org.springframework.util.xml.DomUtils;
0063:
0064:        /**
0065:         * Stateful delegate class used to parse XML bean definitions.
0066:         * Intended for use by both the main parser and any extension
0067:         * {@link BeanDefinitionParser BeanDefinitionParsers}
0068:         * or {@link BeanDefinitionDecorator BeanDefinitionDecorators}.
0069:         *
0070:         * @author Rob Harrop
0071:         * @author Juergen Hoeller
0072:         * @author Rod Johnson
0073:         * @since 2.0
0074:         * @see ParserContext
0075:         * @see DefaultBeanDefinitionDocumentReader
0076:         */
0077:        public class BeanDefinitionParserDelegate {
0078:
0079:            public static final String BEANS_NAMESPACE_URI = "http://www.springframework.org/schema/beans";
0080:
0081:            public static final String BEAN_NAME_DELIMITERS = ",; ";
0082:
0083:            /**
0084:             * Value of a T/F attribute that represents true.
0085:             * Anything else represents false. Case seNsItive.
0086:             */
0087:            public static final String TRUE_VALUE = "true";
0088:
0089:            public static final String DEFAULT_VALUE = "default";
0090:
0091:            public static final String DESCRIPTION_ELEMENT = "description";
0092:
0093:            public static final String AUTOWIRE_BY_NAME_VALUE = "byName";
0094:
0095:            public static final String AUTOWIRE_BY_TYPE_VALUE = "byType";
0096:
0097:            public static final String AUTOWIRE_CONSTRUCTOR_VALUE = "constructor";
0098:
0099:            public static final String AUTOWIRE_AUTODETECT_VALUE = "autodetect";
0100:
0101:            public static final String DEPENDENCY_CHECK_ALL_ATTRIBUTE_VALUE = "all";
0102:
0103:            public static final String DEPENDENCY_CHECK_SIMPLE_ATTRIBUTE_VALUE = "simple";
0104:
0105:            public static final String DEPENDENCY_CHECK_OBJECTS_ATTRIBUTE_VALUE = "objects";
0106:
0107:            public static final String NAME_ATTRIBUTE = "name";
0108:
0109:            public static final String BEAN_ELEMENT = "bean";
0110:
0111:            public static final String META_ELEMENT = "meta";
0112:
0113:            public static final String ID_ATTRIBUTE = "id";
0114:
0115:            public static final String PARENT_ATTRIBUTE = "parent";
0116:
0117:            public static final String CLASS_ATTRIBUTE = "class";
0118:
0119:            public static final String ABSTRACT_ATTRIBUTE = "abstract";
0120:
0121:            public static final String SCOPE_ATTRIBUTE = "scope";
0122:
0123:            public static final String SINGLETON_ATTRIBUTE = "singleton";
0124:
0125:            public static final String LAZY_INIT_ATTRIBUTE = "lazy-init";
0126:
0127:            public static final String AUTOWIRE_ATTRIBUTE = "autowire";
0128:
0129:            public static final String AUTOWIRE_CANDIDATE_ATTRIBUTE = "autowire-candidate";
0130:
0131:            public static final String DEPENDENCY_CHECK_ATTRIBUTE = "dependency-check";
0132:
0133:            public static final String DEPENDS_ON_ATTRIBUTE = "depends-on";
0134:
0135:            public static final String INIT_METHOD_ATTRIBUTE = "init-method";
0136:
0137:            public static final String DESTROY_METHOD_ATTRIBUTE = "destroy-method";
0138:
0139:            public static final String FACTORY_METHOD_ATTRIBUTE = "factory-method";
0140:
0141:            public static final String FACTORY_BEAN_ATTRIBUTE = "factory-bean";
0142:
0143:            public static final String CONSTRUCTOR_ARG_ELEMENT = "constructor-arg";
0144:
0145:            public static final String INDEX_ATTRIBUTE = "index";
0146:
0147:            public static final String TYPE_ATTRIBUTE = "type";
0148:
0149:            public static final String VALUE_TYPE_ATTRIBUTE = "value-type";
0150:
0151:            public static final String KEY_TYPE_ATTRIBUTE = "key-type";
0152:
0153:            public static final String PROPERTY_ELEMENT = "property";
0154:
0155:            public static final String REF_ATTRIBUTE = "ref";
0156:
0157:            public static final String VALUE_ATTRIBUTE = "value";
0158:
0159:            public static final String LOOKUP_METHOD_ELEMENT = "lookup-method";
0160:
0161:            public static final String REPLACED_METHOD_ELEMENT = "replaced-method";
0162:
0163:            public static final String REPLACER_ATTRIBUTE = "replacer";
0164:
0165:            public static final String ARG_TYPE_ELEMENT = "arg-type";
0166:
0167:            public static final String ARG_TYPE_MATCH_ATTRIBUTE = "match";
0168:
0169:            public static final String REF_ELEMENT = "ref";
0170:
0171:            public static final String IDREF_ELEMENT = "idref";
0172:
0173:            public static final String BEAN_REF_ATTRIBUTE = "bean";
0174:
0175:            public static final String LOCAL_REF_ATTRIBUTE = "local";
0176:
0177:            public static final String PARENT_REF_ATTRIBUTE = "parent";
0178:
0179:            public static final String VALUE_ELEMENT = "value";
0180:
0181:            public static final String NULL_ELEMENT = "null";
0182:
0183:            public static final String LIST_ELEMENT = "list";
0184:
0185:            public static final String SET_ELEMENT = "set";
0186:
0187:            public static final String MAP_ELEMENT = "map";
0188:
0189:            public static final String ENTRY_ELEMENT = "entry";
0190:
0191:            public static final String KEY_ELEMENT = "key";
0192:
0193:            public static final String KEY_ATTRIBUTE = "key";
0194:
0195:            public static final String KEY_REF_ATTRIBUTE = "key-ref";
0196:
0197:            public static final String VALUE_REF_ATTRIBUTE = "value-ref";
0198:
0199:            public static final String PROPS_ELEMENT = "props";
0200:
0201:            public static final String PROP_ELEMENT = "prop";
0202:
0203:            public static final String MERGE_ATTRIBUTE = "merge";
0204:
0205:            public static final String DEFAULT_LAZY_INIT_ATTRIBUTE = "default-lazy-init";
0206:
0207:            public static final String DEFAULT_AUTOWIRE_ATTRIBUTE = "default-autowire";
0208:
0209:            public static final String DEFAULT_DEPENDENCY_CHECK_ATTRIBUTE = "default-dependency-check";
0210:
0211:            public static final String DEFAULT_INIT_METHOD_ATTRIBUTE = "default-init-method";
0212:
0213:            public static final String DEFAULT_DESTROY_METHOD_ATTRIBUTE = "default-destroy-method";
0214:
0215:            public static final String DEFAULT_MERGE_ATTRIBUTE = "default-merge";
0216:
0217:            protected final Log logger = LogFactory.getLog(getClass());
0218:
0219:            private final XmlReaderContext readerContext;
0220:
0221:            private DocumentDefaultsDefinition defaults;
0222:
0223:            private ParseState parseState = new ParseState();
0224:
0225:            /**
0226:             * Stores all used bean names so we can enforce uniqueness on a per file basis.
0227:             */
0228:            private final Set usedNames = new HashSet();
0229:
0230:            /**
0231:             * Create a new BeanDefinitionParserDelegate associated with the
0232:             * supplied {@link XmlReaderContext}.
0233:             */
0234:            public BeanDefinitionParserDelegate(XmlReaderContext readerContext) {
0235:                Assert.notNull(readerContext,
0236:                        "XmlReaderContext must not be null");
0237:                this .readerContext = readerContext;
0238:            }
0239:
0240:            /**
0241:             * Get the {@link XmlReaderContext} associated with this helper instance.
0242:             */
0243:            public final XmlReaderContext getReaderContext() {
0244:                return this .readerContext;
0245:            }
0246:
0247:            /**
0248:             * Invoke the {@link org.springframework.beans.factory.parsing.SourceExtractor} to pull the
0249:             * source metadata from the supplied {@link Element}.
0250:             */
0251:            protected Object extractSource(Element ele) {
0252:                return this .readerContext.extractSource(ele);
0253:            }
0254:
0255:            /**
0256:             * Report an error with the given message for the given source element.
0257:             */
0258:            protected void error(String message, Element source) {
0259:                this .readerContext.error(message, source, this .parseState
0260:                        .snapshot());
0261:            }
0262:
0263:            /**
0264:             * Report an error with the given message for the given source element.
0265:             */
0266:            protected void error(String message, Element source, Throwable cause) {
0267:                this .readerContext.error(message, source, this .parseState
0268:                        .snapshot(), cause);
0269:            }
0270:
0271:            /**
0272:             * Initialize the default lazy-init, autowire, dependency check settings,
0273:             * init-method, destroy-method and merge settings.
0274:             * @see #getDefaults()
0275:             */
0276:            public void initDefaults(Element root) {
0277:                DocumentDefaultsDefinition defaults = new DocumentDefaultsDefinition();
0278:                defaults.setLazyInit(root
0279:                        .getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE));
0280:                defaults.setAutowire(root
0281:                        .getAttribute(DEFAULT_AUTOWIRE_ATTRIBUTE));
0282:                defaults.setDependencyCheck(root
0283:                        .getAttribute(DEFAULT_DEPENDENCY_CHECK_ATTRIBUTE));
0284:                if (root.hasAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)) {
0285:                    defaults.setInitMethod(root
0286:                            .getAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE));
0287:                }
0288:                if (root.hasAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)) {
0289:                    defaults.setDestroyMethod(root
0290:                            .getAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE));
0291:                }
0292:                defaults.setMerge(root.getAttribute(DEFAULT_MERGE_ATTRIBUTE));
0293:                defaults.setSource(this .readerContext.extractSource(root));
0294:
0295:                this .defaults = defaults;
0296:                this .readerContext.fireDefaultsRegistered(defaults);
0297:            }
0298:
0299:            /**
0300:             * Return the defaults definition object, or <code>null</code> if the
0301:             * defaults have been initialized yet.
0302:             */
0303:            public DocumentDefaultsDefinition getDefaults() {
0304:                return this .defaults;
0305:            }
0306:
0307:            /**
0308:             * Parses the supplied <code>&lt;bean&gt;</code> element. May return <code>null</code>
0309:             * if there were errors during parse. Errors are reported to the
0310:             * {@link org.springframework.beans.factory.parsing.ProblemReporter}.
0311:             */
0312:            public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
0313:                return parseBeanDefinitionElement(ele, null);
0314:            }
0315:
0316:            /**
0317:             * Parses the supplied <code>&lt;bean&gt;</code> element. May return <code>null</code>
0318:             * if there were errors during parse. Errors are reported to the
0319:             * {@link org.springframework.beans.factory.parsing.ProblemReporter}.
0320:             */
0321:            public BeanDefinitionHolder parseBeanDefinitionElement(Element ele,
0322:                    BeanDefinition containingBean) {
0323:                String id = ele.getAttribute(ID_ATTRIBUTE);
0324:                String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
0325:
0326:                List aliases = new ArrayList();
0327:                if (StringUtils.hasLength(nameAttr)) {
0328:                    String[] nameArr = StringUtils.tokenizeToStringArray(
0329:                            nameAttr, BEAN_NAME_DELIMITERS);
0330:                    aliases.addAll(Arrays.asList(nameArr));
0331:                }
0332:
0333:                String beanName = id;
0334:                if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
0335:                    beanName = (String) aliases.remove(0);
0336:                    if (logger.isDebugEnabled()) {
0337:                        logger.debug("No XML 'id' specified - using '"
0338:                                + beanName + "' as bean name and " + aliases
0339:                                + " as aliases");
0340:                    }
0341:                }
0342:
0343:                if (containingBean == null) {
0344:                    checkNameUniqueness(beanName, aliases, ele);
0345:                }
0346:
0347:                AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(
0348:                        ele, beanName, containingBean);
0349:                if (beanDefinition != null) {
0350:                    if (!StringUtils.hasText(beanName)) {
0351:                        try {
0352:                            if (containingBean != null) {
0353:                                beanName = BeanDefinitionReaderUtils
0354:                                        .generateBeanName(beanDefinition,
0355:                                                this .readerContext
0356:                                                        .getRegistry(), true);
0357:                            } else {
0358:                                beanName = this .readerContext
0359:                                        .generateBeanName(beanDefinition);
0360:                            }
0361:                            if (logger.isDebugEnabled()) {
0362:                                logger
0363:                                        .debug("Neither XML 'id' nor 'name' specified - "
0364:                                                + "using generated bean name ["
0365:                                                + beanName + "]");
0366:                            }
0367:                        } catch (BeanDefinitionStoreException ex) {
0368:                            error(ex.getMessage(), ele);
0369:                            return null;
0370:                        }
0371:                    }
0372:                    String[] aliasesArray = StringUtils.toStringArray(aliases);
0373:                    return new BeanDefinitionHolder(beanDefinition, beanName,
0374:                            aliasesArray);
0375:                }
0376:
0377:                return null;
0378:            }
0379:
0380:            private void checkNameUniqueness(String beanName, List aliases,
0381:                    Element beanElement) {
0382:                String foundName = null;
0383:
0384:                if (StringUtils.hasText(beanName)
0385:                        && this .usedNames.contains(beanName)) {
0386:                    foundName = beanName;
0387:                }
0388:                if (foundName == null) {
0389:                    foundName = (String) CollectionUtils.findFirstMatch(
0390:                            this .usedNames, aliases);
0391:                }
0392:                if (foundName != null) {
0393:                    error("Bean name '" + foundName
0394:                            + "' is already used in this file.", beanElement);
0395:                }
0396:
0397:                this .usedNames.add(beanName);
0398:                this .usedNames.addAll(aliases);
0399:            }
0400:
0401:            /**
0402:             * Parse the bean definition itself, without regard to name or aliases. May return
0403:             * <code>null</code> if problems occured during the parse of the bean definition.
0404:             */
0405:            public AbstractBeanDefinition parseBeanDefinitionElement(
0406:                    Element ele, String beanName, BeanDefinition containingBean) {
0407:
0408:                String className = null;
0409:                if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
0410:                    className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
0411:                }
0412:                String parent = null;
0413:                if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
0414:                    parent = ele.getAttribute(PARENT_ATTRIBUTE);
0415:                }
0416:
0417:                try {
0418:                    this .parseState.push(new BeanEntry(beanName));
0419:
0420:                    AbstractBeanDefinition bd = BeanDefinitionReaderUtils
0421:                            .createBeanDefinition(parent, className,
0422:                                    this .readerContext.getBeanClassLoader());
0423:
0424:                    if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
0425:                        // Spring 2.0 "scope" attribute
0426:                        bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
0427:                        if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
0428:                            error(
0429:                                    "Specify either 'scope' or 'singleton', not both",
0430:                                    ele);
0431:                        }
0432:                    } else if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
0433:                        // Spring 1.x "singleton" attribute
0434:                        bd.setSingleton(TRUE_VALUE.equals(ele
0435:                                .getAttribute(SINGLETON_ATTRIBUTE)));
0436:                    } else if (containingBean != null) {
0437:                        // Take default from containing bean in case of an inner bean definition.
0438:                        bd.setSingleton(containingBean.isSingleton());
0439:                    }
0440:
0441:                    if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
0442:                        bd.setAbstract(TRUE_VALUE.equals(ele
0443:                                .getAttribute(ABSTRACT_ATTRIBUTE)));
0444:                    }
0445:
0446:                    String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
0447:                    if (DEFAULT_VALUE.equals(lazyInit) && bd.isSingleton()) {
0448:                        // Just apply default to singletons, as lazy-init has no meaning for prototypes.
0449:                        lazyInit = this .defaults.getLazyInit();
0450:                    }
0451:                    bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
0452:
0453:                    if (ele.hasAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE)) {
0454:                        bd.setAutowireCandidate(TRUE_VALUE.equals(ele
0455:                                .getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE)));
0456:                    }
0457:
0458:                    String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
0459:                    if (DEFAULT_VALUE.equals(autowire)) {
0460:                        autowire = this .defaults.getAutowire();
0461:                    }
0462:                    bd.setAutowireMode(getAutowireMode(autowire));
0463:
0464:                    String dependencyCheck = ele
0465:                            .getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);
0466:                    if (DEFAULT_VALUE.equals(dependencyCheck)) {
0467:                        dependencyCheck = this .defaults.getDependencyCheck();
0468:                    }
0469:                    bd.setDependencyCheck(getDependencyCheck(dependencyCheck));
0470:
0471:                    if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
0472:                        String dependsOn = ele
0473:                                .getAttribute(DEPENDS_ON_ATTRIBUTE);
0474:                        bd.setDependsOn(StringUtils.tokenizeToStringArray(
0475:                                dependsOn, BEAN_NAME_DELIMITERS));
0476:                    }
0477:
0478:                    if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
0479:                        bd.setFactoryMethodName(ele
0480:                                .getAttribute(FACTORY_METHOD_ATTRIBUTE));
0481:                    }
0482:                    if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
0483:                        bd.setFactoryBeanName(ele
0484:                                .getAttribute(FACTORY_BEAN_ATTRIBUTE));
0485:                    }
0486:
0487:                    if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
0488:                        String initMethodName = ele
0489:                                .getAttribute(INIT_METHOD_ATTRIBUTE);
0490:                        if (!"".equals(initMethodName)) {
0491:                            bd.setInitMethodName(initMethodName);
0492:                        }
0493:                    } else {
0494:                        if (this .defaults.getInitMethod() != null) {
0495:                            bd.setInitMethodName(this .defaults.getInitMethod());
0496:                            bd.setEnforceInitMethod(false);
0497:                        }
0498:                    }
0499:
0500:                    if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
0501:                        String destroyMethodName = ele
0502:                                .getAttribute(DESTROY_METHOD_ATTRIBUTE);
0503:                        if (!"".equals(destroyMethodName)) {
0504:                            bd.setDestroyMethodName(destroyMethodName);
0505:                        }
0506:                    } else {
0507:                        if (this .defaults.getDestroyMethod() != null) {
0508:                            bd.setDestroyMethodName(this .defaults
0509:                                    .getDestroyMethod());
0510:                            bd.setEnforceDestroyMethod(false);
0511:                        }
0512:                    }
0513:
0514:                    parseMetaElements(ele, bd);
0515:                    parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
0516:                    parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
0517:
0518:                    parseConstructorArgElements(ele, bd);
0519:                    parsePropertyElements(ele, bd);
0520:
0521:                    bd.setResourceDescription(this .readerContext.getResource()
0522:                            .getDescription());
0523:                    bd.setSource(extractSource(ele));
0524:
0525:                    return bd;
0526:                } catch (ClassNotFoundException ex) {
0527:                    error("Bean class [" + className + "] not found", ele, ex);
0528:                } catch (NoClassDefFoundError err) {
0529:                    error("Class that bean class [" + className
0530:                            + "] depends on not found", ele, err);
0531:                } catch (Throwable ex) {
0532:                    error("Unexpected failure during bean definition parsing",
0533:                            ele, ex);
0534:                } finally {
0535:                    this .parseState.pop();
0536:                }
0537:
0538:                return null;
0539:            }
0540:
0541:            public void parseMetaElements(Element ele,
0542:                    AttributeAccessor attributeAccessor) {
0543:                NodeList nl = ele.getChildNodes();
0544:                for (int i = 0; i < nl.getLength(); i++) {
0545:                    Node node = nl.item(i);
0546:                    if (node instanceof  Element
0547:                            && DomUtils.nodeNameEquals(node, META_ELEMENT)) {
0548:                        Element metaElement = (Element) node;
0549:                        String key = metaElement.getAttribute(KEY_ATTRIBUTE);
0550:                        String value = metaElement
0551:                                .getAttribute(VALUE_ATTRIBUTE);
0552:                        attributeAccessor.setAttribute(key, value);
0553:                    }
0554:                }
0555:            }
0556:
0557:            public int getDependencyCheck(String att) {
0558:                int dependencyCheckCode = AbstractBeanDefinition.DEPENDENCY_CHECK_NONE;
0559:                if (DEPENDENCY_CHECK_ALL_ATTRIBUTE_VALUE.equals(att)) {
0560:                    dependencyCheckCode = AbstractBeanDefinition.DEPENDENCY_CHECK_ALL;
0561:                } else if (DEPENDENCY_CHECK_SIMPLE_ATTRIBUTE_VALUE.equals(att)) {
0562:                    dependencyCheckCode = AbstractBeanDefinition.DEPENDENCY_CHECK_SIMPLE;
0563:                } else if (DEPENDENCY_CHECK_OBJECTS_ATTRIBUTE_VALUE.equals(att)) {
0564:                    dependencyCheckCode = AbstractBeanDefinition.DEPENDENCY_CHECK_OBJECTS;
0565:                }
0566:                // Else leave default value.
0567:                return dependencyCheckCode;
0568:            }
0569:
0570:            public int getAutowireMode(String att) {
0571:                int autowire = AbstractBeanDefinition.AUTOWIRE_NO;
0572:                if (AUTOWIRE_BY_NAME_VALUE.equals(att)) {
0573:                    autowire = AbstractBeanDefinition.AUTOWIRE_BY_NAME;
0574:                } else if (AUTOWIRE_BY_TYPE_VALUE.equals(att)) {
0575:                    autowire = AbstractBeanDefinition.AUTOWIRE_BY_TYPE;
0576:                } else if (AUTOWIRE_CONSTRUCTOR_VALUE.equals(att)) {
0577:                    autowire = AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR;
0578:                } else if (AUTOWIRE_AUTODETECT_VALUE.equals(att)) {
0579:                    autowire = AbstractBeanDefinition.AUTOWIRE_AUTODETECT;
0580:                }
0581:                // Else leave default value.
0582:                return autowire;
0583:            }
0584:
0585:            /**
0586:             * Parse constructor-arg sub-elements of the given bean element.
0587:             */
0588:            public void parseConstructorArgElements(Element beanEle,
0589:                    BeanDefinition bd) {
0590:                NodeList nl = beanEle.getChildNodes();
0591:                for (int i = 0; i < nl.getLength(); i++) {
0592:                    Node node = nl.item(i);
0593:                    if (node instanceof  Element
0594:                            && DomUtils.nodeNameEquals(node,
0595:                                    CONSTRUCTOR_ARG_ELEMENT)) {
0596:                        parseConstructorArgElement((Element) node, bd);
0597:                    }
0598:                }
0599:            }
0600:
0601:            /**
0602:             * Parse property sub-elements of the given bean element.
0603:             */
0604:            public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
0605:                NodeList nl = beanEle.getChildNodes();
0606:                for (int i = 0; i < nl.getLength(); i++) {
0607:                    Node node = nl.item(i);
0608:                    if (node instanceof  Element
0609:                            && DomUtils.nodeNameEquals(node, PROPERTY_ELEMENT)) {
0610:                        parsePropertyElement((Element) node, bd);
0611:                    }
0612:                }
0613:            }
0614:
0615:            /**
0616:             * Parse lookup-override sub-elements of the given bean element.
0617:             */
0618:            public void parseLookupOverrideSubElements(Element beanEle,
0619:                    MethodOverrides overrides) {
0620:                NodeList nl = beanEle.getChildNodes();
0621:                for (int i = 0; i < nl.getLength(); i++) {
0622:                    Node node = nl.item(i);
0623:                    if (node instanceof  Element
0624:                            && DomUtils.nodeNameEquals(node,
0625:                                    LOOKUP_METHOD_ELEMENT)) {
0626:                        Element ele = (Element) node;
0627:                        String methodName = ele.getAttribute(NAME_ATTRIBUTE);
0628:                        String beanRef = ele.getAttribute(BEAN_ELEMENT);
0629:                        LookupOverride override = new LookupOverride(
0630:                                methodName, beanRef);
0631:                        override.setSource(extractSource(ele));
0632:                        overrides.addOverride(override);
0633:                    }
0634:                }
0635:            }
0636:
0637:            /**
0638:             * Parse replaced-method sub-elements of the given bean element.
0639:             */
0640:            public void parseReplacedMethodSubElements(Element beanEle,
0641:                    MethodOverrides overrides) {
0642:                NodeList nl = beanEle.getChildNodes();
0643:                for (int i = 0; i < nl.getLength(); i++) {
0644:                    Node node = nl.item(i);
0645:                    if (node instanceof  Element
0646:                            && DomUtils.nodeNameEquals(node,
0647:                                    REPLACED_METHOD_ELEMENT)) {
0648:                        Element replacedMethodEle = (Element) node;
0649:                        String name = replacedMethodEle
0650:                                .getAttribute(NAME_ATTRIBUTE);
0651:                        String callback = replacedMethodEle
0652:                                .getAttribute(REPLACER_ATTRIBUTE);
0653:                        ReplaceOverride replaceOverride = new ReplaceOverride(
0654:                                name, callback);
0655:                        // Look for arg-type match elements.
0656:                        List argTypeEles = DomUtils.getChildElementsByTagName(
0657:                                replacedMethodEle, ARG_TYPE_ELEMENT);
0658:                        for (Iterator it = argTypeEles.iterator(); it.hasNext();) {
0659:                            Element argTypeEle = (Element) it.next();
0660:                            replaceOverride.addTypeIdentifier(argTypeEle
0661:                                    .getAttribute(ARG_TYPE_MATCH_ATTRIBUTE));
0662:                        }
0663:                        replaceOverride
0664:                                .setSource(extractSource(replacedMethodEle));
0665:                        overrides.addOverride(replaceOverride);
0666:                    }
0667:                }
0668:            }
0669:
0670:            /**
0671:             * Parse a constructor-arg element.
0672:             */
0673:            public void parseConstructorArgElement(Element ele,
0674:                    BeanDefinition bd) {
0675:                String indexAttr = ele.getAttribute(INDEX_ATTRIBUTE);
0676:                String typeAttr = ele.getAttribute(TYPE_ATTRIBUTE);
0677:                if (StringUtils.hasLength(indexAttr)) {
0678:                    try {
0679:                        int index = Integer.parseInt(indexAttr);
0680:                        if (index < 0) {
0681:                            error("'index' cannot be lower than 0", ele);
0682:                        } else {
0683:                            try {
0684:                                this .parseState
0685:                                        .push(new ConstructorArgumentEntry(
0686:                                                index));
0687:                                Object value = parsePropertyValue(ele, bd, null);
0688:                                ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(
0689:                                        value);
0690:                                if (StringUtils.hasLength(typeAttr)) {
0691:                                    valueHolder.setType(typeAttr);
0692:                                }
0693:                                valueHolder.setSource(extractSource(ele));
0694:                                bd.getConstructorArgumentValues()
0695:                                        .addIndexedArgumentValue(index,
0696:                                                valueHolder);
0697:                            } finally {
0698:                                this .parseState.pop();
0699:                            }
0700:                        }
0701:                    } catch (NumberFormatException ex) {
0702:                        error(
0703:                                "Attribute 'index' of tag 'constructor-arg' must be an integer",
0704:                                ele);
0705:                    }
0706:                } else {
0707:                    try {
0708:                        this .parseState.push(new ConstructorArgumentEntry());
0709:                        Object value = parsePropertyValue(ele, bd, null);
0710:                        ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(
0711:                                value);
0712:                        if (StringUtils.hasLength(typeAttr)) {
0713:                            valueHolder.setType(typeAttr);
0714:                        }
0715:                        valueHolder.setSource(extractSource(ele));
0716:                        bd.getConstructorArgumentValues()
0717:                                .addGenericArgumentValue(valueHolder);
0718:                    } finally {
0719:                        this .parseState.pop();
0720:                    }
0721:                }
0722:            }
0723:
0724:            /**
0725:             * Parse a property element.
0726:             */
0727:            public void parsePropertyElement(Element ele, BeanDefinition bd) {
0728:                String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
0729:                if (!StringUtils.hasLength(propertyName)) {
0730:                    error("Tag 'property' must have a 'name' attribute", ele);
0731:                    return;
0732:                }
0733:                this .parseState.push(new PropertyEntry(propertyName));
0734:                try {
0735:                    if (bd.getPropertyValues().contains(propertyName)) {
0736:                        error("Multiple 'property' definitions for property '"
0737:                                + propertyName + "'", ele);
0738:                        return;
0739:                    }
0740:                    Object val = parsePropertyValue(ele, bd, propertyName);
0741:                    PropertyValue pv = new PropertyValue(propertyName, val);
0742:                    parseMetaElements(ele, pv);
0743:                    pv.setSource(extractSource(ele));
0744:                    bd.getPropertyValues().addPropertyValue(pv);
0745:                } finally {
0746:                    this .parseState.pop();
0747:                }
0748:            }
0749:
0750:            /**
0751:             * Get the value of a property element. May be a list etc.
0752:             * Also used for constructor arguments, "propertyName" being null in this case.
0753:             */
0754:            public Object parsePropertyValue(Element ele, BeanDefinition bd,
0755:                    String propertyName) {
0756:                String elementName = (propertyName != null) ? "<property> element for property '"
0757:                        + propertyName + "'"
0758:                        : "<constructor-arg> element";
0759:
0760:                // Should only have one child element: ref, value, list, etc.
0761:                NodeList nl = ele.getChildNodes();
0762:                Element subElement = null;
0763:                for (int i = 0; i < nl.getLength(); i++) {
0764:                    if (nl.item(i) instanceof  Element) {
0765:                        Element candidateEle = (Element) nl.item(i);
0766:                        if (DESCRIPTION_ELEMENT.equals(candidateEle
0767:                                .getTagName())) {
0768:                            // Keep going: we don't use this value for now.
0769:                        } else {
0770:                            // Child element is what we're looking for.
0771:                            if (subElement != null
0772:                                    && !META_ELEMENT.equals(subElement
0773:                                            .getTagName())) {
0774:                                error(
0775:                                        elementName
0776:                                                + " must not contain more than one sub-element",
0777:                                        ele);
0778:                            } else {
0779:                                subElement = candidateEle;
0780:                            }
0781:                        }
0782:                    }
0783:                }
0784:
0785:                boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
0786:                boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
0787:                if ((hasRefAttribute && hasValueAttribute)
0788:                        || ((hasRefAttribute || hasValueAttribute))
0789:                        && subElement != null) {
0790:                    error(
0791:                            elementName
0792:                                    + " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element",
0793:                            ele);
0794:                }
0795:
0796:                if (hasRefAttribute) {
0797:                    String refName = ele.getAttribute(REF_ATTRIBUTE);
0798:                    if (!StringUtils.hasText(refName)) {
0799:                        error(elementName + " contains empty 'ref' attribute",
0800:                                ele);
0801:                    }
0802:                    RuntimeBeanReference ref = new RuntimeBeanReference(refName);
0803:                    ref.setSource(extractSource(ele));
0804:                    return ref;
0805:                } else if (hasValueAttribute) {
0806:                    TypedStringValue valueHolder = new TypedStringValue(ele
0807:                            .getAttribute(VALUE_ATTRIBUTE));
0808:                    valueHolder.setSource(extractSource(ele));
0809:                    return valueHolder;
0810:                } else if (subElement != null) {
0811:                    return parsePropertySubElement(subElement, bd);
0812:                } else {
0813:                    // Neither child element nor "ref" or "value" attribute found.
0814:                    error(elementName + " must specify a ref or value", ele);
0815:                    return null;
0816:                }
0817:            }
0818:
0819:            public Object parsePropertySubElement(Element ele, BeanDefinition bd) {
0820:                return parsePropertySubElement(ele, bd, null);
0821:            }
0822:
0823:            /**
0824:             * Parse a value, ref or collection sub-element of a property or
0825:             * constructor-arg element.
0826:             * @param ele subelement of property element; we don't know which yet
0827:             * @param defaultTypeClassName the default type (class name) for any
0828:             * <code>&lt;value&gt;</code> tag that might be created
0829:             */
0830:            public Object parsePropertySubElement(Element ele,
0831:                    BeanDefinition bd, String defaultTypeClassName) {
0832:                if (!isDefaultNamespace(ele.getNamespaceURI())) {
0833:                    return parseNestedCustomElement(ele, bd);
0834:                } else if (DomUtils.nodeNameEquals(ele, BEAN_ELEMENT)) {
0835:                    BeanDefinitionHolder bdHolder = parseBeanDefinitionElement(
0836:                            ele, bd);
0837:                    if (bdHolder != null) {
0838:                        bdHolder = decorateBeanDefinitionIfRequired(ele,
0839:                                bdHolder);
0840:                    }
0841:                    return bdHolder;
0842:                } else if (DomUtils.nodeNameEquals(ele, REF_ELEMENT)) {
0843:                    // A generic reference to any name of any bean.
0844:                    String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);
0845:                    boolean toParent = false;
0846:                    if (!StringUtils.hasLength(refName)) {
0847:                        // A reference to the id of another bean in the same XML file.
0848:                        refName = ele.getAttribute(LOCAL_REF_ATTRIBUTE);
0849:                        if (!StringUtils.hasLength(refName)) {
0850:                            // A reference to the id of another bean in a parent context.
0851:                            refName = ele.getAttribute(PARENT_REF_ATTRIBUTE);
0852:                            toParent = true;
0853:                            if (!StringUtils.hasLength(refName)) {
0854:                                error(
0855:                                        "'bean', 'local' or 'parent' is required for <ref> element",
0856:                                        ele);
0857:                                return null;
0858:                            }
0859:                        }
0860:                    }
0861:                    if (!StringUtils.hasText(refName)) {
0862:                        error("<ref> element contains empty target attribute",
0863:                                ele);
0864:                        return null;
0865:                    }
0866:                    RuntimeBeanReference ref = new RuntimeBeanReference(
0867:                            refName, toParent);
0868:                    ref.setSource(extractSource(ele));
0869:                    return ref;
0870:                } else if (DomUtils.nodeNameEquals(ele, IDREF_ELEMENT)) {
0871:                    // A generic reference to any name of any bean.
0872:                    String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);
0873:                    if (!StringUtils.hasLength(refName)) {
0874:                        // A reference to the id of another bean in the same XML file.
0875:                        refName = ele.getAttribute(LOCAL_REF_ATTRIBUTE);
0876:                        if (!StringUtils.hasLength(refName)) {
0877:                            error(
0878:                                    "Either 'bean' or 'local' is required for <idref> element",
0879:                                    ele);
0880:                            return null;
0881:                        }
0882:                    }
0883:                    if (!StringUtils.hasText(refName)) {
0884:                        error(
0885:                                "<idref> element contains empty target attribute",
0886:                                ele);
0887:                        return null;
0888:                    }
0889:                    RuntimeBeanNameReference ref = new RuntimeBeanNameReference(
0890:                            refName);
0891:                    ref.setSource(extractSource(ele));
0892:                    return ref;
0893:                } else if (DomUtils.nodeNameEquals(ele, VALUE_ELEMENT)) {
0894:                    // It's a literal value.
0895:                    String value = DomUtils.getTextValue(ele);
0896:                    String typeClassName = ele.getAttribute(TYPE_ATTRIBUTE);
0897:                    if (!StringUtils.hasText(typeClassName)) {
0898:                        typeClassName = defaultTypeClassName;
0899:                    }
0900:                    try {
0901:                        return buildTypedStringValue(value, typeClassName, ele);
0902:                    } catch (ClassNotFoundException ex) {
0903:                        error("Type class [" + typeClassName
0904:                                + "] not found for <value> element", ele, ex);
0905:                        return value;
0906:                    }
0907:                } else if (DomUtils.nodeNameEquals(ele, NULL_ELEMENT)) {
0908:                    // It's a distinguished null value. Let's wrap it in a TypedStringValue
0909:                    // object in order to preserve the source location.
0910:                    TypedStringValue nullHolder = new TypedStringValue(null);
0911:                    nullHolder.setSource(extractSource(ele));
0912:                    return nullHolder;
0913:                } else if (DomUtils.nodeNameEquals(ele, LIST_ELEMENT)) {
0914:                    return parseListElement(ele, bd);
0915:                } else if (DomUtils.nodeNameEquals(ele, SET_ELEMENT)) {
0916:                    return parseSetElement(ele, bd);
0917:                } else if (DomUtils.nodeNameEquals(ele, MAP_ELEMENT)) {
0918:                    return parseMapElement(ele, bd);
0919:                } else if (DomUtils.nodeNameEquals(ele, PROPS_ELEMENT)) {
0920:                    return parsePropsElement(ele);
0921:                }
0922:                error("Unknown property sub-element: [" + ele.getTagName()
0923:                        + "]", ele);
0924:                return null;
0925:            }
0926:
0927:            private Object buildTypedStringValue(String value,
0928:                    String targetTypeName, Element ele)
0929:                    throws ClassNotFoundException {
0930:
0931:                ClassLoader classLoader = this .readerContext
0932:                        .getBeanClassLoader();
0933:                TypedStringValue typedValue = null;
0934:                if (!StringUtils.hasText(targetTypeName)) {
0935:                    typedValue = new TypedStringValue(value);
0936:                } else if (classLoader != null) {
0937:                    Class targetType = ClassUtils.forName(targetTypeName,
0938:                            classLoader);
0939:                    typedValue = new TypedStringValue(value, targetType);
0940:                } else {
0941:                    typedValue = new TypedStringValue(value, targetTypeName);
0942:                }
0943:                typedValue.setSource(extractSource(ele));
0944:                return typedValue;
0945:            }
0946:
0947:            /**
0948:             * Parse a list element.
0949:             */
0950:            public List parseListElement(Element collectionEle,
0951:                    BeanDefinition bd) {
0952:                String defaultTypeClassName = collectionEle
0953:                        .getAttribute(VALUE_TYPE_ATTRIBUTE);
0954:                NodeList nl = collectionEle.getChildNodes();
0955:                ManagedList list = new ManagedList(nl.getLength());
0956:                list.setSource(extractSource(collectionEle));
0957:                list.setMergeEnabled(parseMergeAttribute(collectionEle));
0958:                for (int i = 0; i < nl.getLength(); i++) {
0959:                    if (nl.item(i) instanceof  Element) {
0960:                        Element ele = (Element) nl.item(i);
0961:                        list.add(parsePropertySubElement(ele, bd,
0962:                                defaultTypeClassName));
0963:                    }
0964:                }
0965:                return list;
0966:            }
0967:
0968:            /**
0969:             * Parse a set element.
0970:             */
0971:            public Set parseSetElement(Element collectionEle, BeanDefinition bd) {
0972:                String defaultTypeClassName = collectionEle
0973:                        .getAttribute(VALUE_TYPE_ATTRIBUTE);
0974:                NodeList nl = collectionEle.getChildNodes();
0975:                ManagedSet set = new ManagedSet(nl.getLength());
0976:                set.setSource(extractSource(collectionEle));
0977:                set.setMergeEnabled(parseMergeAttribute(collectionEle));
0978:                for (int i = 0; i < nl.getLength(); i++) {
0979:                    if (nl.item(i) instanceof  Element) {
0980:                        Element ele = (Element) nl.item(i);
0981:                        set.add(parsePropertySubElement(ele, bd,
0982:                                defaultTypeClassName));
0983:                    }
0984:                }
0985:                return set;
0986:            }
0987:
0988:            /**
0989:             * Parse a map element.
0990:             */
0991:            public Map parseMapElement(Element mapEle, BeanDefinition bd) {
0992:                String defaultKeyTypeClassName = mapEle
0993:                        .getAttribute(KEY_TYPE_ATTRIBUTE);
0994:                String defaultValueTypeClassName = mapEle
0995:                        .getAttribute(VALUE_TYPE_ATTRIBUTE);
0996:
0997:                List entryEles = DomUtils.getChildElementsByTagName(mapEle,
0998:                        ENTRY_ELEMENT);
0999:                ManagedMap map = new ManagedMap(entryEles.size());
1000:                map.setMergeEnabled(parseMergeAttribute(mapEle));
1001:                map.setSource(extractSource(mapEle));
1002:
1003:                for (Iterator it = entryEles.iterator(); it.hasNext();) {
1004:                    Element entryEle = (Element) it.next();
1005:                    // Should only have one value child element: ref, value, list, etc.
1006:                    // Optionally, there might be a key child element.
1007:                    NodeList entrySubNodes = entryEle.getChildNodes();
1008:
1009:                    Element keyEle = null;
1010:                    Element valueEle = null;
1011:                    for (int j = 0; j < entrySubNodes.getLength(); j++) {
1012:                        if (entrySubNodes.item(j) instanceof  Element) {
1013:                            Element candidateEle = (Element) entrySubNodes
1014:                                    .item(j);
1015:                            if (DomUtils.nodeNameEquals(candidateEle,
1016:                                    KEY_ELEMENT)) {
1017:                                if (keyEle != null) {
1018:                                    error(
1019:                                            "<entry> element is only allowed to contain one <key> sub-element",
1020:                                            entryEle);
1021:                                } else {
1022:                                    keyEle = candidateEle;
1023:                                }
1024:                            } else {
1025:                                // Child element is what we're looking for.
1026:                                if (valueEle != null) {
1027:                                    error(
1028:                                            "<entry> element must not contain more than one value sub-element",
1029:                                            entryEle);
1030:                                } else {
1031:                                    valueEle = candidateEle;
1032:                                }
1033:                            }
1034:                        }
1035:                    }
1036:
1037:                    // Extract key from attribute or sub-element.
1038:                    Object key = null;
1039:                    boolean hasKeyAttribute = entryEle
1040:                            .hasAttribute(KEY_ATTRIBUTE);
1041:                    boolean hasKeyRefAttribute = entryEle
1042:                            .hasAttribute(KEY_REF_ATTRIBUTE);
1043:                    if ((hasKeyAttribute && hasKeyRefAttribute)
1044:                            || ((hasKeyAttribute || hasKeyRefAttribute))
1045:                            && keyEle != null) {
1046:                        error(
1047:                                "<entry> element is only allowed to contain either "
1048:                                        + "a 'key' attribute OR a 'key-ref' attribute OR a <key> sub-element",
1049:                                entryEle);
1050:                    }
1051:                    if (hasKeyAttribute) {
1052:                        key = buildTypedStringValueForMap(entryEle
1053:                                .getAttribute(KEY_ATTRIBUTE),
1054:                                defaultKeyTypeClassName, entryEle);
1055:                    } else if (hasKeyRefAttribute) {
1056:                        String refName = entryEle
1057:                                .getAttribute(KEY_REF_ATTRIBUTE);
1058:                        if (!StringUtils.hasText(refName)) {
1059:                            error(
1060:                                    "<entry> element contains empty 'key-ref' attribute",
1061:                                    entryEle);
1062:                        }
1063:                        RuntimeBeanReference ref = new RuntimeBeanReference(
1064:                                refName);
1065:                        ref.setSource(extractSource(entryEle));
1066:                        key = ref;
1067:                    } else if (keyEle != null) {
1068:                        key = parseKeyElement(keyEle, bd,
1069:                                defaultKeyTypeClassName);
1070:                    } else {
1071:                        error("<entry> element must specify a key", entryEle);
1072:                    }
1073:
1074:                    // Extract value from attribute or sub-element.
1075:                    Object value = null;
1076:                    boolean hasValueAttribute = entryEle
1077:                            .hasAttribute(VALUE_ATTRIBUTE);
1078:                    boolean hasValueRefAttribute = entryEle
1079:                            .hasAttribute(VALUE_REF_ATTRIBUTE);
1080:                    if ((hasValueAttribute && hasValueRefAttribute)
1081:                            || ((hasValueAttribute || hasValueRefAttribute))
1082:                            && valueEle != null) {
1083:                        error(
1084:                                "<entry> element is only allowed to contain either "
1085:                                        + "'value' attribute OR 'value-ref' attribute OR <value> sub-element",
1086:                                entryEle);
1087:                    }
1088:                    if (hasValueAttribute) {
1089:                        value = buildTypedStringValueForMap(entryEle
1090:                                .getAttribute(VALUE_ATTRIBUTE),
1091:                                defaultValueTypeClassName, entryEle);
1092:                    } else if (hasValueRefAttribute) {
1093:                        String refName = entryEle
1094:                                .getAttribute(VALUE_REF_ATTRIBUTE);
1095:                        if (!StringUtils.hasText(refName)) {
1096:                            error(
1097:                                    "<entry> element contains empty 'value-ref' attribute",
1098:                                    entryEle);
1099:                        }
1100:                        RuntimeBeanReference ref = new RuntimeBeanReference(
1101:                                refName);
1102:                        ref.setSource(extractSource(entryEle));
1103:                        value = ref;
1104:                    } else if (valueEle != null) {
1105:                        value = parsePropertySubElement(valueEle, bd,
1106:                                defaultValueTypeClassName);
1107:                    } else {
1108:                        error("<entry> element must specify a value", entryEle);
1109:                    }
1110:
1111:                    // Add final key and value to the Map.
1112:                    map.put(key, value);
1113:                }
1114:
1115:                return map;
1116:            }
1117:
1118:            private Object buildTypedStringValueForMap(String value,
1119:                    String defaultTypeClassName, Element entryEle) {
1120:                try {
1121:                    return buildTypedStringValue(value, defaultTypeClassName,
1122:                            entryEle);
1123:                } catch (ClassNotFoundException ex) {
1124:                    error("Type class [" + defaultTypeClassName
1125:                            + "] not found for Map key/value type", entryEle,
1126:                            ex);
1127:                    return value;
1128:                }
1129:            }
1130:
1131:            /**
1132:             * Parse a key sub-element of a map element.
1133:             */
1134:            public Object parseKeyElement(Element keyEle, BeanDefinition bd,
1135:                    String defaultKeyTypeClassName) {
1136:                NodeList nl = keyEle.getChildNodes();
1137:                Element subElement = null;
1138:                for (int i = 0; i < nl.getLength(); i++) {
1139:                    if (nl.item(i) instanceof  Element) {
1140:                        Element candidateEle = (Element) nl.item(i);
1141:                        // Child element is what we're looking for.
1142:                        if (subElement != null) {
1143:                            error(
1144:                                    "<key> element must not contain more than one value sub-element",
1145:                                    keyEle);
1146:                        } else {
1147:                            subElement = candidateEle;
1148:                        }
1149:                    }
1150:                }
1151:                return parsePropertySubElement(subElement, bd,
1152:                        defaultKeyTypeClassName);
1153:            }
1154:
1155:            /**
1156:             * Parse a props element.
1157:             */
1158:            public Properties parsePropsElement(Element propsEle) {
1159:                ManagedProperties props = new ManagedProperties();
1160:                props.setSource(extractSource(propsEle));
1161:                props.setMergeEnabled(parseMergeAttribute(propsEle));
1162:
1163:                List propEles = DomUtils.getChildElementsByTagName(propsEle,
1164:                        PROP_ELEMENT);
1165:                for (Iterator it = propEles.iterator(); it.hasNext();) {
1166:                    Element propEle = (Element) it.next();
1167:                    String key = propEle.getAttribute(KEY_ATTRIBUTE);
1168:                    // Trim the text value to avoid unwanted whitespace
1169:                    // caused by typical XML formatting.
1170:                    String value = DomUtils.getTextValue(propEle).trim();
1171:
1172:                    TypedStringValue keyHolder = new TypedStringValue(key);
1173:                    keyHolder.setSource(extractSource(propEle));
1174:                    TypedStringValue valueHolder = new TypedStringValue(value);
1175:                    valueHolder.setSource(extractSource(propEle));
1176:                    props.put(keyHolder, valueHolder);
1177:                }
1178:
1179:                return props;
1180:            }
1181:
1182:            /**
1183:             * Parse the merge attribute of a collection element, if any.
1184:             */
1185:            public boolean parseMergeAttribute(Element collectionElement) {
1186:                String value = collectionElement.getAttribute(MERGE_ATTRIBUTE);
1187:                if (DEFAULT_VALUE.equals(value)) {
1188:                    value = this .defaults.getMerge();
1189:                }
1190:                return TRUE_VALUE.equals(value);
1191:            }
1192:
1193:            public BeanDefinition parseCustomElement(Element ele) {
1194:                return parseCustomElement(ele, null);
1195:            }
1196:
1197:            public BeanDefinition parseCustomElement(Element ele,
1198:                    BeanDefinition containingBd) {
1199:                String namespaceUri = ele.getNamespaceURI();
1200:                NamespaceHandler handler = this .readerContext
1201:                        .getNamespaceHandlerResolver().resolve(namespaceUri);
1202:                if (handler == null) {
1203:                    error(
1204:                            "Unable to locate Spring NamespaceHandler for XML schema namespace ["
1205:                                    + namespaceUri + "]", ele);
1206:                    return null;
1207:                }
1208:                return handler.parse(ele, new ParserContext(this .readerContext,
1209:                        this , containingBd));
1210:            }
1211:
1212:            public BeanDefinitionHolder decorateBeanDefinitionIfRequired(
1213:                    Element ele, BeanDefinitionHolder definitionHolder) {
1214:                BeanDefinitionHolder finalDefinition = definitionHolder;
1215:
1216:                // Decorate based on custom attributes first.
1217:                NamedNodeMap attributes = ele.getAttributes();
1218:                for (int i = 0; i < attributes.getLength(); i++) {
1219:                    Node node = attributes.item(i);
1220:                    finalDefinition = decorateIfRequired(node, finalDefinition);
1221:                }
1222:
1223:                // Decorate based on custom nested elements.
1224:                NodeList children = ele.getChildNodes();
1225:                for (int i = 0; i < children.getLength(); i++) {
1226:                    Node node = children.item(i);
1227:                    if (node.getNodeType() == Node.ELEMENT_NODE) {
1228:                        finalDefinition = decorateIfRequired(node,
1229:                                finalDefinition);
1230:                    }
1231:                }
1232:                return finalDefinition;
1233:            }
1234:
1235:            private BeanDefinitionHolder decorateIfRequired(Node node,
1236:                    BeanDefinitionHolder originalDefinition) {
1237:                String namespaceUri = node.getNamespaceURI();
1238:                if (!isDefaultNamespace(namespaceUri)) {
1239:                    NamespaceHandler handler = this .readerContext
1240:                            .getNamespaceHandlerResolver()
1241:                            .resolve(namespaceUri);
1242:                    if (handler != null) {
1243:                        return handler.decorate(node, originalDefinition,
1244:                                new ParserContext(this .readerContext, this ));
1245:                    } else {
1246:                        // A custom namespace, not to be handled by Spring - maybe "xml:...".
1247:                        if (logger.isDebugEnabled()) {
1248:                            logger
1249:                                    .debug("No Spring NamespaceHandler found for XML schema namespace ["
1250:                                            + namespaceUri + "]");
1251:                        }
1252:                    }
1253:                }
1254:                return originalDefinition;
1255:            }
1256:
1257:            public boolean isDefaultNamespace(String namespaceUri) {
1258:                return (!StringUtils.hasLength(namespaceUri) || BEANS_NAMESPACE_URI
1259:                        .equals(namespaceUri));
1260:            }
1261:
1262:            private BeanDefinitionHolder parseNestedCustomElement(Element ele,
1263:                    BeanDefinition containingBd) {
1264:                BeanDefinition innerDefinition = parseCustomElement(ele,
1265:                        containingBd);
1266:                if (innerDefinition == null) {
1267:                    error(
1268:                            "Incorrect usage of element '"
1269:                                    + ele.getNodeName()
1270:                                    + "' in a nested manner. "
1271:                                    + "This tag cannot be used nested inside <property>.",
1272:                            ele);
1273:                    return null;
1274:                }
1275:                String id = ele.getNodeName()
1276:                        + BeanDefinitionReaderUtils.GENERATED_BEAN_NAME_SEPARATOR
1277:                        + ObjectUtils.getIdentityHexString(innerDefinition);
1278:                if (logger.isDebugEnabled()) {
1279:                    logger.debug("Using generated bean name [" + id
1280:                            + "] for nested custom element '"
1281:                            + ele.getNodeName() + "'");
1282:                }
1283:                return new BeanDefinitionHolder(innerDefinition, id);
1284:            }
1285:
1286:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.