Return-Path: Delivered-To: apmail-commons-commits-archive@locus.apache.org Received: (qmail 11124 invoked from network); 19 Sep 2007 20:30:08 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 19 Sep 2007 20:30:08 -0000 Received: (qmail 20295 invoked by uid 500); 19 Sep 2007 20:29:59 -0000 Delivered-To: apmail-commons-commits-archive@commons.apache.org Received: (qmail 20234 invoked by uid 500); 19 Sep 2007 20:29:59 -0000 Mailing-List: contact commits-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@commons.apache.org Delivered-To: mailing list commits@commons.apache.org Received: (qmail 20218 invoked by uid 99); 19 Sep 2007 20:29:59 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 19 Sep 2007 13:29:59 -0700 X-ASF-Spam-Status: No, hits=-100.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 19 Sep 2007 20:32:03 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 262911A9832; Wed, 19 Sep 2007 13:29:43 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r577436 - in /commons/proper/configuration/trunk/src: java/org/apache/commons/configuration/XMLConfiguration.java test/org/apache/commons/configuration/TestXMLConfiguration.java Date: Wed, 19 Sep 2007 20:29:42 -0000 To: commits@commons.apache.org From: oheger@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20070919202943.262911A9832@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: oheger Date: Wed Sep 19 13:29:42 2007 New Revision: 577436 URL: http://svn.apache.org/viewvc?rev=577436&view=rev Log: CONFIGURATION-290: Add ability to XMLConfiguration for registering entity IDs analogous to digester's register() method; this code is based on code of the o.a.c.digester.Digester class Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/XMLConfiguration.java commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestXMLConfiguration.java Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/XMLConfiguration.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/XMLConfiguration.java?rev=577436&r1=577435&r2=577436&view=diff ============================================================================== --- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/XMLConfiguration.java (original) +++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/XMLConfiguration.java Wed Sep 19 13:29:42 2007 @@ -18,14 +18,18 @@ package org.apache.commons.configuration; import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.io.Writer; import java.net.URL; +import java.net.URLConnection; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -49,6 +53,7 @@ import org.w3c.dom.NamedNodeMap; import org.w3c.dom.NodeList; import org.w3c.dom.Text; +import org.xml.sax.EntityResolver; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; @@ -71,9 +76,9 @@ * path set for this configuration.

* *

By inheriting from {@link AbstractConfiguration} this class - * provides some extended functionaly, e.g. interpolation of property values. + * provides some extended functionality, e.g. interpolation of property values. * Like in {@link PropertiesConfiguration} property values can - * contain delimiter characters (the comma ',' per default) and are then splitted + * contain delimiter characters (the comma ',' per default) and are then split * into multiple values. This works for XML attributes and text content of * elements as well. The delimiter can be escaped by a backslash. As an example * consider the following XML fragment:

@@ -87,7 +92,7 @@ * </config> * *

- *

Here the content of the array element will be splitted at + *

