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 }