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
018 package org.apache.geronimo.kernel.config;
019
020 import java.util.Collection;
021 import java.util.Collections;
022 import java.util.Iterator;
023 import java.util.LinkedHashSet;
024 import java.util.Map;
025 import java.util.Set;
026
027 import org.apache.geronimo.gbean.AbstractName;
028 import org.apache.geronimo.gbean.AbstractNameQuery;
029 import org.apache.geronimo.gbean.GBeanData;
030 import org.apache.geronimo.gbean.GBeanInfo;
031 import org.apache.geronimo.gbean.GBeanInfoBuilder;
032 import org.apache.geronimo.gbean.GBeanLifecycle;
033 import org.apache.geronimo.gbean.InvalidConfigurationException;
034 import org.apache.geronimo.kernel.GBeanAlreadyExistsException;
035 import org.apache.geronimo.kernel.GBeanNotFoundException;
036 import org.apache.geronimo.kernel.InternalKernelException;
037 import org.apache.geronimo.kernel.Kernel;
038 import org.apache.geronimo.kernel.management.State;
039 import org.apache.geronimo.kernel.repository.Artifact;
040 import org.apache.geronimo.kernel.repository.ArtifactManager;
041 import org.apache.geronimo.kernel.repository.ArtifactResolver;
042 import org.apache.geronimo.kernel.repository.DefaultArtifactResolver;
043
044 /**
045 * The standard non-editable ConfigurationManager implementation. That is,
046 * you can save a lost configurations and stuff, but not change the set of
047 * GBeans included in a configuration.
048 *
049 * @version $Rev:386276 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
050 * @see EditableConfigurationManager
051 */
052 public class KernelConfigurationManager extends SimpleConfigurationManager implements GBeanLifecycle {
053
054 protected final Kernel kernel;
055 protected final ManageableAttributeStore attributeStore;
056 protected final PersistentConfigurationList configurationList;
057 private final ArtifactManager artifactManager;
058 protected final ClassLoader classLoader;
059 private final ShutdownHook shutdownHook;
060 private boolean online = true;
061
062 public KernelConfigurationManager(Kernel kernel,
063 Collection stores,
064 ManageableAttributeStore attributeStore,
065 PersistentConfigurationList configurationList,
066 ArtifactManager artifactManager,
067 ArtifactResolver artifactResolver,
068 Collection repositories,
069 Collection watchers,
070 ClassLoader classLoader) {
071
072 super(stores,
073 createArtifactResolver(artifactResolver, artifactManager, repositories),
074 repositories, watchers);
075
076 this.kernel = kernel;
077 this.attributeStore = attributeStore;
078 this.configurationList = configurationList;
079 this.artifactManager = artifactManager;
080 this.classLoader = classLoader;
081
082 shutdownHook = new ShutdownHook(kernel, configurationModel);
083 }
084
085 private static ArtifactResolver createArtifactResolver(ArtifactResolver artifactResolver, ArtifactManager artifactManager, Collection repositories) {
086 if (artifactResolver != null) {
087 return artifactResolver;
088 }
089 return new DefaultArtifactResolver(artifactManager, repositories, null);
090 }
091
092 public synchronized LifecycleResults loadConfiguration(Artifact configurationId) throws NoSuchConfigException, LifecycleException {
093 // todo hack for bootstrap deploy
094 AbstractName abstractName = null;
095 try {
096 abstractName = Configuration.getConfigurationAbstractName(configurationId);
097 } catch (InvalidConfigException e) {
098 throw new RuntimeException(e);
099 }
100 if (getConfiguration(configurationId) == null && kernel.isLoaded(abstractName)) {
101 try {
102 Configuration configuration = (Configuration) kernel.getGBean(abstractName);
103 addNewConfigurationToModel(configuration);
104 configurationModel.load(configurationId);
105 configurationModel.start(configurationId);
106 return new LifecycleResults();
107 } catch (GBeanNotFoundException e) {
108 // configuration was unloaded, just continue as normal
109 }
110 }
111
112 return super.loadConfiguration(configurationId);
113 }
114
115 protected void load(Artifact configurationId) throws NoSuchConfigException {
116 super.load(configurationId);
117 if (configurationList != null) {
118 configurationList.addConfiguration(configurationId);
119 }
120 }
121
122 protected void migrateConfiguration(Artifact oldName, Artifact newName, Configuration configuration, boolean running) throws NoSuchConfigException {
123 super.migrateConfiguration(oldName, newName, configuration, running);
124 if (configurationList != null) {
125 configurationList.migrateConfiguration(oldName, newName, configuration);
126 if(running) {
127 configurationList.startConfiguration(newName);
128 }
129 }
130 }
131
132 protected Configuration load(ConfigurationData configurationData, LinkedHashSet resolvedParentIds, Map loadedConfigurations) throws InvalidConfigException {
133 Artifact configurationId = configurationData.getId();
134 AbstractName configurationName = Configuration.getConfigurationAbstractName(configurationId);
135 GBeanData gbeanData = new GBeanData(configurationName, Configuration.GBEAN_INFO);
136 gbeanData.setAttribute("configurationData", configurationData);
137 gbeanData.setAttribute("configurationResolver", new ConfigurationResolver(configurationData, repositories, getArtifactResolver()));
138 //TODO is this dangerous?
139 gbeanData.setAttribute("managedAttributeStore", attributeStore);
140
141 // add parents to the parents reference collection
142 LinkedHashSet parentNames = new LinkedHashSet();
143 for (Iterator iterator = resolvedParentIds.iterator(); iterator.hasNext();) {
144 Artifact resolvedParentId = (Artifact) iterator.next();
145 AbstractName parentName = Configuration.getConfigurationAbstractName(resolvedParentId);
146 parentNames.add(parentName);
147 }
148 gbeanData.addDependencies(parentNames);
149 gbeanData.setReferencePatterns("Parents", parentNames);
150
151 // load the configuration
152 try {
153 kernel.loadGBean(gbeanData, classLoader);
154 } catch (GBeanAlreadyExistsException e) {
155 throw new InvalidConfigException("Unable to load configuration gbean " + configurationId, e);
156 }
157
158 // start the configuration and assure it started
159 Configuration configuration;
160 try {
161 kernel.startGBean(configurationName);
162 if (State.RUNNING_INDEX != kernel.getGBeanState(configurationName)) {
163 String stateReason = kernel.getStateReason(configurationName);
164 throw new InvalidConfigurationException("Configuration gbean failed to start " + configurationId + "\nreason: " + stateReason);
165 }
166
167 // get the configuration
168 configuration = (Configuration) kernel.getGBean(configurationName);
169
170 // declare the dependencies as loaded
171 if (artifactManager != null) {
172 artifactManager.loadArtifacts(configurationId, configuration.getDependencies());
173 }
174
175 log.debug("Loaded Configuration " + configurationName);
176 } catch (Exception e) {
177 unload(configurationId);
178 if (e instanceof InvalidConfigException) {
179 throw (InvalidConfigException) e;
180 }
181 throw new InvalidConfigException("Error starting configuration gbean " + configurationId, e);
182 }
183 return configuration;
184 }
185
186 public void start(Configuration configuration) throws InvalidConfigException {
187 if (online) {
188 ConfigurationUtil.startConfigurationGBeans(configuration.getAbstractName(), configuration, kernel);
189 }
190
191 if (configurationList != null && configuration.getConfigurationData().isAutoStart()) {
192 configurationList.startConfiguration(configuration.getId());
193 }
194 }
195
196 public boolean isOnline() {
197 return online;
198 }
199
200 public void setOnline(boolean online) {
201 this.online = online;
202 }
203
204 protected void stop(Configuration configuration) {
205 stopRecursive(configuration);
206 if (configurationList != null) {
207 configurationList.stopConfiguration(configuration.getId());
208 }
209 }
210
211 private void stopRecursive(Configuration configuration) {
212 // stop all of the child configurations first
213 for (Iterator iterator = configuration.getChildren().iterator(); iterator.hasNext();) {
214 Configuration childConfiguration = (Configuration) iterator.next();
215 stopRecursive(childConfiguration);
216 }
217
218 Collection gbeans = configuration.getGBeans().values();
219
220 // stop the gbeans
221 for (Iterator iterator = gbeans.iterator(); iterator.hasNext();) {
222 GBeanData gbeanData = (GBeanData) iterator.next();
223 AbstractName gbeanName = gbeanData.getAbstractName();
224 try {
225 kernel.stopGBean(gbeanName);
226 } catch (GBeanNotFoundException ignored) {
227 } catch (IllegalStateException ignored) {
228 } catch (InternalKernelException kernelException) {
229 log.debug("Error cleaning up after failed start of configuration " + configuration.getId() + " gbean " + gbeanName, kernelException);
230 }
231 }
232
233 // unload the gbeans
234 for (Iterator iterator = gbeans.iterator(); iterator.hasNext();) {
235 GBeanData gbeanData = (GBeanData) iterator.next();
236 AbstractName gbeanName = gbeanData.getAbstractName();
237 try {
238 kernel.unloadGBean(gbeanName);
239 } catch (GBeanNotFoundException ignored) {
240 } catch (IllegalStateException ignored) {
241 } catch (InternalKernelException kernelException) {
242 log.debug("Error cleaning up after failed start of configuration " + configuration.getId() + " gbean " + gbeanName, kernelException);
243 }
244 }
245 }
246
247 protected void unload(Configuration configuration) {
248 Artifact configurationId = configuration.getId();
249 unload(configurationId);
250 }
251
252 private void unload(Artifact configurationId) {
253 AbstractName configurationName;
254 try {
255 configurationName = Configuration.getConfigurationAbstractName(configurationId);
256 } catch (InvalidConfigException e) {
257 throw new AssertionError(e);
258 }
259
260 if (artifactManager != null) {
261 artifactManager.unloadAllArtifacts(configurationId);
262 }
263
264 // unload this configuration
265 try {
266 kernel.stopGBean(configurationName);
267 } catch (GBeanNotFoundException ignored) {
268 // Good
269 } catch (Exception stopException) {
270 log.warn("Unable to stop failed configuration: " + configurationId, stopException);
271 }
272
273 try {
274 kernel.unloadGBean(configurationName);
275 } catch (GBeanNotFoundException ignored) {
276 // Good
277 } catch (Exception unloadException) {
278 log.warn("Unable to unload failed configuration: " + configurationId, unloadException);
279 }
280 }
281
282 protected void uninstall(Artifact configurationId) {
283 if (configurationList != null) {
284 configurationList.removeConfiguration( configurationId );
285 }
286 }
287
288 public void doStart() {
289 kernel.registerShutdownHook(shutdownHook);
290 }
291
292 public void doStop() {
293 kernel.unregisterShutdownHook(shutdownHook);
294 }
295
296 public void doFail() {
297 log.error("Cofiguration manager failed");
298 }
299
300 private static class ShutdownHook implements Runnable {
301 private final Kernel kernel;
302 private final ConfigurationModel configurationModel;
303
304 public ShutdownHook(Kernel kernel, ConfigurationModel configurationModel) {
305 this.kernel = kernel;
306 this.configurationModel = configurationModel;
307 }
308
309 public void run() {
310 while (true) {
311 Set configs = kernel.listGBeans(new AbstractNameQuery(Configuration.class.getName()));
312 if (configs.isEmpty()) {
313 return;
314 }
315 LinkedHashSet orderedConfigs = new LinkedHashSet();
316 for (Iterator i = configs.iterator(); i.hasNext();) {
317 AbstractName configName = (AbstractName) i.next();
318 if (kernel.isLoaded(configName) && !orderedConfigs.contains(configName)) {
319 LinkedHashSet startedChildren = configurationModel.getStartedChildren(configName.getArtifact());
320 for (Iterator iterator = startedChildren.iterator(); iterator.hasNext();) {
321 Artifact configurationId = (Artifact) iterator.next();
322 Set childConfig = kernel.listGBeans(new AbstractNameQuery(configurationId, Collections.emptyMap() , Configuration.class.getName()));
323 if (!childConfig.isEmpty()) {
324 AbstractName childConfigName = (AbstractName) childConfig.iterator().next();
325 if (!orderedConfigs.contains(childConfigName))
326 orderedConfigs.add(childConfigName);
327 }
328 }
329 orderedConfigs.add(configName);
330 }
331 }
332
333 for (Iterator i = orderedConfigs.iterator(); i.hasNext();) {
334 AbstractName configName = (AbstractName) i.next();
335 try {
336 kernel.stopGBean(configName);
337 } catch (GBeanNotFoundException e) {
338 // ignore
339 } catch (InternalKernelException e) {
340 log.warn("Could not stop configuration: " + configName, e);
341 }
342 try {
343 kernel.unloadGBean(configName);
344 } catch (GBeanNotFoundException e) {
345 // ignore
346 }
347 }
348 }
349 }
350 }
351
352 public static final GBeanInfo GBEAN_INFO;
353
354 static {
355 GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(KernelConfigurationManager.class, SimpleConfigurationManager.GBEAN_INFO, "ConfigurationManager");
356 infoFactory.addAttribute("kernel", Kernel.class, false);
357 infoFactory.addReference("AttributeStore", ManageableAttributeStore.class, ManageableAttributeStore.ATTRIBUTE_STORE);
358 infoFactory.addReference("PersistentConfigurationList", PersistentConfigurationList.class, PersistentConfigurationList.PERSISTENT_CONFIGURATION_LIST);
359 infoFactory.addReference("ArtifactManager", ArtifactManager.class, "ArtifactManager");
360 infoFactory.addAttribute("classLoader", ClassLoader.class, false);
361 infoFactory.addInterface(ConfigurationManager.class);
362 infoFactory.setConstructor(new String[]{"kernel", "Stores", "AttributeStore", "PersistentConfigurationList", "ArtifactManager", "ArtifactResolver", "Repositories", "Watchers", "classLoader"});
363 GBEAN_INFO = infoFactory.getBeanInfo();
364 }
365
366 public static GBeanInfo getGBeanInfo() {
367 return GBEAN_INFO;
368 }
369 }