import OpenXML4j codebase

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@738842 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yegor Kozlov 2009-01-29 12:44:31 +00:00
parent 980ff2cf30
commit ef4b2ebc2e
144 changed files with 11877 additions and 250 deletions

View File

@ -124,8 +124,6 @@ under the License.
<property name="ooxml.testokfile" location="build/ooxml-testokfile.txt"/>
<!-- The following jars are downloaded by the fetch-ooxml-jars task -->
<property name="ooxml.openxml4j.jar" location="${ooxml.lib}/openxml4j-1.0-beta.jar"/>
<property name="ooxml.openxml4j.url" value="http://mirrors.ibiblio.org/pub/mirrors/maven2/org/apache/poi/openxml4j/1.0-beta/openxml4j-1.0-beta.jar"/>
<property name="ooxml.dom4j.jar" location="${ooxml.lib}/dom4j-1.6.1.jar"/>
<property name="ooxml.dom4j.url" value="${repository}/dom4j/jars/dom4j-1.6.1.jar"/>
<property name="ooxml.xmlbeans.jar" location="${ooxml.lib}/xmlbeans-2.3.0.jar"/>
@ -144,8 +142,6 @@ under the License.
<property name="maven.ooxml.xsds.version.id" value="1.0"/>
<property name="maven.ooxml.xsds.jar" value="ooxml-schemas-${maven.ooxml.xsds.version.id}.jar"/>
<property name="maven.openxml4j.version.id" value="1.0-beta"/>
<property name="maven.openxml4j.jar" value="openxml4j-${maven.openxml4j.version.id}.jar"/>
<property name="build.site" location="build/tmp/site/build/site"/>
<property name="build.site.src" location="build/tmp/site"/>
@ -354,7 +350,6 @@ under the License.
<available file="${ooxml.xmlbeans.jar}"/>
<available file="${ooxml.jsr173.jar}"/>
<available file="${ooxml.schemas.jar}"/>
<available file="${ooxml.openxml4j.jar}"/>
</and>
<isset property="disconnected"/>
</or>
@ -377,10 +372,6 @@ under the License.
<param name="sourcefile" value="${ooxml.schemas.url}"/>
<param name="destfile" value="${ooxml.schemas.jar}"/>
</antcall>
<antcall target="downloadfile">
<param name="sourcefile" value="${ooxml.openxml4j.url}"/>
<param name="destfile" value="${ooxml.openxml4j.jar}"/>
</antcall>
</target>
<target name="check-ooxml-xsds">
@ -524,7 +515,6 @@ under the License.
</target>
<target name="compile-ooxml" depends="init, compile-main, compile-scratchpad">
<!-- openxml4j requires java 1.5, so so must we, for now -->
<javac target="1.5" source="1.5"
destdir="${ooxml.output.dir}" debug="on" srcdir="${ooxml.src}">
<classpath refid="ooxml.classpath"/>
@ -805,6 +795,9 @@ under the License.
<sysproperty key="HSLF.testdata.path" file="${scratchpad.src.test}/org/apache/poi/hslf/data"/>
<sysproperty key="HDGF.testdata.path" file="${scratchpad.src.test}/org/apache/poi/hdgf/data"/>
<sysproperty key="OOXML.testdata.path" file="${ooxml.src.test}/org/apache/poi/ooxml/data"/>
<sysproperty key="openxml4j.compliance.input" file="${ooxml.src.test}/org/apache/poi/openxml4j/opc/compliance/input"/>
<sysproperty key="openxml4j.testdata.input" file="${ooxml.src.test}/org/apache/poi/openxml4j/opc/INPUT"/>
<sysproperty key="openxml4j.testdata.output" file="${ooxml.src.test}/org/apache/poi/openxml4j/opc/OUTPUT"/>
<sysproperty key="java.awt.headless" value="true"/>
<formatter type="plain"/>
<formatter type="xml"/>
@ -812,6 +805,7 @@ under the License.
<fileset dir="${ooxml.src.test}">
<include name="**/Test*.java"/>
<exclude name="**/All*Tests.java"/>
<exclude name="**/TestCore.java"/> <!--non-junit class from OpenXML4j-->
</fileset>
</batchtest>
</junit>
@ -1129,16 +1123,7 @@ FORREST_HOME environment variable!</echo>
</copy>
</target>
<target name="maven-ooxml-dependencies" description="Builds the POM files for OpenXml4J and compiled XmlBeans generated from the Ecma supplied xsds">
<!-- OpenXml4J -->
<copy file="${ooxml.jar6.dir}" tofile="${mavendist.ooxml.dir}/org.openxml4j/jars/${maven.openxml4j.jar}" />
<copy file="maven/openxml4j.pom" tofile="${mavendist.ooxml.dir}/org.openxml4j/poms/openxml4j-${maven.openxml4j.version.id}.pom">
<filterchain>
<replacetokens>
<token key="VERSION" value="${maven.openxml4j.version.id}" />
</replacetokens>
</filterchain>
</copy>
<target name="maven-ooxml-dependencies" description="Builds the POM files for the compiled XmlBeans generated from the Ecma supplied xsds">
<!-- ooxml-schemas -->
<copy file="${ooxml.xsds.jar}" tofile="${mavendist.ooxml.dir}/org.apache.poi/jars/${maven.ooxml.xsds.jar}" />

View File

@ -17,6 +17,3 @@ own licensing:
Apache Licence Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0
* DOM4J - http://www.dom4j.org/
BSD Licence - http://www.dom4j.org/license.html
* OpenXml4J - http://www.openxml4j.org/
BSD Licence or Apache Licence Version 2.0 -
http://www.openxml4j.org/Licensing/Default.html

View File

@ -1,70 +0,0 @@
<?xml version="1.0"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.openxml4j</groupId>
<artifactId>openxml4j</artifactId>
<version>@VERSION@</version>
<packaging>jar</packaging>
<name>OpenXML4J</name>
<url>http://openxml4j.org/</url>
<description>Office Open XML File Format library for Java</description>
<mailingLists>
<mailingList>
<name>OpenXML4J Users List</name>
<archive>http://sourceforge.net/mailarchive/forum.php?forum_name=openxml4j-users</archive>
</mailingList>
<mailingList>
<name>OpenXML4J Developer List</name>
<archive>http://sourceforge.net/mailarchive/forum.php?forum_name=openxml4j-devs</archive>
</mailingList>
</mailingLists>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<organization>
<name>OpenXML4J</name>
<url>http://www.openxml4j.org/</url>
</organization>
<dependencies>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.8</version>
</dependency>
</dependencies>
</project>

View File

@ -59,27 +59,20 @@
</organization>
<dependencies>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.13</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>openxml4j</artifactId>
<version>1.0-beta</version>
<artifactId>poi</artifactId>
<version>@VERSION@</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
</dependencies>
</project>

View File

@ -42,6 +42,7 @@
<menu-item label="HSMF" href="hsmf/index.html"/>
<menu-item label="HDGF" href="hdgf/index.html"/>
<menu-item label="HPBF" href="hpbf/index.html"/>
<menu-item label="OpenXML4J" href="oxml4j/index.html"/>
<menu-item label="POI-Ruby" href="poi-ruby.html"/>
<menu-item label="POI-Utils" href="utils/index.html"/>
<menu-item label="Text Extraction" href="text-extraction.html"/>

View File

@ -0,0 +1,34 @@
<?xml version="1.0"?>
<!--
====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
====================================================================
-->
<!DOCTYPE book PUBLIC "-//APACHE//DTD Cocoon Documentation Book V1.0//EN" "../dtd/book-cocoon-v10.dtd">
<book software="POI Project"
title="OpenXML4J"
copyright="@year@ POI Project">
<menu label="Apache POI">
<menu-item label="Top" href="../index.html"/>
</menu>
<menu label="OpenXML4J">
<menu-item label="Overview" href="index.html"/>
</menu>
</book>

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
====================================================================
-->
<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.1//EN" "../dtd/document-v11.dtd">
<document>
<header>
<title>POI-OpenXML4J - Java API To Access Office Open XML documents</title>
<subtitle>Overview</subtitle>
</header>
<body>
<section>
<title>Overview</title>
<p>OpenXML4J is the POI Project's pure Java implementation of the Open Packaging Conventions (OPC) defined in
<link href="http://www.ecma-international.org/publications/standards/Ecma-376.htm">ECMA-376</link>.</p>
<p>Every OpenXML file comprises a collection of byte streams called parts, combined into a container called a package.
POI OpenXML4J provides a physical implementation of the OPC that uses the Zip file format.</p>
</section>
<section>
<title>History</title>
<p>OpenXML4J was originally developed by <link href="http://openxml4j.org/">http://openxml4j.org/</link> and contributed to POI in 2008.
Thanks to the support and guidance of Julien Chable</p>
</section>
</body>
</document>

View File

@ -509,7 +509,7 @@ import java.util.Iterator;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.openxml4j.opc.Package;
import org.apache.poi.openxml4j.opc.Package;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;

View File

@ -22,7 +22,7 @@ import java.util.Iterator;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.openxml4j.opc.Package;
import org.apache.poi.openxml4j.opc.Package;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;

View File

@ -23,10 +23,10 @@ import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.PackageHelper;
import org.apache.xmlbeans.XmlException;
import org.openxml4j.exceptions.InvalidFormatException;
import org.openxml4j.exceptions.OpenXML4JException;
import org.openxml4j.opc.*;
import org.openxml4j.opc.Package;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.*;
import org.apache.poi.openxml4j.opc.Package;
public abstract class POIXMLDocument extends POIXMLDocumentPart{

View File

@ -23,15 +23,15 @@ import java.util.List;
import org.apache.xmlbeans.XmlOptions;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.POILogFactory;
import org.openxml4j.exceptions.OpenXML4JException;
import org.openxml4j.opc.*;
import org.openxml4j.opc.Package;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.*;
import org.apache.poi.openxml4j.opc.Package;
/**
* Represents an entry of a OOXML package.
*
* <p>
* Each POIXMLDocumentPart keeps a reference to the underlying a {@link org.openxml4j.opc.PackagePart}.
* Each POIXMLDocumentPart keeps a reference to the underlying a {@link org.apache.poi.openxml4j.opc.PackagePart}.
* </p>
*
* @author Yegor Kozlov

View File

@ -16,8 +16,8 @@
==================================================================== */
package org.apache.poi;
import org.openxml4j.opc.PackageRelationship;
import org.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.PackagePart;
/**

View File

@ -19,10 +19,10 @@ package org.apache.poi;
import java.io.IOException;
import org.apache.xmlbeans.XmlException;
import org.openxml4j.exceptions.OpenXML4JException;
import org.openxml4j.opc.Package;
import org.openxml4j.opc.PackageRelationshipCollection;
import org.openxml4j.opc.internal.PackagePropertiesPart;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.Package;
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart;
/**
* Wrapper around the two different kinds of OOXML properties

View File

@ -19,8 +19,8 @@ package org.apache.poi;
import java.io.IOException;
import org.apache.xmlbeans.XmlException;
import org.openxml4j.exceptions.OpenXML4JException;
import org.openxml4j.opc.internal.PackagePropertiesPart;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart;
import org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty;
/**

View File

@ -20,7 +20,7 @@ import java.io.IOException;
import org.apache.poi.POIXMLProperties.*;
import org.apache.xmlbeans.XmlException;
import org.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
public abstract class POIXMLTextExtractor extends POITextExtractor {
/** The POIXMLDocument that's open */

View File

@ -22,11 +22,11 @@ import java.io.InputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import org.openxml4j.opc.Package;
import org.openxml4j.opc.PackageAccess;
import org.openxml4j.opc.PackagePart;
import org.openxml4j.opc.PackageRelationship;
import org.openxml4j.opc.PackageRelationshipCollection;
import org.apache.poi.openxml4j.opc.Package;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
/**
* Prints out the contents of a OOXML container.

View File

@ -41,15 +41,14 @@ import org.apache.poi.xslf.XSLFSlideShow;
import org.apache.poi.xslf.extractor.XSLFPowerPointExtractor;
import org.apache.poi.xssf.extractor.XSSFExcelExtractor;
import org.apache.poi.xssf.usermodel.XSSFRelation;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFRelation;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.xmlbeans.XmlException;
import org.openxml4j.exceptions.InvalidFormatException;
import org.openxml4j.exceptions.OpenXML4JException;
import org.openxml4j.opc.Package;
import org.openxml4j.opc.PackagePart;
import org.openxml4j.opc.PackageRelationshipCollection;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.Package;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
/**
* Figures out the correct POITextExtractor for your supplied

View File

@ -0,0 +1,27 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
====================================================================
*/
package org.apache.poi.openxml4j.exceptions;
@SuppressWarnings("serial")
public class InvalidFormatException extends OpenXML4JException{
public InvalidFormatException(String message){
super(message);
}
}

View File

@ -0,0 +1,32 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.exceptions;
/**
* Throw when an invalid operation is done.
*
* @author Julien Chable
* @version 1.0
*/
@SuppressWarnings("serial")
public class InvalidOperationException extends OpenXML4JRuntimeException{
public InvalidOperationException(String message){
super(message);
}
}

View File

@ -0,0 +1,34 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.exceptions;
/**
* Global exception throws when a critical error occurs. (this exception is not
* set as Runtime in order to force user to manage the exception in a
* try/catch).
*
* @author CDubettier, Julien Chable
* @version 1.0
*/
@SuppressWarnings("serial")
public class OpenXML4JException extends Exception {
public OpenXML4JException(String msg) {
super(msg);
}
}

View File

@ -0,0 +1,34 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.exceptions;
/**
* Global exception throws when a critical error occurs (this exception is
* set as Runtime in order not to force the user to manage the exception in a
* try/catch).
*
* @author Julien Chable
* @version 1.0
*/
@SuppressWarnings("serial")
public class OpenXML4JRuntimeException extends RuntimeException {
public OpenXML4JRuntimeException(String msg) {
super(msg);
}
}

View File

@ -0,0 +1,33 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc;
/**
* Specifies the location where the X.509 certificate that is used in signing is stored.
*
* @author Julien Chable
* @version 1.0
*/
public enum CertificateEmbeddingOption {
/** The certificate is embedded in its own PackagePart. */
IN_CERTIFICATE_PART,
/** The certificate is embedded in the SignaturePart that is created for the signature being added. */
IN_SIGNATURE_PART,
/** The certificate in not embedded in the package. */
NOT_EMBEDDED
}

View File

@ -0,0 +1,47 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.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;
}
}

View File

@ -0,0 +1,43 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc;
import java.io.File;
/**
* Storage class for configuration storage parameters.
* TODO xml syntax checking is no longer done with DOM4j parser -> remove the schema or do it ?
*
* @author CDubettier, Julen Chable
* @version 1.0
*/
public class Configuration {
// TODO configuration by default. should be clearly stated that it should be
// changed to match installation path
// as schemas dir is needed in runtime
static private String pathForXmlSchema = System.getProperty("user.dir")
+ File.separator + "src" + File.separator + "schemas";
public static String getPathForXmlSchema() {
return pathForXmlSchema;
}
public static void setPathForXmlSchema(String pathForXmlSchema) {
Configuration.pathForXmlSchema = pathForXmlSchema;
}
}

View File

@ -0,0 +1,129 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc;
/**
* Open Packaging Convention content types (see Annex F : Standard Namespaces
* and Content Types).
*
* @author CDubettier define some constants, Julien Chable
* @version 0.1
*/
public class ContentTypes {
/*
* Open Packaging Convention (Annex F : Standard Namespaces and Content
* Types)
*/
/**
* Core Properties part.
*/
public static final String CORE_PROPERTIES_PART = "application/vnd.openxmlformats-package.core-properties+xml";
/**
* Digital Signature Certificate part.
*/
public static final String DIGITAL_SIGNATURE_CERTIFICATE_PART = "application/vnd.openxmlformats-package.digital-signature-certificate";
/**
* Digital Signature Origin part.
*/
public static final String DIGITAL_SIGNATURE_ORIGIN_PART = "application/vnd.openxmlformats-package.digital-signature-origin";
/**
* Digital Signature XML Signature part.
*/
public static final String DIGITAL_SIGNATURE_XML_SIGNATURE_PART = "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml";
/**
* Relationships part.
*/
public static final String RELATIONSHIPS_PART = "application/vnd.openxmlformats-package.relationships+xml";
/**
* Custom XML part.
*/
public static final String CUSTOM_XML_PART = "application/vnd.openxmlformats-officedocument.customXmlProperties+xml";
/**
* Plain old xml. Note - OOXML uses application/xml, and not text/xml!
*/
public static final String PLAIN_OLD_XML = "application/xml";
public static final String IMAGE_JPEG = "image/jpeg";
public static final String EXTENSION_JPG_1 = "jpg";
public static final String EXTENSION_JPG_2 = "jpeg";
// image/png ISO/IEC 15948:2003 http://www.libpng.org/pub/png/spec/
public static final String IMAGE_PNG = "image/png";
public static final String EXTENSION_PNG = "png";
// image/gif http://www.w3.org/Graphics/GIF/spec-gif89a.txt
public static final String IMAGE_GIF = "image/gif";
public static final String EXTENSION_GIF = "gif";
/**
* TIFF image format.
*
* @see http://partners.adobe.com/public/developer/tiff/index.html#spec
*/
public static final String IMAGE_TIFF = "image/tiff";
public static final String EXTENSION_TIFF = "tiff";
/**
* Pict image format.
*
* @see http://developer.apple.com/documentation/mac/QuickDraw/QuickDraw-2.html
*/
public static final String IMAGE_PICT = "image/pict";
public static final String EXTENSION_PICT = "tiff";
/**
* XML file.
*/
public static final String XML = "text/xml";
public static final String EXTENSION_XML = "xml";
public static String getContentTypeFromFileExtension(String filename) {
String extension = filename.substring(filename.lastIndexOf(".") + 1)
.toLowerCase();
if (extension.equals(EXTENSION_JPG_1)
|| extension.equals(EXTENSION_JPG_2))
return IMAGE_JPEG;
else if (extension.equals(EXTENSION_GIF))
return IMAGE_GIF;
else if (extension.equals(EXTENSION_PICT))
return IMAGE_PICT;
else if (extension.equals(EXTENSION_PNG))
return IMAGE_PNG;
else if (extension.equals(EXTENSION_TIFF))
return IMAGE_TIFF;
else if (extension.equals(EXTENSION_XML))
return XML;
else
return null;
}
}

View File

