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.configuration;
018
019 import java.util.Collections;
020 import java.util.HashMap;
021 import java.util.Iterator;
022 import java.util.Map;
023
024 import org.apache.xbean.kernel.Kernel;
025 import org.apache.xbean.kernel.ServiceAlreadyExistsException;
026 import org.apache.xbean.kernel.ServiceName;
027 import org.apache.xbean.kernel.ServiceNotFoundException;
028 import org.apache.xbean.kernel.ServiceRegistrationException;
029 import org.apache.xbean.kernel.StaticServiceFactory;
030 import org.apache.xbean.kernel.StringServiceName;
031 import org.apache.xbean.server.spring.loader.SpringLoader;
032 import org.springframework.beans.factory.config.BeanDefinition;
033 import org.springframework.beans.factory.support.BeanDefinitionRegistry;
034 import org.springframework.context.support.AbstractXmlApplicationContext;
035
036 /**
037 * SpringConfiguration that registers and unregisters services that have been defined in a Spring ApplicationContext.
038 *
039 * @author Dain Sundstrom
040 * @version $Id$
041 * @since 2.0
042 */
043 public class SpringConfiguration {
044 private final AbstractXmlApplicationContext applicationContext;
045 private final Map serviceFactories;
046 private final Kernel kernel;
047
048 /**
049 * Creates a SpringConfiguration that registers and unregisters services that have been defined in a Spring ApplicationContext.
050 * @param applicationContext the application context from which services are registered
051 * @param kernel the kernel in which services are registered and unregistered
052 * @throws Exception if a problem occurs while registering the services from the application context
053 */
054 public SpringConfiguration(AbstractXmlApplicationContext applicationContext, Kernel kernel) throws Exception {
055 this.applicationContext = applicationContext;
056 this.kernel = kernel;
057
058 ClassLoader classLoader = getClassLoader(applicationContext);
059 ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
060 Thread.currentThread().setContextClassLoader(classLoader);
061
062 // read the configuration file from source
063 applicationContext.refresh();
064
065 // If the class loader was modified by an xml preprocessor,
066 // make sure we have the right one
067 classLoader = getClassLoader(applicationContext);
068
069 try {
070
071 // build a map from bean name to service name
072 Map serviceNameIndex = buildServiceNameIndex(applicationContext);
073
074 // Use Spring to create all of the beans
075 Map factories = new HashMap(serviceNameIndex.size());
076 for (Iterator iterator = serviceNameIndex.entrySet().iterator(); iterator.hasNext();) {
077 Map.Entry entry = (Map.Entry) iterator.next();
078 String beanName = (String) entry.getKey();
079 ServiceName serviceName = (ServiceName) entry.getValue();
080
081 Object bean = applicationContext.getBean(beanName);
082 StaticServiceFactory serviceFactory = new StaticServiceFactory(bean, classLoader);
083 factories.put(serviceName, serviceFactory);
084 }
085 serviceFactories = Collections.unmodifiableMap(factories);
086
087 // register each bean with the kernel
088 for (Iterator iterator = serviceFactories.entrySet().iterator(); iterator.hasNext();) {
089 Map.Entry entry = (Map.Entry) iterator.next();
090 ServiceName serviceName = (ServiceName) entry.getKey();
091 StaticServiceFactory serviceFactory = (StaticServiceFactory) entry.getValue();
092 kernel.registerService(serviceName, serviceFactory);
093 }
094
095 } catch (ServiceAlreadyExistsException e) {
096 destroy();
097 throw e;
098 } catch (ServiceRegistrationException e) {
099 destroy();
100 throw e;
101 } finally {
102 Thread.currentThread().setContextClassLoader(oldClassLoader);
103 }
104 }
105
106 /**
107 * Gets the unique identifier of this configuration.
108 * @return the unique identifier of this configuration
109 */
110 public String getId() {
111 return applicationContext.getDisplayName();
112 }
113
114 /**
115 * Gets the service factories for the services defined in this configuration by ServiceName.
116 * @return the service factories for the services defined in this configuration by ServiceName
117 */
118 public Map getServiceFactories() {
119 return serviceFactories;
120 }
121
122 /**
123 * Unregisters all of the services registered with the kernel in the constructor.
124 */
125 public void destroy() {
126 ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
127 Thread.currentThread().setContextClassLoader(getClassLoader(applicationContext));
128 try {
129 for (Iterator iterator = serviceFactories.keySet().iterator(); iterator.hasNext();) {
130 ServiceName serviceName = (ServiceName) iterator.next();
131 try {
132 kernel.unregisterService(serviceName);
133 } catch (ServiceNotFoundException e) {
134 // Doesn't matter
135 } catch (ServiceRegistrationException e) {
136 // todo ignored...
137 }
138 }
139
140 applicationContext.close();
141 } finally {
142 Thread.currentThread().setContextClassLoader(oldClassLoader);
143 }
144 }
145
146 private static Map buildServiceNameIndex(AbstractXmlApplicationContext applicationContext) {
147 BeanDefinitionRegistry registry = null;
148 if (applicationContext instanceof BeanDefinitionRegistry) {
149 registry = (BeanDefinitionRegistry) applicationContext;
150 } else if (applicationContext.getBeanFactory() instanceof BeanDefinitionRegistry) {
151 registry = (BeanDefinitionRegistry) applicationContext.getBeanFactory();
152 }
153 if (registry != null) {
154 String[] beanNames = registry.getBeanDefinitionNames();
155 Map serviceNameIndex = new HashMap(beanNames.length);
156 for (int i = 0; i < beanNames.length; i++) {
157 String beanName = beanNames[i];
158 BeanDefinition def = registry.getBeanDefinition(beanName);
159 if (!def.isAbstract()) {
160 ServiceName serviceName = new StringServiceName(beanName);
161 serviceNameIndex.put(beanName, serviceName);
162 }
163 }
164 return serviceNameIndex;
165 } else {
166 String[] beanNames = applicationContext.getBeanDefinitionNames();
167 Map serviceNameIndex = new HashMap(beanNames.length);
168 for (int i = 0; i < beanNames.length; i++) {
169 String beanName = beanNames[i];
170 ServiceName serviceName = new StringServiceName(beanName);
171 serviceNameIndex.put(beanName, serviceName);
172 }
173 return serviceNameIndex;
174 }
175 }
176
177 protected static ClassLoader getClassLoader(AbstractXmlApplicationContext applicationContext) {
178 ClassLoader classLoader = applicationContext.getClassLoader();
179 if (classLoader == null) {
180 classLoader = Thread.currentThread().getContextClassLoader();
181 }
182 if (classLoader == null) {
183 classLoader = SpringLoader.class.getClassLoader();
184 }
185 return classLoader;
186 }
187 }