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