@ -0,0 +1,29 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc;
/**
* Specifies the encryption option for parts in a Package.
*
* @author Julien Chable
* @version 0.1
*/
public enum EncryptionOption {
/** No encryption. */
NONE
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,33 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc;
/**
* Specifies package access.
*
* @author Julien Chable
* @version 1.0
*/
public enum PackageAccess {
/** Read only. Write not authorized. */
READ,
/** Write only. Read not authorized. */
WRITE,
/** Read and Write mode. */
READ_WRITE
}

View File

@ -0,0 +1,52 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc;
/**
* Open Packaging Convention namespaces URI.
*
* @author Julien Chable
* @version 1.0
*/
public interface PackageNamespaces {
/**
* Content Types.
*/
public static final String CONTENT_TYPES = "http://schemas.openxmlformats.org/package/2006/content-types";
/**
* Core Properties.
*/
public static final String CORE_PROPERTIES = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties";
/**
* Digital Signatures.
*/
public static final String DIGITAL_SIGNATURE = "http://schemas.openxmlformats.org/package/2006/digital-signature";
/**
* Relationships.
*/
public static final String RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships";
/**
* Markup Compatibility.
*/
public static final String MARKUP_COMPATIBILITY = "http://schemas.openxmlformats.org/markup-compatibility/2006";
}

View File

@ -0,0 +1,654 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.InvalidOperationException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.internal.ContentType;
/**
* Provides a base class for parts stored in a Package.
*
* @author Julien Chable
* @version 0.9
*/
public abstract class PackagePart implements RelationshipSource {
/**
* This part's container.
*/
protected Package container;
/**
* The part name. (required by the specification [M1.1])
*/
protected PackagePartName partName;
/**
* The type of content of this part. (required by the specification [M1.2])
*/
protected ContentType contentType;
/**
* Flag to know if this part is a relationship.
*/
private boolean isRelationshipPart;
/**
* Flag to know if this part has been logically deleted.
*/
private boolean isDeleted;
/**
* This part's relationships.
*/
private PackageRelationshipCollection relationships;
/**
* Constructor.
*
* @param pack
* Parent package.
* @param partName
* The part name, relative to the parent Package root.
* @param contentType
* The content type.
* @throws InvalidFormatException
* If the specified URI is not valid.
*/
protected PackagePart(Package pack, PackagePartName partName,
ContentType contentType) throws InvalidFormatException {
this(pack, partName, contentType, true);
}
/**
* Constructor.
*
* @param pack
* Parent package.
* @param partName
* The part name, relative to the parent Package root.
* @param contentType
* The content type.
* @param loadRelationships
* Specify if the relationships will be loaded
* @throws InvalidFormatException
* If the specified URI is not valid.
*/
protected PackagePart(Package pack, PackagePartName partName,
ContentType contentType, boolean loadRelationships)
throws InvalidFormatException {
this.partName = partName;
this.contentType = contentType;
this.container = (ZipPackage) pack;
// Check if this part is a relationship part
isRelationshipPart = this.partName.isRelationshipPartURI();
// Load relationships if any
if (loadRelationships)
loadRelationships();
}
/**
* Constructor.
*
* @param pack
* Parent package.
* @param partName
* The part name, relative to the parent Package root.
* @param contentType
* The Multipurpose Internet Mail Extensions (MIME) content type
* of the part's data stream.
*/
public PackagePart(Package pack, PackagePartName partName,
String contentType) throws InvalidFormatException {
this(pack, partName, new ContentType(contentType));
}
/**
* Adds an external relationship to a part (except relationships part).
*
* The targets of external relationships are not subject to the same
* validity checks that internal ones are, as the contents is potentially
* any file, URL or similar.
*
* @param target
* External target of the relationship
* @param relationshipType
* Type of relationship.
* @return The newly created and added relationship
* @see org.apache.poi.openxml4j.opc.RelationshipSource#addExternalRelationship(java.lang.String,
* java.lang.String)
*/
public PackageRelationship addExternalRelationship(String target,
String relationshipType) {
return addExternalRelationship(target, relationshipType, null);
}
/**
* Adds an external relationship to a part (except relationships part).
*
* The targets of external relationships are not subject to the same
* validity checks that internal ones are, as the contents is potentially
* any file, URL or similar.
*
* @param target
* External target of the relationship
* @param relationshipType
* Type of relationship.
* @param id
* Relationship unique id.
* @return The newly created and added relationship
* @see org.apache.poi.openxml4j.opc.RelationshipSource#addExternalRelationship(java.lang.String,
* java.lang.String)
*/
public PackageRelationship addExternalRelationship(String target,
String relationshipType, String id) {
if (target == null) {
throw new IllegalArgumentException("target");
}
if (relationshipType == null) {
throw new IllegalArgumentException("relationshipType");
}
if (relationships == null) {
relationships = new PackageRelationshipCollection();
}
URI targetURI;
try {
targetURI = new URI(target);
} catch (URISyntaxException e) {
throw new IllegalArgumentException("Invalid target - " + e);
}
return relationships.addRelationship(targetURI, TargetMode.EXTERNAL,
relationshipType, id);
}
/**
* Add a relationship to a part (except relationships part).
*
* @param targetPartName
* Name of the target part. This one must be relative to the
* source root directory of the part.
* @param targetMode
* Mode [Internal|External].
* @param relationshipType
* Type of relationship.
* @return The newly created and added relationship
* @see org.apache.poi.openxml4j.opc.RelationshipSource#addRelationship(org.apache.poi.openxml4j.opc.PackagePartName,
* org.apache.poi.openxml4j.opc.TargetMode, java.lang.String)
*/
public PackageRelationship addRelationship(PackagePartName targetPartName,
TargetMode targetMode, String relationshipType) {
return addRelationship(targetPartName, targetMode, relationshipType,
null);
}
/**
* Add a relationship to a part (except relationships part).
*
* Check rule M1.25: The Relationships part shall not have relationships to
* any other part. Package implementers shall enforce this requirement upon
* the attempt to create such a relationship and shall treat any such
* relationship as invalid.
*
* @param targetPartName
* Name of the target part. This one must be relative to the
* source root directory of the part.
* @param targetMode
* Mode [Internal|External].
* @param relationshipType
* Type of relationship.
* @param id
* Relationship unique id.
* @return The newly created and added relationship
*
* @throws InvalidFormatException
* If the URI point to a relationship part URI.
* @see org.apache.poi.openxml4j.opc.RelationshipSource#addRelationship(org.apache.poi.openxml4j.opc.PackagePartName,
* org.apache.poi.openxml4j.opc.TargetMode, java.lang.String, java.lang.String)
*/
public PackageRelationship addRelationship(PackagePartName targetPartName,
TargetMode targetMode, String relationshipType, String id) {
container.throwExceptionIfReadOnly();
if (targetPartName == null) {
throw new IllegalArgumentException("targetPartName");
}
if (targetMode == null) {
throw new IllegalArgumentException("targetMode");
}
if (relationshipType == null) {
throw new IllegalArgumentException("relationshipType");
}
if (this.isRelationshipPart || targetPartName.isRelationshipPartURI()) {
throw new InvalidOperationException(
"Rule M1.25: The Relationships part shall not have relationships to any other part.");
}
if (relationships == null) {
relationships = new PackageRelationshipCollection();
}
return relationships.addRelationship(targetPartName.getURI(),
targetMode, relationshipType, id);
}
/**
* Add a relationship to a part (except relationships part).
*
* @param targetURI
* URI the target part. Must be relative to the source root
* directory of the part.
* @param targetMode
* Mode [Internal|External].
* @param relationshipType
* Type of relationship.
* @return The newly created and added relationship
* @see org.apache.poi.openxml4j.opc.RelationshipSource#addRelationship(org.apache.poi.openxml4j.opc.PackagePartName,
* org.apache.poi.openxml4j.opc.TargetMode, java.lang.String)
*/
public PackageRelationship addRelationship(URI targetURI,
TargetMode targetMode, String relationshipType) {
return addRelationship(targetURI, targetMode, relationshipType, null);
}
/**
* Add a relationship to a part (except relationships part).
*
* Check rule M1.25: The Relationships part shall not have relationships to
* any other part. Package implementers shall enforce this requirement upon
* the attempt to create such a relationship and shall treat any such
* relationship as invalid.
*
* @param targetURI
* URI of the target part. Must be relative to the source root
* directory of the part.
* @param targetMode
* Mode [Internal|External].
* @param relationshipType
* Type of relationship.
* @param id
* Relationship unique id.
* @return The newly created and added relationship
*
* @throws InvalidFormatException
* If the URI point to a relationship part URI.
* @see org.apache.poi.openxml4j.opc.RelationshipSource#addRelationship(org.apache.poi.openxml4j.opc.PackagePartName,
* org.apache.poi.openxml4j.opc.TargetMode, java.lang.String, java.lang.String)
*/
public PackageRelationship addRelationship(URI targetURI,
TargetMode targetMode, String relationshipType, String id) {
container.throwExceptionIfReadOnly();
if (targetURI == null) {
throw new IllegalArgumentException("targetPartName");
}
if (targetMode == null) {
throw new IllegalArgumentException("targetMode");
}
if (relationshipType == null) {
throw new IllegalArgumentException("relationshipType");
}
// Try to retrieve the target part
if (this.isRelationshipPart
|| PackagingURIHelper.isRelationshipPartURI(targetURI)) {
throw new InvalidOperationException(
"Rule M1.25: The Relationships part shall not have relationships to any other part.");
}
if (relationships == null) {
relationships = new PackageRelationshipCollection();
}
return relationships.addRelationship(targetURI,
targetMode, relationshipType, id);
}
/**
* @see org.apache.poi.openxml4j.opc.RelationshipSource#clearRelationships()
*/
public void clearRelationships() {
if (relationships != null) {
relationships.clear();
}
}
/**
* Delete the relationship specified by its id.
*
* @param id
* The ID identified the part to delete.
* @see org.apache.poi.openxml4j.opc.RelationshipSource#removeRelationship(java.lang.String)
*/
public void removeRelationship(String id) {
this.container.throwExceptionIfReadOnly();
if (this.relationships != null)
this.relationships.removeRelationship(id);
}
/**
* Retrieve all the relationships attached to this part.
*
* @return This part's relationships.
* @throws OpenXML4JException
* @see org.apache.poi.openxml4j.opc.RelationshipSource#getRelationships()
*/
public PackageRelationshipCollection getRelationships()
throws InvalidFormatException {
return getRelationshipsCore(null);
}
/**
* Retrieves a package relationship from its id.
*
* @param id
* ID of the package relationship to retrieve.
* @return The package relationship
* @see org.apache.poi.openxml4j.opc.RelationshipSource#getRelationship(java.lang.String)
*/
public PackageRelationship getRelationship(String id) {
return this.relationships.getRelationshipByID(id);
}
/**
* Retrieve all relationships attached to this part which have the specified
* type.
*
* @param relationshipType
* Relationship type filter.
* @return All relationships from this part that have the specified type.
* @throws InvalidFormatException
* If an error occurs while parsing the part.
* @throws InvalidOperationException
* If the package is open in write only mode.
* @see org.apache.poi.openxml4j.opc.RelationshipSource#getRelationshipsByType(java.lang.String)
*/
public PackageRelationshipCollection getRelationshipsByType(
String relationshipType) throws InvalidFormatException {
container.throwExceptionIfWriteOnly();
return getRelationshipsCore(relationshipType);
}
/**
* Implementation of the getRelationships method().
*
* @param filter
* Relationship type filter. If <i>null</i> then the filter is
* disabled and return all the relationships.
* @return All relationships from this part that have the specified type.
* @throws InvalidFormatException
* Throws if an error occurs during parsing the relationships
* part.
* @throws InvalidOperationException
* Throws if the package is open en write only mode.
* @see #getRelationshipsByType(String)
*/
private PackageRelationshipCollection getRelationshipsCore(String filter)
throws InvalidFormatException {
this.container.throwExceptionIfWriteOnly();
if (relationships == null) {
this.throwExceptionIfRelationship();
relationships = new PackageRelationshipCollection(this);
}
return new PackageRelationshipCollection(relationships, filter);
}
/**
* Knows if the part have any relationships.
*
* @return <b>true</b> if the part have at least one relationship else
* <b>false</b>.
* @see org.apache.poi.openxml4j.opc.RelationshipSource#hasRelationships()
*/
public boolean hasRelationships() {
return (!this.isRelationshipPart && (relationships != null && relationships
.size() > 0));
}
/**
* Checks if the specified relationship is part of this package part.
*
* @param rel
* The relationship to check.
* @return <b>true</b> if the specified relationship exists in this part,
* else returns <b>false</b>
* @see org.apache.poi.openxml4j.opc.RelationshipSource#isRelationshipExists(org.apache.poi.openxml4j.opc.PackageRelationship)
*/
@SuppressWarnings("finally")
public boolean isRelationshipExists(PackageRelationship rel) {
try {
for (PackageRelationship r : this.getRelationships()) {
if (r == rel)
return true;
}
} finally {
return false;
}
}
/**
* Get the input stream of this part to read its content.
*
* @return The input stream of the content of this part, else
* <code>null</code>.
*/
public InputStream getInputStream() throws IOException {
InputStream inStream = this.getInputStreamImpl();
if (inStream == null) {
throw new IOException("Can't obtain the input stream from "
+ partName.getName());
} else
return inStream;
}
/**
* Get the output stream of this part. If the part is originally embedded in
* Zip package, it'll be transform intot a <i>MemoryPackagePart</i> in
* order to write inside (the standard Java API doesn't allow to write in
* the file)
*
* @see org.apache.poi.openxml4j.opc.internal.MemoryPackagePart
*/
public OutputStream getOutputStream() {
OutputStream outStream;
// If this part is a zip package part (read only by design) we convert
// this part into a MemoryPackagePart instance for write purpose.
if (this instanceof ZipPackagePart) {
// Delete logically this part
this.container.removePart(this.partName);
// Create a memory part
PackagePart part = container.createPart(this.partName,
this.contentType.toString(), false);
part.relationships = this.relationships;
if (part == null) {
throw new InvalidOperationException(
"Can't create a temporary part !");
}
outStream = part.getOutputStreamImpl();
} else {
outStream = this.getOutputStreamImpl();
}
return outStream;
}
/**
* Throws an exception if this package part is a relationship part.
*
* @throws InvalidOperationException
* If this part is a relationship part.
*/
private void throwExceptionIfRelationship()
throws InvalidOperationException {
if (this.isRelationshipPart)
throw new InvalidOperationException(
"Can do this operation on a relationship part !");
}
/**
* Ensure the package relationships collection instance is built.
*
* @throws InvalidFormatException
* Throws if
*/
private void loadRelationships() throws InvalidFormatException {
if (this.relationships == null && !this.isRelationshipPart) {
this.throwExceptionIfRelationship();
relationships = new PackageRelationshipCollection(this);
}
}
/*
* Accessors
*/
/**
* @return the uri
*/
public PackagePartName getPartName() {
return partName;
}
/**
* @return the contentType
*/
public String getContentType() {
return contentType.toString();
}
/**
* Set the content type.
*
* @param contentType
* the contentType to set
*
* @throws InvalidFormatException
* Throws if the content type is not valid.
* @throws InvalidOperationException
* Throws if you try to change the content type whereas this
* part is already attached to a package.
*/
public void setContentType(String contentType)
throws InvalidFormatException {
if (container == null)
this.contentType = new ContentType(contentType);
else
throw new InvalidOperationException(
"You can't change the content type of a part.");
}
public Package getPackage() {
return container;
}
/**
* @return
*/
public boolean isRelationshipPart() {
return this.isRelationshipPart;
}
/**
* @return
*/
public boolean isDeleted() {
return isDeleted;
}
/**
* @param isDeleted
* the isDeleted to set
*/
public void setDeleted(boolean isDeleted) {
this.isDeleted = isDeleted;
}
@Override
public String toString() {
return "Name: " + this.partName + " - Content Type: "
+ this.contentType.toString();
}
/*-------------- Abstract methods ------------- */
/**
* Abtract method that get the input stream of this part.
*
* @exception IOException
* Throws if an IO Exception occur in the implementation
* method.
*/
protected abstract InputStream getInputStreamImpl() throws IOException;
/**
* Abstract method that get the output stream of this part.
*/
protected abstract OutputStream getOutputStreamImpl();
/**
* Save the content of this part and the associated relationships part (if
* this part own at least one relationship) into the specified output
* stream.
*
* @param zos
* Output stream to save this part.
* @throws OpenXML4JException
* If any exception occur.
*/
public abstract boolean save(OutputStream zos) throws OpenXML4JException;
/**
* Load the content of this part.
*
* @param ios
* The input stream of the content to load.
* @return <b>true</b> if the content has been successfully loaded, else
* <b>false</b>.
* @throws InvalidFormatException
* Throws if the content format is invalid.
*/
public abstract boolean load(InputStream ios) throws InvalidFormatException;
/**
* Close this part : flush this part, close the input stream and output
* stream. After this method call, the part must be available for packaging.
*/
public abstract void close();
/**
* Flush the content of this part. If the input stream and/or output stream
* as in a waiting state to read or write, the must to empty their
* respective buffer.
*/
public abstract void flush();
}

View File

@ -0,0 +1,81 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc;
import java.util.ArrayList;
import java.util.TreeMap;
import org.apache.poi.openxml4j.exceptions.InvalidOperationException;
/**
* A package part collection.
*
* @author Julien Chable
* @version 0.1
*/
public final class PackagePartCollection extends
TreeMap<PackagePartName, PackagePart> {
private static final long serialVersionUID = 2515031135957635515L;
/**
* Arraylist use to store this collection part names as string for rule
* M1.11 optimized checking.
*/
private ArrayList<String> registerPartNameStr = new ArrayList<String>();
@Override
public Object clone() {
return super.clone();
}
/**
* Check rule [M1.11]: a package implementer shall neither create nor
* recognize a part with a part name derived from another part name by
* appending segments to it.
*
* @exception InvalidOperationException
* Throws if you try to add a part with a name derived from
* another part name.
*/
@Override
public PackagePart put(PackagePartName partName, PackagePart part) {
String[] segments = partName.getURI().toASCIIString().split(
PackagingURIHelper.FORWARD_SLASH_STRING);
StringBuffer concatSeg = new StringBuffer();
for (String seg : segments) {
if (!seg.equals(""))
concatSeg.append(PackagingURIHelper.FORWARD_SLASH_CHAR);
concatSeg.append(seg);
if (this.registerPartNameStr.contains(concatSeg.toString())) {
throw new InvalidOperationException(
"You can't add a part with a part name derived from another part ! [M1.11]");
}
}
this.registerPartNameStr.add(partName.getName());
return super.put(partName, part);
}
@Override
public PackagePart remove(Object key) {
if (key instanceof PackagePartName) {
this.registerPartNameStr.remove(((PackagePartName) key).getName());
}
return super.remove(key);
}
}

View File

@ -0,0 +1,509 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc;
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException;
/**
* An immutable Open Packaging Convention compliant part name.
*
* @author Julien Chable
* @version 0.1
*
* @see http://www.ietf.org/rfc/rfc3986.txt
*/
public final class PackagePartName implements Comparable<PackagePartName> {
/**
* Part name stored as an URI.
*/
private URI partNameURI;
/*
* URI Characters definition (RFC 3986)
*/
/**
* Reserved characters for sub delimitations.
*/
private static String[] RFC3986_PCHAR_SUB_DELIMS = { "!", "$", "&", "'",
"(", ")", "*", "+", ",", ";", "=" };
/**
* Unreserved character (+ ALPHA & DIGIT).
*/
private static String[] RFC3986_PCHAR_UNRESERVED_SUP = { "-", ".", "_", "~" };
/**
* Authorized reserved characters for pChar.
*/
private static String[] RFC3986_PCHAR_AUTHORIZED_SUP = { ":", "@" };
/**
* Flag to know if this part name is from a relationship part name.
*/
private boolean isRelationship;
/**
* Constructor. Makes a ValidPartName object from a java.net.URI
*
* @param uri
* The URI to validate and to transform into ValidPartName.
* @param checkConformance
* Flag to specify if the contructor have to validate the OPC
* conformance. Must be always <code>true</code> except for
* special URI like '/' which is needed for internal use by
* OpenXML4J but is not valid.
* @throws InvalidFormatException
* Throw if the specified part name is not conform to Open
* Packaging Convention specifications.
* @see java.net.URI
*/
PackagePartName(URI uri, boolean checkConformance)
throws InvalidFormatException {
if (checkConformance) {
throwExceptionIfInvalidPartUri(uri);
} else {
if (!PackagingURIHelper.PACKAGE_ROOT_URI.equals(uri)) {
throw new OpenXML4JRuntimeException(
"OCP conformance must be check for ALL part name except special cases : ['/']");
}
}
this.partNameURI = uri;
this.isRelationship = isRelationshipPartURI(this.partNameURI);
}
/**
* Constructor. Makes a ValidPartName object from a String part name.
*
* @param partName
* Part name to valid and to create.
* @param checkConformance
* Flag to specify if the contructor have to validate the OPC
* conformance. Must be always <code>true</code> except for
* special URI like '/' which is needed for internal use by
* OpenXML4J but is not valid.
* @throws InvalidFormatException
* Throw if the specified part name is not conform to Open
* Packaging Convention specifications.
*/
PackagePartName(String partName, boolean checkConformance)
throws InvalidFormatException {
URI partURI;
try {
partURI = new URI(partName);
} catch (URISyntaxException e) {
throw new IllegalArgumentException(
"partName argmument is not a valid OPC part name !");
}
if (checkConformance) {
throwExceptionIfInvalidPartUri(partURI);
} else {
if (!PackagingURIHelper.PACKAGE_ROOT_URI.equals(partURI)) {
throw new OpenXML4JRuntimeException(
"OCP conformance must be check for ALL part name except special cases : ['/']");
}
}
this.partNameURI = partURI;
this.isRelationship = isRelationshipPartURI(this.partNameURI);
}
/**
* Check if the specified part name is a relationship part name.
*
* @param partUri
* The URI to check.
* @return <code>true</code> if this part name respect the relationship
* part naming convention else <code>false</code>.
*/
private boolean isRelationshipPartURI(URI partUri) {
if (partUri == null)
throw new IllegalArgumentException("partUri");
return partUri.getPath().matches(
"^.*/" + PackagingURIHelper.RELATIONSHIP_PART_SEGMENT_NAME + "/.*\\"
+ PackagingURIHelper.RELATIONSHIP_PART_EXTENSION_NAME
+ "$");
}
/**
* Know if this part name is a relationship part name.
*
* @return <code>true</code> if this part name respect the relationship
* part naming convention else <code>false</code>.
*/
public boolean isRelationshipPartURI() {
return this.isRelationship;
}
/**
* Throws an exception (of any kind) if the specified part name does not
* follow the Open Packaging Convention specifications naming rules.
*
* @param partUri
* The part name to check.
* @throws Exception
* Throws if the part name is invalid.
*/
private static void throwExceptionIfInvalidPartUri(URI partUri)
throws InvalidFormatException {
if (partUri == null)
throw new IllegalArgumentException("partUri");
// Check if the part name URI is empty [M1.1]
throwExceptionIfEmptyURI(partUri);
// Check if the part name URI is absolute
throwExceptionIfAbsoluteUri(partUri);
// Check if the part name URI starts with a forward slash [M1.4]
throwExceptionIfPartNameNotStartsWithForwardSlashChar(partUri);
// Check if the part name URI ends with a forward slash [M1.5]
throwExceptionIfPartNameEndsWithForwardSlashChar(partUri);
// Check if the part name does not have empty segments. [M1.3]
// Check if a segment ends with a dot ('.') character. [M1.9]
throwExceptionIfPartNameHaveInvalidSegments(partUri);
}
/**
* Throws an exception if the specified URI is empty. [M1.1]
*
* @param partURI
* Part URI to check.
* @throws InvalidFormatException
* If the specified URI is empty.
*/
private static void throwExceptionIfEmptyURI(URI partURI)
throws InvalidFormatException {
if (partURI == null)
throw new IllegalArgumentException("partURI");
String uriPath = partURI.getPath();
if (uriPath.length() == 0
|| ((uriPath.length() == 1) && (uriPath.charAt(0) == PackagingURIHelper.FORWARD_SLASH_CHAR)))
throw new InvalidFormatException(
"A part name shall not be empty [M1.1]: "
+ partURI.getPath());
}
/**
* Throws an exception if the part name has empty segments. [M1.3]
*
* Throws an exception if a segment any characters other than pchar
* characters. [M1.6]
*
* Throws an exception if a segment contain percent-encoded forward slash
* ('/'), or backward slash ('\') characters. [M1.7]
*
* Throws an exception if a segment contain percent-encoded unreserved
* characters. [M1.8]
*
* Throws an exception if the specified part name's segments end with a dot
* ('.') character. [M1.9]
*
* Throws an exception if a segment doesn't include at least one non-dot
* character. [M1.10]
*
* @param partUri
* The part name to check.
* @throws InvalidFormatException
* if the specified URI contain an empty segments or if one the
* segments contained in the part name, ends with a dot ('.')
* character.
*/
private static void throwExceptionIfPartNameHaveInvalidSegments(URI partUri)
throws InvalidFormatException {
if (partUri == null || "".equals(partUri)) {
throw new IllegalArgumentException("partUri");
}
// Split the URI into several part and analyze each
String[] segments = partUri.toASCIIString().split("/");
if (segments.length <= 1 || !segments[0].equals(""))
throw new InvalidFormatException(
"A part name shall not have empty segments [M1.3]: "
+ partUri.getPath());
for (int i = 1; i < segments.length; ++i) {
String seg = segments[i];
if (seg == null || "".equals(seg)) {
throw new InvalidFormatException(
"A part name shall not have empty segments [M1.3]: "
+ partUri.getPath());
}
if (seg.endsWith(".")) {
throw new InvalidFormatException(
"A segment shall not end with a dot ('.') character [M1.9]: "
+ partUri.getPath());
}
if ("".equals(seg.replaceAll("\\\\.", ""))) {
// Normally will never been invoked with the previous
// implementation rule [M1.9]
throw new InvalidFormatException(
"A segment shall include at least one non-dot character. [M1.10]: "
+ partUri.getPath());
}
/*
* Check for rule M1.6, M1.7, M1.8
*/
checkPCharCompliance(seg);
}
}
/**
* Throws an exception if a segment any characters other than pchar
* characters. [M1.6]
*
* Throws an exception if a segment contain percent-encoded forward slash
* ('/'), or backward slash ('\') characters. [M1.7]
*
* Throws an exception if a segment contain percent-encoded unreserved
* characters. [M1.8]
*
* @param segment
* The segment to check
*/
private static void checkPCharCompliance(String segment)
throws InvalidFormatException {
boolean errorFlag;
for (int i = 0; i < segment.length(); ++i) {
char c = segment.charAt(i);
errorFlag = true;
/* Check rule M1.6 */
// Check for digit or letter
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')
|| (c >= '0' && c <= '9')) {
errorFlag = false;
} else {
// Check "-", ".", "_", "~"
for (int j = 0; j < RFC3986_PCHAR_UNRESERVED_SUP.length; ++j) {
if (c == RFC3986_PCHAR_UNRESERVED_SUP[j].charAt(0)) {
errorFlag = false;
break;
}
}
// Check ":", "@"
for (int j = 0; errorFlag
&& j < RFC3986_PCHAR_AUTHORIZED_SUP.length; ++j) {
if (c == RFC3986_PCHAR_AUTHORIZED_SUP[j].charAt(0)) {
errorFlag = false;
}
}
// Check "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "="
for (int j = 0; errorFlag
&& j < RFC3986_PCHAR_SUB_DELIMS.length; ++j) {
if (c == RFC3986_PCHAR_SUB_DELIMS[j].charAt(0)) {
errorFlag = false;
}
}
}
if (errorFlag && c == '%') {
// We certainly found an encoded character, check for length
// now ( '%' HEXDIGIT HEXDIGIT)
if (((segment.length() - i) < 2)) {
throw new InvalidFormatException("The segment " + segment
+ " contain invalid encoded character !");
}
// If not percent encoded character error occur then reset the
// flag -> the character is valid
errorFlag = false;
// Decode the encoded character
char decodedChar = (char) Integer.parseInt(segment.substring(
i + 1, i + 3), 16);
i += 2;
/* Check rule M1.7 */
if (decodedChar == '/' || decodedChar == '\\')
throw new InvalidFormatException(
"A segment shall not contain percent-encoded forward slash ('/'), or backward slash ('\') characters. [M1.7]");
/* Check rule M1.8 */
// Check for unreserved character like define in RFC3986
if ((decodedChar >= 'A' && decodedChar <= 'Z')
|| (decodedChar >= 'a' && decodedChar <= 'z')
|| (decodedChar >= '0' && decodedChar <= '9'))
errorFlag = true;
// Check for unreserved character "-", ".", "_", "~"
for (int j = 0; !errorFlag
&& j < RFC3986_PCHAR_UNRESERVED_SUP.length; ++j) {
if (c == RFC3986_PCHAR_UNRESERVED_SUP[j].charAt(0)) {
errorFlag = true;
break;
}
}
if (errorFlag)
throw new InvalidFormatException(
"A segment shall not contain percent-encoded unreserved characters. [M1.8]");
}
if (errorFlag)
throw new InvalidFormatException(
"A segment shall not hold any characters other than pchar characters. [M1.6]");
}
}
/**
* Throws an exception if the specified part name doesn't start with a
* forward slash character '/'. [M1.4]
*
* @param partUri
* The part name to check.
* @throws InvalidFormatException
* If the specified part name doesn't start with a forward slash
* character '/'.
*/
private static void throwExceptionIfPartNameNotStartsWithForwardSlashChar(
URI partUri) throws InvalidFormatException {
String uriPath = partUri.getPath();
if (uriPath.length() > 0
&& uriPath.charAt(0) != PackagingURIHelper.FORWARD_SLASH_CHAR)
throw new InvalidFormatException(
"A part name shall start with a forward slash ('/') character [M1.4]: "
+ partUri.getPath());
}
/**
* Throws an exception if the specified part name ends with a forwar slash
* character '/'. [M1.5]
*
* @param partUri
* The part name to check.
* @throws InvalidFormatException
* If the specified part name ends with a forwar slash character
* '/'.
*/
private static void throwExceptionIfPartNameEndsWithForwardSlashChar(
URI partUri) throws InvalidFormatException {
String uriPath = partUri.getPath();
if (uriPath.length() > 0
&& uriPath.charAt(uriPath.length() - 1) == PackagingURIHelper.FORWARD_SLASH_CHAR)
throw new InvalidFormatException(
"A part name shall not have a forward slash as the last character [M1.5]: "
+ partUri.getPath());
}
/**
* Throws an exception if the specified URI is absolute.
*
* @param partUri
* The URI to check.
* @throws InvalidFormatException
* Throws if the specified URI is absolute.
*/
private static void throwExceptionIfAbsoluteUri(URI partUri)
throws InvalidFormatException {
if (partUri.isAbsolute())
throw new InvalidFormatException("Absolute URI forbidden: "
+ partUri);
}
/**
* Compare two part name following the rule M1.12 :
*
* Part name equivalence is determined by comparing part names as
* case-insensitive ASCII strings. Packages shall not contain equivalent
* part names and package implementers shall neither create nor recognize
* packages with equivalent part names. [M1.12]
*/
public int compareTo(PackagePartName otherPartName) {
if (otherPartName == null)
return -1;
return this.partNameURI.toASCIIString().toLowerCase().compareTo(
otherPartName.partNameURI.toASCIIString().toLowerCase());
}
/**
* Retrieves the extension of the part name if any. If there is no extension
* returns an empty String. Example : '/document/content.xml' => 'xml'
*
* @return The extension of the part name.
*/
public String getExtension() {
String fragment = this.partNameURI.getPath();
if (fragment.length() > 0) {
int i = fragment.lastIndexOf(".");
if (i > -1)
return fragment.substring(i + 1);
}
return "";
}
/**
* Get this part name.
*
* @return The name of this part name.
*/
public String getName() {
return this.partNameURI.toASCIIString();
}
/**
* Part name equivalence is determined by comparing part names as
* case-insensitive ASCII strings. Packages shall not contain equivalent
* part names and package implementers shall neither create nor recognize
* packages with equivalent part names. [M1.12]
*/
@Override
public boolean equals(Object otherPartName) {
if (otherPartName == null
|| !(otherPartName instanceof PackagePartName))
return false;
return this.partNameURI.toASCIIString().toLowerCase().equals(
((PackagePartName) otherPartName).partNameURI.toASCIIString()
.toLowerCase());
}
@Override
public int hashCode() {
return this.partNameURI.toASCIIString().toLowerCase().hashCode();
}
@Override
public String toString() {
return getName();
}
/* Getters and setters */
/**
* Part name property getter.
*
* @return This part name URI.
*/
public URI getURI() {
return this.partNameURI;
}
}

