Author: maartenc
Date: Tue Sep 30 15:22:12 2008
New Revision: 700610
URL: http://svn.apache.org/viewvc?rev=700610&view=rev
Log:
Maven accepts illegal XML for its pom's, Ivy not (IVY-921)
Added:
ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/parser/m2/m2-entities.ent
Modified:
ant/ivy/core/trunk/CHANGES.txt
ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/parser/m2/PomReader.java
ant/ivy/core/trunk/src/java/org/apache/ivy/util/XMLHelper.java
Modified: ant/ivy/core/trunk/CHANGES.txt
URL:
http://svn.apache.org/viewvc/ant/ivy/core/trunk/CHANGES.txt?rev=700610&r1=700609&r2=700610&view=diff
==============================================================================
--- ant/ivy/core/trunk/CHANGES.txt (original)
+++ ant/ivy/core/trunk/CHANGES.txt Tue Sep 30 15:22:12 2008
@@ -82,6 +82,7 @@
- DOCUMENTATION: Filesystem resolver: talks about "patterns" but does not
mention these must become absolute file paths (IVY-910)
- IMPROVEMENT: Error messages on use of relative paths can be cyrptic (IVY-909)
+- IMPROVEMENT: Maven accepts illegal XML for its pom's, Ivy not (IVY-921)
- FIX: Cannot configure items with java.io.File attributes (IVY-905)
- FIX: Environment properties in ivy settings are no longer resolved (IVY-907)
Modified:
ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/parser/m2/PomReader.java
URL:
http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/parser/m2/PomReader.java?rev=700610&r1=700609&r2=700610&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/parser/m2/PomReader.java
(original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/parser/m2/PomReader.java
Tue Sep 30 15:22:12 2008
@@ -17,7 +17,11 @@
*/
package org.apache.ivy.plugins.parser.m2;
+import java.io.FilterInputStream;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
@@ -36,6 +40,8 @@
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
@@ -80,14 +86,32 @@
private final Element parentElement;
public PomReader(URL descriptorURL, Resource res) throws IOException,
SAXException {
- Document pomDomDoc = XMLHelper.parseToDom(descriptorURL, res);
- projectElement = pomDomDoc.getDocumentElement();
- if (!PROJECT.equals(projectElement.getNodeName())) {
- throw new SAXParseException("project must be the root tag" ,
res.getName() ,
- res.getName(), 0, 0);
+ InputStream stream = new
AddDTDFilterInputStream(descriptorURL.openStream());
+ try {
+ Document pomDomDoc = XMLHelper.parseToDom(stream, res, new
EntityResolver() {
+ public InputSource resolveEntity(String publicId, String
systemId) throws SAXException,
+ IOException {
+ if ((systemId != null) &&
systemId.endsWith("m2-entities.ent")) {
+ return new
InputSource(PomReader.class.getResourceAsStream("m2-entities.ent"));
+ }
+ return null;
+ }
+ });
+ projectElement = pomDomDoc.getDocumentElement();
+ if (!PROJECT.equals(projectElement.getNodeName())) {
+ throw new SAXParseException("project must be the root tag" ,
res.getName() ,
+ res.getName(), 0, 0);
+ }
+ parentElement = getFirstChildElement(projectElement , PARENT);
+ } finally {
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
}
- parentElement = getFirstChildElement(projectElement , PARENT);
- //TODO read the properties because it must be used to interpret every
other field
}
@@ -471,8 +495,74 @@
return r;
}
+ private static final class AddDTDFilterInputStream extends
FilterInputStream {
+ private static String DOCTYPE = "<!DOCTYPE project SYSTEM
\"m2-entities.ent\">\n";
+ private int count;
+ private byte[] prefix = DOCTYPE.getBytes();
+
+ private AddDTDFilterInputStream(InputStream in) throws IOException {
+ super(in);
+
+ if (!in.markSupported()) {
+ throw new IllegalArgumentException("The inputstream doesn't
support mark");
+ }
+
+ in.mark(10000);
+
+ int bytesToSkip = 0;
+ LineNumberReader reader = new LineNumberReader(new
InputStreamReader(in, "UTF-8"));
+ String firstLine = reader.readLine();
+ if (firstLine != null) {
+ String trimmed = firstLine.trim();
+ if (trimmed.startsWith("<?xml ")) {
+ int endIndex = trimmed.indexOf("?>");
+ String xmlDecl = trimmed.substring(0, endIndex + 2);
+ prefix = (xmlDecl + "\n" + DOCTYPE).getBytes();
+ bytesToSkip = xmlDecl.getBytes().length;
+ }
+ }
+
+ in.reset();
+ for (int i = 0; i < bytesToSkip; i++) {
+ in.read();
+ }
+ }
+ public int read() throws IOException {
+ if (count < prefix.length) {
+ return prefix[count++];
+ }
+
+ int result = super.read();
+ return result;
+ }
+
+ public int read(byte[] b, int off, int len) throws IOException {
+ if (b == null) {
+ throw new NullPointerException();
+ } else if ((off < 0) || (off > b.length) || (len < 0) ||
+ ((off + len) > b.length) || ((off + len) < 0)) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0) {
+ return 0;
+ }
+ int nbrBytesCopied = 0;
+
+ if (count < prefix.length) {
+ int nbrBytesFromPrefix = Math.min(prefix.length - count, len);
+ System.arraycopy(prefix, count, b, off, nbrBytesFromPrefix);
+ nbrBytesCopied = nbrBytesFromPrefix;
+ }
+
+ if (nbrBytesCopied < len) {
+ nbrBytesCopied += in.read(b, off + nbrBytesCopied, len -
nbrBytesCopied);
+ }
+
+ count += nbrBytesCopied;
+ return nbrBytesCopied;
+ }
+ }
}
Added:
ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/parser/m2/m2-entities.ent
URL:
http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/parser/m2/m2-entities.ent?rev=700610&view=auto
==============================================================================
---
ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/parser/m2/m2-entities.ent
(added)
+++
ant/ivy/core/trunk/src/java/org/apache/ivy/plugins/parser/m2/m2-entities.ent
Tue Sep 30 15:22:12 2008
@@ -0,0 +1,114 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<!ENTITY nbsp " ">
+<!ENTITY iexcl "¡">
+<!ENTITY cent "¢">
+<!ENTITY pound "£">
+<!ENTITY curren "¤">
+<!ENTITY yen "¥">
+<!ENTITY brvbar "¦">
+<!ENTITY sect "§">
+<!ENTITY uml "¨">
+<!ENTITY copy "©">
+<!ENTITY ordf "ª">
+<!ENTITY laquo "«">
+<!ENTITY not "¬">
+<!ENTITY shy "­">
+<!ENTITY reg "®">
+<!ENTITY macr "¯">
+<!ENTITY deg "°">
+<!ENTITY plusmn "±">
+<!ENTITY sup2 "²">
+<!ENTITY sup3 "³">
+<!ENTITY acute "´">
+<!ENTITY micro "µ">
+<!ENTITY para "¶">
+<!ENTITY middot "·">
+<!ENTITY cedil "¸">
+<!ENTITY sup1 "¹">
+<!ENTITY ordm "º">
+<!ENTITY raquo "»">
+<!ENTITY frac14 "¼">
+<!ENTITY frac12 "½">
+<!ENTITY frac34 "¾">
+<!ENTITY iquest "¿">
+<!ENTITY Agrave "À">
+<!ENTITY Aacute "Á">
+<!ENTITY Acirc "Â">
+<!ENTITY Atilde "Ã">
+<!ENTITY Auml "Ä">
+<!ENTITY Aring "Å">
+<!ENTITY AElig "Æ">
+<!ENTITY Ccedil "Ç">
+<!ENTITY Egrave "È">
+<!ENTITY Eacute "É">
+<!ENTITY Ecirc "Ê">
+<!ENTITY Euml "Ë">
+<!ENTITY Igrave "Ì">
+<!ENTITY Iacute "Í">
+<!ENTITY Icirc "Î">
+<!ENTITY Iuml "Ï">
+<!ENTITY ETH "Ð">
+<!ENTITY Ntilde "Ñ">
+<!ENTITY Ograve "Ò">
+<!ENTITY Oacute "Ó">
+<!ENTITY Ocirc "Ô">
+<!ENTITY Otilde "Õ">
+<!ENTITY Ouml "Ö">
+<!ENTITY times "×">
+<!ENTITY Oslash "Ø">
+<!ENTITY Ugrave "Ù">
+<!ENTITY Uacute "Ú">
+<!ENTITY Ucirc "Û">
+<!ENTITY Uuml "Ü">
+<!ENTITY Yacute "Ý">
+<!ENTITY THORN "Þ">
+<!ENTITY szlig "ß">
+<!ENTITY agrave "à">
+<!ENTITY aacute "á">
+<!ENTITY acirc "â">
+<!ENTITY atilde "ã">
+<!ENTITY auml "ä">
+<!ENTITY aring "å">
+<!ENTITY aelig "æ">
+<!ENTITY ccedil "ç">
+<!ENTITY egrave "è">
+<!ENTITY eacute "é">
+<!ENTITY ecirc "ê">
+<!ENTITY euml "ë">
+<!ENTITY igrave "ì">
+<!ENTITY iacute "í">
+<!ENTITY icirc "î">
+<!ENTITY iuml "ï">
+<!ENTITY eth "ð">
+<!ENTITY ntilde "ñ">
+<!ENTITY ograve "ò">
+<!ENTITY oacute "ó">
+<!ENTITY ocirc "ô">
+<!ENTITY otilde "õ">
+<!ENTITY ouml "ö">
+<!ENTITY divide "÷">
+<!ENTITY oslash "ø">
+<!ENTITY ugrave "ù">
+<!ENTITY uacute "ú">
+<!ENTITY ucirc "û">
+<!ENTITY uuml "ü">
+<!ENTITY yacute "ý">
+<!ENTITY thorn "þ">
+<!ENTITY yuml "ÿ">
Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/util/XMLHelper.java
URL:
http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/util/XMLHelper.java?rev=700610&r1=700609&r2=700610&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/util/XMLHelper.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/util/XMLHelper.java Tue Sep 30
15:22:12 2008
@@ -30,13 +30,15 @@
import org.apache.ivy.plugins.repository.Resource;
import org.apache.ivy.util.url.URLHandlerRegistry;
import org.w3c.dom.Document;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
-import org.xml.sax.InputSource;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.DefaultHandler;
public abstract class XMLHelper {
+
private static final SAXParserFactory VALIDATING_FACTORY =
SAXParserFactory.newInstance();
private static final SAXParserFactory FACTORY =
SAXParserFactory.newInstance();
@@ -193,23 +195,30 @@
}
- public static Document parseToDom(URL descriptorURL, Resource res) throws
IOException,
+ public static Document parseToDom(InputStream stream, Resource res,
EntityResolver entityResolver) throws IOException,
SAXException {
- DocumentBuilder docBuilder = getDocBuilder();
- InputStream pomStream = res.openStream();
+ DocumentBuilder docBuilder = getDocBuilder(entityResolver);
Document pomDomDoc;
try {
- pomDomDoc = docBuilder.parse(pomStream, res.getName());
+ pomDomDoc = docBuilder.parse(stream, res.getName());
+ } catch (SAXException e ) {
+ e.printStackTrace();
+ throw e;
} finally {
- pomStream.close();
+ stream.close();
}
return pomDomDoc;
}
- public static DocumentBuilder getDocBuilder() {
+ public static DocumentBuilder getDocBuilder(EntityResolver entityResolver)
{
if (docBuilder == null) {
try {
- docBuilder =
DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
+ factory.setValidating(false);
+ docBuilder = factory.newDocumentBuilder();
+ if (entityResolver != null) {
+ docBuilder.setEntityResolver(entityResolver);
+ }
} catch (ParserConfigurationException e) {
throw new RuntimeException(e);
}