001 /**
002 *
003 * Copyright 2003-2004 The Apache Software Foundation
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * 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
018 package org.apache.geronimo.kernel.config;
019
020 import java.io.File;
021 import java.io.IOException;
022 import java.net.MalformedURLException;
023 import java.net.URL;
024 import java.util.ArrayList;
025 import java.util.Collection;
026 import java.util.Collections;
027 import java.util.HashMap;
028 import java.util.Iterator;
029 import java.util.LinkedHashSet;
030 import java.util.List;
031 import java.util.ListIterator;
032 import java.util.Map;
033 import java.util.Set;
034
035 import javax.management.MalformedObjectNameException;
036 import javax.management.ObjectName;
037
038 import org.apache.commons.logging.Log;
039 import org.apache.commons.logging.LogFactory;
040 import org.apache.geronimo.gbean.AbstractName;
041 import org.apache.geronimo.gbean.AbstractNameQuery;
042 import org.apache.geronimo.gbean.GBeanData;
043 import org.apache.geronimo.gbean.GBeanInfo;
044 import org.apache.geronimo.gbean.GBeanInfoBuilder;
045 import org.apache.geronimo.gbean.GBeanLifecycle;
046 import org.apache.geronimo.gbean.ReferencePatterns;
047 import org.apache.geronimo.kernel.GBeanAlreadyExistsException;
048 import org.apache.geronimo.kernel.GBeanNotFoundException;
049 import org.apache.geronimo.kernel.Naming;
050 import org.apache.geronimo.kernel.classloader.JarFileClassLoader;
051 import org.apache.geronimo.kernel.repository.Artifact;
052 import org.apache.geronimo.kernel.repository.Dependency;
053 import org.apache.geronimo.kernel.repository.Environment;
054 import org.apache.geronimo.kernel.repository.ImportType;
055 import org.apache.geronimo.kernel.repository.MissingDependencyException;
056
057 /**
058 * A Configuration represents a collection of runnable services that can be
059 * loaded into a Geronimo Kernel and brought online. The primary components in
060 * a Configuration are a codebase, represented by a collection of URLs that
061 * is used to locate classes, and a collection of GBean instances that define
062 * its state.
063 * <p/>
064 * The persistent attributes of the Configuration are:
065 * <ul>
066 * <li>its unique configId used to identify this specific config</li>
067 * <li>the configId of a parent Configuration on which this one is dependent</li>
068 * <li>a List<URI> of code locations (which may be absolute or relative to a baseURL)</li>
069 * <li>a byte[] holding the state of the GBeans instances in Serialized form</li>
070 * </ul>
071 * When a configuration is started, it converts the URIs into a set of absolute
072 * URLs by resolving them against the specified baseURL (this would typically
073 * be the root of the CAR file which contains the configuration) and then
074 * constructs a ClassLoader for that codebase. That ClassLoader is then used
075 * to de-serialize the persisted GBeans, ensuring the GBeans can be recycled
076 * as necessary. Once the GBeans have been restored, they are brought online
077 * by registering them with the MBeanServer.
078 * <p/>
079 * A dependency on the Configuration is created for every GBean it loads. As a
080 * result, a startRecursive() operation on the configuration will result in
081 * a startRecursive() for all the GBeans it contains. Similarly, if the
082 * Configuration is stopped then all of its GBeans will be stopped as well.
083 *
084 * @version $Rev:385718 $ $Date: 2006-11-06 02:28:54 -0800 (Mon, 06 Nov 2006) $
085 */
086 public class Configuration implements GBeanLifecycle, ConfigurationParent {
087 private static final Log log = LogFactory.getLog(Configuration.class);
088
089 /**
090 * Converts an Artifact to an AbstractName for a configuration. Does not
091 * validate that this is a reasonable or resolved Artifact, or that it
092 * corresponds to an actual Configuration.
093 */
094 public static AbstractName getConfigurationAbstractName(Artifact configId) throws InvalidConfigException {
095 return new AbstractName(configId, Collections.singletonMap("configurationName", configId.toString()), getConfigurationObjectName(configId));
096 }
097
098 public static boolean isConfigurationObjectName(ObjectName name) {
099 return name.getDomain().equals("geronimo.config") && name.getKeyPropertyList().size() == 1 && name.getKeyProperty("name") != null;
100 }
101
102 public static Artifact getConfigurationID(ObjectName objectName) {
103 if (isConfigurationObjectName(objectName)) {
104 String name = ObjectName.unquote(objectName.getKeyProperty("name"));
105 return Artifact.create(name);
106 } else {
107 throw new IllegalArgumentException("ObjectName " + objectName + " is not a Configuration name");
108 }
109 }
110
111 private static ObjectName getConfigurationObjectName(Artifact configId) throws InvalidConfigException {
112 try {
113 return new ObjectName("geronimo.config:name=" + ObjectName.quote(configId.toString()));
114 } catch (MalformedObjectNameException e) {
115 throw new InvalidConfigException("Could not construct object name for configuration", e);
116 }
117 }
118
119 /**
120 * The artifact id for this configuration.
121 */
122 private final Artifact id;
123
124 /**
125 * The registered abstractName for this configuraion.
126 */
127 private final AbstractName abstractName;
128
129 /**
130 * Defines the environment requred for this configuration.
131 */
132 private final Environment environment;
133
134 /**
135 * Used to resolve dependecies and paths
136 */
137 private final ConfigurationResolver configurationResolver;
138
139 /**
140 * Parent configurations used for class loader.
141 */
142 private final List classParents = new ArrayList();
143
144 /**
145 * Parent configuations used for service resolution.
146 */
147 private final List serviceParents = new ArrayList();
148
149 /**
150 * All service parents depth first
151 */
152 private final List allServiceParents = new ArrayList();
153
154 /**
155 * Artifacts added to the class loader (non-configuation artifacts).
156 */
157 private final LinkedHashSet dependencies = new LinkedHashSet();
158
159 /**
160 * The GBeanData objects by ObjectName
161 */
162 private final Map gbeans = new HashMap();
163
164 /**
165 * The classloader used to load the child GBeans contained in this configuration.
166 */
167 private final MultiParentClassLoader configurationClassLoader;
168
169 /**
170 * The relative class path (URI) of this configuation.
171 */
172 private final LinkedHashSet classPath;
173
174 /**
175 * Naming system used when generating a name for a new gbean
176 */
177 private final Naming naming;
178
179 /**
180 * Environment, classpath, gbeans and other data for this configuration.
181 */
182 private ConfigurationData configurationData;
183
184 /**
185 * The nested configurations of this configuration.
186 */
187 List children = new ArrayList();
188
189 /**
190 * The parent of this configuration;
191 */
192 private Configuration parent = null;
193
194 /**
195 * Only used to allow declaration as a reference.
196 */
197 public Configuration() {
198 id = null;
199 abstractName = null;
200 environment = null;
201 classPath = null;
202 configurationResolver = null;
203 configurationClassLoader = null;
204 naming = null;
205 }
206
207 /**
208 * Creates a configuration.
209 * @param parents parents of this configuation (not ordered)
210 * @param configurationData the module type, environment and classpath of the configuration
211 * @param configurationResolver used to resolve dependecies and paths
212 */
213 public Configuration(Collection parents,
214 ConfigurationData configurationData,
215 ConfigurationResolver configurationResolver,
216 ManageableAttributeStore attributeStore) throws MissingDependencyException, MalformedURLException, NoSuchConfigException, InvalidConfigException {
217 if (parents == null) parents = Collections.EMPTY_SET;
218 if (configurationData == null) throw new NullPointerException("configurationData is null");
219 if (configurationResolver == null) throw new NullPointerException("configurationResolver is null");
220
221 this.configurationData = configurationData;
222 this.environment = configurationData.getEnvironment();
223 this.configurationResolver = configurationResolver;
224 this.classPath = new LinkedHashSet(configurationData.getClassPath());
225 this.naming = configurationData.getNaming();
226
227 this.id = environment.getConfigId();
228 abstractName = getConfigurationAbstractName(id);
229
230 //
231 // Transitively resolve all the dependencies in the environment
232 //
233 List transtiveDependencies = configurationResolver.resolveTransitiveDependencies(parents, environment.getDependencies());
234
235 //
236 // Process transtive dependencies splitting it into classParents, serviceParents and artifactDependencies
237 //
238 Map parentsById = new HashMap();
239 for (Iterator iterator = parents.iterator(); iterator.hasNext();) {
240 Configuration configuration = (Configuration) iterator.next();
241 Artifact id = configuration.getId();
242 parentsById.put(id, configuration);
243 }
244
245 for (Iterator iterator = transtiveDependencies.iterator(); iterator.hasNext();) {
246 Dependency dependency = (Dependency) iterator.next();
247 Artifact artifact = dependency.getArtifact();
248 if (parentsById.containsKey(artifact)) {
249 Configuration parent = (Configuration) parentsById.get(artifact);
250 if (dependency.getImportType() == ImportType.CLASSES || dependency.getImportType() == ImportType.ALL) {
251 classParents.add(parent);
252 }
253 if (dependency.getImportType() == ImportType.SERVICES || dependency.getImportType() == ImportType.ALL) {
254 serviceParents.add(parent);
255 }
256 } else if (dependency.getImportType() == ImportType.SERVICES) {
257 throw new IllegalStateException("Could not find parent " + artifact + " in the parents collection");
258 } else {
259 dependencies.add(artifact);
260 }
261 }
262
263 try {
264 //
265 // Build the configuration class loader
266 //
267 configurationClassLoader = createConfigurationClasssLoader(parents, environment, classPath);
268
269 //
270 // Get all service parents in depth first order
271 //
272 addDepthFirstServiceParents(this, allServiceParents);
273
274 //
275 // Deserialize the GBeans in the configurationData
276 //
277 Collection gbeans = configurationData.getGBeans(configurationClassLoader);
278 if (attributeStore != null) {
279 gbeans = attributeStore.applyOverrides(id, gbeans, configurationClassLoader);
280 }
281 for (Iterator iterator = gbeans.iterator(); iterator.hasNext();) {
282 GBeanData gbeanData = (GBeanData) iterator.next();
283 this.gbeans.put(gbeanData.getAbstractName(), gbeanData);
284 }
285
286 //
287 // Create child configurations
288 //
289 LinkedHashSet childParents = new LinkedHashSet(parents);
290 childParents.add(this);
291 for (Iterator iterator = configurationData.getChildConfigurations().entrySet().iterator(); iterator.hasNext();) {
292 Map.Entry entry = (Map.Entry) iterator.next();
293 String moduleName = (String) entry.getKey();
294 ConfigurationData childConfigurationData = (ConfigurationData) entry.getValue();
295 Configuration childConfiguration = new Configuration(childParents, childConfigurationData, configurationResolver.createChildResolver(moduleName), attributeStore);
296 childConfiguration.parent = this;
297 children.add(childConfiguration);
298 }
299 } catch (RuntimeException e) {
300 shutdown();
301 throw e;
302 } catch (Error e) {
303 shutdown();
304 throw e;
305 } catch (MissingDependencyException e) {
306 shutdown();
307 throw e;
308 } catch (MalformedURLException e) {
309 shutdown();
310 throw e;
311 } catch (NoSuchConfigException e) {
312 shutdown();
313 throw e;
314 } catch (InvalidConfigException e) {
315 shutdown();
316 throw e;
317 }
318 }
319
320 private MultiParentClassLoader createConfigurationClasssLoader(Collection parents, Environment environment, LinkedHashSet classPath) throws MalformedURLException, MissingDependencyException, NoSuchConfigException {
321 // create the URL list
322 URL[] urls = buildClassPath(classPath);
323
324 // parents
325 ClassLoader[] parentClassLoaders;
326 if (parents.size() == 0 && classParents.size() == 0) {
327 // no explicit parent set, so use the class loader of this class as
328 // the parent... this class should be in the root geronimo classloader,
329 // which is normally the system class loader but not always, so be safe
330 parentClassLoaders = new ClassLoader[] {getClass().getClassLoader()};
331 } else {
332 parentClassLoaders = new ClassLoader[classParents.size()];
333 for (ListIterator iterator = classParents.listIterator(); iterator.hasNext();) {
334 Configuration configuration = (Configuration) iterator.next();
335 parentClassLoaders[iterator.previousIndex()] = configuration.getConfigurationClassLoader();
336 }
337 }
338
339 // hidden classes
340 Set hiddenClassesSet = environment.getHiddenClasses();
341 String[] hiddenClasses = (String[]) hiddenClassesSet.toArray(new String[hiddenClassesSet.size()]);
342
343 // we need to propagate the non-overrideable classes from parents
344 LinkedHashSet nonOverridableSet = new LinkedHashSet();
345 for (Iterator iterator = classParents.iterator(); iterator.hasNext();) {
346 Configuration parent = (Configuration) iterator.next();
347
348 Environment parentEnvironment = parent.getEnvironment();
349 nonOverridableSet.addAll(parentEnvironment.getNonOverrideableClasses());
350 }
351 String[] nonOverridableClasses = (String[]) nonOverridableSet.toArray(new String[nonOverridableSet.size()]);
352
353 if (log.isDebugEnabled()) {
354 StringBuffer buf = new StringBuffer("ClassLoader structure for configuration ").append(id).append("\n");
355 buf.append("Parent configurations:\n");
356 for (Iterator iterator = classParents.iterator(); iterator.hasNext();) {
357 Configuration configuration = (Configuration) iterator.next();
358 buf.append(" ").append(configuration.getId()).append("\n");
359 }
360 buf.append("ClassPath:\n");
361 for (int i = 0; i < urls.length; i++) {
362 URL url = urls[i];
363 buf.append(" ").append(url).append("\n");
364 }
365 log.debug(buf.toString());
366 }
367
368 if (Boolean.getBoolean("Xorg.apache.geronimo.OldClassLoader")) {
369 return new MultiParentClassLoader(environment.getConfigId(),
370 urls,
371 parentClassLoaders,
372 environment.isInverseClassLoading(),
373 hiddenClasses,
374 nonOverridableClasses);
375 } else {
376 return new JarFileClassLoader(environment.getConfigId(),
377 urls,
378 parentClassLoaders,
379 environment.isInverseClassLoading(),
380 hiddenClasses,
381 nonOverridableClasses);
382 }
383 }
384
385 private void addDepthFirstServiceParents(Configuration configuration, List ancestors) {
386 ancestors.add(configuration);
387 for (Iterator parents = configuration.getServiceParents().iterator(); parents.hasNext();) {
388 Configuration parent = (Configuration) parents.next();
389 addDepthFirstServiceParents(parent, ancestors);
390 }
391 }
392
393 private URL[] buildClassPath(LinkedHashSet classPath) throws MalformedURLException, MissingDependencyException, NoSuchConfigException {
394 List urls = new ArrayList();
395 for (Iterator i = dependencies.iterator(); i.hasNext();) {
396 Artifact artifact = (Artifact) i.next();
397 File file = configurationResolver.resolve(artifact);
398 urls.add(file.toURL());
399 }
400 if (classPath != null) {
401 for (Iterator i = classPath.iterator(); i.hasNext();) {
402 String pattern = (String) i.next();
403 Set matches = configurationResolver.resolve(pattern);
404 for (Iterator iterator = matches.iterator(); iterator.hasNext();) {
405 URL url = (URL) iterator.next();
406 urls.add(url);
407 }
408 }
409 }
410 return (URL[]) urls.toArray(new URL[urls.size()]);
411 }
412
413 /**
414 * Return the unique Id
415 * @return the unique Id
416 */
417 public Artifact getId() {
418 return id;
419 }
420
421 /**
422 * Gets the unique name of this configuration within the kernel.
423 * @return the unique name of this configuration
424 */
425 public String getObjectName() {
426 try {
427 return getConfigurationObjectName(id).getCanonicalName();
428 } catch (InvalidConfigException e) {
429 throw new AssertionError(e);
430 }
431 }
432
433 public AbstractName getAbstractName() {
434 return abstractName;
435 }
436
437 /**
438 * Gets the parent configurations used for class loading.
439 * @return the parents of this configuration used for class loading
440 */
441 public List getClassParents() {
442 return classParents;
443 }
444
445 /**
446 * Gets the parent configurations used for service resolution.
447 * @return the parents of this configuration used for service resolution
448 */
449 public List getServiceParents() {
450 return serviceParents;
451 }
452
453 /**
454 * Gets the artifact dependencies of this configuration.
455 * @return the artifact dependencies of this configuration
456 */
457 public LinkedHashSet getDependencies() {
458 return dependencies;
459 }
460
461 /**
462 * Gets the declaration of the environment in which this configuration runs.
463 * @return the environment of this configuration
464 */
465 public Environment getEnvironment() {
466 return environment;
467 }
468
469 /**
470 * This is used by the configuration manager to restart an existing configuation.
471 * Do not modify the configuation data.
472 * @return the configuation data for this configuration; do not modify
473 */
474 ConfigurationData getConfigurationData() {
475 return configurationData;
476 }
477
478 /**
479 * @deprecated this is only exposed temporarily for configuration manager
480 */
481 public ConfigurationResolver getConfigurationResolver() {
482 return configurationResolver;
483 }
484
485 /**
486 * Gets the relative class path (URIs) of this configuration.
487 * @return the relative class path of this configuation
488 */
489 public List getClassPath() {
490 return new ArrayList(classPath);
491 }
492
493 public void addToClassPath(String pattern) throws IOException {
494 if (!classPath.contains(pattern)) {
495 try {
496 Set matches = configurationResolver.resolve(pattern);
497 for (Iterator iterator = matches.iterator(); iterator.hasNext();) {
498 URL url = (URL) iterator.next();
499 configurationClassLoader.addURL(url);
500 }
501 classPath.add(pattern);
502 } catch (Exception e) {
503 throw new IOException("Unable to extend classpath with " + pattern);
504 }
505 }
506 }
507
508 /**
509 * Gets the type of the configuration (WAR, RAR et cetera)
510 * @return Type of the configuration.
511 */
512 public ConfigurationModuleType getModuleType() {
513 return configurationData.getModuleType();
514 }
515
516 /**
517 * Gets the time at which this configuration was created (or deployed).
518 * @return the time at which this configuration was created (or deployed)
519 */
520 public long getCreated() {
521 return configurationData.getCreated();
522 }
523
524 /**
525 * Gets the class loader for this configuration.
526 * @return the class loader for this configuration
527 */
528 public ClassLoader getConfigurationClassLoader() {
529 return configurationClassLoader;
530 }
531
532 /**
533 * Gets the nested configurations of this configuration. That is, the
534 * configurations within this one as a WAR can be within an EAR; not
535 * including wholly separate configurations that just depend on this
536 * one as a parent.
537 *
538 * @return the nested configuration of this configuration
539 */
540 public List getChildren() {
541 return Collections.unmodifiableList(children);
542 }
543
544 /**
545 * Gets the configurations owned by this configuration. This is only used for cascade-uninstall.
546 * @return the configurations owned by this configuration
547 */
548 public Set getOwnedConfigurations() {
549 return configurationData.getOwnedConfigurations();
550 }
551
552 /**
553 * Gets an unmodifiable collection of the GBeanDatas for the GBeans in this configuration.
554 * @return the GBeans in this configuration
555 */
556 public Map getGBeans() {
557 return Collections.unmodifiableMap(gbeans);
558 }
559
560 /**
561 * Determines of this configuration constains the specified GBean.
562 * @param gbean the name of the GBean
563 * @return true if this configuration contains the specified GBean; false otherwise
564 */
565 public synchronized boolean containsGBean(AbstractName gbean) {
566 return gbeans.containsKey(gbean);
567 }
568
569 /**
570 * Gets the enclosing configuration of this one (e.g. the EAR for a WAR),
571 * or null if it has none.
572 */
573 public Configuration getEnclosingConfiguration() {
574 return parent;
575 }
576
577 public synchronized AbstractName addGBean(String name, GBeanData gbean) throws GBeanAlreadyExistsException {
578 AbstractName abstractName = gbean.getAbstractName();
579 if (abstractName != null) {
580 throw new IllegalArgumentException("gbean already has an abstract name: " + abstractName);
581 }
582
583 String j2eeType = gbean.getGBeanInfo().getJ2eeType();
584 if (j2eeType == null) j2eeType = "GBean";
585 abstractName = naming.createRootName(id, name, j2eeType);
586 gbean.setAbstractName(abstractName);
587
588 if (gbeans.containsKey(abstractName)) {
589 throw new GBeanAlreadyExistsException(gbean.getAbstractName().toString());
590 }
591 gbeans.put(abstractName, gbean);
592 return abstractName;
593 }
594
595 public synchronized void addGBean(GBeanData gbean) throws GBeanAlreadyExistsException {
596 if (gbeans.containsKey(gbean.getAbstractName())) {
597 throw new GBeanAlreadyExistsException(gbean.getAbstractName().toString());
598 }
599 gbeans.put(gbean.getAbstractName(), gbean);
600 }
601
602 public synchronized void removeGBean(AbstractName name) throws GBeanNotFoundException {
603 if (!gbeans.containsKey(name)) {
604 throw new GBeanNotFoundException(name);
605 }
606 gbeans.remove(name);
607 }
608
609 public AbstractName findGBean(AbstractNameQuery pattern) throws GBeanNotFoundException {
610 if (pattern == null) throw new NullPointerException("pattern is null");
611 return findGBean(Collections.singleton(pattern));
612 }
613
614 public GBeanData findGBeanData(AbstractNameQuery pattern) throws GBeanNotFoundException {
615 if (pattern == null) throw new NullPointerException("pattern is null");
616 return findGBeanData(Collections.singleton(pattern));
617 }
618
619 public AbstractName findGBean(ReferencePatterns referencePatterns) throws GBeanNotFoundException {
620 if (referencePatterns == null) throw new NullPointerException("referencePatterns is null");
621 if (referencePatterns.isResolved()) {
622 return referencePatterns.getAbstractName();
623 }
624
625 // check the local config
626 Set patterns = referencePatterns.getPatterns();
627 return findGBean(patterns);
628 }
629
630 public AbstractName findGBean(Set patterns) throws GBeanNotFoundException {
631 if (patterns == null) throw new NullPointerException("patterns is null");
632 return findGBeanData(patterns).getAbstractName();
633 }
634
635 public GBeanData findGBeanData(Set patterns) throws GBeanNotFoundException {
636 if (patterns == null) throw new NullPointerException("patterns is null");
637 Set result = findGBeanDatas(this, patterns);
638 if (result.size() > 1) {
639 throw new GBeanNotFoundException("More than one match to referencePatterns", patterns);
640 } else if (result.size() == 1) {
641 return (GBeanData) result.iterator().next();
642 }
643
644 // search all parents
645 for (Iterator iterator = allServiceParents.iterator(); iterator.hasNext();) {
646 Configuration configuration = (Configuration) iterator.next();
647 result.addAll(findGBeanDatas(configuration, patterns));
648
649 // if we already found a match we have an ambiguous query
650 if (result.size() > 1) {
651 List names = new ArrayList(result.size());
652 for (Iterator iterator1 = result.iterator(); iterator1.hasNext();) {
653 GBeanData gBeanData = (GBeanData) iterator1.next();
654 names.add(gBeanData.getAbstractName());
655 }
656 throw new GBeanNotFoundException("More than one match to referencePatterns: " + names.toString(), patterns);
657 }
658 }
659
660 if (result.isEmpty()) {
661 throw new GBeanNotFoundException("No matches for referencePatterns", patterns);
662 }
663
664 return (GBeanData) result.iterator().next();
665 }
666
667 public LinkedHashSet findGBeans(AbstractNameQuery pattern) {
668 if (pattern == null) throw new NullPointerException("pattern is null");
669 return findGBeans(Collections.singleton(pattern));
670 }
671
672 public LinkedHashSet findGBeans(ReferencePatterns referencePatterns) {
673 if (referencePatterns == null) throw new NullPointerException("referencePatterns is null");
674 if (referencePatterns.getAbstractName() != null) {
675 // this pattern is already resolved
676 LinkedHashSet result = new LinkedHashSet();
677 result.add(referencePatterns.getAbstractName());
678 return result;
679 }
680
681 // check the local config
682 Set patterns = referencePatterns.getPatterns();
683 return findGBeans(patterns);
684 }
685
686 public LinkedHashSet findGBeans(Set patterns) {
687 if (patterns == null) throw new NullPointerException("patterns is null");
688 LinkedHashSet datas = findGBeanDatas(patterns);
689 LinkedHashSet result = new LinkedHashSet(datas.size());
690 for (Iterator iterator = datas.iterator(); iterator.hasNext();) {
691 GBeanData gBeanData = (GBeanData) iterator.next();
692 result.add(gBeanData.getAbstractName());
693 }
694
695 return result;
696 }
697
698 public LinkedHashSet findGBeanDatas(Set patterns) {
699 if (patterns == null) throw new NullPointerException("patterns is null");
700 LinkedHashSet datas = findGBeanDatas(this, patterns);
701
702 // search all parents
703 for (Iterator iterator = allServiceParents.iterator(); iterator.hasNext();) {
704 Configuration configuration = (Configuration) iterator.next();
705 Set match = findGBeanDatas(configuration, patterns);
706 datas.addAll(match);
707 }
708 return datas;
709 }
710
711 private LinkedHashSet findGBeanDatas(Configuration configuration, Set patterns) {
712 LinkedHashSet result = new LinkedHashSet();
713
714 Set gbeanNames = configuration.getGBeans().entrySet();
715 for (Iterator abstractNameQueries = patterns.iterator(); abstractNameQueries.hasNext();) {
716 AbstractNameQuery abstractNameQuery = (AbstractNameQuery) abstractNameQueries.next();
717 Artifact queryArtifact = abstractNameQuery.getArtifact();
718
719 // Does this query apply to this configuration
720 if (queryArtifact == null || queryArtifact.matches(configuration.getId())) {
721
722 // Search the GBeans
723 for (Iterator iterator = gbeanNames.iterator(); iterator.hasNext();) {
724 Map.Entry entry = (Map.Entry) iterator.next();
725 AbstractName abstractName = (AbstractName) entry.getKey();
726 GBeanData gbeanData = (GBeanData) entry.getValue();
727 if (abstractNameQuery.matches(abstractName, gbeanData.getGBeanInfo().getInterfaces())) {
728 result.add(gbeanData);
729 }
730 }
731 }
732 }
733 return result;
734 }
735
736 public void doStart() throws Exception {
737 log.debug("Started configuration " + id);
738 }
739
740 public synchronized void doStop() throws Exception {
741 log.debug("Stopping configuration " + id);
742 shutdown();
743
744 }
745
746 public void doFail() {
747 log.debug("Failed configuration " + id);
748 shutdown();
749 }
750
751 private void shutdown() {
752 for (Iterator iterator = children.iterator(); iterator.hasNext();) {
753 Configuration configuration = (Configuration) iterator.next();
754 configuration.shutdown();
755 }
756
757 // clear references to GBeanDatas
758 gbeans.clear();
759
760 // destroy the class loader
761 if (configurationClassLoader != null) {
762 configurationClassLoader.destroy();
763 }
764 }
765
766 public static final GBeanInfo GBEAN_INFO;
767
768 static {
769 GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(Configuration.class);//does not use jsr-77 naming
770 infoFactory.addReference("Parents", Configuration.class);
771 infoFactory.addAttribute("configurationData", ConfigurationData.class, true, false);
772 infoFactory.addAttribute("configurationResolver", ConfigurationResolver.class, true);
773 infoFactory.addAttribute("managedAttributeStore", ManageableAttributeStore.class, true);
774
775 infoFactory.addInterface(Configuration.class);
776
777 infoFactory.setConstructor(new String[]{
778 "Parents",
779 "configurationData",
780 "configurationResolver",
781 "managedAttributeStore"
782 });
783
784 GBEAN_INFO = infoFactory.getBeanInfo();
785 }
786
787 public static GBeanInfo getGBeanInfo() {
788 return GBEAN_INFO;
789 }
790 }