Package org.apache.geronimo.kernel.config

Source Code of org.apache.geronimo.kernel.config.SimpleConfigurationManager

/**
*  Licensed to the Apache Software Foundation (ASF) under one or more
*  contributor license agreements.  See the NOTICE file distributed with
*  this work for additional information regarding copyright ownership.
*  The ASF licenses this file to You 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 java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;

import org.apache.geronimo.gbean.AbstractName;
import org.apache.geronimo.gbean.GBeanData;
import org.apache.geronimo.gbean.annotation.GBean;
import org.apache.geronimo.gbean.annotation.ParamReference;
import org.apache.geronimo.gbean.annotation.ParamSpecial;
import org.apache.geronimo.gbean.annotation.SpecialAttributeType;
import org.apache.geronimo.kernel.management.State;
import org.apache.xbean.osgi.bundle.util.BundleUtils;
import org.apache.geronimo.kernel.repository.Artifact;
import org.apache.geronimo.kernel.repository.ArtifactResolver;
import org.apache.geronimo.kernel.repository.Dependency;
import org.apache.geronimo.kernel.repository.Environment;
import org.apache.geronimo.kernel.repository.MissingDependencyException;
import org.apache.geronimo.kernel.repository.Repository;
import org.apache.geronimo.kernel.repository.Version;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* @version $Rev: 938294 $ $Date: 2010-04-26 22:05:48 -0400 (Mon, 26 Apr 2010) $
*/
@GBean(j2eeType = "ConfigurationManager")
public class SimpleConfigurationManager implements ConfigurationManager {
    protected static final Logger log = LoggerFactory.getLogger(SimpleConfigurationManager.class);
    protected final Collection<ConfigurationStore> stores;
    private final ArtifactResolver artifactResolver;
    protected final Map<Artifact, Configuration> configurations = new LinkedHashMap<Artifact, Configuration>();
    protected final Map<Artifact, Bundle> bundles = new LinkedHashMap<Artifact, Bundle>();
    protected final ConfigurationModel configurationModel;
    protected final Collection<? extends Repository> repositories;
    protected final Collection<DeploymentWatcher> watchers;
    protected final BundleContext bundleContext;

    //TODO need thread local of loaded configurations OSGI GROSS!!
    private final ThreadLocal<Map<Artifact, Configuration>> loadedConfigurations = new ThreadLocal<Map<Artifact, Configuration>>() {
    };

    /**
     * When this is not null, it points to the "new" configuration that is
     * part of an in-process reload operation.  This configuration will
     * definitely be loaded, but might not be started yet.  It shold never be
     * populated outside the scope of a reload operation.
     */
    private Configuration reloadingConfiguration;


    public SimpleConfigurationManager(Collection<ConfigurationStore> stores, ArtifactResolver artifactResolver, Collection<? extends Repository> repositories, BundleContext bundleContext) {
        this(stores, artifactResolver, repositories, Collections.<DeploymentWatcher>emptySet(), bundleContext);
    }

    public SimpleConfigurationManager(@ParamReference(name = "Stores", namingType = "ConfigurationStore") Collection<ConfigurationStore> stores,
                                      @ParamReference(name = "ArtifactResolver", namingType = "ArtifactResolver") ArtifactResolver artifactResolver,
                                      @ParamReference(name = "Repositories", namingType = "Repository") Collection<? extends Repository> repositories,
                                      @ParamReference(name = "Watchers") Collection<DeploymentWatcher> watchers,
                                      @ParamSpecial(type = SpecialAttributeType.bundleContext) BundleContext bundleContext) {
        this(stores, artifactResolver, repositories, watchers, bundleContext, new ConfigurationModel());
    }

    public SimpleConfigurationManager(Collection<ConfigurationStore> stores, ArtifactResolver artifactResolver, Collection<? extends Repository> repositories, Collection<DeploymentWatcher> watchers, BundleContext bundleContext, ConfigurationModel configurationModel) {
        if (stores == null) stores = Collections.emptySet();
        if (repositories == null) repositories = Collections.emptySet();
        for (Repository repo : repositories) {
            if (repo == null) throw new NullPointerException("null repository");
        }
        if (watchers == null) watchers = Collections.emptySet();
        for (DeploymentWatcher watcher : watchers) {
            if (watcher == null) throw new NullPointerException("null DeploymentWatcher");
        }
        this.configurationModel = configurationModel;
        this.stores = stores;
        this.artifactResolver = artifactResolver;
        this.repositories = repositories;
        this.watchers = watchers;
        this.bundleContext = bundleContext;
    }

    public ConfigurationModel getConfigurationModel() {
        return configurationModel;
    }

    public synchronized boolean isInstalled(Artifact configId) {
        if (!configId.isResolved()) {
            throw new IllegalArgumentException("Artifact " + configId + " is not fully resolved");
        }
        for (ConfigurationStore store : getStoreList()) {
            if (store.containsConfiguration(configId)) {
                return true;
            }
        }
        return false;
    }

    public synchronized boolean isLoaded(Artifact configId) {
        if (!configId.isResolved()) {
            throw new IllegalArgumentException("Artifact " + configId + " is not fully resolved");
        }
        if (reloadingConfiguration != null && reloadingConfiguration.getId().equals(configId)) {
            return true;
        }
        return configurationModel.isLoaded(configId);
    }

    public synchronized boolean isRunning(Artifact configId) {
        if (!configId.isResolved()) {
            throw new IllegalArgumentException("Artifact " + configId + " is not fully resolved");
        }
        return configurationModel.isStarted(configId);
    }

    public Artifact[] getInstalled(Artifact query) {
        Artifact[] all = artifactResolver.queryArtifacts(query);
        List<Artifact> configs = new ArrayList<Artifact>();
        for (Artifact artifact : all) {
            if (isConfiguration(artifact)) {
                configs.add(artifact);
            }
        }
        if (configs.size() == all.length) {
            return all;
        }
        return configs.toArray(new Artifact[configs.size()]);
    }

    public Artifact[] getLoaded(Artifact query) {
        return configurationModel.getLoaded(query);
    }

    public Artifact[] getRunning(Artifact query) {
        return configurationModel.getStarted(query);
    }


    public List<AbstractName> listStores() {
        List<ConfigurationStore> storeSnapshot = getStoreList();
        List<AbstractName> result = new ArrayList<AbstractName>(storeSnapshot.size());
        for (ConfigurationStore store : storeSnapshot) {
            result.add(store.getAbstractName());
        }
        return result;
    }

    public ConfigurationStore[] getStores() {
        List<ConfigurationStore> storeSnapshot = getStoreList();
        return storeSnapshot.toArray(new ConfigurationStore[storeSnapshot.size()]);
    }

    public Collection<? extends Repository> getRepositories() {
        return repositories;
    }

    public List listConfigurations() {
        List<ConfigurationStore> storeSnapshot = getStoreList();
        List<ConfigurationInfo> list = new ArrayList<ConfigurationInfo>();
        for (ConfigurationStore store : storeSnapshot) {
            list.addAll(listConfigurations(store));
        }
        return list;
    }