View File

@ -0,0 +1,227 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc;
import java.util.Date;
import org.apache.poi.openxml4j.util.Nullable;
/**
* Represents the core properties of an OPC package.
*
* @author Julien Chable
* @version 1.0
* @see org.apache.poi.openxml4j.opc.Package
*/
public interface PackageProperties {
/**
* Dublin Core Terms URI.
*/
public final static String NAMESPACE_DCTERMS = "http://purl.org/dc/terms/";
/**
* Dublin Core namespace URI.
*/
public final static String NAMESPACE_DC = "http://purl.org/dc/elements/1.1/";
/* Getters and setters */
/**
* Set the category of the content of this package.
*/
public abstract Nullable<String> getCategoryProperty();
/**
* Set the category of the content of this package.
*/
public abstract void setCategoryProperty(String category);
/**
* Set the status of the content.
*/
public abstract Nullable<String> getContentStatusProperty();
/**
* Get the status of the content.
*/
public abstract void setContentStatusProperty(String contentStatus);
/**
* Get the type of content represented, generally defined by a specific use
* and intended audience.
*/
public abstract Nullable<String> getContentTypeProperty();
/**
* Set the type of content represented, generally defined by a specific use
* and intended audience.
*/
public abstract void setContentTypeProperty(String contentType);
/**
* Get the date of creation of the resource.
*/
public abstract Nullable<Date> getCreatedProperty();
/**
* Set the date of creation of the resource.
*/
public abstract void setCreatedProperty(String created);
/**
* Set the date of creation of the resource.
*/
public abstract void setCreatedProperty(Nullable<Date> created);
/**
* Get the entity primarily responsible for making the content of the
* resource.
*/
public abstract Nullable<String> getCreatorProperty();
/**
* Set the entity primarily responsible for making the content of the
* resource.
*/
public abstract void setCreatorProperty(String creator);
/**
* Get the explanation of the content of the resource.
*/
public abstract Nullable<String> getDescriptionProperty();
/**
* Set the explanation of the content of the resource.
*/
public abstract void setDescriptionProperty(String description);
/**
* Get an unambiguous reference to the resource within a given context.
*/
public abstract Nullable<String> getIdentifierProperty();
/**
* Set an unambiguous reference to the resource within a given context.
*/
public abstract void setIdentifierProperty(String identifier);
/**
* Get a delimited set of keywords to support searching and indexing. This
* is typically a list of terms that are not available elsewhere in the
* properties
*/
public abstract Nullable<String> getKeywordsProperty();
/**
* Set a delimited set of keywords to support searching and indexing. This
* is typically a list of terms that are not available elsewhere in the
* properties
*/
public abstract void setKeywordsProperty(String keywords);
/**
* Get the language of the intellectual content of the resource.
*/
public abstract Nullable<String> getLanguageProperty();
/**
* Set the language of the intellectual content of the resource.
*/
public abstract void setLanguageProperty(String language);
/**
* Get the user who performed the last modification.
*/
public abstract Nullable<String> getLastModifiedByProperty();
/**
* Set the user who performed the last modification.
*/
public abstract void setLastModifiedByProperty(String lastModifiedBy);
/**
* Get the date and time of the last printing.
*/
public abstract Nullable<Date> getLastPrintedProperty();
/**
* Set the date and time of the last printing.
*/
public abstract void setLastPrintedProperty(String lastPrinted);
/**
* Set the date and time of the last printing.
*/
public abstract void setLastPrintedProperty(Nullable<Date> lastPrinted);
/**
* Get the date on which the resource was changed.
*/
public abstract Nullable<Date> getModifiedProperty();
/**
* Set the date on which the resource was changed.
*/
public abstract void setModifiedProperty(String modified);
/**
* Set the date on which the resource was changed.
*/
public abstract void setModifiedProperty(Nullable<Date> modified);
/**
* Get the revision number.
*/
public abstract Nullable<String> getRevisionProperty();
/**
* Set the revision number.
*/
public abstract void setRevisionProperty(String revision);
/**
* Get the topic of the content of the resource.
*/
public abstract Nullable<String> getSubjectProperty();
/**
* Set the topic of the content of the resource.
*/
public abstract void setSubjectProperty(String subject);
/**
* Get the name given to the resource.
*/
public abstract Nullable<String> getTitleProperty();
/**
* Set the name given to the resource.
*/
public abstract void setTitleProperty(String title);
/**
* Get the version number.
*/
public abstract Nullable<String> getVersionProperty();
/**
* Set the version number.
*/
public abstract void setVersionProperty(String version);
}

View File

