001/*
002 * Copyright 2006-2010 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.springframework.batch.core.configuration.support;
017
018import java.util.ArrayList;
019import java.util.Arrays;
020import java.util.List;
021
022import org.springframework.beans.factory.BeanFactoryAware;
023import org.springframework.beans.factory.FactoryBean;
024import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
025import org.springframework.beans.factory.config.BeanPostProcessor;
026import org.springframework.beans.factory.config.CustomEditorConfigurer;
027import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
028import org.springframework.context.ApplicationContext;
029import org.springframework.context.ApplicationContextAware;
030import org.springframework.core.io.Resource;
031
032/**
033 * A convenient factory for creating a set of {@link ApplicationContextFactory}
034 * components from a set of {@link Resource resources}.
035 *
036 * @author Dave Syer
037 *
038 */
039public class ClasspathXmlApplicationContextsFactoryBean implements FactoryBean<ApplicationContextFactory[]>, ApplicationContextAware {
040
041        private List<Resource> resources = new ArrayList<Resource>();
042
043        private boolean copyConfiguration = true;
044
045        private Class<? extends BeanFactoryPostProcessor>[] beanFactoryPostProcessorClasses;
046
047        private Class<?>[] beanPostProcessorExcludeClasses;
048
049        private ApplicationContext applicationContext;
050
051        /**
052         * A set of resources to load using a
053         * {@link GenericApplicationContextFactory}. Each resource should be a
054         * Spring configuration file which is loaded into an application context
055         * whose parent is the current context. In a configuration file the
056         * resources can be given as a pattern (e.g.
057         * <code>classpath*:/config/*-context.xml</code>).
058         *
059         * @param resources array of resources to use
060         */
061        public void setResources(Resource[] resources) {
062                this.resources = Arrays.asList(resources);
063        }
064
065        /**
066         * Flag to indicate that configuration such as bean post processors and
067         * custom editors should be copied from the parent context. Defaults to
068         * true.
069         *
070         * @param copyConfiguration the flag value to set
071         */
072        public void setCopyConfiguration(boolean copyConfiguration) {
073                this.copyConfiguration = copyConfiguration;
074        }
075
076        /**
077         * Determines which bean factory post processors (like property
078         * placeholders) should be copied from the parent context. Defaults to
079         * {@link PropertyPlaceholderConfigurer} and {@link CustomEditorConfigurer}.
080         *
081         * @param beanFactoryPostProcessorClasses post processor types to be copied
082         */
083
084        public void setBeanFactoryPostProcessorClasses(
085                        Class<? extends BeanFactoryPostProcessor>[] beanFactoryPostProcessorClasses) {
086                this.beanFactoryPostProcessorClasses = beanFactoryPostProcessorClasses;
087        }
088
089        /**
090         * Determines by exclusion which bean post processors should be copied from
091         * the parent context. Defaults to {@link BeanFactoryAware} (so any post
092         * processors that have a reference to the parent bean factory are not
093         * copied into the child). Note that these classes do not themselves have to
094         * be {@link BeanPostProcessor} implementations or sub-interfaces.
095         *
096         * @param beanPostProcessorExcludeClasses the classes to set
097         */
098        public void setBeanPostProcessorExcludeClasses(Class<?>[] beanPostProcessorExcludeClasses) {
099                this.beanPostProcessorExcludeClasses = beanPostProcessorExcludeClasses;
100        }
101
102        /**
103         * Create an {@link ApplicationContextFactory} from each resource provided
104         * in {@link #setResources(Resource[])}.
105         *
106         * @return an array of {@link ApplicationContextFactory}
107         * @see org.springframework.beans.factory.FactoryBean#getObject()
108         */
109        @Override
110        public ApplicationContextFactory[] getObject() throws Exception {
111
112                if (resources == null) {
113                        return new ApplicationContextFactory[0];
114                }
115
116                List<ApplicationContextFactory> applicationContextFactories = new ArrayList<>();
117                for (Resource resource : resources) {
118                        GenericApplicationContextFactory factory = new GenericApplicationContextFactory(resource);
119                        factory.setCopyConfiguration(copyConfiguration);
120                        if (beanFactoryPostProcessorClasses != null) {
121                                factory.setBeanFactoryPostProcessorClasses(beanFactoryPostProcessorClasses);
122                        }
123                        if (beanPostProcessorExcludeClasses != null) {
124                                factory.setBeanPostProcessorExcludeClasses(beanPostProcessorExcludeClasses);
125                        }
126                        factory.setApplicationContext(applicationContext);
127                        applicationContextFactories.add(factory);
128                }
129                return applicationContextFactories.toArray(new ApplicationContextFactory[applicationContextFactories.size()]);
130        }
131
132        /**
133         * The type of object returned by this factory - an array of
134         * {@link ApplicationContextFactory}.
135         *
136         * @return array of {@link ApplicationContextFactory}
137         * @see FactoryBean#getObjectType()
138         */
139        @Override
140        public Class<?> getObjectType() {
141                return ApplicationContextFactory[].class;
142        }
143
144        /**
145         * Optimization hint for bean factory.
146         * @return true
147         * @see FactoryBean#isSingleton()
148         */
149        @Override
150        public boolean isSingleton() {
151                return true;
152        }
153
154        /**
155         * An application context that can be used as a parent context for all the
156         * factories.
157         *
158         * @param applicationContext the {@link ApplicationContext} to set
159         * @see ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
160         */
161        @Override
162        public void setApplicationContext(ApplicationContext applicationContext) {
163                this.applicationContext = applicationContext;
164        }
165
166}