sync merge to trunk

git-svn-id: https://svn.apache.org/repos/asf/poi/branches/xml_signature@1617624 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andreas Beeker 2014-08-12 23:33:07 +00:00
commit c378d75e51
27 changed files with 621 additions and 732 deletions

View File

@ -1,30 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<classpath> <classpath>
<classpathentry kind="src" path="src/java"/> <classpathentry kind="src" path="src/java"/>
<classpathentry kind="src" path="src/testcases"/> <classpathentry kind="src" path="src/testcases"/>
<classpathentry kind="src" path="src/resources/main"/> <classpathentry kind="src" path="src/resources/main"/>
<classpathentry kind="src" path="src/ooxml/java"/> <classpathentry kind="src" path="src/ooxml/java"/>
<classpathentry kind="src" path="src/ooxml/testcases"/> <classpathentry kind="src" path="src/ooxml/testcases"/>
<classpathentry kind="src" path="src/resources/ooxml"/> <classpathentry kind="src" path="src/resources/ooxml"/>
<classpathentry kind="src" path="src/scratchpad/src"/> <classpathentry kind="src" path="src/scratchpad/src"/>
<classpathentry kind="src" path="src/scratchpad/testcases"/> <classpathentry kind="src" path="src/scratchpad/testcases"/>
<classpathentry kind="src" path="src/resources/scratchpad"/> <classpathentry kind="src" path="src/resources/scratchpad"/>
<classpathentry kind="src" path="src/contrib/poi-ruby/java"/> <classpathentry kind="src" path="src/contrib/poi-ruby/java"/>
<classpathentry kind="src" path="src/examples/src"/> <classpathentry kind="src" path="src/examples/src"/>
<classpathentry kind="src" path="src/excelant/java"/> <classpathentry kind="src" path="src/excelant/java"/>
<classpathentry kind="src" path="src/excelant/testcases"/> <classpathentry kind="src" path="src/excelant/testcases"/>
<classpathentry kind="src" path="src/excelant/resources"/> <classpathentry kind="src" path="src/excelant/resources"/>
<classpathentry kind="lib" path="lib/ant-1.9.4.jar"/> <classpathentry kind="lib" path="lib/ant-1.9.4.jar"/>
<classpathentry kind="lib" path="lib/ant-launcher-1.9.4.jar"/> <classpathentry kind="lib" path="lib/ant-launcher-1.9.4.jar"/>
<classpathentry kind="lib" path="lib/commons-codec-1.9.jar"/> <classpathentry kind="lib" path="lib/commons-codec-1.9.jar"/>
<classpathentry kind="lib" path="lib/commons-logging-1.1.3.jar"/> <classpathentry kind="lib" path="lib/commons-logging-1.1.3.jar"/>
<classpathentry kind="lib" path="lib/log4j-1.2.17.jar"/> <classpathentry kind="lib" path="lib/log4j-1.2.17.jar"/>
<classpathentry kind="lib" path="ooxml-lib/dom4j-1.6.1.jar"/> <classpathentry kind="lib" path="ooxml-lib/xmlbeans-2.6.0.jar"/>
<classpathentry kind="lib" path="ooxml-lib/xmlbeans-2.6.0.jar"/> <classpathentry kind="lib" path="lib/hamcrest-core-1.3.jar"/>
<classpathentry kind="lib" path="lib/hamcrest-core-1.3.jar"/> <classpathentry kind="lib" path="lib/junit-4.11.jar"/>
<classpathentry kind="lib" path="lib/junit-4.11.jar"/> <classpathentry kind="lib" path="ooxml-lib/ooxml-schemas-1.1.jar" sourcepath="ooxml-lib/ooxml-schemas-src-1.1.jar"/>
<classpathentry kind="lib" path="ooxml-lib/ooxml-schemas-1.1.jar" sourcepath="ooxml-lib/ooxml-schemas-src-1.1.jar"/> <classpathentry kind="lib" path="ooxml-lib/ooxml-encryption-1.2.jar" sourcepath="ooxml-lib/ooxml-encryption-src-1.2.jar"/>
<classpathentry kind="lib" path="ooxml-lib/ooxml-encryption-1.2.jar" sourcepath="ooxml-lib/ooxml-encryption-src-1.2.jar"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> <classpathentry kind="lib" path="lib/mockito-core-1.9.5.jar" sourcepath="E:/tmp/mavenRepo/org/mockito/mockito-core/1.9.5/mockito-core-1.9.5-sources.jar"/>
<classpathentry kind="output" path="build/eclipse"/> <classpathentry kind="output" path="build/eclipse"/>
</classpath> </classpath>

View File

@ -0,0 +1,6 @@
eclipse.preferences.version=1
extraProperties=
lastAnalysisDate=1394235544000
projectKey=org.apache.poi\:poi-main
serverUrl=http\://nemo.sonarqube.org
version=2

View File

@ -147,8 +147,6 @@ under the License.
<property name="main.antlauncher.url" value="${repository.m2}/maven2/org/apache/ant/ant-launcher/1.9.4/ant-launcher-1.9.4.jar"/> <property name="main.antlauncher.url" value="${repository.m2}/maven2/org/apache/ant/ant-launcher/1.9.4/ant-launcher-1.9.4.jar"/>
<!-- jars in the lib-ooxml directory, see the fetch-ooxml-jars target--> <!-- jars in the lib-ooxml directory, see the fetch-ooxml-jars target-->
<property name="ooxml.dom4j.jar" location="${ooxml.lib}/dom4j-1.6.1.jar"/>
<property name="ooxml.dom4j.url" value="${repository.m2}/maven2/dom4j/dom4j/1.6.1/dom4j-1.6.1.jar"/>
<property name="ooxml.xmlbeans23.jar" location="${ooxml.lib}/xmlbeans-2.3.0.jar"/> <property name="ooxml.xmlbeans23.jar" location="${ooxml.lib}/xmlbeans-2.3.0.jar"/>
<property name="ooxml.xmlbeans23.url" <property name="ooxml.xmlbeans23.url"
value="${repository.m2}/maven2/org/apache/xmlbeans/xmlbeans/2.3.0/xmlbeans-2.3.0.jar"/> value="${repository.m2}/maven2/org/apache/xmlbeans/xmlbeans/2.3.0/xmlbeans-2.3.0.jar"/>
@ -233,7 +231,6 @@ under the License.
</path> </path>
<path id="ooxml.classpath"> <path id="ooxml.classpath">
<pathelement location="${ooxml.dom4j.jar}"/>
<pathelement location="${ooxml.xmlbeans26.jar}"/> <pathelement location="${ooxml.xmlbeans26.jar}"/>
<pathelement location="${ooxml.xsds.jar}"/> <pathelement location="${ooxml.xsds.jar}"/>
<path refid="main.classpath"/> <path refid="main.classpath"/>
@ -263,7 +260,6 @@ under the License.
</path> </path>
<path id="ooxml-lite.classpath"> <path id="ooxml-lite.classpath">
<pathelement location="${ooxml.dom4j.jar}"/>
<pathelement location="${ooxml.xmlbeans26.jar}"/> <pathelement location="${ooxml.xmlbeans26.jar}"/>
<pathelement location="build/ooxml-xsds-lite"/> <!-- instead of ooxml-xsds.jar use the filtered classes--> <pathelement location="build/ooxml-xsds-lite"/> <!-- instead of ooxml-xsds.jar use the filtered classes-->
<path refid="main.classpath"/> <path refid="main.classpath"/>
@ -441,7 +437,6 @@ under the License.
<condition property="ooxml.jars.present"> <condition property="ooxml.jars.present">
<or> <or>
<and> <and>
<available file="${ooxml.dom4j.jar}"/>
<available file="${ooxml.xmlbeans23.jar}"/> <available file="${ooxml.xmlbeans23.jar}"/>
<available file="${ooxml.xmlbeans26.jar}"/> <available file="${ooxml.xmlbeans26.jar}"/>
<available file="${ooxml.xsds.jar}"/> <available file="${ooxml.xsds.jar}"/>
@ -452,10 +447,6 @@ under the License.
</target> </target>
<target name="fetch-ooxml-jars" depends="check-ooxml-jars" unless="ooxml.jars.present"> <target name="fetch-ooxml-jars" depends="check-ooxml-jars" unless="ooxml.jars.present">
<mkdir dir="${ooxml.lib}"/> <mkdir dir="${ooxml.lib}"/>
<antcall target="downloadfile">
<param name="sourcefile" value="${ooxml.dom4j.url}"/>
<param name="destfile" value="${ooxml.dom4j.jar}"/>
</antcall>
<antcall target="downloadfile"> <antcall target="downloadfile">
<param name="sourcefile" value="${ooxml.xmlbeans23.url}"/> <param name="sourcefile" value="${ooxml.xmlbeans23.url}"/>
<param name="destfile" value="${ooxml.xmlbeans23.jar}"/> <param name="destfile" value="${ooxml.xmlbeans23.jar}"/>
@ -1306,7 +1297,6 @@ under the License.
<include name="log4j-*.jar"/> <include name="log4j-*.jar"/>
</zipfileset> </zipfileset>
<zipfileset dir="${ooxml.lib}" prefix="${zipdir}/ooxml-lib"> <zipfileset dir="${ooxml.lib}" prefix="${zipdir}/ooxml-lib">
<include name="dom4j-*.jar"/>
<include name="xmlbeans-2.6*.jar"/> <include name="xmlbeans-2.6*.jar"/>
</zipfileset> </zipfileset>
<zipfileset dir="${dist.dir}" prefix="${zipdir}"> <zipfileset dir="${dist.dir}" prefix="${zipdir}">
@ -1334,7 +1324,6 @@ under the License.
<include name="log4j-*.jar"/> <include name="log4j-*.jar"/>
</zipfileset> </zipfileset>
<tarfileset dir="${ooxml.lib}" prefix="${zipdir}/ooxml-lib"> <tarfileset dir="${ooxml.lib}" prefix="${zipdir}/ooxml-lib">
<include name="dom4j-*.jar"/>
<include name="xmlbeans-2.6*.jar"/> <include name="xmlbeans-2.6*.jar"/>
</tarfileset> </tarfileset>
<tarfileset dir="${build.site}" prefix="${zipdir}/docs"/> <tarfileset dir="${build.site}" prefix="${zipdir}/docs"/>
@ -1467,7 +1456,6 @@ under the License.
<auxClasspath path="ooxml-lib/ooxml-schemas-1.1.jar" /> <auxClasspath path="ooxml-lib/ooxml-schemas-1.1.jar" />
<auxClasspath path="ooxml-lib/ooxml-encryption-1.2.jar" /> <auxClasspath path="ooxml-lib/ooxml-encryption-1.2.jar" />
<auxClasspath path="ooxml-lib/xmlbeans-2.6.0.jar" /> <auxClasspath path="ooxml-lib/xmlbeans-2.6.0.jar" />
<auxClasspath path="ooxml-lib/dom4j-1.6.1.jar" />
<auxClasspath path="lib/commons-codec-1.9.jar" /> <auxClasspath path="lib/commons-codec-1.9.jar" />
<auxClasspath path="lib/commons-logging-1.1.3.jar" /> <auxClasspath path="lib/commons-logging-1.1.3.jar" />
<auxClasspath path="lib/junit-4.11.jar" /> <auxClasspath path="lib/junit-4.11.jar" />

