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