001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.xbean.server.spring.loader;
018
019 import java.io.File;
020 import java.util.Collections;
021 import java.util.Iterator;
022 import java.util.List;
023
024 import org.apache.xbean.kernel.Kernel;
025 import org.apache.xbean.kernel.ServiceFactory;
026 import org.apache.xbean.kernel.ServiceName;
027 import org.apache.xbean.kernel.StringServiceName;
028 import org.apache.xbean.server.loader.Loader;
029 import org.apache.xbean.server.spring.configuration.SpringConfigurationServiceFactory;
030 import org.apache.xbean.spring.context.FileSystemXmlApplicationContext;
031 import org.apache.xbean.spring.context.SpringApplicationContext;
032 import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
033 import org.springframework.context.support.AbstractXmlApplicationContext;
034
035 /**
036 * SpringLoader loads Spring xml configurations into a Kernel. This service uses the XBean version of
037 * FileSystemXmlApplicationContext so custom XML extensions are available. This loader also support the specification
038 * of SpringXmlPreprocessors and BeanFactoryPostProcessors to apply to the configuration.
039 *
040 * @org.apache.xbean.XBean namespace="http://xbean.apache.org/schemas/server" element="spring-loader"
041 * description="Loads Spring xml configurations into a Kernel"
042 *
043 * @author Dain Sundstrom
044 * @version $Id$
045 * @since 2.0
046 */
047 public class SpringLoader implements Loader {
048 private Kernel kernel;
049 private File baseDir = new File(".").getAbsoluteFile();
050 private List beanFactoryPostProcessors = Collections.EMPTY_LIST;
051 private List xmlPreprocessors = Collections.EMPTY_LIST;
052 private AbstractXmlApplicationContext applicationContext;
053
054 /**
055 * Creates an empty SpringLoader. Note this loader is not usable until a kernel is specified.
056 */
057 public SpringLoader() {
058 }
059
060 /**
061 * {@inheritDoc}
062 */
063 public Kernel getKernel() {
064 return kernel;
065 }
066
067 /**
068 * Sets the kernel in which configurations are loaded.
069 * @param kernel the kernel in which configurations are loaded
070 */
071 public void setKernel(Kernel kernel) {
072 this.kernel = kernel;
073 }
074
075 /**
076 * Gets the BeanFactoryPostProcessors to apply to the configuration.
077 * @return the BeanFactoryPostProcessors to apply to the configuration
078 */
079 public List getBeanFactoryPostProcessors() {
080 return beanFactoryPostProcessors;
081 }
082
083 /**
084 * Sets the BeanFactoryPostProcessors to apply to the configuration.
085 * @param beanFactoryPostProcessors the BeanFactoryPostProcessors to apply to the configuration
086 */
087 public void setBeanFactoryPostProcessors(List beanFactoryPostProcessors) {
088 this.beanFactoryPostProcessors = beanFactoryPostProcessors;
089 }
090
091 /**
092 * Gets the base directory from which configuration locations are resolved.
093 * @return the base directory from which configuration locations are resolved
094 */
095 public File getBaseDir() {
096 return baseDir;
097 }
098
099 /**
100 * Sets the base directory from which configuration locations are resolved.
101 * @param baseDir the base directory from which configuration locations are resolved
102 */
103 public void setBaseDir(File baseDir) {
104 this.baseDir = baseDir;
105 }
106
107 /**
108 * Gets the SpringXmlPreprocessors applied to the configuration.
109 * @return the SpringXmlPreprocessors applied to the configuration
110 */
111 public List getXmlPreprocessors() {
112 return xmlPreprocessors;
113 }
114
115 /**
116 * Sets the SpringXmlPreprocessors applied to the configuration.
117 * @param xmlPreprocessors the SpringXmlPreprocessors applied to the configuration
118 */
119 public void setXmlPreprocessors(List xmlPreprocessors) {
120 this.xmlPreprocessors = xmlPreprocessors;
121 }
122
123 /**
124 * Loads the specified configuration into the kernel. The location specifies a file relative to the baseDir using
125 * baseDir.toURI().resolve(location).getPath() + ".xml". This service uses the XBean version of
126 * FileSystemXmlApplicationContext so custom XML extensions are available.
127 * @param location the location of the configuration file relative to the base directory without the .xml extension
128 * @return the name of the SpringConfiguration service for this location
129 * @throws Exception if a problem occurs while loading the Spring configuration file
130 */
131 public ServiceName load(String location) throws Exception {
132 String resolvedLocation = baseDir.toURI().resolve(location).getPath();
133 String configLocation = "/" + resolvedLocation + ".xml";
134 applicationContext = createXmlApplicationContext(configLocation);
135
136 for (Iterator iter = beanFactoryPostProcessors.iterator(); iter.hasNext();) {
137 BeanFactoryPostProcessor processor = (BeanFactoryPostProcessor) iter.next();
138 applicationContext.addBeanFactoryPostProcessor(processor);
139 }
140 applicationContext.setDisplayName(location);
141
142 ClassLoader classLoader = applicationContext.getClassLoader();
143 if (classLoader == null) {
144 classLoader = Thread.currentThread().getContextClassLoader();
145 }
146 if (classLoader == null) {
147 classLoader = SpringLoader.class.getClassLoader();
148 }
149
150 ServiceName serviceName = new StringServiceName("configuration:" + location);
151 ServiceFactory springConfigurationServiceFactory = new SpringConfigurationServiceFactory(applicationContext);
152 kernel.registerService(serviceName, springConfigurationServiceFactory);
153 return serviceName;
154 }
155
156 /**
157 * Returns the last Spring application context that was read via the call to {@link #load(String)}
158 */
159 public AbstractXmlApplicationContext getApplicationContext() {
160 return applicationContext;
161 }
162
163 /**
164 * A factory method for creating the application context
165 */
166 protected AbstractXmlApplicationContext createXmlApplicationContext(String configLocation) {
167 return new FileSystemXmlApplicationContext(
168 new String[] {configLocation},
169 false,
170 xmlPreprocessors);
171 }
172 }