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.ArrayList; 020 import java.util.Iterator; 021 import java.util.List; 022 import java.util.Map; 023 import java.util.Set; 024 import java.util.HashSet; 025 import java.util.Collections; 026 027 import org.apache.xbean.kernel.AbstractServiceFactory; 028 import org.apache.xbean.kernel.ServiceCondition; 029 import org.apache.xbean.kernel.ServiceConditionContext; 030 import org.apache.xbean.kernel.ServiceContext; 031 import org.apache.xbean.kernel.ServiceFactory; 032 import org.apache.xbean.kernel.ServiceName; 033 import org.springframework.context.support.AbstractXmlApplicationContext; 034 035 /** 036 * SpringConfigurationServiceFactory is manages the creation and destruction of a SpringConfiguration. 037 * 038 * @author Dain Sundstrom 039 * @version $Id$ 040 * @since 2.0 041 */ 042 public class SpringConfigurationServiceFactory extends AbstractServiceFactory { 043 private final AbstractXmlApplicationContext applicationContext; 044 private final ConfigurationStopCondition configurationStopCondition; 045 private SpringConfiguration springConfiguration; 046 047 /** 048 * Creates a SpringConfigurationServiceFactory that wraps the specified application context. 049 * @param applicationContext the application context for this configuration 050 */ 051 public SpringConfigurationServiceFactory(AbstractXmlApplicationContext applicationContext) { 052 this.applicationContext = applicationContext; 053 configurationStopCondition = new ConfigurationStopCondition(); 054 addStopCondition(configurationStopCondition); 055 } 056 057 /** 058 * Gets the unique id if this configuration. 059 * @return the unique id if this configuration 060 */ 061 public String getId() { 062 return applicationContext.getDisplayName(); 063 } 064 065 /** 066 * Gets the application context wrapped by this configuration. Use caution when modifiying this context as it can 067 * effect the running state of services. 068 * @return the application context wrapped by this configuration 069 */ 070 public AbstractXmlApplicationContext getApplicationContext() { 071 return applicationContext; 072 } 073 074 /** 075 * {@inheritDoc} 076 */ 077 public Class[] getTypes() { 078 return new Class[]{SpringConfiguration.class}; 079 } 080 081 /** 082 * SpringConfigurationServiceFactory is restartable so this method always returns true. 083 * @return true 084 */ 085 public boolean isRestartable() { 086 return false; 087 } 088 089 /** 090 * Gets the ServiceNames of the services defined in the application context if the configuration has been started, 091 * otherwise this method returns an empty set. 092 * 093 * @return the ServiceNames of the services defined in the application context if the configuration has been started 094 */ 095 public Set getOwnedServices() { 096 if (springConfiguration != null) { 097 return new HashSet(springConfiguration.getServiceFactories().keySet()); 098 } 099 return Collections.EMPTY_SET; 100 } 101 102 /** 103 * {@inheritDoc} 104 */ 105 public Object createService(ServiceContext serviceContext) throws Exception { 106 springConfiguration = new SpringConfiguration(applicationContext, serviceContext.getKernel()); 107 108 // add owned service stop conditions 109 Set ownedServices = springConfiguration.getServiceFactories().keySet(); 110 for (Iterator iterator = springConfiguration.getServiceFactories().entrySet().iterator(); iterator.hasNext();) { 111 Map.Entry entry = (Map.Entry) iterator.next(); 112 ServiceName serviceName = (ServiceName) entry.getKey(); 113 ServiceFactory serviceFactory = (ServiceFactory) entry.getValue(); 114 if (ownedServices.contains(serviceName)) { 115 serviceFactory.addStopCondition(configurationStopCondition.createOwnedServiceStopCondition()); 116 } 117 } 118 119 return springConfiguration; 120 } 121 122 /** 123 * {@inheritDoc} 124 */ 125 public void destroyService(ServiceContext serviceContext) { 126 if (springConfiguration != null) { 127 springConfiguration.destroy(); 128 springConfiguration = null; 129 } 130 applicationContext.close(); 131 } 132 133 /** 134 * {@inheritDoc} 135 */ 136 public ClassLoader getClassLoader() { 137 return SpringConfiguration.getClassLoader(applicationContext); 138 } 139 140 private static class ConfigurationStopCondition implements ServiceCondition { 141 private final List ownedServiceConditions = new ArrayList(); 142 143 public synchronized void initialize(ServiceConditionContext context) { 144 for (Iterator iterator = ownedServiceConditions.iterator(); iterator.hasNext();) { 145 OwnedServiceCondition ownedServiceCondition = (OwnedServiceCondition) iterator.next(); 146 ownedServiceCondition.setSatisfied(); 147 } 148 } 149 150 public boolean isSatisfied() { 151 return true; 152 } 153 154 public synchronized void destroy() { 155 for (Iterator iterator = ownedServiceConditions.iterator(); iterator.hasNext();) { 156 OwnedServiceCondition ownedServiceCondition = (OwnedServiceCondition) iterator.next(); 157 ownedServiceCondition.setSatisfied(); 158 } 159 } 160 161 public ServiceCondition createOwnedServiceStopCondition() { 162 ServiceCondition ownedServiceCondition = new OwnedServiceCondition(); 163 ownedServiceConditions.add(ownedServiceCondition); 164 return ownedServiceCondition; 165 } 166 167 private static class OwnedServiceCondition implements ServiceCondition { 168 private boolean satisfied = false; 169 private ServiceConditionContext context; 170 171 public synchronized void initialize(ServiceConditionContext context) { 172 this.context = context; 173 } 174 175 public synchronized boolean isSatisfied() { 176 return satisfied; 177 } 178 179 private void setSatisfied() { 180 this.satisfied = true; 181 if (context != null) { 182 context.setSatisfied(); 183 } 184 } 185 186 public synchronized void destroy() { 187 context = null; 188 } 189 } 190 } 191 }