KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > beans > factory > xml > DefaultBeanDefinitionDocumentReader


1 /*
2  * Copyright 2002-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.beans.factory.xml;
18
19 import java.io.IOException JavaDoc;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.w3c.dom.Document JavaDoc;
24 import org.w3c.dom.Element JavaDoc;
25 import org.w3c.dom.Node JavaDoc;
26 import org.w3c.dom.NodeList JavaDoc;
27
28 import org.springframework.beans.factory.BeanDefinitionStoreException;
29 import org.springframework.beans.factory.config.BeanDefinitionHolder;
30 import org.springframework.beans.factory.parsing.BeanComponentDefinition;
31 import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
32 import org.springframework.core.io.Resource;
33 import org.springframework.core.io.support.ResourcePatternUtils;
34 import org.springframework.util.StringUtils;
35 import org.springframework.util.SystemPropertyUtils;
36 import org.springframework.util.xml.DomUtils;
37
38 /**
39  * Default implementation of the {@link BeanDefinitionDocumentReader} interface.
40  * Reads bean definitions according to the "spring-beans" DTD and XSD format
41  * (Spring's default XML bean definition format).
42  *
43  * <p>The structure, elements and attribute names of the required XML document
44  * are hard-coded in this class. (Of course a transform could be run if necessary
45  * to produce this format). <code>&lt;beans&gt;</code> doesn't need to be the root
46  * element of the XML document: This class will parse all bean definition elements
47  * in the XML file, not regarding the actual root element.
48  *
49  * @author Rod Johnson
50  * @author Juergen Hoeller
51  * @author Rob Harrop
52  * @author Erik Wiersma
53  * @since 18.12.2003
54  */

55 public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
56
57     public static final String JavaDoc BEAN_ELEMENT = BeanDefinitionParserDelegate.BEAN_ELEMENT;
58
59     public static final String JavaDoc ALIAS_ELEMENT = "alias";
60
61     public static final String JavaDoc NAME_ATTRIBUTE = "name";
62
63     public static final String JavaDoc ALIAS_ATTRIBUTE = "alias";
64
65     public static final String JavaDoc IMPORT_ELEMENT = "import";
66
67     public static final String JavaDoc RESOURCE_ATTRIBUTE = "resource";
68
69
70     protected final Log logger = LogFactory.getLog(getClass());
71
72     private XmlReaderContext readerContext;
73
74
75     /**
76      * Parses bean definitions according to the "spring-beans" DTD.
77      * <p>Opens a DOM Document; then initializes the default settings
78      * specified at <code>&lt;beans&gt;</code> level; then parses
79      * the contained bean definitions.
80      */

81     public void registerBeanDefinitions(Document JavaDoc doc, XmlReaderContext readerContext) {
82         this.readerContext = readerContext;
83
84         logger.debug("Loading bean definitions");
85         Element JavaDoc root = doc.getDocumentElement();
86
87         BeanDefinitionParserDelegate delegate = createHelper(readerContext, root);
88
89         preProcessXml(root);
90         parseBeanDefinitions(root, delegate);
91         postProcessXml(root);
92     }
93
94     protected BeanDefinitionParserDelegate createHelper(XmlReaderContext readerContext, Element JavaDoc root) {
95         BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
96         delegate.initDefaults(root);
97         return delegate;
98     }
99
100     /**
101      * Return the descriptor for the XML resource that this parser works on.
102      */

103     protected final XmlReaderContext getReaderContext() {
104         return this.readerContext;
105     }
106
107     /**
108      * Invoke the {@link org.springframework.beans.factory.parsing.SourceExtractor} to pull the
109      * source metadata from the supplied {@link Element}.
110      */

111     protected Object JavaDoc extractSource(Element JavaDoc ele) {
112         return this.readerContext.extractSource(ele);
113     }
114
115
116     /**
117      * Parse the elements at the root level in the document:
118      * "import", "alias", "bean".
119      * @param root the DOM root element of the document
120      */

121     protected void parseBeanDefinitions(Element JavaDoc root, BeanDefinitionParserDelegate delegate) {
122         if (delegate.isDefaultNamespace(root.getNamespaceURI())) {
123             NodeList JavaDoc nl = root.getChildNodes();
124             for (int i = 0; i < nl.getLength(); i++) {
125                 Node JavaDoc node = nl.item(i);
126                 if (node instanceof Element JavaDoc) {
127                     Element JavaDoc ele = (Element JavaDoc) node;
128                     String JavaDoc namespaceUri = ele.getNamespaceURI();
129                     if (delegate.isDefaultNamespace(namespaceUri)) {
130                         parseDefaultElement(ele, delegate);
131                     }
132                     else {
133                         delegate.parseCustomElement(ele);
134                     }
135                 }
136             }
137         }
138         else {
139             delegate.parseCustomElement(root);
140         }
141     }
142
143     private void parseDefaultElement(Element JavaDoc ele, BeanDefinitionParserDelegate delegate) {
144         if (DomUtils.nodeNameEquals(ele, IMPORT_ELEMENT)) {
145             importBeanDefinitionResource(ele);
146         }
147         else if (DomUtils.nodeNameEquals(ele, ALIAS_ELEMENT)) {
148             processAliasRegistration(ele);
149         }
150         else if (DomUtils.nodeNameEquals(ele, BEAN_ELEMENT)) {
151             processBeanDefinition(ele, delegate);
152         }
153     }
154
155     /**
156      * Parse an "import" element and load the bean definitions
157      * from the given resource into the bean factory.
158      */

