git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@738842 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_5_BETA5
@@ -124,8 +124,6 @@ under the License. | |||
<property name="ooxml.testokfile" location="build/ooxml-testokfile.txt"/> | |||
<!-- The following jars are downloaded by the fetch-ooxml-jars task --> | |||
<property name="ooxml.openxml4j.jar" location="${ooxml.lib}/openxml4j-1.0-beta.jar"/> | |||
<property name="ooxml.openxml4j.url" value="http://mirrors.ibiblio.org/pub/mirrors/maven2/org/apache/poi/openxml4j/1.0-beta/openxml4j-1.0-beta.jar"/> | |||
<property name="ooxml.dom4j.jar" location="${ooxml.lib}/dom4j-1.6.1.jar"/> | |||
<property name="ooxml.dom4j.url" value="${repository}/dom4j/jars/dom4j-1.6.1.jar"/> | |||
<property name="ooxml.xmlbeans.jar" location="${ooxml.lib}/xmlbeans-2.3.0.jar"/> | |||
@@ -144,8 +142,6 @@ under the License. | |||
<property name="maven.ooxml.xsds.version.id" value="1.0"/> | |||
<property name="maven.ooxml.xsds.jar" value="ooxml-schemas-${maven.ooxml.xsds.version.id}.jar"/> | |||
<property name="maven.openxml4j.version.id" value="1.0-beta"/> | |||
<property name="maven.openxml4j.jar" value="openxml4j-${maven.openxml4j.version.id}.jar"/> | |||
<property name="build.site" location="build/tmp/site/build/site"/> | |||
<property name="build.site.src" location="build/tmp/site"/> | |||
@@ -354,7 +350,6 @@ under the License. | |||
<available file="${ooxml.xmlbeans.jar}"/> | |||
<available file="${ooxml.jsr173.jar}"/> | |||
<available file="${ooxml.schemas.jar}"/> | |||
<available file="${ooxml.openxml4j.jar}"/> | |||
</and> | |||
<isset property="disconnected"/> | |||
</or> | |||
@@ -377,10 +372,6 @@ under the License. | |||
<param name="sourcefile" value="${ooxml.schemas.url}"/> | |||
<param name="destfile" value="${ooxml.schemas.jar}"/> | |||
</antcall> | |||
<antcall target="downloadfile"> | |||
<param name="sourcefile" value="${ooxml.openxml4j.url}"/> | |||
<param name="destfile" value="${ooxml.openxml4j.jar}"/> | |||
</antcall> | |||
</target> | |||
<target name="check-ooxml-xsds"> | |||
@@ -524,7 +515,6 @@ under the License. | |||
</target> | |||
<target name="compile-ooxml" depends="init, compile-main, compile-scratchpad"> | |||
<!-- openxml4j requires java 1.5, so so must we, for now --> | |||
<javac target="1.5" source="1.5" | |||
destdir="${ooxml.output.dir}" debug="on" srcdir="${ooxml.src}"> | |||
<classpath refid="ooxml.classpath"/> | |||
@@ -805,6 +795,9 @@ under the License. | |||
<sysproperty key="HSLF.testdata.path" file="${scratchpad.src.test}/org/apache/poi/hslf/data"/> | |||
<sysproperty key="HDGF.testdata.path" file="${scratchpad.src.test}/org/apache/poi/hdgf/data"/> | |||
<sysproperty key="OOXML.testdata.path" file="${ooxml.src.test}/org/apache/poi/ooxml/data"/> | |||
<sysproperty key="openxml4j.compliance.input" file="${ooxml.src.test}/org/apache/poi/openxml4j/opc/compliance/input"/> | |||
<sysproperty key="openxml4j.testdata.input" file="${ooxml.src.test}/org/apache/poi/openxml4j/opc/INPUT"/> | |||
<sysproperty key="openxml4j.testdata.output" file="${ooxml.src.test}/org/apache/poi/openxml4j/opc/OUTPUT"/> | |||
<sysproperty key="java.awt.headless" value="true"/> | |||
<formatter type="plain"/> | |||
<formatter type="xml"/> | |||
@@ -812,6 +805,7 @@ under the License. | |||
<fileset dir="${ooxml.src.test}"> | |||
<include name="**/Test*.java"/> | |||
<exclude name="**/All*Tests.java"/> | |||
<exclude name="**/TestCore.java"/> <!--non-junit class from OpenXML4j--> | |||
</fileset> | |||
</batchtest> | |||
</junit> | |||
@@ -1129,16 +1123,7 @@ FORREST_HOME environment variable!</echo> | |||
</copy> | |||
</target> | |||
<target name="maven-ooxml-dependencies" description="Builds the POM files for OpenXml4J and compiled XmlBeans generated from the Ecma supplied xsds"> | |||
<!-- OpenXml4J --> | |||
<copy file="${ooxml.jar6.dir}" tofile="${mavendist.ooxml.dir}/org.openxml4j/jars/${maven.openxml4j.jar}" /> | |||
<copy file="maven/openxml4j.pom" tofile="${mavendist.ooxml.dir}/org.openxml4j/poms/openxml4j-${maven.openxml4j.version.id}.pom"> | |||
<filterchain> | |||
<replacetokens> | |||
<token key="VERSION" value="${maven.openxml4j.version.id}" /> | |||
</replacetokens> | |||
</filterchain> | |||
</copy> | |||
<target name="maven-ooxml-dependencies" description="Builds the POM files for the compiled XmlBeans generated from the Ecma supplied xsds"> | |||
<!-- ooxml-schemas --> | |||
<copy file="${ooxml.xsds.jar}" tofile="${mavendist.ooxml.dir}/org.apache.poi/jars/${maven.ooxml.xsds.jar}" /> |
@@ -17,6 +17,3 @@ own licensing: | |||
Apache Licence Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0 | |||
* DOM4J - http://www.dom4j.org/ | |||
BSD Licence - http://www.dom4j.org/license.html | |||
* OpenXml4J - http://www.openxml4j.org/ | |||
BSD Licence or Apache Licence Version 2.0 - | |||
http://www.openxml4j.org/Licensing/Default.html |
@@ -1,70 +0,0 @@ | |||
<?xml version="1.0"?> | |||
<!-- | |||
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. | |||
--> | |||
<project xmlns="http://maven.apache.org/POM/4.0.0" | |||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | |||
<modelVersion>4.0.0</modelVersion> | |||
<groupId>org.openxml4j</groupId> | |||
<artifactId>openxml4j</artifactId> | |||
<version>@VERSION@</version> | |||
<packaging>jar</packaging> | |||
<name>OpenXML4J</name> | |||
<url>http://openxml4j.org/</url> | |||
<description>Office Open XML File Format library for Java</description> | |||
<mailingLists> | |||
<mailingList> | |||
<name>OpenXML4J Users List</name> | |||
<archive>http://sourceforge.net/mailarchive/forum.php?forum_name=openxml4j-users</archive> | |||
</mailingList> | |||
<mailingList> | |||
<name>OpenXML4J Developer List</name> | |||
<archive>http://sourceforge.net/mailarchive/forum.php?forum_name=openxml4j-devs</archive> | |||
</mailingList> | |||
</mailingLists> | |||
<licenses> | |||
<license> | |||
<name>The Apache Software License, Version 2.0</name> | |||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url> | |||
<distribution>repo</distribution> | |||
</license> | |||
</licenses> | |||
<organization> | |||
<name>OpenXML4J</name> | |||
<url>http://www.openxml4j.org/</url> | |||
</organization> | |||
<dependencies> | |||
<dependency> | |||
<groupId>dom4j</groupId> | |||
<artifactId>dom4j</artifactId> | |||
<version>1.6.1</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>log4j</groupId> | |||
<artifactId>log4j</artifactId> | |||
<version>1.2.8</version> | |||
</dependency> | |||
</dependencies> | |||
</project> |
@@ -60,26 +60,19 @@ | |||
<dependencies> | |||
<dependency> | |||
<groupId>commons-logging</groupId> | |||
<artifactId>commons-logging</artifactId> | |||
<version>1.1</version> | |||
<scope>runtime</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>log4j</groupId> | |||
<artifactId>log4j</artifactId> | |||
<version>1.2.13</version> | |||
<scope>runtime</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.apache.poi</groupId> | |||
<artifactId>openxml4j</artifactId> | |||
<version>1.0-beta</version> | |||
<groupId>org.apache.poi</groupId> | |||
<artifactId>poi</artifactId> | |||
<version>@VERSION@</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.apache.poi</groupId> | |||
<artifactId>ooxml-schemas</artifactId> | |||
<version>1.0</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>dom4j</groupId> | |||
<artifactId>dom4j</artifactId> | |||
<version>1.6.1</version> | |||
</dependency> | |||
</dependencies> | |||
</project> |
@@ -42,7 +42,8 @@ | |||
<menu-item label="HSMF" href="hsmf/index.html"/> | |||
<menu-item label="HDGF" href="hdgf/index.html"/> | |||
<menu-item label="HPBF" href="hpbf/index.html"/> | |||
<menu-item label="POI-Ruby" href="poi-ruby.html"/> | |||
<menu-item label="OpenXML4J" href="oxml4j/index.html"/> | |||
<menu-item label="POI-Ruby" href="poi-ruby.html"/> | |||
<menu-item label="POI-Utils" href="utils/index.html"/> | |||
<menu-item label="Text Extraction" href="text-extraction.html"/> | |||
<menu-item label="Download" href="ext:download"/> |
@@ -0,0 +1,34 @@ | |||
<?xml version="1.0"?> | |||
<!-- | |||
==================================================================== | |||
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. | |||
==================================================================== | |||
--> | |||
<!DOCTYPE book PUBLIC "-//APACHE//DTD Cocoon Documentation Book V1.0//EN" "../dtd/book-cocoon-v10.dtd"> | |||
<book software="POI Project" | |||
title="OpenXML4J" | |||
copyright="@year@ POI Project"> | |||
<menu label="Apache POI"> | |||
<menu-item label="Top" href="../index.html"/> | |||
</menu> | |||
<menu label="OpenXML4J"> | |||
<menu-item label="Overview" href="index.html"/> | |||
</menu> | |||
</book> |
@@ -0,0 +1,42 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!-- | |||
==================================================================== | |||
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. | |||
==================================================================== | |||
--> | |||
<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.1//EN" "../dtd/document-v11.dtd"> | |||
<document> | |||
<header> | |||
<title>POI-OpenXML4J - Java API To Access Office Open XML documents</title> | |||
<subtitle>Overview</subtitle> | |||
</header> | |||
<body> | |||
<section> | |||
<title>Overview</title> | |||
<p>OpenXML4J is the POI Project's pure Java implementation of the Open Packaging Conventions (OPC) defined in | |||
<link href="http://www.ecma-international.org/publications/standards/Ecma-376.htm">ECMA-376</link>.</p> | |||
<p>Every OpenXML file comprises a collection of byte streams called parts, combined into a container called a package. | |||
POI OpenXML4J provides a physical implementation of the OPC that uses the Zip file format.</p> | |||
</section> | |||
<section> | |||
<title>History</title> | |||
<p>OpenXML4J was originally developed by <link href="http://openxml4j.org/">http://openxml4j.org/</link> and contributed to POI in 2008. | |||
Thanks to the support and guidance of Julien Chable</p> | |||
</section> | |||
</body> | |||
</document> |
@@ -509,7 +509,7 @@ import java.util.Iterator; | |||
import org.apache.poi.xssf.eventusermodel.XSSFReader; | |||
import org.apache.poi.xssf.model.SharedStringsTable; | |||
import org.openxml4j.opc.Package; | |||
import org.apache.poi.openxml4j.opc.Package; | |||
import org.xml.sax.Attributes; | |||
import org.xml.sax.ContentHandler; | |||
import org.xml.sax.InputSource; |
@@ -22,7 +22,7 @@ import java.util.Iterator; | |||
import org.apache.poi.xssf.eventusermodel.XSSFReader; | |||
import org.apache.poi.xssf.model.SharedStringsTable; | |||
import org.apache.poi.xssf.usermodel.XSSFRichTextString; | |||
import org.openxml4j.opc.Package; | |||
import org.apache.poi.openxml4j.opc.Package; | |||
import org.xml.sax.Attributes; | |||
import org.xml.sax.ContentHandler; | |||
import org.xml.sax.InputSource; |
@@ -23,10 +23,10 @@ import org.apache.poi.poifs.common.POIFSConstants; | |||
import org.apache.poi.util.IOUtils; | |||
import org.apache.poi.util.PackageHelper; | |||
import org.apache.xmlbeans.XmlException; | |||
import org.openxml4j.exceptions.InvalidFormatException; | |||
import org.openxml4j.exceptions.OpenXML4JException; | |||
import org.openxml4j.opc.*; | |||
import org.openxml4j.opc.Package; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.*; | |||
import org.apache.poi.openxml4j.opc.Package; | |||
public abstract class POIXMLDocument extends POIXMLDocumentPart{ | |||
@@ -23,15 +23,15 @@ import java.util.List; | |||
import org.apache.xmlbeans.XmlOptions; | |||
import org.apache.poi.util.POILogger; | |||
import org.apache.poi.util.POILogFactory; | |||
import org.openxml4j.exceptions.OpenXML4JException; | |||
import org.openxml4j.opc.*; | |||
import org.openxml4j.opc.Package; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.*; | |||
import org.apache.poi.openxml4j.opc.Package; | |||
/** | |||
* Represents an entry of a OOXML package. | |||
* | |||
* <p> | |||
* Each POIXMLDocumentPart keeps a reference to the underlying a {@link org.openxml4j.opc.PackagePart}. | |||
* Each POIXMLDocumentPart keeps a reference to the underlying a {@link org.apache.poi.openxml4j.opc.PackagePart}. | |||
* </p> | |||
* | |||
* @author Yegor Kozlov |
@@ -16,8 +16,8 @@ | |||
==================================================================== */ | |||
package org.apache.poi; | |||
import org.openxml4j.opc.PackageRelationship; | |||
import org.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.PackageRelationship; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
/** |
@@ -19,10 +19,10 @@ package org.apache.poi; | |||
import java.io.IOException; | |||
import org.apache.xmlbeans.XmlException; | |||
import org.openxml4j.exceptions.OpenXML4JException; | |||
import org.openxml4j.opc.Package; | |||
import org.openxml4j.opc.PackageRelationshipCollection; | |||
import org.openxml4j.opc.internal.PackagePropertiesPart; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.Package; | |||
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; | |||
import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart; | |||
/** | |||
* Wrapper around the two different kinds of OOXML properties |
@@ -19,8 +19,8 @@ package org.apache.poi; | |||
import java.io.IOException; | |||
import org.apache.xmlbeans.XmlException; | |||
import org.openxml4j.exceptions.OpenXML4JException; | |||
import org.openxml4j.opc.internal.PackagePropertiesPart; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart; | |||
import org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty; | |||
/** |
@@ -20,7 +20,7 @@ import java.io.IOException; | |||
import org.apache.poi.POIXMLProperties.*; | |||
import org.apache.xmlbeans.XmlException; | |||
import org.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
public abstract class POIXMLTextExtractor extends POITextExtractor { | |||
/** The POIXMLDocument that's open */ |
@@ -22,11 +22,11 @@ import java.io.InputStream; | |||
import java.io.PrintStream; | |||
import java.util.ArrayList; | |||
import org.openxml4j.opc.Package; | |||
import org.openxml4j.opc.PackageAccess; | |||
import org.openxml4j.opc.PackagePart; | |||
import org.openxml4j.opc.PackageRelationship; | |||
import org.openxml4j.opc.PackageRelationshipCollection; | |||
import org.apache.poi.openxml4j.opc.Package; | |||
import org.apache.poi.openxml4j.opc.PackageAccess; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.PackageRelationship; | |||
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; | |||
/** | |||
* Prints out the contents of a OOXML container. |
@@ -41,15 +41,14 @@ import org.apache.poi.xslf.XSLFSlideShow; | |||
import org.apache.poi.xslf.extractor.XSLFPowerPointExtractor; | |||
import org.apache.poi.xssf.extractor.XSSFExcelExtractor; | |||
import org.apache.poi.xssf.usermodel.XSSFRelation; | |||
import org.apache.poi.xwpf.usermodel.XWPFDocument; | |||
import org.apache.poi.xwpf.usermodel.XWPFRelation; | |||
import org.apache.poi.xwpf.extractor.XWPFWordExtractor; | |||
import org.apache.xmlbeans.XmlException; | |||
import org.openxml4j.exceptions.InvalidFormatException; | |||
import org.openxml4j.exceptions.OpenXML4JException; | |||
import org.openxml4j.opc.Package; | |||
import org.openxml4j.opc.PackagePart; | |||
import org.openxml4j.opc.PackageRelationshipCollection; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.Package; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; | |||
/** | |||
* Figures out the correct POITextExtractor for your supplied |
@@ -0,0 +1,27 @@ | |||
/* ==================================================================== | |||
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.openxml4j.exceptions; | |||
@SuppressWarnings("serial") | |||
public class InvalidFormatException extends OpenXML4JException{ | |||
public InvalidFormatException(String message){ | |||
super(message); | |||
} | |||
} |
@@ -0,0 +1,32 @@ | |||
/* ==================================================================== | |||
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.openxml4j.exceptions; | |||
/** | |||
* Throw when an invalid operation is done. | |||
* | |||
* @author Julien Chable | |||
* @version 1.0 | |||
*/ | |||
@SuppressWarnings("serial") | |||
public class InvalidOperationException extends OpenXML4JRuntimeException{ | |||
public InvalidOperationException(String message){ | |||
super(message); | |||
} | |||
} |
@@ -0,0 +1,34 @@ | |||
/* ==================================================================== | |||
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.openxml4j.exceptions; | |||
/** | |||
* Global exception throws when a critical error occurs. (this exception is not | |||
* set as Runtime in order to force user to manage the exception in a | |||
* try/catch). | |||
* | |||
* @author CDubettier, Julien Chable | |||
* @version 1.0 | |||
*/ | |||
@SuppressWarnings("serial") | |||
public class OpenXML4JException extends Exception { | |||
public OpenXML4JException(String msg) { | |||
super(msg); | |||
} | |||
} |
@@ -0,0 +1,34 @@ | |||
/* ==================================================================== | |||
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.openxml4j.exceptions; | |||
/** | |||
* Global exception throws when a critical error occurs (this exception is | |||
* set as Runtime in order not to force the user to manage the exception in a | |||
* try/catch). | |||
* | |||
* @author Julien Chable | |||
* @version 1.0 | |||
*/ | |||
@SuppressWarnings("serial") | |||
public class OpenXML4JRuntimeException extends RuntimeException { | |||
public OpenXML4JRuntimeException(String msg) { | |||
super(msg); | |||
} | |||
} |
@@ -0,0 +1,33 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc; | |||
/** | |||
* Specifies the location where the X.509 certificate that is used in signing is stored. | |||
* | |||
* @author Julien Chable | |||
* @version 1.0 | |||
*/ | |||
public enum CertificateEmbeddingOption { | |||
/** The certificate is embedded in its own PackagePart. */ | |||
IN_CERTIFICATE_PART, | |||
/** The certificate is embedded in the SignaturePart that is created for the signature being added. */ | |||
IN_SIGNATURE_PART, | |||
/** The certificate in not embedded in the package. */ | |||
NOT_EMBEDDED | |||
} |
@@ -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.openxml4j.opc; | |||
import java.util.zip.Deflater; | |||
/** | |||
* Specifies the compression level for content that is stored in a PackagePart. | |||
* | |||
* @author Julien Chable | |||
* @version 1.0 | |||
*/ | |||
public enum CompressionOption { | |||
/** Compression is optimized for performance. */ | |||
FAST(Deflater.BEST_SPEED), | |||
/** Compression is optimized for size. */ | |||
MAXIMUM(Deflater.BEST_COMPRESSION), | |||
/** Compression is optimized for a balance between size and performance. */ | |||
NORMAL(Deflater.DEFAULT_COMPRESSION), | |||
/** Compression is turned off. */ | |||
NOT_COMPRESSED(Deflater.NO_COMPRESSION); | |||
private final int value; | |||
CompressionOption(int value) { | |||
this.value = value; | |||
} | |||
public int value() { | |||
return this.value; | |||
} | |||
} |
@@ -0,0 +1,43 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc; | |||
import java.io.File; | |||
/** | |||
* Storage class for configuration storage parameters. | |||
* TODO xml syntax checking is no longer done with DOM4j parser -> remove the schema or do it ? | |||
* | |||
* @author CDubettier, Julen Chable | |||
* @version 1.0 | |||
*/ | |||
public class Configuration { | |||
// TODO configuration by default. should be clearly stated that it should be | |||
// changed to match installation path | |||
// as schemas dir is needed in runtime | |||
static private String pathForXmlSchema = System.getProperty("user.dir") | |||
+ File.separator + "src" + File.separator + "schemas"; | |||
public static String getPathForXmlSchema() { | |||
return pathForXmlSchema; | |||
} | |||
public static void setPathForXmlSchema(String pathForXmlSchema) { | |||
Configuration.pathForXmlSchema = pathForXmlSchema; | |||
} | |||
} |
@@ -0,0 +1,129 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc; | |||
/** | |||
* Open Packaging Convention content types (see Annex F : Standard Namespaces | |||
* and Content Types). | |||
* | |||
* @author CDubettier define some constants, Julien Chable | |||
* @version 0.1 | |||
*/ | |||
public class ContentTypes { | |||
/* | |||
* Open Packaging Convention (Annex F : Standard Namespaces and Content | |||
* Types) | |||
*/ | |||
/** | |||
* Core Properties part. | |||
*/ | |||
public static final String CORE_PROPERTIES_PART = "application/vnd.openxmlformats-package.core-properties+xml"; | |||
/** | |||
* Digital Signature Certificate part. | |||
*/ | |||
public static final String DIGITAL_SIGNATURE_CERTIFICATE_PART = "application/vnd.openxmlformats-package.digital-signature-certificate"; | |||
/** | |||
* Digital Signature Origin part. | |||
*/ | |||
public static final String DIGITAL_SIGNATURE_ORIGIN_PART = "application/vnd.openxmlformats-package.digital-signature-origin"; | |||
/** | |||
* Digital Signature XML Signature part. | |||
*/ | |||
public static final String DIGITAL_SIGNATURE_XML_SIGNATURE_PART = "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml"; | |||
/** | |||
* Relationships part. | |||
*/ | |||
public static final String RELATIONSHIPS_PART = "application/vnd.openxmlformats-package.relationships+xml"; | |||
/** | |||
* Custom XML part. | |||
*/ | |||
public static final String CUSTOM_XML_PART = "application/vnd.openxmlformats-officedocument.customXmlProperties+xml"; | |||
/** | |||
* Plain old xml. Note - OOXML uses application/xml, and not text/xml! | |||
*/ | |||
public static final String PLAIN_OLD_XML = "application/xml"; | |||
public static final String IMAGE_JPEG = "image/jpeg"; | |||
public static final String EXTENSION_JPG_1 = "jpg"; | |||
public static final String EXTENSION_JPG_2 = "jpeg"; | |||
// image/png ISO/IEC 15948:2003 http://www.libpng.org/pub/png/spec/ | |||
public static final String IMAGE_PNG = "image/png"; | |||
public static final String EXTENSION_PNG = "png"; | |||
// image/gif http://www.w3.org/Graphics/GIF/spec-gif89a.txt | |||
public static final String IMAGE_GIF = "image/gif"; | |||
public static final String EXTENSION_GIF = "gif"; | |||
/** | |||
* TIFF image format. | |||
* | |||
* @see http://partners.adobe.com/public/developer/tiff/index.html#spec | |||
*/ | |||
public static final String IMAGE_TIFF = "image/tiff"; | |||
public static final String EXTENSION_TIFF = "tiff"; | |||
/** | |||
* Pict image format. | |||
* | |||
* @see http://developer.apple.com/documentation/mac/QuickDraw/QuickDraw-2.html | |||
*/ | |||
public static final String IMAGE_PICT = "image/pict"; | |||
public static final String EXTENSION_PICT = "tiff"; | |||
/** | |||
* XML file. | |||
*/ | |||
public static final String XML = "text/xml"; | |||
public static final String EXTENSION_XML = "xml"; | |||
public static String getContentTypeFromFileExtension(String filename) { | |||
String extension = filename.substring(filename.lastIndexOf(".") + 1) | |||
.toLowerCase(); | |||
if (extension.equals(EXTENSION_JPG_1) | |||
|| extension.equals(EXTENSION_JPG_2)) | |||
return IMAGE_JPEG; | |||
else if (extension.equals(EXTENSION_GIF)) | |||
return IMAGE_GIF; | |||
else if (extension.equals(EXTENSION_PICT)) | |||
return IMAGE_PICT; | |||
else if (extension.equals(EXTENSION_PNG)) | |||
return IMAGE_PNG; | |||
else if (extension.equals(EXTENSION_TIFF)) | |||
return IMAGE_TIFF; | |||
else if (extension.equals(EXTENSION_XML)) | |||
return XML; | |||
else | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,29 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc; | |||
/** | |||
* Specifies the encryption option for parts in a Package. | |||
* | |||
* @author Julien Chable | |||
* @version 0.1 | |||
*/ | |||
public enum EncryptionOption { | |||
/** No encryption. */ | |||
NONE | |||
} |
@@ -0,0 +1,33 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc; | |||
/** | |||
* Specifies package access. | |||
* | |||
* @author Julien Chable | |||
* @version 1.0 | |||
*/ | |||
public enum PackageAccess { | |||
/** Read only. Write not authorized. */ | |||
READ, | |||
/** Write only. Read not authorized. */ | |||
WRITE, | |||
/** Read and Write mode. */ | |||
READ_WRITE | |||
} |
@@ -0,0 +1,52 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc; | |||
/** | |||
* Open Packaging Convention namespaces URI. | |||
* | |||
* @author Julien Chable | |||
* @version 1.0 | |||
*/ | |||
public interface PackageNamespaces { | |||
/** | |||
* Content Types. | |||
*/ | |||
public static final String CONTENT_TYPES = "http://schemas.openxmlformats.org/package/2006/content-types"; | |||
/** | |||
* Core Properties. | |||
*/ | |||
public static final String CORE_PROPERTIES = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties"; | |||
/** | |||
* Digital Signatures. | |||
*/ | |||
public static final String DIGITAL_SIGNATURE = "http://schemas.openxmlformats.org/package/2006/digital-signature"; | |||
/** | |||
* Relationships. | |||
*/ | |||
public static final String RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships"; | |||
/** | |||
* Markup Compatibility. | |||
*/ | |||
public static final String MARKUP_COMPATIBILITY = "http://schemas.openxmlformats.org/markup-compatibility/2006"; | |||
} |
@@ -0,0 +1,654 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import java.net.URI; | |||
import java.net.URISyntaxException; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
import org.apache.poi.openxml4j.exceptions.InvalidOperationException; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.internal.ContentType; | |||
/** | |||
* Provides a base class for parts stored in a Package. | |||
* | |||
* @author Julien Chable | |||
* @version 0.9 | |||
*/ | |||
public abstract class PackagePart implements RelationshipSource { | |||
/** | |||
* This part's container. | |||
*/ | |||
protected Package container; | |||
/** | |||
* The part name. (required by the specification [M1.1]) | |||
*/ | |||
protected PackagePartName partName; | |||
/** | |||
* The type of content of this part. (required by the specification [M1.2]) | |||
*/ | |||
protected ContentType contentType; | |||
/** | |||
* Flag to know if this part is a relationship. | |||
*/ | |||
private boolean isRelationshipPart; | |||
/** | |||
* Flag to know if this part has been logically deleted. | |||
*/ | |||
private boolean isDeleted; | |||
/** | |||
* This part's relationships. | |||
*/ | |||
private PackageRelationshipCollection relationships; | |||
/** | |||
* Constructor. | |||
* | |||
* @param pack | |||
* Parent package. | |||
* @param partName | |||
* The part name, relative to the parent Package root. | |||
* @param contentType | |||
* The content type. | |||
* @throws InvalidFormatException | |||
* If the specified URI is not valid. | |||
*/ | |||
protected PackagePart(Package pack, PackagePartName partName, | |||
ContentType contentType) throws InvalidFormatException { | |||
this(pack, partName, contentType, true); | |||
} | |||
/** | |||
* Constructor. | |||
* | |||
* @param pack | |||
* Parent package. | |||
* @param partName | |||
* The part name, relative to the parent Package root. | |||
* @param contentType | |||
* The content type. | |||
* @param loadRelationships | |||
* Specify if the relationships will be loaded | |||
* @throws InvalidFormatException | |||
* If the specified URI is not valid. | |||
*/ | |||
protected PackagePart(Package pack, PackagePartName partName, | |||
ContentType contentType, boolean loadRelationships) | |||
throws InvalidFormatException { | |||
this.partName = partName; | |||
this.contentType = contentType; | |||
this.container = (ZipPackage) pack; | |||
// Check if this part is a relationship part | |||
isRelationshipPart = this.partName.isRelationshipPartURI(); | |||
// Load relationships if any | |||
if (loadRelationships) | |||
loadRelationships(); | |||
} | |||
/** | |||
* Constructor. | |||
* | |||
* @param pack | |||
* Parent package. | |||
* @param partName | |||
* The part name, relative to the parent Package root. | |||
* @param contentType | |||
* The Multipurpose Internet Mail Extensions (MIME) content type | |||
* of the part's data stream. | |||
*/ | |||
public PackagePart(Package pack, PackagePartName partName, | |||
String contentType) throws InvalidFormatException { | |||
this(pack, partName, new ContentType(contentType)); | |||
} | |||
/** | |||
* Adds an external relationship to a part (except relationships part). | |||
* | |||
* The targets of external relationships are not subject to the same | |||
* validity checks that internal ones are, as the contents is potentially | |||
* any file, URL or similar. | |||
* | |||
* @param target | |||
* External target of the relationship | |||
* @param relationshipType | |||
* Type of relationship. | |||
* @return The newly created and added relationship | |||
* @see org.apache.poi.openxml4j.opc.RelationshipSource#addExternalRelationship(java.lang.String, | |||
* java.lang.String) | |||
*/ | |||
public PackageRelationship addExternalRelationship(String target, | |||
String relationshipType) { | |||
return addExternalRelationship(target, relationshipType, null); | |||
} | |||
/** | |||
* Adds an external relationship to a part (except relationships part). | |||
* | |||
* The targets of external relationships are not subject to the same | |||
* validity checks that internal ones are, as the contents is potentially | |||
* any file, URL or similar. | |||
* | |||
* @param target | |||
* External target of the relationship | |||
* @param relationshipType | |||
* Type of relationship. | |||
* @param id | |||
* Relationship unique id. | |||
* @return The newly created and added relationship | |||
* @see org.apache.poi.openxml4j.opc.RelationshipSource#addExternalRelationship(java.lang.String, | |||
* java.lang.String) | |||
*/ | |||
public PackageRelationship addExternalRelationship(String target, | |||
String relationshipType, String id) { | |||
if (target == null) { | |||
throw new IllegalArgumentException("target"); | |||
} | |||
if (relationshipType == null) { | |||
throw new IllegalArgumentException("relationshipType"); | |||
} | |||
if (relationships == null) { | |||
relationships = new PackageRelationshipCollection(); | |||
} | |||
URI targetURI; | |||
try { | |||
targetURI = new URI(target); | |||
} catch (URISyntaxException e) { | |||
throw new IllegalArgumentException("Invalid target - " + e); | |||
} | |||
return relationships.addRelationship(targetURI, TargetMode.EXTERNAL, | |||
relationshipType, id); | |||
} | |||
/** | |||
* Add a relationship to a part (except relationships part). | |||
* | |||
* @param targetPartName | |||
* Name of the target part. This one must be relative to the | |||
* source root directory of the part. | |||
* @param targetMode | |||
* Mode [Internal|External]. | |||
* @param relationshipType | |||
* Type of relationship. | |||
* @return The newly created and added relationship | |||
* @see org.apache.poi.openxml4j.opc.RelationshipSource#addRelationship(org.apache.poi.openxml4j.opc.PackagePartName, | |||
* org.apache.poi.openxml4j.opc.TargetMode, java.lang.String) | |||
*/ | |||
public PackageRelationship addRelationship(PackagePartName targetPartName, | |||
TargetMode targetMode, String relationshipType) { | |||
return addRelationship(targetPartName, targetMode, relationshipType, | |||
null); | |||
} | |||
/** | |||
* Add a relationship to a part (except relationships part). | |||
* | |||
* Check rule M1.25: The Relationships part shall not have relationships to | |||
* any other part. Package implementers shall enforce this requirement upon | |||
* the attempt to create such a relationship and shall treat any such | |||
* relationship as invalid. | |||
* | |||
* @param targetPartName | |||
* Name of the target part. This one must be relative to the | |||
* source root directory of the part. | |||
* @param targetMode | |||
* Mode [Internal|External]. | |||
* @param relationshipType | |||
* Type of relationship. | |||
* @param id | |||
* Relationship unique id. | |||
* @return The newly created and added relationship | |||
* | |||
* @throws InvalidFormatException | |||
* If the URI point to a relationship part URI. | |||
* @see org.apache.poi.openxml4j.opc.RelationshipSource#addRelationship(org.apache.poi.openxml4j.opc.PackagePartName, | |||
* org.apache.poi.openxml4j.opc.TargetMode, java.lang.String, java.lang.String) | |||
*/ | |||
public PackageRelationship addRelationship(PackagePartName targetPartName, | |||
TargetMode targetMode, String relationshipType, String id) { | |||
container.throwExceptionIfReadOnly(); | |||
if (targetPartName == null) { | |||
throw new IllegalArgumentException("targetPartName"); | |||
} | |||
if (targetMode == null) { | |||
throw new IllegalArgumentException("targetMode"); | |||
} | |||
if (relationshipType == null) { | |||
throw new IllegalArgumentException("relationshipType"); | |||
} | |||
if (this.isRelationshipPart || targetPartName.isRelationshipPartURI()) { | |||
throw new InvalidOperationException( | |||
"Rule M1.25: The Relationships part shall not have relationships to any other part."); | |||
} | |||
if (relationships == null) { | |||
relationships = new PackageRelationshipCollection(); | |||
} | |||
return relationships.addRelationship(targetPartName.getURI(), | |||
targetMode, relationshipType, id); | |||
} | |||
/** | |||
* Add a relationship to a part (except relationships part). | |||
* | |||
* @param targetURI | |||
* URI the target part. Must be relative to the source root | |||
* directory of the part. | |||
* @param targetMode | |||
* Mode [Internal|External]. | |||
* @param relationshipType | |||
* Type of relationship. | |||
* @return The newly created and added relationship | |||
* @see org.apache.poi.openxml4j.opc.RelationshipSource#addRelationship(org.apache.poi.openxml4j.opc.PackagePartName, | |||
* org.apache.poi.openxml4j.opc.TargetMode, java.lang.String) | |||
*/ | |||
public PackageRelationship addRelationship(URI targetURI, | |||
TargetMode targetMode, String relationshipType) { | |||
return addRelationship(targetURI, targetMode, relationshipType, null); | |||
} | |||
/** | |||
* Add a relationship to a part (except relationships part). | |||
* | |||
* Check rule M1.25: The Relationships part shall not have relationships to | |||
* any other part. Package implementers shall enforce this requirement upon | |||
* the attempt to create such a relationship and shall treat any such | |||
* relationship as invalid. | |||
* | |||
* @param targetURI | |||
* URI of the target part. Must be relative to the source root | |||
* directory of the part. | |||
* @param targetMode | |||
* Mode [Internal|External]. | |||
* @param relationshipType | |||
* Type of relationship. | |||
* @param id | |||
* Relationship unique id. | |||
* @return The newly created and added relationship | |||
* | |||
* @throws InvalidFormatException | |||
* If the URI point to a relationship part URI. | |||
* @see org.apache.poi.openxml4j.opc.RelationshipSource#addRelationship(org.apache.poi.openxml4j.opc.PackagePartName, | |||
* org.apache.poi.openxml4j.opc.TargetMode, java.lang.String, java.lang.String) | |||
*/ | |||
public PackageRelationship addRelationship(URI targetURI, | |||
TargetMode targetMode, String relationshipType, String id) { | |||
container.throwExceptionIfReadOnly(); | |||
if (targetURI == null) { | |||
throw new IllegalArgumentException("targetPartName"); | |||
} | |||
if (targetMode == null) { | |||
throw new IllegalArgumentException("targetMode"); | |||
} | |||
if (relationshipType == null) { | |||
throw new IllegalArgumentException("relationshipType"); | |||
} | |||
// Try to retrieve the target part | |||
if (this.isRelationshipPart | |||
|| PackagingURIHelper.isRelationshipPartURI(targetURI)) { | |||
throw new InvalidOperationException( | |||
"Rule M1.25: The Relationships part shall not have relationships to any other part."); | |||
} | |||
if (relationships == null) { | |||
relationships = new PackageRelationshipCollection(); | |||
} | |||
return relationships.addRelationship(targetURI, | |||
targetMode, relationshipType, id); | |||
} | |||
/** | |||
* @see org.apache.poi.openxml4j.opc.RelationshipSource#clearRelationships() | |||
*/ | |||
public void clearRelationships() { | |||
if (relationships != null) { | |||
relationships.clear(); | |||
} | |||
} | |||
/** | |||
* Delete the relationship specified by its id. | |||
* | |||
* @param id | |||
* The ID identified the part to delete. | |||
* @see org.apache.poi.openxml4j.opc.RelationshipSource#removeRelationship(java.lang.String) | |||
*/ | |||
public void removeRelationship(String id) { | |||
this.container.throwExceptionIfReadOnly(); | |||
if (this.relationships != null) | |||
this.relationships.removeRelationship(id); | |||
} | |||
/** | |||
* Retrieve all the relationships attached to this part. | |||
* | |||
* @return This part's relationships. | |||
* @throws OpenXML4JException | |||
* @see org.apache.poi.openxml4j.opc.RelationshipSource#getRelationships() | |||
*/ | |||
public PackageRelationshipCollection getRelationships() | |||
throws InvalidFormatException { | |||
return getRelationshipsCore(null); | |||
} | |||
/** | |||
* Retrieves a package relationship from its id. | |||
* | |||
* @param id | |||
* ID of the package relationship to retrieve. | |||
* @return The package relationship | |||
* @see org.apache.poi.openxml4j.opc.RelationshipSource#getRelationship(java.lang.String) | |||
*/ | |||
public PackageRelationship getRelationship(String id) { | |||
return this.relationships.getRelationshipByID(id); | |||
} | |||
/** | |||
* Retrieve all relationships attached to this part which have the specified | |||
* type. | |||
* | |||
* @param relationshipType | |||
* Relationship type filter. | |||
* @return All relationships from this part that have the specified type. | |||
* @throws InvalidFormatException | |||
* If an error occurs while parsing the part. | |||
* @throws InvalidOperationException | |||
* If the package is open in write only mode. | |||
* @see org.apache.poi.openxml4j.opc.RelationshipSource#getRelationshipsByType(java.lang.String) | |||
*/ | |||
public PackageRelationshipCollection getRelationshipsByType( | |||
String relationshipType) throws InvalidFormatException { | |||
container.throwExceptionIfWriteOnly(); | |||
return getRelationshipsCore(relationshipType); | |||
} | |||
/** | |||
* Implementation of the getRelationships method(). | |||
* | |||
* @param filter | |||
* Relationship type filter. If <i>null</i> then the filter is | |||
* disabled and return all the relationships. | |||
* @return All relationships from this part that have the specified type. | |||
* @throws InvalidFormatException | |||
* Throws if an error occurs during parsing the relationships | |||
* part. | |||
* @throws InvalidOperationException | |||
* Throws if the package is open en write only mode. | |||
* @see #getRelationshipsByType(String) | |||
*/ | |||
private PackageRelationshipCollection getRelationshipsCore(String filter) | |||
throws InvalidFormatException { | |||
this.container.throwExceptionIfWriteOnly(); | |||
if (relationships == null) { | |||
this.throwExceptionIfRelationship(); | |||
relationships = new PackageRelationshipCollection(this); | |||
} | |||
return new PackageRelationshipCollection(relationships, filter); | |||
} | |||
/** | |||
* Knows if the part have any relationships. | |||
* | |||
* @return <b>true</b> if the part have at least one relationship else | |||
* <b>false</b>. | |||
* @see org.apache.poi.openxml4j.opc.RelationshipSource#hasRelationships() | |||
*/ | |||
public boolean hasRelationships() { | |||
return (!this.isRelationshipPart && (relationships != null && relationships | |||
.size() > 0)); | |||
} | |||
/** | |||
* Checks if the specified relationship is part of this package part. | |||
* | |||
* @param rel | |||
* The relationship to check. | |||
* @return <b>true</b> if the specified relationship exists in this part, | |||
* else returns <b>false</b> | |||
* @see org.apache.poi.openxml4j.opc.RelationshipSource#isRelationshipExists(org.apache.poi.openxml4j.opc.PackageRelationship) | |||
*/ | |||
@SuppressWarnings("finally") | |||
public boolean isRelationshipExists(PackageRelationship rel) { | |||
try { | |||
for (PackageRelationship r : this.getRelationships()) { | |||
if (r == rel) | |||
return true; | |||
} | |||
} finally { | |||
return false; | |||
} | |||
} | |||
/** | |||
* Get the input stream of this part to read its content. | |||
* | |||
* @return The input stream of the content of this part, else | |||
* <code>null</code>. | |||
*/ | |||
public InputStream getInputStream() throws IOException { | |||
InputStream inStream = this.getInputStreamImpl(); | |||
if (inStream == null) { | |||
throw new IOException("Can't obtain the input stream from " | |||
+ partName.getName()); | |||
} else | |||
return inStream; | |||
} | |||
/** | |||
* Get the output stream of this part. If the part is originally embedded in | |||
* Zip package, it'll be transform intot a <i>MemoryPackagePart</i> in | |||
* order to write inside (the standard Java API doesn't allow to write in | |||
* the file) | |||
* | |||
* @see org.apache.poi.openxml4j.opc.internal.MemoryPackagePart | |||
*/ | |||
public OutputStream getOutputStream() { | |||
OutputStream outStream; | |||
// If this part is a zip package part (read only by design) we convert | |||
// this part into a MemoryPackagePart instance for write purpose. | |||
if (this instanceof ZipPackagePart) { | |||
// Delete logically this part | |||
this.container.removePart(this.partName); | |||
// Create a memory part | |||
PackagePart part = container.createPart(this.partName, | |||
this.contentType.toString(), false); | |||
part.relationships = this.relationships; | |||
if (part == null) { | |||
throw new InvalidOperationException( | |||
"Can't create a temporary part !"); | |||
} | |||
outStream = part.getOutputStreamImpl(); | |||
} else { | |||
outStream = this.getOutputStreamImpl(); | |||
} | |||
return outStream; | |||
} | |||
/** | |||
* Throws an exception if this package part is a relationship part. | |||
* | |||
* @throws InvalidOperationException | |||
* If this part is a relationship part. | |||
*/ | |||
private void throwExceptionIfRelationship() | |||
throws InvalidOperationException { | |||
if (this.isRelationshipPart) | |||
throw new InvalidOperationException( | |||
"Can do this operation on a relationship part !"); | |||
} | |||
/** | |||
* Ensure the package relationships collection instance is built. | |||
* | |||
* @throws InvalidFormatException | |||
* Throws if | |||
*/ | |||
private void loadRelationships() throws InvalidFormatException { | |||
if (this.relationships == null && !this.isRelationshipPart) { | |||
this.throwExceptionIfRelationship(); | |||
relationships = new PackageRelationshipCollection(this); | |||
} | |||
} | |||
/* | |||
* Accessors | |||
*/ | |||
/** | |||
* @return the uri | |||
*/ | |||
public PackagePartName getPartName() { | |||
return partName; | |||
} | |||
/** | |||
* @return the contentType | |||
*/ | |||
public String getContentType() { | |||
return contentType.toString(); | |||
} | |||
/** | |||
* Set the content type. | |||
* | |||
* @param contentType | |||
* the contentType to set | |||
* | |||
* @throws InvalidFormatException | |||
* Throws if the content type is not valid. | |||
* @throws InvalidOperationException | |||
* Throws if you try to change the content type whereas this | |||
* part is already attached to a package. | |||
*/ | |||
public void setContentType(String contentType) | |||
throws InvalidFormatException { | |||
if (container == null) | |||
this.contentType = new ContentType(contentType); | |||
else | |||
throw new InvalidOperationException( | |||
"You can't change the content type of a part."); | |||
} | |||
public Package getPackage() { | |||
return container; | |||
} | |||
/** | |||
* @return | |||
*/ | |||
public boolean isRelationshipPart() { | |||
return this.isRelationshipPart; | |||
} | |||
/** | |||
* @return | |||
*/ | |||
public boolean isDeleted() { | |||
return isDeleted; | |||
} | |||
/** | |||
* @param isDeleted | |||
* the isDeleted to set | |||
*/ | |||
public void setDeleted(boolean isDeleted) { | |||
this.isDeleted = isDeleted; | |||
} | |||
@Override | |||
public String toString() { | |||
return "Name: " + this.partName + " - Content Type: " | |||
+ this.contentType.toString(); | |||
} | |||
/*-------------- Abstract methods ------------- */ | |||
/** | |||
* Abtract method that get the input stream of this part. | |||
* | |||
* @exception IOException | |||
* Throws if an IO Exception occur in the implementation | |||
* method. | |||
*/ | |||
protected abstract InputStream getInputStreamImpl() throws IOException; | |||
/** | |||
* Abstract method that get the output stream of this part. | |||
*/ | |||
protected abstract OutputStream getOutputStreamImpl(); | |||
/** | |||
* Save the content of this part and the associated relationships part (if | |||
* this part own at least one relationship) into the specified output | |||
* stream. | |||
* | |||
* @param zos | |||
* Output stream to save this part. | |||
* @throws OpenXML4JException | |||
* If any exception occur. | |||
*/ | |||
public abstract boolean save(OutputStream zos) throws OpenXML4JException; | |||
/** | |||
* Load the content of this part. | |||
* | |||
* @param ios | |||
* The input stream of the content to load. | |||
* @return <b>true</b> if the content has been successfully loaded, else | |||
* <b>false</b>. | |||
* @throws InvalidFormatException | |||
* Throws if the content format is invalid. | |||
*/ | |||
public abstract boolean load(InputStream ios) throws InvalidFormatException; | |||
/** | |||
* Close this part : flush this part, close the input stream and output | |||
* stream. After this method call, the part must be available for packaging. | |||
*/ | |||
public abstract void close(); | |||
/** | |||
* Flush the content of this part. If the input stream and/or output stream | |||
* as in a waiting state to read or write, the must to empty their | |||
* respective buffer. | |||
*/ | |||
public abstract void flush(); | |||
} |
@@ -0,0 +1,81 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc; | |||
import java.util.ArrayList; | |||
import java.util.TreeMap; | |||
import org.apache.poi.openxml4j.exceptions.InvalidOperationException; | |||
/** | |||
* A package part collection. | |||
* | |||
* @author Julien Chable | |||
* @version 0.1 | |||
*/ | |||
public final class PackagePartCollection extends | |||
TreeMap<PackagePartName, PackagePart> { | |||
private static final long serialVersionUID = 2515031135957635515L; | |||
/** | |||
* Arraylist use to store this collection part names as string for rule | |||
* M1.11 optimized checking. | |||
*/ | |||
private ArrayList<String> registerPartNameStr = new ArrayList<String>(); | |||
@Override | |||
public Object clone() { | |||
return super.clone(); | |||
} | |||
/** | |||
* Check rule [M1.11]: a package implementer shall neither create nor | |||
* recognize a part with a part name derived from another part name by | |||
* appending segments to it. | |||
* | |||
* @exception InvalidOperationException | |||
* Throws if you try to add a part with a name derived from | |||
* another part name. | |||
*/ | |||
@Override | |||
public PackagePart put(PackagePartName partName, PackagePart part) { | |||
String[] segments = partName.getURI().toASCIIString().split( | |||
PackagingURIHelper.FORWARD_SLASH_STRING); | |||
StringBuffer concatSeg = new StringBuffer(); | |||
for (String seg : segments) { | |||
if (!seg.equals("")) | |||
concatSeg.append(PackagingURIHelper.FORWARD_SLASH_CHAR); | |||
concatSeg.append(seg); | |||
if (this.registerPartNameStr.contains(concatSeg.toString())) { | |||
throw new InvalidOperationException( | |||
"You can't add a part with a part name derived from another part ! [M1.11]"); | |||
} | |||
} | |||
this.registerPartNameStr.add(partName.getName()); | |||
return super.put(partName, part); | |||
} | |||
@Override | |||
public PackagePart remove(Object key) { | |||
if (key instanceof PackagePartName) { | |||
this.registerPartNameStr.remove(((PackagePartName) key).getName()); | |||
} | |||
return super.remove(key); | |||
} | |||
} |
@@ -0,0 +1,509 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc; | |||
import java.net.URI; | |||
import java.net.URISyntaxException; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException; | |||
/** | |||
* An immutable Open Packaging Convention compliant part name. | |||
* | |||
* @author Julien Chable | |||
* @version 0.1 | |||
* | |||
* @see http://www.ietf.org/rfc/rfc3986.txt | |||
*/ | |||
public final class PackagePartName implements Comparable<PackagePartName> { | |||
/** | |||
* Part name stored as an URI. | |||
*/ | |||
private URI partNameURI; | |||
/* | |||
* URI Characters definition (RFC 3986) | |||
*/ | |||
/** | |||
* Reserved characters for sub delimitations. | |||
*/ | |||
private static String[] RFC3986_PCHAR_SUB_DELIMS = { "!", "$", "&", "'", | |||
"(", ")", "*", "+", ",", ";", "=" }; | |||
/** | |||
* Unreserved character (+ ALPHA & DIGIT). | |||
*/ | |||
private static String[] RFC3986_PCHAR_UNRESERVED_SUP = { "-", ".", "_", "~" }; | |||
/** | |||
* Authorized reserved characters for pChar. | |||
*/ | |||
private static String[] RFC3986_PCHAR_AUTHORIZED_SUP = { ":", "@" }; | |||
/** | |||
* Flag to know if this part name is from a relationship part name. | |||
*/ | |||
private boolean isRelationship; | |||
/** | |||
* Constructor. Makes a ValidPartName object from a java.net.URI | |||
* | |||
* @param uri | |||
* The URI to validate and to transform into ValidPartName. | |||
* @param checkConformance | |||
* Flag to specify if the contructor have to validate the OPC | |||
* conformance. Must be always <code>true</code> except for | |||
* special URI like '/' which is needed for internal use by | |||
* OpenXML4J but is not valid. | |||
* @throws InvalidFormatException | |||
* Throw if the specified part name is not conform to Open | |||
* Packaging Convention specifications. | |||
* @see java.net.URI | |||
*/ | |||
PackagePartName(URI uri, boolean checkConformance) | |||
throws InvalidFormatException { | |||
if (checkConformance) { | |||
throwExceptionIfInvalidPartUri(uri); | |||
} else { | |||
if (!PackagingURIHelper.PACKAGE_ROOT_URI.equals(uri)) { | |||
throw new OpenXML4JRuntimeException( | |||
"OCP conformance must be check for ALL part name except special cases : ['/']"); | |||
} | |||
} | |||
this.partNameURI = uri; | |||
this.isRelationship = isRelationshipPartURI(this.partNameURI); | |||
} | |||
/** | |||
* Constructor. Makes a ValidPartName object from a String part name. | |||
* | |||
* @param partName | |||
* Part name to valid and to create. | |||
* @param checkConformance | |||
* Flag to specify if the contructor have to validate the OPC | |||
* conformance. Must be always <code>true</code> except for | |||
* special URI like '/' which is needed for internal use by | |||
* OpenXML4J but is not valid. | |||
* @throws InvalidFormatException | |||
* Throw if the specified part name is not conform to Open | |||
* Packaging Convention specifications. | |||
*/ | |||
PackagePartName(String partName, boolean checkConformance) | |||
throws InvalidFormatException { | |||
URI partURI; | |||
try { | |||
partURI = new URI(partName); | |||
} catch (URISyntaxException e) { | |||
throw new IllegalArgumentException( | |||
"partName argmument is not a valid OPC part name !"); | |||
} | |||
if (checkConformance) { | |||
throwExceptionIfInvalidPartUri(partURI); | |||
} else { | |||
if (!PackagingURIHelper.PACKAGE_ROOT_URI.equals(partURI)) { | |||
throw new OpenXML4JRuntimeException( | |||
"OCP conformance must be check for ALL part name except special cases : ['/']"); | |||
} | |||
} | |||
this.partNameURI = partURI; | |||
this.isRelationship = isRelationshipPartURI(this.partNameURI); | |||
} | |||
/** | |||
* Check if the specified part name is a relationship part name. | |||
* | |||
* @param partUri | |||
* The URI to check. | |||
* @return <code>true</code> if this part name respect the relationship | |||
* part naming convention else <code>false</code>. | |||
*/ | |||
private boolean isRelationshipPartURI(URI partUri) { | |||
if (partUri == null) | |||
throw new IllegalArgumentException("partUri"); | |||
return partUri.getPath().matches( | |||
"^.*/" + PackagingURIHelper.RELATIONSHIP_PART_SEGMENT_NAME + "/.*\\" | |||
+ PackagingURIHelper.RELATIONSHIP_PART_EXTENSION_NAME | |||
+ "$"); | |||
} | |||
/** | |||
* Know if this part name is a relationship part name. | |||
* | |||
* @return <code>true</code> if this part name respect the relationship | |||
* part naming convention else <code>false</code>. | |||
*/ | |||
public boolean isRelationshipPartURI() { | |||
return this.isRelationship; | |||
} | |||
/** | |||
* Throws an exception (of any kind) if the specified part name does not | |||
* follow the Open Packaging Convention specifications naming rules. | |||
* | |||
* @param partUri | |||
* The part name to check. | |||
* @throws Exception | |||
* Throws if the part name is invalid. | |||
*/ | |||
private static void throwExceptionIfInvalidPartUri(URI partUri) | |||
throws InvalidFormatException { | |||
if (partUri == null) | |||
throw new IllegalArgumentException("partUri"); | |||
// Check if the part name URI is empty [M1.1] | |||
throwExceptionIfEmptyURI(partUri); | |||
// Check if the part name URI is absolute | |||
throwExceptionIfAbsoluteUri(partUri); | |||
// Check if the part name URI starts with a forward slash [M1.4] | |||
throwExceptionIfPartNameNotStartsWithForwardSlashChar(partUri); | |||
// Check if the part name URI ends with a forward slash [M1.5] | |||
throwExceptionIfPartNameEndsWithForwardSlashChar(partUri); | |||
// Check if the part name does not have empty segments. [M1.3] | |||
// Check if a segment ends with a dot ('.') character. [M1.9] | |||
throwExceptionIfPartNameHaveInvalidSegments(partUri); | |||
} | |||
/** | |||
* Throws an exception if the specified URI is empty. [M1.1] | |||
* | |||
* @param partURI | |||
* Part URI to check. | |||
* @throws InvalidFormatException | |||
* If the specified URI is empty. | |||
*/ | |||
private static void throwExceptionIfEmptyURI(URI partURI) | |||
throws InvalidFormatException { | |||
if (partURI == null) | |||
throw new IllegalArgumentException("partURI"); | |||
String uriPath = partURI.getPath(); | |||
if (uriPath.length() == 0 | |||
|| ((uriPath.length() == 1) && (uriPath.charAt(0) == PackagingURIHelper.FORWARD_SLASH_CHAR))) | |||
throw new InvalidFormatException( | |||
"A part name shall not be empty [M1.1]: " | |||
+ partURI.getPath()); | |||
} | |||
/** | |||
* Throws an exception if the part name has empty segments. [M1.3] | |||
* | |||
* Throws an exception if a segment any characters other than pchar | |||
* characters. [M1.6] | |||
* | |||
* Throws an exception if a segment contain percent-encoded forward slash | |||
* ('/'), or backward slash ('\') characters. [M1.7] | |||
* | |||
* Throws an exception if a segment contain percent-encoded unreserved | |||
* characters. [M1.8] | |||
* | |||
* Throws an exception if the specified part name's segments end with a dot | |||
* ('.') character. [M1.9] | |||
* | |||
* Throws an exception if a segment doesn't include at least one non-dot | |||
* character. [M1.10] | |||
* | |||
* @param partUri | |||
* The part name to check. | |||
* @throws InvalidFormatException | |||
* if the specified URI contain an empty segments or if one the | |||
* segments contained in the part name, ends with a dot ('.') | |||
* character. | |||
*/ | |||
private static void throwExceptionIfPartNameHaveInvalidSegments(URI partUri) | |||
throws InvalidFormatException { | |||
if (partUri == null || "".equals(partUri)) { | |||
throw new IllegalArgumentException("partUri"); | |||
} | |||
// Split the URI into several part and analyze each | |||
String[] segments = partUri.toASCIIString().split("/"); | |||
if (segments.length <= 1 || !segments[0].equals("")) | |||
throw new InvalidFormatException( | |||
"A part name shall not have empty segments [M1.3]: " | |||
+ partUri.getPath()); | |||
for (int i = 1; i < segments.length; ++i) { | |||
String seg = segments[i]; | |||
if (seg == null || "".equals(seg)) { | |||
throw new InvalidFormatException( | |||
"A part name shall not have empty segments [M1.3]: " | |||
+ partUri.getPath()); | |||
} | |||
if (seg.endsWith(".")) { | |||
throw new InvalidFormatException( | |||
"A segment shall not end with a dot ('.') character [M1.9]: " | |||
+ partUri.getPath()); | |||
} | |||
if ("".equals(seg.replaceAll("\\\\.", ""))) { | |||
// Normally will never been invoked with the previous | |||
// implementation rule [M1.9] | |||
throw new InvalidFormatException( | |||
"A segment shall include at least one non-dot character. [M1.10]: " | |||
+ partUri.getPath()); | |||
} | |||
/* | |||
* Check for rule M1.6, M1.7, M1.8 | |||
*/ | |||
checkPCharCompliance(seg); | |||
} | |||
} | |||
/** | |||
* Throws an exception if a segment any characters other than pchar | |||
* characters. [M1.6] | |||
* | |||
* Throws an exception if a segment contain percent-encoded forward slash | |||
* ('/'), or backward slash ('\') characters. [M1.7] | |||
* | |||
* Throws an exception if a segment contain percent-encoded unreserved | |||
* characters. [M1.8] | |||
* | |||
* @param segment | |||
* The segment to check | |||
*/ | |||
private static void checkPCharCompliance(String segment) | |||
throws InvalidFormatException { | |||
boolean errorFlag; | |||
for (int i = 0; i < segment.length(); ++i) { | |||
char c = segment.charAt(i); | |||
errorFlag = true; | |||
/* Check rule M1.6 */ | |||
// Check for digit or letter | |||
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') | |||
|| (c >= '0' && c <= '9')) { | |||
errorFlag = false; | |||
} else { | |||
// Check "-", ".", "_", "~" | |||
for (int j = 0; j < RFC3986_PCHAR_UNRESERVED_SUP.length; ++j) { | |||
if (c == RFC3986_PCHAR_UNRESERVED_SUP[j].charAt(0)) { | |||
errorFlag = false; | |||
break; | |||
} | |||
} | |||
// Check ":", "@" | |||
for (int j = 0; errorFlag | |||
&& j < RFC3986_PCHAR_AUTHORIZED_SUP.length; ++j) { | |||
if (c == RFC3986_PCHAR_AUTHORIZED_SUP[j].charAt(0)) { | |||
errorFlag = false; | |||
} | |||
} | |||
// Check "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "=" | |||
for (int j = 0; errorFlag | |||
&& j < RFC3986_PCHAR_SUB_DELIMS.length; ++j) { | |||
if (c == RFC3986_PCHAR_SUB_DELIMS[j].charAt(0)) { | |||
errorFlag = false; | |||
} | |||
} | |||
} | |||
if (errorFlag && c == '%') { | |||
// We certainly found an encoded character, check for length | |||
// now ( '%' HEXDIGIT HEXDIGIT) | |||
if (((segment.length() - i) < 2)) { | |||
throw new InvalidFormatException("The segment " + segment | |||
+ " contain invalid encoded character !"); | |||
} | |||
// If not percent encoded character error occur then reset the | |||
// flag -> the character is valid | |||
errorFlag = false; | |||
// Decode the encoded character | |||
char decodedChar = (char) Integer.parseInt(segment.substring( | |||
i + 1, i + 3), 16); | |||
i += 2; | |||
/* Check rule M1.7 */ | |||
if (decodedChar == '/' || decodedChar == '\\') | |||
throw new InvalidFormatException( | |||
"A segment shall not contain percent-encoded forward slash ('/'), or backward slash ('\') characters. [M1.7]"); | |||
/* Check rule M1.8 */ | |||
// Check for unreserved character like define in RFC3986 | |||
if ((decodedChar >= 'A' && decodedChar <= 'Z') | |||
|| (decodedChar >= 'a' && decodedChar <= 'z') | |||
|| (decodedChar >= '0' && decodedChar <= '9')) | |||
errorFlag = true; | |||
// Check for unreserved character "-", ".", "_", "~" | |||
for (int j = 0; !errorFlag | |||
&& j < RFC3986_PCHAR_UNRESERVED_SUP.length; ++j) { | |||
if (c == RFC3986_PCHAR_UNRESERVED_SUP[j].charAt(0)) { | |||
errorFlag = true; | |||
break; | |||
} | |||
} | |||
if (errorFlag) | |||
throw new InvalidFormatException( | |||
"A segment shall not contain percent-encoded unreserved characters. [M1.8]"); | |||
} | |||
if (errorFlag) | |||
throw new InvalidFormatException( | |||
"A segment shall not hold any characters other than pchar characters. [M1.6]"); | |||
} | |||
} | |||
/** | |||
* Throws an exception if the specified part name doesn't start with a | |||
* forward slash character '/'. [M1.4] | |||
* | |||
* @param partUri | |||
* The part name to check. | |||
* @throws InvalidFormatException | |||
* If the specified part name doesn't start with a forward slash | |||
* character '/'. | |||
*/ | |||
private static void throwExceptionIfPartNameNotStartsWithForwardSlashChar( | |||
URI partUri) throws InvalidFormatException { | |||
String uriPath = partUri.getPath(); | |||
if (uriPath.length() > 0 | |||
&& uriPath.charAt(0) != PackagingURIHelper.FORWARD_SLASH_CHAR) | |||
throw new InvalidFormatException( | |||
"A part name shall start with a forward slash ('/') character [M1.4]: " | |||
+ partUri.getPath()); | |||
} | |||
/** | |||
* Throws an exception if the specified part name ends with a forwar slash | |||
* character '/'. [M1.5] | |||
* | |||
* @param partUri | |||
* The part name to check. | |||
* @throws InvalidFormatException | |||
* If the specified part name ends with a forwar slash character | |||
* '/'. | |||
*/ | |||
private static void throwExceptionIfPartNameEndsWithForwardSlashChar( | |||
URI partUri) throws InvalidFormatException { | |||
String uriPath = partUri.getPath(); | |||
if (uriPath.length() > 0 | |||
&& uriPath.charAt(uriPath.length() - 1) == PackagingURIHelper.FORWARD_SLASH_CHAR) | |||
throw new InvalidFormatException( | |||
"A part name shall not have a forward slash as the last character [M1.5]: " | |||
+ partUri.getPath()); | |||
} | |||
/** | |||
* Throws an exception if the specified URI is absolute. | |||
* | |||
* @param partUri | |||
* The URI to check. | |||
* @throws InvalidFormatException | |||
* Throws if the specified URI is absolute. | |||
*/ | |||
private static void throwExceptionIfAbsoluteUri(URI partUri) | |||
throws InvalidFormatException { | |||
if (partUri.isAbsolute()) | |||
throw new InvalidFormatException("Absolute URI forbidden: " | |||
+ partUri); | |||
} | |||
/** | |||
* Compare two part name following the rule M1.12 : | |||
* | |||
* Part name equivalence is determined by comparing part names as | |||
* case-insensitive ASCII strings. Packages shall not contain equivalent | |||
* part names and package implementers shall neither create nor recognize | |||
* packages with equivalent part names. [M1.12] | |||
*/ | |||
public int compareTo(PackagePartName otherPartName) { | |||
if (otherPartName == null) | |||
return -1; | |||
return this.partNameURI.toASCIIString().toLowerCase().compareTo( | |||
otherPartName.partNameURI.toASCIIString().toLowerCase()); | |||
} | |||
/** | |||
* Retrieves the extension of the part name if any. If there is no extension | |||
* returns an empty String. Example : '/document/content.xml' => 'xml' | |||
* | |||
* @return The extension of the part name. | |||
*/ | |||
public String getExtension() { | |||
String fragment = this.partNameURI.getPath(); | |||
if (fragment.length() > 0) { | |||
int i = fragment.lastIndexOf("."); | |||
if (i > -1) | |||
return fragment.substring(i + 1); | |||
} | |||
return ""; | |||
} | |||
/** | |||
* Get this part name. | |||
* | |||
* @return The name of this part name. | |||
*/ | |||
public String getName() { | |||
return this.partNameURI.toASCIIString(); | |||
} | |||
/** | |||
* Part name equivalence is determined by comparing part names as | |||
* case-insensitive ASCII strings. Packages shall not contain equivalent | |||
* part names and package implementers shall neither create nor recognize | |||
* packages with equivalent part names. [M1.12] | |||
*/ | |||
@Override | |||
public boolean equals(Object otherPartName) { | |||
if (otherPartName == null | |||
|| !(otherPartName instanceof PackagePartName)) | |||
return false; | |||
return this.partNameURI.toASCIIString().toLowerCase().equals( | |||
((PackagePartName) otherPartName).partNameURI.toASCIIString() | |||
.toLowerCase()); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return this.partNameURI.toASCIIString().toLowerCase().hashCode(); | |||
} | |||
@Override | |||
public String toString() { | |||
return getName(); | |||
} | |||
/* Getters and setters */ | |||
/** | |||
* Part name property getter. | |||
* | |||
* @return This part name URI. | |||
*/ | |||
public URI getURI() { | |||
return this.partNameURI; | |||
} | |||
} |
@@ -0,0 +1,227 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc; | |||
import java.util.Date; | |||
import org.apache.poi.openxml4j.util.Nullable; | |||
/** | |||
* Represents the core properties of an OPC package. | |||
* | |||
* @author Julien Chable | |||
* @version 1.0 | |||
* @see org.apache.poi.openxml4j.opc.Package | |||
*/ | |||
public interface PackageProperties { | |||
/** | |||
* Dublin Core Terms URI. | |||
*/ | |||
public final static String NAMESPACE_DCTERMS = "http://purl.org/dc/terms/"; | |||
/** | |||
* Dublin Core namespace URI. | |||
*/ | |||
public final static String NAMESPACE_DC = "http://purl.org/dc/elements/1.1/"; | |||
/* Getters and setters */ | |||
/** | |||
* Set the category of the content of this package. | |||
*/ | |||
public abstract Nullable<String> getCategoryProperty(); | |||
/** | |||
* Set the category of the content of this package. | |||
*/ | |||
public abstract void setCategoryProperty(String category); | |||
/** | |||
* Set the status of the content. | |||
*/ | |||
public abstract Nullable<String> getContentStatusProperty(); | |||
/** | |||
* Get the status of the content. | |||
*/ | |||
public abstract void setContentStatusProperty(String contentStatus); | |||
/** | |||
* Get the type of content represented, generally defined by a specific use | |||
* and intended audience. | |||
*/ | |||
public abstract Nullable<String> getContentTypeProperty(); | |||
/** | |||
* Set the type of content represented, generally defined by a specific use | |||
* and intended audience. | |||
*/ | |||
public abstract void setContentTypeProperty(String contentType); | |||
/** | |||
* Get the date of creation of the resource. | |||
*/ | |||
public abstract Nullable<Date> getCreatedProperty(); | |||
/** | |||
* Set the date of creation of the resource. | |||
*/ | |||
public abstract void setCreatedProperty(String created); | |||
/** | |||
* Set the date of creation of the resource. | |||
*/ | |||
public abstract void setCreatedProperty(Nullable<Date> created); | |||
/** | |||
* Get the entity primarily responsible for making the content of the | |||
* resource. | |||
*/ | |||
public abstract Nullable<String> getCreatorProperty(); | |||
/** | |||
* Set the entity primarily responsible for making the content of the | |||
* resource. | |||
*/ | |||
public abstract void setCreatorProperty(String creator); | |||
/** | |||
* Get the explanation of the content of the resource. | |||
*/ | |||
public abstract Nullable<String> getDescriptionProperty(); | |||
/** | |||
* Set the explanation of the content of the resource. | |||
*/ | |||
public abstract void setDescriptionProperty(String description); | |||
/** | |||
* Get an unambiguous reference to the resource within a given context. | |||
*/ | |||
public abstract Nullable<String> getIdentifierProperty(); | |||
/** | |||
* Set an unambiguous reference to the resource within a given context. | |||
*/ | |||
public abstract void setIdentifierProperty(String identifier); | |||
/** | |||
* Get a delimited set of keywords to support searching and indexing. This | |||
* is typically a list of terms that are not available elsewhere in the | |||
* properties | |||
*/ | |||
public abstract Nullable<String> getKeywordsProperty(); | |||
/** | |||
* Set a delimited set of keywords to support searching and indexing. This | |||
* is typically a list of terms that are not available elsewhere in the | |||
* properties | |||
*/ | |||
public abstract void setKeywordsProperty(String keywords); | |||
/** | |||
* Get the language of the intellectual content of the resource. | |||
*/ | |||
public abstract Nullable<String> getLanguageProperty(); | |||
/** | |||
* Set the language of the intellectual content of the resource. | |||
*/ | |||
public abstract void setLanguageProperty(String language); | |||
/** | |||
* Get the user who performed the last modification. | |||
*/ | |||
public abstract Nullable<String> getLastModifiedByProperty(); | |||
/** | |||
* Set the user who performed the last modification. | |||
*/ | |||
public abstract void setLastModifiedByProperty(String lastModifiedBy); | |||
/** | |||
* Get the date and time of the last printing. | |||
*/ | |||
public abstract Nullable<Date> getLastPrintedProperty(); | |||
/** | |||
* Set the date and time of the last printing. | |||
*/ | |||
public abstract void setLastPrintedProperty(String lastPrinted); | |||
/** | |||
* Set the date and time of the last printing. | |||
*/ | |||
public abstract void setLastPrintedProperty(Nullable<Date> lastPrinted); | |||
/** | |||
* Get the date on which the resource was changed. | |||
*/ | |||
public abstract Nullable<Date> getModifiedProperty(); | |||
/** | |||
* Set the date on which the resource was changed. | |||
*/ | |||
public abstract void setModifiedProperty(String modified); | |||
/** | |||
* Set the date on which the resource was changed. | |||
*/ | |||
public abstract void setModifiedProperty(Nullable<Date> modified); | |||
/** | |||
* Get the revision number. | |||
*/ | |||
public abstract Nullable<String> getRevisionProperty(); | |||
/** | |||
* Set the revision number. | |||
*/ | |||
public abstract void setRevisionProperty(String revision); | |||
/** | |||
* Get the topic of the content of the resource. | |||
*/ | |||
public abstract Nullable<String> getSubjectProperty(); | |||
/** | |||
* Set the topic of the content of the resource. | |||
*/ | |||
public abstract void setSubjectProperty(String subject); | |||
/** | |||
* Get the name given to the resource. | |||
*/ | |||
public abstract Nullable<String> getTitleProperty(); | |||
/** | |||
* Set the name given to the resource. | |||
*/ | |||
public abstract void setTitleProperty(String title); | |||
/** | |||
* Get the version number. | |||
*/ | |||
public abstract Nullable<String> getVersionProperty(); | |||
/** | |||
* Set the version number. | |||
*/ | |||
public abstract void setVersionProperty(String version); | |||
} |
@@ -0,0 +1,227 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc; | |||
import java.net.URI; | |||
import java.net.URISyntaxException; | |||
/** | |||
* A part relationship. | |||
* | |||
* @author Julien Chable | |||
* @version 1.0 | |||
*/ | |||
public final class PackageRelationship { | |||
private static URI containerRelationshipPart; | |||
static { | |||
try { | |||
containerRelationshipPart = new URI("/_rels/.rels"); | |||
} catch (URISyntaxException e) { | |||
// Do nothing | |||
} | |||
} | |||
/* XML markup */ | |||
public static final String ID_ATTRIBUTE_NAME = "Id"; | |||
public static final String RELATIONSHIPS_TAG_NAME = "Relationships"; | |||
public static final String RELATIONSHIP_TAG_NAME = "Relationship"; | |||
public static final String TARGET_ATTRIBUTE_NAME = "Target"; | |||
public static final String TARGET_MODE_ATTRIBUTE_NAME = "TargetMode"; | |||
public static final String TYPE_ATTRIBUTE_NAME = "Type"; | |||
/* End XML markup */ | |||
/** | |||
* L'ID de la relation. | |||
*/ | |||
private String id; | |||
/** | |||
* R�f�rence vers le package. | |||
*/ | |||
private Package container; | |||
/** | |||
* Type de relation. | |||
*/ | |||
private String relationshipType; | |||
/** | |||
* Partie source de cette relation. | |||
*/ | |||
private PackagePart source; | |||
/** | |||
* Le mode de ciblage [Internal|External] | |||
*/ | |||
private TargetMode targetMode; | |||
/** | |||
* URI de la partie cible. | |||
*/ | |||
private URI targetUri; | |||
/** | |||
* Constructor. | |||
* | |||
* @param packageParent | |||
* @param sourcePart | |||
* @param targetUri | |||
* @param targetMode | |||
* @param relationshipType | |||
* @param id | |||
*/ | |||
public PackageRelationship(Package pkg, PackagePart sourcePart, | |||
URI targetUri, TargetMode targetMode, String relationshipType, | |||
String id) { | |||
if (pkg == null) | |||
throw new IllegalArgumentException("pkg"); | |||
if (targetUri == null) | |||
throw new IllegalArgumentException("targetUri"); | |||
if (relationshipType == null) | |||
throw new IllegalArgumentException("relationshipType"); | |||
if (id == null) | |||
throw new IllegalArgumentException("id"); | |||
this.container = pkg; | |||
this.source = sourcePart; | |||
this.targetUri = targetUri; | |||
this.targetMode = targetMode; | |||
this.relationshipType = relationshipType; | |||
this.id = id; | |||
} | |||
@Override | |||
public boolean equals(Object obj) { | |||
if (!(obj instanceof PackageRelationship)) { | |||
return false; | |||
} | |||
PackageRelationship rel = (PackageRelationship) obj; | |||
return (this.id == rel.id | |||
&& this.relationshipType == rel.relationshipType | |||
&& (rel.source != null ? rel.source.equals(this.source) : true) | |||
&& this.targetMode == rel.targetMode && this.targetUri | |||
.equals(rel.targetUri)); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return this.id.hashCode() + this.relationshipType.hashCode() | |||
+ this.source.hashCode() + this.targetMode.hashCode() | |||
+ this.targetUri.hashCode(); | |||
} | |||
/* Getters */ | |||
public URI getContainerPartRelationship() { | |||
return containerRelationshipPart; | |||
} | |||
/** | |||
* @return the container | |||
*/ | |||
public Package getPackage() { | |||
return container; | |||
} | |||
/** | |||
* @return the id | |||
*/ | |||
public String getId() { | |||
return id; | |||
} | |||
/** | |||
* @return the relationshipType | |||
*/ | |||
public String getRelationshipType() { | |||
return relationshipType; | |||
} | |||
/** | |||
* @return the source | |||
*/ | |||
public PackagePart getSource() { | |||
return source; | |||
} | |||
/** | |||
* | |||
* @return | |||
*/ | |||
public URI getSourceURI() { | |||
if (source == null) { | |||
return PackagingURIHelper.PACKAGE_ROOT_URI; | |||
} | |||
return source.partName.getURI(); | |||
} | |||
/** | |||
* public URI getSourceUri(){ } | |||
* | |||
* @return the targetMode | |||
*/ | |||
public TargetMode getTargetMode() { | |||
return targetMode; | |||
} | |||
/** | |||
* @return the targetUri | |||
*/ | |||
public URI getTargetURI() { | |||
// If it's an external target, we don't | |||
// need to apply our normal validation rules | |||
if(targetMode == TargetMode.EXTERNAL) { | |||
return targetUri; | |||
} | |||
// Internal target | |||
// If it isn't absolute, resolve it relative | |||
// to ourselves | |||
if (!targetUri.toASCIIString().startsWith("/")) { | |||
// So it's a relative part name, try to resolve it | |||
return PackagingURIHelper.resolvePartUri(getSourceURI(), targetUri); | |||
} | |||
return targetUri; | |||
} | |||
@Override | |||
public String toString() { | |||
StringBuilder sb = new StringBuilder(); | |||
sb.append(id == null ? "id=null" : "id=" + id); | |||
sb.append(container == null ? " - container=null" : " - container=" | |||
+ container.toString()); | |||
sb.append(relationshipType == null ? " - relationshipType=null" | |||
: " - relationshipType=" + relationshipType.toString()); | |||
sb.append(source == null ? " - source=null" : " - source=" | |||
+ getSourceURI().toASCIIString()); | |||
sb.append(targetUri == null ? " - target=null" : " - target=" | |||
+ getTargetURI().toASCIIString()); | |||
sb.append(targetMode == null ? ",targetMode=null" : ",targetMode=" | |||
+ targetMode.toString()); | |||
return sb.toString(); | |||
} | |||
} |
@@ -0,0 +1,450 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc; | |||
import java.net.URI; | |||
import java.net.URISyntaxException; | |||
import java.util.ArrayList; | |||
import java.util.Iterator; | |||
import java.util.TreeMap; | |||
import org.apache.log4j.Logger; | |||
import org.dom4j.Attribute; | |||
import org.dom4j.Document; | |||
import org.dom4j.Element; | |||
import org.dom4j.io.SAXReader; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
import org.apache.poi.openxml4j.exceptions.InvalidOperationException; | |||
/** | |||
* Represents a collection of PackageRelationship elements that are owned by a | |||
* given PackagePart or the Package. | |||
* | |||
* @author Julien Chable, CDubettier | |||
* @version 0.1 | |||
*/ | |||
public final class PackageRelationshipCollection implements | |||
Iterable<PackageRelationship> { | |||
private static Logger logger = Logger.getLogger("org.openxml4j.opc"); | |||
/** | |||
* Package relationships ordered by ID. | |||
*/ | |||
private TreeMap<String, PackageRelationship> relationshipsByID; | |||
/** | |||
* Package relationships ordered by type. | |||
*/ | |||
private TreeMap<String, PackageRelationship> relationshipsByType; | |||
/** | |||
* This relationshipPart. | |||
*/ | |||
private PackagePart relationshipPart; | |||
/** | |||
* Source part. | |||
*/ | |||
private PackagePart sourcePart; | |||
/** | |||
* This part name. | |||
*/ | |||
private PackagePartName partName; | |||
/** | |||
* Reference to the package. | |||
*/ | |||
private Package container; | |||
/** | |||
* Constructor. | |||
*/ | |||
PackageRelationshipCollection() { | |||
relationshipsByID = new TreeMap<String, PackageRelationship>(); | |||
relationshipsByType = new TreeMap<String, PackageRelationship>(); | |||
} | |||
/** | |||
* Copy constructor. | |||
* | |||
* This collection will contain only elements from the specified collection | |||
* for which the type is compatible with the specified relationship type | |||
* filter. | |||
* | |||
* @param coll | |||
* Collection to import. | |||
* @param filter | |||
* Relationship type filter. | |||
*/ | |||
public PackageRelationshipCollection(PackageRelationshipCollection coll, | |||
String filter) { | |||
this(); | |||
for (PackageRelationship rel : coll.relationshipsByID.values()) { | |||
if (filter == null || rel.getRelationshipType().equals(filter)) | |||
addRelationship(rel); | |||
} | |||
} | |||
/** | |||
* Constructor. | |||
*/ | |||
public PackageRelationshipCollection(Package container) | |||
throws InvalidFormatException { | |||
this(container, null); | |||
} | |||
/** | |||
* Constructor. | |||
* | |||
* @throws InvalidFormatException | |||
* Throws if the format of the content part is invalid. | |||
* | |||
* @throws InvalidOperationException | |||
* Throws if the specified part is a relationship part. | |||
*/ | |||
public PackageRelationshipCollection(PackagePart part) | |||
throws InvalidFormatException { | |||
this(part.container, part); | |||
} | |||
/** | |||
* Constructor. Parse the existing package relationship part if one exists. | |||
* | |||
* @param container | |||
* The parent package. | |||
* @param part | |||
* The part that own this relationships collection. If <b>null</b> | |||
* then this part is considered as the package root. | |||
* @throws InvalidFormatException | |||
* If an error occurs during the parsing of the relatinships | |||
* part fo the specified part. | |||
*/ | |||
public PackageRelationshipCollection(Package container, PackagePart part) | |||
throws InvalidFormatException { | |||
this(); | |||
if (container == null) | |||
throw new IllegalArgumentException("container"); | |||
// Check if the specified part is not a relationship part | |||
if (part != null && part.isRelationshipPart()) | |||
throw new IllegalArgumentException("part"); | |||
this.container = container; | |||
this.sourcePart = part; | |||
this.partName = getRelationshipPartName(part); | |||
if ((container.getPackageAccess() != PackageAccess.WRITE) | |||
&& container.containPart(this.partName)) { | |||
relationshipPart = container.getPart(this.partName); | |||
parseRelationshipsPart(relationshipPart); | |||
} | |||
} | |||
/** | |||
* Get the relationship part name of the specified part. | |||
* | |||
* @param part | |||
* The part . | |||
* @return The relationship part name of the specified part. Be careful, | |||
* only the correct name is returned, this method does not check if | |||
* the part really exist in a package ! | |||
* @throws InvalidOperationException | |||
* Throws if the specified part is a relationship part. | |||
*/ | |||
private static PackagePartName getRelationshipPartName(PackagePart part) | |||
throws InvalidOperationException { | |||
PackagePartName partName; | |||
if (part == null) { | |||
partName = PackagingURIHelper.PACKAGE_ROOT_PART_NAME; | |||
} else { | |||
partName = part.getPartName(); | |||
} | |||
return PackagingURIHelper.getRelationshipPartName(partName); | |||
} | |||
/** | |||
* Add the specified relationship to the collection. | |||
* | |||
* @param relPart | |||
* The relationship to add. | |||
*/ | |||
public void addRelationship(PackageRelationship relPart) { | |||
relationshipsByID.put(relPart.getId(), relPart); | |||
relationshipsByType.put(relPart.getRelationshipType(), relPart); | |||
} | |||
/** | |||
* Add a relationship to the collection. | |||
* | |||
* @param targetUri | |||
* Target URI. | |||
* @param targetMode | |||
* The target mode : INTERNAL or EXTERNAL | |||
* @param relationshipType | |||
* Relationship type. | |||
* @param id | |||
* Relationship ID. | |||
* @return The newly created relationship. | |||
* @see PackageAccess | |||
*/ | |||
public PackageRelationship addRelationship(URI targetUri, | |||
TargetMode targetMode, String relationshipType, String id) { | |||
if (id == null) { | |||
// Generate a unique ID is id parameter is null. | |||
int i = 0; | |||
do { | |||
id = "rId" + ++i; | |||
} while (relationshipsByID.get(id) != null); | |||
} | |||
PackageRelationship rel = new PackageRelationship(container, | |||
sourcePart, targetUri, targetMode, relationshipType, id); | |||
relationshipsByID.put(rel.getId(), rel); | |||
relationshipsByType.put(rel.getRelationshipType(), rel); | |||
return rel; | |||
} | |||
/** | |||
* Remove a relationship by its ID. | |||
* | |||
* @param id | |||
* The relationship ID to remove. | |||
*/ | |||
public void removeRelationship(String id) { | |||
if (relationshipsByID != null && relationshipsByType != null) { | |||
PackageRelationship rel = relationshipsByID.get(id); | |||
if (rel != null) { | |||
relationshipsByID.remove(rel.getId()); | |||
relationshipsByType.values().remove(rel); | |||
} | |||
} | |||
} | |||
/** | |||
* Remove a relationship by its reference. | |||
* | |||
* @param rel | |||
* The relationship to delete. | |||
*/ | |||
public void removeRelationship(PackageRelationship rel) { | |||
if (rel == null) | |||
throw new IllegalArgumentException("rel"); | |||
relationshipsByID.values().remove(rel); | |||
relationshipsByType.values().remove(rel); | |||
} | |||
/** | |||
* Retrieves a relationship by its index in the collection. | |||
* | |||
* @param index | |||
* Must be a value between [0-relationships_count-1] | |||
*/ | |||
public PackageRelationship getRelationship(int index) { | |||
if (index < 0 || index > relationshipsByID.values().size()) | |||
throw new IllegalArgumentException("index"); | |||
PackageRelationship retRel = null; | |||
int i = 0; | |||
for (PackageRelationship rel : relationshipsByID.values()) { | |||
if (index == i++) | |||
return rel; | |||
} | |||
return retRel; | |||
} | |||
/** | |||
* Retrieves a package relationship based on its id. | |||
* | |||
* @param id | |||
* ID of the package relationship to retrieve. | |||
* @return The package relationship identified by the specified id. | |||
*/ | |||
public PackageRelationship getRelationshipByID(String id) { | |||
return relationshipsByID.get(id); | |||
} | |||
/** | |||
* Get the numbe rof relationships in the collection. | |||
*/ | |||
public int size() { | |||
return relationshipsByID.values().size(); | |||
} | |||
/** | |||
* Parse the relationship part and add all relationship in this collection. | |||
* | |||
* @param relPart | |||
* The package part to parse. | |||
* @throws InvalidFormatException | |||
* Throws if the relationship part is invalid. | |||
*/ | |||
private void parseRelationshipsPart(PackagePart relPart) | |||
throws InvalidFormatException { | |||
try { | |||
SAXReader reader = new SAXReader(); | |||
logger.debug("Parsing relationship: " + relPart.getPartName()); | |||
Document xmlRelationshipsDoc = reader | |||
.read(relPart.getInputStream()); | |||
// Browse default types | |||
Element root = xmlRelationshipsDoc.getRootElement(); | |||
// Check OPC compliance M4.1 rule | |||
boolean fCorePropertiesRelationship = false; | |||
for (Iterator i = root | |||
.elementIterator(PackageRelationship.RELATIONSHIP_TAG_NAME); i | |||
.hasNext();) { | |||
Element element = (Element) i.next(); | |||
// Relationship ID | |||
String id = element.attribute( | |||
PackageRelationship.ID_ATTRIBUTE_NAME).getValue(); | |||
// Relationship type | |||
String type = element.attribute( | |||
PackageRelationship.TYPE_ATTRIBUTE_NAME).getValue(); | |||
/* Check OPC Compliance */ | |||
// Check Rule M4.1 | |||
if (type.equals(PackageRelationshipTypes.CORE_PROPERTIES)) | |||
if (!fCorePropertiesRelationship) | |||
fCorePropertiesRelationship = true; | |||
else | |||
throw new InvalidFormatException( | |||
"OPC Compliance error [M4.1]: there is more than one core properties relationship in the package !"); | |||
/* End OPC Compliance */ | |||
// TargetMode (default value "Internal") | |||
Attribute targetModeAttr = element | |||
.attribute(PackageRelationship.TARGET_MODE_ATTRIBUTE_NAME); | |||
TargetMode targetMode = TargetMode.INTERNAL; | |||
if (targetModeAttr != null) { | |||
targetMode = targetModeAttr.getValue().toLowerCase() | |||
.equals("internal") ? TargetMode.INTERNAL | |||
: TargetMode.EXTERNAL; | |||
} | |||
// Target converted in URI | |||
URI target; | |||
String value = ""; | |||
try { | |||
value = element.attribute( | |||
PackageRelationship.TARGET_ATTRIBUTE_NAME) | |||
.getValue(); | |||
if (value.indexOf("\\") != -1) { | |||
logger | |||
.info("target contains \\ therefore not a valid URI" | |||
+ value + " replaced by /"); | |||
value = value.replaceAll("\\\\", "/"); | |||
// word can save external relationship with a \ instead | |||
// of / | |||
} | |||
target = new URI(value); | |||
} catch (URISyntaxException e) { | |||
logger.error("Cannot convert " + value | |||
+ " in a valid relationship URI-> ignored", e); | |||
continue; | |||
} | |||
addRelationship(target, targetMode, type, id); | |||
} | |||
} catch (Exception e) { | |||
logger.error(e); | |||
throw new InvalidFormatException(e.getMessage()); | |||
} | |||
} | |||
/** | |||
* Retrieves all relations with the specified type. | |||
* | |||
* @param typeFilter | |||
* Relationship type filter. If <b>null</b> then all | |||
* relationships are returned. | |||
* @return All relationships of the type specified by the filter. | |||
*/ | |||
public PackageRelationshipCollection getRelationships(String typeFilter) { | |||
PackageRelationshipCollection coll = new PackageRelationshipCollection( | |||
this, typeFilter); | |||
return coll; | |||
} | |||
/** | |||
* Get this collection's iterator. | |||
*/ | |||
public Iterator<PackageRelationship> iterator() { | |||
return relationshipsByID.values().iterator(); | |||
} | |||
/** | |||
* Get an iterator of a collection with all relationship with the specified | |||
* type. | |||
* | |||
* @param typeFilter | |||
* Type filter. | |||
* @return An iterator to a collection containing all relationships with the | |||
* specified type contain in this collection. | |||
*/ | |||
public Iterator<PackageRelationship> iterator(String typeFilter) { | |||
ArrayList<PackageRelationship> retArr = new ArrayList<PackageRelationship>(); | |||
for (PackageRelationship rel : relationshipsByID.values()) { | |||
if (rel.getRelationshipType().equals(typeFilter)) | |||
retArr.add(rel); | |||
} | |||
return retArr.iterator(); | |||
} | |||
/** | |||
* Clear all relationships. | |||
*/ | |||
public void clear() { | |||
relationshipsByID.clear(); | |||
relationshipsByType.clear(); | |||
} | |||
@Override | |||
public String toString() { | |||
String str; | |||
if (relationshipsByID == null) { | |||
str = "relationshipsByID=null"; | |||
} else { | |||
str = relationshipsByID.size() + " relationship(s) = ["; | |||
} | |||
if ((relationshipPart != null) && (relationshipPart.partName != null)) { | |||
str = str + "," + relationshipPart.partName; | |||
} else { | |||
str = str + ",relationshipPart=null"; | |||
} | |||
// Source of this relationship | |||
if ((sourcePart != null) && (sourcePart.partName != null)) { | |||
str = str + "," + sourcePart.partName; | |||
} else { | |||
str = str + ",sourcePart=null"; | |||
} | |||
if (partName != null) { | |||
str = str + "," + partName; | |||
} else { | |||
str = str + ",uri=null)"; | |||
} | |||
return str + "]"; | |||
} | |||
} |
@@ -0,0 +1,77 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc; | |||
/** | |||
* Relationship types. | |||
* | |||
* @author Julien Chable | |||
* @version 0.2 | |||
*/ | |||
public interface PackageRelationshipTypes { | |||
/** | |||
* Core properties relationship type. | |||
*/ | |||
String CORE_PROPERTIES = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"; | |||
/** | |||
* Digital signature relationship type. | |||
*/ | |||
String DIGITAL_SIGNATURE = "http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/signature"; | |||
/** | |||
* Digital signature certificate relationship type. | |||
*/ | |||
String DIGITAL_SIGNATURE_CERTIFICATE = "http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/certificate"; | |||
/** | |||
* Digital signature origin relationship type. | |||
*/ | |||
String DIGITAL_SIGNATURE_ORIGIN = "http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin"; | |||
/** | |||
* Thumbnail relationship type. | |||
*/ | |||
String THUMBNAIL = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"; | |||
/** | |||
* Extended properties relationship type. | |||
*/ | |||
String EXTENDED_PROPERTIES = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties"; | |||
/** | |||
* Core properties relationship type. | |||
*/ | |||
String CORE_DOCUMENT = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"; | |||
/** | |||
* Custom XML relationship type. | |||
*/ | |||
String CUSTOM_XML = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml"; | |||
/** | |||
* Image type. | |||
*/ | |||
String IMAGE_PART = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"; | |||
/** | |||
* Style type. | |||
*/ | |||
String STYLE_PART = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"; | |||
} |
@@ -0,0 +1,623 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc; | |||
import java.net.URI; | |||
import java.net.URISyntaxException; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
import org.apache.poi.openxml4j.exceptions.InvalidOperationException; | |||
/** | |||
* Helper for part and pack URI. | |||
* | |||
* @author Julien Chable, CDubet, Kim Ung | |||
* @version 0.1 | |||
*/ | |||
public final class PackagingURIHelper { | |||
/** | |||
* Package root URI. | |||
*/ | |||
private static URI packageRootUri; | |||
/** | |||
* Extension name of a relationship part. | |||
*/ | |||
public static final String RELATIONSHIP_PART_EXTENSION_NAME; | |||
/** | |||
* Segment name of a relationship part. | |||
*/ | |||
public static final String RELATIONSHIP_PART_SEGMENT_NAME; | |||
/** | |||
* Segment name of the package properties folder. | |||
*/ | |||
public static final String PACKAGE_PROPERTIES_SEGMENT_NAME; | |||
/** | |||
* Core package properties art name. | |||
*/ | |||
public static final String PACKAGE_CORE_PROPERTIES_NAME; | |||
/** | |||
* Forward slash URI separator. | |||
*/ | |||
public static final char FORWARD_SLASH_CHAR; | |||
/** | |||
* Forward slash URI separator. | |||
*/ | |||
public static final String FORWARD_SLASH_STRING; | |||
/** | |||
* Package relationships part URI | |||
*/ | |||
public static final URI PACKAGE_RELATIONSHIPS_ROOT_URI; | |||
/** | |||
* Package relationships part name. | |||
*/ | |||
public static final PackagePartName PACKAGE_RELATIONSHIPS_ROOT_PART_NAME; | |||
/** | |||
* Core properties part URI. | |||
*/ | |||
public static final URI CORE_PROPERTIES_URI; | |||
/** | |||
* Core properties partname. | |||
*/ | |||
public static final PackagePartName CORE_PROPERTIES_PART_NAME; | |||
/** | |||
* Root package URI. | |||
*/ | |||
public static final URI PACKAGE_ROOT_URI; | |||
/** | |||
* Root package part name. | |||
*/ | |||
public static final PackagePartName PACKAGE_ROOT_PART_NAME; | |||
/* Static initialization */ | |||
static { | |||
RELATIONSHIP_PART_SEGMENT_NAME = "_rels"; | |||
RELATIONSHIP_PART_EXTENSION_NAME = ".rels"; | |||
FORWARD_SLASH_CHAR = '/'; | |||
FORWARD_SLASH_STRING = "/"; | |||
PACKAGE_PROPERTIES_SEGMENT_NAME = "docProps"; | |||
PACKAGE_CORE_PROPERTIES_NAME = "core.xml"; | |||
// Make URI | |||
URI uriPACKAGE_ROOT_URI = null; | |||
URI uriPACKAGE_RELATIONSHIPS_ROOT_URI = null; | |||
URI uriPACKAGE_PROPERTIES_URI = null; | |||
try { | |||
uriPACKAGE_ROOT_URI = new URI("/"); | |||
uriPACKAGE_RELATIONSHIPS_ROOT_URI = new URI(FORWARD_SLASH_CHAR | |||
+ RELATIONSHIP_PART_SEGMENT_NAME + FORWARD_SLASH_CHAR | |||
+ RELATIONSHIP_PART_EXTENSION_NAME); | |||
packageRootUri = new URI("/"); | |||
uriPACKAGE_PROPERTIES_URI = new URI(FORWARD_SLASH_CHAR | |||
+ PACKAGE_PROPERTIES_SEGMENT_NAME + FORWARD_SLASH_CHAR | |||
+ PACKAGE_CORE_PROPERTIES_NAME); | |||
} catch (URISyntaxException e) { | |||
// Should never happen in production as all data are fixed | |||
} | |||
PACKAGE_ROOT_URI = uriPACKAGE_ROOT_URI; | |||
PACKAGE_RELATIONSHIPS_ROOT_URI = uriPACKAGE_RELATIONSHIPS_ROOT_URI; | |||
CORE_PROPERTIES_URI = uriPACKAGE_PROPERTIES_URI; | |||
// Make part name from previous URI | |||
PackagePartName tmpPACKAGE_ROOT_PART_NAME = null; | |||
PackagePartName tmpPACKAGE_RELATIONSHIPS_ROOT_PART_NAME = null; | |||
PackagePartName tmpCORE_PROPERTIES_URI = null; | |||
try { | |||
tmpPACKAGE_RELATIONSHIPS_ROOT_PART_NAME = createPartName(PACKAGE_RELATIONSHIPS_ROOT_URI); | |||
tmpCORE_PROPERTIES_URI = createPartName(CORE_PROPERTIES_URI); | |||
tmpPACKAGE_ROOT_PART_NAME = new PackagePartName(PACKAGE_ROOT_URI, | |||
false); | |||
} catch (InvalidFormatException e) { | |||
// Should never happen in production as all data are fixed | |||
} | |||
PACKAGE_RELATIONSHIPS_ROOT_PART_NAME = tmpPACKAGE_RELATIONSHIPS_ROOT_PART_NAME; | |||
CORE_PROPERTIES_PART_NAME = tmpCORE_PROPERTIES_URI; | |||
PACKAGE_ROOT_PART_NAME = tmpPACKAGE_ROOT_PART_NAME; | |||
} | |||
/** | |||
* Gets the URI for the package root. | |||
* | |||
* @return URI of the package root. | |||
*/ | |||
public static URI getPackageRootUri() { | |||
return packageRootUri; | |||
} | |||
/** | |||
* Know if the specified URI is a relationship part name. | |||
* | |||
* @param partUri | |||
* URI to check. | |||
* @return <i>true</i> if the URI <i>false</i>. | |||
*/ | |||
public static boolean isRelationshipPartURI(URI partUri) { | |||
if (partUri == null) | |||
throw new IllegalArgumentException("partUri"); | |||
return partUri.getPath().matches( | |||
".*" + RELATIONSHIP_PART_SEGMENT_NAME + ".*" | |||
+ RELATIONSHIP_PART_EXTENSION_NAME + "$"); | |||
} | |||
/** | |||
* Get file name from the specified URI. | |||
*/ | |||
public static String getFilename(URI uri) { | |||
if (uri != null) { | |||
String path = uri.getPath(); | |||
int len = path.length(); | |||
int num2 = len; | |||
while (--num2 >= 0) { | |||
char ch1 = path.charAt(num2); | |||
if (ch1 == PackagingURIHelper.FORWARD_SLASH_CHAR) | |||
return path.substring(num2 + 1, len); | |||
} | |||
} | |||
return ""; | |||
} | |||
/** | |||
* Get the file name without the trailing extension. | |||
*/ | |||
public static String getFilenameWithoutExtension(URI uri) { | |||
String filename = getFilename(uri); | |||
int dotIndex = filename.lastIndexOf("."); | |||
if (dotIndex == -1) | |||
return filename; | |||
return filename.substring(0, dotIndex); | |||
} | |||
/** | |||
* Get the directory path from the specified URI. | |||
*/ | |||
public static URI getPath(URI uri) { | |||
if (uri != null) { | |||
String path = uri.getPath(); | |||
int len = path.length(); | |||
int num2 = len; | |||
while (--num2 >= 0) { | |||
char ch1 = path.charAt(num2); | |||
if (ch1 == PackagingURIHelper.FORWARD_SLASH_CHAR) { | |||
try { | |||
return new URI(path.substring(0, num2)); | |||
} catch (URISyntaxException e) { | |||
return null; | |||
} | |||
} | |||
} | |||
} | |||
return null; | |||
} | |||
/** | |||
* Combine les deux URI. | |||
* | |||
* @param prefix | |||
* L'URI de pr�fixe. | |||
* @param suffix | |||
* L'URI de suffixe. | |||
* @return | |||
*/ | |||
public static URI combine(URI prefix, URI suffix) { | |||
URI retUri = null; | |||
try { | |||
retUri = new URI(combine(prefix.getPath(), suffix.getPath())); | |||
} catch (URISyntaxException e) { | |||
throw new IllegalArgumentException( | |||
"Prefix and suffix can't be combine !"); | |||
} | |||
return retUri; | |||
} | |||
/** | |||
* Combine a string URI with a prefix and a suffix. | |||
*/ | |||
public static String combine(String prefix, String suffix) { | |||
if (!prefix.endsWith("" + FORWARD_SLASH_CHAR) | |||
&& !suffix.startsWith("" + FORWARD_SLASH_CHAR)) | |||
return prefix + FORWARD_SLASH_CHAR + suffix; | |||
else if ((!prefix.endsWith("" + FORWARD_SLASH_CHAR) | |||
&& suffix.startsWith("" + FORWARD_SLASH_CHAR) || (prefix | |||
.endsWith("" + FORWARD_SLASH_CHAR) && !suffix.startsWith("" | |||
+ FORWARD_SLASH_CHAR)))) | |||
return prefix + suffix; | |||
else | |||
return ""; | |||
} | |||
/** | |||
* Fully relativize the source part URI against the target part URI. | |||
* | |||
* @param sourceURI | |||
* The source part URI. | |||
* @param targetURI | |||
* The target part URI. | |||
* @return A fully relativize part name URI ('word/media/image1.gif', | |||
* '/word/document.xml' => 'media/image1.gif') else | |||
* <code>null</code>. | |||
*/ | |||
public static URI relativizeURI(URI sourceURI, URI targetURI) { | |||
StringBuilder retVal = new StringBuilder(); | |||
String[] segmentsSource = sourceURI.getPath().split("/", -1); | |||
String[] segmentsTarget = targetURI.getPath().split("/", -1); | |||
// If the source URI is empty | |||
if (segmentsSource.length == 0) { | |||
throw new IllegalArgumentException( | |||
"Can't relativize an empty source URI !"); | |||
} | |||
// If target URI is empty | |||
if (segmentsTarget.length == 0) { | |||
throw new IllegalArgumentException( | |||
"Can't relativize an empty target URI !"); | |||
} | |||
// If the source is the root, then the relativized | |||
// form must actually be an absolute URI | |||
if(sourceURI.toString().equals("/")) { | |||
return targetURI; | |||
} | |||
// Relativize the source URI against the target URI. | |||
// First up, figure out how many steps along we can go | |||
// and still have them be the same | |||
int segmentsTheSame = 0; | |||
for (int i = 0; i < segmentsSource.length && i < segmentsTarget.length; i++) { | |||
if (segmentsSource[i].equals(segmentsTarget[i])) { | |||
// Match so far, good | |||
segmentsTheSame++; | |||
} else { | |||
break; | |||
} | |||
} | |||
// If we didn't have a good match or at least except a first empty element | |||
if ((segmentsTheSame == 0 || segmentsTheSame == 1) && | |||
segmentsSource[0].equals("") && segmentsTarget[0].equals("")) { | |||
for (int i = 0; i < segmentsSource.length - 2; i++) { | |||
retVal.append("../"); | |||
} | |||
for (int i = 0; i < segmentsTarget.length; i++) { | |||
if (segmentsTarget[i].equals("")) | |||
continue; | |||
retVal.append(segmentsTarget[i]); | |||
if (i != segmentsTarget.length - 1) | |||
retVal.append("/"); | |||
} | |||
try { | |||
return new URI(retVal.toString()); | |||
} catch (Exception e) { | |||
System.err.println(e); | |||
return null; | |||
} | |||
} | |||
// Special case for where the two are the same | |||
if (segmentsTheSame == segmentsSource.length | |||
&& segmentsTheSame == segmentsTarget.length) { | |||
retVal.append(""); | |||
} else { | |||
// Matched for so long, but no more | |||
// Do we need to go up a directory or two from | |||
// the source to get here? | |||
// (If it's all the way up, then don't bother!) | |||
if (segmentsTheSame == 1) { | |||
retVal.append("/"); | |||
} else { | |||
for (int j = segmentsTheSame; j < segmentsSource.length - 1; j++) { | |||
retVal.append("../"); | |||
} | |||
} | |||
// Now go from here on down | |||
for (int j = segmentsTheSame; j < segmentsTarget.length; j++) { | |||
if (retVal.length() > 0 | |||
&& retVal.charAt(retVal.length() - 1) != '/') { | |||
retVal.append("/"); | |||
} | |||
retVal.append(segmentsTarget[j]); | |||
} | |||
} | |||
try { | |||
return new URI(retVal.toString()); | |||
} catch (Exception e) { | |||
System.err.println(e); | |||
return null; | |||
} | |||
} | |||
/** | |||
* Resolve a source uri against a target. | |||
* | |||
* @param sourcePartUri | |||
* The source URI. | |||
* @param targetUri | |||
* The target URI. | |||
* @return The resolved URI. | |||
*/ | |||
public static URI resolvePartUri(URI sourcePartUri, URI targetUri) { | |||
if (sourcePartUri == null || sourcePartUri.isAbsolute()) { | |||
throw new IllegalArgumentException("sourcePartUri invalid - " | |||
+ sourcePartUri); | |||
} | |||
if (targetUri == null || targetUri.isAbsolute()) { | |||
throw new IllegalArgumentException("targetUri invalid - " | |||
+ targetUri); | |||
} | |||
return sourcePartUri.resolve(targetUri); | |||
} | |||
/** | |||
* Get URI from a string path. | |||
*/ | |||
public static URI getURIFromPath(String path) { | |||
URI retUri = null; | |||
try { | |||
retUri = new URI(path); | |||
} catch (URISyntaxException e) { | |||
throw new IllegalArgumentException("path"); | |||
} | |||
return retUri; | |||
} | |||
/** | |||
* Get the source part URI from a specified relationships part. | |||
* | |||
* @param relationshipPartUri | |||
* The relationship part use to retrieve the source part. | |||
* @return The source part URI from the specified relationships part. | |||
*/ | |||
public static URI getSourcePartUriFromRelationshipPartUri( | |||
URI relationshipPartUri) { | |||
if (relationshipPartUri == null) | |||
throw new IllegalArgumentException( | |||
"Le param�tre relationshipPartUri ne doit pas �tre null !"); | |||
if (!isRelationshipPartURI(relationshipPartUri)) | |||
throw new IllegalArgumentException( | |||
"L'URI ne doit pas �tre celle d'une partie de type relation."); | |||
if (relationshipPartUri.compareTo(PACKAGE_RELATIONSHIPS_ROOT_URI) == 0) | |||
return PACKAGE_ROOT_URI; | |||
String filename = relationshipPartUri.getPath(); | |||
String filenameWithoutExtension = getFilenameWithoutExtension(relationshipPartUri); | |||
filename = filename | |||
.substring(0, ((filename.length() - filenameWithoutExtension | |||
.length()) - RELATIONSHIP_PART_EXTENSION_NAME.length())); | |||
filename = filename.substring(0, filename.length() | |||
- RELATIONSHIP_PART_SEGMENT_NAME.length() - 1); | |||
filename = combine(filename, filenameWithoutExtension); | |||
return getURIFromPath(filename); | |||
} | |||
/** | |||
* Create an OPC compliant part name by throwing an exception if the URI is | |||
* not valid. | |||
* | |||
* @param partUri | |||
* The part name URI to validate. | |||
* @return A valid part name object, else <code>null</code>. | |||
* @throws InvalidFormatException | |||
* Throws if the specified URI is not OPC compliant. | |||
*/ | |||
public static PackagePartName createPartName(URI partUri) | |||
throws InvalidFormatException { | |||
if (partUri == null) | |||
throw new IllegalArgumentException("partName"); | |||
return new PackagePartName(partUri, true); | |||
} | |||
/** | |||
* Create an OPC compliant part name. | |||
* | |||
* @param partName | |||
* The part name to validate. | |||
* @return The correspondant part name if valid, else <code>null</code>. | |||
* @throws InvalidFormatException | |||
* Throws if the specified part name is not OPC compliant. | |||
* @see #createPartName(URI) | |||
*/ | |||
public static PackagePartName createPartName(String partName) | |||
throws InvalidFormatException { | |||
URI partNameURI; | |||
try { | |||
partNameURI = new URI(partName); | |||
} catch (URISyntaxException e) { | |||
throw new InvalidFormatException(e.getMessage()); | |||
} | |||
return createPartName(partNameURI); | |||
} | |||
/** | |||
* Create an OPC compliant part name by resolving it using a base part. | |||
* | |||
* @param partName | |||
* The part name to validate. | |||
* @param relativePart | |||
* The relative base part. | |||
* @return The correspondant part name if valid, else <code>null</code>. | |||
* @throws InvalidFormatException | |||
* Throws if the specified part name is not OPC compliant. | |||
* @see #createPartName(URI) | |||
*/ | |||
public static PackagePartName createPartName(String partName, | |||
PackagePart relativePart) throws InvalidFormatException { | |||
URI newPartNameURI; | |||
try { | |||
newPartNameURI = resolvePartUri( | |||
relativePart.getPartName().getURI(), new URI(partName)); | |||
} catch (URISyntaxException e) { | |||
throw new InvalidFormatException(e.getMessage()); | |||
} | |||
return createPartName(newPartNameURI); | |||
} | |||
/** | |||
* Create an OPC compliant part name by resolving it using a base part. | |||
* | |||
* @param partName | |||
* The part name URI to validate. | |||
* @param relativePart | |||
* The relative base part. | |||
* @return The correspondant part name if valid, else <code>null</code>. | |||
* @throws InvalidFormatException | |||
* Throws if the specified part name is not OPC compliant. | |||
* @see #createPartName(URI) | |||
*/ | |||
public static PackagePartName createPartName(URI partName, | |||
PackagePart relativePart) throws InvalidFormatException { | |||
URI newPartNameURI = resolvePartUri( | |||
relativePart.getPartName().getURI(), partName); | |||
return createPartName(newPartNameURI); | |||
} | |||
/** | |||
* Validate a part URI by returning a boolean. | |||
* ([M1.1],[M1.3],[M1.4],[M1.5],[M1.6]) | |||
* | |||
* (OPC Specifications 8.1.1 Part names) : | |||
* | |||
* Part Name Syntax | |||
* | |||
* The part name grammar is defined as follows: | |||
* | |||
* <i>part_name = 1*( "/" segment ) | |||
* | |||
* segment = 1*( pchar )</i> | |||
* | |||
* | |||
* (pchar is defined in RFC 3986) | |||
* | |||
* @param partUri | |||
* The URI to validate. | |||
* @return <b>true</b> if the URI is valid to the OPC Specifications, else | |||
* <b>false</b> | |||
* | |||
* @see #createPartName(URI) | |||
*/ | |||
public static boolean isValidPartName(URI partUri) { | |||
if (partUri == null) | |||
throw new IllegalArgumentException("partUri"); | |||
try { | |||
createPartName(partUri); | |||
return true; | |||
} catch (Exception e) { | |||
return false; | |||
} | |||
} | |||
/** | |||
* Decode a URI by converting all percent encoded character into a String | |||
* character. | |||
* | |||
* @param uri | |||
* The URI to decode. | |||
* @return The specified URI in a String with converted percent encoded | |||
* characters. | |||
*/ | |||
public static String decodeURI(URI uri) { | |||
StringBuffer retVal = new StringBuffer(); | |||
String uriStr = uri.toASCIIString(); | |||
char c; | |||
for (int i = 0; i < uriStr.length(); ++i) { | |||
c = uriStr.charAt(i); | |||
if (c == '%') { | |||
// We certainly found an encoded character, check for length | |||
// now ( '%' HEXDIGIT HEXDIGIT) | |||
if (((uriStr.length() - i) < 2)) { | |||
throw new IllegalArgumentException("The uri " + uriStr | |||
+ " contain invalid encoded character !"); | |||
} | |||
// Decode the encoded character | |||
char decodedChar = (char) Integer.parseInt(uriStr.substring( | |||
i + 1, i + 3), 16); | |||
retVal.append(decodedChar); | |||
i += 2; | |||
continue; | |||
} | |||
retVal.append(c); | |||
} | |||
return retVal.toString(); | |||
} | |||
/** | |||
* Build a part name where the relationship should be stored ((ex | |||
* /word/document.xml -> /word/_rels/document.xml.rels) | |||
* | |||
* @param partName | |||
* Source part URI | |||
* @return the full path (as URI) of the relation file | |||
* @throws InvalidOperationException | |||
* Throws if the specified URI is a relationshp part. | |||
*/ | |||
public static PackagePartName getRelationshipPartName( | |||
PackagePartName partName) { | |||
if (partName == null) | |||
throw new IllegalArgumentException("partName"); | |||
if (PackagingURIHelper.PACKAGE_ROOT_URI.getPath() == partName.getURI() | |||
.getPath()) | |||
return PackagingURIHelper.PACKAGE_RELATIONSHIPS_ROOT_PART_NAME; | |||
if (partName.isRelationshipPartURI()) | |||
throw new InvalidOperationException("Can't be a relationship part"); | |||
String fullPath = partName.getURI().getPath(); | |||
String filename = getFilename(partName.getURI()); | |||
fullPath = fullPath.substring(0, fullPath.length() - filename.length()); | |||
fullPath = combine(fullPath, | |||
PackagingURIHelper.RELATIONSHIP_PART_SEGMENT_NAME); | |||
fullPath = combine(fullPath, filename); | |||
fullPath = fullPath | |||
+ PackagingURIHelper.RELATIONSHIP_PART_EXTENSION_NAME; | |||
PackagePartName retPartName; | |||
try { | |||
retPartName = createPartName(fullPath); | |||
} catch (InvalidFormatException e) { | |||
// Should never happen in production as all data are fixed but in | |||
// case of return null: | |||
return null; | |||
} | |||
return retPartName; | |||
} | |||
} |
@@ -0,0 +1,166 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
import org.apache.poi.openxml4j.exceptions.InvalidOperationException; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
public interface RelationshipSource { | |||
/** | |||
* Add a relationship to a part (except relationships part). | |||
* | |||
* @param targetPartName | |||
* Name of the target part. This one must be relative to the | |||
* source root directory of the part. | |||
* @param targetMode | |||
* Mode [Internal|External]. | |||
* @param relationshipType | |||
* Type of relationship. | |||
* @return The newly created and added relationship | |||
*/ | |||
public abstract PackageRelationship addRelationship( | |||
PackagePartName targetPartName, TargetMode targetMode, | |||
String relationshipType); | |||
/** | |||
* Add a relationship to a part (except relationships part). | |||
* | |||
* Check rule M1.25: The Relationships part shall not have relationships to | |||
* any other part. Package implementers shall enforce this requirement upon | |||
* the attempt to create such a relationship and shall treat any such | |||
* relationship as invalid. | |||
* | |||
* @param targetPartName | |||
* Name of the target part. This one must be relative to the | |||
* source root directory of the part. | |||
* @param targetMode | |||
* Mode [Internal|External]. | |||
* @param relationshipType | |||
* Type of relationship. | |||
* @param id | |||
* Relationship unique id. | |||
* @return The newly created and added relationship | |||
* | |||
* @throws InvalidFormatException | |||
* If the URI point to a relationship part URI. | |||
*/ | |||
public abstract PackageRelationship addRelationship( | |||
PackagePartName targetPartName, TargetMode targetMode, | |||
String relationshipType, String id); | |||
/** | |||
* Adds an external relationship to a part | |||
* (except relationships part). | |||
* | |||
* The targets of external relationships are not | |||
* subject to the same validity checks that internal | |||
* ones are, as the contents is potentially | |||
* any file, URL or similar. | |||
* | |||
* @param target External target of the relationship | |||
* @param relationshipType Type of relationship. | |||
* @return The newly created and added relationship | |||
* @see org.apache.poi.openxml4j.opc.RelationshipSource#addExternalRelationship(java.lang.String, java.lang.String) | |||
*/ | |||
public PackageRelationship addExternalRelationship(String target, String relationshipType); | |||
/** | |||
* Adds an external relationship to a part | |||
* (except relationships part). | |||
* | |||
* The targets of external relationships are not | |||
* subject to the same validity checks that internal | |||
* ones are, as the contents is potentially | |||
* any file, URL or similar. | |||
* | |||
* @param target External target of the relationship | |||
* @param relationshipType Type of relationship. | |||
* @param id Relationship unique id. | |||
* @return The newly created and added relationship | |||
* @see org.apache.poi.openxml4j.opc.RelationshipSource#addExternalRelationship(java.lang.String, java.lang.String) | |||
*/ | |||
public PackageRelationship addExternalRelationship(String target, String relationshipType, String id); | |||
/** | |||
* Delete all the relationships attached to this. | |||
*/ | |||
public abstract void clearRelationships(); | |||
/** | |||
* Delete the relationship specified by its id. | |||
* | |||
* @param id | |||
* The ID identified the part to delete. | |||
*/ | |||
public abstract void removeRelationship(String id); | |||
/** | |||
* Retrieve all the relationships attached to this. | |||
* | |||
* @return This part's relationships. | |||
* @throws OpenXML4JException | |||
*/ | |||
public abstract PackageRelationshipCollection getRelationships() | |||
throws InvalidFormatException, OpenXML4JException; | |||
/** | |||
* Retrieves a package relationship from its id. | |||
* | |||
* @param id | |||
* ID of the package relationship to retrieve. | |||
* @return The package relationship | |||
*/ | |||
public abstract PackageRelationship getRelationship(String id); | |||
/** | |||
* Retrieve all relationships attached to this part which have the specified | |||
* type. | |||
* | |||
* @param relationshipType | |||
* Relationship type filter. | |||
* @return All relationships from this part that have the specified type. | |||
* @throws InvalidFormatException | |||
* If an error occurs while parsing the part. | |||
* @throws InvalidOperationException | |||
* If the package is open in write only mode. | |||
*/ | |||
public abstract PackageRelationshipCollection getRelationshipsByType( | |||
String relationshipType) throws InvalidFormatException, | |||
IllegalArgumentException, OpenXML4JException; | |||
/** | |||
* Knows if the part have any relationships. | |||
* | |||
* @return <b>true</b> if the part have at least one relationship else | |||
* <b>false</b>. | |||
*/ | |||
public abstract boolean hasRelationships(); | |||
/** | |||
* Checks if the specified relationship is part of this package part. | |||
* | |||
* @param rel | |||
* The relationship to check. | |||
* @return <b>true</b> if the specified relationship exists in this part, | |||
* else returns <b>false</b> | |||
*/ | |||
@SuppressWarnings("finally") | |||
public abstract boolean isRelationshipExists(PackageRelationship rel); | |||
} |
@@ -0,0 +1,77 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import org.dom4j.Document; | |||
import org.dom4j.io.OutputFormat; | |||
import org.dom4j.io.XMLWriter; | |||
public final class StreamHelper { | |||
private StreamHelper() { | |||
// Do nothing | |||
} | |||
/** | |||
* Turning the DOM4j object in the specified output stream. | |||
* | |||
* @param xmlContent | |||
* The XML document. | |||
* @param outStream | |||
* The OutputStream in which the XML document will be written. | |||
* @return <b>true</b> if the xml is successfully written in the stream, | |||
* else <b>false</b>. | |||
*/ | |||
public static boolean saveXmlInStream(Document xmlContent, | |||
OutputStream outStream) { | |||
try { | |||
OutputFormat outformat = OutputFormat.createPrettyPrint(); | |||
outformat.setEncoding("UTF-8"); | |||
XMLWriter writer = new XMLWriter(outStream, outformat); | |||
writer.write(xmlContent); | |||
} catch (Exception e) { | |||
return false; | |||
} | |||
return true; | |||
} | |||
/** | |||
* Copy the input stream into the output stream. | |||
* | |||
* @param inStream | |||
* The source stream. | |||
* @param outStream | |||
* The destination stream. | |||
* @return <b>true</b> if the operation succeed, else return <b>false</b>. | |||
*/ | |||
public static boolean copyStream(InputStream inStream, OutputStream outStream) { | |||
try { | |||
byte[] buffer = new byte[1024]; | |||
int bytesRead; | |||
while ((bytesRead = inStream.read(buffer)) >= 0) { | |||
outStream.write(buffer, 0, bytesRead); | |||
} | |||
} catch (Exception e) { | |||
return false; | |||
} | |||
return true; | |||
} | |||
} |
@@ -0,0 +1,32 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc; | |||
/** | |||
* Specifies whether the target of a PackageRelationship is inside or outside a | |||
* Package. | |||
* | |||
* @author Julien Chable | |||
* @version 1.0 | |||
*/ | |||
public enum TargetMode { | |||
/** The relationship references a resource that is external to the package. */ | |||
INTERNAL, | |||
/** The relationship references a part that is inside the package. */ | |||
EXTERNAL | |||
} |
@@ -0,0 +1,464 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import java.net.URI; | |||
import java.util.Enumeration; | |||
import java.util.zip.ZipEntry; | |||
import java.util.zip.ZipFile; | |||
import java.util.zip.ZipInputStream; | |||
import java.util.zip.ZipOutputStream; | |||
import org.apache.log4j.Logger; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
import org.apache.poi.openxml4j.exceptions.InvalidOperationException; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.internal.ContentTypeManager; | |||
import org.apache.poi.openxml4j.opc.internal.FileHelper; | |||
import org.apache.poi.openxml4j.opc.internal.MemoryPackagePart; | |||
import org.apache.poi.openxml4j.opc.internal.PartMarshaller; | |||
import org.apache.poi.openxml4j.opc.internal.ZipContentTypeManager; | |||
import org.apache.poi.openxml4j.opc.internal.ZipHelper; | |||
import org.apache.poi.openxml4j.opc.internal.marshallers.ZipPackagePropertiesMarshaller; | |||
import org.apache.poi.openxml4j.opc.internal.marshallers.ZipPartMarshaller; | |||
import org.apache.poi.openxml4j.util.ZipEntrySource; | |||
import org.apache.poi.openxml4j.util.ZipFileZipEntrySource; | |||
import org.apache.poi.openxml4j.util.ZipInputStreamZipEntrySource; | |||
/** | |||
* Physical zip package. | |||
* | |||
* @author Julien Chable | |||
* @version 0.2 | |||
*/ | |||
public final class ZipPackage extends Package { | |||
private static Logger logger = Logger.getLogger("org.openxml4j"); | |||
/** | |||
* Zip archive, as either a file on disk, | |||
* or a stream | |||
*/ | |||
private final ZipEntrySource zipArchive; | |||
/** | |||
* Constructor. Creates a new ZipPackage. | |||
*/ | |||
public ZipPackage() { | |||
super(defaultPackageAccess); | |||
this.zipArchive = null; | |||
} | |||
/** | |||
* Constructor. <b>Operation not supported.</b> | |||
* | |||
* @param in | |||
* Zip input stream to load. | |||
* @param access | |||
* @throws IllegalArgumentException | |||
* If the specified input stream not an instance of | |||
* ZipInputStream. | |||
*/ | |||
ZipPackage(InputStream in, PackageAccess access) throws IOException { | |||
super(access); | |||
this.zipArchive = new ZipInputStreamZipEntrySource( | |||
new ZipInputStream(in) | |||
); | |||
} | |||
/** | |||
* Constructor. Opens a Zip based Open XML document. | |||
* | |||
* @param path | |||
* The path of the file to open or create. | |||
* @param access | |||
* The package access mode. | |||
* @throws InvalidFormatException | |||
* If the content type part parsing encounters an error. | |||
*/ | |||
ZipPackage(String path, PackageAccess access) throws InvalidFormatException { | |||
super(access); | |||
ZipFile zipFile = ZipHelper.openZipFile(path); | |||
if (zipFile == null) | |||
throw new InvalidOperationException( | |||
"Can't open the specified file: '" + path + "'"); | |||
this.zipArchive = new ZipFileZipEntrySource(zipFile); | |||
} | |||
/** | |||
* Retrieves the parts from this package. We assume that the package has not | |||
* been yet inspect to retrieve all the parts, this method will open the | |||
* archive and look for all parts contain inside it. If the package part | |||
* list is not empty, it will be emptied. | |||
* | |||
* @return All parts contain in this package. | |||
* @throws InvalidFormatException | |||
* Throws if the package is not valid. | |||
*/ | |||
@Override | |||
protected PackagePart[] getPartsImpl() throws InvalidFormatException { | |||
if (this.partList == null) { | |||
// The package has just been created, we create an empty part | |||
// list. | |||
this.partList = new PackagePartCollection(); | |||
} | |||
if (this.zipArchive == null) { | |||
return this.partList.values().toArray( | |||
new PackagePart[this.partList.values().size()]); | |||
} else { | |||
// First we need to parse the content type part | |||
Enumeration<? extends ZipEntry> entries = this.zipArchive.getEntries(); | |||
while (entries.hasMoreElements()) { | |||
ZipEntry entry = entries.nextElement(); | |||
if (entry.getName().equals( | |||
ContentTypeManager.CONTENT_TYPES_PART_NAME)) { | |||
try { | |||
this.contentTypeManager = new ZipContentTypeManager( | |||
getZipArchive().getInputStream(entry), this); | |||
} catch (IOException e) { | |||
throw new InvalidFormatException(e.getMessage()); | |||
} | |||
break; | |||
} | |||
} | |||
// At this point, we should have loaded the content type part | |||
if (this.contentTypeManager == null) { | |||
throw new InvalidFormatException( | |||
"Package should contain a content type part [M1.13]"); | |||
} | |||
// Now create all the relationships | |||
// (Need to create relationships before other | |||
// parts, otherwise we might create a part before | |||
// its relationship exists, and then it won't tie up) | |||
entries = this.zipArchive.getEntries(); | |||
while (entries.hasMoreElements()) { | |||
ZipEntry entry = (ZipEntry) entries.nextElement(); | |||
PackagePartName partName = buildPartName(entry); | |||
if(partName == null) continue; | |||
// Only proceed for Relationships at this stage | |||
String contentType = contentTypeManager.getContentType(partName); | |||
if (contentType != null && contentType.equals(ContentTypes.RELATIONSHIPS_PART)) { | |||
try { | |||
partList.put(partName, new ZipPackagePart(this, entry, | |||
partName, contentType)); | |||
} catch (InvalidOperationException e) { | |||
throw new InvalidFormatException(e.getMessage()); | |||
} | |||
} | |||
} | |||
// Then we can go through all the other parts | |||
entries = this.zipArchive.getEntries(); | |||
while (entries.hasMoreElements()) { | |||
ZipEntry entry = (ZipEntry) entries.nextElement(); | |||
PackagePartName partName = buildPartName(entry); | |||
if(partName == null) continue; | |||
String contentType = contentTypeManager | |||
.getContentType(partName); | |||
if (contentType != null && contentType.equals(ContentTypes.RELATIONSHIPS_PART)) { | |||
// Already handled | |||
} | |||
else if (contentType != null) { | |||
try { | |||
partList.put(partName, new ZipPackagePart(this, entry, | |||
partName, contentType)); | |||
} catch (InvalidOperationException e) { | |||
throw new InvalidFormatException(e.getMessage()); | |||
} | |||
} else { | |||
throw new InvalidFormatException( | |||
"The part " | |||
+ partName.getURI().getPath() | |||
+ " does not have any content type ! Rule: Package require content types when retrieving a part from a package. [M.1.14]"); | |||
} | |||
} | |||
return (ZipPackagePart[]) partList.values().toArray( | |||
new ZipPackagePart[partList.size()]); | |||
} | |||
} | |||
/** | |||
* Builds a PackagePartName for the given ZipEntry, | |||
* or null if it's the content types / invalid part | |||
*/ | |||
private PackagePartName buildPartName(ZipEntry entry) { | |||
try { | |||
// We get an error when we parse [Content_Types].xml | |||
// because it's not a valid URI. | |||
if (entry.getName().equals( | |||
ContentTypeManager.CONTENT_TYPES_PART_NAME)) { | |||
return null; | |||
} else { | |||
return PackagingURIHelper.createPartName(ZipHelper | |||
.getOPCNameFromZipItemName(entry.getName())); | |||
} | |||
} catch (Exception e) { | |||
// We assume we can continue, even in degraded mode ... | |||
logger.warn("Entry " | |||
+ entry.getName() | |||
+ " is not valid, so this part won't be add to the package."); | |||
return null; | |||
} | |||
} | |||
/** | |||
* Create a new MemoryPackagePart from the specified URI and content type | |||
* | |||
* | |||
* aram partName The part URI. | |||
* | |||
* @param contentType | |||
* The part content type. | |||
* @return The newly created zip package part, else <b>null</b>. | |||
*/ | |||
@Override | |||
protected PackagePart createPartImpl(PackagePartName partName, | |||
String contentType, boolean loadRelationships) { | |||
if (contentType == null) | |||
throw new IllegalArgumentException("contentType"); | |||
if (partName == null) | |||
throw new IllegalArgumentException("partName"); | |||
try { | |||
return new MemoryPackagePart(this, partName, contentType, | |||
loadRelationships); | |||
} catch (InvalidFormatException e) { | |||
System.err.println(e); | |||
return null; | |||
} | |||
} | |||
/** | |||
* Delete a part from the package | |||
* | |||
* @throws IllegalArgumentException | |||
* Throws if the part URI is nulll or invalid. | |||
*/ | |||
@Override | |||
protected void removePartImpl(PackagePartName partName) { | |||
if (partName == null) | |||
throw new IllegalArgumentException("partUri"); | |||
} | |||
/** | |||
* Flush the package. Do nothing. | |||
*/ | |||
@Override | |||
protected void flushImpl() { | |||
// Do nothing | |||
} | |||
/** | |||
* Close and save the package. | |||
* | |||
* @see #close() | |||
*/ | |||
@Override | |||
protected void closeImpl() throws IOException { | |||
// Flush the package | |||
flush(); | |||
// Save the content | |||
if (this.originalPackagePath != null | |||
&& !"".equals(this.originalPackagePath)) { | |||
File targetFile = new File(this.originalPackagePath); | |||
if (targetFile.exists()) { | |||
// Case of a package previously open | |||
File tempFile = File.createTempFile( | |||
generateTempFileName(FileHelper | |||
.getDirectory(targetFile)), ".tmp"); | |||
// Save the final package to a temporary file | |||
try { | |||
save(tempFile); | |||
this.zipArchive.close(); // Close the zip archive to be | |||
// able to delete it | |||
FileHelper.copyFile(tempFile, targetFile); | |||
} finally { | |||
// Either the save operation succeed or not, we delete the | |||
// temporary file | |||
if (!tempFile.delete()) { | |||
logger | |||
.warn("The temporary file: '" | |||
+ targetFile.getAbsolutePath() | |||
+ "' cannot be deleted ! Make sure that no other application use it."); | |||
} | |||
} | |||
} else { | |||
throw new InvalidOperationException( | |||
"Can't close a package not previously open with the open() method !"); | |||
} | |||
} | |||
} | |||
/** | |||
* Create a unique identifier to be use as a temp file name. | |||
* | |||
* @return A unique identifier use to be use as a temp file name. | |||
*/ | |||
private synchronized String generateTempFileName(File directory) { | |||
File tmpFilename; | |||
do { | |||
tmpFilename = new File(directory.getAbsoluteFile() + File.separator | |||
+ "OpenXML4J" + System.nanoTime()); | |||
} while (tmpFilename.exists()); | |||
return FileHelper.getFilename(tmpFilename.getAbsoluteFile()); | |||
} | |||
/** | |||
* Close the package without saving the document. Discard all the changes | |||
* made to this package. | |||
*/ | |||
@Override | |||
protected void revertImpl() { | |||
try { | |||
if (this.zipArchive != null) | |||
this.zipArchive.close(); | |||
} catch (IOException e) { | |||
// Do nothing, user dont have to know | |||
} | |||
} | |||
/** | |||
* Implement the getPart() method to retrieve a part from its URI in the | |||
* current package | |||
* | |||
* | |||
* @see #getPart(URI) | |||
*/ | |||
@Override | |||
protected PackagePart getPartImpl(PackagePartName partName) { | |||
if (partList.containsKey(partName)) { | |||
return partList.get(partName); | |||
} | |||
return null; | |||
} | |||
/** | |||
* Save this package into the specified stream | |||
* | |||
* | |||
* @param outputStream | |||
* The stream use to save this package. | |||
* | |||
* @see #save(OutputStream) | |||
* @see #saveInZip(ZipOutputStream) | |||
*/ | |||
@Override | |||
public void saveImpl(OutputStream outputStream) { | |||
// Check that the document was open in write mode | |||
throwExceptionIfReadOnly(); | |||
ZipOutputStream zos = null; | |||
try { | |||
if (!(outputStream instanceof ZipOutputStream)) | |||
zos = new ZipOutputStream(outputStream); | |||
else | |||
zos = (ZipOutputStream) outputStream; | |||
// If the core properties part does not exist in the part list, | |||
// we save it as well | |||
if (this.getPartsByRelationshipType( | |||
PackageRelationshipTypes.CORE_PROPERTIES).size() == 0) { | |||
logger.debug("Save core properties part"); | |||
// We have to save the core properties part ... | |||
new ZipPackagePropertiesMarshaller().marshall( | |||
this.packageProperties, zos); | |||
// ... and to add its relationship ... | |||
this.relationships.addRelationship(this.packageProperties | |||
.getPartName().getURI(), TargetMode.INTERNAL, | |||
PackageRelationshipTypes.CORE_PROPERTIES, null); | |||
// ... and the content if it has not been added yet. | |||
if (!this.contentTypeManager | |||
.isContentTypeRegister(ContentTypes.CORE_PROPERTIES_PART)) { | |||
this.contentTypeManager.addContentType( | |||
this.packageProperties.getPartName(), | |||
ContentTypes.CORE_PROPERTIES_PART); | |||
} | |||
} | |||
// Save package relationships part. | |||
logger.debug("Save package relationships"); | |||
ZipPartMarshaller.marshallRelationshipPart(this.getRelationships(), | |||
PackagingURIHelper.PACKAGE_RELATIONSHIPS_ROOT_PART_NAME, | |||
zos); | |||
// Save content type part. | |||
logger.debug("Save content types part"); | |||
this.contentTypeManager.save(zos); | |||
// Save parts. | |||
for (PackagePart part : getParts()) { | |||
// If the part is a relationship part, we don't save it, it's | |||
// the source part that will do the job. | |||
if (part.isRelationshipPart()) | |||
continue; | |||
logger.debug("Save part '" | |||
+ ZipHelper.getZipItemNameFromOPCName(part | |||
.getPartName().getName()) + "'"); | |||
PartMarshaller marshaller = partMarshallers | |||
.get(part.contentType); | |||
if (marshaller != null) { | |||
if (!marshaller.marshall(part, zos)) { | |||
throw new OpenXML4JException( | |||
"The part " | |||
+ part.getPartName().getURI() | |||
+ " fail to be saved in the stream with marshaller " | |||
+ marshaller); | |||
} | |||
} else { | |||
if (!defaultPartMarshaller.marshall(part, zos)) | |||
throw new OpenXML4JException( | |||
"The part " | |||
+ part.getPartName().getURI() | |||
+ " fail to be saved in the stream with marshaller " | |||
+ defaultPartMarshaller); | |||
} | |||
} | |||
zos.close(); | |||
} catch (Exception e) { | |||
logger | |||
.error("Fail to save: an error occurs while saving the package : " | |||
+ e.getMessage()); | |||
} | |||
} | |||
/** | |||
* Get the zip archive | |||
* | |||
* @return The zip archive. | |||
*/ | |||
public ZipEntrySource getZipArchive() { | |||
return zipArchive; | |||
} | |||
} |
@@ -0,0 +1,135 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import java.util.zip.ZipEntry; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
import org.apache.poi.openxml4j.exceptions.InvalidOperationException; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.internal.marshallers.ZipPartMarshaller; | |||
/** | |||
* Zip implementation of a PackagePart. | |||
* | |||
* @author Julien Chable | |||
* @version 1.0 | |||
* @see PackagePart | |||
*/ | |||
public class ZipPackagePart extends PackagePart { | |||
/** | |||
* The zip entry corresponding to this part. | |||
*/ | |||
private ZipEntry zipEntry; | |||
/** | |||
* Constructor. | |||
* | |||
* @param container | |||
* The container package. | |||
* @param partName | |||
* Part name. | |||
* @param contentType | |||
* Content type. | |||
* @throws InvalidFormatException | |||
* Throws if the content of this part invalid. | |||
*/ | |||
public ZipPackagePart(Package container, PackagePartName partName, | |||
String contentType) throws InvalidFormatException { | |||
super(container, partName, contentType); | |||
} | |||
/** | |||
* Constructor. | |||
* | |||
* @param container | |||
* The container package. | |||
* @param zipEntry | |||
* The zip entry corresponding to this part. | |||
* @param partName | |||
* The part name. | |||
* @param contentType | |||
* Content type. | |||
* @throws InvalidFormatException | |||
* Throws if the content of this part is invalid. | |||
*/ | |||
public ZipPackagePart(Package container, ZipEntry zipEntry, | |||
PackagePartName partName, String contentType) | |||
throws InvalidFormatException { | |||
super(container, partName, contentType); | |||
this.zipEntry = zipEntry; | |||
} | |||
/** | |||
* Get the zip entry of this part. | |||
* | |||
* @return The zip entry in the zip structure coresponding to this part. | |||
*/ | |||
public ZipEntry getZipArchive() { | |||
return zipEntry; | |||
} | |||
/** | |||
* Implementation of the getInputStream() which return the inputStream of | |||
* this part zip entry. | |||
* | |||
* @return Input stream of this part zip entry. | |||
*/ | |||
@Override | |||
protected InputStream getInputStreamImpl() throws IOException { | |||
// We use the getInputStream() method from java.util.zip.ZipFile | |||
// class which return an InputStream to this part zip entry. | |||
return ((ZipPackage) container).getZipArchive() | |||
.getInputStream(zipEntry); | |||
} | |||
/** | |||
* Implementation of the getOutputStream(). Return <b>null</b>. Normally | |||
* will never be called since the MemoryPackage is use instead. | |||
* | |||
* @return <b>null</b> | |||
*/ | |||
@Override | |||
protected OutputStream getOutputStreamImpl() { | |||
return null; | |||
} | |||
@Override | |||
public boolean save(OutputStream os) throws OpenXML4JException { | |||
return new ZipPartMarshaller().marshall(this, os); | |||
} | |||
@Override | |||
public boolean load(InputStream ios) throws InvalidFormatException { | |||
throw new InvalidOperationException("Method not implemented !"); | |||
} | |||
@Override | |||
public void close() { | |||
throw new InvalidOperationException("Method not implemented !"); | |||
} | |||
@Override | |||
public void flush() { | |||
throw new InvalidOperationException("Method not implemented !"); | |||
} | |||
} |
@@ -0,0 +1,224 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc.internal; | |||
import java.io.UnsupportedEncodingException; | |||
import java.util.Hashtable; | |||
import java.util.regex.Matcher; | |||
import java.util.regex.Pattern; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
/** | |||
* Represents a immutable MIME ContentType value (RFC 2616 �3.7) | |||
* | |||
* media-type = type "/" subtype *( ";" parameter ) type = token<br> | |||
* subtype = token<br> | |||
* | |||
* Rule M1.13 : Package implementers shall only create and only recognize parts | |||
* with a content type; format designers shall specify a content type for each | |||
* part included in the format. Content types for package parts shall fit the | |||
* definition and syntax for media types as specified in RFC 2616,��3.7. | |||
* | |||
* Rule M1.14: Content types shall not use linear white space either between the | |||
* type and subtype or between an attribute and its value. Content types also | |||
* shall not have leading or trailing white spaces. Package implementers shall | |||
* create only such content types and shall require such content types when | |||
* retrieving a part from a package; format designers shall specify only such | |||
* content types for inclusion in the format. | |||
* | |||
* @author Julien Chable | |||
* @version 0.1 | |||
* | |||
* @see http://www.ietf.org/rfc/rfc2045.txt | |||
* @see http://www.ietf.org/rfc/rfc2616.txt | |||
*/ | |||
public final class ContentType { | |||
/** | |||
* Type in Type/Subtype. | |||
*/ | |||
private String type; | |||
/** | |||
* Subtype | |||
*/ | |||
private String subType; | |||
/** | |||
* Parameters | |||
*/ | |||
private Hashtable<String, String> parameters; | |||
/** | |||
* Media type compiled pattern for parameters. | |||
*/ | |||
private final static Pattern patternMediaType; | |||
static { | |||
/* | |||
* token = 1*<any CHAR except CTLs or separators> | |||
* | |||
* separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | | |||
* <"> | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT | |||
* | |||
* CTL = <any US-ASCII control character (octets 0 - 31) and DEL (127)> | |||
* | |||
* CHAR = <any US-ASCII character (octets 0 - 127)> | |||
*/ | |||
String token = "[\\x21-\\x7E&&[^\\(\\)<>@,;:\\\\/\"\\[\\]\\?={}\\x20\\x09]]"; | |||
/* | |||
* parameter = attribute "=" value | |||
* | |||
* attribute = token | |||
* | |||
* value = token | quoted-string | |||
*/ | |||
// Keep for future use with parameter: | |||
// String parameter = "(" + token + "+)=(\"?" + token + "+\"?)"; | |||
/* | |||
* Pattern for media type. | |||
* | |||
* Don't allow comment, rule M1.15: The package implementer shall | |||
* require a content type that does not include comments and the format | |||
* designer shall specify such a content type. | |||
* | |||
* comment = "(" *( ctext | quoted-pair | comment ) ")" | |||
* | |||
* ctext = <any TEXT excluding "(" and ")"> | |||
* | |||
* TEXT = <any OCTET except CTLs, but including LWS> | |||
* | |||
* LWS = [CRLF] 1*( SP | HT ) | |||
* | |||
* CR = <US-ASCII CR, carriage return (13)> | |||
* | |||
* LF = <US-ASCII LF, linefeed (10)> | |||
* | |||
* SP = <US-ASCII SP, space (32)> | |||
* | |||
* HT = <US-ASCII HT, horizontal-tab (9)> | |||
* | |||
* quoted-pair = "\" CHAR | |||
*/ | |||
// Keep for future use with parameter: | |||
// patternMediaType = Pattern.compile("^(" + token + "+)/(" + token | |||
// + "+)(;" + parameter + ")*$"); | |||
patternMediaType = Pattern.compile("^(" + token + "+)/(" + token | |||
+ "+)$"); | |||
} | |||
/** | |||
* Constructor. Check the input with the RFC 2616 grammar. | |||
* | |||
* @param contentType | |||
* The content type to store. | |||
* @throws InvalidFormatException | |||
* If the specified content type is not valid with RFC 2616. | |||
*/ | |||
public ContentType(String contentType) throws InvalidFormatException { | |||
// Conversion en US-ASCII | |||
String contentTypeASCII = null; | |||
try { | |||
contentTypeASCII = new String(contentType.getBytes(), "US-ASCII"); | |||
} catch (UnsupportedEncodingException e) { | |||
throw new InvalidFormatException( | |||
"The specified content type is not an ASCII value."); | |||
} | |||
Matcher mMediaType = patternMediaType.matcher(contentTypeASCII); | |||
if (!mMediaType.matches()) | |||
throw new InvalidFormatException( | |||
"The specified content type '" | |||
+ contentType | |||
+ "' is not compliant with RFC 2616: malformed content type."); | |||
// Type/subtype | |||
if (mMediaType.groupCount() >= 2) { | |||
this.type = mMediaType.group(1); | |||
this.subType = mMediaType.group(2); | |||
// Parameters | |||
this.parameters = new Hashtable<String, String>(1); | |||
for (int i = 4; i <= mMediaType.groupCount() | |||
&& (mMediaType.group(i) != null); i += 2) { | |||
this.parameters.put(mMediaType.group(i), mMediaType | |||
.group(i + 1)); | |||
} | |||
} | |||
} | |||
@Override | |||
public final String toString() { | |||
StringBuffer retVal = new StringBuffer(); | |||
retVal.append(this.getType()); | |||
retVal.append("/"); | |||
retVal.append(this.getSubType()); | |||
// Keep for future implementation if needed | |||
// for (String key : parameters.keySet()) { | |||
// retVal.append(";"); | |||
// retVal.append(key); | |||
// retVal.append("="); | |||
// retVal.append(parameters.get(key)); | |||
// } | |||
return retVal.toString(); | |||
} | |||
@Override | |||
public boolean equals(Object obj) { | |||
return (!(obj instanceof ContentType)) | |||
|| (this.toString().equalsIgnoreCase(obj.toString())); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return this.toString().hashCode(); | |||
} | |||
/* Getters */ | |||
/** | |||
* Get the subtype. | |||
* | |||
* @return The subtype of this content type. | |||
*/ | |||
public String getSubType() { | |||
return this.subType; | |||
} | |||
/** | |||
* Get the type. | |||
* | |||
* @return The type of this content type. | |||
*/ | |||
public String getType() { | |||
return this.type; | |||
} | |||
/** | |||
* Gets the value associated to the specified key. | |||
* | |||
* @param key | |||
* The key of the key/value pair. | |||
* @return The value associated to the specified key. | |||
*/ | |||
public String getParameters(String key) { | |||
return parameters.get(key); | |||
} | |||
} |
@@ -0,0 +1,498 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc.internal; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import java.net.URI; | |||
import java.net.URISyntaxException; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.TreeMap; | |||
import java.util.Map.Entry; | |||
import java.util.zip.ZipOutputStream; | |||
import org.apache.log4j.Logger; | |||
import org.dom4j.Document; | |||
import org.dom4j.DocumentException; | |||
import org.dom4j.DocumentHelper; | |||
import org.dom4j.Element; | |||
import org.dom4j.Namespace; | |||
import org.dom4j.QName; | |||
import org.dom4j.io.SAXReader; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
import org.apache.poi.openxml4j.exceptions.InvalidOperationException; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException; | |||
import org.apache.poi.openxml4j.opc.Package; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.PackagePartName; | |||
import org.apache.poi.openxml4j.opc.PackagingURIHelper; | |||
/** | |||
* Manage package content types ([Content_Types].xml part). | |||
* | |||
* @author Julien Chable | |||
* @version 1.0 | |||
*/ | |||
public abstract class ContentTypeManager { | |||
protected static Logger logger = Logger.getLogger("org.openxml4j"); | |||
/** | |||
* Reference to the package using this content type manager. | |||
*/ | |||
protected Package container; | |||
/** | |||
* Content type part name. | |||
*/ | |||
public static final String CONTENT_TYPES_PART_NAME = "[Content_Types].xml"; | |||
/** | |||
* Content type namespace | |||
*/ | |||
public static final String TYPES_NAMESPACE_URI = "http://schemas.openxmlformats.org/package/2006/content-types"; | |||
/* Xml elements in content type part */ | |||
private static final String TYPES_TAG_NAME = "Types"; | |||
private static final String DEFAULT_TAG_NAME = "Default"; | |||
private static final String EXTENSION_ATTRIBUTE_NAME = "Extension"; | |||
private static final String CONTENT_TYPE_ATTRIBUTE_NAME = "ContentType"; | |||
private static final String OVERRIDE_TAG_NAME = "Override"; | |||
private static final String PART_NAME_ATTRIBUTE_NAME = "PartName"; | |||
/** | |||
* Default content type tree. <Extension, ContentType> | |||
*/ | |||
private TreeMap<String, String> defaultContentType; | |||
/** | |||
* Override content type tree. | |||
*/ | |||
private TreeMap<PackagePartName, String> overrideContentType; | |||
/** | |||
* Constructor. Parses the content of the specified input stream. | |||
* | |||
* @param archive | |||
* If different of <i>null</i> then the content types part is | |||
* retrieve and parse. | |||
* @throws InvalidFormatException | |||
* If the content types part content is not valid. | |||
*/ | |||
public ContentTypeManager(InputStream in, Package pkg) | |||
throws InvalidFormatException { | |||
this.container = pkg; | |||
this.defaultContentType = new TreeMap<String, String>(); | |||
if (in != null) { | |||
try { | |||
parseContentTypesFile(in); | |||
} catch (InvalidFormatException e) { | |||
throw new InvalidFormatException( | |||
"Can't read content types part !"); | |||
} | |||
} | |||
} | |||
/** | |||
* Build association extention-> content type (will be stored in | |||
* [Content_Types].xml) for example ContentType="image/png" Extension="png" | |||
* | |||
* [M2.8]: When adding a new part to a package, the package implementer | |||
* shall ensure that a content type for that part is specified in the | |||
* Content Types stream; the package implementer shall perform the steps | |||
* described in��9.1.2.3: | |||
* | |||
* 1. Get the extension from the part name by taking the substring to the | |||
* right of the rightmost occurrence of the dot character (.) from the | |||
* rightmost segment. | |||
* | |||
* 2. If a part name has no extension, a corresponding Override element | |||
* shall be added to the Content Types stream. | |||
* | |||
* 3. Compare the resulting extension with the values specified for the | |||
* Extension attributes of the Default elements in the Content Types stream. | |||
* The comparison shall be case-insensitive ASCII. | |||
* | |||
* 4. If there is a Default element with a matching Extension attribute, | |||
* then the content type of the new part shall be compared with the value of | |||
* the ContentType attribute. The comparison might be case-sensitive and | |||
* include every character regardless of the role it plays in the | |||
* content-type grammar of RFC 2616, or it might follow the grammar of RFC | |||
* 2616. | |||
* | |||
* a. If the content types match, no further action is required. | |||
* | |||
* b. If the content types do not match, a new Override element shall be | |||
* added to the Content Types stream. . | |||
* | |||
* 5. If there is no Default element with a matching Extension attribute, a | |||
* new Default element or Override element shall be added to the Content | |||
* Types stream. | |||
* | |||
* | |||
* @param partUri | |||
* the uri that will be stored | |||
* @return <b>false</b> if an error occured. | |||
*/ | |||
public void addContentType(PackagePartName partName, String contentType) { | |||
boolean defaultCTExists = false; | |||
String extension = partName.getExtension().toLowerCase(); | |||
if ((extension.length() == 0) | |||
|| (this.defaultContentType.containsKey(extension) && !(defaultCTExists = this.defaultContentType | |||
.containsValue(contentType)))) | |||
this.addOverrideContentType(partName, contentType); | |||
else if (!defaultCTExists) | |||
this.addDefaultContentType(extension, contentType); | |||
} | |||
/** | |||
* Add an override content type for a specific part. | |||
* | |||
* @param partName | |||
* Name of the part. | |||
* @param contentType | |||
* Content type of the part. | |||
*/ | |||
private void addOverrideContentType(PackagePartName partName, | |||
String contentType) { | |||
if (overrideContentType == null) | |||
overrideContentType = new TreeMap<PackagePartName, String>(); | |||
overrideContentType.put(partName, contentType); | |||
} | |||
/** | |||
* Add a content type associated with the specified extension. | |||
* | |||
* @param extension | |||
* The part name extension to bind to a content type. | |||
* @param contentType | |||
* The content type associated with the specified extension. | |||
*/ | |||
private void addDefaultContentType(String extension, String contentType) { | |||
// Remark : Originally the latest parameter was : | |||
// contentType.toLowerCase(). Change due to a request ID 1996748. | |||
defaultContentType.put(extension.toLowerCase(), contentType); | |||
} | |||
/** | |||
* Delete a content type based on the specified part name. If the specified | |||
* part name is register with an override content type, then this content | |||
* type is remove, else the content type is remove in the default content | |||
* type list if it exists and if no part is associated with it yet. | |||
* | |||
* Check rule M2.4: The package implementer shall require that the Content | |||
* Types stream contain one of the following for every part in the package: | |||
* One matching Default element One matching Override element Both a | |||
* matching Default element and a matching Override element, in which case | |||
* the Override element takes precedence. | |||
* | |||
* @param partUri | |||
* The part URI associated with the override content type to | |||
* delete. | |||
* @exception InvalidOperationException | |||
* Throws if | |||
*/ | |||
public void removeContentType(PackagePartName partName) | |||
throws InvalidOperationException { | |||
if (partName == null) | |||
throw new IllegalArgumentException("partName"); | |||
/* Override content type */ | |||
if (this.overrideContentType != null | |||
&& (this.overrideContentType.get(partName) != null)) { | |||
// Remove the override definition for the specified part. | |||
this.overrideContentType.remove(partName); | |||
return; | |||
} | |||
/* Default content type */ | |||
String extensionToDelete = partName.getExtension(); | |||
boolean deleteDefaultContentTypeFlag = true; | |||
if (this.container != null) { | |||
try { | |||
for (PackagePart part : this.container.getParts()) { | |||
if (!part.getPartName().equals(partName) | |||
&& part.getPartName().getExtension() | |||
.equalsIgnoreCase(extensionToDelete)) { | |||
deleteDefaultContentTypeFlag = false; | |||
break; | |||
} | |||
} | |||
} catch (InvalidFormatException e) { | |||
throw new InvalidOperationException(e.getMessage()); | |||
} | |||
} | |||
// Remove the default content type, no other part use this content type. | |||
if (deleteDefaultContentTypeFlag) { | |||
this.defaultContentType.remove(extensionToDelete); | |||
} | |||
/* | |||
* Check rule 2.4: The package implementer shall require that the | |||
* Content Types stream contain one of the following for every part in | |||
* the package: One matching Default element One matching Override | |||
* element Both a matching Default element and a matching Override | |||
* element, in which case the Override element takes precedence. | |||
*/ | |||
if (this.container != null) { | |||
try { | |||
for (PackagePart part : this.container.getParts()) { | |||
if (!part.getPartName().equals(partName) | |||
&& this.getContentType(part.getPartName()) == null) | |||
throw new InvalidOperationException( | |||
"Rule M2.4 is not respected: Nor a default element or override element is associated with the part: " | |||
+ part.getPartName().getName()); | |||
} | |||
} catch (InvalidFormatException e) { | |||
throw new InvalidOperationException(e.getMessage()); | |||
} | |||
} | |||
} | |||
/** | |||
* Check if the specified content type is already register. | |||
* | |||
* @param contentType | |||
* The content type to check. | |||
* @return <code>true</code> if the specified content type is already | |||
* register, then <code>false</code>. | |||
*/ | |||
public boolean isContentTypeRegister(String contentType) { | |||
if (contentType == null) | |||
throw new IllegalArgumentException("contentType"); | |||
return (this.defaultContentType.values().contains(contentType) || (this.overrideContentType != null && this.overrideContentType | |||
.values().contains(contentType))); | |||
} | |||
/** | |||
* Get the content type for the specified part, if any. | |||
* | |||
* Rule [M2.9]: To get the content type of a part, the package implementer | |||
* shall perform the steps described in��9.1.2.4: | |||
* | |||
* 1. Compare the part name with the values specified for the PartName | |||
* attribute of the Override elements. The comparison shall be | |||
* case-insensitive ASCII. | |||
* | |||
* 2. If there is an Override element with a matching PartName attribute, | |||
* return the value of its ContentType attribute. No further action is | |||
* required. | |||
* | |||
* 3. If there is no Override element with a matching PartName attribute, | |||
* then a. Get the extension from the part name by taking the substring to | |||
* the right of the rightmost occurrence of the dot character (.) from the | |||
* rightmost segment. b. Check the Default elements of the Content Types | |||
* stream, comparing the extension with the value of the Extension | |||
* attribute. The comparison shall be case-insensitive ASCII. | |||
* | |||
* 4. If there is a Default element with a matching Extension attribute, | |||
* return the value of its ContentType attribute. No further action is | |||
* required. | |||
* | |||
* 5. If neither Override nor Default elements with matching attributes are | |||
* found for the specified part name, the implementation shall not map this | |||
* part name to a part. | |||
* | |||
* @param partUri | |||
* The URI part to check. | |||
* @return The content type associated with the URI (in case of an override | |||
* content type) or the extension (in case of default content type), | |||
* else <code>null</code>. | |||
* | |||
* @exception OpenXML4JRuntimeException | |||
* Throws if the content type manager is not able to find the | |||
* content from an existing part. | |||
*/ | |||
public String getContentType(PackagePartName partName) { | |||
if (partName == null) | |||
throw new IllegalArgumentException("partName"); | |||
if ((this.overrideContentType != null) | |||
&& this.overrideContentType.containsKey(partName)) | |||
return this.overrideContentType.get(partName); | |||
String extension = partName.getExtension().toLowerCase(); | |||
if (this.defaultContentType.containsKey(extension)) | |||
return this.defaultContentType.get(extension); | |||
/* | |||
* [M2.4] : The package implementer shall require that the Content Types | |||
* stream contain one of the following for every part in the package: | |||
* One matching Default element, One matching Override element, Both a | |||
* matching Default element and a matching Override element, in which | |||
* case the Override element takes precedence. | |||
*/ | |||
if (this.container != null && this.container.getPart(partName) != null) { | |||
throw new OpenXML4JRuntimeException( | |||
"Rule M2.4 exception : this error should NEVER happen, if so please send a mail to the developers team, thanks !"); | |||
} else { | |||
return null; | |||
} | |||
} | |||
/** | |||
* Clear all content types. | |||
*/ | |||
public void clearAll() { | |||
this.defaultContentType.clear(); | |||
if (this.overrideContentType != null) | |||
this.overrideContentType.clear(); | |||
} | |||
/** | |||
* Clear all override content types. | |||
* | |||
*/ | |||
public void clearOverrideContentTypes() { | |||
if (this.overrideContentType != null) | |||
this.overrideContentType.clear(); | |||
} | |||
/** | |||
* Parse the content types part. | |||
* | |||
* @throws InvalidFormatException | |||
* Throws if the content type doesn't exist or the XML format is | |||
* invalid. | |||
*/ | |||
private void parseContentTypesFile(InputStream in) | |||
throws InvalidFormatException { | |||
try { | |||
SAXReader xmlReader = new SAXReader(); | |||
Document xmlContentTypetDoc = xmlReader.read(in); | |||
// Default content types | |||
List defaultTypes = xmlContentTypetDoc.getRootElement().elements( | |||
DEFAULT_TAG_NAME); | |||
Iterator elementIteratorDefault = defaultTypes.iterator(); | |||
while (elementIteratorDefault.hasNext()) { | |||
Element element = (Element) elementIteratorDefault.next(); | |||
String extension = element.attribute(EXTENSION_ATTRIBUTE_NAME) | |||
.getValue(); | |||
String contentType = element.attribute( | |||
CONTENT_TYPE_ATTRIBUTE_NAME).getValue(); | |||
addDefaultContentType(extension, contentType); | |||
} | |||
// Overriden content types | |||
List overrideTypes = xmlContentTypetDoc.getRootElement().elements( | |||
OVERRIDE_TAG_NAME); | |||
Iterator elementIteratorOverride = overrideTypes.iterator(); | |||
while (elementIteratorOverride.hasNext()) { | |||
Element element = (Element) elementIteratorOverride.next(); | |||
URI uri = new URI(element.attribute(PART_NAME_ATTRIBUTE_NAME) | |||
.getValue()); | |||
PackagePartName partName = PackagingURIHelper | |||
.createPartName(uri); | |||
String contentType = element.attribute( | |||
CONTENT_TYPE_ATTRIBUTE_NAME).getValue(); | |||
addOverrideContentType(partName, contentType); | |||
} | |||
} catch (URISyntaxException urie) { | |||
throw new InvalidFormatException(urie.getMessage()); | |||
} catch (DocumentException e) { | |||
throw new InvalidFormatException(e.getMessage()); | |||
} | |||
} | |||
/** | |||
* Save the contents type part. | |||
* | |||
* @param outStream | |||
* The output stream use to save the XML content of the content | |||
* types part. | |||
* @return <b>true</b> if the operation success, else <b>false</b>. | |||
*/ | |||
public boolean save(OutputStream outStream) { | |||
Document xmlOutDoc = DocumentHelper.createDocument(); | |||
// Building namespace | |||
Namespace dfNs = Namespace.get("", TYPES_NAMESPACE_URI); | |||
Element typesElem = xmlOutDoc | |||
.addElement(new QName(TYPES_TAG_NAME, dfNs)); | |||
// Adding default types | |||
for (Entry<String, String> entry : defaultContentType.entrySet()) { | |||
appendDefaultType(typesElem, entry); | |||
} | |||
// Adding specific types if any exist | |||
if (overrideContentType != null) { | |||
for (Entry<PackagePartName, String> entry : overrideContentType | |||
.entrySet()) { | |||
appendSpecificTypes(typesElem, entry); | |||
} | |||
} | |||
xmlOutDoc.normalize(); | |||
// Save content in the specified output stream | |||
return this.saveImpl(xmlOutDoc, outStream); | |||
} | |||
/** | |||
* Use to append specific type XML elements, use by the save() method. | |||
* | |||
* @param root | |||
* XML parent element use to append this override type element. | |||
* @param entry | |||
* The values to append. | |||
* @see #save(ZipOutputStream) | |||
*/ | |||
private void appendSpecificTypes(Element root, | |||
Entry<PackagePartName, String> entry) { | |||
root.addElement(OVERRIDE_TAG_NAME).addAttribute( | |||
PART_NAME_ATTRIBUTE_NAME, | |||
((PackagePartName) entry.getKey()).getName()).addAttribute( | |||
CONTENT_TYPE_ATTRIBUTE_NAME, (String) entry.getValue()); | |||
} | |||
/** | |||
* Use to append default types XML elements, use by the save() metid. | |||
* | |||
* @param root | |||
* XML parent element use to append this default type element. | |||
* @param entry | |||
* The values to append. | |||
* @see #save(ZipOutputStream) | |||
*/ | |||
private void appendDefaultType(Element root, Entry<String, String> entry) { | |||
root.addElement(DEFAULT_TAG_NAME).addAttribute( | |||
EXTENSION_ATTRIBUTE_NAME, (String) entry.getKey()) | |||
.addAttribute(CONTENT_TYPE_ATTRIBUTE_NAME, | |||
(String) entry.getValue()); | |||
} | |||
/** | |||
* Specific implementation of the save method. Call by the save() method, | |||
* call before exiting. | |||
* | |||
* @param out | |||
* The output stream use to write the content type XML. | |||
*/ | |||
public abstract boolean saveImpl(Document content, OutputStream out); | |||
} |
@@ -0,0 +1,91 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc.internal; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.FileOutputStream; | |||
import java.io.IOException; | |||
import java.nio.channels.FileChannel; | |||
/** | |||
* Provide useful method to manage file. | |||
* | |||
* @author Julien Chable | |||
* @version 0.1 | |||
*/ | |||
public final class FileHelper { | |||
/** | |||
* Get the directory part of the specified file path. | |||
* | |||
* @param f | |||
* File to process. | |||
* @return The directory path from the specified | |||
*/ | |||
public static File getDirectory(File f) { | |||
if (f != null) { | |||
String path = f.getPath(); | |||
int len = path.length(); | |||
int num2 = len; | |||
while (--num2 >= 0) { | |||
char ch1 = path.charAt(num2); | |||
if (ch1 == File.separatorChar) { | |||
return new File(path.substring(0, num2)); | |||
} | |||
} | |||
} | |||
return null; | |||
} | |||
/** | |||
* Copy a file. | |||
* | |||
* @param in | |||
* The source file. | |||
* @param out | |||
* The target location. | |||
* @throws IOException | |||
* If an I/O error occur. | |||
*/ | |||
public static void copyFile(File in, File out) throws IOException { | |||
FileChannel sourceChannel = new FileInputStream(in).getChannel(); | |||
FileChannel destinationChannel = new FileOutputStream(out).getChannel(); | |||
sourceChannel.transferTo(0, sourceChannel.size(), destinationChannel); | |||
sourceChannel.close(); | |||
destinationChannel.close(); | |||
} | |||
/** | |||
* Get file name from the specified File object. | |||
*/ | |||
public static String getFilename(File file) { | |||
if (file != null) { | |||
String path = file.getPath(); | |||
int len = path.length(); | |||
int num2 = len; | |||
while (--num2 >= 0) { | |||
char ch1 = path.charAt(num2); | |||
if (ch1 == File.separatorChar) | |||
return path.substring(num2 + 1, len); | |||
} | |||
} | |||
return ""; | |||
} | |||
} |
@@ -0,0 +1,126 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc.internal; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.Package; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.PackagePartName; | |||
import org.apache.poi.openxml4j.opc.internal.marshallers.ZipPartMarshaller; | |||
/** | |||
* Memory version of a package part. Use to | |||
* | |||
* @author Julien Chable | |||
* @version 1.0 | |||
*/ | |||
public final class MemoryPackagePart extends PackagePart { | |||
/** | |||
* Storage for the part data. | |||
*/ | |||
protected byte[] data; | |||
/** | |||
* Size of data. | |||
*/ | |||
protected int length; | |||
/** | |||
* Constructor. | |||
* | |||
* @param pack | |||
* The owner package. | |||
* @param partName | |||
* The part name. | |||
* @param contentType | |||
* The content type. | |||
* @throws InvalidFormatException | |||
* If the specified URI is not OPC compliant. | |||
*/ | |||
public MemoryPackagePart(Package pack, PackagePartName partName, | |||
String contentType) throws InvalidFormatException { | |||
super(pack, partName, contentType); | |||
} | |||
/** | |||
* Constructor. | |||
* | |||
* @param pack | |||
* The owner package. | |||
* @param partName | |||
* The part name. | |||
* @param contentType | |||
* The content type. | |||
* @param loadRelationships | |||
* Specify if the relationships will be loaded. | |||
* @throws InvalidFormatException | |||
* If the specified URI is not OPC compliant. | |||
*/ | |||
public MemoryPackagePart(Package pack, PackagePartName partName, | |||
String contentType, boolean loadRelationships) | |||
throws InvalidFormatException { | |||
super(pack, partName, new ContentType(contentType), loadRelationships); | |||
} | |||
@Override | |||
protected InputStream getInputStreamImpl() { | |||
// If this part has been created from scratch and/or the data buffer is | |||
// not | |||
// initialize, so we do it now. | |||
if (data == null) { | |||
data = new byte[0]; | |||
} | |||
return new ByteArrayInputStream(data); | |||
} | |||
@Override | |||
protected OutputStream getOutputStreamImpl() { | |||
return new MemoryPackagePartOutputStream(this); | |||
} | |||
public void clear() { | |||
data = null; | |||
length = 0; | |||
} | |||
@Override | |||
public boolean save(OutputStream os) throws OpenXML4JException { | |||
return new ZipPartMarshaller().marshall(this, os); | |||
} | |||
@Override | |||
public boolean load(InputStream ios) throws InvalidFormatException { | |||
throw new InvalidFormatException("Method not implemented"); | |||
} | |||
@Override | |||
public void close() { | |||
// Do nothing | |||
} | |||
@Override | |||
public void flush() { | |||
// Do nothing | |||
} | |||
} |
@@ -0,0 +1,96 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc.internal; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
/** | |||
* Build an output stream for MemoryPackagePart. | |||
* | |||
* @author Julien Chable | |||
* @version 1.0 | |||
*/ | |||
public final class MemoryPackagePartOutputStream extends OutputStream { | |||
private MemoryPackagePart part; | |||
private ByteArrayOutputStream buff; | |||
public MemoryPackagePartOutputStream(MemoryPackagePart part) { | |||
this.part = part; | |||
buff = new ByteArrayOutputStream(); | |||
} | |||
@Override | |||
public void write(int b) throws IOException { | |||
buff.write(b); | |||
} | |||
/** | |||
* Close this stream and flush the content. | |||
* @see #flush() | |||
*/ | |||
@Override | |||
public void close() throws IOException { | |||
this.flush(); | |||
} | |||
/** | |||
* Flush this output stream. This method is called by the close() method. | |||
* Warning : don't call this method for output consistency. | |||
* @see #close() | |||
*/ | |||
@Override | |||
public void flush() throws IOException { | |||
buff.flush(); | |||
if (part.data != null) { | |||
byte[] newArray = new byte[part.data.length + buff.size()]; | |||
// copy the previous contents of part.data in newArray | |||
System.arraycopy(part.data, 0, newArray, 0, part.data.length); | |||
// append the newly added data | |||
byte[] buffArr = buff.toByteArray(); | |||
System.arraycopy(buffArr, 0, newArray, part.data.length, | |||
buffArr.length); | |||
// save the result as new data | |||
part.data = newArray; | |||
} else { | |||
// was empty, just fill it | |||
part.data = buff.toByteArray(); | |||
} | |||
/* | |||
* Clear this streams buffer, in case flush() is called a second time | |||
* Fix bug 1921637 - provided by Rainer Schwarze | |||
*/ | |||
buff.reset(); | |||
} | |||
@Override | |||
public void write(byte[] b, int off, int len) throws IOException { | |||
buff.write(b, off, len); | |||
} | |||
@Override | |||
public void write(byte[] b) throws IOException { | |||
buff.write(b); | |||
} | |||
} |
@@ -0,0 +1,621 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc.internal; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import java.text.ParsePosition; | |||
import java.text.SimpleDateFormat; | |||
import java.util.Date; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
import org.apache.poi.openxml4j.exceptions.InvalidOperationException; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.ContentTypes; | |||
import org.apache.poi.openxml4j.opc.Package; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.PackagePartName; | |||
import org.apache.poi.openxml4j.opc.PackageProperties; | |||
import org.apache.poi.openxml4j.util.Nullable; | |||
/** | |||
* Represents the core properties part of a package. | |||
* | |||
* @author Julien Chable | |||
* @version 1.0 | |||
*/ | |||
public class PackagePropertiesPart extends PackagePart implements | |||
PackageProperties { | |||
public final static String NAMESPACE_DC_URI = "http://purl.org/dc/elements/1.1/"; | |||
public final static String NAMESPACE_CP_URI = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties"; | |||
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. | |||
* | |||
* @param pack | |||
* Container package. | |||
* @param partName | |||
* Name of this part. | |||
* @throws InvalidFormatException | |||
* Throws if the content is invalid. | |||
*/ | |||
public PackagePropertiesPart(Package pack, PackagePartName partName) | |||
throws InvalidFormatException { | |||
super(pack, partName, ContentTypes.CORE_PROPERTIES_PART); | |||
} | |||
/** | |||
* A categorization of the content of this package. | |||
* | |||
* [Example: Example values for this property might include: Resume, Letter, | |||
* Financial Forecast, Proposal, Technical Presentation, and so on. This | |||
* value might be used by an application's user interface to facilitate | |||
* navigation of a large set of documents. end example] | |||
*/ | |||
protected Nullable<String> category = new Nullable<String>(); | |||
/** | |||
* The status of the content. | |||
* | |||
* [Example: Values might include "Draft", "Reviewed", and "Final". end | |||
* example] | |||
*/ | |||
protected Nullable<String> contentStatus = new Nullable<String>(); | |||
/** | |||
* The type of content represented, generally defined by a specific use and | |||
* intended audience. | |||
* | |||
* [Example: Values might include "Whitepaper", "Security Bulletin", and | |||
* "Exam". end example] [Note: This property is distinct from MIME content | |||
* types as defined in RFC 2616. end note] | |||
*/ | |||
protected Nullable<String> contentType = new Nullable<String>(); | |||
/** | |||
* Date of creation of the resource. | |||
*/ | |||
protected Nullable<Date> created = new Nullable<Date>(); | |||
/** | |||
* An entity primarily responsible for making the content of the resource. | |||
*/ | |||
protected Nullable<String> creator = new Nullable<String>(); | |||
/** | |||
* An explanation of the content of the resource. | |||
* | |||
* [Example: Values might include an abstract, table of contents, reference | |||
* to a graphical representation of content, and a free-text account of the | |||
* content. end example] | |||
*/ | |||
protected Nullable<String> description = new Nullable<String>(); | |||
/** | |||
* An unambiguous reference to the resource within a given context. | |||
*/ | |||
protected Nullable<String> identifier = new Nullable<String>(); | |||
/** | |||
* A delimited set of keywords to support searching and indexing. This is | |||
* typically a list of terms that are not available elsewhere in the | |||
* properties. | |||
*/ | |||
protected Nullable<String> keywords = new Nullable<String>(); | |||
/** | |||
* The language of the intellectual content of the resource. | |||
* | |||
* [Note: IETF RFC 3066 provides guidance on encoding to represent | |||
* languages. end note] | |||
*/ | |||
protected Nullable<String> language = new Nullable<String>(); | |||
/** | |||
* The user who performed the last modification. The identification is | |||
* environment-specific. | |||
* | |||
* [Example: A name, email address, or employee ID. end example] It is | |||
* recommended that this value be as concise as possible. | |||
*/ | |||
protected Nullable<String> lastModifiedBy = new Nullable<String>(); | |||
/** | |||
* The date and time of the last printing. | |||
*/ | |||
protected Nullable<Date> lastPrinted = new Nullable<Date>(); | |||
/** | |||
* Date on which the resource was changed. | |||
*/ | |||
protected Nullable<Date> modified = new Nullable<Date>(); | |||
/** | |||
* The revision number. | |||
* | |||
* [Example: This value might indicate the number of saves or revisions, | |||
* provided the application updates it after each revision. end example] | |||
*/ | |||
protected Nullable<String> revision = new Nullable<String>(); | |||
/** | |||
* The topic of the content of the resource. | |||
*/ | |||
protected Nullable<String> subject = new Nullable<String>(); | |||
/** | |||
* The name given to the resource. | |||
*/ | |||
protected Nullable<String> title = new Nullable<String>(); | |||
/** | |||
* The version number. This value is set by the user or by the application. | |||
*/ | |||
protected Nullable<String> version = new Nullable<String>(); | |||
/* | |||
* Getters and setters | |||
*/ | |||
/** | |||
* Get the category property. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#getCategoryProperty() | |||
*/ | |||
public Nullable<String> getCategoryProperty() { | |||
return category; | |||
} | |||
/** | |||
* Get content status. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#getContentStatusProperty() | |||
*/ | |||
public Nullable<String> getContentStatusProperty() { | |||
return contentStatus; | |||
} | |||
/** | |||
* Get content type. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#getContentTypeProperty() | |||
*/ | |||
public Nullable<String> getContentTypeProperty() { | |||
return contentType; | |||
} | |||
/** | |||
* Get created date. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#getCreatedProperty() | |||
*/ | |||
public Nullable<Date> getCreatedProperty() { | |||
return created; | |||
} | |||
/** | |||
* Get created date formated into a String. | |||
* | |||
* @return A string representation of the created date. | |||
*/ | |||
public String getCreatedPropertyString() { | |||
return getDateValue(created); | |||
} | |||
/** | |||
* Get creator. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#getCreatorProperty() | |||
*/ | |||
public Nullable<String> getCreatorProperty() { | |||
return creator; | |||
} | |||
/** | |||
* Get description. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#getDescriptionProperty() | |||
*/ | |||
public Nullable<String> getDescriptionProperty() { | |||
return description; | |||
} | |||
/** | |||
* Get identifier. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#getIdentifierProperty() | |||
*/ | |||
public Nullable<String> getIdentifierProperty() { | |||
return identifier; | |||
} | |||
/** | |||
* Get keywords. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#getKeywordsProperty() | |||
*/ | |||
public Nullable<String> getKeywordsProperty() { | |||
return keywords; | |||
} | |||
/** | |||
* Get the language. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#getLanguageProperty() | |||
*/ | |||
public Nullable<String> getLanguageProperty() { | |||
return language; | |||
} | |||
/** | |||
* Get the author of last modifications. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#getLastModifiedByProperty() | |||
*/ | |||
public Nullable<String> getLastModifiedByProperty() { | |||
return lastModifiedBy; | |||
} | |||
/** | |||
* Get last printed date. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#getLastPrintedProperty() | |||
*/ | |||
public Nullable<Date> getLastPrintedProperty() { | |||
return lastPrinted; | |||
} | |||
/** | |||
* Get last printed date formated into a String. | |||
* | |||
* @return A string representation of the last printed date. | |||
*/ | |||
public String getLastPrintedPropertyString() { | |||
return getDateValue(created); | |||
} | |||
/** | |||
* Get modified date. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#getModifiedProperty() | |||
*/ | |||
public Nullable<Date> getModifiedProperty() { | |||
return modified; | |||
} | |||
/** | |||
* Get modified date formated into a String. | |||
* | |||
* @return A string representation of the modified date. | |||
*/ | |||
public String getModifiedPropertyString() { | |||
if (!modified.hasValue()) | |||
return getDateValue(new Nullable<Date>(new Date())); | |||
else | |||
return getDateValue(modified); | |||
} | |||
/** | |||
* Get revision. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#getRevisionProperty() | |||
*/ | |||
public Nullable<String> getRevisionProperty() { | |||
return revision; | |||
} | |||
/** | |||
* Get subject. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#getSubjectProperty() | |||
*/ | |||
public Nullable<String> getSubjectProperty() { | |||
return subject; | |||
} | |||
/** | |||
* Get title. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#getTitleProperty() | |||
*/ | |||
public Nullable<String> getTitleProperty() { | |||
return title; | |||
} | |||
/** | |||
* Get version. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#getVersionProperty() | |||
*/ | |||
public Nullable<String> getVersionProperty() { | |||
return version; | |||
} | |||
/** | |||
* Set the category. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#setCategoryProperty(java.lang.String) | |||
*/ | |||
public void setCategoryProperty(String category) { | |||
this.category = setStringValue(category); | |||
} | |||
/** | |||
* Set the content status. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#setContentStatusProperty(java.lang.String) | |||
*/ | |||
public void setContentStatusProperty(String contentStatus) { | |||
this.contentStatus = setStringValue(contentStatus); | |||
} | |||
/** | |||
* Set the content type. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#setContentTypeProperty(java.lang.String) | |||
*/ | |||
public void setContentTypeProperty(String contentType) { | |||
this.contentType = setStringValue(contentType); | |||
} | |||
/** | |||
* Set the created date. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#setCreatedProperty(org.apache.poi.openxml4j.util.Nullable) | |||
*/ | |||
public void setCreatedProperty(String created) { | |||
try { | |||
this.created = setDateValue(created); | |||
} catch (InvalidFormatException e) { | |||
new IllegalArgumentException("created : " | |||
+ e.getLocalizedMessage()); | |||
} | |||
} | |||
/** | |||
* Set the created date. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#setCreatedProperty(org.apache.poi.openxml4j.util.Nullable) | |||
*/ | |||
public void setCreatedProperty(Nullable<Date> created) { | |||
if (created.hasValue()) | |||
this.created = created; | |||
} | |||
/** | |||
* Set the creator. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#setCreatorProperty(java.lang.String) | |||
*/ | |||
public void setCreatorProperty(String creator) { | |||
this.creator = setStringValue(creator); | |||
} | |||
/** | |||
* Set the description. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#setDescriptionProperty(java.lang.String) | |||
*/ | |||
public void setDescriptionProperty(String description) { | |||
this.description = setStringValue(description); | |||
} | |||
/** | |||
* Set identifier. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#setIdentifierProperty(java.lang.String) | |||
*/ | |||
public void setIdentifierProperty(String identifier) { | |||
this.identifier = setStringValue(identifier); | |||
} | |||
/** | |||
* Set keywords. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#setKeywordsProperty(java.lang.String) | |||
*/ | |||
public void setKeywordsProperty(String keywords) { | |||
this.keywords = setStringValue(keywords); | |||
} | |||
/** | |||
* Set language. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#setLanguageProperty(java.lang.String) | |||
*/ | |||
public void setLanguageProperty(String language) { | |||
this.language = setStringValue(language); | |||
} | |||
/** | |||
* Set last modifications author. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#setLastModifiedByProperty(java.lang.String) | |||
*/ | |||
public void setLastModifiedByProperty(String lastModifiedBy) { | |||
this.lastModifiedBy = setStringValue(lastModifiedBy); | |||
} | |||
/** | |||
* Set last printed date. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#setLastPrintedProperty(org.apache.poi.openxml4j.util.Nullable) | |||
*/ | |||
public void setLastPrintedProperty(String lastPrinted) { | |||
try { | |||
this.lastPrinted = setDateValue(lastPrinted); | |||
} catch (InvalidFormatException e) { | |||
new IllegalArgumentException("lastPrinted : " | |||
+ e.getLocalizedMessage()); | |||
} | |||
} | |||
/** | |||
* Set last printed date. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#setLastPrintedProperty(org.apache.poi.openxml4j.util.Nullable) | |||
*/ | |||
public void setLastPrintedProperty(Nullable<Date> lastPrinted) { | |||
if (lastPrinted.hasValue()) | |||
this.lastPrinted = lastPrinted; | |||
} | |||
/** | |||
* Set last modification date. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#setModifiedProperty(org.apache.poi.openxml4j.util.Nullable) | |||
*/ | |||
public void setModifiedProperty(String modified) { | |||
try { | |||
this.modified = setDateValue(modified); | |||
} catch (InvalidFormatException e) { | |||
new IllegalArgumentException("modified : " | |||
+ e.getLocalizedMessage()); | |||
} | |||
} | |||
/** | |||
* Set last modification date. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#setModifiedProperty(org.apache.poi.openxml4j.util.Nullable) | |||
*/ | |||
public void setModifiedProperty(Nullable<Date> modified) { | |||
if (modified.hasValue()) | |||
this.modified = modified; | |||
} | |||
/** | |||
* Set revision. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#setRevisionProperty(java.lang.String) | |||
*/ | |||
public void setRevisionProperty(String revision) { | |||
this.revision = setStringValue(revision); | |||
} | |||
/** | |||
* Set subject. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#setSubjectProperty(java.lang.String) | |||
*/ | |||
public void setSubjectProperty(String subject) { | |||
this.subject = setStringValue(subject); | |||
} | |||
/** | |||
* Set title. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#setTitleProperty(java.lang.String) | |||
*/ | |||
public void setTitleProperty(String title) { | |||
this.title = setStringValue(title); | |||
} | |||
/** | |||
* Set version. | |||
* | |||
* @see org.apache.poi.openxml4j.opc.PackageProperties#setVersionProperty(java.lang.String) | |||
*/ | |||
public void setVersionProperty(String version) { | |||
this.version = setStringValue(version); | |||
} | |||
/** | |||
* Convert a strig value into a Nullable<String> | |||
*/ | |||
private Nullable<String> setStringValue(String s) { | |||
if (s == null || s.equals("")) | |||
return new Nullable<String>(); | |||
else | |||
return new Nullable<String>(s); | |||
} | |||
/** | |||
* Convert a string value represented a date into a Nullable<Date>. | |||
* | |||
* @throws InvalidFormatException | |||
* Throws if the date format isnot valid. | |||
*/ | |||
private Nullable<Date> setDateValue(String s) throws InvalidFormatException { | |||
if (s == null || s.equals("")) | |||
return new Nullable<Date>(); | |||
else { | |||
SimpleDateFormat df = new SimpleDateFormat( | |||
"yyyy-MM-dd'T'HH:mm:ss'Z'"); | |||
Date d = df.parse(s, new ParsePosition(0)); | |||
if (d == null) | |||
throw new InvalidFormatException("Date not well formated"); | |||
return new Nullable<Date>(d); | |||
} | |||
} | |||
/** | |||
* Convert a Nullable<Date> into a String. | |||
* | |||
* @param d | |||
* The Date to convert. | |||
* @return The formated date or null. | |||
* @see java.util.SimpleDateFormat | |||
*/ | |||
private String getDateValue(Nullable<Date> d) { | |||
if (d == null || d.equals("")) | |||
return ""; | |||
else { | |||
SimpleDateFormat df = new SimpleDateFormat( | |||
"yyyy-MM-dd'T'HH:mm:ss'Z'"); | |||
return df.format(d.getValue()); | |||
} | |||
} | |||
@Override | |||
protected InputStream getInputStreamImpl() { | |||
throw new InvalidOperationException("Operation not authorized"); | |||
} | |||
@Override | |||
protected OutputStream getOutputStreamImpl() { | |||
throw new InvalidOperationException( | |||
"Can't use output stream to set properties !"); | |||
} | |||
@Override | |||
public boolean save(OutputStream zos) throws OpenXML4JException { | |||
throw new InvalidOperationException("Operation not authorized"); | |||
} | |||
@Override | |||
public boolean load(InputStream ios) throws InvalidFormatException { | |||
throw new InvalidOperationException("Operation not authorized"); | |||
} | |||
@Override | |||
public void close() { | |||
// Do nothing | |||
} | |||
@Override | |||
public void flush() { | |||
// Do nothing | |||
} | |||
} |
@@ -0,0 +1,49 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc.internal; | |||
import java.io.OutputStream; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
/** | |||
* Object implemented this interface are considered as part marshaller. A part | |||
* marshaller is responsible to marshall a part in order to be save in a | |||
* package. | |||
* | |||
* @author Julien Chable | |||
* @version 0.1 | |||
*/ | |||
public interface PartMarshaller { | |||
/** | |||
* Save the content of the package in the stream | |||
* | |||
* @param part | |||
* Part to marshall. | |||
* @param out | |||
* The output stream into which the part will be marshall. | |||
* @return <b>false</b> if any marshall error occurs, else <b>true</b> | |||
* @throws OpenXML4JException | |||
* Throws only if any other exceptions are thrown by inner | |||
* methods. | |||
*/ | |||
public boolean marshall(PackagePart part, OutputStream out) | |||
throws OpenXML4JException; | |||
} |
@@ -0,0 +1,50 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc.internal; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.internal.unmarshallers.UnmarshallContext; | |||
/** | |||
* Object implemented this interface are considered as part unmarshaller. A part | |||
* unmarshaller is responsible to unmarshall a part in order to load it from a | |||
* package. | |||
* | |||
* @author Julien Chable | |||
* @version 0.1 | |||
*/ | |||
public interface PartUnmarshaller { | |||
/** | |||
* Save the content of the package in the stream | |||
* | |||
* @param in | |||
* The input stream from which the part will be unmarshall. | |||
* @return The part freshly unmarshall from the input stream. | |||
* @throws OpenXML4JException | |||
* Throws only if any other exceptions are thrown by inner | |||
* methods. | |||
*/ | |||
public PackagePart unmarshall(UnmarshallContext context, InputStream in) | |||
throws InvalidFormatException, IOException; | |||
} |
@@ -0,0 +1,90 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc.internal; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import java.util.zip.ZipEntry; | |||
import java.util.zip.ZipOutputStream; | |||
import org.dom4j.Document; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
import org.apache.poi.openxml4j.opc.Package; | |||
import org.apache.poi.openxml4j.opc.StreamHelper; | |||
/** | |||
* Zip implementation of the ContentTypeManager. | |||
* | |||
* @author Julien Chable | |||
* @version 1.0 | |||
* @see ContentTypeManager | |||
*/ | |||
public class ZipContentTypeManager extends ContentTypeManager { | |||
/** | |||
* Delegate constructor to the super constructor. | |||
* | |||
* @param in | |||
* The input stream to parse to fill internal content type | |||
* collections. | |||
* @throws InvalidFormatException | |||
* If the content types part content is not valid. | |||
*/ | |||
public ZipContentTypeManager(InputStream in, Package pkg) | |||
throws InvalidFormatException { | |||
super(in, pkg); | |||
} | |||
@Override | |||
public boolean saveImpl(Document content, OutputStream out) { | |||
ZipOutputStream zos = null; | |||
if (out instanceof ZipOutputStream) | |||
zos = (ZipOutputStream) out; | |||
else | |||
zos = new ZipOutputStream(out); | |||
ZipEntry partEntry = new ZipEntry(CONTENT_TYPES_PART_NAME); | |||
try { | |||
// Referenced in ZIP | |||
zos.putNextEntry(partEntry); | |||
// Saving data in the ZIP file | |||
ByteArrayOutputStream outTemp = new ByteArrayOutputStream(); | |||
StreamHelper.saveXmlInStream(content, out); | |||
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; | |||
} else { | |||
zos.write(buff, 0, resultRead); | |||
} | |||
} | |||
zos.closeEntry(); | |||
} catch (IOException ioe) { | |||
logger.error("Cannot write: " + CONTENT_TYPES_PART_NAME | |||
+ " in Zip !", ioe); | |||
return false; | |||
} | |||
return true; | |||
} | |||
} |
@@ -0,0 +1,163 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc.internal; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.net.URI; | |||
import java.net.URISyntaxException; | |||
import java.util.Enumeration; | |||
import java.util.zip.ZipEntry; | |||
import java.util.zip.ZipFile; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.PackageRelationship; | |||
import org.apache.poi.openxml4j.opc.PackageRelationshipTypes; | |||
import org.apache.poi.openxml4j.opc.ZipPackage; | |||
public final class ZipHelper { | |||
/** | |||
* Forward slash use to convert part name between OPC and zip item naming | |||
* conventions. | |||
*/ | |||
private final static String FORWARD_SLASH = "/"; | |||
/** | |||
* Buffer to read data from file. Use big buffer to improve performaces. the | |||
* InputStream class is reading only 8192 bytes per read call (default value | |||
* set by sun) | |||
*/ | |||
public static final int READ_WRITE_FILE_BUFFER_SIZE = 8192; | |||
/** | |||
* Prevent this class to be instancied. | |||
*/ | |||
private ZipHelper() { | |||
// Do nothing | |||
} | |||
/** | |||
* Retrieve the zip entry of the core properties part. | |||
* | |||
* @throws OpenXML4JException | |||
* Throws if internal error occurs. | |||
*/ | |||
public static ZipEntry getCorePropertiesZipEntry(ZipPackage pkg) | |||
throws OpenXML4JException { | |||
PackageRelationship corePropsRel = pkg.getRelationshipsByType( | |||
PackageRelationshipTypes.CORE_PROPERTIES).getRelationship(0); | |||
if (corePropsRel == null) | |||
return null; | |||
return new ZipEntry(corePropsRel.getTargetURI().getPath()); | |||
} | |||
/** | |||
* Retrieve the Zip entry of the content types part. | |||
*/ | |||
public static ZipEntry getContentTypeZipEntry(ZipPackage pkg) { | |||
Enumeration entries = pkg.getZipArchive().getEntries(); | |||
// Enumerate through the Zip entries until we find the one named | |||
// '[Content_Types].xml'. | |||
while (entries.hasMoreElements()) { | |||
ZipEntry entry = (ZipEntry) entries.nextElement(); | |||
if (entry.getName().equals( | |||
ContentTypeManager.CONTENT_TYPES_PART_NAME)) | |||
return entry; | |||
} | |||
return null; | |||
} | |||
/** | |||
* Convert a zip name into an OPC name by adding a leading forward slash to | |||
* the specified item name. | |||
* | |||
* @param zipItemName | |||
* Zip item name to convert. | |||
* @return An OPC compliant name. | |||
*/ | |||
public static String getOPCNameFromZipItemName(String zipItemName) { | |||
if (zipItemName == null) | |||
throw new IllegalArgumentException("zipItemName"); | |||
if (zipItemName.startsWith(FORWARD_SLASH)) | |||
return zipItemName; | |||
else | |||
return FORWARD_SLASH + zipItemName; | |||
} | |||
/** | |||
* Convert an OPC item name into a zip item name by removing any leading | |||
* forward slash if it exist. | |||
* | |||
* @param opcItemName | |||
* The OPC item name to convert. | |||
* @return A zip item name without any leading slashes. | |||
*/ | |||
public static String getZipItemNameFromOPCName(String opcItemName) { | |||
if (opcItemName == null) | |||
throw new IllegalArgumentException("opcItemName"); | |||
String retVal = new String(opcItemName); | |||
while (retVal.startsWith(FORWARD_SLASH)) | |||
retVal = retVal.substring(1); | |||
return retVal; | |||
} | |||
/** | |||
* Convert an OPC item name into a zip URI by removing any leading forward | |||
* slash if it exist. | |||
* | |||
* @param opcItemName | |||
* The OPC item name to convert. | |||
* @return A zip URI without any leading slashes. | |||
*/ | |||
public static URI getZipURIFromOPCName(String opcItemName) { | |||
if (opcItemName == null) | |||
throw new IllegalArgumentException("opcItemName"); | |||
String retVal = new String(opcItemName); | |||
while (retVal.startsWith(FORWARD_SLASH)) | |||
retVal = retVal.substring(1); | |||
try { | |||
return new URI(retVal); | |||
} catch (URISyntaxException e) { | |||
return null; | |||
} | |||
} | |||
/** | |||
* Retrieve and open a zip file with the specified path. | |||
* | |||
* @param path | |||
* The file path. | |||
* @return The zip archive freshly open. | |||
*/ | |||
public static ZipFile openZipFile(String path) { | |||
File f = new File(path); | |||
try { | |||
if (!f.exists()) { | |||
return null; | |||
} | |||
return new ZipFile(f); | |||
} catch (IOException ioe) { | |||
return null; | |||
} | |||
} | |||
} |
@@ -0,0 +1,45 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc.internal.marshallers; | |||
import java.io.OutputStream; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.internal.PartMarshaller; | |||
/** | |||
* Default marshaller that specified that the part is responsible to marshall its content. | |||
* | |||
* @author Julien Chable | |||
* @version 1.0 | |||
* @see PartMarshaller | |||
*/ | |||
public class DefaultMarshaller implements PartMarshaller { | |||
/** | |||
* Save part in the output stream by using the save() method of the part. | |||
* | |||
* @throws OpenXML4JException | |||
* If any error occur. | |||
*/ | |||
public boolean marshall(PackagePart part, OutputStream out) | |||
throws OpenXML4JException { | |||
return part.save(out); | |||
} | |||
} |
@@ -0,0 +1,434 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc.internal.marshallers; | |||
import java.io.OutputStream; | |||
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.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart; | |||
import org.apache.poi.openxml4j.opc.internal.PartMarshaller; | |||
/** | |||
* Package properties marshaller. | |||
* | |||
* @author CDubet, Julien Chable | |||
* @version 1.0 | |||
*/ | |||
public class PackagePropertiesMarshaller implements PartMarshaller { | |||
private final static Namespace namespaceDC = new Namespace("dc", | |||
PackagePropertiesPart.NAMESPACE_DC_URI); | |||
private final static Namespace namespaceCoreProperties = new Namespace("", | |||
PackagePropertiesPart.NAMESPACE_CP_URI); | |||
private final static Namespace namespaceDcTerms = new Namespace("dcterms", | |||
PackagePropertiesPart.NAMESPACE_DCTERMS_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_CONTENT_STATUS = "contentStatus"; | |||
protected static final String KEYWORD_CONTENT_TYPE = "contentType"; | |||
protected static final String KEYWORD_CREATED = "created"; | |||
protected static final String KEYWORD_CREATOR = "creator"; | |||
protected static final String KEYWORD_DESCRIPTION = "description"; | |||
protected static final String KEYWORD_IDENTIFIER = "identifier"; | |||
protected static final String KEYWORD_KEYWORDS = "keywords"; | |||
protected static final String KEYWORD_LANGUAGE = "language"; | |||
protected static final String KEYWORD_LAST_MODIFIED_BY = "lastModifiedBy"; | |||
protected static final String KEYWORD_LAST_PRINTED = "lastPrinted"; | |||
protected static final String KEYWORD_MODIFIED = "modified"; | |||
protected static final String KEYWORD_REVISION = "revision"; | |||
protected static final String KEYWORD_SUBJECT = "subject"; | |||
protected static final String KEYWORD_TITLE = "title"; | |||
protected static final String KEYWORD_VERSION = "version"; | |||
PackagePropertiesPart propsPart; | |||
// The document | |||
Document xmlDoc = null; | |||
/** | |||
* Marshall package core properties to an XML document. Always return | |||
* <code>true</code>. | |||
*/ | |||
public boolean marshall(PackagePart part, OutputStream out) | |||
throws OpenXML4JException { | |||
if (!(part instanceof PackagePropertiesPart)) | |||
throw new IllegalArgumentException( | |||
"'part' must be a PackagePropertiesPart instance."); | |||
propsPart = (PackagePropertiesPart) part; | |||
// Configure the document | |||
xmlDoc = DocumentHelper.createDocument(); | |||
Element rootElem = xmlDoc.addElement(new QName("coreProperties", | |||
namespaceCoreProperties)); | |||
rootElem.addNamespace("cp", PackagePropertiesPart.NAMESPACE_CP_URI); | |||
rootElem.addNamespace("dc", PackagePropertiesPart.NAMESPACE_DC_URI); | |||
rootElem.addNamespace("dcterms", | |||
PackagePropertiesPart.NAMESPACE_DCTERMS_URI); | |||
rootElem.addNamespace("xsi", PackagePropertiesPart.NAMESPACE_XSI_URI); | |||
addCategory(); | |||
addContentStatus(); | |||
addContentType(); | |||
addCreated(); | |||
addCreator(); | |||
addDescription(); | |||
addIdentifier(); | |||
addKeywords(); | |||
addLanguage(); | |||
addLastModifiedBy(); | |||
addLastPrinted(); | |||
addModified(); | |||
addRevision(); | |||
addSubject(); | |||
addTitle(); | |||
addVersion(); | |||
return true; | |||
} | |||
/** | |||
* Add category property element if needed. | |||
*/ | |||
private void addCategory() { | |||
if (!propsPart.getCategoryProperty().hasValue()) | |||
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. | |||
*/ | |||
private void addContentStatus() { | |||
if (!propsPart.getContentStatusProperty().hasValue()) | |||
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. | |||
*/ | |||
private void addContentType() { | |||
if (!propsPart.getContentTypeProperty().hasValue()) | |||
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. | |||
*/ | |||
private void addCreated() { | |||
if (!propsPart.getCreatedProperty().hasValue()) | |||
return; | |||
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. | |||
*/ | |||
private void addCreator() { | |||
if (!propsPart.getCreatorProperty().hasValue()) | |||
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. | |||
*/ | |||
private void addDescription() { | |||
if (!propsPart.getDescriptionProperty().hasValue()) | |||
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. | |||
*/ | |||
private void addIdentifier() { | |||
if (!propsPart.getIdentifierProperty().hasValue()) | |||
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. | |||
*/ | |||
private void addKeywords() { | |||
if (!propsPart.getKeywordsProperty().hasValue()) | |||
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. | |||
*/ | |||
private void addLanguage() { | |||
if (!propsPart.getLanguageProperty().hasValue()) | |||
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. | |||
*/ | |||
private void addLastModifiedBy() { | |||
if (!propsPart.getLastModifiedByProperty().hasValue()) | |||
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()); | |||
} | |||
/** | |||
* Add 'last printed' property if needed. | |||
* | |||
*/ | |||
private void addLastPrinted() { | |||
if (!propsPart.getLastPrintedProperty().hasValue()) | |||
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. | |||
*/ | |||
private void addModified() { | |||
if (!propsPart.getModifiedProperty().hasValue()) | |||
return; | |||
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. | |||
*/ | |||
private void addRevision() { | |||
if (!propsPart.getRevisionProperty().hasValue()) | |||
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. | |||
*/ | |||
private void addSubject() { | |||
if (!propsPart.getSubjectProperty().hasValue()) | |||
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. | |||
*/ | |||
private void addTitle() { | |||
if (!propsPart.getTitleProperty().hasValue()) | |||
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() { | |||
if (!propsPart.getVersionProperty().hasValue()) | |||
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()); | |||
} | |||
} |
@@ -0,0 +1,64 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc.internal.marshallers; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import java.util.zip.ZipEntry; | |||
import java.util.zip.ZipOutputStream; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.StreamHelper; | |||
import org.apache.poi.openxml4j.opc.internal.ZipHelper; | |||
/** | |||
* Package core properties marshaller specialized for zipped package. | |||
* | |||
* @author Julien Chable | |||
* @version 1.0 | |||
*/ | |||
public class ZipPackagePropertiesMarshaller extends PackagePropertiesMarshaller { | |||
@Override | |||
public boolean marshall(PackagePart part, OutputStream out) | |||
throws OpenXML4JException { | |||
if (!(out instanceof ZipOutputStream)) { | |||
throw new IllegalArgumentException("ZipOutputStream expected!"); | |||
} | |||
ZipOutputStream zos = (ZipOutputStream) out; | |||
// Saving the part in the zip file | |||
ZipEntry ctEntry = new ZipEntry(ZipHelper | |||
.getZipItemNameFromOPCName(part.getPartName().getURI() | |||
.toString())); | |||
try { | |||
// Save in ZIP | |||
zos.putNextEntry(ctEntry); // Add entry in ZIP | |||
super.marshall(part, out); // Marshall the properties inside a XML | |||
// Document | |||
if (!StreamHelper.saveXmlInStream(xmlDoc, out)) { | |||
return false; | |||
} | |||
zos.closeEntry(); | |||
} catch (IOException e) { | |||
throw new OpenXML4JException(e.getLocalizedMessage()); | |||
} | |||
return true; | |||
} | |||
} |
@@ -0,0 +1,193 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc.internal.marshallers; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import java.net.URI; | |||
import java.util.zip.ZipEntry; | |||
import java.util.zip.ZipOutputStream; | |||
import org.apache.log4j.Logger; | |||
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.opc.PackageNamespaces; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.PackagePartName; | |||
import org.apache.poi.openxml4j.opc.PackageRelationship; | |||
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; | |||
import org.apache.poi.openxml4j.opc.PackagingURIHelper; | |||
import org.apache.poi.openxml4j.opc.StreamHelper; | |||
import org.apache.poi.openxml4j.opc.TargetMode; | |||
import org.apache.poi.openxml4j.opc.internal.PartMarshaller; | |||
import org.apache.poi.openxml4j.opc.internal.ZipHelper; | |||
/** | |||
* Zip part marshaller. This marshaller is use to save any part in a zip stream. | |||
* | |||
* @author Julien Chable | |||
* @version 0.1 | |||
*/ | |||
public class ZipPartMarshaller implements PartMarshaller { | |||
private static Logger logger = Logger.getLogger("org.openxml4j"); | |||
/** | |||
* Save the specified part. | |||
* | |||
* @throws OpenXML4JException | |||
* Throws if an internal exception is thrown. | |||
*/ | |||
public boolean marshall(PackagePart part, OutputStream os) | |||
throws OpenXML4JException { | |||
if (!(os instanceof ZipOutputStream)) { | |||
logger.error("Unexpected class " + os.getClass().getName()); | |||
throw new OpenXML4JException("ZipOutputStream expected !"); | |||
// Normally should happen only in developpement phase, so just throw | |||
// exception | |||
} | |||
ZipOutputStream zos = (ZipOutputStream) os; | |||
ZipEntry partEntry = new ZipEntry(ZipHelper | |||
.getZipItemNameFromOPCName(part.getPartName().getURI() | |||
.getPath())); | |||
try { | |||
// Create next zip entry | |||
zos.putNextEntry(partEntry); | |||
// Saving data in the ZIP file | |||
InputStream ins = part.getInputStream(); | |||
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; | |||
} else { | |||
zos.write(buff, 0, resultRead); | |||
} | |||
} | |||
zos.closeEntry(); | |||
} catch (IOException ioe) { | |||
logger.error("Cannot write: " + part.getPartName() + ": in ZIP", | |||
ioe); | |||
return false; | |||
} | |||
// Saving relationship part | |||
if (part.hasRelationships()) { | |||
PackagePartName relationshipPartName = PackagingURIHelper | |||
.getRelationshipPartName(part.getPartName()); | |||
marshallRelationshipPart(part.getRelationships(), | |||
relationshipPartName, zos); | |||
} | |||
return true; | |||
} | |||
/** | |||
* Save relationships into the part. | |||
* | |||
* @param rels | |||
* The relationships collection to marshall. | |||
* @param relPartURI | |||
* Part name of the relationship part to marshall. | |||
* @param zos | |||
* Zip output stream in which to save the XML content of the | |||
* relationships serialization. | |||
*/ | |||
public static boolean marshallRelationshipPart( | |||
PackageRelationshipCollection rels, PackagePartName relPartName, | |||
ZipOutputStream zos) { | |||
// Building xml | |||
Document xmlOutDoc = DocumentHelper.createDocument(); | |||
// make something like <Relationships | |||
// xmlns="http://schemas.openxmlformats.org/package/2006/relationships"> | |||
Namespace dfNs = Namespace.get("", PackageNamespaces.RELATIONSHIPS); | |||
Element root = xmlOutDoc.addElement(new QName( | |||
PackageRelationship.RELATIONSHIPS_TAG_NAME, dfNs)); | |||
// <Relationship | |||
// TargetMode="External" | |||
// Id="rIdx" | |||
// Target="http://www.custom.com/images/pic1.jpg" | |||
// Type="http://www.custom.com/external-resource"/> | |||
URI sourcePartURI = PackagingURIHelper | |||
.getSourcePartUriFromRelationshipPartUri(relPartName.getURI()); | |||
for (PackageRelationship rel : rels) { | |||
// L'�l�ment de la relation | |||
Element relElem = root | |||
.addElement(PackageRelationship.RELATIONSHIP_TAG_NAME); | |||
// L'attribut ID | |||
relElem.addAttribute(PackageRelationship.ID_ATTRIBUTE_NAME, rel | |||
.getId()); | |||
// L'attribut Type | |||
relElem.addAttribute(PackageRelationship.TYPE_ATTRIBUTE_NAME, rel | |||
.getRelationshipType()); | |||
// L'attribut Target | |||
String targetValue; | |||
URI uri = rel.getTargetURI(); | |||
if (rel.getTargetMode() == TargetMode.EXTERNAL) { | |||
// Save the target as-is - we don't need to validate it, | |||
// alter it etc | |||
targetValue = uri.toString(); | |||
// add TargetMode attribut (as it is external link external) | |||
relElem.addAttribute( | |||
PackageRelationship.TARGET_MODE_ATTRIBUTE_NAME, | |||
"External"); | |||
} else { | |||
targetValue = PackagingURIHelper.relativizeURI( | |||
sourcePartURI, rel.getTargetURI()).getPath(); | |||
} | |||
relElem.addAttribute(PackageRelationship.TARGET_ATTRIBUTE_NAME, | |||
targetValue); | |||
} | |||
xmlOutDoc.normalize(); | |||
// String schemaFilename = Configuration.getPathForXmlSchema()+ | |||
// File.separator + "opc-relationships.xsd"; | |||
// Save part in zip | |||
ZipEntry ctEntry = new ZipEntry(ZipHelper.getZipURIFromOPCName( | |||
relPartName.getURI().toASCIIString()).getPath()); | |||
try { | |||
// Cr�ation de l'entr�e dans le fichier ZIP | |||
zos.putNextEntry(ctEntry); | |||
if (!StreamHelper.saveXmlInStream(xmlOutDoc, zos)) { | |||
return false; | |||
} | |||
zos.closeEntry(); | |||
} catch (IOException e) { | |||
logger.error("Cannot create zip entry " + relPartName, e); | |||
return false; | |||
} | |||
return true; // success | |||
} | |||
} |
@@ -0,0 +1,79 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc.internal.signature; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.internal.ContentType; | |||
/** | |||
* Digital certificate part. | |||
* | |||
* @author Julien Chable | |||
* @version 0.1 | |||
*/ | |||
public final class DigitalCertificatePart extends PackagePart { | |||
public DigitalCertificatePart() throws InvalidFormatException{ | |||
super(null, null, new ContentType("")); | |||
// Review constructor | |||
} | |||
@Override | |||
public void close() { | |||
// TODO Auto-generated method stub | |||
} | |||
@Override | |||
public void flush() { | |||
// TODO Auto-generated method stub | |||
} | |||
@Override | |||
protected InputStream getInputStreamImpl() throws IOException { | |||
// TODO Auto-generated method stub | |||
return null; | |||
} | |||
@Override | |||
protected OutputStream getOutputStreamImpl() { | |||
// TODO Auto-generated method stub | |||
return null; | |||
} | |||
@Override | |||
public boolean load(InputStream ios) throws InvalidFormatException { | |||
// TODO Auto-generated method stub | |||
return false; | |||
} | |||
@Override | |||
public boolean save(OutputStream zos) throws OpenXML4JException { | |||
// TODO Auto-generated method stub | |||
return false; | |||
} | |||
// TODO Introduire le concept de partie typ�e d�s cette partie | |||
} |
@@ -0,0 +1,28 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc.internal.signature; | |||
/** | |||
* Represents a digital signature origin part. | |||
* | |||
* @author Julien Chable | |||
* @version 0.1 | |||
*/ | |||
public class DigitalSignatureOriginPart { | |||
} |
@@ -0,0 +1,390 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc.internal.unmarshallers; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.zip.ZipEntry; | |||
import org.dom4j.Attribute; | |||
import org.dom4j.Document; | |||
import org.dom4j.DocumentException; | |||
import org.dom4j.Element; | |||
import org.dom4j.Namespace; | |||
import org.dom4j.QName; | |||
import org.dom4j.io.SAXReader; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.PackageNamespaces; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.PackageProperties; | |||
import org.apache.poi.openxml4j.opc.ZipPackage; | |||
import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart; | |||
import org.apache.poi.openxml4j.opc.internal.PartUnmarshaller; | |||
import org.apache.poi.openxml4j.opc.internal.ZipHelper; | |||
/** | |||
* Package properties unmarshaller. | |||
* | |||
* @author Julien Chable | |||
* @version 1.0 | |||
*/ | |||
public 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_CONTENT_STATUS = "contentStatus"; | |||
protected static final String KEYWORD_CONTENT_TYPE = "contentType"; | |||
protected static final String KEYWORD_CREATED = "created"; | |||
protected static final String KEYWORD_CREATOR = "creator"; | |||
protected static final String KEYWORD_DESCRIPTION = "description"; | |||
protected static final String KEYWORD_IDENTIFIER = "identifier"; | |||
protected static final String KEYWORD_KEYWORDS = "keywords"; | |||
protected static final String KEYWORD_LANGUAGE = "language"; | |||
protected static final String KEYWORD_LAST_MODIFIED_BY = "lastModifiedBy"; | |||
protected static final String KEYWORD_LAST_PRINTED = "lastPrinted"; | |||
protected static final String KEYWORD_MODIFIED = "modified"; | |||
protected static final String KEYWORD_REVISION = "revision"; | |||
protected static final String KEYWORD_SUBJECT = "subject"; | |||
protected static final String KEYWORD_TITLE = "title"; | |||
protected static final String KEYWORD_VERSION = "version"; | |||
// TODO Load element with XMLBeans or dynamic table | |||
// TODO Check every element/namespace for compliance | |||
public PackagePart unmarshall(UnmarshallContext context, InputStream in) | |||
throws InvalidFormatException, IOException { | |||
PackagePropertiesPart coreProps = new PackagePropertiesPart(context | |||
.getPackage(), context.getPartName()); | |||
// If the input stream is null then we try to get it from the | |||
// package. | |||
if (in == null) { | |||
if (context.getZipEntry() != null) { | |||
in = ((ZipPackage) context.getPackage()).getZipArchive() | |||
.getInputStream(context.getZipEntry()); | |||
} else if (context.getPackage() != null) { | |||
// Try to retrieve the part inputstream from the URI | |||
ZipEntry zipEntry; | |||
try { | |||
zipEntry = ZipHelper | |||
.getCorePropertiesZipEntry((ZipPackage) context | |||
.getPackage()); | |||
} catch (OpenXML4JException e) { | |||
throw new IOException( | |||
"Error while trying to get the part input stream."); | |||
} | |||
in = ((ZipPackage) context.getPackage()).getZipArchive() | |||
.getInputStream(zipEntry); | |||
} else | |||
throw new IOException( | |||
"Error while trying to get the part input stream."); | |||
} | |||
SAXReader xmlReader = new SAXReader(); | |||
Document xmlDoc; | |||
try { | |||
xmlDoc = xmlReader.read(in); | |||
/* Check OPC compliance */ | |||
// Rule M4.2, M4.3, M4.4 and M4.5/ | |||
checkElementForOPCCompliance(xmlDoc.getRootElement()); | |||
/* End OPC compliance */ | |||
} catch (DocumentException e) { | |||
throw new IOException(e.getMessage()); | |||
} | |||
coreProps.setCategoryProperty(loadCategory(xmlDoc)); | |||
coreProps.setContentStatusProperty(loadContentStatus(xmlDoc)); | |||
coreProps.setContentTypeProperty(loadContentType(xmlDoc)); | |||
coreProps.setCreatedProperty(loadCreated(xmlDoc)); | |||
coreProps.setCreatorProperty(loadCreator(xmlDoc)); | |||
coreProps.setDescriptionProperty(loadDescription(xmlDoc)); | |||
coreProps.setIdentifierProperty(loadIdentifier(xmlDoc)); | |||
coreProps.setKeywordsProperty(loadKeywords(xmlDoc)); | |||
coreProps.setLanguageProperty(loadLanguage(xmlDoc)); | |||
coreProps.setLastModifiedByProperty(loadLastModifiedBy(xmlDoc)); | |||
coreProps.setLastPrintedProperty(loadLastPrinted(xmlDoc)); | |||
coreProps.setModifiedProperty(loadModified(xmlDoc)); | |||
coreProps.setRevisionProperty(loadRevision(xmlDoc)); | |||
coreProps.setSubjectProperty(loadSubject(xmlDoc)); | |||
coreProps.setTitleProperty(loadTitle(xmlDoc)); | |||
coreProps.setVersionProperty(loadVersion(xmlDoc)); | |||
return coreProps; | |||
} | |||
private String loadCategory(Document xmlDoc) { | |||
Element el = xmlDoc.getRootElement().element( | |||
new QName(KEYWORD_CATEGORY, namespaceCP)); | |||
if (el != null) | |||
return el.getStringValue(); | |||
else | |||
return null; | |||
} | |||
private String loadContentStatus(Document xmlDoc) { | |||
Element el = xmlDoc.getRootElement().element( | |||
new QName(KEYWORD_CONTENT_STATUS, namespaceCP)); | |||
if (el != null) | |||
return el.getStringValue(); | |||
else | |||
return null; | |||
} | |||
private String loadContentType(Document xmlDoc) { | |||
Element el = xmlDoc.getRootElement().element( | |||
new QName(KEYWORD_CONTENT_TYPE, namespaceCP)); | |||
if (el != null) | |||
return el.getStringValue(); | |||
else | |||
return null; | |||
} | |||
private String loadCreated(Document xmlDoc) { | |||
Element el = xmlDoc.getRootElement().element( | |||
new QName(KEYWORD_CREATED, namespaceDcTerms)); | |||
if (el != null) | |||
return el.getStringValue(); | |||
else | |||
return null; | |||
} | |||
private String loadCreator(Document xmlDoc) { | |||
Element el = xmlDoc.getRootElement().element( | |||
new QName(KEYWORD_CREATOR, namespaceDC)); | |||
if (el != null) | |||
return el.getStringValue(); | |||
else | |||
return null; | |||
} | |||
private String loadDescription(Document xmlDoc) { | |||
Element el = xmlDoc.getRootElement().element( | |||
new QName(KEYWORD_DESCRIPTION, namespaceDC)); | |||
if (el != null) | |||
return el.getStringValue(); | |||
else | |||
return null; | |||
} | |||
private String loadIdentifier(Document xmlDoc) { | |||
Element el = xmlDoc.getRootElement().element( | |||
new QName(KEYWORD_IDENTIFIER, namespaceDC)); | |||
if (el != null) | |||
return el.getStringValue(); | |||
else | |||
return null; | |||
} | |||
private String loadKeywords(Document xmlDoc) { | |||
Element el = xmlDoc.getRootElement().element( | |||
new QName(KEYWORD_KEYWORDS, namespaceCP)); | |||
if (el != null) | |||
return el.getStringValue(); | |||
else | |||
return null; | |||
} | |||
private String loadLanguage(Document xmlDoc) { | |||
Element el = xmlDoc.getRootElement().element( | |||
new QName(KEYWORD_LANGUAGE, namespaceDC)); | |||
if (el != null) | |||
return el.getStringValue(); | |||
else | |||
return null; | |||
} | |||
private String loadLastModifiedBy(Document xmlDoc) { | |||
Element el = xmlDoc.getRootElement().element( | |||
new QName(KEYWORD_LAST_MODIFIED_BY, namespaceCP)); | |||
if (el != null) | |||
return el.getStringValue(); | |||
else | |||
return null; | |||
} | |||
private String loadLastPrinted(Document xmlDoc) { | |||
Element el = xmlDoc.getRootElement().element( | |||
new QName(KEYWORD_LAST_PRINTED, namespaceCP)); | |||
if (el != null) | |||
return el.getStringValue(); | |||
else | |||
return null; | |||
} | |||
private String loadModified(Document xmlDoc) { | |||
Element el = xmlDoc.getRootElement().element( | |||
new QName(KEYWORD_MODIFIED, namespaceDcTerms)); | |||
if (el != null) | |||
return el.getStringValue(); | |||
else | |||
return null; | |||
} | |||
private String loadRevision(Document xmlDoc) { | |||
Element el = xmlDoc.getRootElement().element( | |||
new QName(KEYWORD_REVISION, namespaceCP)); | |||
if (el != null) | |||
return el.getStringValue(); | |||
else | |||
return null; | |||
} | |||
private String loadSubject(Document xmlDoc) { | |||
Element el = xmlDoc.getRootElement().element( | |||
new QName(KEYWORD_SUBJECT, namespaceDC)); | |||
if (el != null) | |||
return el.getStringValue(); | |||
else | |||
return null; | |||
} | |||
private String loadTitle(Document xmlDoc) { | |||
Element el = xmlDoc.getRootElement().element( | |||
new QName(KEYWORD_TITLE, namespaceDC)); | |||
if (el != null) | |||
return el.getStringValue(); | |||
else | |||
return null; | |||
} | |||
private String loadVersion(Document xmlDoc) { | |||
Element el = xmlDoc.getRootElement().element( | |||
new QName(KEYWORD_VERSION, namespaceCP)); | |||
if (el != null) | |||
return el.getStringValue(); | |||
else | |||
return null; | |||
} | |||
/* OPC Compliance methods */ | |||
/** | |||
* Check the element for the following OPC compliance rules: | |||
* | |||
* Rule M4.2: A format consumer shall consider the use of the Markup | |||
* Compatibility namespace to be an error. | |||
* | |||
* Rule 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: 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: Producers shall not create a document element that contains | |||
* the xsi:type attribute, except for a <dcterms:created> or | |||
* <dcterms:modified> element where the xsi:type attribute shall be present | |||
* and shall hold the value dcterms:W3CDTF, where dcterms is the namespace | |||
* prefix of the Dublin Core namespace. Consumers shall consider a document | |||
* element that violates this constraint to be an error. | |||
*/ | |||
public void checkElementForOPCCompliance(Element el) | |||
throws InvalidFormatException { | |||
// Check the current element | |||
List declaredNamespaces = el.declaredNamespaces(); | |||
Iterator itNS = declaredNamespaces.iterator(); | |||
while (itNS.hasNext()) { | |||
Namespace ns = (Namespace) itNS.next(); | |||
// Rule M4.2 | |||
if (ns.getURI().equals(PackageNamespaces.MARKUP_COMPATIBILITY)) | |||
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 | |||
if (el.getNamespace().getURI().equals( | |||
PackageProperties.NAMESPACE_DCTERMS) | |||
&& !(el.getName().equals(KEYWORD_CREATED) || el.getName() | |||
.equals(KEYWORD_MODIFIED))) | |||
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."); | |||
// Rule M4.4 | |||
if (el.attribute(new QName("lang", namespaceXML)) != null) | |||
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."); | |||
// Rule M4.5 | |||
if (el.getNamespace().getURI().equals( | |||
PackageProperties.NAMESPACE_DCTERMS)) { | |||
// DCTerms namespace only use with 'created' and 'modified' elements | |||
String elName = el.getName(); | |||
if (!(elName.equals(KEYWORD_CREATED) || elName | |||
.equals(KEYWORD_MODIFIED))) | |||
throw new InvalidFormatException("Namespace error : " + elName | |||
+ " shouldn't have the following naemspace -> " | |||
+ PackageProperties.NAMESPACE_DCTERMS); | |||
// Check for the 'xsi:type' attribute | |||
Attribute typeAtt = el.attribute(new QName("type", namespaceXSI)); | |||
if (typeAtt == null) | |||
throw new InvalidFormatException("The element '" + elName | |||
+ "' must have the '" + namespaceXSI.getPrefix() | |||
+ ":type' attribute present !"); | |||
// Check for the attribute value => 'dcterms:W3CDTF' | |||
if (!typeAtt.getValue().equals("dcterms:W3CDTF")) | |||
throw new InvalidFormatException("The element '" + elName | |||
+ "' must have the '" + namespaceXSI.getPrefix() | |||
+ ":type' attribute with the value 'dcterms:W3CDTF' !"); | |||
} | |||
// Check its children | |||
Iterator itChildren = el.elementIterator(); | |||
while (itChildren.hasNext()) | |||
checkElementForOPCCompliance((Element) itChildren.next()); | |||
} | |||
} |
@@ -0,0 +1,96 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc.internal.unmarshallers; | |||
import java.util.zip.ZipEntry; | |||
import org.apache.poi.openxml4j.opc.Package; | |||
import org.apache.poi.openxml4j.opc.PackagePartName; | |||
/** | |||
* Context needed for the unmarshall process of a part. This class is immutable. | |||
* | |||
* @author Julien Chable | |||
* @version 1.0 | |||
*/ | |||
public final class UnmarshallContext { | |||
private Package _package; | |||
private PackagePartName partName; | |||
private ZipEntry zipEntry; | |||
/** | |||
* Constructor. | |||
* | |||
* @param targetPackage | |||
* Container. | |||
* @param partName | |||
* Name of the part to unmarshall. | |||
*/ | |||
public UnmarshallContext(Package targetPackage, PackagePartName partName) { | |||
this._package = targetPackage; | |||
this.partName = partName; | |||
} | |||
/** | |||
* @return the container | |||
*/ | |||
Package getPackage() { | |||
return _package; | |||
} | |||
/** | |||
* @param container | |||
* the container to set | |||
*/ | |||
public void setPackage(Package container) { | |||
this._package = container; | |||
} | |||
/** | |||
* @return the partName | |||
*/ | |||
PackagePartName getPartName() { | |||
return partName; | |||
} | |||
/** | |||
* @param partName | |||
* the partName to set | |||
*/ | |||
public void setPartName(PackagePartName partName) { | |||
this.partName = partName; | |||
} | |||
/** | |||
* @return the zipEntry | |||
*/ | |||
ZipEntry getZipEntry() { | |||
return zipEntry; | |||
} | |||
/** | |||
* @param zipEntry | |||
* the zipEntry to set | |||
*/ | |||
public void setZipEntry(ZipEntry zipEntry) { | |||
this.zipEntry = zipEntry; | |||
} | |||
} |
@@ -0,0 +1,70 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc.signature; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.OutputStream; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.internal.ContentType; | |||
public class PackageDigitalSignature extends PackagePart { | |||
public PackageDigitalSignature() throws InvalidFormatException { | |||
super(null, null, new ContentType("")); | |||
} | |||
@Override | |||
public void close() { | |||
// TODO Auto-generated method stub | |||
} | |||
@Override | |||
public void flush() { | |||
// TODO Auto-generated method stub | |||
} | |||
@Override | |||
protected InputStream getInputStreamImpl() throws IOException { | |||
// TODO Auto-generated method stub | |||
return null; | |||
} | |||
@Override | |||
protected OutputStream getOutputStreamImpl() { | |||
// TODO Auto-generated method stub | |||
return null; | |||
} | |||
@Override | |||
public boolean load(InputStream ios) throws InvalidFormatException { | |||
// TODO Auto-generated method stub | |||
return false; | |||
} | |||
@Override | |||
public boolean save(OutputStream zos) throws OpenXML4JException { | |||
// TODO Auto-generated method stub | |||
return false; | |||
} | |||
} |
@@ -0,0 +1,22 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc.signature; | |||
public class PackageDigitalSignatureManager { | |||
} |
@@ -0,0 +1,71 @@ | |||
/* ==================================================================== | |||
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.openxml4j.util; | |||
/** | |||
* An immutable object that could be defined as null. | |||
* | |||
* @author Julien Chable | |||
* @version 0.9 | |||
*/ | |||
public final class Nullable<E> { | |||
private E value; | |||
/** | |||
* Constructor. | |||
*/ | |||
public Nullable() { | |||
// Do nothing | |||
} | |||
/** | |||
* Constructor. | |||
* | |||
* @param value | |||
* The value to set to this nullable. | |||
*/ | |||
public Nullable(E value) { | |||
this.value = value; | |||
} | |||
/** | |||
* Get the store value if any. | |||
* | |||
* @return | |||
*/ | |||
public E getValue() { | |||
return value; | |||
} | |||
/** | |||
* Get the status of this nullable. | |||
* | |||
* @return <b>true</b> if the nullable store a value (empty string is | |||
* considered to be a value) else <b>false</>. | |||
*/ | |||
public boolean hasValue() { | |||
return value != null; | |||
} | |||
/** | |||
* Set the stored value to <i>null</i>. | |||
*/ | |||
public void nullify() { | |||
value = null; | |||
} | |||
} |
@@ -0,0 +1,48 @@ | |||
/* ==================================================================== | |||
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.openxml4j.util; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.util.Enumeration; | |||
import java.util.zip.ZipEntry; | |||
/** | |||
* An Interface to make getting the different bits | |||
* of a Zip File easy. | |||
* Allows you to get at the ZipEntries, without | |||
* needing to worry about ZipFile vs ZipInputStream | |||
* being annoyingly very different. | |||
*/ | |||
public interface ZipEntrySource { | |||
/** | |||
* Returns an Enumeration of all the Entries | |||
*/ | |||
public Enumeration<? extends ZipEntry> getEntries(); | |||
/** | |||
* Returns an InputStream of the decompressed | |||
* data that makes up the entry | |||
*/ | |||
public InputStream getInputStream(ZipEntry entry) throws IOException; | |||
/** | |||
* Indicates we are done with reading, and | |||
* resources may be freed | |||
*/ | |||
public void close() throws IOException; | |||
} |
@@ -0,0 +1,48 @@ | |||
/* ==================================================================== | |||
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.openxml4j.util; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.util.Enumeration; | |||
import java.util.zip.ZipEntry; | |||
import java.util.zip.ZipFile; | |||
/** | |||
* A ZipEntrySource wrapper around a ZipFile. | |||
* Should be as low in terms of memory as a | |||
* normal ZipFile implementation is. | |||
*/ | |||
public class ZipFileZipEntrySource implements ZipEntrySource { | |||
private ZipFile zipArchive; | |||
public ZipFileZipEntrySource(ZipFile zipFile) { | |||
this.zipArchive = zipFile; | |||
} | |||
public void close() throws IOException { | |||
zipArchive.close(); | |||
zipArchive = null; | |||
} | |||
public Enumeration<? extends ZipEntry> getEntries() { | |||
return zipArchive.entries(); | |||
} | |||
public InputStream getInputStream(ZipEntry entry) throws IOException { | |||
return zipArchive.getInputStream(entry); | |||
} | |||
} |
@@ -0,0 +1,125 @@ | |||
/* ==================================================================== | |||
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.openxml4j.util; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.util.ArrayList; | |||
import java.util.Enumeration; | |||
import java.util.Iterator; | |||
import java.util.zip.ZipEntry; | |||
import java.util.zip.ZipInputStream; | |||
/** | |||
* Provides a way to get at all the ZipEntries | |||
* from a ZipInputStream, as many times as required. | |||
* Allows a ZipInputStream to be treated much like | |||
* a ZipFile, for a price in terms of memory. | |||
* Be sure to call {@link #close()} as soon as you're | |||
* done, to free up that memory! | |||
*/ | |||
public class ZipInputStreamZipEntrySource implements ZipEntrySource { | |||
private ArrayList<FakeZipEntry> zipEntries; | |||
/** | |||
* Reads all the entries from the ZipInputStream | |||
* into memory, and closes the source stream. | |||
* We'll then eat lots of memory, but be able to | |||
* work with the entries at-will. | |||
*/ | |||
public ZipInputStreamZipEntrySource(ZipInputStream inp) throws IOException { | |||
zipEntries = new ArrayList<FakeZipEntry>(); | |||
boolean going = true; | |||
while(going) { | |||
ZipEntry zipEntry = inp.getNextEntry(); | |||
if(zipEntry == null) { | |||
going = false; | |||
} else { | |||
FakeZipEntry entry = new FakeZipEntry(zipEntry, inp); | |||
inp.closeEntry(); | |||
zipEntries.add(entry); | |||
} | |||
} | |||
inp.close(); | |||
} | |||
public Enumeration<? extends ZipEntry> getEntries() { | |||
return new EntryEnumerator(); | |||
} | |||
public InputStream getInputStream(ZipEntry zipEntry) { | |||
FakeZipEntry entry = (FakeZipEntry)zipEntry; | |||
return entry.getInputStream(); | |||
} | |||
public void close() { | |||
// Free the memory | |||
zipEntries = null; | |||
} | |||
/** | |||
* Why oh why oh why are Iterator and Enumeration | |||
* still not compatible? | |||
*/ | |||
private class EntryEnumerator implements Enumeration<ZipEntry> { | |||
private Iterator<? extends ZipEntry> iterator; | |||
private EntryEnumerator() { | |||
iterator = zipEntries.iterator(); | |||
} | |||
public boolean hasMoreElements() { | |||
return iterator.hasNext(); | |||
} | |||
public ZipEntry nextElement() { | |||
return iterator.next(); | |||
} | |||
} | |||
/** | |||
* So we can close the real zip entry and still | |||
* effectively work with it. | |||
* Holds the (decompressed!) data in memory, so | |||
* close this as soon as you can! | |||
*/ | |||
public static class FakeZipEntry extends ZipEntry { | |||
private byte[] data; | |||
public FakeZipEntry(ZipEntry entry, ZipInputStream inp) throws IOException { | |||
super(entry.getName()); | |||
// Grab the de-compressed contents for later | |||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |||
byte[] buffer = new byte[4096]; | |||
int read = 0; | |||
while( (read = inp.read(buffer)) != -1 ) { | |||
baos.write(buffer, 0, read); | |||
} | |||
data = baos.toByteArray(); | |||
} | |||
public InputStream getInputStream() { | |||
return new ByteArrayInputStream(data); | |||
} | |||
} | |||
} |
@@ -24,7 +24,7 @@ import org.apache.poi.POIXMLDocument; | |||
import org.apache.poi.hssf.usermodel.HSSFWorkbook; | |||
import org.apache.poi.poifs.filesystem.POIFSFileSystem; | |||
import org.apache.poi.xssf.usermodel.XSSFWorkbook; | |||
import org.openxml4j.opc.Package; | |||
import org.apache.poi.openxml4j.opc.Package; | |||
/** | |||
* Factory for creating the appropriate kind of Workbook |
@@ -16,16 +16,12 @@ | |||
==================================================================== */ | |||
package org.apache.poi.util; | |||
import org.openxml4j.opc.*; | |||
import org.openxml4j.opc.Package; | |||
import org.openxml4j.opc.internal.PackagePropertiesPart; | |||
import org.openxml4j.opc.internal.marshallers.PackagePropertiesMarshaller; | |||
import org.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.*; | |||
import org.apache.poi.openxml4j.opc.Package; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.util.IOUtils; | |||
import java.io.*; | |||
import java.util.ArrayList; | |||
import java.lang.reflect.Method; | |||
/** | |||
* Provides handy methods to work with OOXML packages |
@@ -22,12 +22,12 @@ import java.util.LinkedList; | |||
import org.apache.poi.POIXMLDocument; | |||
import org.apache.xmlbeans.XmlException; | |||
import org.openxml4j.exceptions.InvalidFormatException; | |||
import org.openxml4j.exceptions.OpenXML4JException; | |||
import org.openxml4j.opc.Package; | |||
import org.openxml4j.opc.PackagePart; | |||
import org.openxml4j.opc.PackageRelationship; | |||
import org.openxml4j.opc.PackageRelationshipCollection; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.Package; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.PackageRelationship; | |||
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; | |||
import org.openxmlformats.schemas.presentationml.x2006.main.CTCommentList; | |||
import org.openxmlformats.schemas.presentationml.x2006.main.CTNotesSlide; | |||
import org.openxmlformats.schemas.presentationml.x2006.main.CTPresentation; |
@@ -23,8 +23,8 @@ import org.apache.poi.xslf.XSLFSlideShow; | |||
import org.apache.poi.xslf.usermodel.XMLSlideShow; | |||
import org.apache.poi.xslf.usermodel.XSLFSlide; | |||
import org.apache.xmlbeans.XmlException; | |||
import org.openxml4j.exceptions.OpenXML4JException; | |||
import org.openxml4j.opc.Package; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.Package; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph; |
@@ -25,14 +25,14 @@ import org.apache.poi.xssf.model.StylesTable; | |||
import org.apache.poi.xssf.usermodel.XSSFRelation; | |||
import org.apache.poi.POIXMLException; | |||
import org.apache.xmlbeans.XmlException; | |||
import org.openxml4j.exceptions.InvalidFormatException; | |||
import org.openxml4j.exceptions.OpenXML4JException; | |||
import org.openxml4j.opc.Package; | |||
import org.openxml4j.opc.PackagePart; | |||
import org.openxml4j.opc.PackagePartName; | |||
import org.openxml4j.opc.PackageRelationship; | |||
import org.openxml4j.opc.PackageRelationshipTypes; | |||
import org.openxml4j.opc.PackagingURIHelper; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.Package; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.PackagePartName; | |||
import org.apache.poi.openxml4j.opc.PackageRelationship; | |||
import org.apache.poi.openxml4j.opc.PackageRelationshipTypes; | |||
import org.apache.poi.openxml4j.opc.PackagingURIHelper; | |||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbook; | |||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.WorkbookDocument; | |||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet; |
@@ -29,8 +29,8 @@ import org.apache.poi.xssf.usermodel.XSSFCell; | |||
import org.apache.poi.xssf.usermodel.XSSFSheet; | |||
import org.apache.poi.xssf.usermodel.XSSFWorkbook; | |||
import org.apache.xmlbeans.XmlException; | |||
import org.openxml4j.exceptions.OpenXML4JException; | |||
import org.openxml4j.opc.Package; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.Package; | |||
/** | |||
* Helper class to extract text from an OOXML Excel file |
@@ -29,8 +29,8 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment; | |||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCommentList; | |||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComments; | |||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CommentsDocument; | |||
import org.openxml4j.opc.PackagePart; | |||
import org.openxml4j.opc.PackageRelationship; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.PackageRelationship; | |||
public class CommentsTable extends POIXMLDocumentPart { | |||
protected CTComments comments; |
@@ -31,9 +31,8 @@ import org.apache.poi.POIXMLDocumentPart; | |||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst; | |||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSst; | |||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.SstDocument; | |||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet; | |||
import org.openxml4j.opc.PackagePart; | |||
import org.openxml4j.opc.PackageRelationship; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.PackageRelationship; | |||
/** |
@@ -48,8 +48,8 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTStylesheet; | |||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXf; | |||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPatternType; | |||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.StyleSheetDocument; | |||
import org.openxml4j.opc.PackagePart; | |||
import org.openxml4j.opc.PackageRelationship; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.PackageRelationship; | |||
/** |
@@ -17,7 +17,7 @@ | |||
package org.apache.poi.xssf.model; | |||
import org.apache.poi.xssf.usermodel.XSSFRelation; | |||
import org.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
/** | |||
* Common interface for XSSF models, which have (typically |
@@ -7,7 +7,7 @@ import org.apache.poi.ss.usermodel.PictureData; | |||
import org.apache.poi.util.IOUtils; | |||
import org.apache.poi.xssf.model.XSSFWritableModel; | |||
import org.apache.poi.POIXMLException; | |||
import org.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
public class XSSFActiveXData implements PictureData, XSSFWritableModel { | |||
@@ -17,15 +17,8 @@ | |||
package org.apache.poi.xssf.usermodel; | |||
import org.apache.poi.ss.usermodel.Row; | |||
import org.apache.poi.ss.usermodel.Sheet; | |||
import org.apache.poi.POIXMLException; | |||
import org.apache.xmlbeans.XmlException; | |||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.*; | |||
import org.openxml4j.opc.PackagePart; | |||
import org.openxml4j.opc.PackageRelationship; | |||
import java.io.IOException; | |||
//YK: TODO: this is only a prototype | |||
public class XSSFDialogsheet extends XSSFSheet implements Sheet{ |
@@ -21,7 +21,7 @@ import org.apache.poi.ss.usermodel.Drawing; | |||
import org.apache.poi.ss.usermodel.ClientAnchor; | |||
import org.apache.xmlbeans.XmlException; | |||
import org.apache.xmlbeans.XmlOptions; | |||
import org.openxml4j.opc.*; | |||
import org.apache.poi.openxml4j.opc.*; | |||
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.*; | |||
import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId; | |||
@@ -22,8 +22,8 @@ import org.apache.poi.POIXMLException; | |||
import org.apache.poi.POIXMLRelation; | |||
import org.apache.poi.util.POILogger; | |||
import org.apache.poi.util.POILogFactory; | |||
import org.openxml4j.opc.PackageRelationship; | |||
import org.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.PackageRelationship; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import java.lang.reflect.Constructor; | |||
@@ -22,8 +22,8 @@ import org.apache.poi.ss.usermodel.Hyperlink; | |||
import org.apache.poi.ss.util.CellReference; | |||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHyperlink; | |||
import org.openxml4j.opc.PackagePart; | |||
import org.openxml4j.opc.PackageRelationship; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.PackageRelationship; | |||
/** |
@@ -23,8 +23,8 @@ import org.apache.poi.ss.usermodel.Picture; | |||
import org.apache.poi.util.POILogger; | |||
import org.apache.poi.util.POILogFactory; | |||
import org.apache.poi.POIXMLDocumentPart; | |||
import org.openxml4j.opc.PackageRelationship; | |||
import org.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.PackageRelationship; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import org.w3c.dom.NodeList; | |||
import org.w3c.dom.Element; | |||
import javax.imageio.ImageIO; |
@@ -24,8 +24,8 @@ import org.apache.poi.util.IOUtils; | |||
import org.apache.poi.POIXMLDocumentPart; | |||
import org.apache.poi.POIXMLException; | |||
import org.apache.poi.POIXMLRelation; | |||
import org.openxml4j.opc.PackagePart; | |||
import org.openxml4j.opc.PackageRelationship; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.PackageRelationship; | |||
/** | |||
* Raw picture data, normally attached to a SpreadsheetML Drawing. |
@@ -30,12 +30,12 @@ import org.apache.poi.xssf.model.SharedStringsTable; | |||
import org.apache.poi.xssf.model.CommentsTable; | |||
import org.apache.poi.util.POILogFactory; | |||
import org.apache.poi.util.POILogger; | |||
import org.openxml4j.exceptions.InvalidFormatException; | |||
import org.openxml4j.opc.PackagePart; | |||
import org.openxml4j.opc.PackagePartName; | |||
import org.openxml4j.opc.PackageRelationship; | |||
import org.openxml4j.opc.PackageRelationshipCollection; | |||
import org.openxml4j.opc.PackagingURIHelper; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.PackagePartName; | |||
import org.apache.poi.openxml4j.opc.PackageRelationship; | |||
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; | |||
import org.apache.poi.openxml4j.opc.PackagingURIHelper; | |||
/** | |||
* |
@@ -18,7 +18,7 @@ package org.apache.poi.xssf.usermodel; | |||
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.*; | |||
import org.openxmlformats.schemas.drawingml.x2006.main.*; | |||
import org.openxml4j.opc.PackageRelationship; | |||
import org.apache.poi.openxml4j.opc.PackageRelationship; | |||
/** | |||
* This object specifies a group shape that represents many shapes grouped together. This shape is to be treated |
@@ -39,10 +39,10 @@ import org.apache.poi.util.POILogger; | |||
import org.apache.poi.util.POILogFactory; | |||
import org.apache.xmlbeans.XmlOptions; | |||
import org.apache.xmlbeans.XmlException; | |||
import org.openxml4j.opc.PackagePart; | |||
import org.openxml4j.opc.PackageRelationship; | |||
import org.openxml4j.opc.PackageRelationshipCollection; | |||
import org.openxml4j.exceptions.InvalidFormatException; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.PackageRelationship; | |||
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.*; | |||
import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId; | |||
@@ -50,14 +50,14 @@ import org.apache.poi.xssf.model.StylesTable; | |||
import org.apache.xmlbeans.XmlException; | |||
import org.apache.xmlbeans.XmlObject; | |||
import org.apache.xmlbeans.XmlOptions; | |||
import org.openxml4j.exceptions.OpenXML4JException; | |||
import org.openxml4j.opc.Package; | |||
import org.openxml4j.opc.PackagePart; | |||
import org.openxml4j.opc.PackagePartName; | |||
import org.openxml4j.opc.PackageRelationship; | |||
import org.openxml4j.opc.PackageRelationshipTypes; | |||
import org.openxml4j.opc.PackagingURIHelper; | |||
import org.openxml4j.opc.TargetMode; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.Package; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.PackagePartName; | |||
import org.apache.poi.openxml4j.opc.PackageRelationship; | |||
import org.apache.poi.openxml4j.opc.PackageRelationshipTypes; | |||
import org.apache.poi.openxml4j.opc.PackagingURIHelper; | |||
import org.apache.poi.openxml4j.opc.TargetMode; | |||
import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId; | |||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBookView; | |||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBookViews; |
@@ -29,8 +29,8 @@ import org.apache.poi.xwpf.model.XWPFParagraphDecorator; | |||
import org.apache.poi.xwpf.usermodel.XWPFParagraph; | |||
import org.apache.poi.xwpf.usermodel.XWPFTable; | |||
import org.apache.xmlbeans.XmlException; | |||
import org.openxml4j.exceptions.OpenXML4JException; | |||
import org.openxml4j.opc.Package; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.Package; | |||
/** | |||
* Helper class to extract text from an OOXML Word file |
@@ -22,7 +22,7 @@ import org.apache.poi.xwpf.usermodel.XWPFDocument; | |||
import org.apache.poi.xwpf.usermodel.XWPFFooter; | |||
import org.apache.poi.xwpf.usermodel.XWPFHeader; | |||
import org.apache.xmlbeans.XmlException; | |||
import org.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtrRef; | |||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr; | |||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.FtrDocument; |
@@ -27,10 +27,10 @@ import org.apache.poi.util.PackageHelper; | |||
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy; | |||
import org.apache.xmlbeans.XmlException; | |||
import org.apache.xmlbeans.XmlOptions; | |||
import org.openxml4j.exceptions.InvalidFormatException; | |||
import org.openxml4j.exceptions.OpenXML4JException; | |||
import org.openxml4j.opc.*; | |||
import org.openxml4j.opc.Package; | |||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; | |||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||
import org.apache.poi.openxml4j.opc.*; | |||
import org.apache.poi.openxml4j.opc.Package; | |||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody; | |||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTComment; | |||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDocument1; |
@@ -22,8 +22,8 @@ import org.apache.poi.POIXMLException; | |||
import org.apache.poi.POIXMLRelation; | |||
import org.apache.poi.util.POILogger; | |||
import org.apache.poi.util.POILogFactory; | |||
import org.openxml4j.opc.PackageRelationship; | |||
import org.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.PackageRelationship; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import java.lang.reflect.Constructor; | |||
@@ -25,8 +25,8 @@ import org.apache.poi.util.IOUtils; | |||
import org.apache.poi.xslf.XSLFSlideShow; | |||
import org.apache.poi.xssf.usermodel.XSSFWorkbook; | |||
import org.apache.poi.xwpf.usermodel.XWPFDocument; | |||
import org.openxml4j.opc.Package; | |||
import org.openxml4j.opc.PackagePart; | |||
import org.apache.poi.openxml4j.opc.Package; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
import junit.framework.TestCase; | |||
@@ -20,7 +20,7 @@ import java.io.File; | |||
import org.apache.poi.xssf.extractor.XSSFExcelExtractor; | |||
import org.apache.poi.xssf.usermodel.XSSFWorkbook; | |||
import org.openxml4j.opc.Package; | |||
import org.apache.poi.openxml4j.opc.Package; | |||
import junit.framework.TestCase; | |||
@@ -33,7 +33,7 @@ public class TestXMLPropertiesTextExtractor extends TestCase { | |||
} | |||
public void testGetFromMainExtractor() throws Exception { | |||
org.openxml4j.opc.Package pkg = Package.open( | |||
org.apache.poi.openxml4j.opc.Package pkg = Package.open( | |||
(new File(dirname, "ExcelWithAttachments.xlsx")).toString() | |||
); | |||
XSSFWorkbook wb = new XSSFWorkbook(pkg); | |||
@@ -54,7 +54,7 @@ public class TestXMLPropertiesTextExtractor extends TestCase { | |||
} | |||
public void testCore() throws Exception { | |||
org.openxml4j.opc.Package pkg = Package.open( | |||
org.apache.poi.openxml4j.opc.Package pkg = Package.open( | |||
(new File(dirname, "ExcelWithAttachments.xlsx")).toString() | |||
); | |||
XSSFWorkbook wb = new XSSFWorkbook(pkg); | |||
@@ -71,7 +71,7 @@ public class TestXMLPropertiesTextExtractor extends TestCase { | |||
} | |||
public void testExtended() throws Exception { | |||
org.openxml4j.opc.Package pkg = Package.open( | |||
org.apache.poi.openxml4j.opc.Package pkg = Package.open( | |||
(new File(dirname, "ExcelWithAttachments.xlsx")).toString() | |||
); | |||
XSSFWorkbook wb = new XSSFWorkbook(pkg); |
@@ -33,8 +33,8 @@ import org.apache.poi.xwpf.extractor.XWPFWordExtractor; | |||
import junit.framework.TestCase; | |||
import org.openxml4j.exceptions.InvalidOperationException; | |||
import org.openxml4j.opc.Package; | |||
import org.apache.poi.openxml4j.exceptions.InvalidOperationException; | |||
import org.apache.poi.openxml4j.opc.Package; | |||
/** | |||
* Test that the extractor factory plays nicely |
@@ -0,0 +1,102 @@ | |||
/* ==================================================================== | |||
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.openxml4j; | |||
import java.io.File; | |||
import org.apache.log4j.Logger; | |||
import org.apache.log4j.PropertyConfigurator; | |||
/** | |||
* Core helper for tests. | |||
* | |||
* @author Julien Chable | |||
* @version 1.0 | |||
*/ | |||
public class TestCore { | |||
private String testRootPath; // Test root path | |||
/** | |||
* All sample document are normally located at this place. | |||
*/ | |||
private static String pathRootProject; // Project root path | |||
/** | |||
* Demo logger | |||
*/ | |||
private static Logger logger = Logger.getLogger("org.apache.poi.openxml4j.test"); | |||
static { | |||
pathRootProject = System.getProperty("user.dir") + File.separator + "bin"; | |||
// Log4j configuration | |||
//PropertyConfigurator.configure(pathRootProject + File.separator | |||
// + "config.log4j"); | |||
} | |||
/** | |||
* Constructor. Initialize the demo. | |||
* | |||
*/ | |||
public TestCore(Class cl) { | |||
init(cl); | |||
} | |||
/** | |||
* Initialize the test root path | |||
*/ | |||
public void init(Class cl) { | |||
String packageName = cl.getPackage().getName(); | |||
// replace . by / | |||
String sep = File.separator; | |||
if (sep.equals("\\")) { | |||
sep = "\\\\"; | |||
} | |||
testRootPath = pathRootProject + File.separator | |||
+ packageName.replaceAll("\\.", sep) | |||
+ File.separator; | |||
} | |||
// Accessors | |||
/** | |||
* Gets the test root path. | |||
* | |||
* @return The test root path. | |||
*/ | |||
public String getTestRootPath() { | |||
return testRootPath; | |||
} | |||
/** | |||
* Sets the test root path. | |||
* | |||
* @param testRoot | |||
*/ | |||
public void setTestRootPath(String testRoot) { | |||
this.testRootPath = testRoot; | |||
} | |||
/** | |||
* @return the logger | |||
*/ | |||
public static Logger getLogger() { | |||
return logger; | |||
} | |||
} |
@@ -0,0 +1,38 @@ | |||
/* ==================================================================== | |||
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.openxml4j.opc; | |||
import junit.framework.Test; | |||
import junit.framework.TestSuite; | |||
public class AllTests { | |||
public static Test suite() { | |||
TestSuite suite = new TestSuite( | |||
"Functional tests for org.apache.poi.openxml4j.opc"); | |||
suite.addTestSuite(TestListParts.class); | |||
suite.addTestSuite(TestFileHelper.class); | |||
suite.addTestSuite(TestPackage.class); | |||
suite.addTestSuite(TestPackageCoreProperties.class); | |||
suite.addTestSuite(TestPackagePartName.class); | |||
suite.addTestSuite(TestPackagingURIHelper.class); | |||
suite.addTestSuite(TestContentType.class); | |||
suite.addTestSuite(TestPackageThumbnail.class); | |||
return suite; | |||
} | |||
} |