View File

@ -229,50 +229,6 @@ Office Open XML schemas (ooxml-schemas-1.1.jar)
[5] http://www.ecma-international.org/publications/files/ECMA-ST/Ecma%20PATENT/Patent%20statements%20ok/ECMA-376%20Adobe%20Patent%20Declaration.pdf [5] http://www.ecma-international.org/publications/files/ECMA-ST/Ecma%20PATENT/Patent%20statements%20ok/ECMA-376%20Adobe%20Patent%20Declaration.pdf
DOM4J library (dom4j-1.6.1.jar)
Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
Redistribution and use of this software and associated documentation
("Software"), with or without modification, are permitted provided
that the following conditions are met:
1. Redistributions of source code must retain copyright
statements and notices. Redistributions must also contain a
copy of this document.
2. Redistributions in binary form must reproduce the
above copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
3. The name "DOM4J" must not be used to endorse or promote
products derived from this Software without prior written
permission of MetaStuff, Ltd. For written permission,
please contact dom4j-info@metastuff.com.
4. Products derived from this Software may not be called "DOM4J"
nor may "DOM4J" appear in their names without prior written
permission of MetaStuff, Ltd. DOM4J is a registered
trademark of MetaStuff, Ltd.
5. Due credit should be given to the DOM4J Project -
http://www.dom4j.org
THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
METASTUFF, LTD. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
JUnit test library (junit-4.11.jar) JUnit test library (junit-4.11.jar)
Common Public License - v 1.0 Common Public License - v 1.0

View File