Here the content of the array element will be split at * the commas, so the array key will be assigned 4 values. In the * scalar property and the text attribute of the * cite element the comma is escaped, so that no splitting is @@ -139,6 +144,7 @@ * @version $Revision$, $Date$ */ public class XMLConfiguration extends AbstractHierarchicalFileConfiguration + implements EntityResolver { /** * The serial version UID. @@ -154,6 +160,9 @@ /** The document from this configuration's data source. */ private Document document; + /** Stores a map with the registered public IDs.*/ + private Map registeredEntities = new HashMap(); + /** Stores the name of the root element. */ private String rootElementName; @@ -566,6 +575,7 @@ .newInstance(); factory.setValidating(isValidating()); DocumentBuilder result = factory.newDocumentBuilder(); + result.setEntityResolver(this); if (isValidating()) { @@ -831,6 +841,97 @@ nd.addAttribute(convertToXMLNode((ConfigurationNode) it.next())); } return nd; + } + + /** + *

+ * Registers the specified DTD URL for the specified public identifier. + *

+ *

+ * XMLConfiguration contains an internal + * EntityResolver implementation. This maps + * PUBLICID's to URLs (from which the resource will be + * loaded). A common use case for this method is to register local URLs + * (possibly computed at runtime by a class loader) for DTDs. This allows + * the performance advantage of using a local version without having to + * ensure every SYSTEM URI on every processed XML document is + * local. This implementation provides only basic functionality. If more + * sophisticated features are required, using + * {@link #setDocumentBuilder(DocumentBuilder)} to set a custom + * DocumentBuilder (which also can be initialized with a + * custom EntityResolver) is recommended. + *

+ *

+ * Note: This method will have no effect when a custom + * DocumentBuilder has been set. (Setting a custom + * DocumentBuilder overrides the internal implementation.) + *

+ *

+ * Note: This method must be called before the + * configuration is loaded. So the default constructor of + * XMLConfiguration should be used, the location of the + * configuration file set, registerEntityId() called, and + * finally the load() method can be invoked. + *

+ * + * @param publicId Public identifier of the DTD to be resolved + * @param entityURL The URL to use for reading this DTD + * @throws IllegalArgumentException if the public ID is undefined + * @since 1.5 + */ + public void registerEntityId(String publicId, URL entityURL) + { + if (publicId == null) + { + throw new IllegalArgumentException("Public ID must not be null!"); + } + registeredEntities.put(publicId, entityURL); + } + + /** + * Resolves the requested external entity. This is the default + * implementation of the EntityResolver interface. It checks + * the passed in public ID against the registered entity IDs and uses a + * local URL if possible. + * + * @param publicId the public identifier of the entity being referenced + * @param systemId the system identifier of the entity being referenced + * @throws SAXException if a parsing exception occurs + * @since 1.5 + */ + public InputSource resolveEntity(String publicId, String systemId) + throws SAXException + { + // Has this system identifier been registered? + URL entityURL = null; + if (publicId != null) + { + entityURL = (URL) registeredEntities.get(publicId); + } + + if (entityURL != null) + { + // Obtain an InputSource for this URL. This code is based on the + // createInputSourceFromURL() method of Commons Digester. + try + { + URLConnection connection = entityURL.openConnection(); + connection.setUseCaches(false); + InputStream stream = connection.getInputStream(); + InputSource source = new InputSource(stream); + source.setSystemId(entityURL.toExternalForm()); + return source; + } + catch (IOException e) + { + throw new SAXException(e); + } + } + else + { + // default processing behavior + return null; + } } /** Modified: commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestXMLConfiguration.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestXMLConfiguration.java?rev=577436&r1=577435&r2=577436&view=diff ============================================================================== --- commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestXMLConfiguration.java (original) +++ commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestXMLConfiguration.java Wed Sep 19 13:29:42 2007 @@ -1227,6 +1227,40 @@ } /** + * Tests registering the publicId of a DTD. + */ + public void testRegisterEntityId() throws ConfigurationException, + IOException + { + File dtdFile = new File("conf/properties.dtd"); + final String publicId = "http://commons.apache.org/test/properties.dtd"; + conf = new XMLConfiguration("testDtd.xml"); + conf.setPublicID(publicId); + conf.save(testSaveConf); + XMLConfiguration checkConfig = new XMLConfiguration(); + checkConfig.setFile(testSaveConf); + checkConfig.registerEntityId(publicId, dtdFile.toURL()); + checkConfig.setValidating(true); + checkSavedConfig(checkConfig); + } + + /** + * Tries to register a null public ID. This should cause an exception. + */ + public void testRegisterEntityIdNull() throws IOException + { + try + { + conf.registerEntityId(null, new URL("http://commons.apache.org")); + fail("Could register null public ID!"); + } + catch (IllegalArgumentException iex) + { + // ok + } + } + + /** * Prepares a configuration object for testing a reload operation. * * @return the initialized configuration