git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@738842 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_5_BETA5
<property name="ooxml.testokfile" location="build/ooxml-testokfile.txt"/> | <property name="ooxml.testokfile" location="build/ooxml-testokfile.txt"/> | ||||
<!-- The following jars are downloaded by the fetch-ooxml-jars task --> | <!-- 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.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.dom4j.url" value="${repository}/dom4j/jars/dom4j-1.6.1.jar"/> | ||||
<property name="ooxml.xmlbeans.jar" location="${ooxml.lib}/xmlbeans-2.3.0.jar"/> | <property name="ooxml.xmlbeans.jar" location="${ooxml.lib}/xmlbeans-2.3.0.jar"/> | ||||
<property name="maven.ooxml.xsds.version.id" value="1.0"/> | <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.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" location="build/tmp/site/build/site"/> | ||||
<property name="build.site.src" location="build/tmp/site"/> | <property name="build.site.src" location="build/tmp/site"/> | ||||
<available file="${ooxml.xmlbeans.jar}"/> | <available file="${ooxml.xmlbeans.jar}"/> | ||||
<available file="${ooxml.jsr173.jar}"/> | <available file="${ooxml.jsr173.jar}"/> | ||||
<available file="${ooxml.schemas.jar}"/> | <available file="${ooxml.schemas.jar}"/> | ||||
<available file="${ooxml.openxml4j.jar}"/> | |||||
</and> | </and> | ||||
<isset property="disconnected"/> | <isset property="disconnected"/> | ||||
</or> | </or> | ||||
<param name="sourcefile" value="${ooxml.schemas.url}"/> | <param name="sourcefile" value="${ooxml.schemas.url}"/> | ||||
<param name="destfile" value="${ooxml.schemas.jar}"/> | <param name="destfile" value="${ooxml.schemas.jar}"/> | ||||
</antcall> | </antcall> | ||||
<antcall target="downloadfile"> | |||||
<param name="sourcefile" value="${ooxml.openxml4j.url}"/> | |||||
<param name="destfile" value="${ooxml.openxml4j.jar}"/> | |||||
</antcall> | |||||
</target> | </target> | ||||
<target name="check-ooxml-xsds"> | <target name="check-ooxml-xsds"> | ||||
</target> | </target> | ||||
<target name="compile-ooxml" depends="init, compile-main, compile-scratchpad"> | <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" | <javac target="1.5" source="1.5" | ||||
destdir="${ooxml.output.dir}" debug="on" srcdir="${ooxml.src}"> | destdir="${ooxml.output.dir}" debug="on" srcdir="${ooxml.src}"> | ||||
<classpath refid="ooxml.classpath"/> | <classpath refid="ooxml.classpath"/> | ||||
<sysproperty key="HSLF.testdata.path" file="${scratchpad.src.test}/org/apache/poi/hslf/data"/> | <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="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="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"/> | <sysproperty key="java.awt.headless" value="true"/> | ||||
<formatter type="plain"/> | <formatter type="plain"/> | ||||
<formatter type="xml"/> | <formatter type="xml"/> | ||||
<fileset dir="${ooxml.src.test}"> | <fileset dir="${ooxml.src.test}"> | ||||
<include name="**/Test*.java"/> | <include name="**/Test*.java"/> | ||||
<exclude name="**/All*Tests.java"/> | <exclude name="**/All*Tests.java"/> | ||||
<exclude name="**/TestCore.java"/> <!--non-junit class from OpenXML4j--> | |||||
</fileset> | </fileset> | ||||
</batchtest> | </batchtest> | ||||
</junit> | </junit> | ||||
</copy> | </copy> | ||||
</target> | </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 --> | <!-- ooxml-schemas --> | ||||
<copy file="${ooxml.xsds.jar}" tofile="${mavendist.ooxml.dir}/org.apache.poi/jars/${maven.ooxml.xsds.jar}" /> | <copy file="${ooxml.xsds.jar}" tofile="${mavendist.ooxml.dir}/org.apache.poi/jars/${maven.ooxml.xsds.jar}" /> |
Apache Licence Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0 | Apache Licence Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0 | ||||
* DOM4J - http://www.dom4j.org/ | * DOM4J - http://www.dom4j.org/ | ||||
BSD Licence - http://www.dom4j.org/license.html | 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 |
<?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> |
<dependencies> | <dependencies> | ||||
<dependency> | <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> | ||||
<dependency> | <dependency> | ||||
<groupId>org.apache.poi</groupId> | <groupId>org.apache.poi</groupId> | ||||
<artifactId>ooxml-schemas</artifactId> | <artifactId>ooxml-schemas</artifactId> | ||||
<version>1.0</version> | <version>1.0</version> | ||||
</dependency> | </dependency> | ||||
<dependency> | |||||
<groupId>dom4j</groupId> | |||||
<artifactId>dom4j</artifactId> | |||||
<version>1.6.1</version> | |||||
</dependency> | |||||
</dependencies> | </dependencies> | ||||
</project> | </project> |
<menu-item label="HSMF" href="hsmf/index.html"/> | <menu-item label="HSMF" href="hsmf/index.html"/> | ||||
<menu-item label="HDGF" href="hdgf/index.html"/> | <menu-item label="HDGF" href="hdgf/index.html"/> | ||||
<menu-item label="HPBF" href="hpbf/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="POI-Utils" href="utils/index.html"/> | ||||
<menu-item label="Text Extraction" href="text-extraction.html"/> | <menu-item label="Text Extraction" href="text-extraction.html"/> | ||||
<menu-item label="Download" href="ext:download"/> | <menu-item label="Download" href="ext:download"/> |
<?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> |
<?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> |
import org.apache.poi.xssf.eventusermodel.XSSFReader; | import org.apache.poi.xssf.eventusermodel.XSSFReader; | ||||
import org.apache.poi.xssf.model.SharedStringsTable; | 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.Attributes; | ||||
import org.xml.sax.ContentHandler; | import org.xml.sax.ContentHandler; | ||||
import org.xml.sax.InputSource; | import org.xml.sax.InputSource; |
import org.apache.poi.xssf.eventusermodel.XSSFReader; | import org.apache.poi.xssf.eventusermodel.XSSFReader; | ||||
import org.apache.poi.xssf.model.SharedStringsTable; | import org.apache.poi.xssf.model.SharedStringsTable; | ||||
import org.apache.poi.xssf.usermodel.XSSFRichTextString; | 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.Attributes; | ||||
import org.xml.sax.ContentHandler; | import org.xml.sax.ContentHandler; | ||||
import org.xml.sax.InputSource; | import org.xml.sax.InputSource; |
import org.apache.poi.util.IOUtils; | import org.apache.poi.util.IOUtils; | ||||
import org.apache.poi.util.PackageHelper; | import org.apache.poi.util.PackageHelper; | ||||
import org.apache.xmlbeans.XmlException; | 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{ | public abstract class POIXMLDocument extends POIXMLDocumentPart{ | ||||
import org.apache.xmlbeans.XmlOptions; | import org.apache.xmlbeans.XmlOptions; | ||||
import org.apache.poi.util.POILogger; | import org.apache.poi.util.POILogger; | ||||
import org.apache.poi.util.POILogFactory; | import org.apache.poi.util.POILogFactory; | ||||
import org.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. | * Represents an entry of a OOXML package. | ||||
* | * | ||||
* <p> | * <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> | * </p> | ||||
* | * | ||||
* @author Yegor Kozlov | * @author Yegor Kozlov |
==================================================================== */ | ==================================================================== */ | ||||
package org.apache.poi; | 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; | |||||
/** | /** |
import java.io.IOException; | import java.io.IOException; | ||||
import org.apache.xmlbeans.XmlException; | 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 | * Wrapper around the two different kinds of OOXML properties |
import java.io.IOException; | import java.io.IOException; | ||||
import org.apache.xmlbeans.XmlException; | 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; | import org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty; | ||||
/** | /** |
import org.apache.poi.POIXMLProperties.*; | import org.apache.poi.POIXMLProperties.*; | ||||
import org.apache.xmlbeans.XmlException; | import org.apache.xmlbeans.XmlException; | ||||
import org.openxml4j.exceptions.OpenXML4JException; | |||||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; | |||||
public abstract class POIXMLTextExtractor extends POITextExtractor { | public abstract class POIXMLTextExtractor extends POITextExtractor { | ||||
/** The POIXMLDocument that's open */ | /** The POIXMLDocument that's open */ |
import java.io.PrintStream; | import java.io.PrintStream; | ||||
import java.util.ArrayList; | 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. | * Prints out the contents of a OOXML container. |
import org.apache.poi.xslf.extractor.XSLFPowerPointExtractor; | import org.apache.poi.xslf.extractor.XSLFPowerPointExtractor; | ||||
import org.apache.poi.xssf.extractor.XSSFExcelExtractor; | import org.apache.poi.xssf.extractor.XSSFExcelExtractor; | ||||
import org.apache.poi.xssf.usermodel.XSSFRelation; | 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.usermodel.XWPFRelation; | ||||
import org.apache.poi.xwpf.extractor.XWPFWordExtractor; | import org.apache.poi.xwpf.extractor.XWPFWordExtractor; | ||||
import org.apache.xmlbeans.XmlException; | 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 | * Figures out the correct POITextExtractor for your supplied |
/* ==================================================================== | |||||
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); | |||||
} | |||||
} |
/* ==================================================================== | |||||
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); | |||||
} | |||||
} |
/* ==================================================================== | |||||
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); | |||||
} | |||||
} |
/* ==================================================================== | |||||
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); | |||||
} | |||||
} |
/* ==================================================================== | |||||
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 | |||||
} |
/* ==================================================================== | |||||
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; | |||||
} | |||||
} |
/* ==================================================================== | |||||
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; | |||||
} | |||||
} |
/* ==================================================================== | |||||
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; | |||||
} | |||||
} |
/* ==================================================================== | |||||
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 | |||||
} |
/* ==================================================================== | |||||
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 | |||||
} |
/* ==================================================================== | |||||
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"; | |||||
} |
/* ==================================================================== | |||||
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(); | |||||
} |
/* ==================================================================== | |||||
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); | |||||
} | |||||
} |
/* ==================================================================== | |||||
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; | |||||
} | |||||
} |
/* ==================================================================== | |||||
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); | |||||
} |
/* ==================================================================== | |||||
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(); | |||||
} | |||||
} |
/* ==================================================================== | |||||
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 + "]"; | |||||
} | |||||
} |
/* ==================================================================== | |||||
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"; | |||||
} |
/* ==================================================================== | |||||
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; | |||||
} | |||||
} |
/* ==================================================================== | |||||
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); | |||||
} |
/* ==================================================================== | |||||
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; | |||||
} | |||||
} |
/* ==================================================================== | |||||
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 | |||||
} |
/* ==================================================================== | |||||
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; | |||||
} | |||||
} |
/* ==================================================================== | |||||
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 !"); | |||||
} | |||||
} |
/* ==================================================================== | |||||
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); | |||||
} | |||||
} |
/* ==================================================================== | |||||
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); | |||||
} |
/* ==================================================================== | |||||
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 ""; | |||||
} | |||||
} |
/* ==================================================================== | |||||
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 | |||||
} | |||||
} |
/* ==================================================================== | |||||
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); | |||||
} | |||||
} |
/* ==================================================================== | |||||
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 | |||||
} | |||||
} |
/* ==================================================================== | |||||
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; | |||||
} |
/* ==================================================================== | |||||
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; | |||||
} |
/* ==================================================================== | |||||
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; | |||||
} | |||||
} |
/* ==================================================================== | |||||
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; | |||||
} | |||||
} | |||||
} |
/* ==================================================================== | |||||
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); | |||||
} | |||||
} |
/* ==================================================================== | |||||
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()); | |||||
} | |||||
} |
/* ==================================================================== | |||||
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; | |||||
} | |||||
} |
/* ==================================================================== | |||||
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 | |||||
} | |||||
} |
/* ==================================================================== | |||||
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 | |||||
} |
/* ==================================================================== | |||||
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 { | |||||
} |
/* ==================================================================== | |||||
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()); | |||||
} | |||||
} |
/* ==================================================================== | |||||
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; | |||||
} | |||||
} |
/* ==================================================================== | |||||
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; | |||||
} | |||||
} |
/* ==================================================================== | |||||
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 { | |||||
} |
/* ==================================================================== | |||||
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; | |||||
} | |||||
} |
/* ==================================================================== | |||||
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; | |||||
} |
/* ==================================================================== | |||||
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); | |||||
} | |||||
} |
/* ==================================================================== | |||||
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); | |||||
} | |||||
} | |||||
} |
import org.apache.poi.hssf.usermodel.HSSFWorkbook; | import org.apache.poi.hssf.usermodel.HSSFWorkbook; | ||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem; | import org.apache.poi.poifs.filesystem.POIFSFileSystem; | ||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook; | 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 | * Factory for creating the appropriate kind of Workbook |
==================================================================== */ | ==================================================================== */ | ||||
package org.apache.poi.util; | 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 org.apache.poi.util.IOUtils; | ||||
import java.io.*; | import java.io.*; | ||||
import java.util.ArrayList; | |||||
import java.lang.reflect.Method; | |||||
/** | /** | ||||
* Provides handy methods to work with OOXML packages | * Provides handy methods to work with OOXML packages |
import org.apache.poi.POIXMLDocument; | import org.apache.poi.POIXMLDocument; | ||||
import org.apache.xmlbeans.XmlException; | 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.CTCommentList; | ||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTNotesSlide; | import org.openxmlformats.schemas.presentationml.x2006.main.CTNotesSlide; | ||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTPresentation; | import org.openxmlformats.schemas.presentationml.x2006.main.CTPresentation; |
import org.apache.poi.xslf.usermodel.XMLSlideShow; | import org.apache.poi.xslf.usermodel.XMLSlideShow; | ||||
import org.apache.poi.xslf.usermodel.XSLFSlide; | import org.apache.poi.xslf.usermodel.XSLFSlide; | ||||
import org.apache.xmlbeans.XmlException; | 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.CTRegularTextRun; | ||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody; | import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody; | ||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph; | import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph; |
import org.apache.poi.xssf.usermodel.XSSFRelation; | import org.apache.poi.xssf.usermodel.XSSFRelation; | ||||
import org.apache.poi.POIXMLException; | import org.apache.poi.POIXMLException; | ||||
import org.apache.xmlbeans.XmlException; | 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.CTWorkbook; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.WorkbookDocument; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.WorkbookDocument; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet; |
import org.apache.poi.xssf.usermodel.XSSFSheet; | import org.apache.poi.xssf.usermodel.XSSFSheet; | ||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook; | import org.apache.poi.xssf.usermodel.XSSFWorkbook; | ||||
import org.apache.xmlbeans.XmlException; | 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 | * Helper class to extract text from an OOXML Excel file |
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCommentList; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCommentList; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComments; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComments; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CommentsDocument; | 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 { | public class CommentsTable extends POIXMLDocumentPart { | ||||
protected CTComments comments; | protected CTComments comments; |
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSst; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSst; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.SstDocument; | 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; | |||||
/** | /** |
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXf; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXf; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPatternType; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPatternType; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.StyleSheetDocument; | 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; | |||||
/** | /** |
package org.apache.poi.xssf.model; | package org.apache.poi.xssf.model; | ||||
import org.apache.poi.xssf.usermodel.XSSFRelation; | 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 | * Common interface for XSSF models, which have (typically |
import org.apache.poi.util.IOUtils; | import org.apache.poi.util.IOUtils; | ||||
import org.apache.poi.xssf.model.XSSFWritableModel; | import org.apache.poi.xssf.model.XSSFWritableModel; | ||||
import org.apache.poi.POIXMLException; | import org.apache.poi.POIXMLException; | ||||
import org.openxml4j.opc.PackagePart; | |||||
import org.apache.poi.openxml4j.opc.PackagePart; | |||||
public class XSSFActiveXData implements PictureData, XSSFWritableModel { | public class XSSFActiveXData implements PictureData, XSSFWritableModel { | ||||
package org.apache.poi.xssf.usermodel; | package org.apache.poi.xssf.usermodel; | ||||
import org.apache.poi.ss.usermodel.Row; | |||||
import org.apache.poi.ss.usermodel.Sheet; | 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.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 | //YK: TODO: this is only a prototype | ||||
public class XSSFDialogsheet extends XSSFSheet implements Sheet{ | public class XSSFDialogsheet extends XSSFSheet implements Sheet{ |
import org.apache.poi.ss.usermodel.ClientAnchor; | import org.apache.poi.ss.usermodel.ClientAnchor; | ||||
import org.apache.xmlbeans.XmlException; | import org.apache.xmlbeans.XmlException; | ||||
import org.apache.xmlbeans.XmlOptions; | 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.drawingml.x2006.spreadsheetDrawing.*; | ||||
import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId; | import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId; | ||||
import org.apache.poi.POIXMLRelation; | import org.apache.poi.POIXMLRelation; | ||||
import org.apache.poi.util.POILogger; | import org.apache.poi.util.POILogger; | ||||
import org.apache.poi.util.POILogFactory; | import org.apache.poi.util.POILogFactory; | ||||
import org.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; | import java.lang.reflect.Constructor; | ||||
import org.apache.poi.ss.util.CellReference; | import org.apache.poi.ss.util.CellReference; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHyperlink; | 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; | |||||
/** | /** |
import org.apache.poi.util.POILogger; | import org.apache.poi.util.POILogger; | ||||
import org.apache.poi.util.POILogFactory; | import org.apache.poi.util.POILogFactory; | ||||
import org.apache.poi.POIXMLDocumentPart; | 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.NodeList; | ||||
import org.w3c.dom.Element; | import org.w3c.dom.Element; | ||||
import javax.imageio.ImageIO; | import javax.imageio.ImageIO; |
import org.apache.poi.POIXMLDocumentPart; | import org.apache.poi.POIXMLDocumentPart; | ||||
import org.apache.poi.POIXMLException; | import org.apache.poi.POIXMLException; | ||||
import org.apache.poi.POIXMLRelation; | 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. | * Raw picture data, normally attached to a SpreadsheetML Drawing. |
import org.apache.poi.xssf.model.CommentsTable; | import org.apache.poi.xssf.model.CommentsTable; | ||||
import org.apache.poi.util.POILogFactory; | import org.apache.poi.util.POILogFactory; | ||||
import org.apache.poi.util.POILogger; | import org.apache.poi.util.POILogger; | ||||
import org.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; | |||||
/** | /** | ||||
* | * |
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.*; | import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.*; | ||||
import org.openxmlformats.schemas.drawingml.x2006.main.*; | 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 | * This object specifies a group shape that represents many shapes grouped together. This shape is to be treated |
import org.apache.poi.util.POILogFactory; | import org.apache.poi.util.POILogFactory; | ||||
import org.apache.xmlbeans.XmlOptions; | import org.apache.xmlbeans.XmlOptions; | ||||
import org.apache.xmlbeans.XmlException; | 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.spreadsheetml.x2006.main.*; | ||||
import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId; | import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId; | ||||
import org.apache.xmlbeans.XmlException; | import org.apache.xmlbeans.XmlException; | ||||
import org.apache.xmlbeans.XmlObject; | import org.apache.xmlbeans.XmlObject; | ||||
import org.apache.xmlbeans.XmlOptions; | 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.officeDocument.x2006.relationships.STRelationshipId; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBookView; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBookView; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBookViews; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBookViews; |
import org.apache.poi.xwpf.usermodel.XWPFParagraph; | import org.apache.poi.xwpf.usermodel.XWPFParagraph; | ||||
import org.apache.poi.xwpf.usermodel.XWPFTable; | import org.apache.poi.xwpf.usermodel.XWPFTable; | ||||
import org.apache.xmlbeans.XmlException; | 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 | * Helper class to extract text from an OOXML Word file |
import org.apache.poi.xwpf.usermodel.XWPFFooter; | import org.apache.poi.xwpf.usermodel.XWPFFooter; | ||||
import org.apache.poi.xwpf.usermodel.XWPFHeader; | import org.apache.poi.xwpf.usermodel.XWPFHeader; | ||||
import org.apache.xmlbeans.XmlException; | 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.CTHdrFtrRef; | ||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr; | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr; | ||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.FtrDocument; | import org.openxmlformats.schemas.wordprocessingml.x2006.main.FtrDocument; |
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy; | import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy; | ||||
import org.apache.xmlbeans.XmlException; | import org.apache.xmlbeans.XmlException; | ||||
import org.apache.xmlbeans.XmlOptions; | 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.CTBody; | ||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTComment; | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTComment; | ||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDocument1; | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDocument1; |
import org.apache.poi.POIXMLRelation; | import org.apache.poi.POIXMLRelation; | ||||
import org.apache.poi.util.POILogger; | import org.apache.poi.util.POILogger; | ||||
import org.apache.poi.util.POILogFactory; | import org.apache.poi.util.POILogFactory; | ||||
import org.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; | import java.lang.reflect.Constructor; | ||||
import org.apache.poi.xslf.XSLFSlideShow; | import org.apache.poi.xslf.XSLFSlideShow; | ||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook; | import org.apache.poi.xssf.usermodel.XSSFWorkbook; | ||||
import org.apache.poi.xwpf.usermodel.XWPFDocument; | 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; | import junit.framework.TestCase; | ||||
import org.apache.poi.xssf.extractor.XSSFExcelExtractor; | import org.apache.poi.xssf.extractor.XSSFExcelExtractor; | ||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook; | import org.apache.poi.xssf.usermodel.XSSFWorkbook; | ||||
import org.openxml4j.opc.Package; | |||||
import org.apache.poi.openxml4j.opc.Package; | |||||
import junit.framework.TestCase; | import junit.framework.TestCase; | ||||
} | } | ||||
public void testGetFromMainExtractor() throws Exception { | 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() | (new File(dirname, "ExcelWithAttachments.xlsx")).toString() | ||||
); | ); | ||||
XSSFWorkbook wb = new XSSFWorkbook(pkg); | XSSFWorkbook wb = new XSSFWorkbook(pkg); | ||||
} | } | ||||
public void testCore() throws Exception { | 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() | (new File(dirname, "ExcelWithAttachments.xlsx")).toString() | ||||
); | ); | ||||
XSSFWorkbook wb = new XSSFWorkbook(pkg); | XSSFWorkbook wb = new XSSFWorkbook(pkg); | ||||
} | } | ||||
public void testExtended() throws Exception { | 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() | (new File(dirname, "ExcelWithAttachments.xlsx")).toString() | ||||
); | ); | ||||
XSSFWorkbook wb = new XSSFWorkbook(pkg); | XSSFWorkbook wb = new XSSFWorkbook(pkg); |
import junit.framework.TestCase; | 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 | * Test that the extractor factory plays nicely |
/* ==================================================================== | |||||
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; | |||||
} | |||||
} |
/* ==================================================================== | |||||
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; | |||||
} | |||||
} |