EMMA Coverage Report (generated Thu Jan 24 13:37:04 CST 2013)
[all classes][org.springframework.batch.core.configuration.support]

COVERAGE SUMMARY FOR SOURCE FILE [ClassPathXmlApplicationContextFactory.java]

nameclass, %method, %block, %line, %
ClassPathXmlApplicationContextFactory.java100% (2/2)88%  (21/24)88%  (302/343)87%  (65.6/75)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ClassPathXmlApplicationContextFactory100% (1/1)84%  (16/19)82%  (183/224)82%  (42.6/52)
getBeanFactoryPostProcessorClasses (): Collection 0%   (0/1)0%   (0/3)0%   (0/1)
isCopyConfiguration (): boolean 0%   (0/1)0%   (0/3)0%   (0/1)
setBeanPostProcessorExcludeClasses (Class []): void 0%   (0/1)0%   (0/21)0%   (0/4)
setBeanFactoryPostProcessorClasses (Class []): void 100% (1/1)57%  (12/21)64%  (2.6/4)
createApplicationContext (): ConfigurableApplicationContext 100% (1/1)77%  (10/13)67%  (2/3)
equals (Object): boolean 100% (1/1)87%  (13/15)80%  (4/5)
<static initializer> 100% (1/1)100% (4/4)100% (1/1)
ClassPathXmlApplicationContextFactory (): void 100% (1/1)100% (4/4)100% (2/2)
ClassPathXmlApplicationContextFactory (Resource): void 100% (1/1)100% (34/34)100% (9/9)
access$000 (ClassPathXmlApplicationContextFactory): Resource 100% (1/1)100% (3/3)100% (1/1)
access$100 (ClassPathXmlApplicationContextFactory): Collection 100% (1/1)100% (3/3)100% (1/1)
access$200 (ClassPathXmlApplicationContextFactory): ConfigurableApplicationCo... 100% (1/1)100% (3/3)100% (1/1)
hashCode (): int 100% (1/1)100% (4/4)100% (1/1)
prepareBeanFactory (DefaultListableBeanFactory, DefaultListableBeanFactory): ... 100% (1/1)100% (61/61)100% (9/9)
prepareContext (ConfigurableApplicationContext, ConfigurableApplicationContex... 100% (1/1)100% (1/1)100% (1/1)
setApplicationContext (ApplicationContext): void 100% (1/1)100% (11/11)100% (5/5)
setCopyConfiguration (boolean): void 100% (1/1)100% (4/4)100% (2/2)
setResource (Resource): void 100% (1/1)100% (4/4)100% (2/2)
toString (): String 100% (1/1)100% (12/12)100% (1/1)
     
class ClassPathXmlApplicationContextFactory$ResourceXmlApplicationContext100% (1/1)100% (5/5)100% (119/119)100% (23/23)
ClassPathXmlApplicationContextFactory$ResourceXmlApplicationContext (ClassPat... 100% (1/1)100% (37/37)100% (11/11)
customizeBeanFactory (DefaultListableBeanFactory): void 100% (1/1)100% (55/55)100% (7/7)
generateId (Resource): String 100% (1/1)100% (8/8)100% (3/3)
getConfigResources (): Resource [] 100% (1/1)100% (9/9)100% (1/1)
toString (): String 100% (1/1)100% (10/10)100% (1/1)

1/*
2 * Copyright 2006-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 
17package org.springframework.batch.core.configuration.support;
18 
19import java.io.IOException;
20import java.util.ArrayList;
21import java.util.Collection;
22import java.util.List;
23 
24import org.apache.commons.logging.Log;
25import org.apache.commons.logging.LogFactory;
26import org.springframework.beans.BeansException;
27import org.springframework.beans.factory.BeanFactoryAware;
28import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
29import org.springframework.beans.factory.config.BeanPostProcessor;
30import org.springframework.beans.factory.config.ConfigurableBeanFactory;
31import org.springframework.beans.factory.config.CustomEditorConfigurer;
32import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
33import org.springframework.beans.factory.support.DefaultListableBeanFactory;
34import org.springframework.context.ApplicationContext;
35import org.springframework.context.ApplicationContextAware;
36import org.springframework.context.ConfigurableApplicationContext;
37import org.springframework.context.support.AbstractXmlApplicationContext;
38import org.springframework.core.io.Resource;
39import org.springframework.util.Assert;
40 
41/**
42 * {@link ApplicationContextFactory} implementation that takes a parent context
43 * and a path to the context to create. When createApplicationContext method is
44 * called, the child {@link ApplicationContext} will be returned. The child
45 * context is not re-created every time it is requested, it is lazily
46 * initialized and cached. Clients should ensure that it is closed when it is no
47 * longer needed. If a path is not set, the parent will always be returned.
48 * 
49 */
50public class ClassPathXmlApplicationContextFactory implements ApplicationContextFactory, ApplicationContextAware {
51 
52        private static final Log logger = LogFactory.getLog(ClassPathXmlApplicationContextFactory.class);
53 
54        private Resource resource;
55 
56        private ConfigurableApplicationContext parent;
57 
58        private boolean copyConfiguration = true;
59 
60        private Collection<Class<? extends BeanFactoryPostProcessor>> beanFactoryPostProcessorClasses;
61 
62        private Collection<Class<?>> beanPostProcessorExcludeClasses;
63 
64        /**
65         * Convenient constructor for configuration purposes.
66         */
67        public ClassPathXmlApplicationContextFactory() {
68                this(null);
69        }
70 
71        /**
72         * Create a factory instance with the resource specified. The resource is a
73         * Spring XML configuration file.
74         */
75        public ClassPathXmlApplicationContextFactory(Resource resource) {
76 
77                this.resource = resource;
78                beanFactoryPostProcessorClasses = new ArrayList<Class<? extends BeanFactoryPostProcessor>>();
79                beanFactoryPostProcessorClasses.add(PropertyPlaceholderConfigurer.class);
80                beanFactoryPostProcessorClasses.add(CustomEditorConfigurer.class);
81                beanPostProcessorExcludeClasses = new ArrayList<Class<?>>();
82                /*
83                 * Assume that a BeanPostProcessor that is BeanFactoryAware must be
84                 * specific to the parent and remove it from the child (e.g. an
85                 * AutoProxyCreator will not work properly). Unfortunately there might
86                 * still be a a BeanPostProcessor with a dependency that itself is
87                 * BeanFactoryAware, but we can't legislate for that here.
88                 */
89                beanPostProcessorExcludeClasses.add(BeanFactoryAware.class);
90        }
91 
92        /**
93         * Setter for the path to the xml to load to create an
94         * {@link ApplicationContext}. Use imports to centralise the configuration
95         * in one file.
96         * 
97         * @param resource the resource path to the xml to load for the child
98         * context.
99         */
100        public void setResource(Resource resource) {
101                this.resource = resource;
102        }
103 
104        /**
105         * Flag to indicate that configuration such as bean post processors and
106         * custom editors should be copied from the parent context. Defaults to
107         * true.
108         * 
109         * @param copyConfiguration the flag value to set
110         */
111        public void setCopyConfiguration(boolean copyConfiguration) {
112                this.copyConfiguration = copyConfiguration;
113        }
114 
115        /**
116         * Protected access for subclasses to the flag determining whether
117         * configuration should be copied from parent context.
118         * 
119         * @return the flag value
120         */
121        protected final boolean isCopyConfiguration() {
122                return copyConfiguration;
123        }
124 
125        /**
126         * Determines which bean factory post processors (like property
127         * placeholders) should be copied from the parent context. Defaults to
128         * {@link PropertyPlaceholderConfigurer} and {@link CustomEditorConfigurer}.
129         * 
130         * @param copyBeanFactoryPostProcessors the flag value to set
131         */
132 
133        public void setBeanFactoryPostProcessorClasses(
134                        Class<? extends BeanFactoryPostProcessor>[] beanFactoryPostProcessorClasses) {
135                this.beanFactoryPostProcessorClasses = new ArrayList<Class<? extends BeanFactoryPostProcessor>>();
136                for (int i = 0; i < beanFactoryPostProcessorClasses.length; i++) {
137                        this.beanFactoryPostProcessorClasses.add(beanFactoryPostProcessorClasses[i]);
138                }
139        }
140 
141        /**
142         * Determines by exclusion which bean post processors should be copied from
143         * the parent context. Defaults to {@link BeanFactoryAware} (so any post
144         * processors that have a reference to the parent bean factory are not
145         * copied into the child). Note that these classes do not themselves have to
146         * be {@link BeanPostProcessor} implementations or sub-interfaces.
147         * 
148         * @param beanPostProcessorExcludeClasses the classes to set
149         */
150        public void setBeanPostProcessorExcludeClasses(Class<?>[] beanPostProcessorExcludeClasses) {
151                this.beanPostProcessorExcludeClasses = new ArrayList<Class<?>>();
152                for (int i = 0; i < beanPostProcessorExcludeClasses.length; i++) {
153                        this.beanPostProcessorExcludeClasses.add(beanPostProcessorExcludeClasses[i]);
154                }
155 
156        }
157 
158        /**
159         * Protected access to the list of bean factory post processor classes that
160         * should be copied over to the context from the parent.
161         * 
162         * @return the classes for post processors that were nominated for copying
163         */
164        protected final Collection<Class<? extends BeanFactoryPostProcessor>> getBeanFactoryPostProcessorClasses() {
165                return beanFactoryPostProcessorClasses;
166        }
167 
168        /**
169         * Setter for the parent application context.
170         * 
171         * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
172         */
173        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
174                if (applicationContext == null) {
175                        return;
176                }
177                Assert.isInstanceOf(ConfigurableApplicationContext.class, applicationContext);
178                parent = (ConfigurableApplicationContext) applicationContext;
179        }
180 
181        /**
182         * Creates an {@link ApplicationContext} from the provided path.
183         * 
184         * @see ApplicationContextFactory#createApplicationContext()
185         */
186        public ConfigurableApplicationContext createApplicationContext() {
187 
188                if (resource == null) {
189                        return parent;
190                }
191 
192                return new ResourceXmlApplicationContext(parent);
193 
194        }
195 
196        /**
197         * @author Dave Syer
198         * 
199         */
200        private final class ResourceXmlApplicationContext extends AbstractXmlApplicationContext {
201 
202                private final DefaultListableBeanFactory parentBeanFactory;
203 
204                /**
205                 * @param parent
206                 */
207                public ResourceXmlApplicationContext(ConfigurableApplicationContext parent) {
208                        super(parent);
209                        setId(generateId(resource));
210                        if (parent != null) {
211                                Assert.isTrue(parent.getBeanFactory() instanceof DefaultListableBeanFactory,
212                                                "The parent application context must have a bean factory of type DefaultListableBeanFactory");
213                                parentBeanFactory = (DefaultListableBeanFactory) parent.getBeanFactory();
214                                refreshBeanFactory();
215                                prepareContext(parent, this);
216                        }
217                        else {
218                                parentBeanFactory = null;
219                        }
220                        refresh();
221                }
222 
223                /**
224                 * @param resource
225                 * @return an identifier for the context
226                 */
227                private String generateId(Resource resource) {
228                        try {
229                                return resource.getURI().toString();
230                        }
231                        catch (IOException e) {
232                                return resource.toString();
233                        }
234                }
235 
236                @Override
237                protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
238                        super.customizeBeanFactory(beanFactory);
239                        if (parentBeanFactory != null) {
240                                ClassPathXmlApplicationContextFactory.this.prepareBeanFactory(parentBeanFactory, beanFactory);
241                                for (Class<? extends BeanFactoryPostProcessor> cls : beanFactoryPostProcessorClasses) {
242                                        for (String name : parent.getBeanNamesForType(cls)) {
243                                                beanFactory.registerSingleton(name, ((BeanFactoryPostProcessor) parent.getBean(name)));
244                                        }
245                                }
246                        }
247                }
248 
249                @Override
250                protected Resource[] getConfigResources() {
251                        return new Resource[] { resource };
252                }
253 
254                @Override
255                public String toString() {
256                        return "ResourceXmlApplicationContext:" + getId();
257                }
258 
259        }
260 
261        /**
262         * Extension point for special subclasses that want to do more complex
263         * things with the context prior to refresh. The default implementation
264         * does nothing.
265         * 
266         * @param parent the parent for the new application context
267         * @param context the new application context before it is refreshed, but
268         * after bean factory is initialized
269         * 
270         * @see ClassPathXmlApplicationContextFactory#setBeanFactoryPostProcessorClasses(Class[])
271         */
272        protected void prepareContext(ConfigurableApplicationContext parent, ConfigurableApplicationContext context) {
273        }
274 
275        /**
276         * Extension point for special subclasses that want to do more complex
277         * things with the bean factory prior to refresh. The default implementation
278         * copies all configuration from the parent according to the
279         * {@link #setCopyConfiguration(boolean) flag} set.
280         * 
281         * @param parent the parent bean factory for the new context (will never be
282         * null)
283         * @param beanFactory the new bean factory before bean definitions are
284         * loaded
285         * 
286         * @see ClassPathXmlApplicationContextFactory#setCopyConfiguration(boolean)
287         * @see DefaultListableBeanFactory#copyConfigurationFrom(ConfigurableBeanFactory)
288         */
289        protected void prepareBeanFactory(DefaultListableBeanFactory parent, DefaultListableBeanFactory beanFactory) {
290                if (copyConfiguration && parent != null) {
291                        beanFactory.copyConfigurationFrom(parent);
292                        @SuppressWarnings("unchecked")
293                        List<BeanPostProcessor> beanPostProcessors = beanFactory.getBeanPostProcessors();
294                        for (BeanPostProcessor beanPostProcessor : new ArrayList<BeanPostProcessor>(beanPostProcessors)) {
295                                for (Class<?> cls : beanPostProcessorExcludeClasses) {
296                                        if (cls.isAssignableFrom(beanPostProcessor.getClass())) {
297                                                logger.debug("Removing bean post processor: " + beanPostProcessor + " of type " + cls);
298                                                beanPostProcessors.remove(beanPostProcessor);
299                                        }
300                                }
301                        }
302                }
303        }
304 
305        @Override
306        public String toString() {
307                return "ClassPathXmlApplicationContextFactory [resource=" + resource + "]";
308        }
309 
310        @Override
311        public int hashCode() {
312                return toString().hashCode();
313        }
314 
315        @Override
316        public boolean equals(Object obj) {
317                if (this == obj)
318                        return true;
319                if (obj == null)
320                        return false;
321                return toString().equals(obj.toString());
322        }
323 
324}

[all classes][org.springframework.batch.core.configuration.support]
EMMA 2.0.5312 (C) Vladimir Roubtsov