    public ConfigurationStore getStoreForConfiguration(Artifact configId) {
        if (!configId.isResolved()) {
            throw new IllegalArgumentException("Artifact " + configId + " is not fully resolved");
        }
        List<ConfigurationStore> storeSnapshot = getStoreList();
        for (ConfigurationStore store : storeSnapshot) {
            if (store.containsConfiguration(configId)) {
                return store;
            }
        }
        return null;
    }

    public List<ConfigurationInfo> listConfigurations(AbstractName storeName) throws NoSuchStoreException {
        for (ConfigurationStore store : getStoreList()) {
            if (storeName.equals(store.getAbstractName())) {
                return listConfigurations(store);
            }
        }
        throw new NoSuchStoreException("No such store: " + storeName);
    }

    private List<ConfigurationInfo> listConfigurations(ConfigurationStore store) {
        List<ConfigurationInfo> list = store.listConfigurations();
        for (ListIterator<ConfigurationInfo> iterator = list.listIterator(); iterator.hasNext();) {
            ConfigurationInfo configurationInfo = iterator.next();
            if (isRunning(configurationInfo.getConfigID())) {
                configurationInfo = new ConfigurationInfo(store.getAbstractName(),
                        configurationInfo.getConfigID(),
                        configurationInfo.getType(),
                        configurationInfo.getCreated(),
                        configurationInfo.getOwnedConfigurations(),
                        configurationInfo.getChildConfigurations(),
                        configurationInfo.getInPlaceLocation(),
                        State.RUNNING);
            } else {
                configurationInfo = new ConfigurationInfo(store.getAbstractName(),
                        configurationInfo.getConfigID(),
                        configurationInfo.getType(),
                        configurationInfo.getCreated(),
                        configurationInfo.getOwnedConfigurations(),
                        configurationInfo.getChildConfigurations(),
                        configurationInfo.getInPlaceLocation(),
                        State.STOPPED);
            }
            iterator.set(configurationInfo);
        }
        return list;
    }

    public boolean isConfiguration(Artifact artifact) {
        if (!artifact.isResolved()) {
            throw new IllegalArgumentException("Artifact " + artifact + " is not fully resolved");
        }
        synchronized (this) {
            // if it is loaded, it is definitely a configuration
            if (configurations.containsKey(artifact)) {
                return true;
            }
        }

        // see if any stores think it is a configuration
        for (ConfigurationStore store : getStoreList()) {
            if (store.containsConfiguration(artifact)) {
                return true;
            }
        }
        return false;
    }

    public synchronized Configuration getConfiguration(Artifact configurationId) {
        if (!configurationId.isResolved()) {
            throw new IllegalArgumentException("Artifact " + configurationId + " is not fully resolved");
        }
        if (reloadingConfiguration != null && reloadingConfiguration.getId().equals(configurationId)) {
            return reloadingConfiguration;
        }
        return configurations.get(configurationId);
    }

    public Bundle getBundle(Artifact id) {
        if (!id.isResolved()) {
            throw new IllegalArgumentException("Artifact " + id + " is not fully resolved");
        }
        return bundles.get(id);
    }

    public synchronized LifecycleResults loadConfiguration(Artifact configurationId) throws NoSuchConfigException, LifecycleException {
        return loadConfiguration(configurationId, NullLifecycleMonitor.INSTANCE);
    }

    public synchronized LifecycleResults loadConfiguration(Artifact configurationId, LifecycleMonitor monitor) throws NoSuchConfigException, LifecycleException {
        if (!configurationId.isResolved()) {
            throw new IllegalArgumentException("Artifact " + configurationId + " is not fully resolved");
        }
        if (isLoaded(configurationId)) {
            // already loaded, so just mark the configuration as user loaded
            load(configurationId);

            monitor.finished();
            return new LifecycleResults();
        }


        // load the ConfigurationData for the new configuration
        try {
            String location = locateBundle(configurationId, monitor);
            Bundle bundle = bundleContext.installBundle(location);
            if (BundleUtils.canStart(bundle)) {
                bundle.start(Bundle.START_TRANSIENT);
            }
            bundles.put(configurationId, bundle);
        } catch (Exception e) {
            monitor.finished();
            throw new LifecycleException("load", configurationId, e);
        }

        // load the configuration
//        LifecycleResults results = loadConfiguration(configurationData, monitor);
        LifecycleResults results = new LifecycleResults();
        if (!configurations.containsKey(configurationId)) {
            configurationModel.addConfiguration(configurationId,
                    Collections.<Artifact>emptySet(),
                    Collections.<Artifact>emptySet());
//            configurations.put(configurationId, configuration);

//            throw new NoSuchConfigException(configurationId, "not loaded");
        }
//        addNewConfigurationToModel(configurations.get(configurationId));
        load(configurationId);
        return results;
    }

    public synchronized LifecycleResults loadConfiguration(ConfigurationData configurationData) throws NoSuchConfigException, LifecycleException {
        return loadConfiguration(configurationData, NullLifecycleMonitor.INSTANCE);
    }

    public synchronized LifecycleResults loadConfiguration(ConfigurationData configurationData, LifecycleMonitor monitor) throws NoSuchConfigException, LifecycleException {
        Artifact id = configurationData.getId();
        LifecycleResults results = new LifecycleResults();
        if (!isLoaded(id)) {
            // recursively load configurations from the new child to the parents
//            LinkedHashMap<Artifact, UnloadedConfiguration> configurationsToLoad = new LinkedHashMap<Artifact, UnloadedConfiguration>();
            LinkedHashSet<Artifact> resolvedParents;
            try {
                resolvedParents = resolveParentIds(configurationData);
//                loadDepthFirst(configurationData, configurationsToLoad, monitor);
            } catch (Exception e) {
                monitor.finished();
                throw new LifecycleException("load", id, e);
            }

            // load and start the unloaded the gbean for each configuration (depth first)
            Map<Artifact, Configuration> actuallyLoaded = loadedConfigurations.get();
            boolean newLoad = actuallyLoaded == null;
            if (actuallyLoaded == null) {
                actuallyLoaded = new LinkedHashMap<Artifact, Configuration>(resolvedParents.size());
                loadedConfigurations.set(actuallyLoaded);
            }
            try {
                // update the status of the loaded configurations
                Configuration configuration = load(configurationData, resolvedParents, actuallyLoaded);
                actuallyLoaded.put(configurationData.getId(), configuration);
                addNewConfigurationToModel(configuration);
            } catch (Exception e) {
//                monitor.failed(configurationId, e);

                // there was a problem, so we need to unload all configurations that were actually loaded
//                for (Bundle bundle : actuallyLoaded.values()) {
//                    try {
//                        //TODO OSGI REALLY?
//                        bundle.stop();
//                    } catch (BundleException e1) {
//                        //?? TODO OSGI WHAT??
//                    }
//                }

                monitor.finished();
                throw new LifecycleException("load", id, e);
            } finally {
                if (newLoad) {
                    loadedConfigurations.remove();
                }
            }
        }
        load(id);
        monitor.finished();
        return results;
    }

