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