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 }