    protected void load(Artifact configurationId) throws NoSuchConfigException {
        configurationModel.load(configurationId);
    }

    protected Configuration load(ConfigurationData configurationData, LinkedHashSet<Artifact> resolvedParentIds, Map<Artifact, Configuration> loadedConfigurations) throws InvalidConfigException {
        try {
            ConfigurationResolver configurationResolver = newConfigurationResolver(configurationData);

            return doLoad(configurationData, resolvedParentIds, loadedConfigurations, configurationResolver);
        } catch (Exception e) {
            throw new InvalidConfigException("Error starting configuration gbean " + configurationData.getId(), e);
        }
    }

    public ConfigurationResolver newConfigurationResolver(ConfigurationData configurationData) {
        ConfigurationResolver configurationResolver = new ConfigurationResolver(configurationData, repositories, artifactResolver);
        return configurationResolver;
    }

    protected Configuration doLoad(ConfigurationData configurationData, LinkedHashSet<Artifact> resolvedParentIds, Map<Artifact, Configuration> loadedConfigurations, ConfigurationResolver configurationResolver) throws Exception {
        DependencyNode dependencyNode = buildDependencyNode(configurationData);

//        ClassLoaderHolder classLoaderHolder = buildClassLoaders(configurationData, loadedConfigurations, dependencyNode, configurationResolver);

        List<Configuration> allServiceParents = buildAllServiceParents(loadedConfigurations, dependencyNode);

        Configuration configuration = new Configuration(configurationData, dependencyNode, allServiceParents, null, configurationResolver, this);
        configuration.doStart();
        //TODO why???
        resolvedParentIds.add(configuration.getId());

        Map<Artifact, Configuration> moreLoadedConfigurations = loadedConfigurations;//new LinkedHashMap<Artifact, Configuration>(loadedConfigurations);
        moreLoadedConfigurations.put(dependencyNode.getId(), configuration);
        for (Map.Entry<String, ConfigurationData> childEntry : configurationData.getChildConfigurations().entrySet()) {
            ConfigurationResolver childResolver = configurationResolver.createChildResolver(childEntry.getKey());
            Configuration child = doLoad(childEntry.getValue(), resolvedParentIds, moreLoadedConfigurations, childResolver);
            configuration.addChild(child);
        }
        return configuration;
    }

    protected List<Configuration> buildAllServiceParents(Map<Artifact, Configuration> loadedConfigurations, DependencyNode dependencyNode) throws InvalidConfigException {
        List<Configuration> allServiceParents = new ArrayList<Configuration>();
        for (Artifact parentId : dependencyNode.getServiceParents()) {
            addDepthFirstServiceParents(parentId, allServiceParents, new HashSet<Artifact>(), loadedConfigurations);
        }
        return allServiceParents;
    }


    protected DependencyNode buildDependencyNode(ConfigurationData configurationData) throws MissingDependencyException {
        DependencyNode dependencyNode = DependencyNodeUtil.toDependencyNode(configurationData.getEnvironment(), artifactResolver, this);
        return dependencyNode;
    }

    private void addDepthFirstServiceParents(Artifact id, List<Configuration> ancestors, Set<Artifact> ids, Map<Artifact, Configuration> loadedConfigurations) throws InvalidConfigException {
        if (!ids.contains(id)) {
            Configuration configuration = getConfiguration(id, loadedConfigurations);
            ancestors.add(configuration);
            ids.add(id);
            for (Artifact parentId : configuration.getDependencyNode().getServiceParents()) {
                addDepthFirstServiceParents(parentId, ancestors, ids, loadedConfigurations);
            }
        }
    }

//    private Collection<Configuration> findParentConfigurations(LinkedHashSet<Artifact> resolvedParentIds, Map<Artifact, Configuration> loadedConfigurations) throws InvalidConfigException {
//        LinkedHashMap<Artifact, Configuration> parents = new LinkedHashMap<Artifact, Configuration>();
//        for (Artifact resolvedArtifact : resolvedParentIds) {
//
//            Configuration parent = getConfiguration(resolvedArtifact, loadedConfigurations);
//
//            parents.put(resolvedArtifact, parent);
//        }
//        return parents.values();
//    }

    private Configuration getConfiguration(Artifact resolvedArtifact, Map<Artifact, Configuration> loadedConfigurations) throws InvalidConfigException {
        Configuration parent;

        //TODO OSGI track loaded configurations in thread local ???
        if (loadedConfigurations.containsKey(resolvedArtifact)) {
            parent = loadedConfigurations.get(resolvedArtifact);
        } else
        if (isLoaded(resolvedArtifact)) {
            parent = getConfiguration(resolvedArtifact);
        } else {
            throw new InvalidConfigException("Cound not find parent configuration: " + resolvedArtifact);
        }
        return parent;
    }

//    private void addNewConfigurationsToModel(Map<Artifact, Bundle> loadedConfigurations) throws NoSuchConfigException {
//        for (Bundle configuration : loadedConfigurations.values()) {
//            addNewConfigurationToModel(configuration);
//        }
//    }

    protected void addNewConfigurationToModel(Configuration configuration) throws NoSuchConfigException {
        configurationModel.addConfiguration(configuration.getId(),
                getConfigurationIds(getLoadParents(configuration)),
                getConfigurationIds(getStartParents(configuration)));
        configurations.put(configuration.getId(), configuration);
    }

    protected LinkedHashSet<Configuration> getLoadParents(Configuration configuration) throws NoSuchConfigException {
        LinkedHashSet<Configuration> loadParent = new LinkedHashSet<Configuration>();
        getLoadParentsInternal(configuration, loadParent, this);
        return loadParent;
    }

    private void getLoadParentsInternal(final Configuration configuration, LinkedHashSet<Configuration> parents, final ConfigurationSource configurationSource) throws NoSuchConfigException {
        DependencyNodeUtil.addClassParents(configuration.getDependencyNode(), parents, configurationSource);
        for (Configuration childConfiguration : configuration.getChildren()) {
            ConfigurationSource childSource = new ConfigurationSource() {

                public Configuration getConfiguration(Artifact configurationId) {
                    if (configurationId.equals(configuration.getId())) {
                        return configuration;
                    }
                    return configurationSource.getConfiguration(configurationId);
                }
            };
            getLoadParentsInternal(childConfiguration, parents, childSource);
            // remove this configuration from the parent Ids since it will cause an infinite loop
            parents.remove(configuration);
        }
    }

    protected LinkedHashSet<Configuration> getStartParents(Configuration configuration) throws NoSuchConfigException {
        LinkedHashSet<Configuration> startParent = new LinkedHashSet<Configuration>();
        getStartParentsInternal(configuration, startParent, this);
        return startParent;
    }