@ -4,9 +4,6 @@ Copyright 2003-2014 The Apache Software Foundation
This product includes software developed by This product includes software developed by
The Apache Software Foundation (http://www.apache.org/). The Apache Software Foundation (http://www.apache.org/).
This product contains the DOM4J library (http://www.dom4j.org).
Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
This product contains parts that were originally based on software from BEA. This product contains parts that were originally based on software from BEA.
Copyright (c) 2000-2003, BEA Systems, <http://www.bea.com/>. Copyright (c) 2000-2003, BEA Systems, <http://www.bea.com/>.

View File

@ -69,10 +69,5 @@
<artifactId>poi-ooxml-schemas</artifactId> <artifactId>poi-ooxml-schemas</artifactId>
<version>@VERSION@</version> <version>@VERSION@</version>
</dependency> </dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -116,12 +116,6 @@
<version>2.3.0</version> <version>2.3.0</version>
</dependency> </dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<!-- non-test dependency for OOXMLLite --> <!-- non-test dependency for OOXMLLite -->
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>

View File

@ -179,7 +179,7 @@ public class ExcelAntTask extends Task {
throw new BuildException( throw new BuildException(
"The <classpath> for <excelant> must include poi.jar and poi-ooxml.jar " + "The <classpath> for <excelant> must include poi.jar and poi-ooxml.jar " +
"if not in Ant's own classpath. Processing .xlsx spreadsheets requires " + "if not in Ant's own classpath. Processing .xlsx spreadsheets requires " +
"additional poi-ooxml-schemas.jar, xmlbeans.jar and dom4j.jar" , "additional poi-ooxml-schemas.jar, xmlbeans.jar" ,
e, getLocation()); e, getLocation());
} }

View File

@ -21,7 +21,7 @@ import java.io.File;
/** /**
* Storage class for configuration storage parameters. * Storage class for configuration storage parameters.
* TODO xml syntax checking is no longer done with DOM4j parser -> remove the schema or do it ? * TODO xml syntax checking is not done with JAXP by default -> remove the schema or do it ?
* *
* @author CDubettier, Julen Chable * @author CDubettier, Julen Chable
* @version 1.0 * @version 1.0

View File

@ -27,9 +27,10 @@ import org.apache.poi.openxml4j.exceptions.InvalidOperationException;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
import org.apache.poi.util.SAXHelper; import org.apache.poi.util.SAXHelper;
import org.dom4j.Attribute; import org.w3c.dom.Attr;
import org.dom4j.Document; import org.w3c.dom.Document;
import org.dom4j.Element; import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/** /**
* Represents a collection of PackageRelationship elements that are owned by a * Represents a collection of PackageRelationship elements that are owned by a
@ -313,22 +314,19 @@ public final class PackageRelationshipCollection implements
Document xmlRelationshipsDoc = SAXHelper.readSAXDocument(relPart.getInputStream()); Document xmlRelationshipsDoc = SAXHelper.readSAXDocument(relPart.getInputStream());
// Browse default types // Browse default types
Element root = xmlRelationshipsDoc.getRootElement(); Element root = xmlRelationshipsDoc.getDocumentElement();
// Check OPC compliance M4.1 rule // Check OPC compliance M4.1 rule
boolean fCorePropertiesRelationship = false; boolean fCorePropertiesRelationship = false;
@SuppressWarnings("unchecked") NodeList nodeList = root.getElementsByTagName(PackageRelationship.RELATIONSHIP_TAG_NAME);
Iterator<Element> iter = (Iterator<Element>) int nodeCount = nodeList.getLength();
root.elementIterator(PackageRelationship.RELATIONSHIP_TAG_NAME); for (int i = 0; i < nodeCount; i++) {
while (iter.hasNext()) { Element element = (Element)nodeList.item(i);
Element element = iter.next();
// Relationship ID // Relationship ID
String id = element.attribute( String id = element.getAttribute(PackageRelationship.ID_ATTRIBUTE_NAME);
PackageRelationship.ID_ATTRIBUTE_NAME).getValue();
// Relationship type // Relationship type
String type = element.attribute( String type = element.getAttribute(PackageRelationship.TYPE_ATTRIBUTE_NAME);
PackageRelationship.TYPE_ATTRIBUTE_NAME).getValue();
/* Check OPC Compliance */ /* Check OPC Compliance */
// Check Rule M4.1 // Check Rule M4.1
@ -342,8 +340,7 @@ public final class PackageRelationshipCollection implements
/* End OPC Compliance */ /* End OPC Compliance */
// TargetMode (default value "Internal") // TargetMode (default value "Internal")
Attribute targetModeAttr = element Attr targetModeAttr = element.getAttributeNode(PackageRelationship.TARGET_MODE_ATTRIBUTE_NAME);
.attribute(PackageRelationship.TARGET_MODE_ATTRIBUTE_NAME);
TargetMode targetMode = TargetMode.INTERNAL; TargetMode targetMode = TargetMode.INTERNAL;
if (targetModeAttr != null) { if (targetModeAttr != null) {
targetMode = targetModeAttr.getValue().toLowerCase() targetMode = targetModeAttr.getValue().toLowerCase()
@ -353,9 +350,7 @@ public final class PackageRelationshipCollection implements
// Target converted in URI // Target converted in URI
URI target = PackagingURIHelper.toURI("http://invalid.uri"); // dummy url URI target = PackagingURIHelper.toURI("http://invalid.uri"); // dummy url
String value = element.attribute( String value = element.getAttribute(PackageRelationship.TARGET_ATTRIBUTE_NAME);
PackageRelationship.TARGET_ATTRIBUTE_NAME)
.getValue();
try { try {
// when parsing of the given uri fails, we can either // when parsing of the given uri fails, we can either
// ignore this relationship, which leads to IllegalStateException // ignore this relationship, which leads to IllegalStateException

View File

@ -17,21 +17,36 @@
package org.apache.poi.openxml4j.opc; package org.apache.poi.openxml4j.opc;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import org.dom4j.Document; import javax.xml.transform.OutputKeys;
import org.dom4j.io.OutputFormat; import javax.xml.transform.Result;
import org.dom4j.io.XMLWriter; import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
public final class StreamHelper { public final class StreamHelper {
private StreamHelper() { private StreamHelper() {
// Do nothing // Do nothing
} }
private static final TransformerFactory transformerFactory = TransformerFactory.newInstance();
private static synchronized Transformer getIdentityTransformer() throws TransformerException {
return transformerFactory.newTransformer();
}
/** /**
* Turning the DOM4j object in the specified output stream. * Save the document object in the specified output stream.
* *
* @param xmlContent * @param xmlContent
* The XML document. * The XML document.
@ -40,18 +55,34 @@ public final class StreamHelper {
* @return <b>true</b> if the xml is successfully written in the stream, * @return <b>true</b> if the xml is successfully written in the stream,
* else <b>false</b>. * else <b>false</b>.
*/ */
public static boolean saveXmlInStream(Document xmlContent, public static boolean saveXmlInStream(Document xmlContent,
OutputStream outStream) { OutputStream outStream) {
try { try {
OutputFormat outformat = OutputFormat.createPrettyPrint(); Transformer trans = getIdentityTransformer();
outformat.setEncoding("UTF-8"); Source xmlSource = new DOMSource(xmlContent);
XMLWriter writer = new XMLWriter(outStream, outformat); // prevent close of stream by transformer:
writer.write(xmlContent); Result outputTarget = new StreamResult(new FilterOutputStream(
} catch (Exception e) { outStream) {
return false; @Override
} public void write(byte b[], int off, int len)
return true; throws IOException {
} out.write(b, off, len);
}
@Override
public void close() throws IOException {
out.flush(); // only flush, don't close!
}
});
trans.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
trans.setOutputProperty(OutputKeys.INDENT, "yes");
trans.setOutputProperty(OutputKeys.STANDALONE, "yes");
trans.transform(xmlSource, outputTarget);
} catch (TransformerException e) {
return false;
}
return true;
}
/** /**
* Copy the input stream into the output stream. * Copy the input stream into the output stream.

View File

@ -17,12 +17,11 @@
package org.apache.poi.openxml4j.opc.internal; package org.apache.poi.openxml4j.opc.internal;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.TreeMap; import java.util.TreeMap;
@ -33,13 +32,12 @@ import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagePartName; import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackagingURIHelper; import org.apache.poi.openxml4j.opc.PackagingURIHelper;
import org.apache.poi.util.DocumentHelper;
import org.apache.poi.util.SAXHelper; import org.apache.poi.util.SAXHelper;
import org.dom4j.Document; import org.w3c.dom.Document;
import org.dom4j.DocumentException; import org.w3c.dom.Element;
import org.dom4j.DocumentHelper; import org.w3c.dom.NodeList;
import org.dom4j.Element; import org.xml.sax.SAXException;
import org.dom4j.Namespace;
import org.dom4j.QName;
/** /**
* Manage package content types ([Content_Types].xml part). * Manage package content types ([Content_Types].xml part).
@ -375,38 +373,33 @@ public abstract class ContentTypeManager {
Document xmlContentTypetDoc = SAXHelper.readSAXDocument(in); Document xmlContentTypetDoc = SAXHelper.readSAXDocument(in);
// Default content types // Default content types
List defaultTypes = xmlContentTypetDoc.getRootElement().elements( NodeList defaultTypes = xmlContentTypetDoc.getDocumentElement().getElementsByTagName(DEFAULT_TAG_NAME);
DEFAULT_TAG_NAME); int defaultTypeCount = defaultTypes.getLength();
Iterator elementIteratorDefault = defaultTypes.iterator(); for (int i = 0; i < defaultTypeCount; i++) {
while (elementIteratorDefault.hasNext()) { Element element = (Element) defaultTypes.item(i);
Element element = (Element) elementIteratorDefault.next(); String extension = element.getAttribute(EXTENSION_ATTRIBUTE_NAME);
String extension = element.attribute(EXTENSION_ATTRIBUTE_NAME) String contentType = element.getAttribute(CONTENT_TYPE_ATTRIBUTE_NAME);
.getValue();
String contentType = element.attribute(
CONTENT_TYPE_ATTRIBUTE_NAME).getValue();
addDefaultContentType(extension, contentType); addDefaultContentType(extension, contentType);
} }
// Overriden content types // Overriden content types
List overrideTypes = xmlContentTypetDoc.getRootElement().elements( NodeList overrideTypes = xmlContentTypetDoc.getDocumentElement().getElementsByTagName(OVERRIDE_TAG_NAME);
OVERRIDE_TAG_NAME); int overrideTypeCount = overrideTypes.getLength();
Iterator elementIteratorOverride = overrideTypes.iterator(); for (int i = 0; i < overrideTypeCount; i++) {
while (elementIteratorOverride.hasNext()) { Element element = (Element) overrideTypes.item(i);
Element element = (Element) elementIteratorOverride.next(); URI uri = new URI(element.getAttribute(PART_NAME_ATTRIBUTE_NAME));
URI uri = new URI(element.attribute(PART_NAME_ATTRIBUTE_NAME) PackagePartName partName = PackagingURIHelper.createPartName(uri);
.getValue()); String contentType = element.getAttribute(CONTENT_TYPE_ATTRIBUTE_NAME);
PackagePartName partName = PackagingURIHelper
.createPartName(uri);
String contentType = element.attribute(
CONTENT_TYPE_ATTRIBUTE_NAME).getValue();
addOverrideContentType(partName, contentType); addOverrideContentType(partName, contentType);
} }
} catch (URISyntaxException urie) { } catch (URISyntaxException urie) {
throw new InvalidFormatException(urie.getMessage()); throw new InvalidFormatException(urie.getMessage());
} catch (DocumentException e) { } catch (SAXException e) {
throw new InvalidFormatException(e.getMessage()); throw new InvalidFormatException(e.getMessage());
} } catch (IOException e) {
} throw new InvalidFormatException(e.getMessage());
}
}
/** /**
* Save the contents type part. * Save the contents type part.
@ -420,9 +413,8 @@ public abstract class ContentTypeManager {
Document xmlOutDoc = DocumentHelper.createDocument(); Document xmlOutDoc = DocumentHelper.createDocument();
// Building namespace // Building namespace
Namespace dfNs = Namespace.get("", TYPES_NAMESPACE_URI); Element typesElem = xmlOutDoc.createElementNS(TYPES_NAMESPACE_URI, TYPES_TAG_NAME);
Element typesElem = xmlOutDoc xmlOutDoc.appendChild(typesElem);
.addElement(new QName(TYPES_TAG_NAME, dfNs));
// Adding default types // Adding default types
for (Entry<String, String> entry : defaultContentType.entrySet()) { for (Entry<String, String> entry : defaultContentType.entrySet()) {
@ -453,10 +445,10 @@ public abstract class ContentTypeManager {
*/ */
private void appendSpecificTypes(Element root, private void appendSpecificTypes(Element root,
Entry<PackagePartName, String> entry) { Entry<PackagePartName, String> entry) {
root.addElement(OVERRIDE_TAG_NAME).addAttribute( Element specificType = root.getOwnerDocument().createElement(OVERRIDE_TAG_NAME);
PART_NAME_ATTRIBUTE_NAME, specificType.setAttribute(PART_NAME_ATTRIBUTE_NAME, entry.getKey().getName());
entry.getKey().getName()).addAttribute( specificType.setAttribute(CONTENT_TYPE_ATTRIBUTE_NAME, entry.getValue());
CONTENT_TYPE_ATTRIBUTE_NAME, entry.getValue()); root.appendChild(specificType);
} }
/** /**
@ -469,11 +461,10 @@ public abstract class ContentTypeManager {
* @see #save(java.io.OutputStream) * @see #save(java.io.OutputStream)
*/ */
private void appendDefaultType(Element root, Entry<String, String> entry) { private void appendDefaultType(Element root, Entry<String, String> entry) {
root.addElement(DEFAULT_TAG_NAME).addAttribute( Element defaultType = root.getOwnerDocument().createElement(DEFAULT_TAG_NAME);
EXTENSION_ATTRIBUTE_NAME, entry.getKey()) defaultType.setAttribute(EXTENSION_ATTRIBUTE_NAME, entry.getKey());
.addAttribute(CONTENT_TYPE_ATTRIBUTE_NAME, defaultType.setAttribute(CONTENT_TYPE_ATTRIBUTE_NAME, entry.getValue());
entry.getValue()); root.appendChild(defaultType);
} }
/** /**

View File

@ -48,8 +48,6 @@ public final class PackagePropertiesPart extends PackagePart implements
public final static String NAMESPACE_DCTERMS_URI = "http://purl.org/dc/terms/"; public final static String NAMESPACE_DCTERMS_URI = "http://purl.org/dc/terms/";
public final static String NAMESPACE_XSI_URI = "http://www.w3.org/2001/XMLSchema-instance";
/** /**
* Constructor. * Constructor.
* *

View File

@ -17,8 +17,6 @@
package org.apache.poi.openxml4j.opc.internal; package org.apache.poi.openxml4j.opc.internal;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
@ -30,7 +28,7 @@ import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.StreamHelper; import org.apache.poi.openxml4j.opc.StreamHelper;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
import org.dom4j.Document; import org.w3c.dom.Document;
/** /**
* Zip implementation of the ContentTypeManager. * Zip implementation of the ContentTypeManager.
@ -69,17 +67,8 @@ public class ZipContentTypeManager extends ContentTypeManager {
// Referenced in ZIP // Referenced in ZIP
zos.putNextEntry(partEntry); zos.putNextEntry(partEntry);
// Saving data in the ZIP file // Saving data in the ZIP file
ByteArrayOutputStream outTemp = new ByteArrayOutputStream(); if (!StreamHelper.saveXmlInStream(content, zos)) {
StreamHelper.saveXmlInStream(content, out); return false;
InputStream ins = new ByteArrayInputStream(outTemp.toByteArray());
byte[] buff = new byte[ZipHelper.READ_WRITE_FILE_BUFFER_SIZE];
while (ins.available() > 0) {
int resultRead = ins.read(buff);
if (resultRead == -1) {
// end of file reached
break;
}
zos.write(buff, 0, resultRead);
} }
zos.closeEntry(); zos.closeEntry();
} catch (IOException ioe) { } catch (IOException ioe) {

View File

@ -19,15 +19,18 @@ package org.apache.poi.openxml4j.opc.internal.marshallers;
import java.io.OutputStream; import java.io.OutputStream;
import org.dom4j.Document; import javax.xml.XMLConstants;
import org.dom4j.DocumentHelper; import javax.xml.stream.XMLEventFactory;
import org.dom4j.Element; import javax.xml.stream.events.Namespace;
import org.dom4j.Namespace;
import org.dom4j.QName;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart; import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart;
import org.apache.poi.openxml4j.opc.internal.PartMarshaller; import org.apache.poi.openxml4j.opc.internal.PartMarshaller;
import org.apache.poi.openxml4j.util.Nullable;
import org.apache.poi.util.DocumentHelper;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/** /**
* Package properties marshaller. * Package properties marshaller.
@ -36,17 +39,15 @@ import org.apache.poi.openxml4j.opc.internal.PartMarshaller;
*/ */
public class PackagePropertiesMarshaller implements PartMarshaller { public class PackagePropertiesMarshaller implements PartMarshaller {
private final static Namespace namespaceDC = new Namespace("dc",
PackagePropertiesPart.NAMESPACE_DC_URI); private final static Namespace namespaceDC, namespaceCoreProperties, namespaceDcTerms, namespaceXSI;
static {
private final static Namespace namespaceCoreProperties = new Namespace("", final XMLEventFactory f = XMLEventFactory.newFactory();
PackagePropertiesPart.NAMESPACE_CP_URI); namespaceDC = f.createNamespace("dc", PackagePropertiesPart.NAMESPACE_DC_URI);
namespaceCoreProperties = f.createNamespace("cp", PackagePropertiesPart.NAMESPACE_CP_URI);
private final static Namespace namespaceDcTerms = new Namespace("dcterms", namespaceDcTerms = f.createNamespace("dcterms", PackagePropertiesPart.NAMESPACE_DCTERMS_URI);
PackagePropertiesPart.NAMESPACE_DCTERMS_URI); namespaceXSI = f.createNamespace("xsi", XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
}
private final static Namespace namespaceXSI = new Namespace("xsi",
PackagePropertiesPart.NAMESPACE_XSI_URI);
protected static final String KEYWORD_CATEGORY = "category"; protected static final String KEYWORD_CATEGORY = "category";
@ -98,13 +99,13 @@ public class PackagePropertiesMarshaller implements PartMarshaller {
// Configure the document // Configure the document
xmlDoc = DocumentHelper.createDocument(); xmlDoc = DocumentHelper.createDocument();
Element rootElem = xmlDoc.addElement(new QName("coreProperties", Element rootElem = xmlDoc.createElementNS(namespaceCoreProperties.getNamespaceURI(),
namespaceCoreProperties)); getQName("coreProperties", namespaceCoreProperties));
rootElem.addNamespace("cp", PackagePropertiesPart.NAMESPACE_CP_URI); DocumentHelper.addNamespaceDeclaration(rootElem, namespaceCoreProperties);
rootElem.addNamespace("dc", PackagePropertiesPart.NAMESPACE_DC_URI); DocumentHelper.addNamespaceDeclaration(rootElem, namespaceDC);
rootElem.addNamespace("dcterms", DocumentHelper.addNamespaceDeclaration(rootElem, namespaceDcTerms);
PackagePropertiesPart.NAMESPACE_DCTERMS_URI); DocumentHelper.addNamespaceDeclaration(rootElem, namespaceXSI);
rootElem.addNamespace("xsi", PackagePropertiesPart.NAMESPACE_XSI_URI); xmlDoc.appendChild(rootElem);
addCategory(); addCategory();
addContentStatus(); addContentStatus();
@ -125,197 +126,110 @@ public class PackagePropertiesMarshaller implements PartMarshaller {
return true; return true;
} }
/** /**
* Sets the given element's text content, creating it if necessary.
*/
private Element setElementTextContent(String localName, Namespace namespace, Nullable<String> property) {
return setElementTextContent(localName, namespace, property, property.getValue());
}
private String getQName(String localName, Namespace namespace) {
return namespace.getPrefix().isEmpty() ? localName : namespace.getPrefix() + ':' + localName;
}
private Element setElementTextContent(String localName, Namespace namespace, Nullable<?> property, String propertyValue) {
if (!property.hasValue())
return null;
Element root = xmlDoc.getDocumentElement();
Element elem = (Element) root.getElementsByTagNameNS(namespace.getNamespaceURI(), localName).item(0);
if (elem == null) {
// missing, we add it
elem = xmlDoc.createElementNS(namespace.getNamespaceURI(), getQName(localName, namespace));
root.appendChild(elem);
}
elem.setTextContent(propertyValue);
return elem;
}
private Element setElementTextContent(String localName, Namespace namespace, Nullable<?> property, String propertyValue, String xsiType) {
Element element = setElementTextContent(localName, namespace, property, propertyValue);
if (element != null) {
element.setAttributeNS(namespaceXSI.getNamespaceURI(), getQName("type", namespaceXSI), xsiType);
}
return element;
}
/**
* Add category property element if needed. * Add category property element if needed.
*/ */
private void addCategory() { private void addCategory() {
if (!propsPart.getCategoryProperty().hasValue()) setElementTextContent(KEYWORD_CATEGORY, namespaceCoreProperties, propsPart.getCategoryProperty());
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_CATEGORY, namespaceCoreProperties));
if (elem == null) {
// Missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_CATEGORY, namespaceCoreProperties));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getCategoryProperty().getValue());
} }
/** /**
* Add content status property element if needed. * Add content status property element if needed.
*/ */
private void addContentStatus() { private void addContentStatus() {
if (!propsPart.getContentStatusProperty().hasValue()) setElementTextContent(KEYWORD_CONTENT_STATUS, namespaceCoreProperties, propsPart.getContentStatusProperty());
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_CONTENT_STATUS, namespaceCoreProperties));
if (elem == null) {
// Missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_CONTENT_STATUS, namespaceCoreProperties));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getContentStatusProperty().getValue());
} }
/** /**
* Add content type property element if needed. * Add content type property element if needed.
*/ */
private void addContentType() { private void addContentType() {
if (!propsPart.getContentTypeProperty().hasValue()) setElementTextContent(KEYWORD_CONTENT_TYPE, namespaceCoreProperties, propsPart.getContentTypeProperty());
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_CONTENT_TYPE, namespaceCoreProperties));
if (elem == null) {
// Missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_CONTENT_TYPE, namespaceCoreProperties));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getContentTypeProperty().getValue());
} }
/** /**
* Add created property element if needed. * Add created property element if needed.
*/ */
private void addCreated() { private void addCreated() {
if (!propsPart.getCreatedProperty().hasValue()) setElementTextContent(KEYWORD_CREATED, namespaceDcTerms, propsPart.getCreatedProperty(),
return; propsPart.getCreatedPropertyString(), "dcterms:W3CDTF");
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_CREATED, namespaceDcTerms));
if (elem == null) {
// missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_CREATED, namespaceDcTerms));
} else {
elem.clearContent();// clear the old value
}
elem.addAttribute(new QName("type", namespaceXSI), "dcterms:W3CDTF");
elem.addText(propsPart.getCreatedPropertyString());
} }
/** /**
* Add creator property element if needed. * Add creator property element if needed.
*/ */
private void addCreator() { private void addCreator() {
if (!propsPart.getCreatorProperty().hasValue()) setElementTextContent(KEYWORD_CREATOR, namespaceDC, propsPart.getCreatorProperty());
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_CREATOR, namespaceDC));
if (elem == null) {
// missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_CREATOR, namespaceDC));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getCreatorProperty().getValue());
} }
/** /**
* Add description property element if needed. * Add description property element if needed.
*/ */
private void addDescription() { private void addDescription() {
if (!propsPart.getDescriptionProperty().hasValue()) setElementTextContent(KEYWORD_DESCRIPTION, namespaceDC, propsPart.getDescriptionProperty());
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_DESCRIPTION, namespaceDC));
if (elem == null) {
// missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_DESCRIPTION, namespaceDC));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getDescriptionProperty().getValue());
} }
/** /**
* Add identifier property element if needed. * Add identifier property element if needed.
*/ */
private void addIdentifier() { private void addIdentifier() {
if (!propsPart.getIdentifierProperty().hasValue()) setElementTextContent(KEYWORD_IDENTIFIER, namespaceDC, propsPart.getIdentifierProperty());
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_IDENTIFIER, namespaceDC));
if (elem == null) {
// missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_IDENTIFIER, namespaceDC));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getIdentifierProperty().getValue());
} }
/** /**
* Add keywords property element if needed. * Add keywords property element if needed.
*/ */
private void addKeywords() { private void addKeywords() {
if (!propsPart.getKeywordsProperty().hasValue()) setElementTextContent(KEYWORD_KEYWORDS, namespaceCoreProperties, propsPart.getKeywordsProperty());
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_KEYWORDS, namespaceCoreProperties));
if (elem == null) {
// missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_KEYWORDS, namespaceCoreProperties));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getKeywordsProperty().getValue());
} }
/** /**
* Add language property element if needed. * Add language property element if needed.
*/ */
private void addLanguage() { private void addLanguage() {
if (!propsPart.getLanguageProperty().hasValue()) setElementTextContent(KEYWORD_LANGUAGE, namespaceDC, propsPart.getLanguageProperty());
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_LANGUAGE, namespaceDC));
if (elem == null) {
// missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_LANGUAGE, namespaceDC));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getLanguageProperty().getValue());
} }
/** /**
* Add 'last modified by' property if needed. * Add 'last modified by' property if needed.
*/ */
private void addLastModifiedBy() { private void addLastModifiedBy() {
if (!propsPart.getLastModifiedByProperty().hasValue()) setElementTextContent(KEYWORD_LAST_MODIFIED_BY, namespaceCoreProperties, propsPart.getLastModifiedByProperty());
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_LAST_MODIFIED_BY, namespaceCoreProperties));
if (elem == null) {
// missing, we add it
elem = xmlDoc.getRootElement()
.addElement(
new QName(KEYWORD_LAST_MODIFIED_BY,
namespaceCoreProperties));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getLastModifiedByProperty().getValue());
} }
/** /**
@ -323,111 +237,39 @@ public class PackagePropertiesMarshaller implements PartMarshaller {
* *
*/ */
private void addLastPrinted() { private void addLastPrinted() {
if (!propsPart.getLastPrintedProperty().hasValue()) setElementTextContent(KEYWORD_LAST_PRINTED, namespaceCoreProperties, propsPart.getLastPrintedProperty(), propsPart.getLastPrintedPropertyString());
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_LAST_PRINTED, namespaceCoreProperties));
if (elem == null) {
// missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_LAST_PRINTED, namespaceCoreProperties));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getLastPrintedPropertyString());
} }
/** /**
* Add modified property element if needed. * Add modified property element if needed.
*/ */
private void addModified() { private void addModified() {
if (!propsPart.getModifiedProperty().hasValue()) setElementTextContent(KEYWORD_MODIFIED, namespaceDcTerms, propsPart.getModifiedProperty(),
return; propsPart.getModifiedPropertyString(), "dcterms:W3CDTF");
}
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_MODIFIED, namespaceDcTerms));
if (elem == null) {
// missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_MODIFIED, namespaceDcTerms));
} else {
elem.clearContent();// clear the old value
}
elem.addAttribute(new QName("type", namespaceXSI), "dcterms:W3CDTF");
elem.addText(propsPart.getModifiedPropertyString());
}
/** /**
* Add revision property if needed. * Add revision property if needed.
*/ */
private void addRevision() { private void addRevision() {
if (!propsPart.getRevisionProperty().hasValue()) setElementTextContent(KEYWORD_REVISION, namespaceCoreProperties, propsPart.getRevisionProperty());
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_REVISION, namespaceCoreProperties));
if (elem == null) {
// missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_REVISION, namespaceCoreProperties));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getRevisionProperty().getValue());
} }
/** /**
* Add subject property if needed. * Add subject property if needed.
*/ */
private void addSubject() { private void addSubject() {
if (!propsPart.getSubjectProperty().hasValue()) setElementTextContent(KEYWORD_SUBJECT, namespaceDC, propsPart.getSubjectProperty());
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_SUBJECT, namespaceDC));
if (elem == null) {
// missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_SUBJECT, namespaceDC));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getSubjectProperty().getValue());
} }
/** /**
* Add title property if needed. * Add title property if needed.
*/ */
private void addTitle() { private void addTitle() {
if (!propsPart.getTitleProperty().hasValue()) setElementTextContent(KEYWORD_TITLE, namespaceDC, propsPart.getTitleProperty());
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_TITLE, namespaceDC));
if (elem == null) {
// missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_TITLE, namespaceDC));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getTitleProperty().getValue());
} }
private void addVersion() { private void addVersion() {
if (!propsPart.getVersionProperty().hasValue()) setElementTextContent(KEYWORD_VERSION, namespaceCoreProperties, propsPart.getVersionProperty());
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_VERSION, namespaceCoreProperties));
if (elem == null) {
// missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_VERSION, namespaceCoreProperties));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getVersionProperty().getValue());
} }
} }