@ -0,0 +1,227 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc;
import java.net.URI;
import java.net.URISyntaxException;
/**
* A part relationship.
*
* @author Julien Chable
* @version 1.0
*/
public final class PackageRelationship {
private static URI containerRelationshipPart;
static {
try {
containerRelationshipPart = new URI("/_rels/.rels");
} catch (URISyntaxException e) {
// Do nothing
}
}
/* XML markup */
public static final String ID_ATTRIBUTE_NAME = "Id";
public static final String RELATIONSHIPS_TAG_NAME = "Relationships";
public static final String RELATIONSHIP_TAG_NAME = "Relationship";
public static final String TARGET_ATTRIBUTE_NAME = "Target";
public static final String TARGET_MODE_ATTRIBUTE_NAME = "TargetMode";
public static final String TYPE_ATTRIBUTE_NAME = "Type";
/* End XML markup */
/**
* L'ID de la relation.
*/
private String id;
/**
* R<EFBFBD>f<EFBFBD>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();
}
}

View File

@ -0,0 +1,450 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.TreeMap;
import org.apache.log4j.Logger;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.InvalidOperationException;
/**
* Represents a collection of PackageRelationship elements that are owned by a
* given PackagePart or the Package.
*
* @author Julien Chable, CDubettier
* @version 0.1
*/
public final class PackageRelationshipCollection implements
Iterable<PackageRelationship> {
private static Logger logger = Logger.getLogger("org.openxml4j.opc");
/**
* Package relationships ordered by ID.
*/
private TreeMap<String, PackageRelationship> relationshipsByID;
/**
* Package relationships ordered by type.
*/
private TreeMap<String, PackageRelationship> relationshipsByType;
/**
* This relationshipPart.
*/
private PackagePart relationshipPart;
/**
* Source part.
*/
private PackagePart sourcePart;
/**
* This part name.
*/
private PackagePartName partName;
/**
* Reference to the package.
*/
private Package container;
/**
* Constructor.
*/
PackageRelationshipCollection() {
relationshipsByID = new TreeMap<String, PackageRelationship>();
relationshipsByType = new TreeMap<String, PackageRelationship>();
}
/**
* Copy constructor.
*
* This collection will contain only elements from the specified collection
* for which the type is compatible with the specified relationship type
* filter.
*
* @param coll
* Collection to import.
* @param filter
* Relationship type filter.
*/
public PackageRelationshipCollection(PackageRelationshipCollection coll,
String filter) {
this();
for (PackageRelationship rel : coll.relationshipsByID.values()) {
if (filter == null || rel.getRelationshipType().equals(filter))
addRelationship(rel);
}
}
/**
* Constructor.
*/
public PackageRelationshipCollection(Package container)
throws InvalidFormatException {
this(container, null);
}
/**
* Constructor.
*
* @throws InvalidFormatException
* Throws if the format of the content part is invalid.
*
* @throws InvalidOperationException
* Throws if the specified part is a relationship part.
*/
public PackageRelationshipCollection(PackagePart part)
throws InvalidFormatException {
this(part.container, part);
}
/**
* Constructor. Parse the existing package relationship part if one exists.
*
* @param container
* The parent package.
* @param part
* The part that own this relationships collection. If <b>null</b>
* then this part is considered as the package root.
* @throws InvalidFormatException
* If an error occurs during the parsing of the relatinships
* part fo the specified part.
*/
public PackageRelationshipCollection(Package container, PackagePart part)
throws InvalidFormatException {
this();
if (container == null)
throw new IllegalArgumentException("container");
// Check if the specified part is not a relationship part
if (part != null && part.isRelationshipPart())
throw new IllegalArgumentException("part");
this.container = container;
this.sourcePart = part;
this.partName = getRelationshipPartName(part);
if ((container.getPackageAccess() != PackageAccess.WRITE)
&& container.containPart(this.partName)) {
relationshipPart = container.getPart(this.partName);
parseRelationshipsPart(relationshipPart);
}
}
/**
* Get the relationship part name of the specified part.
*
* @param part
* The part .
* @return The relationship part name of the specified part. Be careful,
* only the correct name is returned, this method does not check if
* the part really exist in a package !
* @throws InvalidOperationException
* Throws if the specified part is a relationship part.
*/
private static PackagePartName getRelationshipPartName(PackagePart part)
throws InvalidOperationException {
PackagePartName partName;
if (part == null) {
partName = PackagingURIHelper.PACKAGE_ROOT_PART_NAME;
} else {
partName = part.getPartName();
}
return PackagingURIHelper.getRelationshipPartName(partName);
}
/**
* Add the specified relationship to the collection.
*
* @param relPart
* The relationship to add.
*/
public void addRelationship(PackageRelationship relPart) {
relationshipsByID.put(relPart.getId(), relPart);
relationshipsByType.put(relPart.getRelationshipType(), relPart);
}
/**
* Add a relationship to the collection.
*
* @param targetUri
* Target URI.
* @param targetMode
* The target mode : INTERNAL or EXTERNAL
* @param relationshipType
* Relationship type.
* @param id
* Relationship ID.
* @return The newly created relationship.
* @see PackageAccess
*/
public PackageRelationship addRelationship(URI targetUri,
TargetMode targetMode, String relationshipType, String id) {
if (id == null) {
// Generate a unique ID is id parameter is null.
int i = 0;
do {
id = "rId" + ++i;
} while (relationshipsByID.get(id) != null);
}
PackageRelationship rel = new PackageRelationship(container,
sourcePart, targetUri, targetMode, relationshipType, id);
relationshipsByID.put(rel.getId(), rel);
relationshipsByType.put(rel.getRelationshipType(), rel);
return rel;
}
/**
* Remove a relationship by its ID.
*
* @param id
* The relationship ID to remove.
*/
public void removeRelationship(String id) {
if (relationshipsByID != null && relationshipsByType != null) {
PackageRelationship rel = relationshipsByID.get(id);
if (rel != null) {
relationshipsByID.remove(rel.getId());
relationshipsByType.values().remove(rel);
}
}
}
/**
* Remove a relationship by its reference.
*
* @param rel
* The relationship to delete.
*/
public void removeRelationship(PackageRelationship rel) {
if (rel == null)
throw new IllegalArgumentException("rel");
relationshipsByID.values().remove(rel);
relationshipsByType.values().remove(rel);
}
/**
* Retrieves a relationship by its index in the collection.
*
* @param index
* Must be a value between [0-relationships_count-1]
*/
public PackageRelationship getRelationship(int index) {
if (index < 0 || index > relationshipsByID.values().size())
throw new IllegalArgumentException("index");
PackageRelationship retRel = null;
int i = 0;
for (PackageRelationship rel : relationshipsByID.values()) {
if (index == i++)
return rel;
}
return retRel;
}
/**
* Retrieves a package relationship based on its id.
*
* @param id
* ID of the package relationship to retrieve.
* @return The package relationship identified by the specified id.
*/
public PackageRelationship getRelationshipByID(String id) {
return relationshipsByID.get(id);
}
/**
* Get the numbe rof relationships in the collection.
*/
public int size() {
return relationshipsByID.values().size();
}
/**
* Parse the relationship part and add all relationship in this collection.
*
* @param relPart
* The package part to parse.
* @throws InvalidFormatException
* Throws if the relationship part is invalid.
*/
private void parseRelationshipsPart(PackagePart relPart)
throws InvalidFormatException {
try {
SAXReader reader = new SAXReader();
logger.debug("Parsing relationship: " + relPart.getPartName());
Document xmlRelationshipsDoc = reader
.read(relPart.getInputStream());
// Browse default types
Element root = xmlRelationshipsDoc.getRootElement();
// Check OPC compliance M4.1 rule
boolean fCorePropertiesRelationship = false;
for (Iterator i = root
.elementIterator(PackageRelationship.RELATIONSHIP_TAG_NAME); i
.hasNext();) {
Element element = (Element) i.next();
// Relationship ID
String id = element.attribute(
PackageRelationship.ID_ATTRIBUTE_NAME).getValue();
// Relationship type
String type = element.attribute(
PackageRelationship.TYPE_ATTRIBUTE_NAME).getValue();
/* Check OPC Compliance */
// Check Rule M4.1
if (type.equals(PackageRelationshipTypes.CORE_PROPERTIES))
if (!fCorePropertiesRelationship)
fCorePropertiesRelationship = true;
else
throw new InvalidFormatException(
"OPC Compliance error [M4.1]: there is more than one core properties relationship in the package !");
/* End OPC Compliance */
// TargetMode (default value "Internal")
Attribute targetModeAttr = element
.attribute(PackageRelationship.TARGET_MODE_ATTRIBUTE_NAME);
TargetMode targetMode = TargetMode.INTERNAL;
if (targetModeAttr != null) {
targetMode = targetModeAttr.getValue().toLowerCase()
.equals("internal") ? TargetMode.INTERNAL
: TargetMode.EXTERNAL;
}
// Target converted in URI
URI target;
String value = "";
try {
value = element.attribute(
PackageRelationship.TARGET_ATTRIBUTE_NAME)
.getValue();
if (value.indexOf("\\") != -1) {
logger
.info("target contains \\ therefore not a valid URI"
+ value + " replaced by /");
value = value.replaceAll("\\\\", "/");
// word can save external relationship with a \ instead
// of /
}
target = new URI(value);
} catch (URISyntaxException e) {
logger.error("Cannot convert " + value
+ " in a valid relationship URI-> ignored", e);
continue;
}
addRelationship(target, targetMode, type, id);
}
} catch (Exception e) {
logger.error(e);
throw new InvalidFormatException(e.getMessage());
}
}
/**
* Retrieves all relations with the specified type.
*
* @param typeFilter
* Relationship type filter. If <b>null</b> then all
* relationships are returned.
* @return All relationships of the type specified by the filter.
*/
public PackageRelationshipCollection getRelationships(String typeFilter) {
PackageRelationshipCollection coll = new PackageRelationshipCollection(
this, typeFilter);
return coll;
}
/**
* Get this collection's iterator.
*/
public Iterator<PackageRelationship> iterator() {
return relationshipsByID.values().iterator();
}
/**
* Get an iterator of a collection with all relationship with the specified
* type.
*
* @param typeFilter
* Type filter.
* @return An iterator to a collection containing all relationships with the
* specified type contain in this collection.
*/
public Iterator<PackageRelationship> iterator(String typeFilter) {
ArrayList<PackageRelationship> retArr = new ArrayList<PackageRelationship>();
for (PackageRelationship rel : relationshipsByID.values()) {
if (rel.getRelationshipType().equals(typeFilter))
retArr.add(rel);
}
return retArr.iterator();
}
/**
* Clear all relationships.
*/
public void clear() {
relationshipsByID.clear();
relationshipsByType.clear();
}
@Override
public String toString() {
String str;
if (relationshipsByID == null) {
str = "relationshipsByID=null";
} else {
str = relationshipsByID.size() + " relationship(s) = [";
}
if ((relationshipPart != null) && (relationshipPart.partName != null)) {
str = str + "," + relationshipPart.partName;
} else {
str = str + ",relationshipPart=null";
}
// Source of this relationship
if ((sourcePart != null) && (sourcePart.partName != null)) {
str = str + "," + sourcePart.partName;
} else {
str = str + ",sourcePart=null";
}
if (partName != null) {
str = str + "," + partName;
} else {
str = str + ",uri=null)";
}
return str + "]";
}
}

View File

@ -0,0 +1,77 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc;
/**
* Relationship types.
*
* @author Julien Chable
* @version 0.2
*/
public interface PackageRelationshipTypes {
/**
* Core properties relationship type.
*/
String CORE_PROPERTIES = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
/**
* Digital signature relationship type.
*/
String DIGITAL_SIGNATURE = "http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/signature";
/**
* Digital signature certificate relationship type.
*/
String DIGITAL_SIGNATURE_CERTIFICATE = "http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/certificate";
/**
* Digital signature origin relationship type.
*/
String DIGITAL_SIGNATURE_ORIGIN = "http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin";
/**
* Thumbnail relationship type.
*/
String THUMBNAIL = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
/**
* Extended properties relationship type.
*/
String EXTENDED_PROPERTIES = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties";
/**
* Core properties relationship type.
*/
String CORE_DOCUMENT = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
/**
* Custom XML relationship type.
*/
String CUSTOM_XML = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml";
/**
* Image type.
*/
String IMAGE_PART = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
/**
* Style type.
*/
String STYLE_PART = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";
}

View File

@ -0,0 +1,623 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc;
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.InvalidOperationException;
/**
* Helper for part and pack URI.
*
* @author Julien Chable, CDubet, Kim Ung
* @version 0.1
*/
public final class PackagingURIHelper {
/**
* Package root URI.
*/
private static URI packageRootUri;
/**
* Extension name of a relationship part.
*/
public static final String RELATIONSHIP_PART_EXTENSION_NAME;
/**
* Segment name of a relationship part.
*/
public static final String RELATIONSHIP_PART_SEGMENT_NAME;
/**
* Segment name of the package properties folder.
*/
public static final String PACKAGE_PROPERTIES_SEGMENT_NAME;
/**
* Core package properties art name.
*/
public static final String PACKAGE_CORE_PROPERTIES_NAME;
/**
* Forward slash URI separator.
*/
public static final char FORWARD_SLASH_CHAR;
/**
* Forward slash URI separator.
*/
public static final String FORWARD_SLASH_STRING;
/**
* Package relationships part URI
*/
public static final URI PACKAGE_RELATIONSHIPS_ROOT_URI;
/**
* Package relationships part name.
*/
public static final PackagePartName PACKAGE_RELATIONSHIPS_ROOT_PART_NAME;
/**
* Core properties part URI.
*/
public static final URI CORE_PROPERTIES_URI;
/**
* Core properties partname.
*/
public static final PackagePartName CORE_PROPERTIES_PART_NAME;
/**
* Root package URI.
*/
public static final URI PACKAGE_ROOT_URI;
/**
* Root package part name.
*/
public static final PackagePartName PACKAGE_ROOT_PART_NAME;
/* Static initialization */
static {
RELATIONSHIP_PART_SEGMENT_NAME = "_rels";
RELATIONSHIP_PART_EXTENSION_NAME = ".rels";
FORWARD_SLASH_CHAR = '/';
FORWARD_SLASH_STRING = "/";
PACKAGE_PROPERTIES_SEGMENT_NAME = "docProps";
PACKAGE_CORE_PROPERTIES_NAME = "core.xml";
// Make URI
URI uriPACKAGE_ROOT_URI = null;
URI uriPACKAGE_RELATIONSHIPS_ROOT_URI = null;
URI uriPACKAGE_PROPERTIES_URI = null;
try {
uriPACKAGE_ROOT_URI = new URI("/");
uriPACKAGE_RELATIONSHIPS_ROOT_URI = new URI(FORWARD_SLASH_CHAR
+ RELATIONSHIP_PART_SEGMENT_NAME + FORWARD_SLASH_CHAR
+ RELATIONSHIP_PART_EXTENSION_NAME);
packageRootUri = new URI("/");
uriPACKAGE_PROPERTIES_URI = new URI(FORWARD_SLASH_CHAR
+ PACKAGE_PROPERTIES_SEGMENT_NAME + FORWARD_SLASH_CHAR
+ PACKAGE_CORE_PROPERTIES_NAME);
} catch (URISyntaxException e) {
// Should never happen in production as all data are fixed
}
PACKAGE_ROOT_URI = uriPACKAGE_ROOT_URI;
PACKAGE_RELATIONSHIPS_ROOT_URI = uriPACKAGE_RELATIONSHIPS_ROOT_URI;
CORE_PROPERTIES_URI = uriPACKAGE_PROPERTIES_URI;
// Make part name from previous URI
PackagePartName tmpPACKAGE_ROOT_PART_NAME = null;
PackagePartName tmpPACKAGE_RELATIONSHIPS_ROOT_PART_NAME = null;
PackagePartName tmpCORE_PROPERTIES_URI = null;
try {
tmpPACKAGE_RELATIONSHIPS_ROOT_PART_NAME = createPartName(PACKAGE_RELATIONSHIPS_ROOT_URI);
tmpCORE_PROPERTIES_URI = createPartName(CORE_PROPERTIES_URI);
tmpPACKAGE_ROOT_PART_NAME = new PackagePartName(PACKAGE_ROOT_URI,
false);
} catch (InvalidFormatException e) {
// Should never happen in production as all data are fixed
}
PACKAGE_RELATIONSHIPS_ROOT_PART_NAME = tmpPACKAGE_RELATIONSHIPS_ROOT_PART_NAME;
CORE_PROPERTIES_PART_NAME = tmpCORE_PROPERTIES_URI;
PACKAGE_ROOT_PART_NAME = tmpPACKAGE_ROOT_PART_NAME;
}
/**
* Gets the URI for the package root.
*
* @return URI of the package root.
*/
public static URI getPackageRootUri() {
return packageRootUri;
}
/**
* Know if the specified URI is a relationship part name.
*
* @param partUri
* URI to check.
* @return <i>true</i> if the URI <i>false</i>.
*/
public static boolean isRelationshipPartURI(URI partUri) {
if (partUri == null)
throw new IllegalArgumentException("partUri");
return partUri.getPath().matches(
".*" + RELATIONSHIP_PART_SEGMENT_NAME + ".*"
+ RELATIONSHIP_PART_EXTENSION_NAME + "$");
}
/**
* Get file name from the specified URI.
*/
public static String getFilename(URI uri) {
if (uri != null) {
String path = uri.getPath();
int len = path.length();
int num2 = len;
while (--num2 >= 0) {
char ch1 = path.charAt(num2);
if (ch1 == PackagingURIHelper.FORWARD_SLASH_CHAR)
return path.substring(num2 + 1, len);
}
}
return "";
}
/**
* Get the file name without the trailing extension.
*/
public static String getFilenameWithoutExtension(URI uri) {
String filename = getFilename(uri);
int dotIndex = filename.lastIndexOf(".");
if (dotIndex == -1)
return filename;
return filename.substring(0, dotIndex);
}
/**
* Get the directory path from the specified URI.
*/
public static URI getPath(URI uri) {
if (uri != null) {
String path = uri.getPath();
int len = path.length();
int num2 = len;
while (--num2 >= 0) {
char ch1 = path.charAt(num2);
if (ch1 == PackagingURIHelper.FORWARD_SLASH_CHAR) {
try {
return new URI(path.substring(0, num2));
} catch (URISyntaxException e) {
return null;
}
}
}
}
return null;
}
/**
* Combine les deux URI.
*
* @param prefix
* L'URI de pr<EFBFBD>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<61>tre relationshipPartUri ne doit pas <20>tre null !");
if (!isRelationshipPartURI(relationshipPartUri))
throw new IllegalArgumentException(
"L'URI ne doit pas <20>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;
}
}

View File

@ -0,0 +1,166 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.InvalidOperationException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
public interface RelationshipSource {
/**
* Add a relationship to a part (except relationships part).
*
* @param targetPartName
* Name of the target part. This one must be relative to the
* source root directory of the part.
* @param targetMode
* Mode [Internal|External].
* @param relationshipType
* Type of relationship.
* @return The newly created and added relationship
*/
public abstract PackageRelationship addRelationship(
PackagePartName targetPartName, TargetMode targetMode,
String relationshipType);
/**
* Add a relationship to a part (except relationships part).
*
* Check rule M1.25: The Relationships part shall not have relationships to
* any other part. Package implementers shall enforce this requirement upon
* the attempt to create such a relationship and shall treat any such
* relationship as invalid.
*
* @param targetPartName
* Name of the target part. This one must be relative to the
* source root directory of the part.
* @param targetMode
* Mode [Internal|External].
* @param relationshipType
* Type of relationship.
* @param id
* Relationship unique id.
* @return The newly created and added relationship
*
* @throws InvalidFormatException
* If the URI point to a relationship part URI.
*/
public abstract PackageRelationship addRelationship(
PackagePartName targetPartName, TargetMode targetMode,
String relationshipType, String id);
/**
* Adds an external relationship to a part
* (except relationships part).
*
* The targets of external relationships are not
* subject to the same validity checks that internal
* ones are, as the contents is potentially
* any file, URL or similar.
*
* @param target External target of the relationship
* @param relationshipType Type of relationship.
* @return The newly created and added relationship
* @see org.apache.poi.openxml4j.opc.RelationshipSource#addExternalRelationship(java.lang.String, java.lang.String)
*/
public PackageRelationship addExternalRelationship(String target, String relationshipType);
/**
* Adds an external relationship to a part
* (except relationships part).
*
* The targets of external relationships are not
* subject to the same validity checks that internal
* ones are, as the contents is potentially
* any file, URL or similar.
*
* @param target External target of the relationship
* @param relationshipType Type of relationship.
* @param id Relationship unique id.
* @return The newly created and added relationship
* @see org.apache.poi.openxml4j.opc.RelationshipSource#addExternalRelationship(java.lang.String, java.lang.String)
*/
public PackageRelationship addExternalRelationship(String target, String relationshipType, String id);
/**
* Delete all the relationships attached to this.
*/
public abstract void clearRelationships();
/**
* Delete the relationship specified by its id.
*
* @param id
* The ID identified the part to delete.
*/
public abstract void removeRelationship(String id);
/**
* Retrieve all the relationships attached to this.
*
* @return This part's relationships.
* @throws OpenXML4JException
*/
public abstract PackageRelationshipCollection getRelationships()
throws InvalidFormatException, OpenXML4JException;
/**
* Retrieves a package relationship from its id.
*
* @param id
* ID of the package relationship to retrieve.
* @return The package relationship
*/
public abstract PackageRelationship getRelationship(String id);
/**
* Retrieve all relationships attached to this part which have the specified
* type.
*
* @param relationshipType
* Relationship type filter.
* @return All relationships from this part that have the specified type.
* @throws InvalidFormatException
* If an error occurs while parsing the part.
* @throws InvalidOperationException
* If the package is open in write only mode.
*/
public abstract PackageRelationshipCollection getRelationshipsByType(
String relationshipType) throws InvalidFormatException,
IllegalArgumentException, OpenXML4JException;
/**
* Knows if the part have any relationships.
*
* @return <b>true</b> if the part have at least one relationship else
* <b>false</b>.
*/
public abstract boolean hasRelationships();
/**
* Checks if the specified relationship is part of this package part.
*
* @param rel
* The relationship to check.
* @return <b>true</b> if the specified relationship exists in this part,
* else returns <b>false</b>
*/
@SuppressWarnings("finally")
public abstract boolean isRelationshipExists(PackageRelationship rel);
}

View File

@ -0,0 +1,77 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc;
import java.io.InputStream;
import java.io.OutputStream;
import org.dom4j.Document;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
public final class StreamHelper {
private StreamHelper() {
// Do nothing
}
/**
* Turning the DOM4j object in the specified output stream.
*
* @param xmlContent
* The XML document.
* @param outStream
* The OutputStream in which the XML document will be written.
* @return <b>true</b> if the xml is successfully written in the stream,
* else <b>false</b>.
*/
public static boolean saveXmlInStream(Document xmlContent,
OutputStream outStream) {
try {
OutputFormat outformat = OutputFormat.createPrettyPrint();
outformat.setEncoding("UTF-8");
XMLWriter writer = new XMLWriter(outStream, outformat);
writer.write(xmlContent);
} catch (Exception e) {
return false;
}
return true;
}
/**
* Copy the input stream into the output stream.
*
* @param inStream
* The source stream.
* @param outStream
* The destination stream.
* @return <b>true</b> if the operation succeed, else return <b>false</b>.
*/
public static boolean copyStream(InputStream inStream, OutputStream outStream) {
try {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inStream.read(buffer)) >= 0) {
outStream.write(buffer, 0, bytesRead);
}
} catch (Exception e) {
return false;
}
return true;
}
}

View File

@ -0,0 +1,32 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc;
/**
* Specifies whether the target of a PackageRelationship is inside or outside a
* Package.
*
* @author Julien Chable
* @version 1.0
*/
public enum TargetMode {
/** The relationship references a resource that is external to the package. */
INTERNAL,
/** The relationship references a part that is inside the package. */
EXTERNAL
}

View File