    private void getStartParentsInternal(final Configuration configuration, LinkedHashSet<Configuration> parents, final ConfigurationSource configurationSource) throws NoSuchConfigException {
        DependencyNodeUtil.addServiceParents(configuration.getDependencyNode(), parents, configurationSource);
        for (Configuration childConfiguration : configuration.getChildren()) {
            ConfigurationSource childSource = new ConfigurationSource() {

                public Configuration getConfiguration(Artifact configurationId) {
                    if (configurationId.equals(configuration.getId())) {
                        return configuration;
                    }
                    return configurationSource.getConfiguration(configurationId);
                }
            };
            getStartParentsInternal(childConfiguration, parents, childSource);
            // remove this configuration from the parent Ids since it will cause an infinite loop
            parents.remove(configuration);
        }
    }

    private static LinkedHashSet<Artifact> getConfigurationIds(Collection<Configuration> configurations) {
        LinkedHashSet<Artifact> configurationIds = new LinkedHashSet<Artifact>(configurations.size());
        for (Configuration configuration : configurations) {
            configurationIds.add(configuration.getId());
        }
        return configurationIds;
    }

    private synchronized void loadDepthFirst(ConfigurationData configurationData, LinkedHashMap<Artifact, UnloadedConfiguration> configurationsToLoad, LifecycleMonitor monitor) throws NoSuchConfigException, IOException, InvalidConfigException, MissingDependencyException {
        // if this parent hasn't already been processed, iterate into the parent
        Artifact configurationId = configurationData.getId();
        if (!configurationsToLoad.containsKey(configurationId)) {
            monitor.resolving(configurationId);
            LinkedHashSet<Artifact> resolvedParentIds = resolveParentIds(configurationData);
            monitor.succeeded(configurationId);

            for (Artifact parentId : resolvedParentIds) {
                // if this parent id hasn't already been loaded and is actually a configuration
                if (!isLoaded(parentId) && isConfiguration(parentId)) {
                    ConfigurationData parentConfigurationData = loadConfigurationData(parentId, monitor);
                    loadDepthFirst(parentConfigurationData, configurationsToLoad, monitor);
                }
            }

            // depth first - all unloaded parents have been added, now add this configuration
            configurationsToLoad.put(configurationId, new UnloadedConfiguration(configurationData, resolvedParentIds));
        }
    }

    // Return ids that can be loaded in sorted order.  Remove loadable ids from source set.
    public LinkedHashSet<Artifact> sort(List<Artifact> ids, LifecycleMonitor monitor) throws InvalidConfigException, IOException, NoSuchConfigException, MissingDependencyException {
        LinkedHashSet<Artifact> sorted = new LinkedHashSet<Artifact>();
        sort(ids, sorted, monitor);
        sorted.retainAll(ids);
        ids.removeAll(sorted);
        return sorted;
    }

    private void sort(Collection<Artifact> ids, LinkedHashSet<Artifact> sorted, LifecycleMonitor monitor) throws InvalidConfigException, IOException, NoSuchConfigException, MissingDependencyException {
        for (Artifact id : ids) {
            if (!sorted.contains(id)) {
                try {
                    //configuration may not be loadable yet, the config-store may not be available to load from
                    ConfigurationData data = loadConfigurationData(id, monitor);
                    LinkedHashSet<Artifact> parents = resolveParentIds(data);
                    sort(parents, sorted, monitor);
                    sorted.add(id);
                } catch (NoSuchConfigException e) {
                    //ignore
                } catch (IOException e) {
                    //ignore
                } catch (InvalidConfigException e) {
                    //ignore
                } catch (MissingDependencyException e) {
                    //ignore
                }
            }
        }
    }

    private ConfigurationData loadConfigurationData(Artifact configurationId, LifecycleMonitor monitor) throws NoSuchConfigException, IOException, InvalidConfigException {
        List<ConfigurationStore> storeSnapshot = getStoreList();

        monitor.addConfiguration(configurationId);
        monitor.reading(configurationId);
        for (ConfigurationStore store : storeSnapshot) {
            if (store.containsConfiguration(configurationId)) {
                ConfigurationData configurationData = store.loadConfiguration(configurationId);
                monitor.succeeded(configurationId);
                return configurationData;
            }
        }
        NoSuchConfigException exception = new NoSuchConfigException(configurationId);
        monitor.failed(configurationId, exception);
        throw exception;
    }

    private String locateBundle(Artifact configurationId, LifecycleMonitor monitor) throws NoSuchConfigException, IOException, InvalidConfigException {
        if (System.getProperty("geronimo.build.car") == null) {
            return "mvn:" + configurationId.getGroupId() + "/" + configurationId.getArtifactId() + "/" + configurationId.getVersion() + "/" + configurationId.getType();
        }
        monitor.addConfiguration(configurationId);
        monitor.reading(configurationId);
        for (Repository repo : repositories) {
            if (repo.contains(configurationId)) {
                return "reference:file://" + repo.getLocation(configurationId).getAbsolutePath();
            }
        }
        NoSuchConfigException exception = new NoSuchConfigException(configurationId);
        monitor.failed(configurationId, exception);
        throw exception;
    }

    public LinkedHashSet<Artifact> resolveParentIds(ConfigurationData configurationData) throws MissingDependencyException, InvalidConfigException {
        Environment environment = configurationData.getEnvironment();

        LinkedHashSet<Artifact> parentIds = new LinkedHashSet<Artifact>();
        List<Dependency> dependencies = new ArrayList<Dependency>(environment.getDependencies());
        for (ListIterator<Dependency> iterator = dependencies.listIterator(); iterator.hasNext();) {
            Dependency dependency = iterator.next();
            Artifact resolvedArtifact = artifactResolver.resolveInClassLoader(dependency.getArtifact());
//            if (isConfiguration(resolvedArtifact)) {
            parentIds.add(resolvedArtifact);

            // update the dependency list to contain the resolved artifact
            dependency = new Dependency(resolvedArtifact, dependency.getImportType());
            iterator.set(dependency);
//            } else if (dependency.getImportType() == ImportType.SERVICES) {
//                 Service depdendencies require that the depdencency be a configuration
//                throw new InvalidConfigException("Dependency does not have services: " + resolvedArtifact);
//            }
        }

        for (ConfigurationData childConfigurationData : configurationData.getChildConfigurations().values()) {
            LinkedHashSet<Artifact> childParentIds = resolveParentIds(childConfigurationData);
            // remove this configuration's id from the parent Ids since it will cause an infinite loop
            childParentIds.remove(configurationData.getId());
            parentIds.addAll(childParentIds);
        }
        return parentIds;
    }

    private static class UnloadedConfiguration {
        private final ConfigurationData configurationData;
        private final LinkedHashSet<Artifact> resolvedParentIds;

        public UnloadedConfiguration(ConfigurationData configurationData, LinkedHashSet<Artifact> resolvedParentIds) {
            this.configurationData = configurationData;
            this.resolvedParentIds = resolvedParentIds;
        }

        public ConfigurationData getConfigurationData() {
            return configurationData;
        }

        public LinkedHashSet<Artifact> getResolvedParentIds() {
            return resolvedParentIds;
        }
    }

    public synchronized LifecycleResults startConfiguration(Artifact id) throws NoSuchConfigException, LifecycleException {
        return startConfiguration(id, NullLifecycleMonitor.INSTANCE);
    }

