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 }