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