    public synchronized LifecycleResults startConfiguration(Artifact id, LifecycleMonitor monitor) throws NoSuchConfigException, LifecycleException {
        if (!id.isResolved()) {
            throw new IllegalArgumentException("Artifact " + id + " is not fully resolved");
        }
        LinkedHashSet<Artifact> unstartedConfigurations = configurationModel.start(id);

        addConfigurationsToMonitor(monitor, unstartedConfigurations);

        LifecycleResults results = new LifecycleResults();
        Artifact configurationId = null;
        try {
            for (Artifact unstartedConfiguration : unstartedConfigurations) {
                configurationId = unstartedConfiguration;
                Configuration configuration = getConfiguration(configurationId);
                if (configuration == null) {
                    throw new NoSuchConfigException(configurationId, "trying to start ancestor config, but not found");
                }
                monitor.starting(configurationId);
                start(configuration);
                monitor.succeeded(configurationId);

                results.addStarted(configurationId);
            }
        } catch (Exception e) {
            monitor.failed(configurationId, e);
            configurationModel.stop(id);

            for (Artifact started : results.getStarted()) {
                Configuration configuration = getConfiguration(started);
                monitor.stopping(started);
                stop(configuration);
                monitor.succeeded(started);
            }
            monitor.finished();
            throw new LifecycleException("start", id, e);
        }
        monitor.finished();
        return results;
    }

    protected void start(Configuration configuration) throws Exception {
        throw new UnsupportedOperationException();
    }

    public synchronized LifecycleResults stopConfiguration(Artifact id) throws NoSuchConfigException {
        return stopConfiguration(id, NullLifecycleMonitor.INSTANCE);
    }

    public synchronized LifecycleResults stopConfiguration(Artifact id, LifecycleMonitor monitor) throws NoSuchConfigException {
        if (!id.isResolved()) {
            throw new IllegalArgumentException("Artifact " + id + " is not fully resolved");
        }
        LinkedHashSet<Artifact> stopList = configurationModel.stop(id);

        addConfigurationsToMonitor(monitor, stopList);

        LifecycleResults results = new LifecycleResults();
        for (Artifact configurationId : stopList) {
            Configuration configuration = getConfiguration(configurationId);

            monitor.stopping(configurationId);
            stop(configuration);
            monitor.succeeded(configurationId);

            results.addStopped(configurationId);
        }

        monitor.finished();
        return results;
    }

    protected void stop(Configuration configuration) {
        // Don't throw an exception because we call this from unload to be sure that all
        // unloaded configurations are stopped first
    }

    public synchronized LifecycleResults restartConfiguration(Artifact id) throws NoSuchConfigException, LifecycleException {
        return restartConfiguration(id, NullLifecycleMonitor.INSTANCE);
    }

    public synchronized LifecycleResults restartConfiguration(Artifact id, LifecycleMonitor monitor) throws NoSuchConfigException, LifecycleException {
        if (!id.isResolved()) {
            throw new IllegalArgumentException("Artifact " + id + " is not fully resolved");
        }
        // get a sorted list of configurations to restart
        LinkedHashSet<Artifact> restartList = configurationModel.restart(id);

        addConfigurationsToMonitor(monitor, restartList);

        // stop the configuations
        LifecycleResults results = new LifecycleResults();
        for (Artifact configurationId : restartList) {
            Configuration configuration = getConfiguration(configurationId);
            monitor.stopping(configurationId);
            stop(configuration);
            monitor.succeeded(configurationId);
            results.addStopped(configurationId);
        }

        // reverse the list
        restartList = reverse(restartList);

        // restart the configurations
        Set<Artifact> skip = new HashSet<Artifact>();
        for (Artifact configurationId : restartList) {

            // skip the configurations that have alredy failed or are children of failed configurations
            if (skip.contains(configurationId)) {
                continue;
            }

            // try to start the configuation
            try {
                Configuration configuration = getConfiguration(configurationId);
                applyOverrides(configuration);
                monitor.starting(configurationId);
                start(configuration);
                monitor.succeeded(configurationId);
                results.addStarted(configurationId);
            } catch (Exception e) {
                // the configuraiton failed to restart
                results.addFailed(configurationId, e);
                monitor.failed(configurationId, e);
                skip.add(configurationId);

                // officially stop the configuration in the model (without gc)
                LinkedHashSet<Artifact> stopList = configurationModel.stop(configurationId, false);

                // all of the configurations to be stopped must be in our restart list, or the model is corrupt
                if (!restartList.containsAll(stopList)) {
                    throw new AssertionError("Configuration data model is corrupt.   You must restart your server.");
                }

                // add the children of the failed configuration to the results as stopped
                for (Artifact failedId : stopList) {

                    // if any of the failed configuration is in the restarted set, the model is
                    // corrupt because we started a child before a parent
                    if (results.wasStarted(failedId)) {
                        throw new AssertionError("Configuration data model is corrupt.   You must restart your server.");
                    }

                    skip.add(failedId);
                }
            }
        }

        monitor.finished();
        if (!results.wasStarted(id)) {
            throw new LifecycleException("restart", id, results);
        }
        return results;
    }

    public synchronized LifecycleResults unloadConfiguration(Artifact id) throws NoSuchConfigException, LifecycleException {
        return unloadConfiguration(id, NullLifecycleMonitor.INSTANCE);
    }

    public synchronized LifecycleResults unloadConfiguration(Artifact id, LifecycleMonitor monitor) throws NoSuchConfigException, LifecycleException {
        if (!id.isResolved()) {
            throw new IllegalArgumentException("Artifact " + id + " is not fully resolved");
        }
        Set started = configurationModel.getStarted();
        LinkedHashSet<Artifact> unloadList = configurationModel.unload(id);

        addConfigurationsToMonitor(monitor, unloadList);

        LifecycleResults results = new LifecycleResults();
        for (Artifact configurationId : unloadList) {
            Configuration configuration = getConfiguration(configurationId);

            // first make sure it is stopped
            if (started.contains(configurationId)) {
                monitor.stopping(configurationId);
                stop(configuration);
                monitor.succeeded(configurationId);
                results.addStopped(configurationId);
            } else {
                // call stop just to be sure the beans aren't running
                stop(configuration);
            }

            // now unload it
            monitor.unloading(configurationId);
            unload(configuration);
            monitor.succeeded(configurationId);
            results.addUnloaded(configurationId);

            // clean up the model
            removeConfigurationFromModel(configurationId);

            try {
                Bundle bundle = bundles.remove(configurationId);
                if (bundle != null) {
                    if (BundleUtils.canStop(bundle)) {
                        bundle.stop(Bundle.STOP_TRANSIENT);
                    }
                    if (BundleUtils.canUninstall(bundle)) {
                        bundle.uninstall();
                    }
                }
            } catch (BundleException e) {
                monitor.finished();
                throw new LifecycleException("unload", configurationId, e);
            }
        }
        monitor.finished();
        return results;
    }

    protected void removeConfigurationFromModel(Artifact configurationId) throws NoSuchConfigException {
        if (configurationModel.containsConfiguration(configurationId)) {
            configurationModel.removeConfiguration(configurationId);
        }
        configurations.remove(configurationId);
    }

