0001: /**
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */package org.apache.geronimo.kernel.config;
0017:
0018: import java.io.IOException;
0019: import java.util.ArrayList;
0020: import java.util.Collection;
0021: import java.util.Collections;
0022: import java.util.HashSet;
0023: import java.util.Iterator;
0024: import java.util.LinkedHashMap;
0025: import java.util.LinkedHashSet;
0026: import java.util.List;
0027: import java.util.ListIterator;
0028: import java.util.Map;
0029: import java.util.Set;
0030:
0031: import org.apache.commons.logging.Log;
0032: import org.apache.commons.logging.LogFactory;
0033: import org.apache.geronimo.gbean.AbstractName;
0034: import org.apache.geronimo.gbean.GBeanInfo;
0035: import org.apache.geronimo.gbean.GBeanInfoBuilder;
0036: import org.apache.geronimo.kernel.management.State;
0037: import org.apache.geronimo.kernel.repository.Artifact;
0038: import org.apache.geronimo.kernel.repository.ArtifactResolver;
0039: import org.apache.geronimo.kernel.repository.Dependency;
0040: import org.apache.geronimo.kernel.repository.Environment;
0041: import org.apache.geronimo.kernel.repository.ImportType;
0042: import org.apache.geronimo.kernel.repository.MissingDependencyException;
0043: import org.apache.geronimo.kernel.repository.Repository;
0044: import org.apache.geronimo.kernel.repository.Version;
0045:
0046: /**
0047: * @version $Rev: 620729 $ $Date: 2008-02-12 01:19:46 -0800 (Tue, 12 Feb 2008) $
0048: */
0049: public class SimpleConfigurationManager implements ConfigurationManager {
0050: protected static final Log log = LogFactory
0051: .getLog(SimpleConfigurationManager.class);
0052: protected final Collection stores;
0053: private final ArtifactResolver artifactResolver;
0054: protected final Map configurations = new LinkedHashMap();
0055: protected final ConfigurationModel configurationModel = new ConfigurationModel();
0056: protected final Collection<? extends Repository> repositories;
0057: protected final Collection watchers;
0058:
0059: /**
0060: * When this is not null, it points to the "new" configuration that is
0061: * part of an in-process reload operation. This configuration will
0062: * definitely be loaded, but might not be started yet. It shold never be
0063: * populated outside the scope of a reload operation.
0064: */
0065: private Configuration reloadingConfiguration;
0066:
0067: public SimpleConfigurationManager(Collection stores,
0068: ArtifactResolver artifactResolver,
0069: Collection<? extends Repository> repositories) {
0070: this (stores, artifactResolver, repositories,
0071: Collections.EMPTY_SET);
0072: }
0073:
0074: public SimpleConfigurationManager(Collection stores,
0075: ArtifactResolver artifactResolver,
0076: Collection<? extends Repository> repositories,
0077: Collection watchers) {
0078: if (stores == null)
0079: stores = Collections.EMPTY_SET;
0080: if (repositories == null)
0081: repositories = Collections.emptySet();
0082: if (watchers == null)
0083: watchers = Collections.EMPTY_SET;
0084:
0085: this .stores = stores;
0086: this .artifactResolver = artifactResolver;
0087: this .repositories = repositories;
0088: this .watchers = watchers;
0089: }
0090:
0091: public synchronized boolean isInstalled(Artifact configId) {
0092: if (!configId.isResolved()) {
0093: throw new IllegalArgumentException("Artifact " + configId
0094: + " is not fully resolved");
0095: }
0096: List storeSnapshot = getStoreList();
0097: for (int i = 0; i < storeSnapshot.size(); i++) {
0098: ConfigurationStore store = (ConfigurationStore) storeSnapshot
0099: .get(i);
0100: if (store.containsConfiguration(configId)) {
0101: return true;
0102: }
0103: }
0104: return false;
0105: }
0106:
0107: public synchronized boolean isLoaded(Artifact configId) {
0108: if (!configId.isResolved()) {
0109: throw new IllegalArgumentException("Artifact " + configId
0110: + " is not fully resolved");
0111: }
0112: if (reloadingConfiguration != null
0113: && reloadingConfiguration.getId().equals(configId)) {
0114: return true;
0115: }
0116: return configurationModel.isLoaded(configId);
0117: }
0118:
0119: public synchronized boolean isRunning(Artifact configId) {
0120: if (!configId.isResolved()) {
0121: throw new IllegalArgumentException("Artifact " + configId
0122: + " is not fully resolved");
0123: }
0124: return configurationModel.isStarted(configId);
0125: }
0126:
0127: public Artifact[] getInstalled(Artifact query) {
0128: Artifact[] all = artifactResolver.queryArtifacts(query);
0129: List configs = new ArrayList();
0130: for (int i = 0; i < all.length; i++) {
0131: Artifact artifact = all[i];
0132: if (isConfiguration(artifact)) {
0133: configs.add(artifact);
0134: }
0135: }
0136: if (configs.size() == all.length) {
0137: return all;
0138: }
0139: return (Artifact[]) configs
0140: .toArray(new Artifact[configs.size()]);
0141: }
0142:
0143: public Artifact[] getLoaded(Artifact query) {
0144: return configurationModel.getLoaded(query);
0145: }
0146:
0147: public Artifact[] getRunning(Artifact query) {
0148: return configurationModel.getStarted(query);
0149: }
0150:
0151: public List listStores() {
0152: List storeSnapshot = getStoreList();
0153: List result = new ArrayList(storeSnapshot.size());
0154: for (int i = 0; i < storeSnapshot.size(); i++) {
0155: ConfigurationStore store = (ConfigurationStore) storeSnapshot
0156: .get(i);
0157: result.add(store.getAbstractName());
0158: }
0159: return result;
0160: }
0161:
0162: public ConfigurationStore[] getStores() {
0163: List storeSnapshot = getStoreList();
0164: return (ConfigurationStore[]) storeSnapshot
0165: .toArray(new ConfigurationStore[storeSnapshot.size()]);
0166: }
0167:
0168: public Collection<? extends Repository> getRepositories() {
0169: return repositories;
0170: }
0171:
0172: public List listConfigurations() {
0173: List storeSnapshot = getStoreList();
0174: List list = new ArrayList();
0175: for (int i = 0; i < storeSnapshot.size(); i++) {
0176: ConfigurationStore store = (ConfigurationStore) storeSnapshot
0177: .get(i);
0178: list.addAll(listConfigurations(store));
0179: }
0180: return list;
0181: }
0182:
0183: public ConfigurationStore getStoreForConfiguration(Artifact configId) {
0184: if (!configId.isResolved()) {
0185: throw new IllegalArgumentException("Artifact " + configId
0186: + " is not fully resolved");
0187: }
0188: List storeSnapshot = getStoreList();
0189: for (int i = 0; i < storeSnapshot.size(); i++) {
0190: ConfigurationStore store = (ConfigurationStore) storeSnapshot
0191: .get(i);
0192: if (store.containsConfiguration(configId)) {
0193: return store;
0194: }
0195: }
0196: return null;
0197: }
0198:
0199: public List<ConfigurationInfo> listConfigurations(
0200: AbstractName storeName) throws NoSuchStoreException {
0201: List<ConfigurationStore> storeSnapshot = getStoreList();
0202: for (ConfigurationStore store : storeSnapshot) {
0203: if (storeName.equals(store.getAbstractName())) {
0204: return listConfigurations(store);
0205: }
0206: }
0207: throw new NoSuchStoreException("No such store: " + storeName);
0208: }
0209:
0210: private List<ConfigurationInfo> listConfigurations(
0211: ConfigurationStore store) {
0212: List<ConfigurationInfo> list = store.listConfigurations();
0213: for (ListIterator<ConfigurationInfo> iterator = list
0214: .listIterator(); iterator.hasNext();) {
0215: ConfigurationInfo configurationInfo = (ConfigurationInfo) iterator
0216: .next();
0217: if (isRunning(configurationInfo.getConfigID())) {
0218: configurationInfo = new ConfigurationInfo(store
0219: .getAbstractName(), configurationInfo
0220: .getConfigID(), configurationInfo.getType(),
0221: configurationInfo.getCreated(),
0222: configurationInfo.getOwnedConfigurations(),
0223: configurationInfo.getChildConfigurations(),
0224: configurationInfo.getInPlaceLocation(),
0225: State.RUNNING);
0226: } else {
0227: configurationInfo = new ConfigurationInfo(store
0228: .getAbstractName(), configurationInfo
0229: .getConfigID(), configurationInfo.getType(),
0230: configurationInfo.getCreated(),
0231: configurationInfo.getOwnedConfigurations(),
0232: configurationInfo.getChildConfigurations(),
0233: configurationInfo.getInPlaceLocation(),
0234: State.STOPPED);
0235: }
0236: iterator.set(configurationInfo);
0237: }
0238: return list;
0239: }
0240:
0241: public boolean isConfiguration(Artifact artifact) {
0242: if (!artifact.isResolved()) {
0243: throw new IllegalArgumentException("Artifact " + artifact
0244: + " is not fully resolved");
0245: }
0246: synchronized (this ) {
0247: // if it is loaded, it is definitely a configuration
0248: if (configurations.containsKey(artifact)) {
0249: return true;
0250: }
0251: }
0252:
0253: // see if any stores think it is a configuration
0254: List storeSnapshot = getStoreList();
0255: for (int i = 0; i < storeSnapshot.size(); i++) {
0256: ConfigurationStore store = (ConfigurationStore) storeSnapshot
0257: .get(i);
0258: if (store.containsConfiguration(artifact)) {
0259: return true;
0260: }
0261: }
0262: return false;
0263: }
0264:
0265: public synchronized Configuration getConfiguration(
0266: Artifact configurationId) {
0267: if (!configurationId.isResolved()) {
0268: throw new IllegalArgumentException("Artifact "
0269: + configurationId + " is not fully resolved");
0270: }
0271: if (reloadingConfiguration != null
0272: && reloadingConfiguration.getId().equals(
0273: configurationId)) {
0274: return reloadingConfiguration;
0275: }
0276: return (Configuration) configurations.get(configurationId);
0277: }
0278:
0279: public synchronized LifecycleResults loadConfiguration(
0280: Artifact configurationId) throws NoSuchConfigException,
0281: LifecycleException {
0282: return loadConfiguration(configurationId,
0283: NullLifecycleMonitor.INSTANCE);
0284: }
0285:
0286: public synchronized LifecycleResults loadConfiguration(
0287: Artifact configurationId, LifecycleMonitor monitor)
0288: throws NoSuchConfigException, LifecycleException {
0289: if (!configurationId.isResolved()) {
0290: throw new IllegalArgumentException("Artifact "
0291: + configurationId + " is not fully resolved");
0292: }
0293: if (isLoaded(configurationId)) {
0294: // already loaded, so just mark the configuration as user loaded
0295: load(configurationId);
0296:
0297: monitor.finished();
0298: return new LifecycleResults();
0299: }
0300:
0301: // load the ConfigurationData for the new configuration
0302: ConfigurationData configurationData = null;
0303: try {
0304: configurationData = loadConfigurationData(configurationId,
0305: monitor);
0306: } catch (Exception e) {
0307: monitor.finished();
0308: throw new LifecycleException("load", configurationId, e);
0309: }
0310:
0311: // load the configuration
0312: LifecycleResults results = loadConfiguration(configurationData,
0313: monitor);
0314:
0315: return results;
0316: }
0317:
0318: public synchronized LifecycleResults loadConfiguration(
0319: ConfigurationData configurationData)
0320: throws NoSuchConfigException, LifecycleException {
0321: return loadConfiguration(configurationData,
0322: NullLifecycleMonitor.INSTANCE);
0323: }
0324:
0325: public synchronized LifecycleResults loadConfiguration(
0326: ConfigurationData configurationData,
0327: LifecycleMonitor monitor) throws NoSuchConfigException,
0328: LifecycleException {
0329: Artifact id = configurationData.getId();
0330: LifecycleResults results = new LifecycleResults();
0331: if (!isLoaded(id)) {
0332: // recursively load configurations from the new child to the parents
0333: LinkedHashMap configurationsToLoad = new LinkedHashMap();
0334: try {
0335: loadDepthFirst(configurationData, configurationsToLoad,
0336: monitor);
0337: } catch (Exception e) {
0338: monitor.finished();
0339: throw new LifecycleException("load", id, e);
0340: }
0341:
0342: // load and start the unloaded the gbean for each configuration (depth first)
0343: Map actuallyLoaded = new LinkedHashMap(configurationsToLoad
0344: .size());
0345: Artifact configurationId = null;
0346: try {
0347: for (Iterator iterator = configurationsToLoad
0348: .entrySet().iterator(); iterator.hasNext();) {
0349: Map.Entry entry = (Map.Entry) iterator.next();
0350: configurationId = (Artifact) entry.getKey();
0351: UnloadedConfiguration unloadedConfiguration = (UnloadedConfiguration) entry
0352: .getValue();
0353:
0354: monitor.loading(configurationId);
0355: Configuration configuration = load(
0356: unloadedConfiguration
0357: .getConfigurationData(),
0358: unloadedConfiguration
0359: .getResolvedParentIds(),
0360: actuallyLoaded);
0361: monitor.succeeded(configurationId);
0362:
0363: actuallyLoaded.put(configurationId, configuration);
0364: }
0365: } catch (Exception e) {
0366: monitor.failed(configurationId, e);
0367:
0368: // there was a problem, so we need to unload all configurations that were actually loaded
0369: for (Iterator iterator = actuallyLoaded.values()
0370: .iterator(); iterator.hasNext();) {
0371: Configuration configuration = (Configuration) iterator
0372: .next();
0373: unload(configuration);
0374: }
0375:
0376: monitor.finished();
0377: throw new LifecycleException("load", id, e);
0378: }
0379:
0380: // update the status of the loaded configurations
0381: addNewConfigurationsToModel(actuallyLoaded);
0382: results.setLoaded(actuallyLoaded.keySet());
0383: }
0384: load(id);
0385: monitor.finished();
0386: return results;
0387: }
0388:
0389: protected void load(Artifact configurationId)
0390: throws NoSuchConfigException {
0391: configurationModel.load(configurationId);
0392: }
0393:
0394: protected Configuration load(ConfigurationData configurationData,
0395: LinkedHashSet resolvedParentIds, Map loadedConfigurations)
0396: throws InvalidConfigException {
0397: Artifact configurationId = configurationData.getId();
0398: try {
0399: Collection parents = findParentConfigurations(
0400: resolvedParentIds, loadedConfigurations);
0401:
0402: Configuration configuration = new Configuration(parents,
0403: configurationData, new ConfigurationResolver(
0404: configurationData, repositories,
0405: artifactResolver), null);
0406: configuration.doStart();
0407: return configuration;
0408: } catch (Exception e) {
0409: throw new InvalidConfigException(
0410: "Error starting configuration gbean "
0411: + configurationId, e);
0412: }
0413: }
0414:
0415: private Collection findParentConfigurations(
0416: LinkedHashSet resolvedParentIds, Map loadedConfigurations)
0417: throws InvalidConfigException {
0418: LinkedHashMap parents = new LinkedHashMap();
0419: for (Iterator iterator = resolvedParentIds.iterator(); iterator
0420: .hasNext();) {
0421: Artifact resolvedArtifact = (Artifact) iterator.next();
0422:
0423: Configuration parent = null;
0424: if (loadedConfigurations.containsKey(resolvedArtifact)) {
0425: parent = (Configuration) loadedConfigurations
0426: .get(resolvedArtifact);
0427: } else if (isLoaded(resolvedArtifact)) {
0428: parent = getConfiguration(resolvedArtifact);
0429: } else {
0430: throw new InvalidConfigException(
0431: "Cound not find parent configuration: "
0432: + resolvedArtifact);
0433: }
0434:
0435: parents.put(resolvedArtifact, parent);
0436: }
0437: return parents.values();
0438: }
0439:
0440: private void addNewConfigurationsToModel(Map loadedConfigurations)
0441: throws NoSuchConfigException {
0442: for (Iterator iterator = loadedConfigurations.values()
0443: .iterator(); iterator.hasNext();) {
0444: Configuration configuration = (Configuration) iterator
0445: .next();
0446: addNewConfigurationToModel(configuration);
0447: }
0448: }
0449:
0450: protected void addNewConfigurationToModel(
0451: Configuration configuration) throws NoSuchConfigException {
0452: configurationModel.addConfiguation(configuration.getId(),
0453: getConfigurationIds(getLoadParents(configuration)),
0454: getConfigurationIds(getStartParents(configuration)));
0455: configurations.put(configuration.getId(), configuration);
0456: }
0457:
0458: protected LinkedHashSet getLoadParents(Configuration configuration) {
0459: LinkedHashSet loadParent = new LinkedHashSet(configuration
0460: .getClassParents());
0461: for (Iterator iterator = configuration.getChildren().iterator(); iterator
0462: .hasNext();) {
0463: Configuration childConfiguration = (Configuration) iterator
0464: .next();
0465: LinkedHashSet childLoadParent = getLoadParents(childConfiguration);
0466:
0467: // remove this configuration from the parent Ids since it will cause an infinite loop
0468: childLoadParent.remove(configuration);
0469:
0470: loadParent.addAll(childLoadParent);
0471: }
0472: return loadParent;
0473: }
0474:
0475: protected LinkedHashSet getStartParents(Configuration configuration) {
0476: LinkedHashSet startParent = new LinkedHashSet(configuration
0477: .getServiceParents());
0478: for (Iterator iterator = configuration.getChildren().iterator(); iterator
0479: .hasNext();) {
0480: Configuration childConfiguration = (Configuration) iterator
0481: .next();
0482: LinkedHashSet childStartParent = getStartParents(childConfiguration);
0483:
0484: // remove this configuration from the parent Ids since it will cause an infinite loop
0485: childStartParent.remove(configuration);
0486:
0487: startParent.addAll(childStartParent);
0488: }
0489: return startParent;
0490: }
0491:
0492: private static LinkedHashSet<Artifact> getConfigurationIds(
0493: Collection<Configuration> configurations) {
0494: LinkedHashSet<Artifact> configurationIds = new LinkedHashSet<Artifact>(
0495: configurations.size());
0496: for (Configuration configuration : configurations) {
0497: configurationIds.add(configuration.getId());
0498: }
0499: return configurationIds;
0500: }
0501:
0502: private synchronized void loadDepthFirst(
0503: ConfigurationData configurationData,
0504: LinkedHashMap<Artifact, UnloadedConfiguration> configurationsToLoad,
0505: LifecycleMonitor monitor) throws NoSuchConfigException,
0506: IOException, InvalidConfigException,
0507: MissingDependencyException {
0508: // if this parent hasn't already been processed, iterate into the parent
0509: Artifact configurationId = configurationData.getId();
0510: if (!configurationsToLoad.containsKey(configurationId)) {
0511: monitor.resolving(configurationId);
0512: LinkedHashSet<Artifact> resolvedParentIds = resolveParentIds(configurationData);
0513: monitor.succeeded(configurationId);
0514:
0515: for (Artifact parentId : resolvedParentIds) {
0516: // if this parent id hasn't already been loaded and is actually a configuration
0517: if (!isLoaded(parentId) && isConfiguration(parentId)) {
0518: ConfigurationData parentConfigurationData = loadConfigurationData(
0519: parentId, monitor);
0520: loadDepthFirst(parentConfigurationData,
0521: configurationsToLoad, monitor);
0522: }
0523: }
0524:
0525: // depth first - all unloaded parents have been added, now add this configuration
0526: configurationsToLoad.put(configurationId,
0527: new UnloadedConfiguration(configurationData,
0528: resolvedParentIds));
0529: }
0530: }
0531:
0532: public LinkedHashSet<Artifact> sort(List<Artifact> ids,
0533: LifecycleMonitor monitor) throws InvalidConfigException,
0534: IOException, NoSuchConfigException,
0535: MissingDependencyException {
0536: LinkedHashSet<Artifact> sorted = new LinkedHashSet<Artifact>();
0537: sort(ids, sorted, monitor);
0538: sorted.retainAll(ids);
0539: return sorted;
0540: }
0541:
0542: private void sort(Collection<Artifact> ids,
0543: LinkedHashSet<Artifact> sorted, LifecycleMonitor monitor)
0544: throws InvalidConfigException, IOException,
0545: NoSuchConfigException, MissingDependencyException {
0546: for (Artifact id : ids) {
0547: if (!sorted.contains(id)) {
0548: ConfigurationData data = loadConfigurationData(id,
0549: monitor);
0550: LinkedHashSet<Artifact> parents = resolveParentIds(data);
0551: sort(parents, sorted, monitor);
0552: sorted.add(id);
0553: }
0554: }
0555: }
0556:
0557: private ConfigurationData loadConfigurationData(
0558: Artifact configurationId, LifecycleMonitor monitor)
0559: throws NoSuchConfigException, IOException,
0560: InvalidConfigException {
0561: List<ConfigurationStore> storeSnapshot = getStoreList();
0562:
0563: monitor.addConfiguration(configurationId);
0564: monitor.reading(configurationId);
0565: for (ConfigurationStore store : storeSnapshot) {
0566: if (store.containsConfiguration(configurationId)) {
0567: ConfigurationData configurationData = store
0568: .loadConfiguration(configurationId);
0569: monitor.succeeded(configurationId);
0570: return configurationData;
0571: }
0572: }
0573: NoSuchConfigException exception = new NoSuchConfigException(
0574: configurationId);
0575: monitor.failed(configurationId, exception);
0576: throw exception;
0577: }
0578:
0579: private LinkedHashSet<Artifact> resolveParentIds(
0580: ConfigurationData configurationData)
0581: throws MissingDependencyException, InvalidConfigException {
0582: Environment environment = configurationData.getEnvironment();
0583:
0584: LinkedHashSet<Artifact> parentIds = new LinkedHashSet<Artifact>();
0585: List<Dependency> dependencies = new ArrayList<Dependency>(
0586: environment.getDependencies());
0587: for (ListIterator<Dependency> iterator = dependencies
0588: .listIterator(); iterator.hasNext();) {
0589: Dependency dependency = iterator.next();
0590: Artifact resolvedArtifact = artifactResolver
0591: .resolveInClassLoader(dependency.getArtifact());
0592: if (isConfiguration(resolvedArtifact)) {
0593: parentIds.add(resolvedArtifact);
0594:
0595: // update the dependency list to contain the resolved artifact
0596: dependency = new Dependency(resolvedArtifact,
0597: dependency.getImportType());
0598: iterator.set(dependency);
0599: } else if (dependency.getImportType() == ImportType.SERVICES) {
0600: // Service depdendencies require that the depdencency be a configuration
0601: throw new InvalidConfigException(
0602: "Dependency does not have services: "
0603: + resolvedArtifact);
0604: }
0605: }
0606:
0607: for (Iterator iterator = configurationData
0608: .getChildConfigurations().values().iterator(); iterator
0609: .hasNext();) {
0610: ConfigurationData childConfigurationData = (ConfigurationData) iterator
0611: .next();
0612: LinkedHashSet<Artifact> childParentIds = resolveParentIds(childConfigurationData);
0613: // remove this configuration's id from the parent Ids since it will cause an infinite loop
0614: childParentIds.remove(configurationData.getId());
0615: parentIds.addAll(childParentIds);
0616: }
0617: return parentIds;
0618: }
0619:
0620: private static class UnloadedConfiguration {
0621: private final ConfigurationData configurationData;
0622: private final LinkedHashSet resolvedParentIds;
0623:
0624: public UnloadedConfiguration(
0625: ConfigurationData configurationData,
0626: LinkedHashSet resolvedParentIds) {
0627: this .configurationData = configurationData;
0628: this .resolvedParentIds = resolvedParentIds;
0629: }
0630:
0631: public ConfigurationData getConfigurationData() {
0632: return configurationData;
0633: }
0634:
0635: public LinkedHashSet getResolvedParentIds() {
0636: return resolvedParentIds;
0637: }
0638: }
0639:
0640: public synchronized LifecycleResults startConfiguration(Artifact id)
0641: throws NoSuchConfigException, LifecycleException {
0642: return startConfiguration(id, NullLifecycleMonitor.INSTANCE);
0643: }
0644:
0645: public synchronized LifecycleResults startConfiguration(
0646: Artifact id, LifecycleMonitor monitor)
0647: throws NoSuchConfigException, LifecycleException {
0648: if (!id.isResolved()) {
0649: throw new IllegalArgumentException("Artifact " + id
0650: + " is not fully resolved");
0651: }
0652: LinkedHashSet unstartedConfigurations = configurationModel
0653: .start(id);
0654:
0655: addConfigurationsToMonitor(monitor, unstartedConfigurations);
0656:
0657: LifecycleResults results = new LifecycleResults();
0658: Artifact configurationId = null;
0659: try {
0660: for (Iterator iterator = unstartedConfigurations.iterator(); iterator
0661: .hasNext();) {
0662: configurationId = (Artifact) iterator.next();
0663: Configuration configuration = getConfiguration(configurationId);
0664:
0665: monitor.starting(configurationId);
0666: start(configuration);
0667: monitor.succeeded(configurationId);
0668:
0669: results.addStarted(configurationId);
0670: }
0671: } catch (Exception e) {
0672: monitor.failed(configurationId, e);
0673: configurationModel.stop(id);
0674:
0675: for (Iterator iterator = results.getStarted().iterator(); iterator
0676: .hasNext();) {
0677: configurationId = (Artifact) iterator.next();
0678: Configuration configuration = getConfiguration(configurationId);
0679: monitor.stopping(configurationId);
0680: stop(configuration);
0681: monitor.succeeded(configurationId);
0682: }
0683: monitor.finished();
0684: throw new LifecycleException("start", id, e);
0685: }
0686: monitor.finished();
0687: return results;
0688: }
0689:
0690: protected void start(Configuration configuration) throws Exception {
0691: throw new UnsupportedOperationException();
0692: }
0693:
0694: public synchronized LifecycleResults stopConfiguration(Artifact id)
0695: throws NoSuchConfigException {
0696: return stopConfiguration(id, NullLifecycleMonitor.INSTANCE);
0697: }
0698:
0699: public synchronized LifecycleResults stopConfiguration(Artifact id,
0700: LifecycleMonitor monitor) throws NoSuchConfigException {
0701: if (!id.isResolved()) {
0702: throw new IllegalArgumentException("Artifact " + id
0703: + " is not fully resolved");
0704: }
0705: LinkedHashSet stopList = configurationModel.stop(id);
0706:
0707: addConfigurationsToMonitor(monitor, stopList);
0708:
0709: LifecycleResults results = new LifecycleResults();
0710: for (Iterator iterator = stopList.iterator(); iterator
0711: .hasNext();) {
0712: Artifact configurationId = (Artifact) iterator.next();
0713: Configuration configuration = getConfiguration(configurationId);
0714:
0715: monitor.stopping(configurationId);
0716: stop(configuration);
0717: monitor.succeeded(configurationId);
0718:
0719: results.addStopped(configurationId);
0720: }
0721:
0722: monitor.finished();
0723: return results;
0724: }
0725:
0726: protected void stop(Configuration configuration) {
0727: // Don't throw an exception because we call this from unload to be sure that all
0728: // unloaded configurations are stopped first
0729: }
0730:
0731: public synchronized LifecycleResults restartConfiguration(
0732: Artifact id) throws NoSuchConfigException,
0733: LifecycleException {
0734: return restartConfiguration(id, NullLifecycleMonitor.INSTANCE);
0735: }
0736:
0737: public synchronized LifecycleResults restartConfiguration(
0738: Artifact id, LifecycleMonitor monitor)
0739: throws NoSuchConfigException, LifecycleException {
0740: if (!id.isResolved()) {
0741: throw new IllegalArgumentException("Artifact " + id
0742: + " is not fully resolved");
0743: }
0744: // get a sorted list of configurations to restart
0745: LinkedHashSet restartList = configurationModel.restart(id);
0746:
0747: addConfigurationsToMonitor(monitor, restartList);
0748:
0749: // stop the configuations
0750: LifecycleResults results = new LifecycleResults();
0751: for (Iterator iterator = restartList.iterator(); iterator
0752: .hasNext();) {
0753: Artifact configurationId = (Artifact) iterator.next();
0754: Configuration configuration = getConfiguration(configurationId);
0755: monitor.stopping(configurationId);
0756: stop(configuration);
0757: monitor.succeeded(configurationId);
0758: results.addStopped(configurationId);
0759: }
0760:
0761: // reverse the list
0762: restartList = reverse(restartList);
0763:
0764: // restart the configurations
0765: Set skip = new HashSet();
0766: for (Iterator iterator = restartList.iterator(); iterator
0767: .hasNext();) {
0768: Artifact configurationId = (Artifact) iterator.next();
0769:
0770: // skip the configurations that have alredy failed or are children of failed configurations
0771: if (skip.contains(configurationId)) {
0772: continue;
0773: }
0774:
0775: // try to start the configuation
0776: try {
0777: Configuration configuration = getConfiguration(configurationId);
0778: monitor.starting(configurationId);
0779: start(configuration);
0780: monitor.succeeded(configurationId);
0781: results.addStarted(configurationId);
0782: } catch (Exception e) {
0783: // the configuraiton failed to restart
0784: results.addFailed(configurationId, e);
0785: monitor.failed(configurationId, e);
0786: skip.add(configurationId);
0787:
0788: // officially stop the configuration in the model (without gc)
0789: LinkedHashSet stopList = configurationModel.stop(
0790: configurationId, false);
0791:
0792: // all of the configurations to be stopped must be in our restart list, or the model is corrupt
0793: if (!restartList.containsAll(stopList)) {
0794: throw new AssertionError(
0795: "Configuration data model is corrupt. You must restart your server.");
0796: }
0797:
0798: // add the children of the failed configuration to the results as stopped
0799: for (Iterator iterator1 = stopList.iterator(); iterator1
0800: .hasNext();) {
0801: Artifact failedId = (Artifact) iterator1.next();
0802:
0803: // if any of the failed configuration is in the restarted set, the model is
0804: // corrupt because we started a child before a parent
0805: if (results.wasStarted(failedId)) {
0806: throw new AssertionError(
0807: "Configuration data model is corrupt. You must restart your server.");
0808: }
0809:
0810: skip.add(failedId);
0811: }
0812: }
0813: }
0814:
0815: monitor.finished();
0816: if (!results.wasStarted(id)) {
0817: throw new LifecycleException("restart", id, results);
0818: }
0819: return results;
0820: }
0821:
0822: public synchronized LifecycleResults unloadConfiguration(Artifact id)
0823: throws NoSuchConfigException {
0824: return unloadConfiguration(id, NullLifecycleMonitor.INSTANCE);
0825: }
0826:
0827: public synchronized LifecycleResults unloadConfiguration(
0828: Artifact id, LifecycleMonitor monitor)
0829: throws NoSuchConfigException {
0830: if (!id.isResolved()) {
0831: throw new IllegalArgumentException("Artifact " + id
0832: + " is not fully resolved");
0833: }
0834: Set started = configurationModel.getStarted();
0835: LinkedHashSet unloadList = configurationModel.unload(id);
0836:
0837: addConfigurationsToMonitor(monitor, unloadList);
0838:
0839: LifecycleResults results = new LifecycleResults();
0840: for (Iterator iterator = unloadList.iterator(); iterator
0841: .hasNext();) {
0842: Artifact configurationId = (Artifact) iterator.next();
0843: Configuration configuration = getConfiguration(configurationId);
0844:
0845: // first make sure it is stopped
0846: if (started.contains(configurationId)) {
0847: monitor.stopping(configurationId);
0848: stop(configuration);
0849: monitor.succeeded(configurationId);
0850: results.addStopped(configurationId);
0851: } else {
0852: // call stop just to be sure the beans aren't running
0853: stop(configuration);
0854: }
0855:
0856: // now unload it
0857: monitor.unloading(configurationId);
0858: unload(configuration);
0859: monitor.succeeded(configurationId);
0860: results.addUnloaded(configurationId);
0861:
0862: // clean up the model
0863: removeConfigurationFromModel(configurationId);
0864: }
0865: monitor.finished();
0866: return results;
0867: }
0868:
0869: protected void removeConfigurationFromModel(Artifact configurationId)
0870: throws NoSuchConfigException {
0871: if (configurationModel.containsConfiguration(configurationId)) {
0872: configurationModel.removeConfiguration(configurationId);
0873: }
0874: configurations.remove(configurationId);
0875: }
0876:
0877: protected void unload(Configuration configuration) {
0878: try {
0879: configuration.doStop();
0880: } catch (Exception e) {
0881: log.debug("Problem unloading config: "
0882: + configuration.getId(), e);
0883: }
0884: }
0885:
0886: public synchronized LifecycleResults reloadConfiguration(Artifact id)
0887: throws NoSuchConfigException, LifecycleException {
0888: return reloadConfiguration(id, NullLifecycleMonitor.INSTANCE);
0889: }
0890:
0891: public synchronized LifecycleResults reloadConfiguration(
0892: Artifact id, LifecycleMonitor monitor)
0893: throws NoSuchConfigException, LifecycleException {
0894: return reloadConfiguration(id, id.getVersion(), monitor);
0895: }
0896:
0897: public synchronized LifecycleResults reloadConfiguration(
0898: Artifact id, Version version) throws NoSuchConfigException,
0899: LifecycleException {
0900: return reloadConfiguration(id, version,
0901: NullLifecycleMonitor.INSTANCE);
0902: }
0903:
0904: public synchronized LifecycleResults reloadConfiguration(
0905: Artifact id, Version version, LifecycleMonitor monitor)
0906: throws NoSuchConfigException, LifecycleException {
0907: if (!id.isResolved()) {
0908: throw new IllegalArgumentException("Artifact " + id
0909: + " is not fully resolved");
0910: }
0911: Configuration configuration = getConfiguration(id);
0912: if (configuration == null) { // The configuration to reload is not currently loaded
0913: ConfigurationData data = null;
0914: List storeSnapshot = getStoreList();
0915: for (int i = 0; i < storeSnapshot.size(); i++) {
0916: ConfigurationStore store = (ConfigurationStore) storeSnapshot
0917: .get(i);
0918: if (store.containsConfiguration(id)) {
0919: try {
0920: data = store.loadConfiguration(id);
0921: } catch (Exception e) {
0922: log.warn(
0923: "Unable to load existing configuration "
0924: + id + " from config store", e);
0925: }
0926: }
0927: }
0928: if (data == null) {
0929: throw new NoSuchConfigException(id);
0930: }
0931: UnloadedConfiguration existingUnloadedConfiguration = new UnloadedConfiguration(
0932: data, new LinkedHashSet());
0933: Artifact newId = new Artifact(id.getGroupId(), id
0934: .getArtifactId(), version, id.getType());
0935: ConfigurationData newData = null;
0936: try {
0937: newData = loadConfigurationData(newId, monitor);
0938: } catch (Exception e) {
0939: monitor.finished();
0940: throw new LifecycleException("reload", id, e);
0941: }
0942:
0943: return reloadConfiguration(existingUnloadedConfiguration,
0944: newData, monitor);
0945: } else { // The configuration to reload is loaded
0946: ConfigurationData existingConfigurationData = configuration
0947: .getConfigurationData();
0948: UnloadedConfiguration existingUnloadedConfiguration = new UnloadedConfiguration(
0949: existingConfigurationData,
0950: getResolvedParentIds(configuration));
0951:
0952: Artifact newId = new Artifact(id.getGroupId(), id
0953: .getArtifactId(), version, id.getType());
0954:
0955: // reload the ConfigurationData from a store
0956: ConfigurationData configurationData = null;
0957: try {
0958: configurationData = loadConfigurationData(newId,
0959: monitor);
0960: } catch (Exception e) {
0961: monitor.finished();
0962: throw new LifecycleException("reload", id, e);
0963: }
0964:
0965: return reloadConfiguration(existingUnloadedConfiguration,
0966: configurationData, monitor);
0967: }
0968: }
0969:
0970: public synchronized LifecycleResults reloadConfiguration(
0971: ConfigurationData configurationData)
0972: throws LifecycleException, NoSuchConfigException {
0973: return reloadConfiguration(configurationData,
0974: NullLifecycleMonitor.INSTANCE);
0975: }
0976:
0977: public synchronized LifecycleResults reloadConfiguration(
0978: ConfigurationData configurationData,
0979: LifecycleMonitor monitor) throws LifecycleException,
0980: NoSuchConfigException {
0981: Configuration configuration = getConfiguration(configurationData
0982: .getId());
0983: if (configuration == null) {
0984: throw new NoSuchConfigException(configurationData.getId());
0985: }
0986: ConfigurationData existingConfigurationData = configuration
0987: .getConfigurationData();
0988: UnloadedConfiguration existingUnloadedConfiguration = new UnloadedConfiguration(
0989: existingConfigurationData,
0990: getResolvedParentIds(configuration));
0991: return reloadConfiguration(existingUnloadedConfiguration,
0992: configurationData, monitor);
0993: }
0994:
0995: private boolean hasHardDependency(Artifact configurationId,
0996: ConfigurationData configurationData) {
0997: for (Iterator iterator = configurationData.getEnvironment()
0998: .getDependencies().iterator(); iterator.hasNext();) {
0999: Dependency dependency = (Dependency) iterator.next();
1000: Artifact artifact = dependency.getArtifact();
1001: if (artifact.getVersion() != null
1002: && artifact.matches(configurationId)) {
1003: return true;
1004: }
1005: }
1006:
1007: for (Iterator iterator = configurationData
1008: .getChildConfigurations().values().iterator(); iterator
1009: .hasNext();) {
1010: ConfigurationData childConfigurationData = (ConfigurationData) iterator
1011: .next();
1012: if (hasHardDependency(configurationId,
1013: childConfigurationData)) {
1014: return true;
1015: }
1016: }
1017: return false;
1018: }
1019:
1020: // todo this method ignores garbage collection of configurations
1021: private LifecycleResults reloadConfiguration(
1022: UnloadedConfiguration existingUnloadedConfiguration,
1023: ConfigurationData newConfigurationData,
1024: LifecycleMonitor monitor) throws LifecycleException,
1025: NoSuchConfigException {
1026: boolean force = false;
1027:
1028: Artifact existingConfigurationId = existingUnloadedConfiguration
1029: .getConfigurationData().getId();
1030: Artifact newConfigurationId = newConfigurationData.getId();
1031:
1032: //
1033: // recursively load the new configuration; this will catch any new parents
1034: //
1035: LinkedHashMap newConfigurations = new LinkedHashMap();
1036: try {
1037: loadDepthFirst(newConfigurationData, newConfigurations,
1038: monitor);
1039: } catch (Exception e) {
1040: monitor.finished();
1041: throw new LifecycleException("reload", newConfigurationId,
1042: e);
1043: }
1044:
1045: //
1046: // get a list of the started configuration, so we can restart them later
1047: //
1048: Set started = configurationModel.getStarted();
1049:
1050: //
1051: // get a list of the child configurations that will need to reload
1052: //
1053: // note: we are iterating in reverse order
1054: LinkedHashMap existingParents = new LinkedHashMap();
1055: LinkedHashMap reloadChildren = new LinkedHashMap();
1056: for (Iterator iterator = reverse(
1057: configurationModel.reload(existingConfigurationId))
1058: .iterator(); iterator.hasNext();) {
1059: Artifact configurationId = (Artifact) iterator.next();
1060:
1061: if (configurationId.equals(existingConfigurationId)) {
1062: continue;
1063: }
1064:
1065: // if new configurations contains the child something we have a circular dependency
1066: if (newConfigurations.containsKey(configurationId)) {
1067: throw new LifecycleException("reload",
1068: newConfigurationId, new IllegalStateException(
1069: "Circular depenency between "
1070: + newConfigurationId + " and "
1071: + configurationId));
1072: }
1073:
1074: Configuration configuration = getConfiguration(configurationId);
1075: ConfigurationData configurationData = configuration
1076: .getConfigurationData();
1077:
1078: // save off the exising resolved parent ids in case we need to restore this configuration
1079: LinkedHashSet existingParentIds = getResolvedParentIds(configuration);
1080: existingParents.put(configurationId, existingParentIds);
1081:
1082: // check that the child doen't have a hard dependency on the old configuration
1083: LinkedHashSet resolvedParentIds = null;
1084: if (hasHardDependency(existingConfigurationId,
1085: configurationData)) {
1086: if (force) {
1087: throw new LifecycleException(
1088: "reload",
1089: newConfigurationId,
1090: new IllegalStateException(
1091: "Existing configuration "
1092: + configurationId
1093: + " has a hard dependency on the current version of this configuration "
1094: + existingConfigurationId));
1095: }
1096:
1097: // we leave the resolved parent ids null to signal that we should not reload the configuration
1098: resolvedParentIds = null;
1099: } else {
1100: resolvedParentIds = new LinkedHashSet(existingParentIds);
1101: resolvedParentIds.remove(existingConfigurationId);
1102: resolvedParentIds.add(newConfigurationId);
1103: }
1104:
1105: reloadChildren.put(configurationId,
1106: new UnloadedConfiguration(configurationData,
1107: resolvedParentIds));
1108: monitor.addConfiguration(configurationId);
1109: }
1110:
1111: //
1112: // unload the children
1113: //
1114:
1115: // note: we are iterating in reverse order
1116: LifecycleResults results = new LifecycleResults();
1117: for (Iterator iterator = reverse(reloadChildren).keySet()
1118: .iterator(); iterator.hasNext();) {
1119: Artifact configurationId = (Artifact) iterator.next();
1120: Configuration configuration = getConfiguration(configurationId);
1121:
1122: // first make sure it is stopped
1123: if (started.contains(configurationId)) {
1124: monitor.stopping(configurationId);
1125: stop(configuration);
1126: monitor.succeeded(configurationId);
1127: results.addStopped(configurationId);
1128: } else {
1129: // call stop just to be sure the beans aren't running
1130: stop(configuration);
1131: }
1132:
1133: // now unload it
1134: monitor.unloading(configurationId);
1135: unload(configuration);
1136: monitor.succeeded(configurationId);
1137: results.addUnloaded(configurationId);
1138: }
1139:
1140: //
1141: // unload the existing config
1142: //
1143: Configuration existingConfiguration = getConfiguration(existingConfigurationId);
1144: if (started.contains(existingConfigurationId)) {
1145: monitor.stopping(existingConfigurationId);
1146: stop(existingConfiguration);
1147: monitor.succeeded(existingConfigurationId);
1148: results.addStopped(existingConfigurationId);
1149: } else if (existingConfiguration != null) {
1150: // call stop just to be sure the beans aren't running
1151: stop(existingConfiguration);
1152: }
1153: if (existingConfiguration != null) {
1154: monitor.unloading(existingConfigurationId);
1155: unload(existingConfiguration);
1156: monitor.succeeded(existingConfigurationId);
1157: results.addUnloaded(existingConfigurationId);
1158: }
1159:
1160: //
1161: // load the new configurations
1162: //
1163: boolean reinstatedExisting = false;
1164: /* reduce variable scope */
1165: {
1166: Map loadedParents = new LinkedHashMap();
1167: Map startedParents = new LinkedHashMap();
1168: Configuration newConfiguration = null;
1169: Artifact configurationId = null;
1170: try {
1171: //
1172: // load all of the new configurations
1173: //
1174: for (Iterator iterator = newConfigurations.entrySet()
1175: .iterator(); iterator.hasNext();) {
1176: Map.Entry entry = (Map.Entry) iterator.next();
1177: configurationId = (Artifact) entry.getKey();
1178: UnloadedConfiguration unloadedConfiguration = (UnloadedConfiguration) entry
1179: .getValue();
1180:
1181: monitor.loading(configurationId);
1182: Configuration configuration = load(
1183: unloadedConfiguration
1184: .getConfigurationData(),
1185: unloadedConfiguration
1186: .getResolvedParentIds(),
1187: loadedParents);
1188: monitor.succeeded(configurationId);
1189:
1190: if (configurationId.equals(newConfigurationId)) {
1191: newConfiguration = configuration;
1192: reloadingConfiguration = configuration;
1193: } else {
1194: loadedParents.put(configurationId,
1195: configuration);
1196: }
1197: }
1198:
1199: if (newConfiguration == null) {
1200: AssertionError cause = new AssertionError(
1201: "Internal error: configuration was not load");
1202: results.addFailed(newConfigurationId, cause);
1203: throw new LifecycleException("reload",
1204: newConfigurationId, results);
1205: }
1206:
1207: //
1208: // start the new configurations if the old one was running
1209: //
1210: if (started.contains(existingConfigurationId)) {
1211:
1212: // determine which of the parents we need to start
1213: LinkedHashSet startList = new LinkedHashSet();
1214: for (Iterator iterator = getStartParents(
1215: newConfiguration).iterator(); iterator
1216: .hasNext();) {
1217: Configuration serviceParent = (Configuration) iterator
1218: .next();
1219: if (loadedParents.containsKey(serviceParent
1220: .getId())) {
1221: startList.add(serviceParent);
1222: }
1223: }
1224:
1225: // start the new parents
1226: for (Iterator iterator = startList.iterator(); iterator
1227: .hasNext();) {
1228: Configuration startParent = (Configuration) iterator
1229: .next();
1230: monitor.starting(configurationId);
1231: start(startParent);
1232: monitor.succeeded(configurationId);
1233:
1234: startedParents
1235: .put(configurationId, startParent);
1236: }
1237:
1238: // start the new configuration
1239: monitor.starting(newConfigurationId);
1240: start(newConfiguration);
1241: monitor.succeeded(newConfigurationId);
1242: }
1243:
1244: //
1245: // update the results
1246: //
1247: results.setLoaded(loadedParents.keySet());
1248: results.addLoaded(newConfigurationId);
1249: if (started.contains(existingConfigurationId)) {
1250: results.setStarted(startedParents.keySet());
1251: results.addStarted(newConfigurationId);
1252: }
1253:
1254: //
1255: // update the model
1256: //
1257:
1258: // add all of the new configurations the model
1259: addNewConfigurationsToModel(loadedParents);
1260:
1261: // now ugrade the existing node in the model
1262: if (configurationModel
1263: .containsConfiguration(existingConfigurationId)) {
1264: configurationModel
1265: .upgradeConfiguration(
1266: existingConfigurationId,
1267: newConfigurationId,
1268: getConfigurationIds(getLoadParents(newConfiguration)),
1269: getConfigurationIds(getStartParents(newConfiguration)));
1270: } else {
1271: configurationModel
1272: .addConfiguation(
1273: newConfigurationId,
1274: getConfigurationIds(getLoadParents(newConfiguration)),
1275: getConfigurationIds(getStartParents(newConfiguration)));
1276: load(newConfigurationId);
1277: }
1278:
1279: // replace the configuraiton in he configurations map
1280: configurations.remove(existingConfiguration);
1281: configurations
1282: .put(newConfigurationId, newConfiguration);
1283:
1284: // migrate the configuration settings
1285: migrateConfiguration(existingConfigurationId,
1286: newConfigurationId, newConfiguration, started
1287: .contains(existingConfigurationId));
1288: } catch (Exception e) {
1289: monitor.failed(configurationId, e);
1290: results.addFailed(configurationId, e);
1291:
1292: //
1293: // stop and unload all configurations that were actually loaded
1294: //
1295: for (Iterator iterator = startedParents.values()
1296: .iterator(); iterator.hasNext();) {
1297: Configuration configuration = (Configuration) iterator
1298: .next();
1299: stop(configuration);
1300: }
1301: for (Iterator iterator = loadedParents.values()
1302: .iterator(); iterator.hasNext();) {
1303: Configuration configuration = (Configuration) iterator
1304: .next();
1305: unload(configuration);
1306: }
1307:
1308: // stop and unload the newConfiguration
1309: if (newConfiguration != null) {
1310: stop(newConfiguration);
1311: unload(newConfiguration);
1312: }
1313:
1314: //
1315: // atempt to reinstate the old configuation
1316: //
1317: Configuration configuration = null;
1318: try {
1319: configuration = load(existingUnloadedConfiguration
1320: .getConfigurationData(),
1321: existingUnloadedConfiguration
1322: .getResolvedParentIds(),
1323: Collections.EMPTY_MAP);
1324: reloadingConfiguration = configuration;
1325: // if the configuration was started before restart it
1326: if (started.contains(existingConfigurationId)) {
1327: start(configuration);
1328: results.addStarted(existingConfigurationId);
1329: }
1330:
1331: // don't mark as loded until start completes as it may thorw an exception
1332: results.addLoaded(existingConfigurationId);
1333:
1334: configurations.put(existingConfigurationId,
1335: configuration);
1336:
1337: reinstatedExisting = true;
1338: } catch (Exception ignored) {
1339: monitor.failed(existingConfigurationId, e);
1340:
1341: // we tried our best
1342: if (configuration != null) {
1343: unload(configuration);
1344: }
1345:
1346: //
1347: // cleanup the model
1348: //
1349: for (Iterator iterator = results.getUnloaded()
1350: .iterator(); iterator.hasNext();) {
1351: Artifact childId = (Artifact) iterator.next();
1352: configurationModel.unload(childId);
1353: removeConfigurationFromModel(childId);
1354: }
1355:
1356: throw new LifecycleException("reload",
1357: newConfigurationId, results);
1358: }
1359: } finally {
1360: reloadingConfiguration = null;
1361: }
1362: }
1363:
1364: //
1365: // reload as many child configurations as possible
1366: //
1367: Set skip = new HashSet();
1368: for (Iterator iterator = reloadChildren.entrySet().iterator(); iterator
1369: .hasNext();) {
1370: Map.Entry entry = (Map.Entry) iterator.next();
1371: Artifact configurationId = (Artifact) entry.getKey();
1372: UnloadedConfiguration unloadedConfiguration = (UnloadedConfiguration) entry
1373: .getValue();
1374:
1375: // skip the configurations that have alredy failed or are children of failed configurations
1376: if (skip.contains(configurationId)) {
1377: continue;
1378: }
1379:
1380: // try to load the configuation
1381: Configuration configuration = null;
1382: try {
1383: // get the correct resolved parent ids based on if we are loading with the new config id or the existing one
1384: LinkedHashSet resolvedParentIds;
1385: if (!reinstatedExisting) {
1386: resolvedParentIds = unloadedConfiguration
1387: .getResolvedParentIds();
1388: } else {
1389: resolvedParentIds = (LinkedHashSet) existingParents
1390: .get(configurationId);
1391: }
1392:
1393: // if the resolved parent ids is null, then we are not supposed to reload this configuration
1394: if (resolvedParentIds != null) {
1395: monitor.loading(configurationId);
1396: configuration = load(unloadedConfiguration
1397: .getConfigurationData(), resolvedParentIds,
1398: Collections.EMPTY_MAP);
1399: reloadingConfiguration = configuration;
1400: monitor.succeeded(configurationId);
1401:
1402: // if the configuration was started before restart it
1403: if (started.contains(configurationId)) {
1404: monitor.starting(configurationId);
1405: start(configuration);
1406: monitor.succeeded(configurationId);
1407: results.addStarted(configurationId);
1408: }
1409:
1410: // don't mark as loded until start completes as it may thow an exception
1411: results.addLoaded(configurationId);
1412:
1413: configurations.put(configurationId, configuration);
1414: } else {
1415: removeConfigurationFromModel(configurationId);
1416: }
1417: } catch (Exception e) {
1418: // the configuraiton failed to restart
1419: results.addFailed(configurationId, e);
1420: monitor.failed(configurationId, e);
1421: skip.add(configurationId);
1422:
1423: // unload the configuration if it was loaded and failed in start
1424: if (configuration != null) {
1425: unload(configuration);
1426: }
1427:
1428: // officially unload the configuration in the model (without gc)
1429: LinkedHashSet unloadList = configurationModel.unload(
1430: configurationId, false);
1431: configurationModel.removeConfiguration(configurationId);
1432:
1433: // all of the configurations to be unloaded must be in our unloaded list, or the model is corrupt
1434: if (!reloadChildren.keySet().containsAll(unloadList)) {
1435: throw new AssertionError(
1436: "Configuration data model is corrupt. You must restart your server.");
1437: }
1438:
1439: // add the children of the failed configuration to the results as unloaded
1440: for (Iterator iterator1 = unloadList.iterator(); iterator1
1441: .hasNext();) {
1442: Artifact failedId = (Artifact) iterator1.next();
1443:
1444: // if any of the failed configuration are in the reloaded set, the model is
1445: // corrupt because we loaded a child before a parent
1446: if (results.wasLoaded(failedId)) {
1447: throw new AssertionError(
1448: "Configuration data model is corrupt. You must restart your server.");
1449: }
1450:
1451: skip.add(failedId);
1452: }
1453: } finally {
1454: reloadingConfiguration = null;
1455: }
1456: }
1457:
1458: //
1459: // If nothing failed, delete all the unloaded modules that weren't reloaded
1460: //
1461: if (!results.wasLoaded(existingConfigurationId)
1462: && !results.wasFailed(existingConfigurationId)) {
1463: try {
1464: uninstallConfiguration(existingConfigurationId);
1465: } catch (IOException e) {
1466: log.error("Unable to uninstall configuration "
1467: + existingConfigurationId, e);
1468: }
1469: }
1470:
1471: monitor.finished();
1472: if (results.wasFailed(newConfigurationId)
1473: || !results.wasLoaded(newConfigurationId)) {
1474: throw new LifecycleException("restart", newConfigurationId,
1475: results);
1476: }
1477: return results;
1478: }
1479:
1480: protected void migrateConfiguration(Artifact oldName,
1481: Artifact newName, Configuration configuration,
1482: boolean running) throws NoSuchConfigException {
1483: }
1484:
1485: private static LinkedHashSet getResolvedParentIds(
1486: Configuration configuration) {
1487: LinkedHashSet resolvedParentIds = new LinkedHashSet();
1488: for (Iterator iterator = configuration.getClassParents()
1489: .iterator(); iterator.hasNext();) {
1490: Configuration classParent = (Configuration) iterator.next();
1491: resolvedParentIds.add(classParent.getId());
1492: }
1493: for (Iterator iterator = configuration.getServiceParents()
1494: .iterator(); iterator.hasNext();) {
1495: Configuration serviceParent = (Configuration) iterator
1496: .next();
1497: resolvedParentIds.add(serviceParent.getId());
1498: }
1499: for (Iterator iterator = configuration.getChildren().iterator(); iterator
1500: .hasNext();) {
1501: Configuration child = (Configuration) iterator.next();
1502: resolvedParentIds.addAll(getResolvedParentIds(child));
1503: }
1504:
1505: return resolvedParentIds;
1506: }
1507:
1508: public synchronized void uninstallConfiguration(
1509: Artifact configurationId) throws IOException,
1510: NoSuchConfigException {
1511: if (!configurationId.isResolved()) {
1512: throw new IllegalArgumentException("Artifact "
1513: + configurationId + " is not fully resolved");
1514: }
1515: if (configurations.containsKey(configurationId)) {
1516: if (isRunning(configurationId)) {
1517: stopConfiguration(configurationId);
1518: }
1519: if (isLoaded((configurationId))) {
1520: unloadConfiguration(configurationId);
1521: }
1522: }
1523:
1524: uninstall(configurationId);
1525: List storeSnapshot = getStoreList();
1526: for (int i = 0; i < storeSnapshot.size(); i++) {
1527: ConfigurationStore store = (ConfigurationStore) storeSnapshot
1528: .get(i);
1529: if (store.containsConfiguration(configurationId)) {
1530: store.uninstall(configurationId);
1531: }
1532: }
1533:
1534: removeConfigurationFromModel(configurationId);
1535: notifyWatchers(configurationId);
1536: }
1537:
1538: protected void uninstall(Artifact configurationId) {
1539: //child class can override this method
1540: }
1541:
1542: private void notifyWatchers(Artifact id) {
1543: for (Iterator it = watchers.iterator(); it.hasNext();) {
1544: DeploymentWatcher watcher = (DeploymentWatcher) it.next();
1545: watcher.undeployed(id);
1546: }
1547: }
1548:
1549: public ArtifactResolver getArtifactResolver() {
1550: return artifactResolver;
1551: }
1552:
1553: /**
1554: * this configuration manager never starts configurations.
1555: *
1556: * @return false
1557: */
1558: public boolean isOnline() {
1559: return false;
1560: }
1561:
1562: public void setOnline(boolean online) {
1563: }
1564:
1565: protected List getStoreList() {
1566: return new ArrayList(stores);
1567: }
1568:
1569: private static void addConfigurationsToMonitor(
1570: LifecycleMonitor monitor, LinkedHashSet configurations) {
1571: for (Iterator iterator = configurations.iterator(); iterator
1572: .hasNext();) {
1573: Artifact configurationId = (Artifact) iterator.next();
1574: monitor.addConfiguration(configurationId);
1575: }
1576: }
1577:
1578: private static LinkedHashSet reverse(LinkedHashSet set) {
1579: ArrayList reverseList = new ArrayList(set);
1580: Collections.reverse(reverseList);
1581: set = new LinkedHashSet(reverseList);
1582: return set;
1583: }
1584:
1585: private static LinkedHashMap reverse(LinkedHashMap map) {
1586: ArrayList reverseEntrySet = new ArrayList(map.entrySet());
1587: Collections.reverse(reverseEntrySet);
1588:
1589: map = new LinkedHashMap(reverseEntrySet.size());
1590: for (Iterator iterator = reverseEntrySet.iterator(); iterator
1591: .hasNext();) {
1592: Map.Entry entry = (Map.Entry) iterator.next();
1593: Object key = entry.getKey();
1594: Object value = entry.getValue();
1595: map.put(key, value);
1596: }
1597: return map;
1598: }
1599:
1600: public static final GBeanInfo GBEAN_INFO;
1601:
1602: static {
1603: GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(
1604: SimpleConfigurationManager.class,
1605: "ConfigurationManager");
1606: infoFactory.addReference("Stores", ConfigurationStore.class,
1607: "ConfigurationStore");
1608: infoFactory.addReference("ArtifactResolver",
1609: ArtifactResolver.class, "ArtifactResolver");
1610: infoFactory.addReference("Repositories", Repository.class,
1611: "Repository");
1612: infoFactory.addReference("Watchers", DeploymentWatcher.class);
1613: infoFactory.addInterface(ConfigurationManager.class);
1614: infoFactory.setConstructor(new String[] { "Stores",
1615: "ArtifactResolver", "Repositories", "Watchers" });
1616: GBEAN_INFO = infoFactory.getBeanInfo();
1617: }
1618:
1619: public static GBeanInfo getGBeanInfo() {
1620: return GBEAN_INFO;
1621: }
1622:
1623: }
|