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 }