    protected void unload(Configuration configuration) {
        try {
            configuration.doStop();
        } catch (Exception e) {
            log.debug("Problem unloading config: " + configuration.getId(), e);
        }
    }

    public synchronized LifecycleResults reloadConfiguration(Artifact id) throws NoSuchConfigException, LifecycleException {
        return reloadConfiguration(id, NullLifecycleMonitor.INSTANCE);
    }

    public synchronized LifecycleResults reloadConfiguration(Artifact id, LifecycleMonitor monitor) throws NoSuchConfigException, LifecycleException {
        return reloadConfiguration(id, id.getVersion(), monitor);
    }

    public synchronized LifecycleResults reloadConfiguration(Artifact id, Version version) throws NoSuchConfigException, LifecycleException {
        return reloadConfiguration(id, version, NullLifecycleMonitor.INSTANCE);
    }

    public synchronized LifecycleResults reloadConfiguration(Artifact id, Version version, LifecycleMonitor monitor) throws NoSuchConfigException, LifecycleException {
        if (!id.isResolved()) {
            throw new IllegalArgumentException("Artifact " + id + " is not fully resolved");
        }
        Configuration configuration = getConfiguration(id);
        if (configuration == null) { // The configuration to reload is not currently loaded
            ConfigurationData data = null;
            List<ConfigurationStore> storeSnapshot = getStoreList();
            for (ConfigurationStore store : storeSnapshot) {
                if (store.containsConfiguration(id)) {
                    try {
                        data = store.loadConfiguration(id);
                    } catch (Exception e) {
                        log.warn("Unable to load existing configuration " + id + " from config store", e);
                    }
                }
            }
            if (data == null) {
                throw new NoSuchConfigException(id);
            }
            UnloadedConfiguration existingUnloadedConfiguration = new UnloadedConfiguration(data, new LinkedHashSet<Artifact>());
            Artifact newId = new Artifact(id.getGroupId(), id.getArtifactId(), version, id.getType());
            ConfigurationData newData;
            try {
                newData = loadConfigurationData(newId, monitor);
            } catch (Exception e) {
                monitor.finished();
                throw new LifecycleException("reload", id, e);
            }

            return reloadConfiguration(existingUnloadedConfiguration, newData, monitor);
        } else { // The configuration to reload is loaded
            ConfigurationData existingConfigurationData = configuration.getConfigurationData();
            UnloadedConfiguration existingUnloadedConfiguration = new UnloadedConfiguration(existingConfigurationData, getResolvedParentIds(configuration));

            Artifact newId = new Artifact(id.getGroupId(), id.getArtifactId(), version, id.getType());

            // reload the ConfigurationData from a store
            ConfigurationData configurationData;
            try {
                configurationData = loadConfigurationData(newId, monitor);
            } catch (Exception e) {
                monitor.finished();
                throw new LifecycleException("reload", id, e);
            }

            return reloadConfiguration(existingUnloadedConfiguration, configurationData, monitor);
        }
    }

    public synchronized LifecycleResults reloadConfiguration(ConfigurationData configurationData) throws LifecycleException, NoSuchConfigException {
        return reloadConfiguration(configurationData, NullLifecycleMonitor.INSTANCE);
    }

    public synchronized LifecycleResults reloadConfiguration(ConfigurationData configurationData, LifecycleMonitor monitor) throws LifecycleException, NoSuchConfigException {
        Configuration configuration = getConfiguration(configurationData.getId());
        if (configuration == null) {
            throw new NoSuchConfigException(configurationData.getId());
        }
        ConfigurationData existingConfigurationData = configuration.getConfigurationData();
        UnloadedConfiguration existingUnloadedConfiguration = new UnloadedConfiguration(existingConfigurationData, getResolvedParentIds(configuration));
        return reloadConfiguration(existingUnloadedConfiguration, configurationData, monitor);
    }

    private boolean hasHardDependency(Artifact configurationId, ConfigurationData configurationData) {
        for (Dependency dependency : configurationData.getEnvironment().getDependencies()) {
            Artifact artifact = dependency.getArtifact();
            if (artifact.getVersion() != null && artifact.matches(configurationId)) {
                return true;
            }
        }

        for (ConfigurationData childConfigurationData : configurationData.getChildConfigurations().values()) {
            if (hasHardDependency(configurationId, childConfigurationData)) {
                return true;
            }
        }
        return false;
    }