@ -0,0 +1,464 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import org.apache.log4j.Logger;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.InvalidOperationException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.internal.ContentTypeManager;
import org.apache.poi.openxml4j.opc.internal.FileHelper;
import org.apache.poi.openxml4j.opc.internal.MemoryPackagePart;
import org.apache.poi.openxml4j.opc.internal.PartMarshaller;
import org.apache.poi.openxml4j.opc.internal.ZipContentTypeManager;
import org.apache.poi.openxml4j.opc.internal.ZipHelper;
import org.apache.poi.openxml4j.opc.internal.marshallers.ZipPackagePropertiesMarshaller;
import org.apache.poi.openxml4j.opc.internal.marshallers.ZipPartMarshaller;
import org.apache.poi.openxml4j.util.ZipEntrySource;
import org.apache.poi.openxml4j.util.ZipFileZipEntrySource;
import org.apache.poi.openxml4j.util.ZipInputStreamZipEntrySource;
/**
* Physical zip package.
*
* @author Julien Chable
* @version 0.2
*/
public final class ZipPackage extends Package {
private static Logger logger = Logger.getLogger("org.openxml4j");
/**
* Zip archive, as either a file on disk,
* or a stream
*/
private final ZipEntrySource zipArchive;
/**
* Constructor. Creates a new ZipPackage.
*/
public ZipPackage() {
super(defaultPackageAccess);
this.zipArchive = null;
}
/**
* Constructor. <b>Operation not supported.</b>
*
* @param in
* Zip input stream to load.
* @param access
* @throws IllegalArgumentException
* If the specified input stream not an instance of
* ZipInputStream.
*/
ZipPackage(InputStream in, PackageAccess access) throws IOException {
super(access);
this.zipArchive = new ZipInputStreamZipEntrySource(
new ZipInputStream(in)
);
}
/**
* Constructor. Opens a Zip based Open XML document.
*
* @param path
* The path of the file to open or create.
* @param access
* The package access mode.
* @throws InvalidFormatException
* If the content type part parsing encounters an error.
*/
ZipPackage(String path, PackageAccess access) throws InvalidFormatException {
super(access);
ZipFile zipFile = ZipHelper.openZipFile(path);
if (zipFile == null)
throw new InvalidOperationException(
"Can't open the specified file: '" + path + "'");
this.zipArchive = new ZipFileZipEntrySource(zipFile);
}
/**
* Retrieves the parts from this package. We assume that the package has not
* been yet inspect to retrieve all the parts, this method will open the
* archive and look for all parts contain inside it. If the package part
* list is not empty, it will be emptied.
*
* @return All parts contain in this package.
* @throws InvalidFormatException
* Throws if the package is not valid.
*/
@Override
protected PackagePart[] getPartsImpl() throws InvalidFormatException {
if (this.partList == null) {
// The package has just been created, we create an empty part
// list.
this.partList = new PackagePartCollection();
}
if (this.zipArchive == null) {
return this.partList.values().toArray(
new PackagePart[this.partList.values().size()]);
} else {
// First we need to parse the content type part
Enumeration<? extends ZipEntry> entries = this.zipArchive.getEntries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
if (entry.getName().equals(
ContentTypeManager.CONTENT_TYPES_PART_NAME)) {
try {
this.contentTypeManager = new ZipContentTypeManager(
getZipArchive().getInputStream(entry), this);
} catch (IOException e) {
throw new InvalidFormatException(e.getMessage());
}
break;
}
}
// At this point, we should have loaded the content type part
if (this.contentTypeManager == null) {
throw new InvalidFormatException(
"Package should contain a content type part [M1.13]");
}
// Now create all the relationships
// (Need to create relationships before other
// parts, otherwise we might create a part before
// its relationship exists, and then it won't tie up)
entries = this.zipArchive.getEntries();
while (entries.hasMoreElements()) {
ZipEntry entry = (ZipEntry) entries.nextElement();
PackagePartName partName = buildPartName(entry);
if(partName == null) continue;
// Only proceed for Relationships at this stage
String contentType = contentTypeManager.getContentType(partName);
if (contentType != null && contentType.equals(ContentTypes.RELATIONSHIPS_PART)) {
try {
partList.put(partName, new ZipPackagePart(this, entry,
partName, contentType));
} catch (InvalidOperationException e) {
throw new InvalidFormatException(e.getMessage());
}
}
}
// Then we can go through all the other parts
entries = this.zipArchive.getEntries();
while (entries.hasMoreElements()) {
ZipEntry entry = (ZipEntry) entries.nextElement();
PackagePartName partName = buildPartName(entry);
if(partName == null) continue;
String contentType = contentTypeManager
.getContentType(partName);
if (contentType != null && contentType.equals(ContentTypes.RELATIONSHIPS_PART)) {
// Already handled
}
else if (contentType != null) {
try {
partList.put(partName, new ZipPackagePart(this, entry,
partName, contentType));
} catch (InvalidOperationException e) {
throw new InvalidFormatException(e.getMessage());
}
} else {
throw new InvalidFormatException(
"The part "
+ partName.getURI().getPath()
+ " does not have any content type ! Rule: Package require content types when retrieving a part from a package. [M.1.14]");
}
}
return (ZipPackagePart[]) partList.values().toArray(
new ZipPackagePart[partList.size()]);
}
}
/**
* Builds a PackagePartName for the given ZipEntry,
* or null if it's the content types / invalid part
*/
private PackagePartName buildPartName(ZipEntry entry) {
try {
// We get an error when we parse [Content_Types].xml
// because it's not a valid URI.
if (entry.getName().equals(
ContentTypeManager.CONTENT_TYPES_PART_NAME)) {
return null;
} else {
return PackagingURIHelper.createPartName(ZipHelper
.getOPCNameFromZipItemName(entry.getName()));
}
} catch (Exception e) {
// We assume we can continue, even in degraded mode ...
logger.warn("Entry "
+ entry.getName()
+ " is not valid, so this part won't be add to the package.");
return null;
}
}
/**
* Create a new MemoryPackagePart from the specified URI and content type
*
*
* aram partName The part URI.
*
* @param contentType
* The part content type.
* @return The newly created zip package part, else <b>null</b>.
*/
@Override
protected PackagePart createPartImpl(PackagePartName partName,
String contentType, boolean loadRelationships) {
if (contentType == null)
throw new IllegalArgumentException("contentType");
if (partName == null)
throw new IllegalArgumentException("partName");
try {
return new MemoryPackagePart(this, partName, contentType,
loadRelationships);
} catch (InvalidFormatException e) {
System.err.println(e);
return null;
}
}
/**
* Delete a part from the package
*
* @throws IllegalArgumentException
* Throws if the part URI is nulll or invalid.
*/
@Override
protected void removePartImpl(PackagePartName partName) {
if (partName == null)
throw new IllegalArgumentException("partUri");
}
/**
* Flush the package. Do nothing.
*/
@Override
protected void flushImpl() {
// Do nothing
}
/**
* Close and save the package.
*
* @see #close()
*/
@Override
protected void closeImpl() throws IOException {
// Flush the package
flush();
// Save the content
if (this.originalPackagePath != null
&& !"".equals(this.originalPackagePath)) {
File targetFile = new File(this.originalPackagePath);
if (targetFile.exists()) {
// Case of a package previously open
File tempFile = File.createTempFile(
generateTempFileName(FileHelper
.getDirectory(targetFile)), ".tmp");
// Save the final package to a temporary file
try {
save(tempFile);
this.zipArchive.close(); // Close the zip archive to be
// able to delete it
FileHelper.copyFile(tempFile, targetFile);
} finally {
// Either the save operation succeed or not, we delete the
// temporary file
if (!tempFile.delete()) {
logger
.warn("The temporary file: '"
+ targetFile.getAbsolutePath()
+ "' cannot be deleted ! Make sure that no other application use it.");
}
}
} else {
throw new InvalidOperationException(
"Can't close a package not previously open with the open() method !");
}
}
}
/**
* Create a unique identifier to be use as a temp file name.
*
* @return A unique identifier use to be use as a temp file name.
*/
private synchronized String generateTempFileName(File directory) {
File tmpFilename;
do {
tmpFilename = new File(directory.getAbsoluteFile() + File.separator
+ "OpenXML4J" + System.nanoTime());
} while (tmpFilename.exists());
return FileHelper.getFilename(tmpFilename.getAbsoluteFile());
}
/**
* Close the package without saving the document. Discard all the changes
* made to this package.
*/
@Override
protected void revertImpl() {
try {
if (this.zipArchive != null)
this.zipArchive.close();
} catch (IOException e) {
// Do nothing, user dont have to know
}
}
/**
* Implement the getPart() method to retrieve a part from its URI in the
* current package
*
*
* @see #getPart(URI)
*/
@Override
protected PackagePart getPartImpl(PackagePartName partName) {
if (partList.containsKey(partName)) {
return partList.get(partName);
}
return null;
}
/**
* Save this package into the specified stream
*
*
* @param outputStream
* The stream use to save this package.
*
* @see #save(OutputStream)
* @see #saveInZip(ZipOutputStream)
*/
@Override
public void saveImpl(OutputStream outputStream) {
// Check that the document was open in write mode
throwExceptionIfReadOnly();
ZipOutputStream zos = null;
try {
if (!(outputStream instanceof ZipOutputStream))
zos = new ZipOutputStream(outputStream);
else
zos = (ZipOutputStream) outputStream;
// If the core properties part does not exist in the part list,
// we save it as well
if (this.getPartsByRelationshipType(
PackageRelationshipTypes.CORE_PROPERTIES).size() == 0) {
logger.debug("Save core properties part");
// We have to save the core properties part ...
new ZipPackagePropertiesMarshaller().marshall(
this.packageProperties, zos);
// ... and to add its relationship ...
this.relationships.addRelationship(this.packageProperties
.getPartName().getURI(), TargetMode.INTERNAL,
PackageRelationshipTypes.CORE_PROPERTIES, null);
// ... and the content if it has not been added yet.
if (!this.contentTypeManager
.isContentTypeRegister(ContentTypes.CORE_PROPERTIES_PART)) {
this.contentTypeManager.addContentType(
this.packageProperties.getPartName(),
ContentTypes.CORE_PROPERTIES_PART);
}
}
// Save package relationships part.
logger.debug("Save package relationships");
ZipPartMarshaller.marshallRelationshipPart(this.getRelationships(),
PackagingURIHelper.PACKAGE_RELATIONSHIPS_ROOT_PART_NAME,
zos);
// Save content type part.
logger.debug("Save content types part");
this.contentTypeManager.save(zos);
// Save parts.
for (PackagePart part : getParts()) {
// If the part is a relationship part, we don't save it, it's
// the source part that will do the job.
if (part.isRelationshipPart())
continue;
logger.debug("Save part '"
+ ZipHelper.getZipItemNameFromOPCName(part
.getPartName().getName()) + "'");
PartMarshaller marshaller = partMarshallers
.get(part.contentType);
if (marshaller != null) {
if (!marshaller.marshall(part, zos)) {
throw new OpenXML4JException(
"The part "
+ part.getPartName().getURI()
+ " fail to be saved in the stream with marshaller "
+ marshaller);
}
} else {
if (!defaultPartMarshaller.marshall(part, zos))
throw new OpenXML4JException(
"The part "
+ part.getPartName().getURI()
+ " fail to be saved in the stream with marshaller "
+ defaultPartMarshaller);
}
}
zos.close();
} catch (Exception e) {
logger
.error("Fail to save: an error occurs while saving the package : "
+ e.getMessage());
}
}
/**
* Get the zip archive
*
* @return The zip archive.
*/
public ZipEntrySource getZipArchive() {
return zipArchive;
}
}

View File

@ -0,0 +1,135 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.ZipEntry;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.InvalidOperationException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.internal.marshallers.ZipPartMarshaller;
/**
* Zip implementation of a PackagePart.
*
* @author Julien Chable
* @version 1.0
* @see PackagePart
*/
public class ZipPackagePart extends PackagePart {
/**
* The zip entry corresponding to this part.
*/
private ZipEntry zipEntry;
/**
* Constructor.
*
* @param container
* The container package.
* @param partName
* Part name.
* @param contentType
* Content type.
* @throws InvalidFormatException
* Throws if the content of this part invalid.
*/
public ZipPackagePart(Package container, PackagePartName partName,
String contentType) throws InvalidFormatException {
super(container, partName, contentType);
}
/**
* Constructor.
*
* @param container
* The container package.
* @param zipEntry
* The zip entry corresponding to this part.
* @param partName
* The part name.
* @param contentType
* Content type.
* @throws InvalidFormatException
* Throws if the content of this part is invalid.
*/
public ZipPackagePart(Package container, ZipEntry zipEntry,
PackagePartName partName, String contentType)
throws InvalidFormatException {
super(container, partName, contentType);
this.zipEntry = zipEntry;
}
/**
* Get the zip entry of this part.
*
* @return The zip entry in the zip structure coresponding to this part.
*/
public ZipEntry getZipArchive() {
return zipEntry;
}
/**
* Implementation of the getInputStream() which return the inputStream of
* this part zip entry.
*
* @return Input stream of this part zip entry.
*/
@Override
protected InputStream getInputStreamImpl() throws IOException {
// We use the getInputStream() method from java.util.zip.ZipFile
// class which return an InputStream to this part zip entry.
return ((ZipPackage) container).getZipArchive()
.getInputStream(zipEntry);
}
/**
* Implementation of the getOutputStream(). Return <b>null</b>. Normally
* will never be called since the MemoryPackage is use instead.
*
* @return <b>null</b>
*/
@Override
protected OutputStream getOutputStreamImpl() {
return null;
}
@Override
public boolean save(OutputStream os) throws OpenXML4JException {
return new ZipPartMarshaller().marshall(this, os);
}
@Override
public boolean load(InputStream ios) throws InvalidFormatException {
throw new InvalidOperationException("Method not implemented !");
}
@Override
public void close() {
throw new InvalidOperationException("Method not implemented !");
}
@Override
public void flush() {
throw new InvalidOperationException("Method not implemented !");
}
}

View File

