From 08016200ad3e988a3c9c6cfad48249e568e6a8a037851da6b7e3f3c4fef7f310 Mon Sep 17 00:00:00 2001
From: Fridrich Strba QName
represents a qualified name value of an XML element or
- * attribute. It consists of a local name and a {@link Namespace}instance. This
- * object is immutable.
-+ * @author Filip Jirsak
- *
NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]-+ * -+ * @see XML 1.0 - 2.3 Common Syntactic Constructs -+ * @see XML 1.1 - 2.3 Common Syntactic Constructs -+ */ -+ private static final String NAME_START_CHAR = "_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD"; -+ -+ /** -+ * {@code NameChar} without colon. -+ * -+ *
NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]-+ * -+ * @see XML 1.0 - 2.3 Common Syntactic Constructs -+ * @see XML 1.1 - 2.3 Common Syntactic Constructs -+ */ -+ private static final String NAME_CHAR = NAME_START_CHAR + "-.0-9\u00B7\u0300-\u036F\u203F-\u2040"; -+ -+ /** -+ * {@code NCName} -+ * {@code NCName} -+ * -+ *
-+ * NCName ::= NCNameStartChar NCNameChar* (An XML Name, minus the ":") -+ * NCNameChar ::= NameChar -':' -+ * NCNameStartChar ::= NameStartChar -':' -+ *-+ * -+ * @see Namespaces in XML 1.0 - 4 Qualified Names -+ * @see Namespaces in XML 1.1 - 4 Qualified Names -+ */ -+ private static final String NCNAME = "["+NAME_START_CHAR+"]["+NAME_CHAR+"]*"; -+ -+ /** -+ * Regular expression for {@code Name} (with colon). -+ * -+ *
Name ::= NameStartChar (NameChar)*-+ * -+ * @see XML 1.0 - 2.3 Common Syntactic Constructs -+ * @see XML 1.1 - 2.3 Common Syntactic Constructs -+ */ -+ private static final Pattern RE_NAME = Pattern.compile("[:"+NAME_START_CHAR+"][:"+NAME_CHAR+"]*"); -+ -+ /** -+ * Regular expression for {@code NCName}. -+ * -+ *
-+ * NCName ::= NCNameStartChar NCNameChar* (An XML Name, minus the ":") -+ * NCNameChar ::= NameChar -':' -+ * NCNameStartChar ::= NameStartChar -':' -+ *-+ * -+ * @see Namespaces in XML 1.0 - 4 Qualified Names -+ * @see Namespaces in XML 1.1 - 4 Qualified Names -+ */ -+ private static final Pattern RE_NCNAME = Pattern.compile(NCNAME); -+ -+ /** -+ * Regular expression for {@code QName}. -+ * -+ *
-+ * QName ::= PrefixedName | UnprefixedName -+ * PrefixedName ::= Prefix ':' LocalPart -+ * UnprefixedName ::= LocalPart -+ * Prefix ::= NCName -+ * LocalPart ::= NCName -+ *-+ * -+ * @see Namespaces in XML 1.0 - 4 Qualified Names -+ * @see Namespaces in XML 1.1 - 4 Qualified Names -+ */ -+ private static final Pattern RE_QNAME = Pattern.compile("(?:"+NCNAME+":)?"+NCNAME); -+ - static { - try { - String defaultSingletonClass = "org.dom4j.util.SimpleSingleton"; -@@ -73,6 +150,11 @@ public class QName implements Serializab - this.name = (name == null) ? "" : name; - this.namespace = (namespace == null) ? Namespace.NO_NAMESPACE - : namespace; -+ if (this.namespace.equals(Namespace.NO_NAMESPACE)) { -+ validateName(this.name); -+ } else { -+ validateNCName(this.name); -+ } - } - - public QName(String name, Namespace namespace, String qualifiedName) { -@@ -80,6 +162,8 @@ public class QName implements Serializab - this.qualifiedName = qualifiedName; - this.namespace = (namespace == null) ? Namespace.NO_NAMESPACE - : namespace; -+ validateNCName(this.name); -+ validateQName(this.qualifiedName); - } - - public static QName get(String name) { -@@ -253,6 +337,24 @@ public class QName implements Serializab - QNameCache cache = (QNameCache) singleton.instance(); - return cache; - } -+ -+ private static void validateName(String name) { -+ if (!RE_NAME.matcher(name).matches()) { -+ throw new IllegalArgumentException(String.format("Illegal character in name: '%s'.", name)); -+ } -+ } -+ -+ protected static void validateNCName(String ncname) { -+ if (!RE_NCNAME.matcher(ncname).matches()) { -+ throw new IllegalArgumentException(String.format("Illegal character in local name: '%s'.", ncname)); -+ } -+ } -+ -+ private static void validateQName(String qname) { -+ if (!RE_QNAME.matcher(qname).matches()) { -+ throw new IllegalArgumentException(String.format("Illegal character in qualified name: '%s'.", qname)); -+ } -+ } - } - - -Index: dom4j/src/java/org/dom4j/tree/QNameCache.java -=================================================================== ---- dom4j.orig/src/java/org/dom4j/tree/QNameCache.java -+++ dom4j/src/java/org/dom4j/tree/QNameCache.java -@@ -164,6 +164,8 @@ public class QNameCache { - - if (index < 0) { - return get(qualifiedName, Namespace.get(uri)); -+ } else if (index == 0){ -+ throw new IllegalArgumentException("Qualified name cannot start with ':'."); - } else { - String name = qualifiedName.substring(index + 1); - String prefix = qualifiedName.substring(0, index); -Index: dom4j/src/test/org/dom4j/AllowedCharsTest.java -=================================================================== ---- /dev/null -+++ dom4j/src/test/org/dom4j/AllowedCharsTest.java -@@ -0,0 +1,78 @@ -+package org.dom4j;^M -+^M -+import org.testng.annotations.Test;^M -+^M -+/**^M -+ * @author Filip Jirsak^M -+ */^M -+public class AllowedCharsTest {^M -+ @Test^M -+ public void localName() {^M -+ QName.get("element");^M -+ QName.get(":element");^M -+ QName.get("elem:ent");^M -+ }^M -+^M -+ @Test(expectedExceptions = IllegalArgumentException.class)^M -+ public void localNameFail() {^M -+ QName.get("!element");^M -+ }^M -+^M -+ @Test^M -+ public void qname() {^M -+ QName.get("element", "http://example.com/namespace");^M -+ QName.get("ns:element", "http://example.com/namespace");^M -+ }^M -+^M -+ @Test(expectedExceptions = IllegalArgumentException.class)^M -+ public void qnameFail1() {^M -+ QName.get("ns:elem:ent", "http://example.com/namespace");^M -+ }^M -+^M -+ @Test(expectedExceptions = IllegalArgumentException.class)^M -+ public void qnameFail2() {^M -+ QName.get(":nselement", "http://example.com/namespace");^M -+ }^M -+^M -+ @Test(expectedExceptions = IllegalArgumentException.class)^M -+ public void createElementLT() {^M -+ DocumentHelper.createElement("element
- * SAXHelper
contains some helper methods for working with SAX
-@@ -59,9 +61,18 @@ class SAXHelper {
- }
-
- /**
-- * Creats a default XMLReader via the org.xml.sax.driver system property or
-+ * Creates a default XMLReader via the org.xml.sax.driver system property or
- * JAXP if the system property is not set.
- *
-+ * This method internally calls {@link SAXParserFactory}{@code .newInstance().newSAXParser().getXMLReader()} or {@link XMLReaderFactory#createXMLReader()}.
-+ * Be sure to configure returned reader if the default configuration does not suit you. Consider setting the following properties:
-+ *
-+ *
-+ * reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); -+ * reader.setFeature("http://xml.org/sax/features/external-general-entities", false); -+ * reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false); -+ *-+ * - * @param validating - * DOCUMENT ME! - * -Index: dom4j/src/java/org/dom4j/io/SAXReader.java -=================================================================== ---- dom4j.orig/src/java/org/dom4j/io/SAXReader.java -+++ dom4j/src/java/org/dom4j/io/SAXReader.java -@@ -30,6 +30,8 @@ import org.xml.sax.XMLReader; - import org.xml.sax.helpers.DefaultHandler; - import org.xml.sax.helpers.XMLReaderFactory; - -+import javax.xml.parsers.SAXParserFactory; -+ - /** - *
- * SAXReader
creates a DOM4J tree from SAX parsing events.
-@@ -135,17 +137,76 @@ public class SAXReader {
- /** The SAX filter used to filter SAX events */
- private XMLFilter xmlFilter;
-
-+ public static SAXReader createDefault() {
-+ SAXReader reader = new SAXReader();
-+ try {
-+ reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
-+ reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
-+ reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
-+ } catch (SAXException e) {
-+ // nothing to do, incompatible reader
-+ }
-+ return reader;
-+ }
-+
-+ /**
-+ * This method internally calls {@link SAXParserFactory}{@code .newInstance().newSAXParser().getXMLReader()} or {@link XMLReaderFactory#createXMLReader()}.
-+ * Be sure to configure returned reader if the default configuration does not suit you. Consider setting the following properties:
-+ *
-+ *
-+ * reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); -+ * reader.setFeature("http://xml.org/sax/features/external-general-entities", false); -+ * reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false); -+ *-+ */ - public SAXReader() { - } - -+ /** -+ * This method internally calls {@link SAXParserFactory}{@code .newInstance().newSAXParser().getXMLReader()} or {@link XMLReaderFactory#createXMLReader()}. -+ * Be sure to configure returned reader if the default configuration does not suit you. Consider setting the following properties: -+ * -+ *
-+ * reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); -+ * reader.setFeature("http://xml.org/sax/features/external-general-entities", false); -+ * reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false); -+ *-+ * -+ * @param validating -+ */ - public SAXReader(boolean validating) { - this.validating = validating; - } - -+ /** -+ * This method internally calls {@link SAXParserFactory}{@code .newInstance().newSAXParser().getXMLReader()} or {@link XMLReaderFactory#createXMLReader()}. -+ * Be sure to configure returned reader if the default configuration does not suit you. Consider setting the following properties: -+ * -+ *
-+ * reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); -+ * reader.setFeature("http://xml.org/sax/features/external-general-entities", false); -+ * reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false); -+ *-+ * -+ * @param factory -+ */ - public SAXReader(DocumentFactory factory) { - this.factory = factory; - } - -+ /** -+ * This method internally calls {@link SAXParserFactory}{@code .newInstance().newSAXParser().getXMLReader()} or {@link XMLReaderFactory#createXMLReader()}. -+ * Be sure to configure returned reader if the default configuration does not suit you. Consider setting the following properties: -+ * -+ *
-+ * reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); -+ * reader.setFeature("http://xml.org/sax/features/external-general-entities", false); -+ * reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false); -+ *-+ * -+ * @param factory -+ * @param validating -+ */ - public SAXReader(DocumentFactory factory, boolean validating) { - this.factory = factory; - this.validating = validating; -@@ -185,14 +246,10 @@ public class SAXReader { - * this method is to correctly configure an XMLReader object instance and - * call the {@link #setXMLReader(XMLReader)}method - * -- * @param name -- * is the SAX property name -- * @param value -- * is the value of the SAX property -- * -- * @throws SAXException -- * if the XMLReader could not be created or the property could -- * not be changed. -+ * @param name is the SAX property name -+ * @param value is the value of the SAX property -+ * @throws SAXException if the XMLReader could not be created or the property could -+ * not be changed. - */ - public void setProperty(String name, Object value) throws SAXException { - getXMLReader().setProperty(name, value); -@@ -205,14 +262,10 @@ public class SAXReader { - * calling this method is to correctly configure an XMLReader object - * instance and call the {@link #setXMLReader(XMLReader)}method - * -- * @param name -- * is the SAX feature name -- * @param value -- * is the value of the SAX feature -- * -- * @throws SAXException -- * if the XMLReader could not be created or the feature could -- * not be changed. -+ * @param name is the SAX feature name -+ * @param value is the value of the SAX feature -+ * @throws SAXException if the XMLReader could not be created or the feature could -+ * not be changed. - */ - public void setFeature(String name, boolean value) throws SAXException { - getXMLReader().setFeature(name, value); -@@ -223,13 +276,9 @@ public class SAXReader { - * Reads a Document from the given
File
- *
- *
-- * @param file
-- * is the File
to read from.
-- *
-+ * @param file is the File
to read from.
- * @return the newly created Document instance
-- *
-- * @throws DocumentException
-- * if an error occurs during parsing.
-+ * @throws DocumentException if an error occurs during parsing.
- */
- public Document read(File file) throws DocumentException {
- try {
-@@ -272,13 +321,9 @@ public class SAXReader {
- * Reads a Document from the given URL
using SAX
- *
- *
-- * @param url
-- * URL
to read from.
-- *
-+ * @param url URL
to read from.
- * @return the newly created Document instance
-- *
-- * @throws DocumentException
-- * if an error occurs during parsing.
-+ * @throws DocumentException if an error occurs during parsing.
- */
- public Document read(URL url) throws DocumentException {
- String systemID = url.toExternalForm();
-@@ -304,13 +349,9 @@ public class SAXReader {
- * String} to denote the source of the document.
- *
- *
-- * @param systemId
-- * is a URL for a document or a file name.
-- *
-+ * @param systemId is a URL for a document or a file name.
- * @return the newly created Document instance
-- *
-- * @throws DocumentException
-- * if an error occurs during parsing.
-+ * @throws DocumentException if an error occurs during parsing.
- */
- public Document read(String systemId) throws DocumentException {
- InputSource source = new InputSource(systemId);
-@@ -326,13 +367,9 @@ public class SAXReader {
- * Reads a Document from the given stream using SAX
- *
- *
-- * @param in
-- * InputStream
to read from.
-- *
-+ * @param in InputStream
to read from.
- * @return the newly created Document instance
-- *
-- * @throws DocumentException
-- * if an error occurs during parsing.
-+ * @throws DocumentException if an error occurs during parsing.
- */
- public Document read(InputStream in) throws DocumentException {
- InputSource source = new InputSource(in);
-@@ -348,13 +385,9 @@ public class SAXReader {
- * Reads a Document from the given Reader
using SAX
- *
- *
-- * @param reader
-- * is the reader for the input
-- *
-+ * @param reader is the reader for the input
- * @return the newly created Document instance
-- *
-- * @throws DocumentException
-- * if an error occurs during parsing.
-+ * @throws DocumentException if an error occurs during parsing.
- */
- public Document read(Reader reader) throws DocumentException {
- InputSource source = new InputSource(reader);
-@@ -370,15 +403,10 @@ public class SAXReader {
- * Reads a Document from the given stream using SAX
- *
- *
-- * @param in
-- * InputStream
to read from.
-- * @param systemId
-- * is the URI for the input
-- *
-+ * @param in InputStream
to read from.
-+ * @param systemId is the URI for the input
- * @return the newly created Document instance
-- *
-- * @throws DocumentException
-- * if an error occurs during parsing.
-+ * @throws DocumentException if an error occurs during parsing.
- */
- public Document read(InputStream in, String systemId)
- throws DocumentException {
-@@ -396,13 +424,9 @@ public class SAXReader {
- * Reads a Document from the given Reader
using SAX
- *
- *
-- * @param reader
-- * is the reader for the input
-- * @param systemId
-- * is the URI for the input
-- *
-+ * @param reader is the reader for the input
-+ * @param systemId is the URI for the input
- * @return the newly created Document instance
-- *
- * @throws DocumentException
- * if an error occurs during parsing.
- */
-@@ -422,13 +446,9 @@ public class SAXReader {
- * Reads a Document from the given InputSource
using SAX
- *
- *
-- * @param in
-- * InputSource
to read from.
-- *
-+ * @param in InputSource
to read from.
- * @return the newly created Document instance
-- *
-- * @throws DocumentException
-- * if an error occurs during parsing.
-+ * @throws DocumentException if an error occurs during parsing.
- */
- public Document read(InputSource in) throws DocumentException {
- try {
-@@ -695,8 +715,7 @@ public class SAXReader {
- /**
- * Sets the entity resolver used to resolve entities.
- *
-- * @param entityResolver
-- * DOCUMENT ME!
-+ * @param entityResolver DOCUMENT ME!
- */
- public void setEntityResolver(EntityResolver entityResolver) {
- this.entityResolver = entityResolver;
-@@ -706,9 +725,7 @@ public class SAXReader {
- * DOCUMENT ME!
- *
- * @return the XMLReader
used to parse SAX events
-- *
-- * @throws SAXException
-- * DOCUMENT ME!
-+ * @throws SAXException DOCUMENT ME!
- */
- public XMLReader getXMLReader() throws SAXException {
- if (xmlReader == null) {
-@@ -721,8 +738,7 @@ public class SAXReader {
- /**
- * Sets the XMLReader
used to parse SAX events
- *
-- * @param reader
-- * is the XMLReader
to parse SAX events
-+ * @param reader is the XMLReader
to parse SAX events
- */
- public void setXMLReader(XMLReader reader) {
- this.xmlReader = reader;
-@@ -742,8 +758,7 @@ public class SAXReader {
- /**
- * Sets encoding used for InputSource (null means system default encoding)
- *
-- * @param encoding
-- * is encoding used for InputSource
-+ * @param encoding is encoding used for InputSource
- */
- public void setEncoding(String encoding) {
- this.encoding = encoding;
-@@ -753,12 +768,9 @@ public class SAXReader {
- * Sets the class name of the XMLReader
to be used to parse
- * SAX events.
- *
-- * @param xmlReaderClassName
-- * is the class name of the XMLReader
to parse SAX
-- * events
-- *
-- * @throws SAXException
-- * DOCUMENT ME!
-+ * @param xmlReaderClassName is the class name of the XMLReader
-+ * to parse SAX events
-+ * @throws SAXException DOCUMENT ME!
- */
- public void setXMLReaderClassName(String xmlReaderClassName)
- throws SAXException {
-@@ -769,11 +781,9 @@ public class SAXReader {
- * Adds the ElementHandler
to be called when the specified
- * path is encounted.
- *
-- * @param path
-- * is the path to be handled
-- * @param handler
-- * is the ElementHandler
to be called by the event
-- * based processor.
-+ * @param path is the path to be handled
-+ * @param handler is the ElementHandler
to be called by the event
-+ * based processor.
- */
- public void addHandler(String path, ElementHandler handler) {
- getDispatchHandler().addHandler(path, handler);
-@@ -783,8 +793,7 @@ public class SAXReader {
- * Removes the ElementHandler
from the event based processor,
- * for the specified path.
- *
-- * @param path
-- * is the path to remove the ElementHandler
for.
-+ * @param path is the path to remove the ElementHandler
for.
- */
- public void removeHandler(String path) {
- getDispatchHandler().removeHandler(path);
-@@ -795,9 +804,8 @@ public class SAXReader {
- * registered, this will set a default ElementHandler
to be
- * called for any path which does NOT have a handler registered.
- *
-- * @param handler
-- * is the ElementHandler
to be called by the event
-- * based processor.
-+ * @param handler is the ElementHandler
to be called by the event
-+ * based processor.
- */
- public void setDefaultHandler(ElementHandler handler) {
- getDispatchHandler().setDefaultHandler(handler);
-@@ -824,8 +832,7 @@ public class SAXReader {
- /**
- * Sets the SAX filter to be used when filtering SAX events
- *
-- * @param filter
-- * is the SAX filter to use or null to disable filtering
-+ * @param filter is the SAX filter to use or null to disable filtering
- */
- public void setXMLFilter(XMLFilter filter) {
- this.xmlFilter = filter;
-@@ -838,9 +845,7 @@ public class SAXReader {
- * Installs any XMLFilter objects required to allow the SAX event stream to
- * be filtered and preprocessed before it gets to dom4j.
- *
-- * @param reader
-- * DOCUMENT ME!
-- *
-+ * @param reader DOCUMENT ME!
- * @return the new XMLFilter if applicable or the original XMLReader if no
- * filter is being used.
- */
-@@ -886,9 +891,7 @@ public class SAXReader {
- * XMLReader objects
- *
- * @return DOCUMENT ME!
-- *
-- * @throws SAXException
-- * DOCUMENT ME!
-+ * @throws SAXException DOCUMENT ME!
- */
- protected XMLReader createXMLReader() throws SAXException {
- return SAXHelper.createXMLReader(isValidating());
-@@ -897,13 +900,9 @@ public class SAXReader {
- /**
- * Configures the XMLReader before use
- *
-- * @param reader
-- * DOCUMENT ME!
-- * @param handler
-- * DOCUMENT ME!
-- *
-- * @throws DocumentException
-- * DOCUMENT ME!
-+ * @param reader DOCUMENT ME!
-+ * @param handler DOCUMENT ME!
-+ * @throws DocumentException DOCUMENT ME!
- */
- protected void configureReader(XMLReader reader, DefaultHandler handler)
- throws DocumentException {
-@@ -918,10 +917,11 @@ public class SAXReader {
- SAXHelper.setParserProperty(reader, SAX_DECL_HANDLER, handler);
- }
-
-- // configure namespace support
-- SAXHelper.setParserFeature(reader, SAX_NAMESPACES, true);
-+ // // configure namespace support
-+ // SAXHelper.setParserFeature(reader, SAX_NAMESPACES, true);
-
-- SAXHelper.setParserFeature(reader, SAX_NAMESPACE_PREFIXES, false);
-+ // string interning
-+ // SAXHelper.setParserFeature(reader, SAX_NAMESPACE_PREFIXES, false);
-
- // string interning
- SAXHelper.setParserFeature(reader, SAX_STRING_INTERNING,
-@@ -936,8 +936,8 @@ public class SAXReader {
- * includeExternalParameterEntities );
- */
- // use Locator2 if possible
-- SAXHelper.setParserFeature(reader,
-- "http://xml.org/sax/features/use-locator2", true);
-+ // SAXHelper.setParserFeature(reader,
-+ // "http://xml.org/sax/features/use-locator2", true);
-
- try {
- // configure validation support
-@@ -960,9 +960,7 @@ public class SAXReader {
- /**
- * Factory Method to allow user derived SAXContentHandler objects to be used
- *
-- * @param reader
-- * DOCUMENT ME!
-- *
-+ * @param reader DOCUMENT ME!
- * @return DOCUMENT ME!
- */
- protected SAXContentHandler createContentHandler(XMLReader reader) {
diff --git a/dom4j-build.xml b/dom4j-build.xml
new file mode 100644
index 0000000..4987681
--- /dev/null
+++ b/dom4j-build.xml
@@ -0,0 +1,113 @@
+
+
+