    // todo this method ignores garbage collection of configurations
    private LifecycleResults reloadConfiguration(UnloadedConfiguration existingUnloadedConfiguration, ConfigurationData newConfigurationData, LifecycleMonitor monitor) throws LifecycleException, NoSuchConfigException {
        boolean force = false;

        Artifact existingConfigurationId = existingUnloadedConfiguration.getConfigurationData().getId();
        Artifact newConfigurationId = newConfigurationData.getId();

        //
        // recursively load the new configuration; this will catch any new parents
        //
        LinkedHashMap<Artifact, UnloadedConfiguration> newConfigurations = new LinkedHashMap<Artifact, UnloadedConfiguration>();
        try {
            loadDepthFirst(newConfigurationData, newConfigurations, monitor);
        } catch (Exception e) {
            monitor.finished();
            throw new LifecycleException("reload", newConfigurationId, e);
        }

        //
        // get a list of the started configuration, so we can restart them later
        //
        Set<Artifact> started = configurationModel.getStarted();

        //
        // get a list of the child configurations that will need to reload
        //
        //   note: we are iterating in reverse order
        LinkedHashMap<Artifact, LinkedHashSet<Artifact>> existingParents = new LinkedHashMap<Artifact, LinkedHashSet<Artifact>>();
        LinkedHashMap<Artifact, UnloadedConfiguration> reloadChildren = new LinkedHashMap<Artifact, UnloadedConfiguration>();
        for (Artifact configurationId : reverse(configurationModel.reload(existingConfigurationId))) {

            if (configurationId.equals(existingConfigurationId)) {
                continue;
            }

            // if new configurations contains the child something we have a circular dependency
            if (newConfigurations.containsKey(configurationId)) {
                throw new LifecycleException("reload", newConfigurationId,
                        new IllegalStateException("Circular depenency between " + newConfigurationId + " and " + configurationId));
            }

            Configuration configuration = getConfiguration(configurationId);
            ConfigurationData configurationData = configuration.getConfigurationData();

            // save off the exising resolved parent ids in case we need to restore this configuration
            LinkedHashSet<Artifact> existingParentIds = getResolvedParentIds(configuration);
            existingParents.put(configurationId, existingParentIds);

            // check that the child doen't have a hard dependency on the old configuration
            LinkedHashSet<Artifact> resolvedParentIds;
            if (hasHardDependency(existingConfigurationId, configurationData)) {
                if (force) {
                    throw new LifecycleException("reload", newConfigurationId,
                            new IllegalStateException("Existing configuration " + configurationId + " has a hard dependency on the current version of this configuration " + existingConfigurationId));
                }

                // we leave the resolved parent ids null to signal that we should not reload the configuration
                resolvedParentIds = null;
            } else {
                resolvedParentIds = new LinkedHashSet<Artifact>(existingParentIds);
                resolvedParentIds.remove(existingConfigurationId);
                resolvedParentIds.add(newConfigurationId);
            }

            reloadChildren.put(configurationId, new UnloadedConfiguration(configurationData, resolvedParentIds));
            monitor.addConfiguration(configurationId);
        }

        //
        // unload the children
        //

        // note: we are iterating in reverse order
        LifecycleResults results = new LifecycleResults();
        for (Artifact configurationId : reverse(reloadChildren).keySet()) {
            Configuration configuration = getConfiguration(configurationId);

            // first make sure it is stopped
            if (started.contains(configurationId)) {
                monitor.stopping(configurationId);
                stop(configuration);
                monitor.succeeded(configurationId);
                results.addStopped(configurationId);
            } else {
                // call stop just to be sure the beans aren't running
                stop(configuration);
            }

            // now unload it
            monitor.unloading(configurationId);
            unload(configuration);
            monitor.succeeded(configurationId);
            results.addUnloaded(configurationId);
        }

        //
        // unload the existing config
        //
        Configuration existingConfiguration = getConfiguration(existingConfigurationId);
        if (started.contains(existingConfigurationId)) {
            monitor.stopping(existingConfigurationId);
            stop(existingConfiguration);
            monitor.succeeded(existingConfigurationId);
            results.addStopped(existingConfigurationId);
        } else if (existingConfiguration != null) {
            // call stop just to be sure the beans aren't running
            stop(existingConfiguration);
        }
        if (existingConfiguration != null) {
            monitor.unloading(existingConfigurationId);
            unload(existingConfiguration);
            monitor.succeeded(existingConfigurationId);
            results.addUnloaded(existingConfigurationId);
        }

        //
        // load the new configurations
        //
        boolean reinstatedExisting = false;
        /* reduce variable scope */
        {
            Map<Artifact, Configuration> loadedParents = new LinkedHashMap<Artifact, Configuration>();
            Map<Artifact, Configuration> startedParents = new LinkedHashMap<Artifact, Configuration>();
            Configuration newConfiguration = null;
            Artifact configurationId = null;
            try {
                //
                // load all of the new configurations
                //
                for (Map.Entry<Artifact, UnloadedConfiguration> entry : newConfigurations.entrySet()) {
                    configurationId = entry.getKey();
                    UnloadedConfiguration unloadedConfiguration = entry.getValue();

                    monitor.loading(configurationId);
                    Configuration configuration = load(unloadedConfiguration.getConfigurationData(), unloadedConfiguration.getResolvedParentIds(), loadedParents);
                    monitor.succeeded(configurationId);

                    if (configurationId.equals(newConfigurationId)) {
                        newConfiguration = configuration;
                        reloadingConfiguration = configuration;
                    } else {
                        loadedParents.put(configurationId, configuration);
                    }
                }

                if (newConfiguration == null) {
                    AssertionError cause = new AssertionError("Internal error: configuration was not load");
                    results.addFailed(newConfigurationId, cause);
                    throw new LifecycleException("reload", newConfigurationId, results);
                }

                //
                // start the new configurations if the old one was running
                //
                if (started.contains(existingConfigurationId)) {

                    // determine which of the parents we need to start
                    LinkedHashSet<Configuration> startList = new LinkedHashSet<Configuration>();
                    for (Configuration serviceParent : getStartParents(newConfiguration)) {
                        if (loadedParents.containsKey(serviceParent.getId())) {
                            startList.add(serviceParent);
                        }
                    }

                    // start the new parents
                    for (Configuration startParent : startList) {
                        monitor.starting(configurationId);
                        start(startParent);
                        monitor.succeeded(configurationId);

                        startedParents.put(configurationId, startParent);
                    }

                    //  start the new configuration
                    monitor.starting(newConfigurationId);
                    start(newConfiguration);
                    monitor.succeeded(newConfigurationId);
                }

                //
                // update the results
                //
                results.setLoaded(loadedParents.keySet());
                results.addLoaded(newConfigurationId);
                if (started.contains(existingConfigurationId)) {
                    results.setStarted(startedParents.keySet());
                    results.addStarted(newConfigurationId);
                }

                //
                // update the model
                //

                // add all of the new configurations the model
                //TODO OSGI TOTALLY BROKEN
//                addNewConfigurationsToModel(loadedParents);

                // now ugrade the existing node in the model
                if (configurationModel.containsConfiguration(existingConfigurationId)) {
                    configurationModel.upgradeConfiguration(existingConfigurationId,
                            newConfigurationId,
                            getConfigurationIds(getLoadParents(newConfiguration)),
                            getConfigurationIds(getStartParents(newConfiguration)));
                } else {
                    configurationModel.addConfiguration(newConfigurationId,
                            getConfigurationIds(getLoadParents(newConfiguration)),
                            getConfigurationIds(getStartParents(newConfiguration)));
                    load(newConfigurationId);
                }

                // replace the configuraiton in he configurations map
                configurations.remove(existingConfiguration.getId());
                configurations.put(newConfigurationId, newConfiguration);

                // migrate the configuration settings
                migrateConfiguration(existingConfigurationId, newConfigurationId, newConfiguration, started.contains(existingConfigurationId));
            } catch (Exception e) {
                monitor.failed(configurationId, e);
                results.addFailed(configurationId, e);

                //
                // stop and unload all configurations that were actually loaded
                //
                for (Configuration configuration : startedParents.values()) {
                    stop(configuration);
                }
                for (Configuration configuration : loadedParents.values()) {
                    unload(configuration);
                }

                // stop and unload the newConfiguration
                if (newConfiguration != null) {
                    stop(newConfiguration);
                    unload(newConfiguration);
                }

                //
                // atempt to reinstate the old configuation
                //
                Configuration configuration = null;
                try {
                    configuration = load(existingUnloadedConfiguration.getConfigurationData(),
                            existingUnloadedConfiguration.getResolvedParentIds(),
                            Collections.<Artifact, Configuration>emptyMap()
                    );
                    reloadingConfiguration = configuration;
                    // if the configuration was started before restart it
                    if (started.contains(existingConfigurationId)) {
                        start(configuration);
                        results.addStarted(existingConfigurationId);
                    }

                    // don't mark as loded until start completes as it may thorw an exception
                    results.addLoaded(existingConfigurationId);

                    configurations.put(existingConfigurationId, configuration);

                    reinstatedExisting = true;
                } catch (Exception ignored) {
                    monitor.failed(existingConfigurationId, e);

                    // we tried our best
                    if (configuration != null) {
                        unload(configuration);
                    }

                    //
                    // cleanup the model
                    //
                    for (Artifact childId : results.getUnloaded()) {
                        configurationModel.unload(childId);
                        removeConfigurationFromModel(childId);
                    }

                    throw new LifecycleException("reload", newConfigurationId, results);
                }
            } finally {
                reloadingConfiguration = null;
            }
        }

        //
        // reload as many child configurations as possible
        //
        Set<Artifact> skip = new HashSet<Artifact>();
        for (Map.Entry<Artifact, UnloadedConfiguration> entry : reloadChildren.entrySet()) {
            Artifact configurationId = entry.getKey();
            UnloadedConfiguration unloadedConfiguration = entry.getValue();

            // skip the configurations that have alredy failed or are children of failed configurations
            if (skip.contains(configurationId)) {
                continue;
            }

            // try to load the configuation
            Configuration configuration = null;
            try {
                // get the correct resolved parent ids based on if we are loading with the new config id or the existing one
                LinkedHashSet<Artifact> resolvedParentIds;
                if (!reinstatedExisting) {
                    resolvedParentIds = unloadedConfiguration.getResolvedParentIds();
                } else {
                    resolvedParentIds = existingParents.get(configurationId);
                }

                // if the resolved parent ids is null, then we are not supposed to reload this configuration
                if (resolvedParentIds != null) {
                    monitor.loading(configurationId);
                    configuration = load(unloadedConfiguration.getConfigurationData(),
                            resolvedParentIds,
                            Collections.<Artifact,
                                    Configuration>emptyMap()
                    );
                    reloadingConfiguration = configuration;
                    monitor.succeeded(configurationId);

                    // if the configuration was started before restart it
                    if (started.contains(configurationId)) {
                        monitor.starting(configurationId);
                        start(configuration);
                        monitor.succeeded(configurationId);
                        results.addStarted(configurationId);
                    }

                    // don't mark as loded until start completes as it may thow an exception
                    results.addLoaded(configurationId);

                    configurations.put(configurationId, configuration);
                } else {
                    removeConfigurationFromModel(configurationId);
                }
            } catch (Exception e) {
                // the configuraiton failed to restart
                results.addFailed(configurationId, e);
                monitor.failed(configurationId, e);
                skip.add(configurationId);

                // unload the configuration if it was loaded and failed in start
                if (configuration != null) {
                    unload(configuration);
                }

                // officially unload the configuration in the model (without gc)
                LinkedHashSet<Artifact> unloadList = configurationModel.unload(configurationId, false);
                configurationModel.removeConfiguration(configurationId);

                // all of the configurations to be unloaded must be in our unloaded list, or the model is corrupt
                if (!reloadChildren.keySet().containsAll(unloadList)) {
                    throw new AssertionError("Configuration data model is corrupt.   You must restart your server.");
                }

                // add the children of the failed configuration to the results as unloaded
                for (Artifact failedId : unloadList) {

                    // if any of the failed configuration are in the reloaded set, the model is
                    // corrupt because we loaded a child before a parent
                    if (results.wasLoaded(failedId)) {
                        throw new AssertionError("Configuration data model is corrupt.   You must restart your server.");
                    }

                    skip.add(failedId);
                }
            } finally {
                reloadingConfiguration = null;
            }
        }

        //
        // If nothing failed, delete all the unloaded modules that weren't reloaded
        //
        if (!results.wasLoaded(existingConfigurationId) && !results.wasFailed(existingConfigurationId)) {
            try {
                uninstallConfiguration(existingConfigurationId);
            } catch (IOException e) {
                log.error("Unable to uninstall configuration " + existingConfigurationId, e);
            }
        }

        monitor.finished();
        if (results.wasFailed(newConfigurationId) || !results.wasLoaded(newConfigurationId)) {
            throw new LifecycleException("restart", newConfigurationId, results);
        }
        return results;
    }

