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 }