/** * * Copyright 2003-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.geronimo.kernel.config; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.geronimo.gbean.GBeanInfo; import org.apache.geronimo.gbean.GBeanInfoBuilder; import org.apache.geronimo.gbean.GBeanLifecycle; import org.apache.geronimo.kernel.GBeanNotFoundException; import org.apache.geronimo.kernel.InternalKernelException; import org.apache.geronimo.kernel.Kernel; import org.apache.geronimo.kernel.jmx.JMXUtil; import org.apache.geronimo.kernel.management.State; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import java.io.IOException; import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Set; /** * The standard non-editable ConfigurationManager implementation. That is, * you can save a lost configurations and stuff, but not change the set of * GBeans included in a configuration. * * @see EditableConfigurationManager * * @version $Rev$ $Date$ */ public class ConfigurationManagerImpl implements ConfigurationManager, GBeanLifecycle { private static final Log log = LogFactory.getLog(ConfigurationManagerImpl.class); protected final Kernel kernel; private final Collection stores; protected final ManageableAttributeStore attributeStore; protected final PersistentConfigurationList configurationList; private final ShutdownHook shutdownHook; private static final ObjectName CONFIGURATION_NAME_QUERY; static { try { CONFIGURATION_NAME_QUERY = new ObjectName("geronimo.config:*"); } catch (MalformedObjectNameException e) { throw new RuntimeException("could not create object name... bug", e); } } public ConfigurationManagerImpl(Kernel kernel, Collection stores, ManageableAttributeStore attributeStore, PersistentConfigurationList configurationList) { this.kernel = kernel; this.stores = stores; this.attributeStore = attributeStore; this.configurationList = configurationList; shutdownHook = new ShutdownHook(kernel); } public List listStores() { List storeSnapshot = getStores(); List result = new ArrayList(storeSnapshot.size()); for (int i = 0; i < storeSnapshot.size(); i++) { ConfigurationStore store = (ConfigurationStore) storeSnapshot.get(i); result.add(JMXUtil.getObjectName(store.getObjectName())); } return result; } public List listConfigurations(ObjectName storeName) throws NoSuchStoreException { List storeSnapshot = getStores(); for (int i = 0; i < storeSnapshot.size(); i++) { ConfigurationStore store = (ConfigurationStore) storeSnapshot.get(i); if (storeName.equals(JMXUtil.getObjectName(store.getObjectName()))) { return store.listConfigurations(); } } throw new NoSuchStoreException("No such store: " + storeName); } public boolean isLoaded(URI configID) { try { ObjectName name = Configuration.getConfigurationObjectName(configID); return kernel.isLoaded(name); } catch (MalformedObjectNameException e) { return false; } } public ObjectName load(URI configID) throws NoSuchConfigException, IOException, InvalidConfigException { List storeSnapshot = getStores(); for (int i = 0; i < storeSnapshot.size(); i++) { ConfigurationStore store = (ConfigurationStore) storeSnapshot.get(i); if (store.containsConfiguration(configID)) { ObjectName configName = store.loadConfiguration(configID); return configName; } } throw new NoSuchConfigException("No configuration with id: " + configID); } public void loadGBeans(URI configID) throws InvalidConfigException { ObjectName configName; try { configName = Configuration.getConfigurationObjectName(configID); } catch (MalformedObjectNameException e) { throw new InvalidConfigException("Cannot convert ID to ObjectName: ", e); } try { kernel.startGBean(configName); kernel.invoke(configName, "loadGBeans", new Object[] {attributeStore}, new String[] {ManageableAttributeStore.class.getName()}); } catch (Exception e) { throw new InvalidConfigException("Could not extract gbean data from configuration", e); } } public void start(URI configID) throws InvalidConfigException { ObjectName configName; try { configName = Configuration.getConfigurationObjectName(configID); } catch (MalformedObjectNameException e) { throw new InvalidConfigException("Cannot convert ID to ObjectName: ", e); } try { kernel.invoke(configName, "startRecursiveGBeans"); } catch (Exception e) { throw new InvalidConfigException("Could not start gbeans in configuration", e); } if (configurationList != null) { configurationList.addConfiguration(configID.toString()); } } public void stop(URI configID) throws InvalidConfigException { ObjectName configName; try { configName = Configuration.getConfigurationObjectName(configID); } catch (MalformedObjectNameException e) { throw new InvalidConfigException("Cannot convert ID to ObjectName: ", e); } try { kernel.invoke(configName, "stopGBeans"); } catch (Exception e) { throw new InvalidConfigException("Could not stop gbeans in configuration", e); } if (configurationList != null) { configurationList.removeConfiguration(configID.toString()); } } public List loadRecursive(URI configID) throws NoSuchConfigException, IOException, InvalidConfigException { LinkedList ancestors = new LinkedList(); Set preloaded = kernel.listGBeans(CONFIGURATION_NAME_QUERY); for (Iterator it = preloaded.iterator(); it.hasNext();) { ObjectName name = (ObjectName) it.next(); try { if(kernel.getGBeanState(name) != State.RUNNING_INDEX) { it.remove(); } } catch (GBeanNotFoundException e) { it.remove(); } } loadRecursive(configID, ancestors, preloaded); return ancestors; } private void loadRecursive(URI configID, LinkedList ancestors, Set preloaded) throws NoSuchConfigException, IOException, InvalidConfigException { try { ObjectName name = Configuration.getConfigurationObjectName(configID); if (preloaded.contains(name)) { return; } if (!isLoaded(configID)) { load(configID); } //put the earliest ancestors first, even if we have already started them. ancestors.remove(configID); ancestors.addFirst(configID); URI[] parents = (URI[]) kernel.getAttribute(name, "parentId"); if (parents != null) { for (int i = 0; i < parents.length; i++) { URI parent = parents[i]; loadRecursive(parent, ancestors, preloaded); } } } catch (NoSuchConfigException e) { throw e; } catch (IOException e) { throw e; } catch (InvalidConfigException e) { throw e; } catch (Exception e) { throw new InvalidConfigException(e); } } public void unload(URI configID) throws NoSuchConfigException { ObjectName configName; try { configName = Configuration.getConfigurationObjectName(configID); } catch (MalformedObjectNameException e) { throw new NoSuchConfigException("Cannot convert ID to ObjectName: ", e); } try { if (State.RUNNING_INDEX == kernel.getGBeanState(configName)) { kernel.invoke(configName, "unloadGBeans"); kernel.stopGBean(configName); } kernel.unloadGBean(configName); } catch (GBeanNotFoundException e) { throw new NoSuchConfigException("No config registered: " + configName, e); } catch (Exception e) { throw new NoSuchConfigException("Problem unloading config: " + configName, e); } } private List getStores() { return new ArrayList(stores); } public void doStart() { kernel.registerShutdownHook(shutdownHook); } private static final ObjectName CONFIG_QUERY = JMXUtil.getObjectName("geronimo.config:*"); public void doStop() { kernel.unregisterShutdownHook(shutdownHook); } public void doFail() { log.error("Cofiguration manager failed"); } public static final GBeanInfo GBEAN_INFO; static { GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(ConfigurationManagerImpl.class, "ConfigurationManager"); infoFactory.addAttribute("kernel", Kernel.class, false); infoFactory.addReference("Stores", ConfigurationStore.class, "ConfigurationStore"); infoFactory.addReference("AttributeStore", ManageableAttributeStore.class, ManageableAttributeStore.ATTRIBUTE_STORE); infoFactory.addReference("PersistentConfigurationList", PersistentConfigurationList.class, PersistentConfigurationList.PERSISTENT_CONFIGURATION_LIST); infoFactory.addInterface(ConfigurationManager.class); infoFactory.setConstructor(new String[]{"kernel", "Stores", "AttributeStore", "PersistentConfigurationList"}); GBEAN_INFO = infoFactory.getBeanInfo(); } public static GBeanInfo getGBeanInfo() { return GBEAN_INFO; } private static class ShutdownHook implements Runnable { private final Kernel kernel; public ShutdownHook(Kernel kernel) { this.kernel = kernel; } public void run() { while (true) { Set configs = kernel.listGBeans(CONFIG_QUERY); if (configs.isEmpty()) { return; } for (Iterator i = configs.iterator(); i.hasNext();) { ObjectName configName = (ObjectName) i.next(); if (kernel.isLoaded(configName)) { try { kernel.stopGBean(configName); } catch (GBeanNotFoundException e) { // ignore } catch (InternalKernelException e) { log.warn("Could not stop configuration: " + configName, e); } try { kernel.unloadGBean(configName); } catch (GBeanNotFoundException e) { // ignore } } } } } } }