    protected void migrateConfiguration(Artifact oldName, Artifact newName, Configuration configuration, boolean running) throws NoSuchConfigException {
    }

    private static LinkedHashSet<Artifact> getResolvedParentIds(Configuration configuration) {
        return configuration.getDependencyNode().getParents();
    }

    public synchronized void uninstallConfiguration(Artifact configurationId) throws IOException, NoSuchConfigException, LifecycleException {
        if (!configurationId.isResolved()) {
            throw new IllegalArgumentException("Artifact " + configurationId + " is not fully resolved");
        }
        if (configurations.containsKey(configurationId)) {
            if (isRunning(configurationId)) {
                stopConfiguration(configurationId);
            }
            if (isLoaded((configurationId))) {
                unloadConfiguration(configurationId);
            }
        }

        uninstall(configurationId);

        for (ConfigurationStore store : getStoreList()) {
            if (store.containsConfiguration(configurationId)) {
                store.uninstall(configurationId);
            }
        }

        removeConfigurationFromModel(configurationId);
        notifyWatchers(configurationId);
    }

    protected void uninstall(Artifact configurationId) {
        //child class can override this method
    }

    private void notifyWatchers(Artifact id) {
        for (DeploymentWatcher watcher : watchers) {
            watcher.undeployed(id);
        }
    }

    public ArtifactResolver getArtifactResolver() {
        return artifactResolver;
    }

    /**
     * this configuration manager never starts configurations.
     *
     * @return false
     */
    public boolean isOnline() {
        return false;
    }

    public void setOnline(boolean online) {
    }

    protected List<ConfigurationStore> getStoreList() {
        return new ArrayList<ConfigurationStore>(stores);
    }

    private static void addConfigurationsToMonitor(LifecycleMonitor monitor, LinkedHashSet<Artifact> configurations) {
        for (Artifact configurationId : configurations) {
            monitor.addConfiguration(configurationId);
        }
    }

    private static LinkedHashSet<Artifact> reverse(LinkedHashSet<Artifact> set) {
        ArrayList<Artifact> reverseList = new ArrayList<Artifact>(set);
        Collections.reverse(reverseList);
        set = new LinkedHashSet<Artifact>(reverseList);
        return set;
    }

    private static LinkedHashMap<Artifact, UnloadedConfiguration> reverse(LinkedHashMap<Artifact, UnloadedConfiguration> map) {
        ArrayList<Map.Entry<Artifact, UnloadedConfiguration>> reverseEntrySet = new ArrayList<Map.Entry<Artifact, UnloadedConfiguration>>(map.entrySet());
        Collections.reverse(reverseEntrySet);

        map = new LinkedHashMap<Artifact, UnloadedConfiguration>(reverseEntrySet.size());
        for (Map.Entry<Artifact, UnloadedConfiguration> entry : reverseEntrySet) {
            Artifact key = entry.getKey();
            UnloadedConfiguration value = entry.getValue();
            map.put(key, value);
        }
        return map;
    }

    /**
     * Used to apply overrides to a configuration's gbeans.
     * The overrides are applied before configuration restart.
     *
     * @param configuration configuration to customize
     * @throws InvalidConfigException on error
     */
    private void applyOverrides(Configuration configuration) throws InvalidConfigException {
        Bundle bundle = configuration.getBundle();
        Collection<GBeanData> gbeans = configuration.getConfigurationData().getGBeans(bundle);
        if (configuration.getManageableAttributeStore() != null) {
            configuration.getManageableAttributeStore().applyOverrides(configuration.getId(), gbeans,
                    bundle);
        }
    }

}
TOP

Related Classes of org.apache.geronimo.kernel.config.SimpleConfigurationManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.