@ -0,0 +1,224 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc.internal;
import java.io.UnsupportedEncodingException;
import java.util.Hashtable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
/**
* Represents a immutable MIME ContentType value (RFC 2616 <EFBFBD>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,<EFBFBD><EFBFBD>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);
}
}

View File

@ -0,0 +1,498 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc.internal;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Iterator;
import java.util.List;
import java.util.TreeMap;
import java.util.Map.Entry;
import java.util.zip.ZipOutputStream;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Namespace;
import org.dom4j.QName;
import org.dom4j.io.SAXReader;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.InvalidOperationException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException;
import org.apache.poi.openxml4j.opc.Package;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
/**
* Manage package content types ([Content_Types].xml part).
*
* @author Julien Chable
* @version 1.0
*/
public abstract class ContentTypeManager {
protected static Logger logger = Logger.getLogger("org.openxml4j");
/**
* Reference to the package using this content type manager.
*/
protected Package container;
/**
* Content type part name.
*/
public static final String CONTENT_TYPES_PART_NAME = "[Content_Types].xml";
/**
* Content type namespace
*/
public static final String TYPES_NAMESPACE_URI = "http://schemas.openxmlformats.org/package/2006/content-types";
/* Xml elements in content type part */
private static final String TYPES_TAG_NAME = "Types";
private static final String DEFAULT_TAG_NAME = "Default";
private static final String EXTENSION_ATTRIBUTE_NAME = "Extension";
private static final String CONTENT_TYPE_ATTRIBUTE_NAME = "ContentType";
private static final String OVERRIDE_TAG_NAME = "Override";
private static final String PART_NAME_ATTRIBUTE_NAME = "PartName";
/**
* Default content type tree. <Extension, ContentType>
*/
private TreeMap<String, String> defaultContentType;
/**
* Override content type tree.
*/
private TreeMap<PackagePartName, String> overrideContentType;
/**
* Constructor. Parses the content of the specified input stream.
*
* @param archive
* If different of <i>null</i> then the content types part is
* retrieve and parse.
* @throws InvalidFormatException
* If the content types part content is not valid.
*/
public ContentTypeManager(InputStream in, Package pkg)
throws InvalidFormatException {
this.container = pkg;
this.defaultContentType = new TreeMap<String, String>();
if (in != null) {
try {
parseContentTypesFile(in);
} catch (InvalidFormatException e) {
throw new InvalidFormatException(
"Can't read content types part !");
}
}
}
/**
* Build association extention-> content type (will be stored in
* [Content_Types].xml) for example ContentType="image/png" Extension="png"
*
* [M2.8]: When adding a new part to a package, the package implementer
* shall ensure that a content type for that part is specified in the
* Content Types stream; the package implementer shall perform the steps
* described in<EFBFBD><EFBFBD>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<EFBFBD><EFBFBD>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);
}

View File

@ -0,0 +1,91 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc.internal;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
/**
* Provide useful method to manage file.
*
* @author Julien Chable
* @version 0.1
*/
public final class FileHelper {
/**
* Get the directory part of the specified file path.
*
* @param f
* File to process.
* @return The directory path from the specified
*/
public static File getDirectory(File f) {
if (f != null) {
String path = f.getPath();
int len = path.length();
int num2 = len;
while (--num2 >= 0) {
char ch1 = path.charAt(num2);
if (ch1 == File.separatorChar) {
return new File(path.substring(0, num2));
}
}
}
return null;
}
/**
* Copy a file.
*
* @param in
* The source file.
* @param out
* The target location.
* @throws IOException
* If an I/O error occur.
*/
public static void copyFile(File in, File out) throws IOException {
FileChannel sourceChannel = new FileInputStream(in).getChannel();
FileChannel destinationChannel = new FileOutputStream(out).getChannel();
sourceChannel.transferTo(0, sourceChannel.size(), destinationChannel);
sourceChannel.close();
destinationChannel.close();
}
/**
* Get file name from the specified File object.
*/
public static String getFilename(File file) {
if (file != null) {
String path = file.getPath();
int len = path.length();
int num2 = len;
while (--num2 >= 0) {
char ch1 = path.charAt(num2);
if (ch1 == File.separatorChar)
return path.substring(num2 + 1, len);
}
}
return "";
}
}

View File

@ -0,0 +1,126 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc.internal;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.Package;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.internal.marshallers.ZipPartMarshaller;
/**
* Memory version of a package part. Use to
*
* @author Julien Chable
* @version 1.0
*/
public final class MemoryPackagePart extends PackagePart {
/**
* Storage for the part data.
*/
protected byte[] data;
/**
* Size of data.
*/
protected int length;
/**
* Constructor.
*
* @param pack
* The owner package.
* @param partName
* The part name.
* @param contentType
* The content type.
* @throws InvalidFormatException
* If the specified URI is not OPC compliant.
*/
public MemoryPackagePart(Package pack, PackagePartName partName,
String contentType) throws InvalidFormatException {
super(pack, partName, contentType);
}
/**
* Constructor.
*
* @param pack
* The owner package.
* @param partName
* The part name.
* @param contentType
* The content type.
* @param loadRelationships
* Specify if the relationships will be loaded.
* @throws InvalidFormatException
* If the specified URI is not OPC compliant.
*/
public MemoryPackagePart(Package pack, PackagePartName partName,
String contentType, boolean loadRelationships)
throws InvalidFormatException {
super(pack, partName, new ContentType(contentType), loadRelationships);
}
@Override
protected InputStream getInputStreamImpl() {
// If this part has been created from scratch and/or the data buffer is
// not
// initialize, so we do it now.
if (data == null) {
data = new byte[0];
}
return new ByteArrayInputStream(data);
}
@Override
protected OutputStream getOutputStreamImpl() {
return new MemoryPackagePartOutputStream(this);
}
public void clear() {
data = null;
length = 0;
}
@Override
public boolean save(OutputStream os) throws OpenXML4JException {
return new ZipPartMarshaller().marshall(this, os);
}
@Override
public boolean load(InputStream ios) throws InvalidFormatException {
throw new InvalidFormatException("Method not implemented");
}
@Override
public void close() {
// Do nothing
}
@Override
public void flush() {
// Do nothing
}
}

View File

@ -0,0 +1,96 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc.internal;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* Build an output stream for MemoryPackagePart.
*
* @author Julien Chable
* @version 1.0
*/
public final class MemoryPackagePartOutputStream extends OutputStream {
private MemoryPackagePart part;
private ByteArrayOutputStream buff;
public MemoryPackagePartOutputStream(MemoryPackagePart part) {
this.part = part;
buff = new ByteArrayOutputStream();
}
@Override
public void write(int b) throws IOException {
buff.write(b);
}
/**
* Close this stream and flush the content.
* @see #flush()
*/
@Override
public void close() throws IOException {
this.flush();
}
/**
* Flush this output stream. This method is called by the close() method.
* Warning : don't call this method for output consistency.
* @see #close()
*/
@Override
public void flush() throws IOException {
buff.flush();
if (part.data != null) {
byte[] newArray = new byte[part.data.length + buff.size()];
// copy the previous contents of part.data in newArray
System.arraycopy(part.data, 0, newArray, 0, part.data.length);
// append the newly added data
byte[] buffArr = buff.toByteArray();
System.arraycopy(buffArr, 0, newArray, part.data.length,
buffArr.length);
// save the result as new data
part.data = newArray;
} else {
// was empty, just fill it
part.data = buff.toByteArray();
}
/*
* Clear this streams buffer, in case flush() is called a second time
* Fix bug 1921637 - provided by Rainer Schwarze
*/
buff.reset();
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
buff.write(b, off, len);
}
@Override
public void write(byte[] b) throws IOException {
buff.write(b);
}
}

View File

@ -0,0 +1,621 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc.internal;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.InvalidOperationException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.ContentTypes;
import org.apache.poi.openxml4j.opc.Package;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackageProperties;
import org.apache.poi.openxml4j.util.Nullable;
/**
* Represents the core properties part of a package.
*
* @author Julien Chable
* @version 1.0
*/
public class PackagePropertiesPart extends PackagePart implements
PackageProperties {
public final static String NAMESPACE_DC_URI = "http://purl.org/dc/elements/1.1/";
public final static String NAMESPACE_CP_URI = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties";
public final static String NAMESPACE_DCTERMS_URI = "http://purl.org/dc/terms/";
public final static String NAMESPACE_XSI_URI = "http://www.w3.org/2001/XMLSchema-instance";
/**
* Constructor.
*
* @param pack
* Container package.
* @param partName
* Name of this part.
* @throws InvalidFormatException
* Throws if the content is invalid.
*/
public PackagePropertiesPart(Package pack, PackagePartName partName)
throws InvalidFormatException {
super(pack, partName, ContentTypes.CORE_PROPERTIES_PART);
}
/**
* A categorization of the content of this package.
*
* [Example: Example values for this property might include: Resume, Letter,
* Financial Forecast, Proposal, Technical Presentation, and so on. This
* value might be used by an application's user interface to facilitate
* navigation of a large set of documents. end example]
*/
protected Nullable<String> category = new Nullable<String>();
/**
* The status of the content.
*
* [Example: Values might include "Draft", "Reviewed", and "Final". end
* example]
*/
protected Nullable<String> contentStatus = new Nullable<String>();
/**
* The type of content represented, generally defined by a specific use and
* intended audience.
*
* [Example: Values might include "Whitepaper", "Security Bulletin", and
* "Exam". end example] [Note: This property is distinct from MIME content
* types as defined in RFC 2616. end note]
*/
protected Nullable<String> contentType = new Nullable<String>();
/**
* Date of creation of the resource.
*/
protected Nullable<Date> created = new Nullable<Date>();
/**
* An entity primarily responsible for making the content of the resource.
*/
protected Nullable<String> creator = new Nullable<String>();
/**
* An explanation of the content of the resource.
*
* [Example: Values might include an abstract, table of contents, reference
* to a graphical representation of content, and a free-text account of the
* content. end example]
*/
protected Nullable<String> description = new Nullable<String>();
/**
* An unambiguous reference to the resource within a given context.
*/
protected Nullable<String> identifier = new Nullable<String>();
/**
* A delimited set of keywords to support searching and indexing. This is
* typically a list of terms that are not available elsewhere in the
* properties.
*/
protected Nullable<String> keywords = new Nullable<String>();
/**
* The language of the intellectual content of the resource.
*
* [Note: IETF RFC 3066 provides guidance on encoding to represent
* languages. end note]
*/
protected Nullable<String> language = new Nullable<String>();
/**
* The user who performed the last modification. The identification is
* environment-specific.
*
* [Example: A name, email address, or employee ID. end example] It is
* recommended that this value be as concise as possible.
*/
protected Nullable<String> lastModifiedBy = new Nullable<String>();
/**
* The date and time of the last printing.
*/
protected Nullable<Date> lastPrinted = new Nullable<Date>();
/**
* Date on which the resource was changed.
*/
protected Nullable<Date> modified = new Nullable<Date>();
/**
* The revision number.
*
* [Example: This value might indicate the number of saves or revisions,
* provided the application updates it after each revision. end example]
*/
protected Nullable<String> revision = new Nullable<String>();
/**
* The topic of the content of the resource.
*/
protected Nullable<String> subject = new Nullable<String>();
/**
* The name given to the resource.
*/
protected Nullable<String> title = new Nullable<String>();
/**
* The version number. This value is set by the user or by the application.
*/
protected Nullable<String> version = new Nullable<String>();
/*
* Getters and setters
*/
/**
* Get the category property.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#getCategoryProperty()
*/
public Nullable<String> getCategoryProperty() {
return category;
}
/**
* Get content status.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#getContentStatusProperty()
*/
public Nullable<String> getContentStatusProperty() {
return contentStatus;
}
/**
* Get content type.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#getContentTypeProperty()
*/
public Nullable<String> getContentTypeProperty() {
return contentType;
}
/**
* Get created date.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#getCreatedProperty()
*/
public Nullable<Date> getCreatedProperty() {
return created;
}
/**
* Get created date formated into a String.
*
* @return A string representation of the created date.
*/
public String getCreatedPropertyString() {
return getDateValue(created);
}
/**
* Get creator.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#getCreatorProperty()
*/
public Nullable<String> getCreatorProperty() {
return creator;
}
/**
* Get description.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#getDescriptionProperty()
*/
public Nullable<String> getDescriptionProperty() {
return description;
}
/**
* Get identifier.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#getIdentifierProperty()
*/
public Nullable<String> getIdentifierProperty() {
return identifier;
}
/**
* Get keywords.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#getKeywordsProperty()
*/
public Nullable<String> getKeywordsProperty() {
return keywords;
}
/**
* Get the language.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#getLanguageProperty()
*/
public Nullable<String> getLanguageProperty() {
return language;
}
/**
* Get the author of last modifications.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#getLastModifiedByProperty()
*/
public Nullable<String> getLastModifiedByProperty() {
return lastModifiedBy;
}
/**
* Get last printed date.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#getLastPrintedProperty()
*/
public Nullable<Date> getLastPrintedProperty() {
return lastPrinted;
}
/**
* Get last printed date formated into a String.
*
* @return A string representation of the last printed date.
*/
public String getLastPrintedPropertyString() {
return getDateValue(created);
}
/**
* Get modified date.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#getModifiedProperty()
*/
public Nullable<Date> getModifiedProperty() {
return modified;
}
/**
* Get modified date formated into a String.
*
* @return A string representation of the modified date.
*/
public String getModifiedPropertyString() {
if (!modified.hasValue())
return getDateValue(new Nullable<Date>(new Date()));
else
return getDateValue(modified);
}
/**
* Get revision.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#getRevisionProperty()
*/
public Nullable<String> getRevisionProperty() {
return revision;
}
/**
* Get subject.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#getSubjectProperty()
*/
public Nullable<String> getSubjectProperty() {
return subject;
}
/**
* Get title.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#getTitleProperty()
*/
public Nullable<String> getTitleProperty() {
return title;
}
/**
* Get version.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#getVersionProperty()
*/
public Nullable<String> getVersionProperty() {
return version;
}
/**
* Set the category.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#setCategoryProperty(java.lang.String)
*/
public void setCategoryProperty(String category) {
this.category = setStringValue(category);
}
/**
* Set the content status.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#setContentStatusProperty(java.lang.String)
*/
public void setContentStatusProperty(String contentStatus) {
this.contentStatus = setStringValue(contentStatus);
}
/**
* Set the content type.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#setContentTypeProperty(java.lang.String)
*/
public void setContentTypeProperty(String contentType) {
this.contentType = setStringValue(contentType);
}
/**
* Set the created date.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#setCreatedProperty(org.apache.poi.openxml4j.util.Nullable)
*/
public void setCreatedProperty(String created) {
try {
this.created = setDateValue(created);
} catch (InvalidFormatException e) {
new IllegalArgumentException("created : "
+ e.getLocalizedMessage());
}
}
/**
* Set the created date.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#setCreatedProperty(org.apache.poi.openxml4j.util.Nullable)
*/
public void setCreatedProperty(Nullable<Date> created) {
if (created.hasValue())
this.created = created;
}
/**
* Set the creator.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#setCreatorProperty(java.lang.String)
*/
public void setCreatorProperty(String creator) {
this.creator = setStringValue(creator);
}
/**
* Set the description.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#setDescriptionProperty(java.lang.String)
*/
public void setDescriptionProperty(String description) {
this.description = setStringValue(description);
}
/**
* Set identifier.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#setIdentifierProperty(java.lang.String)
*/
public void setIdentifierProperty(String identifier) {
this.identifier = setStringValue(identifier);
}
/**
* Set keywords.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#setKeywordsProperty(java.lang.String)
*/
public void setKeywordsProperty(String keywords) {
this.keywords = setStringValue(keywords);
}
/**
* Set language.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#setLanguageProperty(java.lang.String)
*/
public void setLanguageProperty(String language) {
this.language = setStringValue(language);
}
/**
* Set last modifications author.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#setLastModifiedByProperty(java.lang.String)
*/
public void setLastModifiedByProperty(String lastModifiedBy) {
this.lastModifiedBy = setStringValue(lastModifiedBy);
}
/**
* Set last printed date.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#setLastPrintedProperty(org.apache.poi.openxml4j.util.Nullable)
*/
public void setLastPrintedProperty(String lastPrinted) {
try {
this.lastPrinted = setDateValue(lastPrinted);
} catch (InvalidFormatException e) {
new IllegalArgumentException("lastPrinted : "
+ e.getLocalizedMessage());
}
}
/**
* Set last printed date.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#setLastPrintedProperty(org.apache.poi.openxml4j.util.Nullable)
*/
public void setLastPrintedProperty(Nullable<Date> lastPrinted) {
if (lastPrinted.hasValue())
this.lastPrinted = lastPrinted;
}
/**
* Set last modification date.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#setModifiedProperty(org.apache.poi.openxml4j.util.Nullable)
*/
public void setModifiedProperty(String modified) {
try {
this.modified = setDateValue(modified);
} catch (InvalidFormatException e) {
new IllegalArgumentException("modified : "
+ e.getLocalizedMessage());
}
}
/**
* Set last modification date.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#setModifiedProperty(org.apache.poi.openxml4j.util.Nullable)
*/
public void setModifiedProperty(Nullable<Date> modified) {
if (modified.hasValue())
this.modified = modified;
}
/**
* Set revision.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#setRevisionProperty(java.lang.String)
*/
public void setRevisionProperty(String revision) {
this.revision = setStringValue(revision);
}
/**
* Set subject.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#setSubjectProperty(java.lang.String)
*/
public void setSubjectProperty(String subject) {
this.subject = setStringValue(subject);
}
/**
* Set title.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#setTitleProperty(java.lang.String)
*/
public void setTitleProperty(String title) {
this.title = setStringValue(title);
}
/**
* Set version.
*
* @see org.apache.poi.openxml4j.opc.PackageProperties#setVersionProperty(java.lang.String)
*/
public void setVersionProperty(String version) {
this.version = setStringValue(version);
}
/**
* Convert a strig value into a Nullable<String>
*/
private Nullable<String> setStringValue(String s) {
if (s == null || s.equals(""))
return new Nullable<String>();
else
return new Nullable<String>(s);
}
/**
* Convert a string value represented a date into a Nullable<Date>.
*
* @throws InvalidFormatException
* Throws if the date format isnot valid.
*/
private Nullable<Date> setDateValue(String s) throws InvalidFormatException {
if (s == null || s.equals(""))
return new Nullable<Date>();
else {
SimpleDateFormat df = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss'Z'");
Date d = df.parse(s, new ParsePosition(0));
if (d == null)
throw new InvalidFormatException("Date not well formated");
return new Nullable<Date>(d);
}
}
/**
* Convert a Nullable<Date> into a String.
*
* @param d
* The Date to convert.
* @return The formated date or null.
* @see java.util.SimpleDateFormat
*/
private String getDateValue(Nullable<Date> d) {
if (d == null || d.equals(""))
return "";
else {
SimpleDateFormat df = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss'Z'");
return df.format(d.getValue());
}
}
@Override
protected InputStream getInputStreamImpl() {
throw new InvalidOperationException("Operation not authorized");
}
@Override
protected OutputStream getOutputStreamImpl() {
throw new InvalidOperationException(
"Can't use output stream to set properties !");
}
@Override
public boolean save(OutputStream zos) throws OpenXML4JException {
throw new InvalidOperationException("Operation not authorized");
}
@Override
public boolean load(InputStream ios) throws InvalidFormatException {
throw new InvalidOperationException("Operation not authorized");
}
@Override
public void close() {
// Do nothing
}
@Override
public void flush() {
// Do nothing
}
}

View File

@ -0,0 +1,49 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc.internal;
import java.io.OutputStream;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.PackagePart;
/**
* Object implemented this interface are considered as part marshaller. A part
* marshaller is responsible to marshall a part in order to be save in a
* package.
*
* @author Julien Chable
* @version 0.1
*/
public interface PartMarshaller {
/**
* Save the content of the package in the stream
*
* @param part
* Part to marshall.
* @param out
* The output stream into which the part will be marshall.
* @return <b>false</b> if any marshall error occurs, else <b>true</b>
* @throws OpenXML4JException
* Throws only if any other exceptions are thrown by inner
* methods.
*/
public boolean marshall(PackagePart part, OutputStream out)
throws OpenXML4JException;
}

View File

@ -0,0 +1,50 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc.internal;
import java.io.IOException;
import java.io.InputStream;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.internal.unmarshallers.UnmarshallContext;
/**
* Object implemented this interface are considered as part unmarshaller. A part
* unmarshaller is responsible to unmarshall a part in order to load it from a
* package.
*
* @author Julien Chable
* @version 0.1
*/
public interface PartUnmarshaller {
/**
* Save the content of the package in the stream
*
* @param in
* The input stream from which the part will be unmarshall.
* @return The part freshly unmarshall from the input stream.
* @throws OpenXML4JException
* Throws only if any other exceptions are thrown by inner
* methods.
*/
public PackagePart unmarshall(UnmarshallContext context, InputStream in)
throws InvalidFormatException, IOException;
}

View File

@ -0,0 +1,90 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc.internal;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.dom4j.Document;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.Package;
import org.apache.poi.openxml4j.opc.StreamHelper;
/**
* Zip implementation of the ContentTypeManager.
*
* @author Julien Chable
* @version 1.0
* @see ContentTypeManager
*/
public class ZipContentTypeManager extends ContentTypeManager {
/**
* Delegate constructor to the super constructor.
*
* @param in
* The input stream to parse to fill internal content type
* collections.
* @throws InvalidFormatException
* If the content types part content is not valid.
*/
public ZipContentTypeManager(InputStream in, Package pkg)
throws InvalidFormatException {
super(in, pkg);
}
@Override
public boolean saveImpl(Document content, OutputStream out) {
ZipOutputStream zos = null;
if (out instanceof ZipOutputStream)
zos = (ZipOutputStream) out;
else
zos = new ZipOutputStream(out);
ZipEntry partEntry = new ZipEntry(CONTENT_TYPES_PART_NAME);
try {
// Referenced in ZIP
zos.putNextEntry(partEntry);
// Saving data in the ZIP file
ByteArrayOutputStream outTemp = new ByteArrayOutputStream();
StreamHelper.saveXmlInStream(content, out);
InputStream ins = new ByteArrayInputStream(outTemp.toByteArray());
byte[] buff = new byte[ZipHelper.READ_WRITE_FILE_BUFFER_SIZE];
while (ins.available() > 0) {
int resultRead = ins.read(buff);
if (resultRead == -1) {
// end of file reached
break;
} else {
zos.write(buff, 0, resultRead);
}
}
zos.closeEntry();
} catch (IOException ioe) {
logger.error("Cannot write: " + CONTENT_TYPES_PART_NAME
+ " in Zip !", ioe);
return false;
}
return true;
}
}

View File

@ -0,0 +1,163 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc.internal;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;
import org.apache.poi.openxml4j.opc.ZipPackage;
public final class ZipHelper {
/**
* Forward slash use to convert part name between OPC and zip item naming
* conventions.
*/
private final static String FORWARD_SLASH = "/";
/**
* Buffer to read data from file. Use big buffer to improve performaces. the
* InputStream class is reading only 8192 bytes per read call (default value
* set by sun)
*/
public static final int READ_WRITE_FILE_BUFFER_SIZE = 8192;
/**
* Prevent this class to be instancied.
*/
private ZipHelper() {
// Do nothing
}
/**
* Retrieve the zip entry of the core properties part.
*
* @throws OpenXML4JException
* Throws if internal error occurs.
*/
public static ZipEntry getCorePropertiesZipEntry(ZipPackage pkg)
throws OpenXML4JException {
PackageRelationship corePropsRel = pkg.getRelationshipsByType(
PackageRelationshipTypes.CORE_PROPERTIES).getRelationship(0);
if (corePropsRel == null)
return null;
return new ZipEntry(corePropsRel.getTargetURI().getPath());
}
/**
* Retrieve the Zip entry of the content types part.
*/
public static ZipEntry getContentTypeZipEntry(ZipPackage pkg) {
Enumeration entries = pkg.getZipArchive().getEntries();
// Enumerate through the Zip entries until we find the one named
// '[Content_Types].xml'.
while (entries.hasMoreElements()) {
ZipEntry entry = (ZipEntry) entries.nextElement();
if (entry.getName().equals(
ContentTypeManager.CONTENT_TYPES_PART_NAME))
return entry;
}
return null;
}
/**
* Convert a zip name into an OPC name by adding a leading forward slash to
* the specified item name.
*
* @param zipItemName
* Zip item name to convert.
* @return An OPC compliant name.
*/
public static String getOPCNameFromZipItemName(String zipItemName) {
if (zipItemName == null)
throw new IllegalArgumentException("zipItemName");
if (zipItemName.startsWith(FORWARD_SLASH))
return zipItemName;
else
return FORWARD_SLASH + zipItemName;
}
/**
* Convert an OPC item name into a zip item name by removing any leading
* forward slash if it exist.
*
* @param opcItemName
* The OPC item name to convert.
* @return A zip item name without any leading slashes.
*/
public static String getZipItemNameFromOPCName(String opcItemName) {
if (opcItemName == null)
throw new IllegalArgumentException("opcItemName");
String retVal = new String(opcItemName);
while (retVal.startsWith(FORWARD_SLASH))
retVal = retVal.substring(1);
return retVal;
}
/**
* Convert an OPC item name into a zip URI by removing any leading forward
* slash if it exist.
*
* @param opcItemName
* The OPC item name to convert.
* @return A zip URI without any leading slashes.
*/
public static URI getZipURIFromOPCName(String opcItemName) {
if (opcItemName == null)
throw new IllegalArgumentException("opcItemName");
String retVal = new String(opcItemName);
while (retVal.startsWith(FORWARD_SLASH))
retVal = retVal.substring(1);
try {
return new URI(retVal);
} catch (URISyntaxException e) {
return null;
}
}
/**
* Retrieve and open a zip file with the specified path.
*
* @param path
* The file path.
* @return The zip archive freshly open.
*/
public static ZipFile openZipFile(String path) {
File f = new File(path);
try {
if (!f.exists()) {
return null;
}
return new ZipFile(f);
} catch (IOException ioe) {
return null;
}
}
}

View File

@ -0,0 +1,45 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc.internal.marshallers;
import java.io.OutputStream;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.internal.PartMarshaller;
/**
* Default marshaller that specified that the part is responsible to marshall its content.
*
* @author Julien Chable
* @version 1.0
* @see PartMarshaller
*/
public class DefaultMarshaller implements PartMarshaller {
/**
* Save part in the output stream by using the save() method of the part.
*
* @throws OpenXML4JException
* If any error occur.
*/
public boolean marshall(PackagePart part, OutputStream out)
throws OpenXML4JException {
return part.save(out);
}
}

View File

@ -0,0 +1,434 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc.internal.marshallers;
import java.io.OutputStream;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Namespace;
import org.dom4j.QName;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart;
import org.apache.poi.openxml4j.opc.internal.PartMarshaller;
/**
* Package properties marshaller.
*
* @author CDubet, Julien Chable
* @version 1.0
*/
public class PackagePropertiesMarshaller implements PartMarshaller {
private final static Namespace namespaceDC = new Namespace("dc",
PackagePropertiesPart.NAMESPACE_DC_URI);
private final static Namespace namespaceCoreProperties = new Namespace("",
PackagePropertiesPart.NAMESPACE_CP_URI);
private final static Namespace namespaceDcTerms = new Namespace("dcterms",
PackagePropertiesPart.NAMESPACE_DCTERMS_URI);
private final static Namespace namespaceXSI = new Namespace("xsi",
PackagePropertiesPart.NAMESPACE_XSI_URI);
protected static final String KEYWORD_CATEGORY = "category";
protected static final String KEYWORD_CONTENT_STATUS = "contentStatus";
protected static final String KEYWORD_CONTENT_TYPE = "contentType";
protected static final String KEYWORD_CREATED = "created";
protected static final String KEYWORD_CREATOR = "creator";
protected static final String KEYWORD_DESCRIPTION = "description";
protected static final String KEYWORD_IDENTIFIER = "identifier";
protected static final String KEYWORD_KEYWORDS = "keywords";
protected static final String KEYWORD_LANGUAGE = "language";
protected static final String KEYWORD_LAST_MODIFIED_BY = "lastModifiedBy";
protected static final String KEYWORD_LAST_PRINTED = "lastPrinted";
protected static final String KEYWORD_MODIFIED = "modified";
protected static final String KEYWORD_REVISION = "revision";
protected static final String KEYWORD_SUBJECT = "subject";
protected static final String KEYWORD_TITLE = "title";
protected static final String KEYWORD_VERSION = "version";
PackagePropertiesPart propsPart;
// The document
Document xmlDoc = null;
/**
* Marshall package core properties to an XML document. Always return
* <code>true</code>.
*/
public boolean marshall(PackagePart part, OutputStream out)
throws OpenXML4JException {
if (!(part instanceof PackagePropertiesPart))
throw new IllegalArgumentException(
"'part' must be a PackagePropertiesPart instance.");
propsPart = (PackagePropertiesPart) part;
// Configure the document
xmlDoc = DocumentHelper.createDocument();
Element rootElem = xmlDoc.addElement(new QName("coreProperties",
namespaceCoreProperties));
rootElem.addNamespace("cp", PackagePropertiesPart.NAMESPACE_CP_URI);
rootElem.addNamespace("dc", PackagePropertiesPart.NAMESPACE_DC_URI);
rootElem.addNamespace("dcterms",
PackagePropertiesPart.NAMESPACE_DCTERMS_URI);
rootElem.addNamespace("xsi", PackagePropertiesPart.NAMESPACE_XSI_URI);
addCategory();
addContentStatus();
addContentType();
addCreated();
addCreator();
addDescription();
addIdentifier();
addKeywords();
addLanguage();
addLastModifiedBy();
addLastPrinted();
addModified();
addRevision();
addSubject();
addTitle();
addVersion();
return true;
}
/**
* Add category property element if needed.
*/
private void addCategory() {
if (!propsPart.getCategoryProperty().hasValue())
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_CATEGORY, namespaceCoreProperties));
if (elem == null) {
// Missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_CATEGORY, namespaceCoreProperties));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getCategoryProperty().getValue());
}
/**
* Add content status property element if needed.
*/
private void addContentStatus() {
if (!propsPart.getContentStatusProperty().hasValue())
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_CONTENT_STATUS, namespaceCoreProperties));
if (elem == null) {
// Missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_CONTENT_STATUS, namespaceCoreProperties));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getContentStatusProperty().getValue());
}
/**
* Add content type property element if needed.
*/
private void addContentType() {
if (!propsPart.getContentTypeProperty().hasValue())
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_CONTENT_TYPE, namespaceCoreProperties));
if (elem == null) {
// Missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_CONTENT_TYPE, namespaceCoreProperties));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getContentTypeProperty().getValue());
}
/**
* Add created property element if needed.
*/
private void addCreated() {
if (!propsPart.getCreatedProperty().hasValue())
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_CREATED, namespaceDcTerms));
if (elem == null) {
// missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_CREATED, namespaceDcTerms));
} else {
elem.clearContent();// clear the old value
}
elem.addAttribute(new QName("type", namespaceXSI), "dcterms:W3CDTF");
elem.addText(propsPart.getCreatedPropertyString());
}
/**
* Add creator property element if needed.
*/
private void addCreator() {
if (!propsPart.getCreatorProperty().hasValue())
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_CREATOR, namespaceDC));
if (elem == null) {
// missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_CREATOR, namespaceDC));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getCreatorProperty().getValue());
}
/**
* Add description property element if needed.
*/
private void addDescription() {
if (!propsPart.getDescriptionProperty().hasValue())
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_DESCRIPTION, namespaceDC));
if (elem == null) {
// missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_DESCRIPTION, namespaceDC));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getDescriptionProperty().getValue());
}
/**
* Add identifier property element if needed.
*/
private void addIdentifier() {
if (!propsPart.getIdentifierProperty().hasValue())
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_IDENTIFIER, namespaceDC));
if (elem == null) {
// missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_IDENTIFIER, namespaceDC));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getIdentifierProperty().getValue());
}
/**
* Add keywords property element if needed.
*/
private void addKeywords() {
if (!propsPart.getKeywordsProperty().hasValue())
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_KEYWORDS, namespaceCoreProperties));
if (elem == null) {
// missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_KEYWORDS, namespaceCoreProperties));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getKeywordsProperty().getValue());
}
/**
* Add language property element if needed.
*/
private void addLanguage() {
if (!propsPart.getLanguageProperty().hasValue())
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_LANGUAGE, namespaceDC));
if (elem == null) {
// missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_LANGUAGE, namespaceDC));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getLanguageProperty().getValue());
}
/**
* Add 'last modified by' property if needed.
*/
private void addLastModifiedBy() {
if (!propsPart.getLastModifiedByProperty().hasValue())
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_LAST_MODIFIED_BY, namespaceCoreProperties));
if (elem == null) {
// missing, we add it
elem = xmlDoc.getRootElement()
.addElement(
new QName(KEYWORD_LAST_MODIFIED_BY,
namespaceCoreProperties));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getLastModifiedByProperty().getValue());
}
/**
* Add 'last printed' property if needed.
*
*/
private void addLastPrinted() {
if (!propsPart.getLastPrintedProperty().hasValue())
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_LAST_PRINTED, namespaceCoreProperties));
if (elem == null) {
// missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_LAST_PRINTED, namespaceCoreProperties));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getLastPrintedPropertyString());
}
/**
* Add modified property element if needed.
*/
private void addModified() {
if (!propsPart.getModifiedProperty().hasValue())
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_MODIFIED, namespaceDcTerms));
if (elem == null) {
// missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_MODIFIED, namespaceDcTerms));
} else {
elem.clearContent();// clear the old value
}
elem.addAttribute(new QName("type", namespaceXSI), "dcterms:W3CDTF");
elem.addText(propsPart.getModifiedPropertyString());
}
/**
* Add revision property if needed.
*/
private void addRevision() {
if (!propsPart.getRevisionProperty().hasValue())
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_REVISION, namespaceCoreProperties));
if (elem == null) {
// missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_REVISION, namespaceCoreProperties));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getRevisionProperty().getValue());
}
/**
* Add subject property if needed.
*/
private void addSubject() {
if (!propsPart.getSubjectProperty().hasValue())
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_SUBJECT, namespaceDC));
if (elem == null) {
// missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_SUBJECT, namespaceDC));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getSubjectProperty().getValue());
}
/**
* Add title property if needed.
*/
private void addTitle() {
if (!propsPart.getTitleProperty().hasValue())
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_TITLE, namespaceDC));
if (elem == null) {
// missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_TITLE, namespaceDC));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getTitleProperty().getValue());
}
private void addVersion() {
if (!propsPart.getVersionProperty().hasValue())
return;
Element elem = xmlDoc.getRootElement().element(
new QName(KEYWORD_VERSION, namespaceCoreProperties));
if (elem == null) {
// missing, we add it
elem = xmlDoc.getRootElement().addElement(
new QName(KEYWORD_VERSION, namespaceCoreProperties));
} else {
elem.clearContent();// clear the old value
}
elem.addText(propsPart.getVersionProperty().getValue());
}
}

