1 17 18 package org.apache.geronimo.kernel.config; 19 20 import java.io.File ; 21 import java.io.IOException ; 22 import java.net.MalformedURLException ; 23 import java.net.URL ; 24 import java.util.ArrayList ; 25 import java.util.Collection ; 26 import java.util.Collections ; 27 import java.util.HashMap ; 28 import java.util.Iterator ; 29 import java.util.LinkedHashSet ; 30 import java.util.List ; 31 import java.util.ListIterator ; 32 import java.util.Map ; 33 import java.util.Set ; 34 import java.util.HashSet ; 35 36 import javax.management.MalformedObjectNameException ; 37 import javax.management.ObjectName ; 38 39 import org.apache.commons.logging.Log; 40 import org.apache.commons.logging.LogFactory; 41 import org.apache.geronimo.gbean.AbstractName; 42 import org.apache.geronimo.gbean.AbstractNameQuery; 43 import org.apache.geronimo.gbean.GBeanData; 44 import org.apache.geronimo.gbean.GBeanInfo; 45 import org.apache.geronimo.gbean.GBeanInfoBuilder; 46 import org.apache.geronimo.gbean.GBeanLifecycle; 47 import org.apache.geronimo.gbean.ReferencePatterns; 48 import org.apache.geronimo.kernel.GBeanAlreadyExistsException; 49 import org.apache.geronimo.kernel.GBeanNotFoundException; 50 import org.apache.geronimo.kernel.Naming; 51 import org.apache.geronimo.kernel.classloader.JarFileClassLoader; 52 import org.apache.geronimo.kernel.repository.Artifact; 53 import org.apache.geronimo.kernel.repository.Dependency; 54 import org.apache.geronimo.kernel.repository.Environment; 55 import org.apache.geronimo.kernel.repository.ImportType; 56 import org.apache.geronimo.kernel.repository.MissingDependencyException; 57 58 87 public class Configuration implements GBeanLifecycle, ConfigurationParent { 88 private static final Log log = LogFactory.getLog(Configuration.class); 89 90 95 public static AbstractName getConfigurationAbstractName(Artifact configId) throws InvalidConfigException { 96 return new AbstractName(configId, Collections.singletonMap("configurationName", configId.toString()), getConfigurationObjectName(configId)); 97 } 98 99 public static boolean isConfigurationObjectName(ObjectName name) { 100 return name.getDomain().equals("geronimo.config") && name.getKeyPropertyList().size() == 1 && name.getKeyProperty("name") != null; 101 } 102 103 public static Artifact getConfigurationID(ObjectName objectName) { 104 if (isConfigurationObjectName(objectName)) { 105 String name = ObjectName.unquote(objectName.getKeyProperty("name")); 106 return Artifact.create(name); 107 } else { 108 throw new IllegalArgumentException ("ObjectName " + objectName + " is not a Configuration name"); 109 } 110 } 111 112 private static ObjectName getConfigurationObjectName(Artifact configId) throws InvalidConfigException { 113 try { 114 return new ObjectName ("geronimo.config:name=" + ObjectName.quote(configId.toString())); 115 } catch (MalformedObjectNameException e) { 116 throw new InvalidConfigException("Could not construct object name for configuration", e); 117 } 118 } 119 120 123 private final Artifact id; 124 125 128 private final AbstractName abstractName; 129 130 133 private final Environment environment; 134 135 138 private final ConfigurationResolver configurationResolver; 139 140 143 private final List classParents = new ArrayList (); 144 145 148 private final List serviceParents = new ArrayList (); 149 150 153 private final List allServiceParents = new ArrayList (); 154 155 158 private final LinkedHashSet dependencies = new LinkedHashSet (); 159 160 163 private final Map gbeans = new HashMap (); 164 165 168 private final MultiParentClassLoader configurationClassLoader; 169 170 173 private final LinkedHashSet classPath; 174 175 178 private final Naming naming; 179 180 183 private ConfigurationData configurationData; 184 185 188 List children = new ArrayList (); 189 190 193 private Configuration parent = null; 194 195 198 public Configuration() { 199 id = null; 200 abstractName = null; 201 environment = null; 202 classPath = null; 203 configurationResolver = null; 204 configurationClassLoader = null; 205 naming = null; 206 } 207 208 214 public Configuration(Collection parents, 215 ConfigurationData configurationData, 216 ConfigurationResolver configurationResolver, 217 ManageableAttributeStore attributeStore) throws MissingDependencyException, MalformedURLException , NoSuchConfigException, InvalidConfigException { 218 if (parents == null) parents = Collections.EMPTY_SET; 219 if (configurationData == null) throw new NullPointerException ("configurationData is null"); 220 if (configurationResolver == null) throw new NullPointerException ("configurationResolver is null"); 221 222 this.configurationData = configurationData; 223 this.environment = configurationData.getEnvironment(); 224 this.configurationResolver = configurationResolver; 225 this.classPath = new LinkedHashSet (configurationData.getClassPath()); 226 this.naming = configurationData.getNaming(); 227 228 this.id = environment.getConfigId(); 229 abstractName = getConfigurationAbstractName(id); 230 231 List transtiveDependencies = configurationResolver.resolveTransitiveDependencies(parents, environment.getDependencies()); 235 236 Map parentsById = new HashMap (); 240 for (Iterator iterator = parents.iterator(); iterator.hasNext();) { 241 Configuration configuration = (Configuration) iterator.next(); 242 Artifact id = configuration.getId(); 243 parentsById.put(id, configuration); 244 } 245 246 for (Iterator iterator = transtiveDependencies.iterator(); iterator.hasNext();) { 247 Dependency dependency = (Dependency) iterator.next(); 248 Artifact artifact = dependency.getArtifact(); 249 if (parentsById.containsKey(artifact)) { 250 Configuration parent = (Configuration) parentsById.get(artifact); 251 if (dependency.getImportType() == ImportType.CLASSES || dependency.getImportType() == ImportType.ALL) { 252 classParents.add(parent); 253 } 254 if (dependency.getImportType() == ImportType.SERVICES || dependency.getImportType() == ImportType.ALL) { 255 serviceParents.add(parent); 256 } 257 } else if (dependency.getImportType() == ImportType.SERVICES) { 258 throw new IllegalStateException ("Could not find parent " + artifact + " in the parents collection"); 259 } else { 260 dependencies.add(artifact); 261 } 262 } 263 264 try { 265 configurationClassLoader = createConfigurationClasssLoader(parents, environment, classPath); 269 270 274 addDepthFirstServiceParents(this, allServiceParents, new HashSet ()); 275 276 Collection gbeans = configurationData.getGBeans(configurationClassLoader); 280 if (attributeStore != null) { 281 gbeans = attributeStore.applyOverrides(id, gbeans, configurationClassLoader); 282 } 283 for (Iterator iterator = gbeans.iterator(); iterator.hasNext();) { 284 GBeanData gbeanData = (GBeanData) iterator.next(); 285 this.gbeans.put(gbeanData.getAbstractName(), gbeanData); 286 } 287 288 LinkedHashSet childParents = new LinkedHashSet (parents); 292 childParents.add(this); 293 for (Iterator iterator = configurationData.getChildConfigurations().entrySet().iterator(); iterator.hasNext();) { 294 Map.Entry entry = (Map.Entry ) iterator.next(); 295 String moduleName = (String ) entry.getKey(); 296 ConfigurationData childConfigurationData = (ConfigurationData) entry.getValue(); 297 Configuration childConfiguration = new Configuration(childParents, childConfigurationData, configurationResolver.createChildResolver(moduleName), attributeStore); 298 childConfiguration.parent = this; 299 children.add(childConfiguration); 300 } 301 } catch (RuntimeException e) { 302 shutdown(); 303 throw e; 304 } catch (Error e) { 305 shutdown(); 306 throw e; 307 } catch (MissingDependencyException e) { 308 shutdown(); 309 throw e; 310 } catch (MalformedURLException e) { 311 shutdown(); 312 throw e; 313 } catch (NoSuchConfigException e) { 314 shutdown(); 315 throw e; 316 } catch (InvalidConfigException e) { 317 shutdown(); 318 throw e; 319 } 320 } 321 322 private MultiParentClassLoader createConfigurationClasssLoader(Collection parents, Environment environment, LinkedHashSet classPath) throws MalformedURLException , MissingDependencyException, NoSuchConfigException { 323 URL [] urls = buildClassPath(classPath); 325 326 ClassLoader [] parentClassLoaders; 328 if (parents.size() == 0 && classParents.size() == 0) { 329 parentClassLoaders = new ClassLoader [] {getClass().getClassLoader()}; 333 } else { 334 parentClassLoaders = new ClassLoader [classParents.size()]; 335 for (ListIterator iterator = classParents.listIterator(); iterator.hasNext();) { 336 Configuration configuration = (Configuration) iterator.next(); 337 parentClassLoaders[iterator.previousIndex()] = configuration.getConfigurationClassLoader(); 338 } 339 } 340 341 Set hiddenClassesSet = environment.getHiddenClasses(); 343 String [] hiddenClasses = (String []) hiddenClassesSet.toArray(new String [hiddenClassesSet.size()]); 344 345 LinkedHashSet nonOverridableSet = new LinkedHashSet (); 347 for (Iterator iterator = classParents.iterator(); iterator.hasNext();) { 348 Configuration parent = (Configuration) iterator.next(); 349 350 Environment parentEnvironment = parent.getEnvironment(); 351 nonOverridableSet.addAll(parentEnvironment.getNonOverrideableClasses()); 352 } 353 String [] nonOverridableClasses = (String []) nonOverridableSet.toArray(new String [nonOverridableSet.size()]); 354 355 if (log.isDebugEnabled()) { 356 StringBuffer buf = new StringBuffer ("ClassLoader structure for configuration ").append(id).append("\n"); 357 buf.append("Parent configurations:\n"); 358 for (Iterator iterator = classParents.iterator(); iterator.hasNext();) { 359 Configuration configuration = (Configuration) iterator.next(); 360 buf.append(" ").append(configuration.getId()).append("\n"); 361 } 362 buf.append("ClassPath:\n"); 363 for (int i = 0; i < urls.length; i++) { 364 URL url = urls[i]; 365 buf.append(" ").append(url).append("\n"); 366 } 367 log.debug(buf.toString()); 368 } 369 370 if (Boolean.getBoolean("Xorg.apache.geronimo.OldClassLoader")) { 371 return new MultiParentClassLoader(environment.getConfigId(), 372 urls, 373 parentClassLoaders, 374 environment.isInverseClassLoading(), 375 hiddenClasses, 376 nonOverridableClasses); 377 } else { 378 return new JarFileClassLoader(environment.getConfigId(), 379 urls, 380 parentClassLoaders, 381 environment.isInverseClassLoading(), 382 hiddenClasses, 383 nonOverridableClasses); 384 } 385 } 386 387 private void addDepthFirstServiceParents(Configuration configuration, List ancestors, Set ids) { 388 if (!ids.contains(configuration.getId())) { 389 ancestors.add(configuration); 390 ids.add(configuration.getId()); 391 for (Iterator parents = configuration.getServiceParents().iterator(); parents.hasNext();) { 392 Configuration parent = (Configuration) parents.next(); 393 addDepthFirstServiceParents(parent, ancestors, ids); 394 } 395 } 396 } 397 398 private URL [] buildClassPath(LinkedHashSet classPath) throws MalformedURLException , MissingDependencyException, NoSuchConfigException { 399 List urls = new ArrayList (); 400 for (Iterator i = dependencies.iterator(); i.hasNext();) { 401 Artifact artifact = (Artifact) i.next(); 402 File file = configurationResolver.resolve(artifact); 403 urls.add(file.toURL()); 404 } 405 if (classPath != null) { 406 for (Iterator i = classPath.iterator(); i.hasNext();) { 407 String pattern = (String ) i.next(); 408 Set matches = configurationResolver.resolve(pattern); 409 for (Iterator iterator = matches.iterator(); iterator.hasNext();) { 410 URL url = (URL ) iterator.next(); 411 urls.add(url); 412 } 413 } 414 } 415 return (URL []) urls.toArray(new URL [urls.size()]); 416 } 417 418 422 public Artifact getId() { 423 return id; 424 } 425 426 430 public String getObjectName() { 431 try { 432 return getConfigurationObjectName(id).getCanonicalName(); 433 } catch (InvalidConfigException e) { 434 throw new AssertionError (e); 435 } 436 } 437 438 public AbstractName getAbstractName() { 439 return abstractName; 440 } 441 442 446 public List getClassParents() { 447 return classParents; 448 } 449 450 454 public List getServiceParents() { 455 return serviceParents; 456 } 457 458 462 public LinkedHashSet getDependencies() { 463 return dependencies; 464 } 465 466 470 public Environment getEnvironment() { 471 return environment; 472 } 473 474 479 ConfigurationData getConfigurationData() { 480 return configurationData; 481 } 482 483 486 public ConfigurationResolver getConfigurationResolver() { 487 return configurationResolver; 488 } 489 490 494 public List getClassPath() { 495 return new ArrayList (classPath); 496 } 497 498 public void addToClassPath(String pattern) throws IOException { 499 if (!classPath.contains(pattern)) { 500 try { 501 Set matches = configurationResolver.resolve(pattern); 502 for (Iterator iterator = matches.iterator(); iterator.hasNext();) { 503 URL url = (URL ) iterator.next(); 504 configurationClassLoader.addURL(url); 505 } 506 classPath.add(pattern); 507 } catch (Exception e) { 508 throw new IOException ("Unable to extend classpath with " + pattern); 509 } 510 } 511 } 512 513 517 public ConfigurationModuleType getModuleType() { 518 return configurationData.getModuleType(); 519 } 520 521 525 public long getCreated() { 526 return configurationData.getCreated(); 527 } 528 529 533 public ClassLoader getConfigurationClassLoader() { 534 return configurationClassLoader; 535 } 536 537 545 public List getChildren() { 546 return Collections.unmodifiableList(children); 547 } 548 549 553 public Set getOwnedConfigurations() { 554 return configurationData.getOwnedConfigurations(); 555 } 556 557 561 public Map getGBeans() { 562 return Collections.unmodifiableMap(gbeans); 563 } 564 565 570 public synchronized boolean containsGBean(AbstractName gbean) { 571 return gbeans.containsKey(gbean); 572 } 573 574 578 public Configuration getEnclosingConfiguration() { 579 return parent; 580 } 581 582 public synchronized AbstractName addGBean(String name, GBeanData gbean) throws GBeanAlreadyExistsException { 583 AbstractName abstractName = gbean.getAbstractName(); 584 if (abstractName != null) { 585 throw new IllegalArgumentException ("gbean already has an abstract name: " + abstractName); 586 } 587 588 String j2eeType = gbean.getGBeanInfo().getJ2eeType(); 589 if (j2eeType == null) j2eeType = "GBean"; 590 abstractName = naming.createRootName(id, name, j2eeType); 591 gbean.setAbstractName(abstractName); 592 593 if (gbeans.containsKey(abstractName)) { 594 throw new GBeanAlreadyExistsException(gbean.getAbstractName().toString()); 595 } 596 gbeans.put(abstractName, gbean); 597 return abstractName; 598 } 599 600 public synchronized void addGBean(GBeanData gbean) throws GBeanAlreadyExistsException { 601 if (gbeans.containsKey(gbean.getAbstractName())) { 602 throw new GBeanAlreadyExistsException(gbean.getAbstractName().toString()); 603 } 604 gbeans.put(gbean.getAbstractName(), gbean); 605 } 606 607 public synchronized void removeGBean(AbstractName name) throws GBeanNotFoundException { 608 if (!gbeans.containsKey(name)) { 609 throw new GBeanNotFoundException(name); 610 } 611 gbeans.remove(name); 612 } 613 614 public AbstractName findGBean(AbstractNameQuery pattern) throws GBeanNotFoundException { 615 if (pattern == null) throw new NullPointerException ("pattern is null"); 616 return findGBean(Collections.singleton(pattern)); 617 } 618 619 public GBeanData findGBeanData(AbstractNameQuery pattern) throws GBeanNotFoundException { 620 if (pattern == null) throw new NullPointerException ("pattern is null"); 621 return findGBeanData(Collections.singleton(pattern)); 622 } 623 624 public AbstractName findGBean(ReferencePatterns referencePatterns) throws GBeanNotFoundException { 625 if (referencePatterns == null) throw new NullPointerException ("referencePatterns is null"); 626 if (referencePatterns.isResolved()) { 627 return referencePatterns.getAbstractName(); 628 } 629 630 Set patterns = referencePatterns.getPatterns(); 632 return findGBean(patterns); 633 } 634 635 public AbstractName findGBean(Set patterns) throws GBeanNotFoundException { 636 if (patterns == null) throw new NullPointerException ("patterns is null"); 637 return findGBeanData(patterns).getAbstractName(); 638 } 639 640 public GBeanData findGBeanData(Set patterns) throws GBeanNotFoundException { 641 if (patterns == null) throw new NullPointerException ("patterns is null"); 642 Set result = findGBeanDatas(this, patterns); 643 if (result.size() > 1) { 644 throw new GBeanNotFoundException("More than one match to referencePatterns", patterns); 645 } else if (result.size() == 1) { 646 return (GBeanData) result.iterator().next(); 647 } 648 649 for (Iterator iterator = allServiceParents.iterator(); iterator.hasNext();) { 651 Configuration configuration = (Configuration) iterator.next(); 652 result.addAll(findGBeanDatas(configuration, patterns)); 653 654 if (result.size() > 1) { 656 List names = new ArrayList (result.size()); 657 for (Iterator iterator1 = result.iterator(); iterator1.hasNext();) { 658 GBeanData gBeanData = (GBeanData) iterator1.next(); 659 names.add(gBeanData.getAbstractName()); 660 } 661 throw new GBeanNotFoundException("More than one match to referencePatterns: " + names.toString(), patterns); 662 } 663 } 664 665 if (result.isEmpty()) { 666 throw new GBeanNotFoundException("No matches for referencePatterns", patterns); 667 } 668 669 return (GBeanData) result.iterator().next(); 670 } 671 672 public LinkedHashSet findGBeans(AbstractNameQuery pattern) { 673 if (pattern == null) throw new NullPointerException ("pattern is null"); 674 return findGBeans(Collections.singleton(pattern)); 675 } 676 677 public LinkedHashSet findGBeans(ReferencePatterns referencePatterns) { 678 if (referencePatterns == null) throw new NullPointerException ("referencePatterns is null"); 679 if (referencePatterns.getAbstractName() != null) { 680 LinkedHashSet result = new LinkedHashSet (); 682 result.add(referencePatterns.getAbstractName()); 683 return result; 684 } 685 686 Set patterns = referencePatterns.getPatterns(); 688 return findGBeans(patterns); 689 } 690 691 public LinkedHashSet findGBeans(Set patterns) { 692 if (patterns == null) throw new NullPointerException ("patterns is null"); 693 LinkedHashSet datas = findGBeanDatas(patterns); 694 LinkedHashSet result = new LinkedHashSet (datas.size()); 695 for (Iterator iterator = datas.iterator(); iterator.hasNext();) { 696 GBeanData gBeanData = (GBeanData) iterator.next(); 697 result.add(gBeanData.getAbstractName()); 698 } 699 700 return result; 701 } 702 703 public LinkedHashSet findGBeanDatas(Set patterns) { 704 if (patterns == null) throw new NullPointerException ("patterns is null"); 705 LinkedHashSet datas = findGBeanDatas(this, patterns); 706 707 for (Iterator iterator = allServiceParents.iterator(); iterator.hasNext();) { 709 Configuration configuration = (Configuration) iterator.next(); 710 Set match = findGBeanDatas(configuration, patterns); 711 datas.addAll(match); 712 } 713 return datas; 714 } 715 716 723 private LinkedHashSet findGBeanDatas(Configuration configuration, Set patterns) { 724 LinkedHashSet result = new LinkedHashSet (); 725 726 Set gbeanNames = configuration.getGBeans().entrySet(); 727 for (Iterator abstractNameQueries = patterns.iterator(); abstractNameQueries.hasNext();) { 728 AbstractNameQuery abstractNameQuery = (AbstractNameQuery) abstractNameQueries.next(); 729 Artifact queryArtifact = abstractNameQuery.getArtifact(); 730 731 if (queryArtifact == null || queryArtifact.matches(configuration.getId())) { 733 734 for (Iterator iterator = gbeanNames.iterator(); iterator.hasNext();) { 736 Map.Entry entry = (Map.Entry ) iterator.next(); 737 AbstractName abstractName = (AbstractName) entry.getKey(); 738 GBeanData gbeanData = (GBeanData) entry.getValue(); 739 if (abstractNameQuery.matches(abstractName, gbeanData.getGBeanInfo().getInterfaces())) { 740 result.add(gbeanData); 741 } 742 } 743 } 744 } 745 return result; 746 } 747 748 public void doStart() throws Exception { 749 log.debug("Started configuration " + id); 750 } 751 752 public synchronized void doStop() throws Exception { 753 log.debug("Stopping configuration " + id); 754 shutdown(); 755 756 } 757 758 public void doFail() { 759 log.debug("Failed configuration " + id); 760 shutdown(); 761 } 762 763 private void shutdown() { 764 for (Iterator iterator = children.iterator(); iterator.hasNext();) { 765 Configuration configuration = (Configuration) iterator.next(); 766 configuration.shutdown(); 767 } 768 769 gbeans.clear(); 771 772 if (configurationClassLoader != null) { 774 configurationClassLoader.destroy(); 775 } 776 } 777 778 public static final GBeanInfo GBEAN_INFO; 779 780 static { 781 GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(Configuration.class); infoFactory.addReference("Parents", Configuration.class); 783 infoFactory.addAttribute("configurationData", ConfigurationData.class, true, false); 784 infoFactory.addAttribute("configurationResolver", ConfigurationResolver.class, true); 785 infoFactory.addAttribute("managedAttributeStore", ManageableAttributeStore.class, true); 786 787 infoFactory.addInterface(Configuration.class); 788 789 infoFactory.setConstructor(new String []{ 790 "Parents", 791 "configurationData", 792 "configurationResolver", 793 "managedAttributeStore" 794 }); 795 796 GBEAN_INFO = infoFactory.getBeanInfo(); 797 } 798 799 public static GBeanInfo getGBeanInfo() { 800 return GBEAN_INFO; 801 } 802 } 803 | Popular Tags |