View File

@ -24,11 +24,6 @@ import java.net.URI;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream; import java.util.zip.ZipOutputStream;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Namespace;
import org.dom4j.QName;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.PackageNamespaces; import org.apache.poi.openxml4j.opc.PackageNamespaces;
import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackagePart;
@ -40,8 +35,11 @@ import org.apache.poi.openxml4j.opc.StreamHelper;
import org.apache.poi.openxml4j.opc.TargetMode; import org.apache.poi.openxml4j.opc.TargetMode;
import org.apache.poi.openxml4j.opc.internal.PartMarshaller; import org.apache.poi.openxml4j.opc.internal.PartMarshaller;
import org.apache.poi.openxml4j.opc.internal.ZipHelper; import org.apache.poi.openxml4j.opc.internal.ZipHelper;
import org.apache.poi.util.DocumentHelper;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/** /**
* Zip part marshaller. This marshaller is use to save any part in a zip stream. * Zip part marshaller. This marshaller is use to save any part in a zip stream.
@ -122,9 +120,8 @@ public final class ZipPartMarshaller implements PartMarshaller {
Document xmlOutDoc = DocumentHelper.createDocument(); Document xmlOutDoc = DocumentHelper.createDocument();
// make something like <Relationships // make something like <Relationships
// xmlns="http://schemas.openxmlformats.org/package/2006/relationships"> // xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
Namespace dfNs = Namespace.get("", PackageNamespaces.RELATIONSHIPS); Element root = xmlOutDoc.createElementNS(PackageNamespaces.RELATIONSHIPS, PackageRelationship.RELATIONSHIPS_TAG_NAME);
Element root = xmlOutDoc.addElement(new QName( xmlOutDoc.appendChild(root);
PackageRelationship.RELATIONSHIPS_TAG_NAME, dfNs));
// <Relationship // <Relationship
// TargetMode="External" // TargetMode="External"
@ -137,16 +134,14 @@ public final class ZipPartMarshaller implements PartMarshaller {
for (PackageRelationship rel : rels) { for (PackageRelationship rel : rels) {
// the relationship element // the relationship element
Element relElem = root Element relElem = xmlOutDoc.createElement(PackageRelationship.RELATIONSHIP_TAG_NAME);
.addElement(PackageRelationship.RELATIONSHIP_TAG_NAME); root.appendChild(relElem);
// the relationship ID // the relationship ID
relElem.addAttribute(PackageRelationship.ID_ATTRIBUTE_NAME, rel relElem.setAttribute(PackageRelationship.ID_ATTRIBUTE_NAME, rel.getId());
.getId());
// the relationship Type // the relationship Type
relElem.addAttribute(PackageRelationship.TYPE_ATTRIBUTE_NAME, rel relElem.setAttribute(PackageRelationship.TYPE_ATTRIBUTE_NAME, rel.getRelationshipType());
.getRelationshipType());
// the relationship Target // the relationship Target
String targetValue; String targetValue;
@ -157,16 +152,13 @@ public final class ZipPartMarshaller implements PartMarshaller {
targetValue = uri.toString(); targetValue = uri.toString();
// add TargetMode attribute (as it is external link external) // add TargetMode attribute (as it is external link external)
relElem.addAttribute( relElem.setAttribute(PackageRelationship.TARGET_MODE_ATTRIBUTE_NAME, "External");
PackageRelationship.TARGET_MODE_ATTRIBUTE_NAME,
"External");
} else { } else {
URI targetURI = rel.getTargetURI(); URI targetURI = rel.getTargetURI();
targetValue = PackagingURIHelper.relativizeURI( targetValue = PackagingURIHelper.relativizeURI(
sourcePartURI, targetURI, true).toString(); sourcePartURI, targetURI, true).toString();
} }
relElem.addAttribute(PackageRelationship.TARGET_ATTRIBUTE_NAME, relElem.setAttribute(PackageRelationship.TARGET_ATTRIBUTE_NAME, targetValue);
targetValue);
} }
xmlOutDoc.normalize(); xmlOutDoc.normalize();

View File

@ -19,10 +19,10 @@ package org.apache.poi.openxml4j.opc.internal.unmarshallers;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import javax.xml.XMLConstants;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.PackageNamespaces; import org.apache.poi.openxml4j.opc.PackageNamespaces;
import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackagePart;
@ -32,12 +32,12 @@ import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart;
import org.apache.poi.openxml4j.opc.internal.PartUnmarshaller; import org.apache.poi.openxml4j.opc.internal.PartUnmarshaller;
import org.apache.poi.openxml4j.opc.internal.ZipHelper; import org.apache.poi.openxml4j.opc.internal.ZipHelper;
import org.apache.poi.util.SAXHelper; import org.apache.poi.util.SAXHelper;
import org.dom4j.Attribute; import org.w3c.dom.Attr;
import org.dom4j.Document; import org.w3c.dom.Document;
import org.dom4j.DocumentException; import org.w3c.dom.Element;
import org.dom4j.Element; import org.w3c.dom.NamedNodeMap;
import org.dom4j.Namespace; import org.w3c.dom.NodeList;
import org.dom4j.QName; import org.xml.sax.SAXException;
/** /**
* Package properties unmarshaller. * Package properties unmarshaller.
@ -46,21 +46,6 @@ import org.dom4j.QName;
*/ */
public final class PackagePropertiesUnmarshaller implements PartUnmarshaller { public final class PackagePropertiesUnmarshaller implements PartUnmarshaller {
private final static Namespace namespaceDC = new Namespace("dc",
PackageProperties.NAMESPACE_DC);
private final static Namespace namespaceCP = new Namespace("cp",
PackageNamespaces.CORE_PROPERTIES);
private final static Namespace namespaceDcTerms = new Namespace("dcterms",
PackageProperties.NAMESPACE_DCTERMS);
private final static Namespace namespaceXML = new Namespace("xml",
"http://www.w3.org/XML/1998/namespace");
private final static Namespace namespaceXSI = new Namespace("xsi",
"http://www.w3.org/2001/XMLSchema-instance");
protected static final String KEYWORD_CATEGORY = "category"; protected static final String KEYWORD_CATEGORY = "category";
protected static final String KEYWORD_CONTENT_STATUS = "contentStatus"; protected static final String KEYWORD_CONTENT_STATUS = "contentStatus";
@ -125,15 +110,15 @@ public final class PackagePropertiesUnmarshaller implements PartUnmarshaller {
/* Check OPC compliance */ /* Check OPC compliance */
// Rule M4.2, M4.3, M4.4 and M4.5/ // Rule M4.2, M4.3, M4.4 and M4.5/
checkElementForOPCCompliance(xmlDoc.getRootElement()); checkElementForOPCCompliance(xmlDoc.getDocumentElement());
/* End OPC compliance */ /* End OPC compliance */
} catch (DocumentException e) { } catch (SAXException e) {
throw new IOException(e.getMessage()); throw new IOException(e.getMessage());
} }
coreProps.setCategoryProperty(loadCategory(xmlDoc)); coreProps.setCategoryProperty(loadCategory(xmlDoc));
coreProps.setContentStatusProperty(loadContentStatus(xmlDoc)); coreProps.setContentStatusProperty(loadContentStatus(xmlDoc));
coreProps.setContentTypeProperty(loadContentType(xmlDoc)); coreProps.setContentTypeProperty(loadContentType(xmlDoc));
coreProps.setCreatedProperty(loadCreated(xmlDoc)); coreProps.setCreatedProperty(loadCreated(xmlDoc));
@ -153,148 +138,76 @@ public final class PackagePropertiesUnmarshaller implements PartUnmarshaller {
return coreProps; return coreProps;
} }
private String readElement(Document xmlDoc, String localName, String namespaceURI) {
Element el = (Element)xmlDoc.getDocumentElement().getElementsByTagNameNS(namespaceURI, localName).item(0);
if (el == null) {
return null;
}
return el.getTextContent();
}
private String loadCategory(Document xmlDoc) { private String loadCategory(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element( return readElement(xmlDoc, KEYWORD_CATEGORY, PackageNamespaces.CORE_PROPERTIES);
new QName(KEYWORD_CATEGORY, namespaceCP));
if (el == null) {
return null;
}
return el.getStringValue();
} }
private String loadContentStatus(Document xmlDoc) { private String loadContentStatus(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element( return readElement(xmlDoc, KEYWORD_CONTENT_STATUS, PackageNamespaces.CORE_PROPERTIES);
new QName(KEYWORD_CONTENT_STATUS, namespaceCP));
if (el == null) {
return null;
}
return el.getStringValue();
} }
private String loadContentType(Document xmlDoc) { private String loadContentType(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element( return readElement(xmlDoc, KEYWORD_CONTENT_TYPE, PackageNamespaces.CORE_PROPERTIES);
new QName(KEYWORD_CONTENT_TYPE, namespaceCP));
if (el == null) {
return null;
}
return el.getStringValue();
} }
private String loadCreated(Document xmlDoc) { private String loadCreated(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element( return readElement(xmlDoc, KEYWORD_CREATED, PackageProperties.NAMESPACE_DCTERMS);
new QName(KEYWORD_CREATED, namespaceDcTerms));
if (el == null) {
return null;
}
return el.getStringValue();
} }
private String loadCreator(Document xmlDoc) { private String loadCreator(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element( return readElement(xmlDoc, KEYWORD_CREATOR, PackageProperties.NAMESPACE_DC);
new QName(KEYWORD_CREATOR, namespaceDC));
if (el == null) {
return null;
}
return el.getStringValue();
} }
private String loadDescription(Document xmlDoc) { private String loadDescription(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element( return readElement(xmlDoc, KEYWORD_DESCRIPTION, PackageProperties.NAMESPACE_DC);
new QName(KEYWORD_DESCRIPTION, namespaceDC));
if (el == null) {
return null;
}
return el.getStringValue();
} }
private String loadIdentifier(Document xmlDoc) { private String loadIdentifier(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element( return readElement(xmlDoc, KEYWORD_IDENTIFIER, PackageProperties.NAMESPACE_DC);
new QName(KEYWORD_IDENTIFIER, namespaceDC));
if (el == null) {
return null;
}
return el.getStringValue();
} }
private String loadKeywords(Document xmlDoc) { private String loadKeywords(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element( return readElement(xmlDoc, KEYWORD_KEYWORDS, PackageNamespaces.CORE_PROPERTIES);
new QName(KEYWORD_KEYWORDS, namespaceCP));
if (el == null) {
return null;
}
return el.getStringValue();
} }
private String loadLanguage(Document xmlDoc) { private String loadLanguage(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element( return readElement(xmlDoc, KEYWORD_LANGUAGE, PackageProperties.NAMESPACE_DC);
new QName(KEYWORD_LANGUAGE, namespaceDC));
if (el == null) {
return null;
}
return el.getStringValue();
} }
private String loadLastModifiedBy(Document xmlDoc) { private String loadLastModifiedBy(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element( return readElement(xmlDoc, KEYWORD_LAST_MODIFIED_BY, PackageNamespaces.CORE_PROPERTIES);
new QName(KEYWORD_LAST_MODIFIED_BY, namespaceCP));
if (el == null) {
return null;
}
return el.getStringValue();
} }
private String loadLastPrinted(Document xmlDoc) { private String loadLastPrinted(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element( return readElement(xmlDoc, KEYWORD_LAST_PRINTED, PackageNamespaces.CORE_PROPERTIES);
new QName(KEYWORD_LAST_PRINTED, namespaceCP));
if (el == null) {
return null;
}
return el.getStringValue();
} }
private String loadModified(Document xmlDoc) { private String loadModified(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element( return readElement(xmlDoc, KEYWORD_MODIFIED, PackageProperties.NAMESPACE_DCTERMS);
new QName(KEYWORD_MODIFIED, namespaceDcTerms));
if (el == null) {
return null;
}
return el.getStringValue();
} }
private String loadRevision(Document xmlDoc) { private String loadRevision(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element( return readElement(xmlDoc, KEYWORD_REVISION, PackageNamespaces.CORE_PROPERTIES);
new QName(KEYWORD_REVISION, namespaceCP));
if (el == null) {
return null;
}
return el.getStringValue();
} }
private String loadSubject(Document xmlDoc) { private String loadSubject(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element( return readElement(xmlDoc, KEYWORD_SUBJECT, PackageProperties.NAMESPACE_DC);
new QName(KEYWORD_SUBJECT, namespaceDC));
if (el == null) {
return null;
}
return el.getStringValue();
} }
private String loadTitle(Document xmlDoc) { private String loadTitle(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element( return readElement(xmlDoc, KEYWORD_TITLE, PackageProperties.NAMESPACE_DC);
new QName(KEYWORD_TITLE, namespaceDC));
if (el == null) {
return null;
}
return el.getStringValue();
} }
private String loadVersion(Document xmlDoc) { private String loadVersion(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element( return readElement(xmlDoc, KEYWORD_VERSION, PackageNamespaces.CORE_PROPERTIES);
new QName(KEYWORD_VERSION, namespaceCP));
if (el == null) {
return null;
}
return el.getStringValue();
} }
/* OPC Compliance methods */ /* OPC Compliance methods */
@ -325,60 +238,56 @@ public final class PackagePropertiesUnmarshaller implements PartUnmarshaller {
public void checkElementForOPCCompliance(Element el) public void checkElementForOPCCompliance(Element el)
throws InvalidFormatException { throws InvalidFormatException {
// Check the current element // Check the current element
@SuppressWarnings("unchecked") NamedNodeMap namedNodeMap = el.getAttributes();
List<Namespace> declaredNamespaces = el.declaredNamespaces(); int namedNodeCount = namedNodeMap.getLength();
Iterator<Namespace> itNS = declaredNamespaces.iterator(); for (int i = 0; i < namedNodeCount; i++) {
while (itNS.hasNext()) { Attr attr = (Attr)namedNodeMap.item(0);
Namespace ns = itNS.next();
// Rule M4.2 if (attr.getNamespaceURI().equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) {
if (ns.getURI().equals(PackageNamespaces.MARKUP_COMPATIBILITY)) // Rule M4.2
throw new InvalidFormatException( if (attr.getValue().equals(PackageNamespaces.MARKUP_COMPATIBILITY))
"OPC Compliance error [M4.2]: A format consumer shall consider the use of the Markup Compatibility namespace to be an error."); throw new InvalidFormatException(
} "OPC Compliance error [M4.2]: A format consumer shall consider the use of the Markup Compatibility namespace to be an error.");
}
}
// Rule M4.3 // Rule M4.3
if (el.getNamespace().getURI().equals( String elName = el.getLocalName();
PackageProperties.NAMESPACE_DCTERMS) if (el.getNamespaceURI().equals(PackageProperties.NAMESPACE_DCTERMS))
&& !(el.getName().equals(KEYWORD_CREATED) || el.getName() if (!(elName.equals(KEYWORD_CREATED) || elName.equals(KEYWORD_MODIFIED)))
.equals(KEYWORD_MODIFIED))) throw new InvalidFormatException(
throw new InvalidFormatException( "OPC Compliance error [M4.3]: Producers shall not create a document element that contains refinements to the Dublin Core elements, except for the two specified in the schema: <dcterms:created> and <dcterms:modified> Consumers shall consider a document element that violates this constraint to be an error.");
"OPC Compliance error [M4.3]: Producers shall not create a document element that contains refinements to the Dublin Core elements, except for the two specified in the schema: <dcterms:created> and <dcterms:modified> Consumers shall consider a document element that violates this constraint to be an error.");
// Rule M4.4 // Rule M4.4
if (el.attribute(new QName("lang", namespaceXML)) != null) if (el.getAttributeNodeNS(XMLConstants.XML_NS_URI, "lang") != null)
throw new InvalidFormatException( throw new InvalidFormatException(
"OPC Compliance error [M4.4]: Producers shall not create a document element that contains the xml:lang attribute. Consumers shall consider a document element that violates this constraint to be an error."); "OPC Compliance error [M4.4]: Producers shall not create a document element that contains the xml:lang attribute. Consumers shall consider a document element that violates this constraint to be an error.");
// Rule M4.5 // Rule M4.5
if (el.getNamespace().getURI().equals( if (el.getNamespaceURI().equals(PackageProperties.NAMESPACE_DCTERMS)) {
PackageProperties.NAMESPACE_DCTERMS)) {
// DCTerms namespace only use with 'created' and 'modified' elements // DCTerms namespace only use with 'created' and 'modified' elements
String elName = el.getName(); if (!(elName.equals(KEYWORD_CREATED) || elName.equals(KEYWORD_MODIFIED)))
if (!(elName.equals(KEYWORD_CREATED) || elName
.equals(KEYWORD_MODIFIED)))
throw new InvalidFormatException("Namespace error : " + elName throw new InvalidFormatException("Namespace error : " + elName
+ " shouldn't have the following naemspace -> " + " shouldn't have the following naemspace -> "
+ PackageProperties.NAMESPACE_DCTERMS); + PackageProperties.NAMESPACE_DCTERMS);
// Check for the 'xsi:type' attribute // Check for the 'xsi:type' attribute
Attribute typeAtt = el.attribute(new QName("type", namespaceXSI)); Attr typeAtt = el.getAttributeNodeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type");
if (typeAtt == null) if (typeAtt == null)
throw new InvalidFormatException("The element '" + elName throw new InvalidFormatException("The element '" + elName
+ "' must have the '" + namespaceXSI.getPrefix() + "' must have the 'xsi:type' attribute present !");
+ ":type' attribute present !");
// Check for the attribute value => 'dcterms:W3CDTF' // Check for the attribute value => 'dcterms:W3CDTF'
if (!typeAtt.getValue().equals("dcterms:W3CDTF")) if (!typeAtt.getValue().equals("dcterms:W3CDTF"))
throw new InvalidFormatException("The element '" + elName throw new InvalidFormatException("The element '" + elName
+ "' must have the '" + namespaceXSI.getPrefix() + "' must have the 'xsi:type' attribute with the value 'dcterms:W3CDTF' !");
+ ":type' attribute with the value 'dcterms:W3CDTF' !");
} }
// Check its children // Check its children
@SuppressWarnings("unchecked") NodeList childElements = el.getElementsByTagName("*");
Iterator<Element> itChildren = el.elementIterator(); int childElementCount = childElements.getLength();
while (itChildren.hasNext()) for (int i = 0; i < childElementCount; i++)
checkElementForOPCCompliance(itChildren.next()); checkElementForOPCCompliance((Element)childElements.item(i));
} }
} }

