1 16 17 package org.apache.commons.configuration; 18 19 import java.io.File ; 20 import java.io.IOException ; 21 import java.io.InputStream ; 22 import java.net.URL ; 23 import java.util.Collection ; 24 import java.util.Iterator ; 25 import java.util.LinkedList ; 26 import java.util.Stack ; 27 28 import org.apache.commons.digester.AbstractObjectCreationFactory; 29 import org.apache.commons.digester.Digester; 30 import org.apache.commons.digester.ObjectCreationFactory; 31 import org.apache.commons.digester.xmlrules.DigesterLoader; 32 import org.apache.commons.lang.StringUtils; 33 import org.apache.commons.logging.Log; 34 import org.apache.commons.logging.LogFactory; 35 import org.xml.sax.Attributes ; 36 import org.xml.sax.SAXException ; 37 38 50 public class ConfigurationFactory 51 { 52 53 private static final String SEC_ROOT = "configuration/"; 54 55 56 private static final String SEC_OVERRIDE = SEC_ROOT + "override/"; 57 58 59 private static final String SEC_ADDITIONAL = SEC_ROOT + "additional/"; 60 61 62 private static final String ATTR_OPTIONAL = "optional"; 63 64 65 private static final String ATTR_FILENAME = "fileName"; 66 67 68 private static final String DEF_BASE_PATH = "."; 69 70 71 private static Log log = LogFactory.getLog(ConfigurationFactory.class); 72 73 74 private String configurationFileName; 75 76 77 private URL configurationURL; 78 79 84 private String implicitBasePath; 85 86 87 private String basePath; 88 89 90 private URL digesterRules; 91 92 93 private String digesterRuleNamespaceURI; 94 95 98 public ConfigurationFactory() 99 { 100 setBasePath(DEF_BASE_PATH); 101 } 102 107 public ConfigurationFactory(String configurationFileName) 108 { 109 this.configurationFileName = configurationFileName; 110 } 111 112 122 public Configuration getConfiguration() throws ConfigurationException 123 { 124 Digester digester; 125 InputStream input = null; 126 ConfigurationBuilder builder = new ConfigurationBuilder(); 127 URL url = getConfigurationURL(); 128 try 129 { 130 if (url == null) 131 { 132 url = ConfigurationUtils.locate(implicitBasePath, getConfigurationFileName()); 133 } 134 input = url.openStream(); 135 } 136 catch (Exception e) 137 { 138 log.error("Exception caught opening stream to URL", e); 139 throw new ConfigurationException("Exception caught opening stream to URL", e); 140 } 141 142 if (getDigesterRules() == null) 143 { 144 digester = new Digester(); 145 configureNamespace(digester); 146 initDefaultDigesterRules(digester); 147 } 148 else 149 { 150 digester = DigesterLoader.createDigester(getDigesterRules()); 151 configureNamespace(digester); 154 } 155 156 digester.setUseContextClassLoader(true); 158 digester.push(builder); 160 try 162 { 163 digester.parse(input); 164 input.close(); 165 } 166 catch (SAXException saxe) 167 { 168 log.error("SAX Exception caught", saxe); 169 throw new ConfigurationException("SAX Exception caught", saxe); 170 } 171 catch (IOException ioe) 172 { 173 log.error("IO Exception caught", ioe); 174 throw new ConfigurationException("IO Exception caught", ioe); 175 } 176 return builder.getConfiguration(); 177 } 178 179 184 public String getConfigurationFileName() 185 { 186 return configurationFileName; 187 } 188 189 194 public void setConfigurationFileName(String configurationFileName) 195 { 196 File file = new File (configurationFileName).getAbsoluteFile(); 197 this.configurationFileName = file.getName(); 198 implicitBasePath = file.getParent(); 199 } 200 201 206 public URL getConfigurationURL() 207 { 208 return configurationURL; 209 } 210 211 217 public void setConfigurationURL(URL url) 218 { 219 configurationURL = url; 220 implicitBasePath = url.toString(); 221 222 if (DEF_BASE_PATH.equals(getBasePath())) 227 { 228 setBasePath(null); 229 } 230 } 231 232 237 public URL getDigesterRules() 238 { 239 return digesterRules; 240 } 241 242 247 public void setDigesterRules(URL digesterRules) 248 { 249 this.digesterRules = digesterRules; 250 } 251 252 262 protected void initDefaultDigesterRules(Digester digester) 263 { 264 initDigesterSectionRules(digester, SEC_ROOT, false); 265 initDigesterSectionRules(digester, SEC_OVERRIDE, false); 266 initDigesterSectionRules(digester, SEC_ADDITIONAL, true); 267 } 268 269 278 protected void initDigesterSectionRules(Digester digester, String matchString, boolean additional) 279 { 280 setupDigesterInstance( 281 digester, 282 matchString + "properties", 283 new FileConfigurationFactory(PropertiesConfiguration.class), 284 null, 285 additional); 286 287 setupDigesterInstance( 288 digester, 289 matchString + "xml", 290 new FileConfigurationFactory(XMLConfiguration.class), 291 null, 292 additional); 293 294 setupDigesterInstance( 295 digester, 296 matchString + "hierarchicalXml", 297 new FileConfigurationFactory(XMLConfiguration.class), 298 null, 299 additional); 300 301 setupDigesterInstance( 302 digester, 303 matchString + "jndi", 304 new JNDIConfigurationFactory(), 305 null, 306 additional); 307 308 setupDigesterInstance( 309 digester, 310 matchString + "system", 311 new SystemConfigurationFactory(), 312 null, 313 additional); 314 } 315 316 327 protected void setupDigesterInstance( 328 Digester digester, 329 String matchString, 330 ObjectCreationFactory factory, 331 String method, 332 boolean additional) 333 { 334 if (additional) 335 { 336 setupUnionRules(digester, matchString); 337 } 338 digester.addFactoryCreate(matchString, factory); 339 digester.addSetProperties(matchString); 340 if (method != null) 341 { 342 digester.addCallMethod(matchString, method); 343 } 344 digester.addSetNext( 345 matchString, 346 "addConfiguration", 347 Configuration.class.getName()); 348 } 349 350 356 protected void setupUnionRules(Digester digester, String matchString) 357 { 358 digester.addObjectCreate(matchString, 359 AdditionalConfigurationData.class); 360 digester.addSetProperties(matchString); 361 digester.addSetNext(matchString, "addAdditionalConfig", 362 AdditionalConfigurationData.class.getName()); 363 } 364 365 370 public String getDigesterRuleNamespaceURI() 371 { 372 return digesterRuleNamespaceURI; 373 } 374 375 380 public void setDigesterRuleNamespaceURI(String digesterRuleNamespaceURI) 381 { 382 this.digesterRuleNamespaceURI = digesterRuleNamespaceURI; 383 } 384 385 392 private void configureNamespace(Digester digester) 393 { 394 if (getDigesterRuleNamespaceURI() != null) 395 { 396 digester.setNamespaceAware(true); 397 digester.setRuleNamespaceURI(getDigesterRuleNamespaceURI()); 398 } 399 else 400 { 401 digester.setNamespaceAware(false); 402 } 403 digester.setValidating(false); 404 } 405 406 413 public String getBasePath() 414 { 415 String path = StringUtils.isEmpty(basePath) ? implicitBasePath : basePath; 416 return StringUtils.isEmpty(path) ? "." : path; 417 } 418 419 430 public void setBasePath(String basePath) 431 { 432 this.basePath = basePath; 433 } 434 435 440 public class DigesterConfigurationFactory extends AbstractObjectCreationFactory 441 { 442 443 private Class clazz; 444 445 450 public DigesterConfigurationFactory(Class clazz) 451 { 452 this.clazz = clazz; 453 } 454 455 462 public Object createObject(Attributes attribs) throws Exception 463 { 464 return clazz.newInstance(); 465 } 466 } 467 468 474 public class FileConfigurationFactory extends DigesterConfigurationFactory 475 { 476 481 public FileConfigurationFactory(Class clazz) 482 { 483 super(clazz); 484 } 485 486 493 public Object createObject(Attributes attributes) throws Exception 494 { 495 FileConfiguration conf = (FileConfiguration) super.createObject(attributes); 496 conf.setBasePath(getBasePath()); 497 conf.setFileName(attributes.getValue(ATTR_FILENAME)); 498 try 499 { 500 log.info("Trying to load configuration " + conf.getFileName()); 501 conf.load(); 502 } 503 catch(ConfigurationException cex) 504 { 505 if(attributes.getValue(ATTR_OPTIONAL) != null 506 && PropertyConverter.toBoolean(attributes.getValue(ATTR_OPTIONAL)).booleanValue()) 507 { 508 log.warn("Could not load optional configuration " + conf.getFileName()); 509 } 510 else 511 { 512 throw cex; 513 } 514 } 515 return conf; 516 } 517 } 518 519 523 private class JNDIConfigurationFactory extends DigesterConfigurationFactory 524 { 525 public JNDIConfigurationFactory() 526 { 527 super(JNDIConfiguration.class); 528 } 529 } 530 531 535 private class SystemConfigurationFactory extends DigesterConfigurationFactory 536 { 537 public SystemConfigurationFactory() 538 { 539 super(SystemConfiguration.class); 540 } 541 } 542 543 547 public static class AdditionalConfigurationData 548 { 549 550 private Configuration configuration; 551 552 553 private String at; 554 555 560 public String getAt() 561 { 562 return at; 563 } 564 565 570 public void setAt(String string) 571 { 572 at = string; 573 } 574 575 580 public Configuration getConfiguration() 581 { 582 return configuration; 583 } 584 585 593 public void addConfiguration(Configuration config) 594 { 595 configuration = config; 596 } 597 } 598 599 603 public static class ConfigurationBuilder 604 { 605 606 private CompositeConfiguration config; 607 608 609 private Collection additionalConfigs; 610 611 614 public ConfigurationBuilder() 615 { 616 config = new CompositeConfiguration(); 617 additionalConfigs = new LinkedList (); 618 } 619 620 626 public void addConfiguration(Configuration conf) 627 { 628 config.addConfiguration(conf); 629 } 630 631 637 public void addAdditionalConfig(AdditionalConfigurationData data) 638 { 639 additionalConfigs.add(data); 640 } 641 642 647 public CompositeConfiguration getConfiguration() 648 { 649 if (!additionalConfigs.isEmpty()) 650 { 651 Configuration unionConfig = createAdditionalConfiguration(additionalConfigs); 652 if (unionConfig != null) 653 { 654 addConfiguration(unionConfig); 655 } 656 additionalConfigs.clear(); 657 } 658 659 return config; 660 } 661 662 672 protected Configuration createAdditionalConfiguration(Collection configs) 673 { 674 HierarchicalConfiguration result = new HierarchicalConfiguration(); 675 676 for (Iterator it = configs.iterator(); it.hasNext();) 677 { 678 AdditionalConfigurationData cdata = 679 (AdditionalConfigurationData) it.next(); 680 result.addNodes(cdata.getAt(), 681 createRootNode(cdata).getChildren()); 682 } 683 684 return result.isEmpty() ? null : result; 685 } 686 687 693 private HierarchicalConfiguration.Node createRootNode(AdditionalConfigurationData cdata) 694 { 695 if (cdata.getConfiguration() instanceof HierarchicalConfiguration) 696 { 697 return ((HierarchicalConfiguration) cdata.getConfiguration()).getRoot(); 699 } 700 else 701 { 702 HierarchicalConfigurationNodeConverter conv = 704 new HierarchicalConfigurationNodeConverter(); 705 conv.process(cdata.getConfiguration()); 706 return conv.getRootNode(); 707 } 708 } 709 } 710 711 718 static class HierarchicalConfigurationNodeConverter extends HierarchicalConfigurationConverter 719 { 720 721 private Stack nodes; 722 723 724 private HierarchicalConfiguration.Node root; 725 726 729 public HierarchicalConfigurationNodeConverter() 730 { 731 nodes = new Stack (); 732 root = new HierarchicalConfiguration.Node(); 733 nodes.push(root); 734 } 735 736 743 protected void elementStart(String name, Object value) 744 { 745 HierarchicalConfiguration.Node parent = (HierarchicalConfiguration.Node) nodes.peek(); 746 HierarchicalConfiguration.Node child = new HierarchicalConfiguration.Node(name); 747 if (value != null) 748 { 749 child.setValue(value); 750 } 751 parent.addChild(child); 752 nodes.push(child); 753 } 754 755 760 protected void elementEnd(String name) 761 { 762 nodes.pop(); 763 } 764 765 770 public HierarchicalConfiguration.Node getRootNode() 771 { 772 return root; 773 } 774 } 775 } 776 | Popular Tags |