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 }