View Javadoc

1   /**
2    *
3    * Copyright 2005 The Apache Software Foundation
4    *
5    *  Licensed under the Apache License, Version 2.0 (the "License");
6    *  you may not use this file except in compliance with the License.
7    *  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  package org.apache.geronimo.kernel.config;
18  
19  import java.io.IOException;
20  import java.util.ArrayList;
21  import java.util.Collection;
22  import java.util.Collections;
23  import java.util.Iterator;
24  import java.util.LinkedHashMap;
25  import java.util.LinkedHashSet;
26  import java.util.List;
27  import java.util.ListIterator;
28  import java.util.Map;
29  import java.util.Set;
30  import java.util.HashSet;
31  
32  import org.apache.commons.logging.Log;
33  import org.apache.commons.logging.LogFactory;
34  import org.apache.geronimo.gbean.AbstractName;
35  import org.apache.geronimo.kernel.management.State;
36  import org.apache.geronimo.kernel.repository.Artifact;
37  import org.apache.geronimo.kernel.repository.ArtifactResolver;
38  import org.apache.geronimo.kernel.repository.Dependency;
39  import org.apache.geronimo.kernel.repository.Environment;
40  import org.apache.geronimo.kernel.repository.ImportType;
41  import org.apache.geronimo.kernel.repository.MissingDependencyException;
42  import org.apache.geronimo.kernel.repository.Version;
43  
44  /**
45   * @version $Rev: 428535 $ $Date: 2006-08-03 14:36:04 -0700 (Thu, 03 Aug 2006) $
46   */
47  public class SimpleConfigurationManager implements ConfigurationManager {
48      protected static final Log log = LogFactory.getLog(SimpleConfigurationManager.class);
49      protected final Collection stores;
50      private final ArtifactResolver artifactResolver;
51      protected final Map configurations = new LinkedHashMap();
52      protected final ConfigurationModel configurationModel = new ConfigurationModel();
53      protected final Collection repositories;
54      protected final Collection watchers;
55  
56      /**
57       * When this is not null, it points to the "new" configuration that is
58       * part of an in-process reload operation.  This configuration will
59       * definitely be loaded, but might not be started yet.  It shold never be
60       * populated outside the scope of a reload operation.
61       */
62      private Configuration reloadingConfiguration;
63  
64  
65      public SimpleConfigurationManager(Collection stores, ArtifactResolver artifactResolver, Collection repositories) {
66          this(stores, artifactResolver, repositories, Collections.EMPTY_SET);
67      }
68      
69      public SimpleConfigurationManager(Collection stores, ArtifactResolver artifactResolver, Collection repositories, Collection watchers) {
70          if (stores == null) stores = Collections.EMPTY_SET;
71          if (repositories == null) repositories = Collections.EMPTY_SET;
72          if (watchers == null) watchers = Collections.EMPTY_SET;
73  
74          this.stores = stores;
75          this.artifactResolver = artifactResolver;
76          this.repositories = repositories;
77          this.watchers = watchers;
78      }
79  
80      public synchronized boolean isInstalled(Artifact configId) {
81          if(!configId.isResolved()) {
82              throw new IllegalArgumentException("Artifact "+configId+" is not fully resolved");
83          }
84          List storeSnapshot = getStoreList();
85          for (int i = 0; i < storeSnapshot.size(); i++) {
86              ConfigurationStore store = (ConfigurationStore) storeSnapshot.get(i);
87              if(store.containsConfiguration(configId)) {
88                  return true;
89              }
90          }
91          return false;
92      }
93  
94      public synchronized boolean isLoaded(Artifact configId) {
95          if(!configId.isResolved()) {
96              throw new IllegalArgumentException("Artifact "+configId+" is not fully resolved");
97          }
98          if(reloadingConfiguration != null && reloadingConfiguration.getId().equals(configId)) {
99              return true;
100         }
101         return configurationModel.isLoaded(configId);
102     }
103 
104     public synchronized boolean isRunning(Artifact configId) {
105         if(!configId.isResolved()) {
106             throw new IllegalArgumentException("Artifact "+configId+" is not fully resolved");
107         }
108         return configurationModel.isStarted(configId);
109     }
110 
111     public Artifact[] getInstalled(Artifact query) {
112         Artifact[] all = artifactResolver.queryArtifacts(query);
113         List configs = new ArrayList();
114         for (int i = 0; i < all.length; i++) {
115             Artifact artifact = all[i];
116             if(isConfiguration(artifact)) {
117                 configs.add(artifact);
118             }
119         }
120         if(configs.size() == all.length) {
121             return all;
122         }
123         return (Artifact[]) configs.toArray(new Artifact[configs.size()]);
124     }
125 
126     public Artifact[] getLoaded(Artifact query) {
127         return configurationModel.getLoaded(query);
128     }
129 
130     public Artifact[] getRunning(Artifact query) {
131         return configurationModel.getStarted(query);
132     }
133 
134 
135     public List listStores() {
136         List storeSnapshot = getStoreList();
137         List result = new ArrayList(storeSnapshot.size());
138         for (int i = 0; i < storeSnapshot.size(); i++) {
139             ConfigurationStore store = (ConfigurationStore) storeSnapshot.get(i);
140             result.add(store.getAbstractName());
141         }
142         return result;
143     }
144 
145     public ConfigurationStore[] getStores() {
146         List storeSnapshot = getStoreList();
147         return (ConfigurationStore[]) storeSnapshot.toArray(new ConfigurationStore[storeSnapshot.size()]);
148     }
149 
150     public Collection getRepositories() {
151         return repositories;
152     }
153 
154     public List listConfigurations() {
155         List storeSnapshot = getStoreList();
156         List list = new ArrayList();
157         for (int i = 0; i < storeSnapshot.size(); i++) {
158             ConfigurationStore store = (ConfigurationStore) storeSnapshot.get(i);
159             list.addAll(listConfigurations(store));
160         }
161         return list;
162     }
163 
164     public ConfigurationStore getStoreForConfiguration(Artifact configId) {
165         if(!configId.isResolved()) {
166             throw new IllegalArgumentException("Artifact "+configId+" is not fully resolved");
167         }
168         List storeSnapshot = getStoreList();
169         for (int i = 0; i < storeSnapshot.size(); i++) {
170             ConfigurationStore store = (ConfigurationStore) storeSnapshot.get(i);
171             if(store.containsConfiguration(configId)) {
172                 return store;
173             }
174         }
175         return null;
176     }
177 
178     public List listConfigurations(AbstractName storeName) throws NoSuchStoreException {
179         List storeSnapshot = getStoreList();
180         for (int i = 0; i < storeSnapshot.size(); i++) {
181             ConfigurationStore store = (ConfigurationStore) storeSnapshot.get(i);
182             if (storeName.equals(store.getAbstractName())) {
183                 return listConfigurations(store);
184             }
185         }
186         throw new NoSuchStoreException("No such store: " + storeName);
187     }
188 
189     private List listConfigurations(ConfigurationStore store) {
190         List list = store.listConfigurations();
191         for (ListIterator iterator = list.listIterator(); iterator.hasNext();) {
192             ConfigurationInfo configurationInfo = (ConfigurationInfo) iterator.next();
193             if (isRunning(configurationInfo.getConfigID())) {
194                 configurationInfo = new ConfigurationInfo(store.getAbstractName(),
195                         configurationInfo.getConfigID(),
196                         configurationInfo.getType(),
197                         configurationInfo.getCreated(),
198                         configurationInfo.getOwnedConfigurations(),
199                         configurationInfo.getChildConfigurations(),
200                         configurationInfo.getInPlaceLocation(),
201                         State.RUNNING);
202             } else {
203                 configurationInfo = new ConfigurationInfo(store.getAbstractName(),
204                         configurationInfo.getConfigID(),
205                         configurationInfo.getType(),
206                         configurationInfo.getCreated(),
207                         configurationInfo.getOwnedConfigurations(),
208                         configurationInfo.getChildConfigurations(),
209                         configurationInfo.getInPlaceLocation(),
210                         State.STOPPED);
211             }
212             iterator.set(configurationInfo);
213         }
214         return list;
215     }
216 
217     public boolean isConfiguration(Artifact artifact) {
218         if(!artifact.isResolved()) {
219             throw new IllegalArgumentException("Artifact "+artifact+" is not fully resolved");
220         }
221         synchronized (this) {
222             // if it is loaded, it is definitely a configuration
223             if (configurations.containsKey(artifact)) {
224                 return true;
225             }
226         }
227 
228         // see if any stores think it is a configuration
229         List storeSnapshot = getStoreList();
230         for (int i = 0; i < storeSnapshot.size(); i++) {
231             ConfigurationStore store = (ConfigurationStore) storeSnapshot.get(i);
232             if (store.containsConfiguration(artifact)) {
233                 return true;
234             }
235         }
236         return false;
237     }
238 
239     public synchronized Configuration getConfiguration(Artifact configurationId) {
240         if(!configurationId.isResolved()) {
241             throw new IllegalArgumentException("Artifact "+configurationId+" is not fully resolved");
242         }
243         if(reloadingConfiguration != null && reloadingConfiguration.getId().equals(configurationId)) {
244             return reloadingConfiguration;
245         }
246         return (Configuration) configurations.get(configurationId);
247     }
248 
249     public synchronized LifecycleResults loadConfiguration(Artifact configurationId) throws NoSuchConfigException, LifecycleException {
250         return loadConfiguration(configurationId, NullLifecycleMonitor.INSTANCE);
251     }
252 
253     public synchronized LifecycleResults loadConfiguration(Artifact configurationId, LifecycleMonitor monitor) throws NoSuchConfigException, LifecycleException {
254         if(!configurationId.isResolved()) {
255             throw new IllegalArgumentException("Artifact "+configurationId+" is not fully resolved");
256         }
257         if (isLoaded(configurationId)) {
258             // already loaded, so just mark the configuration as user loaded
259             load(configurationId);
260 
261             monitor.finished();
262             return new LifecycleResults();
263         }
264 
265         // load the ConfigurationData for the new configuration
266         ConfigurationData configurationData = null;
267         try {
268             configurationData = loadConfigurationData(configurationId, monitor);
269         } catch (Exception e) {
270             monitor.finished();
271             throw new LifecycleException("load", configurationId, e);
272         }
273 
274         // load the configuration
275         LifecycleResults results = loadConfiguration(configurationData, monitor);
276 
277         return results;
278     }
279 
280     public synchronized LifecycleResults loadConfiguration(ConfigurationData configurationData) throws NoSuchConfigException, LifecycleException {
281         return loadConfiguration(configurationData, NullLifecycleMonitor.INSTANCE);
282     }
283 
284     public synchronized LifecycleResults loadConfiguration(ConfigurationData configurationData, LifecycleMonitor monitor) throws NoSuchConfigException, LifecycleException {
285         Artifact id = configurationData.getId();
286         LifecycleResults results = new LifecycleResults();
287         if (!isLoaded(id)) {
288             // recursively load configurations from the new child to the parents
289             LinkedHashMap configurationsToLoad = new LinkedHashMap();
290             try {
291                 loadDepthFirst(configurationData, configurationsToLoad, monitor);
292             } catch (Exception e) {
293                 monitor.finished();
294                 throw new LifecycleException("load", id, e);
295             }
296 
297             // load and start the unloaded the gbean for each configuration (depth first)
298             Map actuallyLoaded = new LinkedHashMap(configurationsToLoad.size());
299             Artifact configurationId = null;
300             try {
301                 for (Iterator iterator = configurationsToLoad.entrySet().iterator(); iterator.hasNext();) {
302                     Map.Entry entry = (Map.Entry) iterator.next();
303                     configurationId = (Artifact) entry.getKey();
304                     UnloadedConfiguration unloadedConfiguration = (UnloadedConfiguration) entry.getValue();
305 
306                     monitor.loading(configurationId);
307                     Configuration configuration = load(unloadedConfiguration.getConfigurationData(), unloadedConfiguration.getResolvedParentIds(), actuallyLoaded);
308                     monitor.succeeded(configurationId);
309 
310                     actuallyLoaded.put(configurationId, configuration);
311                 }
312             } catch (Exception e) {
313                 monitor.failed(configurationId, e);
314 
315                 // there was a problem, so we need to unload all configurations that were actually loaded
316                 for (Iterator iterator = actuallyLoaded.values().iterator(); iterator.hasNext();) {
317                     Configuration configuration = (Configuration) iterator.next();
318                     unload(configuration);
319                 }
320 
321                 monitor.finished();
322                 throw new LifecycleException("load", id, e);
323             }
324 
325             // update the status of the loaded configurations
326             addNewConfigurationsToModel(actuallyLoaded);
327             results.setLoaded(actuallyLoaded.keySet());
328         }
329         load(id);
330         monitor.finished();
331         return results;
332     }
333 
334     protected void load(Artifact configurationId) throws NoSuchConfigException {
335         configurationModel.load(configurationId);
336     }
337 
338     protected Configuration load(ConfigurationData configurationData, LinkedHashSet resolvedParentIds, Map loadedConfigurations) throws InvalidConfigException {
339         Artifact configurationId = configurationData.getId();
340         try {
341             Collection parents = findParentConfigurations(resolvedParentIds, loadedConfigurations);
342 
343             Configuration configuration = new Configuration(parents, configurationData, new ConfigurationResolver(configurationData, repositories, artifactResolver), null);
344             configuration.doStart();
345             return configuration;
346         } catch (Exception e) {
347             throw new InvalidConfigException("Error starting configuration gbean " + configurationId, e);
348         }
349     }
350 
351     private Collection findParentConfigurations(LinkedHashSet resolvedParentIds, Map loadedConfigurations) throws InvalidConfigException {
352         LinkedHashMap parents = new LinkedHashMap();
353         for (Iterator iterator = resolvedParentIds.iterator(); iterator.hasNext();) {
354             Artifact resolvedArtifact = (Artifact) iterator.next();
355 
356             Configuration parent = null;
357             if (loadedConfigurations.containsKey(resolvedArtifact)) {
358                 parent = (Configuration) loadedConfigurations.get(resolvedArtifact);
359             } else if (isLoaded(resolvedArtifact)) {
360                 parent = getConfiguration(resolvedArtifact);
361             } else {
362                 throw new InvalidConfigException("Cound not find parent configuration: " + resolvedArtifact);
363             }
364 
365             parents.put(resolvedArtifact, parent);
366         }
367         return parents.values();
368     }
369 
370     private void addNewConfigurationsToModel(Map loadedConfigurations) throws NoSuchConfigException {
371         for (Iterator iterator = loadedConfigurations.values().iterator(); iterator.hasNext();) {
372             Configuration configuration = (Configuration) iterator.next();
373             addNewConfigurationToModel(configuration);
374         }
375     }
376 
377     protected void addNewConfigurationToModel(Configuration configuration) throws NoSuchConfigException {
378         configurationModel.addConfiguation(configuration.getId(),
379                 getConfigurationIds(getLoadParents(configuration)),
380                 getConfigurationIds(getStartParents(configuration)));
381         configurations.put(configuration.getId(), configuration);
382     }
383 
384     protected LinkedHashSet getLoadParents(Configuration configuration) {
385         LinkedHashSet loadParent = new LinkedHashSet(configuration.getClassParents());
386         for (Iterator iterator = configuration.getChildren().iterator(); iterator.hasNext();) {
387             Configuration childConfiguration = (Configuration) iterator.next();
388             LinkedHashSet childLoadParent = getLoadParents(childConfiguration);
389 
390             // remove this configuration from the parent Ids since it will cause an infinite loop
391             childLoadParent.remove(configuration);
392 
393             loadParent.addAll(childLoadParent);
394         }
395         return loadParent;
396     }
397 
398     protected LinkedHashSet getStartParents(Configuration configuration) {
399         LinkedHashSet startParent = new LinkedHashSet(configuration.getServiceParents());
400         for (Iterator iterator = configuration.getChildren().iterator(); iterator.hasNext();) {
401             Configuration childConfiguration = (Configuration) iterator.next();
402             LinkedHashSet childStartParent = getStartParents(childConfiguration);
403 
404             // remove this configuration from the parent Ids since it will cause an infinite loop
405             childStartParent.remove(configuration);
406 
407             startParent.addAll(childStartParent);
408         }
409         return startParent;
410     }
411 
412     private static LinkedHashSet getConfigurationIds(Collection configurations) {
413         LinkedHashSet configurationIds = new LinkedHashSet(configurations.size());
414         for (Iterator iterator = configurations.iterator(); iterator.hasNext();) {
415             Configuration configuration = (Configuration) iterator.next();
416             configurationIds.add(configuration.getId());
417         }
418         return configurationIds;
419     }
420 
421     private synchronized void loadDepthFirst(ConfigurationData configurationData, LinkedHashMap configurationsToLoad, LifecycleMonitor monitor) throws NoSuchConfigException, IOException, InvalidConfigException, MissingDependencyException {
422         // if this parent hasn't already been processed, iterate into the parent
423         Artifact configurationId = configurationData.getId();
424         if (!configurationsToLoad.containsKey(configurationId)) {
425             LinkedHashSet resolvedParentIds = resolveParentIds(configurationData);
426 
427             for (Iterator iterator = resolvedParentIds.iterator(); iterator.hasNext();) {
428                 Artifact parentId = (Artifact) iterator.next();
429                 // if this parent id hasn't already been loaded and is actually a configuration
430                 if (!isLoaded(parentId) && isConfiguration(parentId)) {
431                     ConfigurationData parentConfigurationData = loadConfigurationData(parentId, monitor);
432                     loadDepthFirst(parentConfigurationData, configurationsToLoad, monitor);
433                 }
434             }
435 
436             // depth first - all unloaded parents have been added, now add this configuration
437             configurationsToLoad.put(configurationId, new UnloadedConfiguration(configurationData, resolvedParentIds));
438         }
439     }
440 
441     private ConfigurationData loadConfigurationData(Artifact configurationId, LifecycleMonitor monitor) throws NoSuchConfigException, IOException, InvalidConfigException {
442         List storeSnapshot = getStoreList();
443 
444         monitor.addConfiguration(configurationId);
445         monitor.reading(configurationId);
446         for (int i = 0; i < storeSnapshot.size(); i++) {
447             ConfigurationStore store = (ConfigurationStore) storeSnapshot.get(i);
448             if (store.containsConfiguration(configurationId)) {
449                 ConfigurationData configurationData = store.loadConfiguration(configurationId);
450                 monitor.succeeded(configurationId);
451                 return configurationData;
452             }
453         }
454         NoSuchConfigException exception = new NoSuchConfigException(configurationId);
455         monitor.failed(configurationId, exception);
456         throw exception;
457     }
458 
459     private LinkedHashSet resolveParentIds(ConfigurationData configurationData) throws MissingDependencyException, InvalidConfigException {
460         Environment environment = configurationData.getEnvironment();
461 
462         LinkedHashSet parentIds = new LinkedHashSet();
463         List dependencies = new ArrayList(environment.getDependencies());
464         for (ListIterator iterator = dependencies.listIterator(); iterator.hasNext();) {
465             Dependency dependency = (Dependency) iterator.next();
466             Artifact resolvedArtifact = artifactResolver.resolveInClassLoader(dependency.getArtifact());
467             if (isConfiguration(resolvedArtifact)) {
468                 parentIds.add(resolvedArtifact);
469 
470                 // update the dependency list to contain the resolved artifact
471                 dependency = new Dependency(resolvedArtifact, dependency.getImportType());
472                 iterator.set(dependency);
473             } else if (dependency.getImportType() == ImportType.SERVICES) {
474                 // Service depdendencies require that the depdencency be a configuration
475                 throw new InvalidConfigException("Dependency does not have services: " + resolvedArtifact);
476             }
477         }
478 
479         for (Iterator iterator = configurationData.getChildConfigurations().values().iterator(); iterator.hasNext();) {
480             ConfigurationData childConfigurationData = (ConfigurationData) iterator.next();
481             LinkedHashSet childParentIds = resolveParentIds(childConfigurationData);
482             // remove this configuration's id from the parent Ids since it will cause an infinite loop
483             childParentIds.remove(configurationData.getId());
484             parentIds.addAll(childParentIds);
485         }
486         return parentIds;
487     }
488 
489     private static class UnloadedConfiguration {
490         private final ConfigurationData configurationData;
491         private final LinkedHashSet resolvedParentIds;
492 
493         public UnloadedConfiguration(ConfigurationData configurationData, LinkedHashSet resolvedParentIds) {
494             this.configurationData = configurationData;
495             this.resolvedParentIds = resolvedParentIds;
496         }
497 
498         public ConfigurationData getConfigurationData() {
499             return configurationData;
500         }
501 
502         public LinkedHashSet getResolvedParentIds() {
503             return resolvedParentIds;
504         }
505     }
506 
507     public synchronized LifecycleResults startConfiguration(Artifact id) throws NoSuchConfigException, LifecycleException {
508         return startConfiguration(id, NullLifecycleMonitor.INSTANCE);
509     }
510 
511     public synchronized LifecycleResults startConfiguration(Artifact id, LifecycleMonitor monitor) throws  NoSuchConfigException, LifecycleException {
512         if(!id.isResolved()) {
513             throw new IllegalArgumentException("Artifact "+id+" is not fully resolved");
514         }
515         LinkedHashSet unstartedConfigurations = configurationModel.start(id);
516 
517         addConfigurationsToMonitor(monitor, unstartedConfigurations);
518 
519         LifecycleResults results = new LifecycleResults();
520         Artifact configurationId = null;
521         try {
522             for (Iterator iterator = unstartedConfigurations.iterator(); iterator.hasNext();) {
523                 configurationId = (Artifact) iterator.next();
524                 Configuration configuration = getConfiguration(configurationId);
525 
526                 monitor.starting(configurationId);
527                 start(configuration);
528                 monitor.succeeded(configurationId);
529 
530                 results.addStarted(configurationId);
531             }
532         } catch (Exception e) {
533             monitor.failed(configurationId, e);
534             configurationModel.stop(id);
535 
536             for (Iterator iterator = results.getStarted().iterator(); iterator.hasNext();) {
537                 configurationId = (Artifact) iterator.next();
538                 Configuration configuration = getConfiguration(configurationId);
539                 monitor.stopping(configurationId);
540                 stop(configuration);
541                 monitor.succeeded(configurationId);
542             }
543             monitor.finished();
544             throw new LifecycleException("start", id, e);
545         }
546         monitor.finished();
547         return results;
548     }
549 
550     protected void start(Configuration configuration) throws Exception {
551         throw new UnsupportedOperationException();
552     }
553 
554     public synchronized LifecycleResults stopConfiguration(Artifact id) throws NoSuchConfigException {
555         return stopConfiguration(id, NullLifecycleMonitor.INSTANCE);
556     }
557 
558     public synchronized LifecycleResults stopConfiguration(Artifact id, LifecycleMonitor monitor) throws NoSuchConfigException {
559         if(!id.isResolved()) {
560             throw new IllegalArgumentException("Artifact "+id+" is not fully resolved");
561         }
562         LinkedHashSet stopList = configurationModel.stop(id);
563 
564         addConfigurationsToMonitor(monitor, stopList);
565 
566         LifecycleResults results = new LifecycleResults();
567         for (Iterator iterator = stopList.iterator(); iterator.hasNext();) {
568             Artifact configurationId = (Artifact) iterator.next();
569             Configuration configuration = getConfiguration(configurationId);
570 
571             monitor.stopping(configurationId);
572             stop(configuration);
573             monitor.succeeded(configurationId);
574 
575             results.addStopped(configurationId);
576         }
577 
578         monitor.finished();
579         return results;
580     }
581 
582     protected void stop(Configuration configuration) {
583         // Don't throw an exception because we call this from unload to be sure that all
584         // unloaded configurations are stopped first
585     }
586 
587     public synchronized LifecycleResults restartConfiguration(Artifact id) throws NoSuchConfigException, LifecycleException {
588         return restartConfiguration(id, NullLifecycleMonitor.INSTANCE);
589     }
590 
591     public synchronized LifecycleResults restartConfiguration(Artifact id, LifecycleMonitor monitor) throws NoSuchConfigException, LifecycleException {
592         if(!id.isResolved()) {
593             throw new IllegalArgumentException("Artifact "+id+" is not fully resolved");
594         }
595         // get a sorted list of configurations to restart
596         LinkedHashSet restartList = configurationModel.restart(id);
597 
598         addConfigurationsToMonitor(monitor, restartList);
599 
600         // stop the configuations
601         LifecycleResults results = new LifecycleResults();
602         for (Iterator iterator = restartList.iterator(); iterator.hasNext();) {
603             Artifact configurationId = (Artifact) iterator.next();
604             Configuration configuration = getConfiguration(configurationId);
605             monitor.stopping(configurationId);
606             stop(configuration);
607             monitor.succeeded(configurationId);
608             results.addStopped(configurationId);
609         }
610 
611         // reverse the list
612         restartList = reverse(restartList);
613 
614         // restart the configurations
615         Set skip = new HashSet();
616         for (Iterator iterator = restartList.iterator(); iterator.hasNext();) {
617             Artifact configurationId = (Artifact) iterator.next();
618 
619             // skip the configurations that have alredy failed or are children of failed configurations
620             if (skip.contains(configurationId)) {
621                 continue;
622             }
623 
624             // try to start the configuation
625             try {
626                 Configuration configuration = getConfiguration(configurationId);
627                 monitor.starting(configurationId);
628                 start(configuration);
629                 monitor.succeeded(configurationId);
630                 results.addStarted(configurationId);
631             } catch (Exception e) {
632                 // the configuraiton failed to restart
633                 results.addFailed(configurationId, e);
634                 monitor.failed(configurationId, e);
635                 skip.add(configurationId);
636 
637                 // officially stop the configuration in the model (without gc)
638                 LinkedHashSet stopList = configurationModel.stop(configurationId, false);
639 
640                 // all of the configurations to be stopped must be in our restart list, or the model is corrupt
641                 if (!restartList.containsAll(stopList)) {
642                     throw new AssertionError("Configuration data model is corrupt.   You must restart your server.");
643                 }
644 
645                 // add the children of the failed configuration to the results as stopped
646                 for (Iterator iterator1 = stopList.iterator(); iterator1.hasNext();) {
647                     Artifact failedId = (Artifact) iterator1.next();
648 
649                     // if any of the failed configuration is in the restarted set, the model is
650                     // corrupt because we started a child before a parent
651                     if (results.wasStarted(failedId)) {
652                         throw new AssertionError("Configuration data model is corrupt.   You must restart your server.");
653                     }
654 
655                     skip.add(failedId);
656                 }
657             }
658         }
659 
660         monitor.finished();
661         if (!results.wasStarted(id)) {
662             throw new LifecycleException("restart", id, results);
663         }
664         return results;
665     }
666 
667     public synchronized LifecycleResults unloadConfiguration(Artifact id) throws NoSuchConfigException {
668         return unloadConfiguration(id, NullLifecycleMonitor.INSTANCE);
669     }
670 
671     public synchronized LifecycleResults unloadConfiguration(Artifact id, LifecycleMonitor monitor) throws NoSuchConfigException {
672         if(!id.isResolved()) {
673             throw new IllegalArgumentException("Artifact "+id+" is not fully resolved");
674         }
675         Set started = configurationModel.getStarted();
676         LinkedHashSet unloadList = configurationModel.unload(id);
677 
678         addConfigurationsToMonitor(monitor, unloadList);
679 
680         LifecycleResults results = new LifecycleResults();
681         for (Iterator iterator = unloadList.iterator(); iterator.hasNext();) {
682             Artifact configurationId = (Artifact) iterator.next();
683             Configuration configuration = getConfiguration(configurationId);
684 
685             // first make sure it is stopped
686             if (started.contains(configurationId)) {
687                 monitor.stopping(configurationId);
688                 stop(configuration);
689                 monitor.succeeded(configurationId);
690                 results.addStopped(configurationId);
691             } else {
692                 // call stop just to be sure the beans aren't running
693                 stop(configuration);
694             }
695 
696             // now unload it
697             monitor.unloading(configurationId);
698             unload(configuration);
699             monitor.succeeded(configurationId);
700             results.addUnloaded(configurationId);
701 
702             // clean up the model
703             removeConfigurationFromModel(configurationId);
704         }
705         monitor.finished();
706         return results;
707     }
708 
709     protected void removeConfigurationFromModel(Artifact configurationId) throws NoSuchConfigException {
710         if(configurationModel.containsConfiguration(configurationId)) {
711             configurationModel.removeConfiguration(configurationId);
712         }
713         configurations.remove(configurationId);
714     }
715 
716     protected void unload(Configuration configuration) {
717         try {
718             configuration.doStop();
719         } catch (Exception e) {
720             log.debug("Problem unloading config: " + configuration.getId(), e);
721         }
722     }
723 
724     public synchronized LifecycleResults reloadConfiguration(Artifact id) throws NoSuchConfigException, LifecycleException {
725         return reloadConfiguration(id, NullLifecycleMonitor.INSTANCE);
726     }
727 
728     public synchronized LifecycleResults reloadConfiguration(Artifact id, LifecycleMonitor monitor) throws NoSuchConfigException, LifecycleException {
729         return reloadConfiguration(id, id.getVersion(), monitor);
730     }
731 
732     public synchronized LifecycleResults reloadConfiguration(Artifact id, Version version) throws NoSuchConfigException, LifecycleException {
733         return reloadConfiguration(id, version, NullLifecycleMonitor.INSTANCE);
734     }
735 
736     public synchronized LifecycleResults reloadConfiguration(Artifact id, Version version, LifecycleMonitor monitor) throws NoSuchConfigException, LifecycleException {
737         if(!id.isResolved()) {
738             throw new IllegalArgumentException("Artifact "+id+" is not fully resolved");
739         }
740         Configuration configuration = getConfiguration(id);
741         if (configuration == null) { // The configuration to reload is not currently loaded
742             ConfigurationData data = null;
743             List storeSnapshot = getStoreList();
744             for (int i = 0; i < storeSnapshot.size(); i++) {
745                 ConfigurationStore store = (ConfigurationStore) storeSnapshot.get(i);
746                 if (store.containsConfiguration(id)) {
747                     try {
748                         data = store.loadConfiguration(id);
749                     } catch (Exception e) {
750                         log.warn("Unable to load existing configuration "+id+" from config store", e);
751                     }
752                 }
753             }
754             if(data == null) {
755                 throw new NoSuchConfigException(id);
756             }
757             UnloadedConfiguration existingUnloadedConfiguration = new UnloadedConfiguration(data, new LinkedHashSet());
758             Artifact newId = new Artifact(id.getGroupId(), id.getArtifactId(), version, id.getType());
759             ConfigurationData newData = null;
760             try {
761                 newData = loadConfigurationData(newId, monitor);
762             } catch (Exception e) {
763                 monitor.finished();
764                 throw new LifecycleException("reload", id, e);
765             }
766 
767             return reloadConfiguration(existingUnloadedConfiguration, newData, monitor);
768         } else { // The configuration to reload is loaded
769             ConfigurationData existingConfigurationData = configuration.getConfigurationData();
770             UnloadedConfiguration existingUnloadedConfiguration = new UnloadedConfiguration(existingConfigurationData, getResolvedParentIds(configuration));
771 
772             Artifact newId = new Artifact(id.getGroupId(), id.getArtifactId(), version, id.getType());
773 
774             // reload the ConfigurationData from a store
775             ConfigurationData configurationData = null;
776             try {
777                 configurationData = loadConfigurationData(newId, monitor);
778             } catch (Exception e) {
779                 monitor.finished();
780                 throw new LifecycleException("reload", id, e);
781             }
782 
783             return reloadConfiguration(existingUnloadedConfiguration, configurationData, monitor);
784         }
785     }
786 
787     public synchronized LifecycleResults reloadConfiguration(ConfigurationData configurationData) throws LifecycleException, NoSuchConfigException {
788         return reloadConfiguration(configurationData, NullLifecycleMonitor.INSTANCE);
789     }
790 
791     public synchronized LifecycleResults reloadConfiguration(ConfigurationData configurationData, LifecycleMonitor monitor) throws LifecycleException, NoSuchConfigException {
792         Configuration configuration = getConfiguration(configurationData.getId());
793         if (configuration == null) {
794             throw new NoSuchConfigException(configurationData.getId());
795         }
796         ConfigurationData existingConfigurationData = configuration.getConfigurationData();
797         UnloadedConfiguration existingUnloadedConfiguration = new UnloadedConfiguration(existingConfigurationData, getResolvedParentIds(configuration));
798         return reloadConfiguration(existingUnloadedConfiguration, configurationData, monitor);
799     }
800 
801     private boolean hasHardDependency(Artifact configurationId, ConfigurationData configurationData) {
802         for (Iterator iterator = configurationData.getEnvironment().getDependencies().iterator(); iterator.hasNext();) {
803             Dependency dependency = (Dependency) iterator.next();
804             Artifact artifact = dependency.getArtifact();
805             if (artifact.getVersion() != null && artifact.matches(configurationId)) {
806                 return true;
807             }
808         }
809 
810         for (Iterator iterator = configurationData.getChildConfigurations().values().iterator(); iterator.hasNext();) {
811             ConfigurationData childConfigurationData = (ConfigurationData) iterator.next();
812             if (hasHardDependency(configurationId, childConfigurationData)) {
813                 return true;
814             }
815         }
816         return false;
817     }
818 
819     // todo this method ignores garbage collection of configurations
820     private LifecycleResults reloadConfiguration(UnloadedConfiguration existingUnloadedConfiguration, ConfigurationData newConfigurationData, LifecycleMonitor monitor) throws LifecycleException, NoSuchConfigException {
821         boolean force = false;
822 
823         Artifact existingConfigurationId = existingUnloadedConfiguration.getConfigurationData().getId();
824         Artifact newConfigurationId = newConfigurationData.getId();
825 
826         //
827         // recursively load the new configuration; this will catch any new parents
828         //
829         LinkedHashMap newConfigurations = new LinkedHashMap();
830         try {
831             loadDepthFirst(newConfigurationData, newConfigurations, monitor);
832         } catch (Exception e) {
833             monitor.finished();
834             throw new LifecycleException("reload", newConfigurationId, e);
835         }
836 
837         //
838         // get a list of the started configuration, so we can restart them later
839         //
840         Set started = configurationModel.getStarted();
841 
842         //
843         // get a list of the child configurations that will need to reload
844         //
845         //   note: we are iterating in reverse order
846         LinkedHashMap existingParents = new LinkedHashMap();
847         LinkedHashMap reloadChildren = new LinkedHashMap();
848         for (Iterator iterator = reverse(configurationModel.reload(existingConfigurationId)).iterator(); iterator.hasNext();) {
849             Artifact configurationId = (Artifact) iterator.next();
850 
851             if (configurationId.equals(existingConfigurationId)) {
852                 continue;
853             }
854 
855             // if new configurations contains the child something we have a circular dependency
856             if (newConfigurations.containsKey(configurationId)) {
857                 throw new LifecycleException("reload", newConfigurationId,
858                         new IllegalStateException("Circular depenency between " + newConfigurationId + " and " + configurationId));
859             }
860 
861             Configuration configuration = getConfiguration(configurationId);
862             ConfigurationData configurationData = configuration.getConfigurationData();
863 
864             // save off the exising resolved parent ids in case we need to restore this configuration
865             LinkedHashSet existingParentIds = getResolvedParentIds(configuration);
866             existingParents.put(configurationId, existingParentIds);
867 
868             // check that the child doen't have a hard dependency on the old configuration
869             LinkedHashSet resolvedParentIds = null;
870             if (hasHardDependency(existingConfigurationId, configurationData)) {
871                 if (force) {
872                     throw new LifecycleException("reload", newConfigurationId,
873                             new IllegalStateException("Existing configuration " + configurationId + " has a hard dependency on the current version of this configuration " + existingConfigurationId));
874                 }
875 
876                 // we leave the resolved parent ids null to signal that we should not reload the configuration
877                 resolvedParentIds = null;
878             } else {
879                 resolvedParentIds = new LinkedHashSet(existingParentIds);
880                 resolvedParentIds.remove(existingConfigurationId);
881                 resolvedParentIds.add(newConfigurationId);
882             }
883 
884             reloadChildren.put(configurationId, new UnloadedConfiguration(configurationData, resolvedParentIds));
885             monitor.addConfiguration(configurationId);
886         }
887 
888         //
889         // unload the children
890         //
891 
892         // note: we are iterating in reverse order
893         LifecycleResults results = new LifecycleResults();
894         for (Iterator iterator = reverse(reloadChildren).keySet().iterator(); iterator.hasNext();) {
895             Artifact configurationId = (Artifact) iterator.next();
896             Configuration configuration = getConfiguration(configurationId);
897 
898             // first make sure it is stopped
899             if (started.contains(configurationId)) {
900                 monitor.stopping(configurationId);
901                 stop(configuration);
902                 monitor.succeeded(configurationId);
903                 results.addStopped(configurationId);
904             } else {
905                 // call stop just to be sure the beans aren't running
906                 stop(configuration);
907             }
908 
909             // now unload it
910             monitor.unloading(configurationId);
911             unload(configuration);
912             monitor.succeeded(configurationId);
913             results.addUnloaded(configurationId);
914         }
915 
916         //
917         // unload the existing config
918         //
919         Configuration existingConfiguration = getConfiguration(existingConfigurationId);
920         if (started.contains(existingConfigurationId)) {
921             monitor.stopping(existingConfigurationId);
922             stop(existingConfiguration);
923             monitor.succeeded(existingConfigurationId);
924             results.addStopped(existingConfigurationId);
925         } else if(existingConfiguration != null) {
926             // call stop just to be sure the beans aren't running
927             stop(existingConfiguration);
928         }
929         if(existingConfiguration != null) {
930             monitor.unloading(existingConfigurationId);
931             unload(existingConfiguration);
932             monitor.succeeded(existingConfigurationId);
933             results.addUnloaded(existingConfigurationId);
934         }
935 
936         //
937         // load the new configurations
938         //
939         boolean reinstatedExisting = false;
940         /* reduce variable scope */ {
941             Map loadedParents = new LinkedHashMap();
942             Map startedParents = new LinkedHashMap();
943             Configuration newConfiguration = null;
944             Artifact configurationId = null;
945             try {
946                 //
947                 // load all of the new configurations
948                 //
949                 for (Iterator iterator = newConfigurations.entrySet().iterator(); iterator.hasNext();) {
950                     Map.Entry entry = (Map.Entry) iterator.next();
951                     configurationId = (Artifact) entry.getKey();
952                     UnloadedConfiguration unloadedConfiguration = (UnloadedConfiguration) entry.getValue();
953 
954                     monitor.loading(configurationId);
955                     Configuration configuration = load(unloadedConfiguration.getConfigurationData(), unloadedConfiguration.getResolvedParentIds(), loadedParents);
956                     monitor.succeeded(configurationId);
957 
958                     if (configurationId.equals(newConfigurationId)) {
959                         newConfiguration = configuration;
960                         reloadingConfiguration = configuration;
961                     } else {
962                         loadedParents.put(configurationId, configuration);
963                     }
964                 }
965 
966                 if (newConfiguration == null) {
967                     AssertionError cause = new AssertionError("Internal error: configuration was not load");
968                     results.addFailed(newConfigurationId, cause);
969                     throw new LifecycleException("reload", newConfigurationId, results);
970                 }
971 
972                 //
973                 // start the new configurations if the old one was running
974                 //
975                 if (started.contains(existingConfigurationId)) {
976 
977                     // determine which of the parents we need to start
978                     LinkedHashSet startList = new LinkedHashSet();
979                     for (Iterator iterator = getStartParents(newConfiguration).iterator(); iterator.hasNext();) {
980                         Configuration serviceParent = (Configuration) iterator.next();
981                         if (loadedParents.containsKey(serviceParent.getId())) {
982                             startList.add(serviceParent);
983                         }
984                     }
985 
986                     // start the new parents
987                     for (Iterator iterator = startList.iterator(); iterator.hasNext();) {
988                         Configuration startParent = (Configuration) iterator.next();
989                         monitor.starting(configurationId);
990                         start(startParent);
991                         monitor.succeeded(configurationId);
992 
993                         startedParents.put(configurationId, startParent);
994                     }
995 
996                     //  start the new configuration
997                     monitor.starting(newConfigurationId);
998                     start(newConfiguration);
999                     monitor.succeeded(newConfigurationId);
1000                 }
1001 
1002                 //
1003                 // update the results
1004                 //
1005                 results.setLoaded(loadedParents.keySet());
1006                 results.addLoaded(newConfigurationId);
1007                 if (started.contains(existingConfigurationId)) {
1008                     results.setStarted(startedParents.keySet());
1009                     results.addStarted(newConfigurationId);
1010                 }
1011 
1012                 //
1013                 // update the model
1014                 //
1015 
1016                 // add all of the new configurations the model
1017                 addNewConfigurationsToModel(loadedParents);
1018 
1019                 // now ugrade the existing node in the model
1020                 if(configurationModel.containsConfiguration(existingConfigurationId)) {
1021                     configurationModel.upgradeConfiguration(existingConfigurationId,
1022                             newConfigurationId,
1023                             getConfigurationIds(getLoadParents(newConfiguration)),
1024                             getConfigurationIds(getStartParents(newConfiguration)));
1025                 } else {
1026                     configurationModel.addConfiguation(newConfigurationId,
1027                             getConfigurationIds(getLoadParents(newConfiguration)),
1028                             getConfigurationIds(getStartParents(newConfiguration)));
1029                     load(newConfigurationId);
1030                 }
1031 
1032                 // replace the configuraiton in he configurations map
1033                 configurations.remove(existingConfiguration);
1034                 configurations.put(newConfigurationId, newConfiguration);
1035 
1036                 // migrate the configuration settings
1037                 migrateConfiguration(existingConfigurationId, newConfigurationId, newConfiguration, started.contains(existingConfigurationId));
1038             } catch (Exception e) {
1039                 monitor.failed(configurationId, e);
1040                 results.addFailed(configurationId, e);
1041 
1042                 //
1043                 // stop and unload all configurations that were actually loaded
1044                 //
1045                 for (Iterator iterator = startedParents.values().iterator(); iterator.hasNext();) {
1046                     Configuration configuration = (Configuration) iterator.next();
1047                     stop(configuration);
1048                 }
1049                 for (Iterator iterator = loadedParents.values().iterator(); iterator.hasNext();) {
1050                     Configuration configuration = (Configuration) iterator.next();
1051                     unload(configuration);
1052                 }
1053 
1054                 // stop and unload the newConfiguration
1055                 if (newConfiguration != null) {
1056                     stop(newConfiguration);
1057                     unload(newConfiguration);
1058                 }
1059 
1060                 //
1061                 // atempt to reinstate the old configuation
1062                 //
1063                 Configuration configuration = null;
1064                 try {
1065                     configuration = load(existingUnloadedConfiguration.getConfigurationData(),
1066                             existingUnloadedConfiguration.getResolvedParentIds(),
1067                             Collections.EMPTY_MAP);
1068                     reloadingConfiguration = configuration;
1069                     // if the configuration was started before restart it
1070                     if (started.contains(existingConfigurationId)) {
1071                         start(configuration);
1072                         results.addStarted(existingConfigurationId);
1073                     }
1074 
1075                     // don't mark as loded until start completes as it may thorw an exception
1076                     results.addLoaded(existingConfigurationId);
1077 
1078                     configurations.put(existingConfigurationId, configuration);
1079 
1080                     reinstatedExisting = true;
1081                 } catch (Exception ignored) {
1082                     monitor.failed(existingConfigurationId, e);
1083 
1084                     // we tried our best
1085                     if (configuration != null) {
1086                         unload(configuration);
1087                     }
1088 
1089                     //
1090                     // cleanup the model
1091                     //
1092                     for (Iterator iterator = results.getUnloaded().iterator(); iterator.hasNext();) {
1093                         Artifact childId = (Artifact) iterator.next();
1094                         configurationModel.unload(childId);
1095                         removeConfigurationFromModel(childId);
1096                     }
1097 
1098                     throw new LifecycleException("reload", newConfigurationId, results);
1099                 }
1100             } finally {
1101                 reloadingConfiguration = null;
1102             }
1103         }
1104 
1105         //
1106         // reload as many child configurations as possible
1107         //
1108         Set skip = new HashSet();
1109         for (Iterator iterator = reloadChildren.entrySet().iterator(); iterator.hasNext();) {
1110             Map.Entry entry = (Map.Entry) iterator.next();
1111             Artifact configurationId = (Artifact) entry.getKey();
1112             UnloadedConfiguration unloadedConfiguration = (UnloadedConfiguration) entry.getValue();
1113 
1114             // skip the configurations that have alredy failed or are children of failed configurations
1115             if (skip.contains(configurationId)) {
1116                 continue;
1117             }
1118 
1119             // try to load the configuation
1120             Configuration configuration = null;
1121             try {
1122                 // get the correct resolved parent ids based on if we are loading with the new config id or the existing one
1123                 LinkedHashSet resolvedParentIds;
1124                 if (!reinstatedExisting) {
1125                     resolvedParentIds = unloadedConfiguration.getResolvedParentIds();
1126                 } else {
1127                     resolvedParentIds = (LinkedHashSet) existingParents.get(configurationId);
1128                 }
1129 
1130                 // if the resolved parent ids is null, then we are not supposed to reload this configuration
1131                 if (resolvedParentIds != null) {
1132                     monitor.loading(configurationId);
1133                     configuration = load(unloadedConfiguration.getConfigurationData(), resolvedParentIds, Collections.EMPTY_MAP);
1134                     reloadingConfiguration = configuration;
1135                     monitor.succeeded(configurationId);
1136 
1137 
1138                     // if the configuration was started before restart it
1139                     if (started.contains(configurationId)) {
1140                         monitor.starting(configurationId);
1141                         start(configuration);
1142                         monitor.succeeded(configurationId);
1143                         results.addStarted(configurationId);
1144                     }
1145 
1146                     // don't mark as loded until start completes as it may thow an exception
1147                     results.addLoaded(configurationId);
1148 
1149                     configurations.put(configurationId, configuration);
1150                 } else {
1151                     removeConfigurationFromModel(configurationId);
1152                 }
1153             } catch (Exception e) {
1154                 // the configuraiton failed to restart
1155                 results.addFailed(configurationId, e);
1156                 monitor.failed(configurationId, e);
1157                 skip.add(configurationId);
1158 
1159                 // unload the configuration if it was loaded and failed in start
1160                 if (configuration != null) {
1161                     unload(configuration);
1162                 }
1163 
1164                 // officially unload the configuration in the model (without gc)
1165                 LinkedHashSet unloadList = configurationModel.unload(configurationId, false);
1166                 configurationModel.removeConfiguration(configurationId);
1167 
1168                 // all of the configurations to be unloaded must be in our unloaded list, or the model is corrupt
1169                 if (!reloadChildren.keySet().containsAll(unloadList)) {
1170                     throw new AssertionError("Configuration data model is corrupt.   You must restart your server.");
1171                 }
1172 
1173                 // add the children of the failed configuration to the results as unloaded
1174                 for (Iterator iterator1 = unloadList.iterator(); iterator1.hasNext();) {
1175                     Artifact failedId = (Artifact) iterator1.next();
1176 
1177                     // if any of the failed configuration are in the reloaded set, the model is
1178                     // corrupt because we loaded a child before a parent
1179                     if (results.wasLoaded(failedId)) {
1180                         throw new AssertionError("Configuration data model is corrupt.   You must restart your server.");
1181                     }
1182 
1183                     skip.add(failedId);
1184                 }
1185             } finally {
1186                 reloadingConfiguration = null;
1187             }
1188         }
1189 
1190         //
1191         // If nothing failed, delete all the unloaded modules that weren't reloaded
1192         //
1193         if(!results.wasLoaded(existingConfigurationId) && !results.wasFailed(existingConfigurationId)) {
1194             try {
1195                 uninstallConfiguration(existingConfigurationId);
1196             } catch (IOException e) {
1197                 log.error("Unable to uninstall configuration "+existingConfigurationId, e);
1198             }
1199         }
1200 
1201         monitor.finished();
1202         if (results.wasFailed(newConfigurationId) || !results.wasLoaded(newConfigurationId)) {
1203             throw new LifecycleException("restart", newConfigurationId, results);
1204         }
1205         return results;
1206     }
1207 
1208     protected void migrateConfiguration(Artifact oldName, Artifact newName, Configuration configuration, boolean running) throws NoSuchConfigException {
1209     }
1210 
1211     private static LinkedHashSet getResolvedParentIds(Configuration configuration) {
1212         LinkedHashSet resolvedParentIds = new LinkedHashSet();
1213         for (Iterator iterator = configuration.getClassParents().iterator(); iterator.hasNext();) {
1214             Configuration classParent = (Configuration) iterator.next();
1215             resolvedParentIds.add(classParent.getId());
1216         }
1217         for (Iterator iterator = configuration.getServiceParents().iterator(); iterator.hasNext();) {
1218             Configuration serviceParent = (Configuration) iterator.next();
1219             resolvedParentIds.add(serviceParent.getId());
1220         }
1221         for (Iterator iterator = configuration.getChildren().iterator(); iterator.hasNext();) {
1222             Configuration child = (Configuration) iterator.next();
1223             resolvedParentIds.addAll(getResolvedParentIds(child));
1224         }
1225 
1226         return resolvedParentIds;
1227     }
1228 
1229     public synchronized void uninstallConfiguration(Artifact configurationId) throws IOException, NoSuchConfigException {
1230         if(!configurationId.isResolved()) {
1231             throw new IllegalArgumentException("Artifact "+configurationId+" is not fully resolved");
1232         }
1233         if (configurations.containsKey(configurationId)) {
1234             if(isRunning(configurationId)) {
1235                 stopConfiguration(configurationId);
1236             }
1237             if(isLoaded((configurationId))) {
1238                 unloadConfiguration(configurationId);
1239             }
1240         }
1241 
1242         List storeSnapshot = getStoreList();
1243         for (int i = 0; i < storeSnapshot.size(); i++) {
1244             ConfigurationStore store = (ConfigurationStore) storeSnapshot.get(i);
1245             if(store.containsConfiguration(configurationId)) {
1246                 store.uninstall(configurationId);
1247             }
1248         }
1249 
1250         removeConfigurationFromModel(configurationId);
1251         notifyWatchers(configurationId);
1252     }
1253 
1254     private void notifyWatchers(Artifact id) {
1255         for (Iterator it = watchers.iterator(); it.hasNext();) {
1256             DeploymentWatcher watcher = (DeploymentWatcher) it.next();
1257             watcher.undeployed(id);
1258         }
1259     }
1260 
1261     public ArtifactResolver getArtifactResolver() {
1262         return artifactResolver;
1263     }
1264 
1265     /**
1266      * this configuration manager never starts configurations.
1267      * @return false
1268      */
1269     public boolean isOnline() {
1270         return false;
1271     }
1272 
1273     public void setOnline(boolean online) {
1274     }
1275 
1276     private List getStoreList() {
1277         return new ArrayList(stores);
1278     }
1279 
1280     private static void addConfigurationsToMonitor(LifecycleMonitor monitor, LinkedHashSet configurations) {
1281         for (Iterator iterator = configurations.iterator(); iterator.hasNext();) {
1282             Artifact configurationId = (Artifact) iterator.next();
1283             monitor.addConfiguration(configurationId);
1284         }
1285     }
1286 
1287     private static LinkedHashSet reverse(LinkedHashSet set) {
1288         ArrayList reverseList = new ArrayList(set);
1289         Collections.reverse(reverseList);
1290         set = new LinkedHashSet(reverseList);
1291         return set;
1292     }
1293 
1294     private static LinkedHashMap reverse(LinkedHashMap map) {
1295         ArrayList reverseEntrySet = new ArrayList(map.entrySet());
1296         Collections.reverse(reverseEntrySet);
1297 
1298         map = new LinkedHashMap(reverseEntrySet.size());
1299         for (Iterator iterator = reverseEntrySet.iterator(); iterator.hasNext();) {
1300             Map.Entry entry = (Map.Entry) iterator.next();
1301             Object key = entry.getKey();
1302             Object value = entry.getValue();
1303             map.put(key, value);
1304         }
1305         return map;
1306     }
1307 }