View Javadoc

1   /*
2    * Copyright 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 net.sf.snamespaces.config;
18  
19  import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
20  import org.springframework.beans.factory.support.AbstractBeanDefinition;
21  import org.springframework.beans.factory.support.BeanDefinitionRegistry;
22  import org.springframework.beans.factory.support.RootBeanDefinition;
23  import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
24  import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate;
25  import org.springframework.beans.factory.xml.ParserContext;
26  import org.springframework.beans.factory.xml.XmlReaderContext;
27  import org.springframework.util.Assert;
28  import org.springframework.util.ClassUtils;
29  import org.springframework.util.StringUtils;
30  import org.w3c.dom.Element;
31  
32  /**
33   * TODO make doc
34   * 
35   * @author Jonhnny Weslley
36   * @version 1.00, 13/09/2007
37   * @since 1.0
38   */
39  public class BeanDefinitionParserDependentFromFactoryPostProcessor extends
40  		AbstractBeanDefinitionParser {
41  
42  	/** Constant for the class attribute */
43  	private static final String CLASS_ATTRIBUTE = "class";
44  
45  	private final String prefix; 
46  	private final Class<?> expectedBeanClass;
47  	private final Class<?> factoryPostProcessorClass;
48  
49  	BeanDefinitionParserDependentFromFactoryPostProcessor(
50  			final String prefix, final Class<?> expectedBeanClass, final Class<?> factoryPostProcessorClass) {
51  		Assert.hasText(prefix);
52  		Assert.notNull(expectedBeanClass);
53  		Assert.isAssignable(BeanFactoryPostProcessor.class, factoryPostProcessorClass);
54  		this.prefix = prefix;
55  		this.expectedBeanClass = expectedBeanClass;
56  		this.factoryPostProcessorClass = factoryPostProcessorClass;
57  	}
58  
59  	@Override
60  	protected final AbstractBeanDefinition parseInternal(final Element element,
61  			final ParserContext parserContext) {
62  
63  		final XmlReaderContext readerContext = parserContext.getReaderContext();
64  		final BeanDefinitionParserDelegate delegate = parserContext.getDelegate();
65  
66  		final String className = getBeanClassName(element);
67  		try {
68  			registerFactoryPostProcessorIfNecessary(parserContext.getRegistry());
69  
70  			final Class<?> beanClass = ClassUtils.forName(className);
71  			Assert.isAssignable(expectedBeanClass, beanClass);
72  
73  			final AbstractBeanDefinition bd = new RootBeanDefinition(beanClass);
74  
75  			/* Parse bean elements */
76  			delegate.parseMetaElements(element, bd);
77  			delegate.parseLookupOverrideSubElements(element, bd.getMethodOverrides());
78  			delegate.parseReplacedMethodSubElements(element, bd.getMethodOverrides());
79  
80  			delegate.parseConstructorArgElements(element, bd);
81  			delegate.parsePropertyElements(element, bd);
82  
83  			bd.setResourceDescription(readerContext.getResource().getDescription());
84  			bd.setSource(parserContext.extractSource(element));
85  			return bd;
86  
87  		} catch (final ClassNotFoundException ex) {
88  			readerContext.error("Bean class [" + className + "] not found", element, null, ex);
89  
90  		} catch (final NoClassDefFoundError err) {
91  			readerContext.error("Class that bean class [" + className + "] depends on not found", element, null, err);
92  
93  		} catch (final Throwable ex) {
94  			readerContext.error("Unexpected failure during bean definition parsing", element, null, ex);
95  		}
96  		return null;
97  	}
98  
99  	/**
100 	 * Determine the bean class name corresponding to the supplied {@link Element}.
101 	 * @param element the <code>Element</code> that is being parsed
102 	 * @return the class name of the bean that is being defined via parsing the supplied <code>Element</code>
103 	 * (must <b>not</b> be <code>null</code>)
104 	 * @see #parseInternal(Element, ParserContext)   
105 	 */
106 	protected String getBeanClassName(final Element element) {
107 		return element.getAttribute(CLASS_ATTRIBUTE);
108 	}
109 
110 	@Override
111 	protected final String resolveId(final Element element,
112 			final AbstractBeanDefinition definition, final ParserContext parserContext) {
113 		return prefix + resolveName(element, definition, parserContext);
114 	}
115 
116 	protected String resolveName(final Element element,
117 			final AbstractBeanDefinition definition, final ParserContext parserContext) {
118 		return getBeanClassName(element);
119 	}
120 
121 	protected String getFactoryPostProcessorBeanName() {
122 		return factoryPostProcessorClass.getPackage().getName() + "." 
123 				+ StringUtils.uncapitalize(factoryPostProcessorClass.getSimpleName());
124 	}
125 
126 	private void registerFactoryPostProcessorIfNecessary(final BeanDefinitionRegistry registry) {
127 		final String factoryPostProcessorBeanName = getFactoryPostProcessorBeanName();
128 		if (!registry.containsBeanDefinition(factoryPostProcessorBeanName)) {
129 			final RootBeanDefinition beanDefinition = new RootBeanDefinition(factoryPostProcessorClass);
130 			registry.registerBeanDefinition(factoryPostProcessorBeanName, beanDefinition);
131 		}
132 	}
133 
134 }