View File

@ -0,0 +1,64 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc.internal.marshallers;
import java.io.IOException;
import java.io.OutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.StreamHelper;
import org.apache.poi.openxml4j.opc.internal.ZipHelper;
/**
* Package core properties marshaller specialized for zipped package.
*
* @author Julien Chable
* @version 1.0
*/
public class ZipPackagePropertiesMarshaller extends PackagePropertiesMarshaller {
@Override
public boolean marshall(PackagePart part, OutputStream out)
throws OpenXML4JException {
if (!(out instanceof ZipOutputStream)) {
throw new IllegalArgumentException("ZipOutputStream expected!");
}
ZipOutputStream zos = (ZipOutputStream) out;
// Saving the part in the zip file
ZipEntry ctEntry = new ZipEntry(ZipHelper
.getZipItemNameFromOPCName(part.getPartName().getURI()
.toString()));
try {
// Save in ZIP
zos.putNextEntry(ctEntry); // Add entry in ZIP
super.marshall(part, out); // Marshall the properties inside a XML
// Document
if (!StreamHelper.saveXmlInStream(xmlDoc, out)) {
return false;
}
zos.closeEntry();
} catch (IOException e) {
throw new OpenXML4JException(e.getLocalizedMessage());
}
return true;
}
}

View File

@ -0,0 +1,193 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc.internal.marshallers;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Namespace;
import org.dom4j.QName;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.PackageNamespaces;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
import org.apache.poi.openxml4j.opc.StreamHelper;
import org.apache.poi.openxml4j.opc.TargetMode;
import org.apache.poi.openxml4j.opc.internal.PartMarshaller;
import org.apache.poi.openxml4j.opc.internal.ZipHelper;
/**
* Zip part marshaller. This marshaller is use to save any part in a zip stream.
*
* @author Julien Chable
* @version 0.1
*/
public class ZipPartMarshaller implements PartMarshaller {
private static Logger logger = Logger.getLogger("org.openxml4j");
/**
* Save the specified part.
*
* @throws OpenXML4JException
* Throws if an internal exception is thrown.
*/
public boolean marshall(PackagePart part, OutputStream os)
throws OpenXML4JException {
if (!(os instanceof ZipOutputStream)) {
logger.error("Unexpected class " + os.getClass().getName());
throw new OpenXML4JException("ZipOutputStream expected !");
// Normally should happen only in developpement phase, so just throw
// exception
}
ZipOutputStream zos = (ZipOutputStream) os;
ZipEntry partEntry = new ZipEntry(ZipHelper
.getZipItemNameFromOPCName(part.getPartName().getURI()
.getPath()));
try {
// Create next zip entry
zos.putNextEntry(partEntry);
// Saving data in the ZIP file
InputStream ins = part.getInputStream();
byte[] buff = new byte[ZipHelper.READ_WRITE_FILE_BUFFER_SIZE];
while (ins.available() > 0) {
int resultRead = ins.read(buff);
if (resultRead == -1) {
// End of file reached
break;
} else {
zos.write(buff, 0, resultRead);
}
}
zos.closeEntry();
} catch (IOException ioe) {
logger.error("Cannot write: " + part.getPartName() + ": in ZIP",
ioe);
return false;
}
// Saving relationship part
if (part.hasRelationships()) {
PackagePartName relationshipPartName = PackagingURIHelper
.getRelationshipPartName(part.getPartName());
marshallRelationshipPart(part.getRelationships(),
relationshipPartName, zos);
}
return true;
}
/**
* Save relationships into the part.
*
* @param rels
* The relationships collection to marshall.
* @param relPartURI
* Part name of the relationship part to marshall.
* @param zos
* Zip output stream in which to save the XML content of the
* relationships serialization.
*/
public static boolean marshallRelationshipPart(
PackageRelationshipCollection rels, PackagePartName relPartName,
ZipOutputStream zos) {
// Building xml
Document xmlOutDoc = DocumentHelper.createDocument();
// make something like <Relationships
// xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
Namespace dfNs = Namespace.get("", PackageNamespaces.RELATIONSHIPS);
Element root = xmlOutDoc.addElement(new QName(
PackageRelationship.RELATIONSHIPS_TAG_NAME, dfNs));
// <Relationship
// TargetMode="External"
// Id="rIdx"
// Target="http://www.custom.com/images/pic1.jpg"
// Type="http://www.custom.com/external-resource"/>
URI sourcePartURI = PackagingURIHelper
.getSourcePartUriFromRelationshipPartUri(relPartName.getURI());
for (PackageRelationship rel : rels) {
// L'<EFBFBD>l<EFBFBD>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<EFBFBD>ation de l'entr<EFBFBD>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
}
}

View File

@ -0,0 +1,79 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc.internal.signature;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.internal.ContentType;
/**
* Digital certificate part.
*
* @author Julien Chable
* @version 0.1
*/
public final class DigitalCertificatePart extends PackagePart {
public DigitalCertificatePart() throws InvalidFormatException{
super(null, null, new ContentType(""));
// Review constructor
}
@Override
public void close() {
// TODO Auto-generated method stub
}
@Override
public void flush() {
// TODO Auto-generated method stub
}
@Override
protected InputStream getInputStreamImpl() throws IOException {
// TODO Auto-generated method stub
return null;
}
@Override
protected OutputStream getOutputStreamImpl() {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean load(InputStream ios) throws InvalidFormatException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean save(OutputStream zos) throws OpenXML4JException {
// TODO Auto-generated method stub
return false;
}
// TODO Introduire le concept de partie typ<EFBFBD>e d<EFBFBD>s cette partie
}

View File

@ -0,0 +1,28 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc.internal.signature;
/**
* Represents a digital signature origin part.
*
* @author Julien Chable
* @version 0.1
*/
public class DigitalSignatureOriginPart {
}

View File

@ -0,0 +1,390 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc.internal.unmarshallers;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import java.util.zip.ZipEntry;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Namespace;
import org.dom4j.QName;
import org.dom4j.io.SAXReader;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.PackageNamespaces;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageProperties;
import org.apache.poi.openxml4j.opc.ZipPackage;
import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart;
import org.apache.poi.openxml4j.opc.internal.PartUnmarshaller;
import org.apache.poi.openxml4j.opc.internal.ZipHelper;
/**
* Package properties unmarshaller.
*
* @author Julien Chable
* @version 1.0
*/
public class PackagePropertiesUnmarshaller implements PartUnmarshaller {
private final static Namespace namespaceDC = new Namespace("dc",
PackageProperties.NAMESPACE_DC);
private final static Namespace namespaceCP = new Namespace("cp",
PackageNamespaces.CORE_PROPERTIES);
private final static Namespace namespaceDcTerms = new Namespace("dcterms",
PackageProperties.NAMESPACE_DCTERMS);
private final static Namespace namespaceXML = new Namespace("xml",
"http://www.w3.org/XML/1998/namespace");
private final static Namespace namespaceXSI = new Namespace("xsi",
"http://www.w3.org/2001/XMLSchema-instance");
protected static final String KEYWORD_CATEGORY = "category";
protected static final String KEYWORD_CONTENT_STATUS = "contentStatus";
protected static final String KEYWORD_CONTENT_TYPE = "contentType";
protected static final String KEYWORD_CREATED = "created";
protected static final String KEYWORD_CREATOR = "creator";
protected static final String KEYWORD_DESCRIPTION = "description";
protected static final String KEYWORD_IDENTIFIER = "identifier";
protected static final String KEYWORD_KEYWORDS = "keywords";
protected static final String KEYWORD_LANGUAGE = "language";
protected static final String KEYWORD_LAST_MODIFIED_BY = "lastModifiedBy";
protected static final String KEYWORD_LAST_PRINTED = "lastPrinted";
protected static final String KEYWORD_MODIFIED = "modified";
protected static final String KEYWORD_REVISION = "revision";
protected static final String KEYWORD_SUBJECT = "subject";
protected static final String KEYWORD_TITLE = "title";
protected static final String KEYWORD_VERSION = "version";
// TODO Load element with XMLBeans or dynamic table
// TODO Check every element/namespace for compliance
public PackagePart unmarshall(UnmarshallContext context, InputStream in)
throws InvalidFormatException, IOException {
PackagePropertiesPart coreProps = new PackagePropertiesPart(context
.getPackage(), context.getPartName());
// If the input stream is null then we try to get it from the
// package.
if (in == null) {
if (context.getZipEntry() != null) {
in = ((ZipPackage) context.getPackage()).getZipArchive()
.getInputStream(context.getZipEntry());
} else if (context.getPackage() != null) {
// Try to retrieve the part inputstream from the URI
ZipEntry zipEntry;
try {
zipEntry = ZipHelper
.getCorePropertiesZipEntry((ZipPackage) context
.getPackage());
} catch (OpenXML4JException e) {
throw new IOException(
"Error while trying to get the part input stream.");
}
in = ((ZipPackage) context.getPackage()).getZipArchive()
.getInputStream(zipEntry);
} else
throw new IOException(
"Error while trying to get the part input stream.");
}
SAXReader xmlReader = new SAXReader();
Document xmlDoc;
try {
xmlDoc = xmlReader.read(in);
/* Check OPC compliance */
// Rule M4.2, M4.3, M4.4 and M4.5/
checkElementForOPCCompliance(xmlDoc.getRootElement());
/* End OPC compliance */
} catch (DocumentException e) {
throw new IOException(e.getMessage());
}
coreProps.setCategoryProperty(loadCategory(xmlDoc));
coreProps.setContentStatusProperty(loadContentStatus(xmlDoc));
coreProps.setContentTypeProperty(loadContentType(xmlDoc));
coreProps.setCreatedProperty(loadCreated(xmlDoc));
coreProps.setCreatorProperty(loadCreator(xmlDoc));
coreProps.setDescriptionProperty(loadDescription(xmlDoc));
coreProps.setIdentifierProperty(loadIdentifier(xmlDoc));
coreProps.setKeywordsProperty(loadKeywords(xmlDoc));
coreProps.setLanguageProperty(loadLanguage(xmlDoc));
coreProps.setLastModifiedByProperty(loadLastModifiedBy(xmlDoc));
coreProps.setLastPrintedProperty(loadLastPrinted(xmlDoc));
coreProps.setModifiedProperty(loadModified(xmlDoc));
coreProps.setRevisionProperty(loadRevision(xmlDoc));
coreProps.setSubjectProperty(loadSubject(xmlDoc));
coreProps.setTitleProperty(loadTitle(xmlDoc));
coreProps.setVersionProperty(loadVersion(xmlDoc));
return coreProps;
}
private String loadCategory(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element(
new QName(KEYWORD_CATEGORY, namespaceCP));
if (el != null)
return el.getStringValue();
else
return null;
}
private String loadContentStatus(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element(
new QName(KEYWORD_CONTENT_STATUS, namespaceCP));
if (el != null)
return el.getStringValue();
else
return null;
}
private String loadContentType(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element(
new QName(KEYWORD_CONTENT_TYPE, namespaceCP));
if (el != null)
return el.getStringValue();
else
return null;
}
private String loadCreated(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element(
new QName(KEYWORD_CREATED, namespaceDcTerms));
if (el != null)
return el.getStringValue();
else
return null;
}
private String loadCreator(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element(
new QName(KEYWORD_CREATOR, namespaceDC));
if (el != null)
return el.getStringValue();
else
return null;
}
private String loadDescription(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element(
new QName(KEYWORD_DESCRIPTION, namespaceDC));
if (el != null)
return el.getStringValue();
else
return null;
}
private String loadIdentifier(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element(
new QName(KEYWORD_IDENTIFIER, namespaceDC));
if (el != null)
return el.getStringValue();
else
return null;
}
private String loadKeywords(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element(
new QName(KEYWORD_KEYWORDS, namespaceCP));
if (el != null)
return el.getStringValue();
else
return null;
}
private String loadLanguage(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element(
new QName(KEYWORD_LANGUAGE, namespaceDC));
if (el != null)
return el.getStringValue();
else
return null;
}
private String loadLastModifiedBy(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element(
new QName(KEYWORD_LAST_MODIFIED_BY, namespaceCP));
if (el != null)
return el.getStringValue();
else
return null;
}
private String loadLastPrinted(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element(
new QName(KEYWORD_LAST_PRINTED, namespaceCP));
if (el != null)
return el.getStringValue();
else
return null;
}
private String loadModified(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element(
new QName(KEYWORD_MODIFIED, namespaceDcTerms));
if (el != null)
return el.getStringValue();
else
return null;
}
private String loadRevision(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element(
new QName(KEYWORD_REVISION, namespaceCP));
if (el != null)
return el.getStringValue();
else
return null;
}
private String loadSubject(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element(
new QName(KEYWORD_SUBJECT, namespaceDC));
if (el != null)
return el.getStringValue();
else
return null;
}
private String loadTitle(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element(
new QName(KEYWORD_TITLE, namespaceDC));
if (el != null)
return el.getStringValue();
else
return null;
}
private String loadVersion(Document xmlDoc) {
Element el = xmlDoc.getRootElement().element(
new QName(KEYWORD_VERSION, namespaceCP));
if (el != null)
return el.getStringValue();
else
return null;
}
/* OPC Compliance methods */
/**
* Check the element for the following OPC compliance rules:
*
* Rule M4.2: A format consumer shall consider the use of the Markup
* Compatibility namespace to be an error.
*
* Rule M4.3: Producers shall not create a document element that contains
* refinements to the Dublin Core elements, except for the two specified in
* the schema: <dcterms:created> and <dcterms:modified> Consumers shall
* consider a document element that violates this constraint to be an error.
*
* Rule M4.4: Producers shall not create a document element that contains
* the xml:lang attribute. Consumers shall consider a document element that
* violates this constraint to be an error.
*
* Rule M4.5: Producers shall not create a document element that contains
* the xsi:type attribute, except for a <dcterms:created> or
* <dcterms:modified> element where the xsi:type attribute shall be present
* and shall hold the value dcterms:W3CDTF, where dcterms is the namespace
* prefix of the Dublin Core namespace. Consumers shall consider a document
* element that violates this constraint to be an error.
*/
public void checkElementForOPCCompliance(Element el)
throws InvalidFormatException {
// Check the current element
List declaredNamespaces = el.declaredNamespaces();
Iterator itNS = declaredNamespaces.iterator();
while (itNS.hasNext()) {
Namespace ns = (Namespace) itNS.next();
// Rule M4.2
if (ns.getURI().equals(PackageNamespaces.MARKUP_COMPATIBILITY))
throw new InvalidFormatException(
"OPC Compliance error [M4.2]: A format consumer shall consider the use of the Markup Compatibility namespace to be an error.");
}
// Rule M4.3
if (el.getNamespace().getURI().equals(
PackageProperties.NAMESPACE_DCTERMS)
&& !(el.getName().equals(KEYWORD_CREATED) || el.getName()
.equals(KEYWORD_MODIFIED)))
throw new InvalidFormatException(
"OPC Compliance error [M4.3]: Producers shall not create a document element that contains refinements to the Dublin Core elements, except for the two specified in the schema: <dcterms:created> and <dcterms:modified> Consumers shall consider a document element that violates this constraint to be an error.");
// Rule M4.4
if (el.attribute(new QName("lang", namespaceXML)) != null)
throw new InvalidFormatException(
"OPC Compliance error [M4.4]: Producers shall not create a document element that contains the xml:lang attribute. Consumers shall consider a document element that violates this constraint to be an error.");
// Rule M4.5
if (el.getNamespace().getURI().equals(
PackageProperties.NAMESPACE_DCTERMS)) {
// DCTerms namespace only use with 'created' and 'modified' elements
String elName = el.getName();
if (!(elName.equals(KEYWORD_CREATED) || elName
.equals(KEYWORD_MODIFIED)))
throw new InvalidFormatException("Namespace error : " + elName
+ " shouldn't have the following naemspace -> "
+ PackageProperties.NAMESPACE_DCTERMS);
// Check for the 'xsi:type' attribute
Attribute typeAtt = el.attribute(new QName("type", namespaceXSI));
if (typeAtt == null)
throw new InvalidFormatException("The element '" + elName
+ "' must have the '" + namespaceXSI.getPrefix()
+ ":type' attribute present !");
// Check for the attribute value => 'dcterms:W3CDTF'
if (!typeAtt.getValue().equals("dcterms:W3CDTF"))
throw new InvalidFormatException("The element '" + elName
+ "' must have the '" + namespaceXSI.getPrefix()
+ ":type' attribute with the value 'dcterms:W3CDTF' !");
}
// Check its children
Iterator itChildren = el.elementIterator();
while (itChildren.hasNext())
checkElementForOPCCompliance((Element) itChildren.next());
}
}

View File

@ -0,0 +1,96 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc.internal.unmarshallers;
import java.util.zip.ZipEntry;
import org.apache.poi.openxml4j.opc.Package;
import org.apache.poi.openxml4j.opc.PackagePartName;
/**
* Context needed for the unmarshall process of a part. This class is immutable.
*
* @author Julien Chable
* @version 1.0
*/
public final class UnmarshallContext {
private Package _package;
private PackagePartName partName;
private ZipEntry zipEntry;
/**
* Constructor.
*
* @param targetPackage
* Container.
* @param partName
* Name of the part to unmarshall.
*/
public UnmarshallContext(Package targetPackage, PackagePartName partName) {
this._package = targetPackage;
this.partName = partName;
}
/**
* @return the container
*/
Package getPackage() {
return _package;
}
/**
* @param container
* the container to set
*/
public void setPackage(Package container) {
this._package = container;
}
/**
* @return the partName
*/
PackagePartName getPartName() {
return partName;
}
/**
* @param partName
* the partName to set
*/
public void setPartName(PackagePartName partName) {
this.partName = partName;
}
/**
* @return the zipEntry
*/
ZipEntry getZipEntry() {
return zipEntry;
}
/**
* @param zipEntry
* the zipEntry to set
*/
public void setZipEntry(ZipEntry zipEntry) {
this.zipEntry = zipEntry;
}
}

View File

@ -0,0 +1,70 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc.signature;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.internal.ContentType;
public class PackageDigitalSignature extends PackagePart {
public PackageDigitalSignature() throws InvalidFormatException {
super(null, null, new ContentType(""));
}
@Override
public void close() {
// TODO Auto-generated method stub
}
@Override
public void flush() {
// TODO Auto-generated method stub
}
@Override
protected InputStream getInputStreamImpl() throws IOException {
// TODO Auto-generated method stub
return null;
}
@Override
protected OutputStream getOutputStreamImpl() {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean load(InputStream ios) throws InvalidFormatException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean save(OutputStream zos) throws OpenXML4JException {
// TODO Auto-generated method stub
return false;
}
}

View File

@ -0,0 +1,22 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc.signature;
public class PackageDigitalSignatureManager {
}

View File

@ -0,0 +1,71 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.util;
/**
* An immutable object that could be defined as null.
*
* @author Julien Chable
* @version 0.9
*/
public final class Nullable<E> {
private E value;
/**
* Constructor.
*/
public Nullable() {
// Do nothing
}
/**
* Constructor.
*
* @param value
* The value to set to this nullable.
*/
public Nullable(E value) {
this.value = value;
}
/**
* Get the store value if any.
*
* @return
*/
public E getValue() {
return value;
}
/**
* Get the status of this nullable.
*
* @return <b>true</b> if the nullable store a value (empty string is
* considered to be a value) else <b>false</>.
*/
public boolean hasValue() {
return value != null;
}
/**
* Set the stored value to <i>null</i>.
*/
public void nullify() {
value = null;
}
}

View File

@ -0,0 +1,48 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.util;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
/**
* An Interface to make getting the different bits
* of a Zip File easy.
* Allows you to get at the ZipEntries, without
* needing to worry about ZipFile vs ZipInputStream
* being annoyingly very different.
*/
public interface ZipEntrySource {
/**
* Returns an Enumeration of all the Entries
*/
public Enumeration<? extends ZipEntry> getEntries();
/**
* Returns an InputStream of the decompressed
* data that makes up the entry
*/
public InputStream getInputStream(ZipEntry entry) throws IOException;
/**
* Indicates we are done with reading, and
* resources may be freed
*/
public void close() throws IOException;
}

View File

@ -0,0 +1,48 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.util;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
* A ZipEntrySource wrapper around a ZipFile.
* Should be as low in terms of memory as a
* normal ZipFile implementation is.
*/
public class ZipFileZipEntrySource implements ZipEntrySource {
private ZipFile zipArchive;
public ZipFileZipEntrySource(ZipFile zipFile) {
this.zipArchive = zipFile;
}
public void close() throws IOException {
zipArchive.close();
zipArchive = null;
}
public Enumeration<? extends ZipEntry> getEntries() {
return zipArchive.entries();
}
public InputStream getInputStream(ZipEntry entry) throws IOException {
return zipArchive.getInputStream(entry);
}
}

View File

@ -0,0 +1,125 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/**
* Provides a way to get at all the ZipEntries
* from a ZipInputStream, as many times as required.
* Allows a ZipInputStream to be treated much like
* a ZipFile, for a price in terms of memory.
* Be sure to call {@link #close()} as soon as you're
* done, to free up that memory!
*/
public class ZipInputStreamZipEntrySource implements ZipEntrySource {
private ArrayList<FakeZipEntry> zipEntries;
/**
* Reads all the entries from the ZipInputStream
* into memory, and closes the source stream.
* We'll then eat lots of memory, but be able to
* work with the entries at-will.
*/
public ZipInputStreamZipEntrySource(ZipInputStream inp) throws IOException {
zipEntries = new ArrayList<FakeZipEntry>();
boolean going = true;
while(going) {
ZipEntry zipEntry = inp.getNextEntry();
if(zipEntry == null) {
going = false;
} else {
FakeZipEntry entry = new FakeZipEntry(zipEntry, inp);
inp.closeEntry();
zipEntries.add(entry);
}
}
inp.close();
}
public Enumeration<? extends ZipEntry> getEntries() {
return new EntryEnumerator();
}
public InputStream getInputStream(ZipEntry zipEntry) {
FakeZipEntry entry = (FakeZipEntry)zipEntry;
return entry.getInputStream();
}
public void close() {
// Free the memory
zipEntries = null;
}
/**
* Why oh why oh why are Iterator and Enumeration
* still not compatible?
*/
private class EntryEnumerator implements Enumeration<ZipEntry> {
private Iterator<? extends ZipEntry> iterator;
private EntryEnumerator() {
iterator = zipEntries.iterator();
}
public boolean hasMoreElements() {
return iterator.hasNext();
}
public ZipEntry nextElement() {
return iterator.next();
}
}
/**
* So we can close the real zip entry and still
* effectively work with it.
* Holds the (decompressed!) data in memory, so
* close this as soon as you can!
*/
public static class FakeZipEntry extends ZipEntry {
private byte[] data;
public FakeZipEntry(ZipEntry entry, ZipInputStream inp) throws IOException {
super(entry.getName());
// Grab the de-compressed contents for later
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int read = 0;
while( (read = inp.read(buffer)) != -1 ) {
baos.write(buffer, 0, read);
}
data = baos.toByteArray();
}
public InputStream getInputStream() {
return new ByteArrayInputStream(data);
}
}
}

View File

@ -24,7 +24,7 @@ import org.apache.poi.POIXMLDocument;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.openxml4j.opc.Package;
import org.apache.poi.openxml4j.opc.Package;
/**
* Factory for creating the appropriate kind of Workbook

View File

@ -16,16 +16,12 @@
==================================================================== */
package org.apache.poi.util;
import org.openxml4j.opc.*;
import org.openxml4j.opc.Package;
import org.openxml4j.opc.internal.PackagePropertiesPart;
import org.openxml4j.opc.internal.marshallers.PackagePropertiesMarshaller;
import org.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.*;
import org.apache.poi.openxml4j.opc.Package;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.util.IOUtils;
import java.io.*;
import java.util.ArrayList;
import java.lang.reflect.Method;
/**
* Provides handy methods to work with OOXML packages

View File

@ -22,12 +22,12 @@ import java.util.LinkedList;
import org.apache.poi.POIXMLDocument;
import org.apache.xmlbeans.XmlException;
import org.openxml4j.exceptions.InvalidFormatException;
import org.openxml4j.exceptions.OpenXML4JException;
import org.openxml4j.opc.Package;
import org.openxml4j.opc.PackagePart;
import org.openxml4j.opc.PackageRelationship;
import org.openxml4j.opc.PackageRelationshipCollection;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.Package;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
import org.openxmlformats.schemas.presentationml.x2006.main.CTCommentList;
import org.openxmlformats.schemas.presentationml.x2006.main.CTNotesSlide;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPresentation;

View File

@ -23,8 +23,8 @@ import org.apache.poi.xslf.XSLFSlideShow;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import org.apache.xmlbeans.XmlException;
import org.openxml4j.exceptions.OpenXML4JException;
import org.openxml4j.opc.Package;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.Package;
import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;

View File

@ -25,14 +25,14 @@ import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.XSSFRelation;
import org.apache.poi.POIXMLException;
import org.apache.xmlbeans.XmlException;
import org.openxml4j.exceptions.InvalidFormatException;
import org.openxml4j.exceptions.OpenXML4JException;
import org.openxml4j.opc.Package;
import org.openxml4j.opc.PackagePart;
import org.openxml4j.opc.PackagePartName;
import org.openxml4j.opc.PackageRelationship;
import org.openxml4j.opc.PackageRelationshipTypes;
import org.openxml4j.opc.PackagingURIHelper;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.Package;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbook;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.WorkbookDocument;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet;

View File

@ -29,8 +29,8 @@ import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.xmlbeans.XmlException;
import org.openxml4j.exceptions.OpenXML4JException;
import org.openxml4j.opc.Package;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.Package;
/**
* Helper class to extract text from an OOXML Excel file

View File

@ -29,8 +29,8 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCommentList;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComments;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CommentsDocument;
import org.openxml4j.opc.PackagePart;
import org.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
public class CommentsTable extends POIXMLDocumentPart {
protected CTComments comments;

View File

@ -31,9 +31,8 @@ import org.apache.poi.POIXMLDocumentPart;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSst;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.SstDocument;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet;
import org.openxml4j.opc.PackagePart;
import org.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
/**

View File

@ -48,8 +48,8 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTStylesheet;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXf;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPatternType;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.StyleSheetDocument;
import org.openxml4j.opc.PackagePart;
import org.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
/**

View File

@ -17,7 +17,7 @@
package org.apache.poi.xssf.model;
import org.apache.poi.xssf.usermodel.XSSFRelation;
import org.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagePart;
/**
* Common interface for XSSF models, which have (typically

View File

@ -7,7 +7,7 @@ import org.apache.poi.ss.usermodel.PictureData;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.model.XSSFWritableModel;
import org.apache.poi.POIXMLException;
import org.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagePart;
public class XSSFActiveXData implements PictureData, XSSFWritableModel {

View File

@ -17,15 +17,8 @@
package org.apache.poi.xssf.usermodel;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.POIXMLException;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
import org.openxml4j.opc.PackagePart;
import org.openxml4j.opc.PackageRelationship;
import java.io.IOException;
//YK: TODO: this is only a prototype
public class XSSFDialogsheet extends XSSFSheet implements Sheet{

View File

@ -21,7 +21,7 @@ import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOptions;
import org.openxml4j.opc.*;
import org.apache.poi.openxml4j.opc.*;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.*;
import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId;

View File

@ -22,8 +22,8 @@ import org.apache.poi.POIXMLException;
import org.apache.poi.POIXMLRelation;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.POILogFactory;
import org.openxml4j.opc.PackageRelationship;
import org.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.PackagePart;
import java.lang.reflect.Constructor;

View File

@ -22,8 +22,8 @@ import org.apache.poi.ss.usermodel.Hyperlink;
import org.apache.poi.ss.util.CellReference;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHyperlink;
import org.openxml4j.opc.PackagePart;
import org.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
/**

View File

@ -23,8 +23,8 @@ import org.apache.poi.ss.usermodel.Picture;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.POIXMLDocumentPart;
import org.openxml4j.opc.PackageRelationship;
import org.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.w3c.dom.NodeList;
import org.w3c.dom.Element;
import javax.imageio.ImageIO;

View File

@ -24,8 +24,8 @@ import org.apache.poi.util.IOUtils;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.POIXMLException;
import org.apache.poi.POIXMLRelation;
import org.openxml4j.opc.PackagePart;
import org.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
/**
* Raw picture data, normally attached to a SpreadsheetML Drawing.

View File

@ -30,12 +30,12 @@ import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.model.CommentsTable;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.openxml4j.exceptions.InvalidFormatException;
import org.openxml4j.opc.PackagePart;
import org.openxml4j.opc.PackagePartName;
import org.openxml4j.opc.PackageRelationship;
import org.openxml4j.opc.PackageRelationshipCollection;
import org.openxml4j.opc.PackagingURIHelper;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
/**
*

View File

@ -18,7 +18,7 @@ package org.apache.poi.xssf.usermodel;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.*;
import org.openxmlformats.schemas.drawingml.x2006.main.*;
import org.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.PackageRelationship;
/**
* This object specifies a group shape that represents many shapes grouped together. This shape is to be treated

View File

@ -39,10 +39,10 @@ import org.apache.poi.util.POILogger;
import org.apache.poi.util.POILogFactory;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.XmlException;
import org.openxml4j.opc.PackagePart;
import org.openxml4j.opc.PackageRelationship;
import org.openxml4j.opc.PackageRelationshipCollection;
import org.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId;

View File

@ -50,14 +50,14 @@ import org.apache.poi.xssf.model.StylesTable;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.openxml4j.exceptions.OpenXML4JException;
import org.openxml4j.opc.Package;
import org.openxml4j.opc.PackagePart;
import org.openxml4j.opc.PackagePartName;
import org.openxml4j.opc.PackageRelationship;
import org.openxml4j.opc.PackageRelationshipTypes;
import org.openxml4j.opc.PackagingURIHelper;
import org.openxml4j.opc.TargetMode;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.Package;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
import org.apache.poi.openxml4j.opc.TargetMode;
import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBookView;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBookViews;

View File

@ -29,8 +29,8 @@ import org.apache.poi.xwpf.model.XWPFParagraphDecorator;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.xmlbeans.XmlException;
import org.openxml4j.exceptions.OpenXML4JException;
import org.openxml4j.opc.Package;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.Package;
/**
* Helper class to extract text from an OOXML Word file

View File

@ -22,7 +22,7 @@ import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFFooter;
import org.apache.poi.xwpf.usermodel.XWPFHeader;
import org.apache.xmlbeans.XmlException;
import org.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtrRef;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.FtrDocument;

View File

@ -27,10 +27,10 @@ import org.apache.poi.util.PackageHelper;
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOptions;
import org.openxml4j.exceptions.InvalidFormatException;
import org.openxml4j.exceptions.OpenXML4JException;
import org.openxml4j.opc.*;
import org.openxml4j.opc.Package;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.*;
import org.apache.poi.openxml4j.opc.Package;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTComment;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDocument1;

View File

@ -22,8 +22,8 @@ import org.apache.poi.POIXMLException;
import org.apache.poi.POIXMLRelation;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.POILogFactory;
import org.openxml4j.opc.PackageRelationship;
import org.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.PackagePart;
import java.lang.reflect.Constructor;

View File

@ -25,8 +25,8 @@ import org.apache.poi.util.IOUtils;
import org.apache.poi.xslf.XSLFSlideShow;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.openxml4j.opc.Package;
import org.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.Package;
import org.apache.poi.openxml4j.opc.PackagePart;
import junit.framework.TestCase;

View File

@ -20,7 +20,7 @@ import java.io.File;
import org.apache.poi.xssf.extractor.XSSFExcelExtractor;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.openxml4j.opc.Package;
import org.apache.poi.openxml4j.opc.Package;
import junit.framework.TestCase;
@ -33,7 +33,7 @@ public class TestXMLPropertiesTextExtractor extends TestCase {
}
public void testGetFromMainExtractor() throws Exception {
org.openxml4j.opc.Package pkg = Package.open(
org.apache.poi.openxml4j.opc.Package pkg = Package.open(
(new File(dirname, "ExcelWithAttachments.xlsx")).toString()
);
XSSFWorkbook wb = new XSSFWorkbook(pkg);
@ -54,7 +54,7 @@ public class TestXMLPropertiesTextExtractor extends TestCase {
}
public void testCore() throws Exception {
org.openxml4j.opc.Package pkg = Package.open(
org.apache.poi.openxml4j.opc.Package pkg = Package.open(
(new File(dirname, "ExcelWithAttachments.xlsx")).toString()
);
XSSFWorkbook wb = new XSSFWorkbook(pkg);
@ -71,7 +71,7 @@ public class TestXMLPropertiesTextExtractor extends TestCase {
}
public void testExtended() throws Exception {
org.openxml4j.opc.Package pkg = Package.open(
org.apache.poi.openxml4j.opc.Package pkg = Package.open(
(new File(dirname, "ExcelWithAttachments.xlsx")).toString()
);
XSSFWorkbook wb = new XSSFWorkbook(pkg);

View File

@ -33,8 +33,8 @@ import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import junit.framework.TestCase;
import org.openxml4j.exceptions.InvalidOperationException;
import org.openxml4j.opc.Package;
import org.apache.poi.openxml4j.exceptions.InvalidOperationException;
import org.apache.poi.openxml4j.opc.Package;
/**
* Test that the extractor factory plays nicely

View File

@ -0,0 +1,102 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j;
import java.io.File;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
/**
* Core helper for tests.
*
* @author Julien Chable
* @version 1.0
*/
public class TestCore {
private String testRootPath; // Test root path
/**
* All sample document are normally located at this place.
*/
private static String pathRootProject; // Project root path
/**
* Demo logger
*/
private static Logger logger = Logger.getLogger("org.apache.poi.openxml4j.test");
static {
pathRootProject = System.getProperty("user.dir") + File.separator + "bin";
// Log4j configuration
//PropertyConfigurator.configure(pathRootProject + File.separator
// + "config.log4j");
}
/**
* Constructor. Initialize the demo.
*
*/
public TestCore(Class cl) {
init(cl);
}
/**
* Initialize the test root path
*/
public void init(Class cl) {
String packageName = cl.getPackage().getName();
// replace . by /
String sep = File.separator;
if (sep.equals("\\")) {
sep = "\\\\";
}
testRootPath = pathRootProject + File.separator
+ packageName.replaceAll("\\.", sep)
+ File.separator;
}
// Accessors
/**
* Gets the test root path.
*
* @return The test root path.
*/
public String getTestRootPath() {
return testRootPath;
}
/**
* Sets the test root path.
*
* @param testRoot
*/
public void setTestRootPath(String testRoot) {
this.testRootPath = testRoot;
}
/**
* @return the logger
*/
public static Logger getLogger() {
return logger;
}
}

View File

@ -0,0 +1,38 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.openxml4j.opc;
import junit.framework.Test;
import junit.framework.TestSuite;
public class AllTests {
public static Test suite() {
TestSuite suite = new TestSuite(
"Functional tests for org.apache.poi.openxml4j.opc");
suite.addTestSuite(TestListParts.class);
suite.addTestSuite(TestFileHelper.class);
suite.addTestSuite(TestPackage.class);
suite.addTestSuite(TestPackageCoreProperties.class);
suite.addTestSuite(TestPackagePartName.class);
suite.addTestSuite(TestPackagingURIHelper.class);
suite.addTestSuite(TestContentType.class);
suite.addTestSuite(TestPackageThumbnail.class);
return suite;
}
}

Some files were not shown because too many files have changed in this diff Show More