159     protected void importBeanDefinitionResource(Element JavaDoc ele) {
160         String JavaDoc location = ele.getAttribute(RESOURCE_ATTRIBUTE);
161         if (!StringUtils.hasText(location)) {
162             getReaderContext().error("Resource location must not be empty", ele);
163             return;
164         }
165
166         // Resolve system properties: e.g. "${user.dir}"
167
location = SystemPropertyUtils.resolvePlaceholders(location);
168
169         if (ResourcePatternUtils.isUrl(location)) {
170             try {
171                 int importCount = getReaderContext().getReader().loadBeanDefinitions(location);
172                 if (logger.isDebugEnabled()) {
173                     logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]");
174                 }
175             }
176             catch (BeanDefinitionStoreException ex) {
177                 getReaderContext().error(
178                         "Failed to import bean definitions from URL location [" + location + "]", ele, ex);
179             }
180         }
181         else {
182             // No URL -> considering resource location as relative to the current file.
183
try {
184                 Resource relativeResource = getReaderContext().getResource().createRelative(location);
185                 int importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
186                 if (logger.isDebugEnabled()) {
187                     logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]");
188                 }
189             }
190             catch (IOException JavaDoc ex) {
191                 getReaderContext().error(
192                         "Invalid relative resource location [" + location + "] to import bean definitions from", ele, ex);
193             }
194             catch (BeanDefinitionStoreException ex) {
195                 getReaderContext().error(
196                         "Failed to import bean definitions from relative location [" + location + "]", ele, ex);
197             }
198         }
199
200         getReaderContext().fireImportProcessed(location, extractSource(ele));
201     }
202
203     /**
204      * Process the given alias element, registering the alias with the registry.
205      */

206     protected void processAliasRegistration(Element JavaDoc ele) {
207         String JavaDoc name = ele.getAttribute(NAME_ATTRIBUTE);
208         String JavaDoc alias = ele.getAttribute(ALIAS_ATTRIBUTE);
209         boolean valid = true;
210         if (!StringUtils.hasText(name)) {
211             getReaderContext().error("Name must not be empty", ele);
212             valid = false;
213         }
214         if (!StringUtils.hasText(alias)) {
215             getReaderContext().error("Alias must not be empty", ele);
216             valid = false;
217         }
218         if (valid) {
219             try {
220                 getReaderContext().getRegistry().registerAlias(name, alias);
221             }
222             catch (BeanDefinitionStoreException ex) {
223                 getReaderContext().error("Failed to register alias '" + alias +
224                         "' for bean with name '" + name + "'", ele, ex);
225             }
226             getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));
227         }
228     }
229
230     /**
231      * Process the given bean element, parsing the bean definition
232      * and registering it with the registry.
233      */

234     protected void processBeanDefinition(Element JavaDoc ele, BeanDefinitionParserDelegate delegate) {
235         BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
236         if (bdHolder != null) {
237             bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
238             try {
239                 // Register the final decorated instance.
240
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
241             }
242             catch (BeanDefinitionStoreException ex) {
243                 getReaderContext().error("Failed to register bean definition with name '" +
244                         bdHolder.getBeanName() + "'", ele, ex);
245             }
246             // Send registration event.
247
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
248         }
249     }
250
251
252     /**
253      * Allow the XML to be extensible by processing any custom element types first,
254      * before we start to process the bean definitions. This method is a natural
255      * extension point for any other custom pre-processing of the XML.
256      * <p>The default implementation is empty. Subclasses can override this method to
257      * convert custom elements into standard Spring bean definitions, for example.
258      * Implementors have access to the parser's bean definition reader and the
259      * underlying XML resource, through the corresponding accessors.
260      * @see #getReaderContext()
261      */

262     protected void preProcessXml(Element JavaDoc root) {
263     }
264
265     /**
266      * Allow the XML to be extensible by processing any custom element types last,
267      * after we finished processing the bean definitions. This method is a natural
268      * extension point for any other custom post-processing of the XML.
269      * <p>The default implementation is empty. Subclasses can override this method to
270      * convert custom elements into standard Spring bean definitions, for example.
271      * Implementors have access to the parser's bean definition reader and the
272      * underlying XML resource, through the corresponding accessors.
273      * @see #getReaderContext()
274      */

275     protected void postProcessXml(Element JavaDoc root) {
276     }
277
278 }
279
Popular Tags