View File

@ -176,6 +176,7 @@ public interface HorribleProxies {
public interface OCSPRespIf extends ProxyIf { public interface OCSPRespIf extends ProxyIf {
String delegateClass = "org.bouncycastle.cert.ocsp.OCSPResp"; String delegateClass = "org.bouncycastle.cert.ocsp.OCSPResp";
BasicOCSPRespIf getResponseObject(); BasicOCSPRespIf getResponseObject();
byte[] getEncoded() throws IOException;
} }
public interface PKIFailureInfoIf extends ProxyIf { public interface PKIFailureInfoIf extends ProxyIf {

View File

@ -171,7 +171,7 @@ public class SignatureInfo {
KeyInfoKeySelector keySelector = new KeyInfoKeySelector(); KeyInfoKeySelector keySelector = new KeyInfoKeySelector();
try { try {
Document doc = SAXHelper.readSAXDocumentW3C(signaturePart.getInputStream()); Document doc = SAXHelper.readSAXDocument(signaturePart.getInputStream());
// dummy call to createSignatureService to tweak document afterwards // dummy call to createSignatureService to tweak document afterwards
createSignatureService(HashAlgorithm.sha1, pkg).registerIds(doc); createSignatureService(HashAlgorithm.sha1, pkg).registerIds(doc);

View File

@ -0,0 +1,84 @@
package org.apache.poi.poifs.crypt.dsig.facets;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.Transform;
import javax.xml.crypto.dsig.XMLObject;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import org.apache.poi.poifs.crypt.HashAlgorithm;
import org.w3.x2000.x09.xmldsig.SignatureType;
/**
* Signature Facet implementation to create enveloped signatures.
*
* @author Frank Cornelis
*
*/
public class EnvelopedSignatureFacet implements SignatureFacet {
private final HashAlgorithm hashAlgo;
/**
* Default constructor. Digest algorithm will be SHA-1.
*/
public EnvelopedSignatureFacet() {
this(HashAlgorithm.sha1);
}
/**
* Main constructor.
*
* @param hashAlgo
* the digest algorithm to be used within the ds:Reference
* element. Possible values: "SHA-1", "SHA-256, or "SHA-512".
*/
public EnvelopedSignatureFacet(HashAlgorithm hashAlgo) {
this.hashAlgo = hashAlgo;
}
@Override
public void postSign(SignatureType signatureElement
, List<X509Certificate> signingCertificateChain) {
// empty
}
@Override
public void preSign(XMLSignatureFactory signatureFactory,
String signatureId,
List<X509Certificate> signingCertificateChain,
List<Reference> references, List<XMLObject> objects)
throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
DigestMethod digestMethod = signatureFactory.newDigestMethod(
this.hashAlgo.xmlSignUri, null);
List<Transform> transforms = new LinkedList<Transform>();
Transform envelopedTransform = signatureFactory
.newTransform(CanonicalizationMethod.ENVELOPED,
(TransformParameterSpec) null);
transforms.add(envelopedTransform);
Transform exclusiveTransform = signatureFactory
.newTransform(CanonicalizationMethod.EXCLUSIVE,
(TransformParameterSpec) null);
transforms.add(exclusiveTransform);
Reference reference = signatureFactory.newReference("", digestMethod,
transforms, null, null);
references.add(reference);
}
@Override
public Map<String,String> getNamespacePrefixMapping() {
return null;
}
}

View File

@ -174,8 +174,10 @@ public class XmlSignatureService implements SignatureService {
* *
* @param signatureFacet * @param signatureFacet
*/ */
protected void addSignatureFacet(SignatureFacet signatureFacet) { public void addSignatureFacet(SignatureFacet... signatureFacets) {
this.signatureFacets.add(signatureFacet); for (SignatureFacet sf : signatureFacets) {
this.signatureFacets.add(sf);
}
} }
/** /**

View File

@ -0,0 +1,60 @@
/* ====================================================================
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.
==================================================================== */
package org.apache.poi.util;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.events.Namespace;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class DocumentHelper {
private static final DocumentBuilder newDocumentBuilder;
static {
try {
newDocumentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
} catch (ParserConfigurationException e) {
throw new IllegalStateException("cannot create a DocumentBuilder", e);
}
}
public static synchronized Document createDocument() {
return newDocumentBuilder.newDocument();
}
/**
* Adds a namespace declaration attribute to the given element.
*/
public static void addNamespaceDeclaration(Element element, String namespacePrefix, String namespaceURI) {
element.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI,
XMLConstants.XMLNS_ATTRIBUTE + ':' + namespacePrefix,
namespaceURI);
}
/**
* Adds a namespace declaration attribute to the given element.
*/
public static void addNamespaceDeclaration(Element element, Namespace namespace) {
addNamespaceDeclaration(element, namespace.getPrefix(), namespace.getNamespaceURI());
}
}

View File

@ -27,9 +27,7 @@ import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import org.dom4j.Document; import org.w3c.dom.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
import org.xml.sax.EntityResolver; import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource; import org.xml.sax.InputSource;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
@ -40,59 +38,7 @@ import org.xml.sax.SAXException;
*/ */
public final class SAXHelper { public final class SAXHelper {
private static POILogger logger = POILogFactory.getLogger(SAXHelper.class); private static POILogger logger = POILogFactory.getLogger(SAXHelper.class);
/**
* Creates a new SAX Reader, with sensible defaults
*/
public static SAXReader getSAXReader() {
SAXReader xmlReader = new SAXReader();
xmlReader.setValidation(false);
xmlReader.setEntityResolver(new EntityResolver() {
public InputSource resolveEntity(String publicId, String systemId)
throws SAXException, IOException {
return new InputSource(new StringReader(""));
}
});
trySetSAXFeature(xmlReader, XMLConstants.FEATURE_SECURE_PROCESSING, true);
trySetXercesSecurityManager(xmlReader);
return xmlReader;
}
private static void trySetSAXFeature(SAXReader xmlReader, String feature, boolean enabled) {
try {
xmlReader.setFeature(feature, enabled);
} catch (Exception e) {
logger.log(POILogger.INFO, "SAX Feature unsupported", feature, e);
}
}
private static void trySetXercesSecurityManager(SAXReader xmlReader) {
// Try built-in JVM one first, standalone if not
for (String securityManagerClassName : new String[] {
"com.sun.org.apache.xerces.internal.util.SecurityManager",
"org.apache.xerces.util.SecurityManager"
}) {
try {
Object mgr = Class.forName(securityManagerClassName).newInstance();
Method setLimit = mgr.getClass().getMethod("setEntityExpansionLimit", Integer.TYPE);
setLimit.invoke(mgr, 4096);
xmlReader.setProperty("http://apache.org/xml/properties/security-manager", mgr);
// Stop once one can be setup without error
return;
} catch (Exception e) {
logger.log(POILogger.INFO, "SAX Security Manager could not be setup", e);
}
}
}
/**
* Parses the given stream via the default (sensible)
* SAX Reader
* @param inp Stream to read the XML data from
* @return the SAX processed Document
*/
public static Document readSAXDocument(InputStream inp) throws DocumentException {
return getSAXReader().read(inp);
}
private static final EntityResolver IGNORING_ENTITY_RESOLVER = new EntityResolver() { private static final EntityResolver IGNORING_ENTITY_RESOLVER = new EntityResolver() {
@Override @Override
public InputSource resolveEntity(String publicId, String systemId) public InputSource resolveEntity(String publicId, String systemId)
@ -101,6 +47,27 @@ public final class SAXHelper {
} }
}; };
private static final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
static {
documentBuilderFactory.setNamespaceAware(true);
documentBuilderFactory.setValidating(false);
trySetSAXFeature(documentBuilderFactory, XMLConstants.FEATURE_SECURE_PROCESSING, true);
trySetXercesSecurityManager(documentBuilderFactory);
}
/**
* Creates a new document builder, with sensible defaults
*/
public static synchronized DocumentBuilder getDocumentBuilder() {
try {
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
documentBuilder.setEntityResolver(IGNORING_ENTITY_RESOLVER);
return documentBuilder;
} catch (ParserConfigurationException e) {
throw new IllegalStateException("cannot create a DocumentBuilder", e);
}
}
private static void trySetSAXFeature(DocumentBuilderFactory documentBuilderFactory, String feature, boolean enabled) { private static void trySetSAXFeature(DocumentBuilderFactory documentBuilderFactory, String feature, boolean enabled) {
try { try {
documentBuilderFactory.setFeature(feature, enabled); documentBuilderFactory.setFeature(feature, enabled);
@ -126,38 +93,14 @@ public final class SAXHelper {
} }
} }
} }
private static final ThreadLocal<DocumentBuilder> documentBuilder = new ThreadLocal<DocumentBuilder>() {
@Override
protected DocumentBuilder initialValue() {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
factory.setValidating(false);
trySetSAXFeature(factory, XMLConstants.FEATURE_SECURE_PROCESSING, true);
trySetXercesSecurityManager(factory);
try {
return factory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
throw new IllegalStateException("cannot create a DocumentBuilder", e);
}
}
@Override
public DocumentBuilder get() {
DocumentBuilder documentBuilder = super.get();
documentBuilder.reset();
documentBuilder.setEntityResolver(IGNORING_ENTITY_RESOLVER);
return documentBuilder;
}
};
/** /**
* Parses the given stream via the default (sensible) * Parses the given stream via the default (sensible)
* SAX Reader * SAX Reader
* @param inp Stream to read the XML data from * @param inp Stream to read the XML data from
* @return the SAX processed Document * @return the SAX processed Document
*/ */
public static org.w3c.dom.Document readSAXDocumentW3C(InputStream inp) throws IOException, SAXException { public static Document readSAXDocument(InputStream inp) throws IOException, SAXException {
return documentBuilder.get().parse(inp); return getDocumentBuilder().parse(inp);
} }
} }

View File

@ -27,7 +27,6 @@ import java.io.OutputStream;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.net.URI; import java.net.URI;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -40,15 +39,14 @@ import org.apache.poi.openxml4j.exceptions.InvalidOperationException;
import org.apache.poi.openxml4j.opc.internal.ContentTypeManager; import org.apache.poi.openxml4j.opc.internal.ContentTypeManager;
import org.apache.poi.openxml4j.opc.internal.FileHelper; import org.apache.poi.openxml4j.opc.internal.FileHelper;
import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart; import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart;
import org.apache.poi.util.DocumentHelper;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
import org.apache.poi.util.SAXHelper; import org.apache.poi.util.SAXHelper;
import org.apache.poi.util.TempFile; import org.apache.poi.util.TempFile;
import org.dom4j.Document; import org.w3c.dom.Document;
import org.dom4j.DocumentHelper; import org.w3c.dom.Element;
import org.dom4j.Element; import org.w3c.dom.NodeList;
import org.dom4j.Namespace;
import org.dom4j.QName;
public final class TestPackage extends TestCase { public final class TestPackage extends TestCase {
private static final POILogger logger = POILogFactory.getLogger(TestPackage.class); private static final POILogger logger = POILogFactory.getLogger(TestPackage.class);
@ -127,18 +125,17 @@ public final class TestPackage extends TestCase {
"application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"); "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml");
Document doc = DocumentHelper.createDocument(); Document doc = DocumentHelper.createDocument();
Namespace nsWordprocessinML = new Namespace("w", Element elDocument = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:document");
"http://schemas.openxmlformats.org/wordprocessingml/2006/main"); doc.appendChild(elDocument);
Element elDocument = doc.addElement(new QName("document", Element elBody = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:body");
nsWordprocessinML)); elDocument.appendChild(elBody);
Element elBody = elDocument.addElement(new QName("body", Element elParagraph = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:p");
nsWordprocessinML)); elBody.appendChild(elParagraph);
Element elParagraph = elBody.addElement(new QName("p", Element elRun = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:r");
nsWordprocessinML)); elParagraph.appendChild(elRun);
Element elRun = elParagraph Element elText = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:t");
.addElement(new QName("r", nsWordprocessinML)); elRun.appendChild(elText);
Element elText = elRun.addElement(new QName("t", nsWordprocessinML)); elText.setTextContent("Hello Open XML !");
elText.setText("Hello Open XML !");
StreamHelper.saveXmlInStream(doc, corePart.getOutputStream()); StreamHelper.saveXmlInStream(doc, corePart.getOutputStream());
pkg.close(); pkg.close();
@ -223,15 +220,13 @@ public final class TestPackage extends TestCase {
Document xmlRelationshipsDoc = SAXHelper.readSAXDocument(relPart.getInputStream()); Document xmlRelationshipsDoc = SAXHelper.readSAXDocument(relPart.getInputStream());
Element root = xmlRelationshipsDoc.getRootElement(); Element root = xmlRelationshipsDoc.getDocumentElement();
for (Iterator i = root NodeList nodeList = root.getElementsByTagName(PackageRelationship.RELATIONSHIP_TAG_NAME);
.elementIterator(PackageRelationship.RELATIONSHIP_TAG_NAME); i int nodeCount = nodeList.getLength();
.hasNext();) { for (int i = 0; i < nodeCount; i++) {
Element element = (Element) i.next(); Element element = (Element) nodeList.item(i);
String value = element.attribute( String value = element.getAttribute(PackageRelationship.TARGET_ATTRIBUTE_NAME);
PackageRelationship.TARGET_ATTRIBUTE_NAME) assertTrue("Root target must not start with a leading slash ('/'): " + value, value.charAt(0) != '/');
.getValue();
assertTrue("Root target must not start with a leadng slash ('/'): " + value, value.charAt(0) != '/');
} }
} }
@ -268,18 +263,17 @@ public final class TestPackage extends TestCase {
// Create a content // Create a content
Document doc = DocumentHelper.createDocument(); Document doc = DocumentHelper.createDocument();
Namespace nsWordprocessinML = new Namespace("w", Element elDocument = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:document");
"http://schemas.openxmlformats.org/wordprocessingml/2006/main"); doc.appendChild(elDocument);
Element elDocument = doc.addElement(new QName("document", Element elBody = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:body");
nsWordprocessinML)); elDocument.appendChild(elBody);
Element elBody = elDocument.addElement(new QName("body", Element elParagraph = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:p");
nsWordprocessinML)); elBody.appendChild(elParagraph);
Element elParagraph = elBody.addElement(new QName("p", Element elRun = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:r");
nsWordprocessinML)); elParagraph.appendChild(elRun);
Element elRun = elParagraph Element elText = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:t");
.addElement(new QName("r", nsWordprocessinML)); elRun.appendChild(elText);
Element elText = elRun.addElement(new QName("t", nsWordprocessinML)); elText.setTextContent("Hello Open XML !");
elText.setText("Hello Open XML !");
StreamHelper.saveXmlInStream(doc, corePart.getOutputStream()); StreamHelper.saveXmlInStream(doc, corePart.getOutputStream());

View File

@ -26,6 +26,10 @@ package org.apache.poi.poifs.crypt;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
@ -40,7 +44,9 @@ import java.security.KeyPair;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.PrivateKey; import java.security.PrivateKey;
import java.security.cert.Certificate; import java.security.cert.Certificate;
import java.security.cert.X509CRL;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
@ -53,8 +59,17 @@ import org.apache.poi.POIDataSamples;
import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess; import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.KeyUsageIf; import org.apache.poi.poifs.crypt.dsig.HorribleProxies.KeyUsageIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.OCSPRespIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxy; import org.apache.poi.poifs.crypt.dsig.HorribleProxy;
import org.apache.poi.poifs.crypt.dsig.SignatureInfo; import org.apache.poi.poifs.crypt.dsig.SignatureInfo;
import org.apache.poi.poifs.crypt.dsig.facets.EnvelopedSignatureFacet;
import org.apache.poi.poifs.crypt.dsig.facets.KeyInfoSignatureFacet;
import org.apache.poi.poifs.crypt.dsig.facets.SignaturePolicyService;
import org.apache.poi.poifs.crypt.dsig.facets.XAdESSignatureFacet;
import org.apache.poi.poifs.crypt.dsig.facets.XAdESXLSignatureFacet;
import org.apache.poi.poifs.crypt.dsig.services.RevocationData;
import org.apache.poi.poifs.crypt.dsig.services.RevocationDataService;
import org.apache.poi.poifs.crypt.dsig.services.TimeStampService;
import org.apache.poi.poifs.crypt.dsig.services.XmlSignatureService; import org.apache.poi.poifs.crypt.dsig.services.XmlSignatureService;
import org.apache.poi.poifs.crypt.dsig.spi.DigestInfo; import org.apache.poi.poifs.crypt.dsig.spi.DigestInfo;
import org.apache.poi.util.IOUtils; import org.apache.poi.util.IOUtils;
@ -62,6 +77,8 @@ import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
public class TestSignatureInfo { public class TestSignatureInfo {
private static final POILogger LOG = POILogFactory.getLogger(TestSignatureInfo.class); private static final POILogger LOG = POILogFactory.getLogger(TestSignatureInfo.class);
@ -171,6 +188,64 @@ public class TestSignatureInfo {
pkg.close(); pkg.close();
} }
@Test
public void testSignEnvelopingDocument() throws Exception {
String testFile = "hello-world-unsigned.xlsx";
OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE);
// setup
EnvelopedSignatureFacet envelopedSignatureFacet = new EnvelopedSignatureFacet();
KeyInfoSignatureFacet keyInfoSignatureFacet = new KeyInfoSignatureFacet(true, false, false);
SignaturePolicyService signaturePolicyService = null;
XAdESSignatureFacet xadesSignatureFacet = new XAdESSignatureFacet(null, null, signaturePolicyService);
TimeStampService mockTimeStampService = mock(TimeStampService.class);
RevocationDataService mockRevocationDataService = mock(RevocationDataService.class);
XAdESXLSignatureFacet xadesXLSignatureFacet = new XAdESXLSignatureFacet(
mockTimeStampService, mockRevocationDataService);
XmlSignatureService testedInstance = new XmlSignatureService(HashAlgorithm.sha1, pkg);
testedInstance.addSignatureFacet(envelopedSignatureFacet, keyInfoSignatureFacet,
xadesSignatureFacet, xadesXLSignatureFacet);
initKeyPair("Test", "CN=Test");
List<X509Certificate> certificateChain = new ArrayList<X509Certificate>();
/*
* We need at least 2 certificates for the XAdES-C complete certificate
* refs construction.
*/
certificateChain.add(x509);
certificateChain.add(x509);
RevocationData revocationData = new RevocationData();
final X509CRL crl = PkiTestUtils.generateCrl(x509, keyPair.getPrivate());
revocationData.addCRL(crl);
OCSPRespIf ocspResp = PkiTestUtils.createOcspResp(x509, false,
x509, x509, keyPair.getPrivate(), "SHA1withRSA");
revocationData.addOCSP(ocspResp.getEncoded());
when(mockTimeStampService.timeStamp(any(byte[].class), any(RevocationData.class)))
.thenAnswer(new Answer<byte[]>(){
public byte[] answer(InvocationOnMock invocation) throws Throwable {
Object[] arguments = invocation.getArguments();
RevocationData revocationData = (RevocationData) arguments[1];
revocationData.addCRL(crl);
return "time-stamp-token".getBytes();
}
});
when(mockRevocationDataService.getRevocationData(eq(certificateChain)))
.thenReturn(revocationData);
// operate
DigestInfo digestInfo = testedInstance.preSign(null, certificateChain, null, null, null);
// verify
assertNotNull(digestInfo);
assertEquals("SHA-1", digestInfo.hashAlgo);
assertNotNull(digestInfo.digestValue);
}
private OPCPackage sign(OPCPackage pkgCopy, String alias, String signerDn, int signerCount) throws Exception { private OPCPackage sign(OPCPackage pkgCopy, String alias, String signerDn, int signerCount) throws Exception {
/*** TODO : set cal to now ... only set to fixed date for debugging ... */ /*** TODO : set cal to now ... only set to fixed date for debugging ... */

View File

@ -0,0 +1,47 @@
/* ====================================================================
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.
==================================================================== */
package org.apache.poi.xwpf.extractor;
import java.io.IOException;
import junit.framework.TestCase;
import org.apache.poi.xwpf.XWPFTestDataSamples;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
public class TestExternalEntities extends TestCase {
/**
* Get text out of the simple file
* @throws IOException
*/
public void testFile() throws IOException {
XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("ExternalEntityInText.docx");
XWPFWordExtractor extractor = new XWPFWordExtractor(doc);
String text = extractor.getText();
assertTrue(text.length() > 0);
// Check contents, they should not contain the text from POI web site after colon!
assertEquals("Here should not be the POI web site: \"\"", text.trim());
extractor.close();
}
}

Binary file not shown.