From: Josh Micich Date: Wed, 18 Mar 2009 18:54:01 +0000 (+0000) Subject: Renamed Package (in org.apache.poi.openxml4j.opc) to OPCPackage so as to avoid clash... X-Git-Tag: REL_3_5_BETA6~93 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=aca8d5187d7d19b4baa52221194a0bd87b0bc038;p=poi.git Renamed Package (in org.apache.poi.openxml4j.opc) to OPCPackage so as to avoid clash with java.lang.Package (see bugzilla 46859) git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@755699 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/examples/src/org/apache/poi/xssf/eventusermodel/examples/FromHowTo.java b/src/examples/src/org/apache/poi/xssf/eventusermodel/examples/FromHowTo.java index 88668093df..fc6604c649 100644 --- a/src/examples/src/org/apache/poi/xssf/eventusermodel/examples/FromHowTo.java +++ b/src/examples/src/org/apache/poi/xssf/eventusermodel/examples/FromHowTo.java @@ -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.apache.poi.openxml4j.opc.Package; +import org.apache.poi.openxml4j.opc.OPCPackage; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.InputSource; @@ -36,7 +36,7 @@ import org.xml.sax.helpers.XMLReaderFactory; */ public class FromHowTo { public void processOneSheet(String filename) throws Exception { - Package pkg = Package.open(filename); + OPCPackage pkg = OPCPackage.open(filename); XSSFReader r = new XSSFReader( pkg ); SharedStringsTable sst = r.getSharedStringsTable(); @@ -51,7 +51,7 @@ public class FromHowTo { } public void processAllSheets(String filename) throws Exception { - Package pkg = Package.open(filename); + OPCPackage pkg = OPCPackage.open(filename); XSSFReader r = new XSSFReader( pkg ); SharedStringsTable sst = r.getSharedStringsTable(); diff --git a/src/ooxml/java/org/apache/poi/POIXMLDocument.java b/src/ooxml/java/org/apache/poi/POIXMLDocument.java index ef333d86df..f71ed7ba3e 100644 --- a/src/ooxml/java/org/apache/poi/POIXMLDocument.java +++ b/src/ooxml/java/org/apache/poi/POIXMLDocument.java @@ -41,14 +41,14 @@ public abstract class POIXMLDocument extends POIXMLDocumentPart{ public static final String PACK_OBJECT_REL_TYPE="http://schemas.openxmlformats.org/officeDocument/2006/relationships/package"; /** The OPC Package */ - private Package pkg; + private OPCPackage pkg; /** * The properties of the OPC package, opened as needed */ private POIXMLProperties properties; - protected POIXMLDocument(Package pkg) { + protected POIXMLDocument(OPCPackage pkg) { super(pkg); this.pkg = pkg; } @@ -58,15 +58,15 @@ public abstract class POIXMLDocument extends POIXMLDocumentPart{ * in the event of a problem. * Works around shortcomings in java's this() constructor calls */ - public static Package openPackage(String path) throws IOException { + public static OPCPackage openPackage(String path) throws IOException { try { - return Package.open(path); + return OPCPackage.open(path); } catch (InvalidFormatException e) { throw new IOException(e.toString()); } } - public Package getPackage() { + public OPCPackage getPackage() { return this.pkg; } @@ -92,7 +92,7 @@ public abstract class POIXMLDocument extends POIXMLDocumentPart{ * @return The target part * @throws InvalidFormatException */ - protected static PackagePart getTargetPart(Package pkg, PackageRelationship rel) throws InvalidFormatException { + protected static PackagePart getTargetPart(OPCPackage pkg, PackageRelationship rel) throws InvalidFormatException { PackagePartName relName = PackagingURIHelper.createPartName(rel.getTargetURI()); PackagePart part = pkg.getPart(relName); if (part == null) { @@ -176,7 +176,7 @@ public abstract class POIXMLDocument extends POIXMLDocumentPart{ * there is no way to change or even save such an instance in a OutputStream. * The workaround is to create a copy via a temp file */ - protected static Package ensureWriteAccess(Package pkg) throws IOException { + protected static OPCPackage ensureWriteAccess(OPCPackage pkg) throws IOException { if(pkg.getPackageAccess() == PackageAccess.READ){ try { return PackageHelper.clone(pkg); diff --git a/src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java b/src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java index aa7f72df19..a93215a3b9 100755 --- a/src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java +++ b/src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java @@ -1,269 +1,265 @@ -/* ==================================================================== - 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; - -import java.io.IOException; -import java.util.LinkedList; -import java.util.List; - -import org.apache.xmlbeans.XmlOptions; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.POILogFactory; -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. - * - *

- * Each POIXMLDocumentPart keeps a reference to the underlying a {@link org.apache.poi.openxml4j.opc.PackagePart}. - *

- * - * @author Yegor Kozlov - */ -public class POIXMLDocumentPart { - private static POILogger logger = POILogFactory.getLogger(POIXMLDocumentPart.class); - - public static final XmlOptions DEFAULT_XML_OPTIONS; - static { - DEFAULT_XML_OPTIONS = new XmlOptions(); - DEFAULT_XML_OPTIONS.setSaveOuter(); - DEFAULT_XML_OPTIONS.setUseDefaultNamespace(); - DEFAULT_XML_OPTIONS.setSaveAggressiveNamespaces(); - } - - private PackagePart packagePart; - private PackageRelationship packageRel; - private POIXMLDocumentPart parent; - private List relations; - - /** - * Construct POIXMLDocumentPart representing a "core document" package part. - */ - public POIXMLDocumentPart(Package pkg) { - try { - PackageRelationship coreRel = pkg.getRelationshipsByType( - PackageRelationshipTypes.CORE_DOCUMENT).getRelationship(0); - - this.relations = new LinkedList(); - this.packagePart = pkg.getPart(coreRel); - this.packageRel = coreRel; - } catch (OpenXML4JException e){ - throw new POIXMLException(e); - } - } - - /** - * Creates new POIXMLDocumentPart - called by client code to create new parts from scratch. - * - * @see #createRelationship(POIXMLRelation, POIXMLFactory, int, boolean) - */ - public POIXMLDocumentPart(){ - this.relations = new LinkedList(); - } - - /** - * Creates an POIXMLDocumentPart representing the given package part and relationship. - * Called by {@link #read(POIXMLFactory)} when reading in an exisiting file. - * - * @param part - The package part that holds xml data represenring this sheet. - * @param rel - the relationship of the given package part - * @see #read(POIXMLFactory) - */ - public POIXMLDocumentPart(PackagePart part, PackageRelationship rel){ - this.relations = new LinkedList(); - this.packagePart = part; - this.packageRel = rel; - } - - /** - * Provides access to the underlying PackagePart - * - * @return the underlying PackagePart - */ - public final PackagePart getPackagePart(){ - return packagePart; - } - - /** - * Provides access to the PackageRelationship that identifies this POIXMLDocumentPart - * - * @return the PackageRelationship that identifies this POIXMLDocumentPart - */ - public final PackageRelationship getPackageRelationship(){ - return packageRel; - } - - /** - * Returns the list of child relations for this POIXMLDocumentPart - * - * @return child relations - */ - public final List getRelations(){ - return relations; - } - - /** - * Add a new child POIXMLDocumentPart - * - * @param part the child to add - */ - protected final void addRelation(POIXMLDocumentPart part){ - relations.add(part); - } - - /** - * Remove the specified part in this package. - */ - public final void removeRelation(POIXMLDocumentPart part){ - getPackagePart().removeRelationship(part.getPackageRelationship().getId()); - getPackagePart().getPackage().removePart(part.getPackagePart()); - relations.remove(part); - } - - /** - * Returns the parent POIXMLDocumentPart. All parts except root have not-null parent. - * - * @return the parent POIXMLDocumentPart or null for the root element. - */ - public final POIXMLDocumentPart getParent(){ - return parent; - } - - @Override - public String toString(){ - return packagePart.toString(); - } - - /** - * Save the content in the underlying package part. - * Default implementation is empty meaning that the package part is left unmodified. - * - * Sub-classes should override and add logic to marshal the "model" into Ooxml4J. - * - * For example, the code saving a generic XML entry may look as follows: - *

-     * protected void commit() throws IOException {
-     *   PackagePart part = getPackagePart();
-     *   OutputStream out = part.getOutputStream();
-     *   XmlObject bean = getXmlBean(); //the "model" which holds changes in memory
-     *   bean.save(out, DEFAULT_XML_OPTIONS);
-     *   out.close();
-     * }
-     *  
- * - */ - protected void commit() throws IOException { - - } - - /** - * Save changes in the underlying OOXML package. - * Recursively fires {@link #commit()} for each package part - */ - protected final void onSave() throws IOException{ - commit(); - for(POIXMLDocumentPart p : relations){ - p.onSave(); - } - } - - /** - * Create a new child POIXMLDocumentPart - * - * @param descriptor the part descriptor - * @param factory the factory that will create an instance of the requested relation - * @return the created child POIXMLDocumentPart - */ - protected final POIXMLDocumentPart createRelationship(POIXMLRelation descriptor, POIXMLFactory factory){ - return createRelationship(descriptor, factory, -1, false); - } - - protected final POIXMLDocumentPart createRelationship(POIXMLRelation descriptor, POIXMLFactory factory, int idx){ - return createRelationship(descriptor, factory, idx, false); - } - - /** - * Create a new child POIXMLDocumentPart - * - * @param descriptor the part descriptor - * @param factory the factory that will create an instance of the requested relation - * @param idx part number - * @param noRelation if true, then no relationship is added. - * @return the created child POIXMLDocumentPart - */ - protected final POIXMLDocumentPart createRelationship(POIXMLRelation descriptor, POIXMLFactory factory, int idx, boolean noRelation){ - try { - - PackagePartName ppName = PackagingURIHelper.createPartName(descriptor.getFileName(idx)); - PackageRelationship rel = null; - if(!noRelation) rel = packagePart.addRelationship(ppName, TargetMode.INTERNAL, descriptor.getRelation()); - - PackagePart part = packagePart.getPackage().createPart(ppName, descriptor.getContentType()); - POIXMLDocumentPart doc = factory.newDocumentPart(descriptor); - doc.packageRel = rel; - doc.packagePart = part; - doc.parent = this; - addRelation(doc); - return doc; - } catch (Exception e){ - throw new POIXMLException(e); - } - } - - /** - * Iterate through the underlying PackagePart and create child POIXMLFactory instances - * using the specified factory - * - * @param factory the factory object that creates POIXMLFactory instances - */ - protected final void read(POIXMLFactory factory) throws OpenXML4JException { - PackageRelationshipCollection rels = packagePart.getRelationships(); - for (PackageRelationship rel : rels) { - if(rel.getTargetMode() == TargetMode.INTERNAL){ - PackagePartName relName = PackagingURIHelper.createPartName(rel.getTargetURI()); - PackagePart p = packagePart.getPackage().getPart(relName); - if(p == null) { - logger.log(POILogger.ERROR, "Skipped invalid entry " + rel.getTargetURI()); - continue; - } - POIXMLDocumentPart childPart = factory.createDocumentPart(rel, p); - childPart.parent = this; - addRelation(childPart); - - if(p.hasRelationships()) childPart.read(factory); - } - } - } - - - /** - * Fired when a new package part is created - */ - protected void onDocumentCreate() throws IOException { - - } - - /** - * Fired when a package part is read - */ - protected void onDocumentRead() throws IOException{ - - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi; + +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; + +import org.apache.xmlbeans.XmlOptions; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.POILogFactory; +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. + * + *

+ * Each POIXMLDocumentPart keeps a reference to the underlying a {@link org.apache.poi.openxml4j.opc.PackagePart}. + *

+ * + * @author Yegor Kozlov + */ +public class POIXMLDocumentPart { + private static POILogger logger = POILogFactory.getLogger(POIXMLDocumentPart.class); + + public static final XmlOptions DEFAULT_XML_OPTIONS; + static { + DEFAULT_XML_OPTIONS = new XmlOptions(); + DEFAULT_XML_OPTIONS.setSaveOuter(); + DEFAULT_XML_OPTIONS.setUseDefaultNamespace(); + DEFAULT_XML_OPTIONS.setSaveAggressiveNamespaces(); + } + + private PackagePart packagePart; + private PackageRelationship packageRel; + private POIXMLDocumentPart parent; + private List relations; + + /** + * Construct POIXMLDocumentPart representing a "core document" package part. + */ + public POIXMLDocumentPart(OPCPackage pkg) { + PackageRelationship coreRel = pkg.getRelationshipsByType( + PackageRelationshipTypes.CORE_DOCUMENT).getRelationship(0); + + this.relations = new LinkedList(); + this.packagePart = pkg.getPart(coreRel); + this.packageRel = coreRel; + } + + /** + * Creates new POIXMLDocumentPart - called by client code to create new parts from scratch. + * + * @see #createRelationship(POIXMLRelation, POIXMLFactory, int, boolean) + */ + public POIXMLDocumentPart(){ + this.relations = new LinkedList(); + } + + /** + * Creates an POIXMLDocumentPart representing the given package part and relationship. + * Called by {@link #read(POIXMLFactory)} when reading in an exisiting file. + * + * @param part - The package part that holds xml data represenring this sheet. + * @param rel - the relationship of the given package part + * @see #read(POIXMLFactory) + */ + public POIXMLDocumentPart(PackagePart part, PackageRelationship rel){ + this.relations = new LinkedList(); + this.packagePart = part; + this.packageRel = rel; + } + + /** + * Provides access to the underlying PackagePart + * + * @return the underlying PackagePart + */ + public final PackagePart getPackagePart(){ + return packagePart; + } + + /** + * Provides access to the PackageRelationship that identifies this POIXMLDocumentPart + * + * @return the PackageRelationship that identifies this POIXMLDocumentPart + */ + public final PackageRelationship getPackageRelationship(){ + return packageRel; + } + + /** + * Returns the list of child relations for this POIXMLDocumentPart + * + * @return child relations + */ + public final List getRelations(){ + return relations; + } + + /** + * Add a new child POIXMLDocumentPart + * + * @param part the child to add + */ + protected final void addRelation(POIXMLDocumentPart part){ + relations.add(part); + } + + /** + * Remove the specified part in this package. + */ + public final void removeRelation(POIXMLDocumentPart part){ + getPackagePart().removeRelationship(part.getPackageRelationship().getId()); + getPackagePart().getPackage().removePart(part.getPackagePart()); + relations.remove(part); + } + + /** + * Returns the parent POIXMLDocumentPart. All parts except root have not-null parent. + * + * @return the parent POIXMLDocumentPart or null for the root element. + */ + public final POIXMLDocumentPart getParent(){ + return parent; + } + + @Override + public String toString(){ + return packagePart.toString(); + } + + /** + * Save the content in the underlying package part. + * Default implementation is empty meaning that the package part is left unmodified. + * + * Sub-classes should override and add logic to marshal the "model" into Ooxml4J. + * + * For example, the code saving a generic XML entry may look as follows: + *

+     * protected void commit() throws IOException {
+     *   PackagePart part = getPackagePart();
+     *   OutputStream out = part.getOutputStream();
+     *   XmlObject bean = getXmlBean(); //the "model" which holds changes in memory
+     *   bean.save(out, DEFAULT_XML_OPTIONS);
+     *   out.close();
+     * }
+     *  
+ * + */ + protected void commit() throws IOException { + + } + + /** + * Save changes in the underlying OOXML package. + * Recursively fires {@link #commit()} for each package part + */ + protected final void onSave() throws IOException{ + commit(); + for(POIXMLDocumentPart p : relations){ + p.onSave(); + } + } + + /** + * Create a new child POIXMLDocumentPart + * + * @param descriptor the part descriptor + * @param factory the factory that will create an instance of the requested relation + * @return the created child POIXMLDocumentPart + */ + protected final POIXMLDocumentPart createRelationship(POIXMLRelation descriptor, POIXMLFactory factory){ + return createRelationship(descriptor, factory, -1, false); + } + + protected final POIXMLDocumentPart createRelationship(POIXMLRelation descriptor, POIXMLFactory factory, int idx){ + return createRelationship(descriptor, factory, idx, false); + } + + /** + * Create a new child POIXMLDocumentPart + * + * @param descriptor the part descriptor + * @param factory the factory that will create an instance of the requested relation + * @param idx part number + * @param noRelation if true, then no relationship is added. + * @return the created child POIXMLDocumentPart + */ + protected final POIXMLDocumentPart createRelationship(POIXMLRelation descriptor, POIXMLFactory factory, int idx, boolean noRelation){ + try { + + PackagePartName ppName = PackagingURIHelper.createPartName(descriptor.getFileName(idx)); + PackageRelationship rel = null; + if(!noRelation) rel = packagePart.addRelationship(ppName, TargetMode.INTERNAL, descriptor.getRelation()); + + PackagePart part = packagePart.getPackage().createPart(ppName, descriptor.getContentType()); + POIXMLDocumentPart doc = factory.newDocumentPart(descriptor); + doc.packageRel = rel; + doc.packagePart = part; + doc.parent = this; + addRelation(doc); + return doc; + } catch (Exception e){ + throw new POIXMLException(e); + } + } + + /** + * Iterate through the underlying PackagePart and create child POIXMLFactory instances + * using the specified factory + * + * @param factory the factory object that creates POIXMLFactory instances + */ + protected final void read(POIXMLFactory factory) throws OpenXML4JException { + PackageRelationshipCollection rels = packagePart.getRelationships(); + for (PackageRelationship rel : rels) { + if(rel.getTargetMode() == TargetMode.INTERNAL){ + PackagePartName relName = PackagingURIHelper.createPartName(rel.getTargetURI()); + PackagePart p = packagePart.getPackage().getPart(relName); + if(p == null) { + logger.log(POILogger.ERROR, "Skipped invalid entry " + rel.getTargetURI()); + continue; + } + POIXMLDocumentPart childPart = factory.createDocumentPart(rel, p); + childPart.parent = this; + addRelation(childPart); + + if(p.hasRelationships()) childPart.read(factory); + } + } + } + + + /** + * Fired when a new package part is created + */ + protected void onDocumentCreate() throws IOException { + + } + + /** + * Fired when a package part is read + */ + protected void onDocumentRead() throws IOException{ + + } + +} diff --git a/src/ooxml/java/org/apache/poi/POIXMLProperties.java b/src/ooxml/java/org/apache/poi/POIXMLProperties.java index 3d862be888..dcb6a9ce3f 100644 --- a/src/ooxml/java/org/apache/poi/POIXMLProperties.java +++ b/src/ooxml/java/org/apache/poi/POIXMLProperties.java @@ -18,23 +18,23 @@ package org.apache.poi; import java.io.IOException; -import org.apache.xmlbeans.XmlException; import org.apache.poi.openxml4j.exceptions.OpenXML4JException; -import org.apache.poi.openxml4j.opc.Package; +import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart; +import org.apache.xmlbeans.XmlException; /** * Wrapper around the two different kinds of OOXML properties * a document can have */ public class POIXMLProperties { - private Package pkg; + private OPCPackage pkg; private CoreProperties core; private ExtendedProperties ext; private CustomProperties cust; - public POIXMLProperties(Package docPackage) throws IOException, OpenXML4JException, XmlException { + public POIXMLProperties(OPCPackage docPackage) throws IOException, OpenXML4JException, XmlException { this.pkg = docPackage; // Core properties @@ -97,7 +97,7 @@ public class POIXMLProperties { * Writes out the ooxml properties into the supplied, * new Package */ - public void write(Package pkg) { + public void write(OPCPackage pkg) { // TODO } diff --git a/src/ooxml/java/org/apache/poi/dev/OOXMLLister.java b/src/ooxml/java/org/apache/poi/dev/OOXMLLister.java index a55bc2632b..ed5fec2855 100644 --- a/src/ooxml/java/org/apache/poi/dev/OOXMLLister.java +++ b/src/ooxml/java/org/apache/poi/dev/OOXMLLister.java @@ -22,7 +22,7 @@ import java.io.InputStream; import java.io.PrintStream; import java.util.ArrayList; -import org.apache.poi.openxml4j.opc.Package; +import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackageAccess; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackageRelationship; @@ -34,13 +34,13 @@ import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; * they're all related to each other. */ public class OOXMLLister { - private Package container; + private OPCPackage container; private PrintStream disp; - public OOXMLLister(Package container) { + public OOXMLLister(OPCPackage container) { this(container, System.out); } - public OOXMLLister(Package container, PrintStream disp) { + public OOXMLLister(OPCPackage container, PrintStream disp) { this.container = container; this.disp = disp; } @@ -122,7 +122,7 @@ public class OOXMLLister { } OOXMLLister lister = new OOXMLLister( - Package.open(f.toString(), PackageAccess.READ) + OPCPackage.open(f.toString(), PackageAccess.READ) ); lister.disp.println(f.toString() + "\n"); diff --git a/src/ooxml/java/org/apache/poi/extractor/ExtractorFactory.java b/src/ooxml/java/org/apache/poi/extractor/ExtractorFactory.java index 7640db845f..dc25f63a38 100644 --- a/src/ooxml/java/org/apache/poi/extractor/ExtractorFactory.java +++ b/src/ooxml/java/org/apache/poi/extractor/ExtractorFactory.java @@ -33,6 +33,11 @@ import org.apache.poi.hdgf.extractor.VisioTextExtractor; import org.apache.poi.hslf.extractor.PowerPointExtractor; import org.apache.poi.hssf.extractor.ExcelExtractor; import org.apache.poi.hwpf.extractor.WordExtractor; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; import org.apache.poi.poifs.filesystem.DirectoryEntry; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.Entry; @@ -41,14 +46,9 @@ 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.XWPFRelation; import org.apache.poi.xwpf.extractor.XWPFWordExtractor; +import org.apache.poi.xwpf.usermodel.XWPFRelation; import org.apache.xmlbeans.XmlException; -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 @@ -67,7 +67,7 @@ public class ExtractorFactory { } if(POIXMLDocument.hasOOXMLHeader(inp)) { inp.close(); - return createExtractor(Package.open(f.toString())); + return createExtractor(OPCPackage.open(f.toString())); } throw new IllegalArgumentException("Your File was neither an OLE2 file, nor an OOXML file"); } @@ -83,12 +83,12 @@ public class ExtractorFactory { return createExtractor(new POIFSFileSystem(inp)); } if(POIXMLDocument.hasOOXMLHeader(inp)) { - return createExtractor(Package.open(inp)); + return createExtractor(OPCPackage.open(inp)); } throw new IllegalArgumentException("Your InputStream was neither an OLE2 stream, nor an OOXML stream"); } - public static POIXMLTextExtractor createExtractor(Package pkg) throws IOException, OpenXML4JException, XmlException { + public static POIXMLTextExtractor createExtractor(OPCPackage pkg) throws IOException, OpenXML4JException, XmlException { PackageRelationshipCollection core = pkg.getRelationshipsByType(CORE_DOCUMENT_REL); if(core.size() != 1) { diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/OPCPackage.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/OPCPackage.java new file mode 100644 index 0000000000..4efe6bdd89 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/OPCPackage.java @@ -0,0 +1,1390 @@ +/* ==================================================================== + 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.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Date; +import java.util.Hashtable; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +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.exceptions.OpenXML4JRuntimeException; +import org.apache.poi.openxml4j.opc.internal.ContentType; +import org.apache.poi.openxml4j.opc.internal.ContentTypeManager; +import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart; +import org.apache.poi.openxml4j.opc.internal.PartMarshaller; +import org.apache.poi.openxml4j.opc.internal.PartUnmarshaller; +import org.apache.poi.openxml4j.opc.internal.ZipContentTypeManager; +import org.apache.poi.openxml4j.opc.internal.marshallers.DefaultMarshaller; +import org.apache.poi.openxml4j.opc.internal.marshallers.ZipPackagePropertiesMarshaller; +import org.apache.poi.openxml4j.opc.internal.unmarshallers.PackagePropertiesUnmarshaller; +import org.apache.poi.openxml4j.opc.internal.unmarshallers.UnmarshallContext; +import org.apache.poi.openxml4j.util.Nullable; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.POILogFactory; + +/** + * Represents a container that can store multiple data objects. + * + * @author Julien Chable, CDubet + * @version 0.1 + */ +public abstract class OPCPackage implements RelationshipSource { + + /** + * Logger. + */ + private static POILogger logger = POILogFactory.getLogger(OPCPackage.class); + + /** + * Default package access. + */ + protected static final PackageAccess defaultPackageAccess = PackageAccess.READ_WRITE; + + /** + * Package access. + */ + private PackageAccess packageAccess; + + /** + * Package parts collection. + */ + protected PackagePartCollection partList; + + /** + * Package relationships. + */ + protected PackageRelationshipCollection relationships; + + /** + * Part marshallers by content type. + */ + protected Hashtable partMarshallers; + + /** + * Default part marshaller. + */ + protected PartMarshaller defaultPartMarshaller; + + /** + * Part unmarshallers by content type. + */ + protected Hashtable partUnmarshallers; + + /** + * Core package properties. + */ + protected PackagePropertiesPart packageProperties; + + /** + * Manage parts content types of this package. + */ + protected ContentTypeManager contentTypeManager; + + /** + * Flag if a modification is done to the document. + */ + protected boolean isDirty = false; + + /** + * File path of this package. + */ + protected String originalPackagePath; + + /** + * Output stream for writing this package. + */ + protected OutputStream output; + + /** + * Constructor. + * + * @param access + * Package access. + */ + OPCPackage(PackageAccess access) { + if (getClass() != ZipPackage.class) { + throw new IllegalArgumentException("PackageBase may not be subclassed"); + } + init(); + this.packageAccess = access; + } + + /** + * Initialize the package instance. + */ + private void init() { + this.partMarshallers = new Hashtable(5); + this.partUnmarshallers = new Hashtable(2); + + try { + // Add 'default' unmarshaller + this.partUnmarshallers.put(new ContentType( + ContentTypes.CORE_PROPERTIES_PART), + new PackagePropertiesUnmarshaller()); + + // Add default marshaller + this.defaultPartMarshaller = new DefaultMarshaller(); + // TODO Delocalize specialized marshallers + this.partMarshallers.put(new ContentType( + ContentTypes.CORE_PROPERTIES_PART), + new ZipPackagePropertiesMarshaller()); + } catch (InvalidFormatException e) { + // Should never happen + throw new OpenXML4JRuntimeException( + "Package.init() : this exception should never happen, if you read this message please send a mail to the developers team."); + } + } + + + /** + * Open a package with read/write permission. + * + * @param path + * The document path. + * @return A Package object, else null. + * @throws InvalidFormatException + * If the specified file doesn't exist, and a parsing error + * occur. + */ + public static OPCPackage open(String path) throws InvalidFormatException { + return open(path, defaultPackageAccess); + } + + /** + * Open a package. + * + * @param path + * The document path. + * @param access + * PackageBase access. + * @return A PackageBase object, else null. + * @throws InvalidFormatException + * If the specified file doesn't exist, and a parsing error + * occur. + */ + public static OPCPackage open(String path, PackageAccess access) + throws InvalidFormatException { + if (path == null || "".equals(path.trim()) + || (new File(path).exists() && new File(path).isDirectory())) + throw new IllegalArgumentException("path"); + + OPCPackage pack = new ZipPackage(path, access); + if (pack.partList == null && access != PackageAccess.WRITE) { + pack.getParts(); + } + pack.originalPackagePath = new File(path).getAbsolutePath(); + return pack; + } + + /** + * Open a package. + * + * Note - uses quite a bit more memory than {@link #open(String)}, which + * doesn't need to hold the whole zip file in memory, and can take advantage + * of native methods + * + * @param in + * The InputStream to read the package from + * @return A PackageBase object + */ + public static OPCPackage open(InputStream in) throws InvalidFormatException, + IOException { + OPCPackage pack = new ZipPackage(in, PackageAccess.READ); + if (pack.partList == null) { + pack.getParts(); + } + return pack; + } + + /** + * Opens a package if it exists, else it creates one. + * + * @param file + * The file to open or to create. + * @return A newly created package if the specified file does not exist, + * else the package extract from the file. + * @throws InvalidFormatException + * Throws if the specified file exist and is not valid. + */ + public static OPCPackage openOrCreate(File file) throws InvalidFormatException { + OPCPackage retPackage = null; + if (file.exists()) { + retPackage = open(file.getAbsolutePath()); + } else { + retPackage = create(file); + } + return retPackage; + } + + /** + * Creates a new package. + * + * @param path + * Path of the document. + * @return A newly created PackageBase ready to use. + */ + public static OPCPackage create(String path) { + return create(new File(path)); + } + + /** + * Creates a new package. + * + * @param file + * Path of the document. + * @return A newly created PackageBase ready to use. + */ + public static OPCPackage create(File file) { + if (file == null || (file.exists() && file.isDirectory())) + throw new IllegalArgumentException("file"); + + if (file.exists()) { + throw new InvalidOperationException( + "This package (or file) already exists : use the open() method or delete the file."); + } + + // Creates a new package + OPCPackage pkg = null; + pkg = new ZipPackage(); + pkg.originalPackagePath = file.getAbsolutePath(); + + configurePackage(pkg); + return pkg; + } + + public static OPCPackage create(OutputStream output) { + OPCPackage pkg = null; + pkg = new ZipPackage(); + pkg.originalPackagePath = null; + pkg.output = output; + + configurePackage(pkg); + return pkg; + } + + /** + * Configure the package. + * + * @param pkg + */ + private static void configurePackage(OPCPackage pkg) { + try { + // Content type manager + pkg.contentTypeManager = new ZipContentTypeManager(null, pkg); + // Add default content types for .xml and .rels + pkg.contentTypeManager + .addContentType( + PackagingURIHelper + .createPartName(PackagingURIHelper.PACKAGE_RELATIONSHIPS_ROOT_URI), + ContentTypes.RELATIONSHIPS_PART); + pkg.contentTypeManager + .addContentType(PackagingURIHelper + .createPartName("/default.xml"), + ContentTypes.PLAIN_OLD_XML); + + // Init some PackageBase properties + pkg.packageProperties = new PackagePropertiesPart(pkg, + PackagingURIHelper.CORE_PROPERTIES_PART_NAME); + pkg.packageProperties.setCreatorProperty("Generated by OpenXML4J"); + pkg.packageProperties.setCreatedProperty(new Nullable( + new Date())); + } catch (InvalidFormatException e) { + // Should never happen + throw new IllegalStateException(e); + } + } + + /** + * Flush the package : save all. + * + * @see #close() + */ + public void flush() { + throwExceptionIfReadOnly(); + + if (this.packageProperties != null) { + this.packageProperties.flush(); + } + + this.flushImpl(); + } + + /** + * Close the package and save its content. + * + * @throws IOException + * If an IO exception occur during the saving process. + */ + public void close() throws IOException { + if (this.packageAccess == PackageAccess.READ) { + logger + .log(POILogger.WARN, "The close() method is intended to SAVE a package. This package is open in READ ONLY mode, use the revert() method instead !"); + return; + } + + // Save the content + ReentrantReadWriteLock l = new ReentrantReadWriteLock(); + try { + l.writeLock().lock(); + if (this.originalPackagePath != null + && !"".equals(this.originalPackagePath.trim())) { + File targetFile = new File(this.originalPackagePath); + if (!targetFile.exists() + || !(this.originalPackagePath + .equalsIgnoreCase(targetFile.getAbsolutePath()))) { + // Case of a package created from scratch + save(targetFile); + } else { + closeImpl(); + } + } else if (this.output != null) { + save(this.output); + } + } finally { + l.writeLock().unlock(); + } + + // Clear + this.contentTypeManager.clearAll(); + + // Call the garbage collector + Runtime.getRuntime().gc(); + } + + /** + * Close the package WITHOUT saving its content. Reinitialize this package + * and cancel all changes done to it. + */ + public void revert() { + revertImpl(); + } + + /** + * Add a thumbnail to the package. This method is provided to make easier + * the addition of a thumbnail in a package. You can do the same work by + * using the traditionnal relationship and part mechanism. + * + * @param path + * The full path to the image file. + */ + public void addThumbnail(String path) throws IOException { + // Check parameter + if ("".equals(path)) + throw new IllegalArgumentException("path"); + + // Get the filename from the path + String filename = path + .substring(path.lastIndexOf(File.separatorChar) + 1); + + // Create the thumbnail part name + String contentType = ContentTypes + .getContentTypeFromFileExtension(filename); + PackagePartName thumbnailPartName = null; + try { + thumbnailPartName = PackagingURIHelper.createPartName("/docProps/" + + filename); + } catch (InvalidFormatException e) { + try { + thumbnailPartName = PackagingURIHelper + .createPartName("/docProps/thumbnail" + + path.substring(path.lastIndexOf(".") + 1)); + } catch (InvalidFormatException e2) { + throw new InvalidOperationException( + "Can't add a thumbnail file named '" + filename + "'"); + } + } + + // Check if part already exist + if (this.getPart(thumbnailPartName) != null) + throw new InvalidOperationException( + "You already add a thumbnail named '" + filename + "'"); + + // Add the thumbnail part to this package. + PackagePart thumbnailPart = this.createPart(thumbnailPartName, + contentType, false); + + // Add the relationship between the package and the thumbnail part + this.addRelationship(thumbnailPartName, TargetMode.INTERNAL, + PackageRelationshipTypes.THUMBNAIL); + + // Copy file data to the newly created part + StreamHelper.copyStream(new FileInputStream(path), thumbnailPart + .getOutputStream()); + } + + /** + * Throws an exception if the package access mode is in read only mode + * (PackageAccess.Read). + * + * @throws InvalidOperationException + * Throws if a writing operation is done on a read only package. + * @see org.apache.poi.openxml4j.opc.PackageAccess + */ + void throwExceptionIfReadOnly() throws InvalidOperationException { + if (packageAccess == PackageAccess.READ) + throw new InvalidOperationException( + "Operation not allowed, document open in read only mode!"); + } + + /** + * Throws an exception if the package access mode is in write only mode + * (PackageAccess.Write). This method is call when other methods need write + * right. + * + * @throws InvalidOperationException + * Throws if a read operation is done on a write only package. + * @see org.apache.poi.openxml4j.opc.PackageAccess + */ + void throwExceptionIfWriteOnly() throws InvalidOperationException { + if (packageAccess == PackageAccess.WRITE) + throw new InvalidOperationException( + "Operation not allowed, document open in write only mode!"); + } + + /** + * Retrieves or creates if none exists, core package property part. + * + * @return The PackageProperties part of this package. + */ + public PackageProperties getPackageProperties() + throws InvalidFormatException { + this.throwExceptionIfWriteOnly(); + // If no properties part has been found then we create one + if (this.packageProperties == null) { + this.packageProperties = new PackagePropertiesPart(this, + PackagingURIHelper.CORE_PROPERTIES_PART_NAME); + } + return this.packageProperties; + } + + /** + * Retrieve a part identified by its name. + * + * @param partName + * Part name of the part to retrieve. + * @return The part with the specified name, else null. + */ + public PackagePart getPart(PackagePartName partName) { + throwExceptionIfWriteOnly(); + + if (partName == null) + throw new IllegalArgumentException("partName"); + + // If the partlist is null, then we parse the package. + if (partList == null) { + try { + getParts(); + } catch (InvalidFormatException e) { + return null; + } + } + return getPartImpl(partName); + } + + /** + * Retrieve parts by content type. + * + * @param contentType + * The content type criteria. + * @return All part associated to the specified content type. + */ + public ArrayList getPartsByContentType(String contentType) { + ArrayList retArr = new ArrayList(); + for (PackagePart part : partList.values()) { + if (part.getContentType().equals(contentType)) + retArr.add(part); + } + return retArr; + } + + /** + * Retrieve parts by relationship type. + * + * @param relationshipType + * Relationship type. + * @return All parts which are the target of a relationship with the + * specified type, if the method can't retrieve relationships from + * the package, then return null. + */ + public ArrayList getPartsByRelationshipType( + String relationshipType) { + if (relationshipType == null) + throw new IllegalArgumentException("relationshipType"); + ArrayList retArr = new ArrayList(); + for (PackageRelationship rel : getRelationshipsByType(relationshipType)) { + retArr.add(getPart(rel)); + } + return retArr; + } + + /** + * Get the target part from the specified relationship. + * + * @param partRel + * The part relationship uses to retrieve the part. + */ + public PackagePart getPart(PackageRelationship partRel) { + PackagePart retPart = null; + ensureRelationships(); + for (PackageRelationship rel : relationships) { + if (rel.getRelationshipType().equals(partRel.getRelationshipType())) { + try { + retPart = getPart(PackagingURIHelper.createPartName(rel + .getTargetURI())); + } catch (InvalidFormatException e) { + continue; + } + break; + } + } + return retPart; + } + + /** + * Load the parts of the archive if it has not been done yet The + * relationships of each part are not loaded + * + * @return All this package's parts. + */ + public ArrayList getParts() throws InvalidFormatException { + throwExceptionIfWriteOnly(); + + // If the part list is null, we parse the package to retrieve all parts. + if (partList == null) { + /* Variables use to validate OPC Compliance */ + + // Ensure rule M4.1 -> A format consumer shall consider more than + // one core properties relationship for a package to be an error + boolean hasCorePropertiesPart = false; + + PackagePart[] parts = this.getPartsImpl(); + this.partList = new PackagePartCollection(); + for (PackagePart part : parts) { + if (partList.containsKey(part.partName)) + throw new InvalidFormatException( + "A part with the name '" + + part.partName + + "' already exist : Packages shall not contain equivalent part names and package implementers shall neither create nor recognize packages with equivalent part names. [M1.12]"); + + // Check OPC compliance rule M4.1 + if (part.getContentType().equals( + ContentTypes.CORE_PROPERTIES_PART)) { + if (!hasCorePropertiesPart) + hasCorePropertiesPart = true; + else + throw new InvalidFormatException( + "OPC Compliance error [M4.1]: there is more than one core properties relationship in the package !"); + } + + PartUnmarshaller partUnmarshaller = partUnmarshallers + .get(part.contentType); + + if (partUnmarshaller != null) { + UnmarshallContext context = new UnmarshallContext(this, + part.partName); + try { + PackagePart unmarshallPart = partUnmarshaller + .unmarshall(context, part.getInputStream()); + partList.put(unmarshallPart.partName, unmarshallPart); + + // Core properties case + if (unmarshallPart instanceof PackagePropertiesPart) + this.packageProperties = (PackagePropertiesPart) unmarshallPart; + } catch (IOException ioe) { + logger.log(POILogger.WARN, "Unmarshall operation : IOException for " + + part.partName); + continue; + } catch (InvalidOperationException invoe) { + throw new InvalidFormatException(invoe.getMessage()); + } + } else { + try { + partList.put(part.partName, part); + } catch (InvalidOperationException e) { + throw new InvalidFormatException(e.getMessage()); + } + } + } + } + return new ArrayList(partList.values()); + } + + /** + * Create and add a part, with the specified name and content type, to the + * package. + * + * @param partName + * Part name. + * @param contentType + * Part content type. + * @return The newly created part. + * @throws InvalidFormatException + * If rule M1.12 is not verified : Packages shall not contain + * equivalent part names and package implementers shall neither + * create nor recognize packages with equivalent part names. + * @see #createPartImpl(PackagePartName, String, boolean) + */ + public PackagePart createPart(PackagePartName partName, String contentType) { + return this.createPart(partName, contentType, true); + } + + /** + * Create and add a part, with the specified name and content type, to the + * package. For general purpose, prefer the overload version of this method + * without the 'loadRelationships' parameter. + * + * @param partName + * Part name. + * @param contentType + * Part content type. + * @param loadRelationships + * Specify if the existing relationship part, if any, logically + * associated to the newly created part will be loaded. + * @return The newly created part. + * @throws InvalidFormatException + * If rule M1.12 is not verified : Packages shall not contain + * equivalent part names and package implementers shall neither + * create nor recognize packages with equivalent part names. + * @see {@link#createPartImpl(URI, String)} + */ + PackagePart createPart(PackagePartName partName, String contentType, + boolean loadRelationships) { + throwExceptionIfReadOnly(); + if (partName == null) { + throw new IllegalArgumentException("partName"); + } + + if (contentType == null || contentType == "") { + throw new IllegalArgumentException("contentType"); + } + + // Check if the specified part name already exists + if (partList.containsKey(partName) + && !partList.get(partName).isDeleted()) { + throw new InvalidOperationException( + "A part with the name '" + + partName.getName() + + "' already exists : Packages shall not contain equivalent part names and package implementers shall neither create nor recognize packages with equivalent part names. [M1.12]"); + } + + /* Check OPC compliance */ + + // Rule [M4.1]: The format designer shall specify and the format + // producer + // shall create at most one core properties relationship for a package. + // A format consumer shall consider more than one core properties + // relationship for a package to be an error. If present, the + // relationship shall target the Core Properties part. + if (contentType == ContentTypes.CORE_PROPERTIES_PART) { + if (this.packageProperties != null) + throw new InvalidOperationException( + "OPC Compliance error [M4.1]: you try to add more than one core properties relationship in the package !"); + } + + /* End check OPC compliance */ + + PackagePart part = this.createPartImpl(partName, contentType, + loadRelationships); + this.contentTypeManager.addContentType(partName, contentType); + this.partList.put(partName, part); + this.isDirty = true; + return part; + } + + /** + * Add a part to the package. + * + * @param partName + * Part name of the part to create. + * @param contentType + * type associated with the file + * @param content + * the contents to add. In order to have faster operation in + * document merge, the data are stored in memory not on a hard + * disk + * + * @return The new part. + * @see #createPart(PackagePartName, String) + */ + public PackagePart createPart(PackagePartName partName, String contentType, + ByteArrayOutputStream content) { + PackagePart addedPart = this.createPart(partName, contentType); + if (addedPart == null) { + return null; + } + // Extract the zip entry content to put it in the part content + if (content != null) { + try { + OutputStream partOutput = addedPart.getOutputStream(); + if (partOutput == null) { + return null; + } + + partOutput.write(content.toByteArray(), 0, content.size()); + partOutput.close(); + + } catch (IOException ioe) { + return null; + } + } else { + return null; + } + return addedPart; + } + + /** + * Add the specified part to the package. If a part already exists in the + * package with the same name as the one specified, then we replace the old + * part by the specified part. + * + * @param part + * The part to add (or replace). + * @return The part added to the package, the same as the one specified. + * @throws InvalidFormatException + * If rule M1.12 is not verified : Packages shall not contain + * equivalent part names and package implementers shall neither + * create nor recognize packages with equivalent part names. + */ + protected PackagePart addPackagePart(PackagePart part) { + throwExceptionIfReadOnly(); + if (part == null) { + throw new IllegalArgumentException("part"); + } + + if (partList.containsKey(part.partName)) { + if (!partList.get(part.partName).isDeleted()) { + throw new InvalidOperationException( + "A part with the name '" + + part.partName.getName() + + "' already exists : Packages shall not contain equivalent part names and package implementers shall neither create nor recognize packages with equivalent part names. [M1.12]"); + } + // If the specified partis flagged as deleted, we make it + // available + part.setDeleted(false); + // and delete the old part to replace it thereafeter + this.partList.remove(part.partName); + } + this.partList.put(part.partName, part); + this.isDirty = true; + return part; + } + + /** + * Remove the specified part in this package. If this part is relationship + * part, then delete all relationships in the source part. + * + * @param part + * The part to remove. If null, skip the action. + * @see #removePart(PackagePartName) + */ + public void removePart(PackagePart part) { + if (part != null) { + removePart(part.getPartName()); + } + } + + /** + * Remove a part in this package. If this part is relationship part, then + * delete all relationships in the source part. + * + * @param partName + * The part name of the part to remove. + */ + public void removePart(PackagePartName partName) { + throwExceptionIfReadOnly(); + if (partName == null || !this.containPart(partName)) + throw new IllegalArgumentException("partName"); + + // Delete the specified part from the package. + if (this.partList.containsKey(partName)) { + this.partList.get(partName).setDeleted(true); + this.removePartImpl(partName); + this.partList.remove(partName); + } else { + this.removePartImpl(partName); + } + + // Delete content type + this.contentTypeManager.removeContentType(partName); + + // If this part is a relationship part, then delete all relationships of + // the source part. + if (partName.isRelationshipPartURI()) { + URI sourceURI = PackagingURIHelper + .getSourcePartUriFromRelationshipPartUri(partName.getURI()); + PackagePartName sourcePartName; + try { + sourcePartName = PackagingURIHelper.createPartName(sourceURI); + } catch (InvalidFormatException e) { + logger + .log(POILogger.ERROR, "Part name URI '" + + sourceURI + + "' is not valid ! This message is not intended to be displayed !"); + return; + } + if (sourcePartName.getURI().equals( + PackagingURIHelper.PACKAGE_ROOT_URI)) { + clearRelationships(); + } else if (containPart(sourcePartName)) { + PackagePart part = getPart(sourcePartName); + if (part != null) + part.clearRelationships(); + } + } + + this.isDirty = true; + } + + /** + * Remove a part from this package as well as its relationship part, if one + * exists, and all parts listed in the relationship part. Be aware that this + * do not delete relationships which target the specified part. + * + * @param partName + * The name of the part to delete. + * @throws InvalidFormatException + * Throws if the associated relationship part of the specified + * part is not valid. + */ + public void removePartRecursive(PackagePartName partName) + throws InvalidFormatException { + // Retrieves relationship part, if one exists + PackagePart relPart = this.partList.get(PackagingURIHelper + .getRelationshipPartName(partName)); + // Retrieves PackagePart object from the package + PackagePart partToRemove = this.partList.get(partName); + + if (relPart != null) { + PackageRelationshipCollection partRels = new PackageRelationshipCollection( + partToRemove); + for (PackageRelationship rel : partRels) { + PackagePartName partNameToRemove = PackagingURIHelper + .createPartName(PackagingURIHelper.resolvePartUri(rel + .getSourceURI(), rel.getTargetURI())); + removePart(partNameToRemove); + } + + // Finally delete its relationship part if one exists + this.removePart(relPart.partName); + } + + // Delete the specified part + this.removePart(partToRemove.partName); + } + + /** + * Delete the part with the specified name and its associated relationships + * part if one exists. Prefer the use of this method to delete a part in the + * package, compare to the remove() methods that don't remove associated + * relationships part. + * + * @param partName + * Name of the part to delete + */ + public void deletePart(PackagePartName partName) { + if (partName == null) + throw new IllegalArgumentException("partName"); + + // Remove the part + this.removePart(partName); + // Remove the relationships part + this.removePart(PackagingURIHelper.getRelationshipPartName(partName)); + } + + /** + * Delete the part with the specified name and all part listed in its + * associated relationships part if one exists. This process is recursively + * apply to all parts in the relationships part of the specified part. + * Prefer the use of this method to delete a part in the package, compare to + * the remove() methods that don't remove associated relationships part. + * + * @param partName + * Name of the part to delete + */ + public void deletePartRecursive(PackagePartName partName) { + if (partName == null || !this.containPart(partName)) + throw new IllegalArgumentException("partName"); + + PackagePart partToDelete = this.getPart(partName); + // Remove the part + this.removePart(partName); + // Remove all relationship parts associated + try { + for (PackageRelationship relationship : partToDelete + .getRelationships()) { + PackagePartName targetPartName = PackagingURIHelper + .createPartName(PackagingURIHelper.resolvePartUri( + partName.getURI(), relationship.getTargetURI())); + this.deletePartRecursive(targetPartName); + } + } catch (InvalidFormatException e) { + logger.log(POILogger.WARN, "An exception occurs while deleting part '" + + partName.getName() + + "'. Some parts may remain in the package. - " + + e.getMessage()); + return; + } + // Remove the relationships part + PackagePartName relationshipPartName = PackagingURIHelper + .getRelationshipPartName(partName); + if (relationshipPartName != null && containPart(relationshipPartName)) + this.removePart(relationshipPartName); + } + + /** + * Check if a part already exists in this package from its name. + * + * @param partName + * Part name to check. + * @return true if the part is logically added to this package, else + * false. + */ + public boolean containPart(PackagePartName partName) { + return (this.getPart(partName) != null); + } + + /** + * Add a relationship to the package (except relationships part). + * + * Check rule M4.1 : The format designer shall specify and the format + * producer shall create at most one core properties relationship for a + * package. A format consumer shall consider more than one core properties + * relationship for a package to be an error. If present, the relationship + * shall target the Core Properties 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 + * Target part name. + * @param targetMode + * Target mode, either Internal or External. + * @param relationshipType + * Relationship type. + * @param relID + * ID of the relationship. + * @see PackageRelationshipTypes + */ + public PackageRelationship addRelationship(PackagePartName targetPartName, + TargetMode targetMode, String relationshipType, String relID) { + /* Check OPC compliance */ + + // Check rule M4.1 : The format designer shall specify and the format + // producer + // shall create at most one core properties relationship for a package. + // A format consumer shall consider more than one core properties + // relationship for a package to be an error. If present, the + // relationship shall target the Core Properties part. + if (relationshipType.equals(PackageRelationshipTypes.CORE_PROPERTIES) + && this.packageProperties != null) + throw new InvalidOperationException( + "OPC Compliance error [M4.1]: can't add another core properties part ! Use the built-in package method instead."); + + /* + * 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. + */ + if (targetPartName.isRelationshipPartURI()) { + throw new InvalidOperationException( + "Rule M1.25: The Relationships part shall not have relationships to any other part."); + } + + /* End OPC compliance */ + + ensureRelationships(); + PackageRelationship retRel = relationships.addRelationship( + targetPartName.getURI(), targetMode, relationshipType, relID); + this.isDirty = true; + return retRel; + } + + /** + * Add a package relationship. + * + * @param targetPartName + * Target part name. + * @param targetMode + * Target mode, either Internal or External. + * @param relationshipType + * Relationship type. + * @see PackageRelationshipTypes + */ + public PackageRelationship addRelationship(PackagePartName targetPartName, + TargetMode targetMode, String relationshipType) { + return this.addRelationship(targetPartName, targetMode, + 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. + * @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"); + } + + URI targetURI; + try { + targetURI = new URI(target); + } catch (URISyntaxException e) { + throw new IllegalArgumentException("Invalid target - " + e); + } + + ensureRelationships(); + PackageRelationship retRel = relationships.addRelationship(targetURI, + TargetMode.EXTERNAL, relationshipType, id); + this.isDirty = true; + return retRel; + } + + /** + * Delete a relationship from this package. + * + * @param id + * Id of the relationship to delete. + */ + public void removeRelationship(String id) { + if (relationships != null) { + relationships.removeRelationship(id); + this.isDirty = true; + } + } + + /** + * Retrieves all package relationships. + * + * @return All package relationships of this package. + * @throws OpenXML4JException + * @see #getRelationshipsHelper(String) + */ + public PackageRelationshipCollection getRelationships() { + return getRelationshipsHelper(null); + } + + /** + * Retrieves all relationships with the specified type. + * + * @param relationshipType + * The filter specifying the relationship type. + * @return All relationships with the specified relationship type. + */ + public PackageRelationshipCollection getRelationshipsByType( + String relationshipType) { + throwExceptionIfWriteOnly(); + if (relationshipType == null) { + throw new IllegalArgumentException("relationshipType"); + } + return getRelationshipsHelper(relationshipType); + } + + /** + * Retrieves all relationships with specified id (normally just ine because + * a relationship id is supposed to be unique). + * + * @param id + * Id of the wanted relationship. + */ + private PackageRelationshipCollection getRelationshipsHelper(String id) { + throwExceptionIfWriteOnly(); + ensureRelationships(); + return this.relationships.getRelationships(id); + } + + /** + * Clear package relationships. + */ + public void clearRelationships() { + if (relationships != null) { + relationships.clear(); + this.isDirty = true; + } + } + + /** + * Ensure that the relationships collection is not null. + */ + public void ensureRelationships() { + if (this.relationships == null) { + try { + this.relationships = new PackageRelationshipCollection(this); + } catch (InvalidFormatException e) { + this.relationships = new PackageRelationshipCollection(); + } + } + } + + /** + * @see org.apache.poi.openxml4j.opc.RelationshipSource#getRelationship(java.lang.String) + */ + public PackageRelationship getRelationship(String id) { + return this.relationships.getRelationshipByID(id); + } + + /** + * @see org.apache.poi.openxml4j.opc.RelationshipSource#hasRelationships() + */ + public boolean hasRelationships() { + return (relationships.size() > 0); + } + + /** + * @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; + } + } + + /** + * Add a marshaller. + * + * @param contentType + * The content type to bind to the specified marshaller. + * @param marshaller + * The marshaller to register with the specified content type. + */ + public void addMarshaller(String contentType, PartMarshaller marshaller) { + try { + partMarshallers.put(new ContentType(contentType), marshaller); + } catch (InvalidFormatException e) { + logger.log(POILogger.WARN, "The specified content type is not valid: '" + + e.getMessage() + "'. The marshaller will not be added !"); + } + } + + /** + * Add an unmarshaller. + * + * @param contentType + * The content type to bind to the specified unmarshaller. + * @param unmarshaller + * The unmarshaller to register with the specified content type. + */ + public void addUnmarshaller(String contentType, + PartUnmarshaller unmarshaller) { + try { + partUnmarshallers.put(new ContentType(contentType), unmarshaller); + } catch (InvalidFormatException e) { + logger.log(POILogger.WARN, "The specified content type is not valid: '" + + e.getMessage() + + "'. The unmarshaller will not be added !"); + } + } + + /** + * Remove a marshaller by its content type. + * + * @param contentType + * The content type associated with the marshaller to remove. + */ + public void removeMarshaller(String contentType) { + partMarshallers.remove(contentType); + } + + /** + * Remove an unmarshaller by its content type. + * + * @param contentType + * The content type associated with the unmarshaller to remove. + */ + public void removeUnmarshaller(String contentType) { + partUnmarshallers.remove(contentType); + } + + /* Accesseurs */ + + /** + * Get the package access mode. + * + * @return the packageAccess The current package access. + */ + public PackageAccess getPackageAccess() { + return packageAccess; + } + + /** + * Validates the package compliance with the OPC specifications. + * + * @return true if the package is valid else false + */ + public boolean validatePackage(OPCPackage pkg) throws InvalidFormatException { + throw new InvalidOperationException("Not implemented yet !!!"); + } + + /** + * Save the document in the specified file. + * + * @param targetFile + * Destination file. + * @throws IOException + * Throws if an IO exception occur. + * @see #save(OutputStream) + */ + public void save(File targetFile) throws IOException { + if (targetFile == null) + throw new IllegalArgumentException("targetFile"); + + this.throwExceptionIfReadOnly(); + FileOutputStream fos = null; + try { + fos = new FileOutputStream(targetFile); + } catch (FileNotFoundException e) { + throw new IOException(e.getLocalizedMessage()); + } + this.save(fos); + } + + /** + * Save the document in the specified output stream. + * + * @param outputStream + * The stream to save the package. + * @see #saveImpl(OutputStream) + */ + public void save(OutputStream outputStream) throws IOException { + throwExceptionIfReadOnly(); + this.saveImpl(outputStream); + } + + /** + * Core method to create a package part. This method must be implemented by + * the subclass. + * + * @param partName + * URI of the part to create. + * @param contentType + * Content type of the part to create. + * @return The newly created package part. + */ + protected abstract PackagePart createPartImpl(PackagePartName partName, + String contentType, boolean loadRelationships); + + /** + * Core method to delete a package part. This method must be implemented by + * the subclass. + * + * @param partName + * The URI of the part to delete. + */ + protected abstract void removePartImpl(PackagePartName partName); + + /** + * Flush the package but not save. + */ + protected abstract void flushImpl(); + + /** + * Close the package and cause a save of the package. + * + */ + protected abstract void closeImpl() throws IOException; + + /** + * Close the package without saving the document. Discard all changes made + * to this package. + */ + protected abstract void revertImpl(); + + /** + * Save the package into the specified output stream. + * + * @param outputStream + * The output stream use to save this package. + */ + protected abstract void saveImpl(OutputStream outputStream) + throws IOException; + + /** + * Get the package part mapped to the specified URI. + * + * @param partName + * The URI of the part to retrieve. + * @return The package part located by the specified URI, else null. + */ + protected abstract PackagePart getPartImpl(PackagePartName partName); + + /** + * Get all parts link to the package. + * + * @return A list of the part owned by the package. + */ + protected abstract PackagePart[] getPartsImpl() + throws InvalidFormatException; +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/Package.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/Package.java index 918337178f..0a41045614 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/Package.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/Package.java @@ -1,1397 +1,179 @@ -/* ==================================================================== - 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.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Date; -import java.util.Hashtable; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -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.exceptions.OpenXML4JRuntimeException; -import org.apache.poi.openxml4j.opc.internal.ContentType; -import org.apache.poi.openxml4j.opc.internal.ContentTypeManager; -import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart; -import org.apache.poi.openxml4j.opc.internal.PartMarshaller; -import org.apache.poi.openxml4j.opc.internal.PartUnmarshaller; -import org.apache.poi.openxml4j.opc.internal.ZipContentTypeManager; -import org.apache.poi.openxml4j.opc.internal.marshallers.DefaultMarshaller; -import org.apache.poi.openxml4j.opc.internal.marshallers.ZipPackagePropertiesMarshaller; -import org.apache.poi.openxml4j.opc.internal.unmarshallers.PackagePropertiesUnmarshaller; -import org.apache.poi.openxml4j.opc.internal.unmarshallers.UnmarshallContext; -import org.apache.poi.openxml4j.util.Nullable; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.POILogFactory; - -/** - * Represents a container that can store multiple data objects. - * - * @author Julien Chable, CDubet - * @version 0.1 - */ -public abstract class Package implements RelationshipSource { - - /** - * Logger. - */ - private static POILogger logger = POILogFactory.getLogger(Package.class); - - /** - * Default package access. - */ - protected static final PackageAccess defaultPackageAccess = PackageAccess.READ_WRITE; - - /** - * Package access. - */ - private PackageAccess packageAccess; - - /** - * Package parts collection. - */ - protected PackagePartCollection partList; - - /** - * Package relationships. - */ - protected PackageRelationshipCollection relationships; - - /** - * Part marshallers by content type. - */ - protected Hashtable partMarshallers; - - /** - * Default part marshaller. - */ - protected PartMarshaller defaultPartMarshaller; - - /** - * Part unmarshallers by content type. - */ - protected Hashtable partUnmarshallers; - - /** - * Core package properties. - */ - protected PackagePropertiesPart packageProperties; - - /** - * Manage parts content types of this package. - */ - protected ContentTypeManager contentTypeManager; - - /** - * Flag if a modification is done to the document. - */ - protected boolean isDirty = false; - - /** - * File path of this package. - */ - protected String originalPackagePath; - - /** - * Output stream for writing this package. - */ - protected OutputStream output; - - /** - * Constructor. - * - * @param access - * Package access. - */ - protected Package(PackageAccess access) { - init(); - this.packageAccess = access; - } - - /** - * Initialize the package instance. - */ - private void init() { - this.partMarshallers = new Hashtable(5); - this.partUnmarshallers = new Hashtable(2); - - try { - // Add 'default' unmarshaller - this.partUnmarshallers.put(new ContentType( - ContentTypes.CORE_PROPERTIES_PART), - new PackagePropertiesUnmarshaller()); - - // Add default marshaller - this.defaultPartMarshaller = new DefaultMarshaller(); - // TODO Delocalize specialized marshallers - this.partMarshallers.put(new ContentType( - ContentTypes.CORE_PROPERTIES_PART), - new ZipPackagePropertiesMarshaller()); - } catch (InvalidFormatException e) { - // Should never happpen - throw new OpenXML4JRuntimeException( - "Package.init() : this exception should never happen, if you read this message please send a mail to the developers team."); - } - } - - /** - * Open a package with read/write permission. - * - * @param path - * The document path. - * @return A Package object, else null. - * @throws InvalidFormatException - * If the specified file doesn't exist, and a parsing error - * occur. - */ - public static Package open(String path) throws InvalidFormatException { - return open(path, defaultPackageAccess); - } - - /** - * Open a package. - * - * @param path - * The document path. - * @param access - * Package access. - * @return A Package object, else null. - * @throws InvalidFormatException - * If the specified file doesn't exist, and a parsing error - * occur. - */ - public static Package open(String path, PackageAccess access) - throws InvalidFormatException { - if (path == null || "".equals(path.trim()) - || (new File(path).exists() && new File(path).isDirectory())) - throw new IllegalArgumentException("path"); - - Package pack = new ZipPackage(path, access); - if (pack.partList == null && access != PackageAccess.WRITE) { - pack.getParts(); - } - pack.originalPackagePath = new File(path).getAbsolutePath(); - return pack; - } - - /** - * Open a package. - * - * Note - uses quite a bit more memory than {@link #open(String)}, which - * doesn't need to hold the whole zip file in memory, and can take advantage - * of native methods - * - * @param in - * The InputStream to read the package from - * @return A Package object - */ - public static Package open(InputStream in) throws InvalidFormatException, - IOException { - Package pack = new ZipPackage(in, PackageAccess.READ); - if (pack.partList == null) { - pack.getParts(); - } - return pack; - } - - /** - * Opens a package if it exists, else it creates one. - * - * @param file - * The file to open or to create. - * @return A newly created package if the specified file does not exist, - * else the package extract from the file. - * @throws InvalidFormatException - * Throws if the specified file exist and is not valid. - */ - public static Package openOrCreate(File file) throws InvalidFormatException { - Package retPackage = null; - if (file.exists()) { - retPackage = open(file.getAbsolutePath()); - } else { - retPackage = create(file); - } - return retPackage; - } - - /** - * Creates a new package. - * - * @param path - * Path of the document. - * @return A newly created Package ready to use. - */ - public static Package create(String path) { - return create(new File(path)); - } - - /** - * Creates a new package. - * - * @param file - * Path of the document. - * @return A newly created Package ready to use. - */ - public static Package create(File file) { - if (file == null || (file.exists() && file.isDirectory())) - throw new IllegalArgumentException("file"); - - if (file.exists()) { - throw new InvalidOperationException( - "This package (or file) already exists : use the open() method or delete the file."); - } - - // Creates a new package - Package pkg = null; - pkg = new ZipPackage(); - pkg.originalPackagePath = file.getAbsolutePath(); - - configurePackage(pkg); - return pkg; - } - - public static Package create(OutputStream output) { - Package pkg = null; - pkg = new ZipPackage(); - pkg.originalPackagePath = null; - pkg.output = output; - - configurePackage(pkg); - return pkg; - } - - /** - * Configure the package. - * - * @param pkg - */ - private static void configurePackage(Package pkg) { - try { - // Content type manager - pkg.contentTypeManager = new ZipContentTypeManager(null, pkg); - // Add default content types for .xml and .rels - pkg.contentTypeManager - .addContentType( - PackagingURIHelper - .createPartName(PackagingURIHelper.PACKAGE_RELATIONSHIPS_ROOT_URI), - ContentTypes.RELATIONSHIPS_PART); - pkg.contentTypeManager - .addContentType(PackagingURIHelper - .createPartName("/default.xml"), - ContentTypes.PLAIN_OLD_XML); - - // Init some Package properties - pkg.packageProperties = new PackagePropertiesPart(pkg, - PackagingURIHelper.CORE_PROPERTIES_PART_NAME); - pkg.packageProperties.setCreatorProperty("Generated by OpenXML4J"); - pkg.packageProperties.setCreatedProperty(new Nullable( - new Date())); - } catch (InvalidFormatException e) { - // Should never happen - throw new IllegalStateException(e); - } - } - - /** - * Flush the package : save all. - * - * @see #close() - */ - public void flush() { - throwExceptionIfReadOnly(); - - if (this.packageProperties != null) - ((PackagePropertiesPart) this.packageProperties).flush(); - - this.flushImpl(); - } - - /** - * Close the package and save its content. - * - * @throws IOException - * If an IO exception occur during the saving process. - */ - public void close() throws IOException { - if (this.packageAccess == PackageAccess.READ) { - logger - .log(POILogger.WARN, "The close() method is intended to SAVE a package. This package is open in READ ONLY mode, use the revert() method instead !"); - return; - } - - // Save the content - ReentrantReadWriteLock l = new ReentrantReadWriteLock(); - try { - l.writeLock().lock(); - if (this.originalPackagePath != null - && !"".equals(this.originalPackagePath.trim())) { - File targetFile = new File(this.originalPackagePath); - if (!targetFile.exists() - || !(this.originalPackagePath - .equalsIgnoreCase(targetFile.getAbsolutePath()))) { - // Case of a package created from scratch - save(targetFile); - } else { - closeImpl(); - } - } else if (this.output != null) { - save(this.output); - } - } finally { - l.writeLock().unlock(); - } - - // Clear - this.contentTypeManager.clearAll(); - - // Call the garbage collector - Runtime.getRuntime().gc(); - } - - /** - * Close the package WITHOUT saving its content. Reinitialize this package - * and cancel all changes done to it. - */ - public void revert() { - revertImpl(); - } - - /** - * Add a thumbnail to the package. This method is provided to make easier - * the addition of a thumbnail in a package. You can do the same work by - * using the traditionnal relationship and part mechanism. - * - * @param path - * The full path to the image file. - */ - public void addThumbnail(String path) throws IOException { - // Check parameter - if ("".equals(path)) - throw new IllegalArgumentException("path"); - - // Get the filename from the path - String filename = path - .substring(path.lastIndexOf(File.separatorChar) + 1); - - // Create the thumbnail part name - String contentType = ContentTypes - .getContentTypeFromFileExtension(filename); - PackagePartName thumbnailPartName = null; - try { - thumbnailPartName = PackagingURIHelper.createPartName("/docProps/" - + filename); - } catch (InvalidFormatException e) { - try { - thumbnailPartName = PackagingURIHelper - .createPartName("/docProps/thumbnail" - + path.substring(path.lastIndexOf(".") + 1)); - } catch (InvalidFormatException e2) { - throw new InvalidOperationException( - "Can't add a thumbnail file named '" + filename + "'"); - } - } - - // Check if part already exist - if (this.getPart(thumbnailPartName) != null) - throw new InvalidOperationException( - "You already add a thumbnail named '" + filename + "'"); - - // Add the thumbnail part to this package. - PackagePart thumbnailPart = this.createPart(thumbnailPartName, - contentType, false); - - // Add the relationship between the package and the thumbnail part - this.addRelationship(thumbnailPartName, TargetMode.INTERNAL, - PackageRelationshipTypes.THUMBNAIL); - - // Copy file data to the newly created part - StreamHelper.copyStream(new FileInputStream(path), thumbnailPart - .getOutputStream()); - } - - /** - * Throws an exception if the package access mode is in read only mode - * (PackageAccess.Read). - * - * @throws InvalidOperationException - * Throws if a writing operation is done on a read only package. - * @see org.apache.poi.openxml4j.opc.PackageAccess - */ - void throwExceptionIfReadOnly() throws InvalidOperationException { - if (packageAccess == PackageAccess.READ) - throw new InvalidOperationException( - "Operation not allowed, document open in read only mode!"); - } - - /** - * Throws an exception if the package access mode is in write only mode - * (PackageAccess.Write). This method is call when other methods need write - * right. - * - * @throws InvalidOperationException - * Throws if a read operation is done on a write only package. - * @see org.apache.poi.openxml4j.opc.PackageAccess - */ - void throwExceptionIfWriteOnly() throws InvalidOperationException { - if (packageAccess == PackageAccess.WRITE) - throw new InvalidOperationException( - "Operation not allowed, document open in write only mode!"); - } - - /** - * Retrieves or creates if none exists, core package property part. - * - * @return The PackageProperties part of this package. - */ - public PackageProperties getPackageProperties() - throws InvalidFormatException { - this.throwExceptionIfWriteOnly(); - // If no properties part has been found then we create one - if (this.packageProperties == null) { - this.packageProperties = new PackagePropertiesPart(this, - PackagingURIHelper.CORE_PROPERTIES_PART_NAME); - } - return this.packageProperties; - } - - /** - * Retrieve a part identified by its name. - * - * @param partName - * Part name of the part to retrieve. - * @return The part with the specified name, else null. - */ - public PackagePart getPart(PackagePartName partName) { - throwExceptionIfWriteOnly(); - - if (partName == null) - throw new IllegalArgumentException("partName"); - - // If the partlist is null, then we parse the package. - if (partList == null) { - try { - getParts(); - } catch (InvalidFormatException e) { - return null; - } - } - return getPartImpl(partName); - } - - /** - * Retrieve parts by content type. - * - * @param contentType - * The content type criteria. - * @return All part associated to the specified content type. - */ - public ArrayList getPartsByContentType(String contentType) { - ArrayList retArr = new ArrayList(); - for (PackagePart part : partList.values()) { - if (part.getContentType().equals(contentType)) - retArr.add(part); - } - return retArr; - } - - /** - * Retrieve parts by relationship type. - * - * @param relationshipType - * Relationship type. - * @return All parts which are the target of a relationship with the - * specified type, if the method can't retrieve relationships from - * the package, then return null. - */ - public ArrayList getPartsByRelationshipType( - String relationshipType) { - if (relationshipType == null) - throw new IllegalArgumentException("relationshipType"); - ArrayList retArr = new ArrayList(); - try { - for (PackageRelationship rel : getRelationshipsByType(relationshipType)) { - retArr.add(getPart(rel)); - } - } catch (OpenXML4JException e) { - logger - .log(POILogger.WARN, "Can't retrieve parts by relationship type: an exception has been thrown by getRelationshipsByType method"); - return null; - } - return retArr; - } - - /** - * Get the target part from the specified relationship. - * - * @param partRel - * The part relationship uses to retrieve the part. - */ - public PackagePart getPart(PackageRelationship partRel) { - PackagePart retPart = null; - ensureRelationships(); - for (PackageRelationship rel : relationships) { - if (rel.getRelationshipType().equals(partRel.getRelationshipType())) { - try { - retPart = getPart(PackagingURIHelper.createPartName(rel - .getTargetURI())); - } catch (InvalidFormatException e) { - continue; - } - break; - } - } - return retPart; - } - - /** - * Load the parts of the archive if it has not been done yet The - * relationships of each part are not loaded - * - * @return All this package's parts. - */ - public ArrayList getParts() throws InvalidFormatException { - throwExceptionIfWriteOnly(); - - // If the part list is null, we parse the package to retrieve all parts. - if (partList == null) { - /* Variables use to validate OPC Compliance */ - - // Ensure rule M4.1 -> A format consumer shall consider more than - // one core properties relationship for a package to be an error - boolean hasCorePropertiesPart = false; - - PackagePart[] parts = this.getPartsImpl(); - this.partList = new PackagePartCollection(); - for (PackagePart part : parts) { - if (partList.containsKey(part.partName)) - throw new InvalidFormatException( - "A part with the name '" - + part.partName - + "' already exist : Packages shall not contain equivalent part names and package implementers shall neither create nor recognize packages with equivalent part names. [M1.12]"); - - // Check OPC compliance rule M4.1 - if (part.getContentType().equals( - ContentTypes.CORE_PROPERTIES_PART)) { - if (!hasCorePropertiesPart) - hasCorePropertiesPart = true; - else - throw new InvalidFormatException( - "OPC Compliance error [M4.1]: there is more than one core properties relationship in the package !"); - } - - PartUnmarshaller partUnmarshaller = partUnmarshallers - .get(part.contentType); - - if (partUnmarshaller != null) { - UnmarshallContext context = new UnmarshallContext(this, - part.partName); - try { - PackagePart unmarshallPart = partUnmarshaller - .unmarshall(context, part.getInputStream()); - partList.put(unmarshallPart.partName, unmarshallPart); - - // Core properties case - if (unmarshallPart instanceof PackagePropertiesPart) - this.packageProperties = (PackagePropertiesPart) unmarshallPart; - } catch (IOException ioe) { - logger.log(POILogger.WARN, "Unmarshall operation : IOException for " - + part.partName); - continue; - } catch (InvalidOperationException invoe) { - throw new InvalidFormatException(invoe.getMessage()); - } - } else { - try { - partList.put(part.partName, part); - } catch (InvalidOperationException e) { - throw new InvalidFormatException(e.getMessage()); - } - } - } - } - return new ArrayList(partList.values()); - } - - /** - * Create and add a part, with the specified name and content type, to the - * package. - * - * @param partName - * Part name. - * @param contentType - * Part content type. - * @return The newly created part. - * @throws InvalidFormatException - * If rule M1.12 is not verified : Packages shall not contain - * equivalent part names and package implementers shall neither - * create nor recognize packages with equivalent part names. - * @see #createPartImpl(PackagePartName, String, boolean) - */ - public PackagePart createPart(PackagePartName partName, String contentType) { - return this.createPart(partName, contentType, true); - } - - /** - * Create and add a part, with the specified name and content type, to the - * package. For general purpose, prefer the overload version of this method - * without the 'loadRelationships' parameter. - * - * @param partName - * Part name. - * @param contentType - * Part content type. - * @param loadRelationships - * Specify if the existing relationship part, if any, logically - * associated to the newly created part will be loaded. - * @return The newly created part. - * @throws InvalidFormatException - * If rule M1.12 is not verified : Packages shall not contain - * equivalent part names and package implementers shall neither - * create nor recognize packages with equivalent part names. - * @see {@link#createPartImpl(URI, String)} - */ - PackagePart createPart(PackagePartName partName, String contentType, - boolean loadRelationships) { - throwExceptionIfReadOnly(); - if (partName == null) { - throw new IllegalArgumentException("partName"); - } - - if (contentType == null || contentType == "") { - throw new IllegalArgumentException("contentType"); - } - - // Check if the specified part name already exists - if (partList.containsKey(partName) - && !partList.get(partName).isDeleted()) { - throw new InvalidOperationException( - "A part with the name '" - + partName.getName() - + "' already exists : Packages shall not contain equivalent part names and package implementers shall neither create nor recognize packages with equivalent part names. [M1.12]"); - } - - /* Check OPC compliance */ - - // Rule [M4.1]: The format designer shall specify and the format - // producer - // shall create at most one core properties relationship for a package. - // A format consumer shall consider more than one core properties - // relationship for a package to be an error. If present, the - // relationship shall target the Core Properties part. - if (contentType == ContentTypes.CORE_PROPERTIES_PART) { - if (this.packageProperties != null) - throw new InvalidOperationException( - "OPC Compliance error [M4.1]: you try to add more than one core properties relationship in the package !"); - } - - /* End check OPC compliance */ - - PackagePart part = this.createPartImpl(partName, contentType, - loadRelationships); - this.contentTypeManager.addContentType(partName, contentType); - this.partList.put(partName, part); - this.isDirty = true; - return part; - } - - /** - * Add a part to the package. - * - * @param partName - * Part name of the part to create. - * @param contentType - * type associated with the file - * @param content - * the contents to add. In order to have faster operation in - * document merge, the data are stored in memory not on a hard - * disk - * - * @return The new part. - * @see #createPart(PackagePartName, String) - */ - public PackagePart createPart(PackagePartName partName, String contentType, - ByteArrayOutputStream content) { - PackagePart addedPart = this.createPart(partName, contentType); - if (addedPart == null) { - return null; - } - // Extract the zip entry content to put it in the part content - if (content != null) { - try { - OutputStream partOutput = addedPart.getOutputStream(); - if (partOutput == null) { - return null; - } - - partOutput.write(content.toByteArray(), 0, content.size()); - partOutput.close(); - - } catch (IOException ioe) { - return null; - } - } else { - return null; - } - return addedPart; - } - - /** - * Add the specified part to the package. If a part already exists in the - * package with the same name as the one specified, then we replace the old - * part by the specified part. - * - * @param part - * The part to add (or replace). - * @return The part added to the package, the same as the one specified. - * @throws InvalidFormatException - * If rule M1.12 is not verified : Packages shall not contain - * equivalent part names and package implementers shall neither - * create nor recognize packages with equivalent part names. - */ - protected PackagePart addPackagePart(PackagePart part) { - throwExceptionIfReadOnly(); - if (part == null) { - throw new IllegalArgumentException("part"); - } - - if (partList.containsKey(part.partName)) { - if (!partList.get(part.partName).isDeleted()) { - throw new InvalidOperationException( - "A part with the name '" - + part.partName.getName() - + "' already exists : Packages shall not contain equivalent part names and package implementers shall neither create nor recognize packages with equivalent part names. [M1.12]"); - } else { - // If the specified partis flagged as deleted, we make it - // available - part.setDeleted(false); - // and delete the old part to replace it thereafeter - this.partList.remove(part.partName); - } - } - this.partList.put(part.partName, part); - this.isDirty = true; - return part; - } - - /** - * Remove the specified part in this package. If this part is relationship - * part, then delete all relationships in the source part. - * - * @param part - * The part to remove. If null, skip the action. - * @see #removePart(PackagePartName) - */ - public void removePart(PackagePart part) { - if (part != null) { - removePart(part.getPartName()); - } - } - - /** - * Remove a part in this package. If this part is relationship part, then - * delete all relationships in the source part. - * - * @param partName - * The part name of the part to remove. - */ - public void removePart(PackagePartName partName) { - throwExceptionIfReadOnly(); - if (partName == null || !this.containPart(partName)) - throw new IllegalArgumentException("partName"); - - // Delete the specified part from the package. - if (this.partList.containsKey(partName)) { - this.partList.get(partName).setDeleted(true); - this.removePartImpl(partName); - this.partList.remove(partName); - } else { - this.removePartImpl(partName); - } - - // Delete content type - this.contentTypeManager.removeContentType(partName); - - // If this part is a relationship part, then delete all relationships of - // the source part. - if (partName.isRelationshipPartURI()) { - URI sourceURI = PackagingURIHelper - .getSourcePartUriFromRelationshipPartUri(partName.getURI()); - PackagePartName sourcePartName; - try { - sourcePartName = PackagingURIHelper.createPartName(sourceURI); - } catch (InvalidFormatException e) { - logger - .log(POILogger.ERROR, "Part name URI '" - + sourceURI - + "' is not valid ! This message is not intended to be displayed !"); - return; - } - if (sourcePartName.getURI().equals( - PackagingURIHelper.PACKAGE_ROOT_URI)) { - clearRelationships(); - } else if (containPart(sourcePartName)) { - PackagePart part = getPart(sourcePartName); - if (part != null) - part.clearRelationships(); - } - } - - this.isDirty = true; - } - - /** - * Remove a part from this package as well as its relationship part, if one - * exists, and all parts listed in the relationship part. Be aware that this - * do not delete relationships which target the specified part. - * - * @param partName - * The name of the part to delete. - * @throws InvalidFormatException - * Throws if the associated relationship part of the specified - * part is not valid. - */ - public void removePartRecursive(PackagePartName partName) - throws InvalidFormatException { - // Retrieves relationship part, if one exists - PackagePart relPart = this.partList.get(PackagingURIHelper - .getRelationshipPartName(partName)); - // Retrieves PackagePart object from the package - PackagePart partToRemove = this.partList.get(partName); - - if (relPart != null) { - PackageRelationshipCollection partRels = new PackageRelationshipCollection( - partToRemove); - for (PackageRelationship rel : partRels) { - PackagePartName partNameToRemove = PackagingURIHelper - .createPartName(PackagingURIHelper.resolvePartUri(rel - .getSourceURI(), rel.getTargetURI())); - removePart(partNameToRemove); - } - - // Finally delete its relationship part if one exists - this.removePart(relPart.partName); - } - - // Delete the specified part - this.removePart(partToRemove.partName); - } - - /** - * Delete the part with the specified name and its associated relationships - * part if one exists. Prefer the use of this method to delete a part in the - * package, compare to the remove() methods that don't remove associated - * relationships part. - * - * @param partName - * Name of the part to delete - */ - public void deletePart(PackagePartName partName) { - if (partName == null) - throw new IllegalArgumentException("partName"); - - // Remove the part - this.removePart(partName); - // Remove the relationships part - this.removePart(PackagingURIHelper.getRelationshipPartName(partName)); - } - - /** - * Delete the part with the specified name and all part listed in its - * associated relationships part if one exists. This process is recursively - * apply to all parts in the relationships part of the specified part. - * Prefer the use of this method to delete a part in the package, compare to - * the remove() methods that don't remove associated relationships part. - * - * @param partName - * Name of the part to delete - */ - public void deletePartRecursive(PackagePartName partName) { - if (partName == null || !this.containPart(partName)) - throw new IllegalArgumentException("partName"); - - PackagePart partToDelete = this.getPart(partName); - // Remove the part - this.removePart(partName); - // Remove all relationship parts associated - try { - for (PackageRelationship relationship : partToDelete - .getRelationships()) { - PackagePartName targetPartName = PackagingURIHelper - .createPartName(PackagingURIHelper.resolvePartUri( - partName.getURI(), relationship.getTargetURI())); - this.deletePartRecursive(targetPartName); - } - } catch (InvalidFormatException e) { - logger.log(POILogger.WARN, "An exception occurs while deleting part '" - + partName.getName() - + "'. Some parts may remain in the package. - " - + e.getMessage()); - return; - } - // Remove the relationships part - PackagePartName relationshipPartName = PackagingURIHelper - .getRelationshipPartName(partName); - if (relationshipPartName != null && containPart(relationshipPartName)) - this.removePart(relationshipPartName); - } - - /** - * Check if a part already exists in this package from its name. - * - * @param partName - * Part name to check. - * @return true if the part is logically added to this package, else - * false. - */ - public boolean containPart(PackagePartName partName) { - return (this.getPart(partName) != null); - } - - /** - * Add a relationship to the package (except relationships part). - * - * Check rule M4.1 : The format designer shall specify and the format - * producer shall create at most one core properties relationship for a - * package. A format consumer shall consider more than one core properties - * relationship for a package to be an error. If present, the relationship - * shall target the Core Properties 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 - * Target part name. - * @param targetMode - * Target mode, either Internal or External. - * @param relationshipType - * Relationship type. - * @param relID - * ID of the relationship. - * @see PackageRelationshipTypes - */ - public PackageRelationship addRelationship(PackagePartName targetPartName, - TargetMode targetMode, String relationshipType, String relID) { - /* Check OPC compliance */ - - // Check rule M4.1 : The format designer shall specify and the format - // producer - // shall create at most one core properties relationship for a package. - // A format consumer shall consider more than one core properties - // relationship for a package to be an error. If present, the - // relationship shall target the Core Properties part. - if (relationshipType.equals(PackageRelationshipTypes.CORE_PROPERTIES) - && this.packageProperties != null) - throw new InvalidOperationException( - "OPC Compliance error [M4.1]: can't add another core properties part ! Use the built-in package method instead."); - - /* - * 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. - */ - if (targetPartName.isRelationshipPartURI()) { - throw new InvalidOperationException( - "Rule M1.25: The Relationships part shall not have relationships to any other part."); - } - - /* End OPC compliance */ - - ensureRelationships(); - PackageRelationship retRel = relationships.addRelationship( - targetPartName.getURI(), targetMode, relationshipType, relID); - this.isDirty = true; - return retRel; - } - - /** - * Add a package relationship. - * - * @param targetPartName - * Target part name. - * @param targetMode - * Target mode, either Internal or External. - * @param relationshipType - * Relationship type. - * @see PackageRelationshipTypes - */ - public PackageRelationship addRelationship(PackagePartName targetPartName, - TargetMode targetMode, String relationshipType) { - return this.addRelationship(targetPartName, targetMode, - 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. - * @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"); - } - - URI targetURI; - try { - targetURI = new URI(target); - } catch (URISyntaxException e) { - throw new IllegalArgumentException("Invalid target - " + e); - } - - ensureRelationships(); - PackageRelationship retRel = relationships.addRelationship(targetURI, - TargetMode.EXTERNAL, relationshipType, id); - this.isDirty = true; - return retRel; - } - - /** - * Delete a relationship from this package. - * - * @param id - * Id of the relationship to delete. - */ - public void removeRelationship(String id) { - if (relationships != null) { - relationships.removeRelationship(id); - this.isDirty = true; - } - } - - /** - * Retrieves all package relationships. - * - * @return All package relationships of this package. - * @throws OpenXML4JException - * @see #getRelationshipsHelper(String) - */ - public PackageRelationshipCollection getRelationships() - throws OpenXML4JException { - return getRelationshipsHelper(null); - } - - /** - * Retrives all relationships with the specified type. - * - * @param relationshipType - * The filter specifying the relationship type. - * @return All relationships with the specified relationship type. - * @throws OpenXML4JException - */ - public PackageRelationshipCollection getRelationshipsByType( - String relationshipType) throws IllegalArgumentException, - OpenXML4JException { - throwExceptionIfWriteOnly(); - if (relationshipType == null) { - throw new IllegalArgumentException("relationshipType"); - } - return getRelationshipsHelper(relationshipType); - } - - /** - * Retrieves all relationships with specified id (normally just ine because - * a relationship id is supposed to be unique). - * - * @param id - * Id of the wanted relationship. - * @throws OpenXML4JException - */ - private PackageRelationshipCollection getRelationshipsHelper(String id) - throws OpenXML4JException { - throwExceptionIfWriteOnly(); - ensureRelationships(); - return this.relationships.getRelationships(id); - } - - /** - * Clear package relationships. - */ - public void clearRelationships() { - if (relationships != null) { - relationships.clear(); - this.isDirty = true; - } - } - - /** - * Ensure that the relationships collection is not null. - */ - public void ensureRelationships() { - if (this.relationships == null) { - try { - this.relationships = new PackageRelationshipCollection(this); - } catch (InvalidFormatException e) { - this.relationships = new PackageRelationshipCollection(); - } - } - } - - /** - * @see org.apache.poi.openxml4j.opc.RelationshipSource#getRelationship(java.lang.String) - */ - public PackageRelationship getRelationship(String id) { - return this.relationships.getRelationshipByID(id); - } - - /** - * @see org.apache.poi.openxml4j.opc.RelationshipSource#hasRelationships() - */ - public boolean hasRelationships() { - return (relationships.size() > 0); - } - - /** - * @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; - } - } - - /** - * Add a marshaller. - * - * @param contentType - * The content type to bind to the specified marshaller. - * @param marshaller - * The marshaller to register with the specified content type. - */ - public void addMarshaller(String contentType, PartMarshaller marshaller) { - try { - partMarshallers.put(new ContentType(contentType), marshaller); - } catch (InvalidFormatException e) { - logger.log(POILogger.WARN, "The specified content type is not valid: '" - + e.getMessage() + "'. The marshaller will not be added !"); - } - } - - /** - * Add an unmarshaller. - * - * @param contentType - * The content type to bind to the specified unmarshaller. - * @param unmarshaller - * The unmarshaller to register with the specified content type. - */ - public void addUnmarshaller(String contentType, - PartUnmarshaller unmarshaller) { - try { - partUnmarshallers.put(new ContentType(contentType), unmarshaller); - } catch (InvalidFormatException e) { - logger.log(POILogger.WARN, "The specified content type is not valid: '" - + e.getMessage() - + "'. The unmarshaller will not be added !"); - } - } - - /** - * Remove a marshaller by its content type. - * - * @param contentType - * The content type associated with the marshaller to remove. - */ - public void removeMarshaller(String contentType) { - partMarshallers.remove(contentType); - } - - /** - * Remove an unmarshaller by its content type. - * - * @param contentType - * The content type associated with the unmarshaller to remove. - */ - public void removeUnmarshaller(String contentType) { - partUnmarshallers.remove(contentType); - } - - /* Accesseurs */ - - /** - * Get the package access mode. - * - * @return the packageAccess The current package access. - */ - public PackageAccess getPackageAccess() { - return packageAccess; - } - - /** - * Validates the package compliance with the OPC specifications. - * - * @return true if the package is valid else false - */ - public boolean validatePackage(Package pkg) throws InvalidFormatException { - throw new InvalidOperationException("Not implemented yet !!!"); - } - - /** - * Save the document in the specified file. - * - * @param targetFile - * Destination file. - * @throws IOException - * Throws if an IO exception occur. - * @see #save(OutputStream) - */ - public void save(File targetFile) throws IOException { - if (targetFile == null) - throw new IllegalArgumentException("targetFile"); - - this.throwExceptionIfReadOnly(); - FileOutputStream fos = null; - try { - fos = new FileOutputStream(targetFile); - } catch (FileNotFoundException e) { - throw new IOException(e.getLocalizedMessage()); - } - this.save(fos); - } - - /** - * Save the document in the specified output stream. - * - * @param outputStream - * The stream to save the package. - * @see #saveImpl(OutputStream) - */ - public void save(OutputStream outputStream) throws IOException { - throwExceptionIfReadOnly(); - this.saveImpl(outputStream); - } - - /** - * Core method to create a package part. This method must be implemented by - * the subclass. - * - * @param partName - * URI of the part to create. - * @param contentType - * Content type of the part to create. - * @return The newly created package part. - */ - protected abstract PackagePart createPartImpl(PackagePartName partName, - String contentType, boolean loadRelationships); - - /** - * Core method to delete a package part. This method must be implemented by - * the subclass. - * - * @param partName - * The URI of the part to delete. - */ - protected abstract void removePartImpl(PackagePartName partName); - - /** - * Flush the package but not save. - */ - protected abstract void flushImpl(); - - /** - * Close the package and cause a save of the package. - * - */ - protected abstract void closeImpl() throws IOException; - - /** - * Close the package without saving the document. Discard all changes made - * to this package. - */ - protected abstract void revertImpl(); - - /** - * Save the package into the specified output stream. - * - * @param outputStream - * The output stream use to save this package. - */ - protected abstract void saveImpl(OutputStream outputStream) - throws IOException; - - /** - * Get the package part mapped to the specified URI. - * - * @param partName - * The URI of the part to retrieve. - * @return The package part located by the specified URI, else null. - */ - protected abstract PackagePart getPartImpl(PackagePartName partName); - - /** - * Get all parts link to the package. - * - * @return A list of the part owned by the package. - */ - protected abstract PackagePart[] getPartsImpl() - throws InvalidFormatException; -} +/* ==================================================================== + 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.util.Date; + +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.exceptions.InvalidOperationException; +import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart; +import org.apache.poi.openxml4j.opc.internal.ZipContentTypeManager; +import org.apache.poi.openxml4j.util.Nullable; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; + +/** + * @deprecated (name clash with {@link java.lang.Package} use {@link OPCPackage} instead. + * + * @author Julien Chable, CDubet + * + */ +public abstract class Package extends OPCPackage { + + /** + * Logger. + */ + private static POILogger logger = POILogFactory.getLogger(Package.class); + + + /** + * @deprecated use {@link OPCPackage} + */ + protected Package(PackageAccess access) { + super(access); + } + + + /** + * @deprecated use {@link OPCPackage#open(String)} + */ + public static Package open(String path) throws InvalidFormatException { + return open(path, defaultPackageAccess); + } + + /** + * @deprecated use {@link OPCPackage#open(String,PackageAccess)} + */ + public static Package open(String path, PackageAccess access) + throws InvalidFormatException { + if (path == null || "".equals(path.trim()) + || (new File(path).exists() && new File(path).isDirectory())) + throw new IllegalArgumentException("path"); + + Package pack = new ZipPackage(path, access); + if (pack.partList == null && access != PackageAccess.WRITE) { + pack.getParts(); + } + pack.originalPackagePath = new File(path).getAbsolutePath(); + return pack; + } + + /** + * @deprecated use {@link OPCPackage#open(InputStream)} + */ + public static Package open(InputStream in) throws InvalidFormatException, + IOException { + Package pack = new ZipPackage(in, PackageAccess.READ); + if (pack.partList == null) { + pack.getParts(); + } + return pack; + } + + /** + * @deprecated use {@link OPCPackage#open(File)} + */ + public static Package openOrCreate(File file) throws InvalidFormatException { + Package retPackage = null; + if (file.exists()) { + retPackage = open(file.getAbsolutePath()); + } else { + retPackage = create(file); + } + return retPackage; + } + + /** + * @deprecated use {@link OPCPackage#create(String)} + */ + public static Package create(String path) { + return create(new File(path)); + } + + /** + * @deprecated use {@link OPCPackage#create(File)} + */ + public static Package create(File file) { + if (file == null || (file.exists() && file.isDirectory())) + throw new IllegalArgumentException("file"); + + if (file.exists()) { + throw new InvalidOperationException( + "This package (or file) already exists : use the open() method or delete the file."); + } + + // Creates a new package + Package pkg = null; + pkg = new ZipPackage(); + pkg.originalPackagePath = file.getAbsolutePath(); + + configurePackage(pkg); + return pkg; + } + + /** + * @deprecated use {@link OPCPackage#create(OutputStream)} + */ + public static Package create(OutputStream output) { + Package pkg = null; + pkg = new ZipPackage(); + pkg.originalPackagePath = null; + pkg.output = output; + + configurePackage(pkg); + return pkg; + } + + /** + * Configure the package. + * + * @param pkg + */ + private static void configurePackage(Package pkg) { + try { + // Content type manager + pkg.contentTypeManager = new ZipContentTypeManager(null, pkg); + // Add default content types for .xml and .rels + pkg.contentTypeManager + .addContentType( + PackagingURIHelper + .createPartName(PackagingURIHelper.PACKAGE_RELATIONSHIPS_ROOT_URI), + ContentTypes.RELATIONSHIPS_PART); + pkg.contentTypeManager + .addContentType(PackagingURIHelper + .createPartName("/default.xml"), + ContentTypes.PLAIN_OLD_XML); + + // Init some Package properties + pkg.packageProperties = new PackagePropertiesPart(pkg, + PackagingURIHelper.CORE_PROPERTIES_PART_NAME); + pkg.packageProperties.setCreatorProperty("Generated by OpenXML4J"); + pkg.packageProperties.setCreatedProperty(new Nullable( + new Date())); + } catch (InvalidFormatException e) { + // Should never happen + throw new IllegalStateException(e); + } + } + + +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackagePart.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackagePart.java index c30e6d9869..928e0a783f 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackagePart.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackagePart.java @@ -1,654 +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 null 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 true if the part have at least one relationship else - * false. - * @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 true if the specified relationship exists in this part, - * else returns false - * @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 - * null. - */ - 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 MemoryPackagePart 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 true if this part is a relationship - */ - public boolean isRelationshipPart() { - return this.isRelationshipPart; - } - - /** - * @return true if this part has been logically deleted - */ - 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 true if the content has been successfully loaded, else - * false. - * @throws InvalidFormatException - * Throws if the content format is invalid. - */ - public abstract boolean load(InputStream ios) throws InvalidFormatException; - - /** - * Close this part : flush this part, close the input stream and output - * stream. After this method call, the part must be available for packaging. - */ - public abstract void close(); - - /** - * Flush the content of this part. If the input stream and/or output stream - * as in a waiting state to read or write, the must to empty their - * respective buffer. - */ - public abstract void flush(); -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc; + +import java.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 OPCPackage 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(OPCPackage 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(OPCPackage pack, PackagePartName partName, + ContentType contentType, boolean loadRelationships) + throws InvalidFormatException { + this.partName = partName; + this.contentType = contentType; + this.container = (ZipPackage) pack; // TODO - enforcing ZipPackage here - perhaps should change constructor signature + + // 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(OPCPackage 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 null 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 true if the part have at least one relationship else + * false. + * @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 true if the specified relationship exists in this part, + * else returns false + * @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 + * null. + */ + 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 MemoryPackagePart 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 OPCPackage getPackage() { + return container; + } + + /** + * @return true if this part is a relationship + */ + public boolean isRelationshipPart() { + return this.isRelationshipPart; + } + + /** + * @return true if this part has been logically deleted + */ + 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 true if the content has been successfully loaded, else + * false. + * @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(); +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageProperties.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageProperties.java index 5ab80dd0f8..3013af4354 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageProperties.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageProperties.java @@ -1,227 +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 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 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 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 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 created); - - /** - * Get the entity primarily responsible for making the content of the - * resource. - */ - public abstract Nullable 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 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 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 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 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 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 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 lastPrinted); - - /** - * Get the date on which the resource was changed. - */ - public abstract Nullable 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 modified); - - /** - * Get the revision number. - */ - public abstract Nullable getRevisionProperty(); - - /** - * Set the revision number. - */ - public abstract void setRevisionProperty(String revision); - - /** - * Get the topic of the content of the resource. - */ - public abstract Nullable 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 getTitleProperty(); - - /** - * Set the name given to the resource. - */ - public abstract void setTitleProperty(String title); - - /** - * Get the version number. - */ - public abstract Nullable getVersionProperty(); - - /** - * Set the version number. - */ - public abstract void setVersionProperty(String version); -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc; + +import java.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.OPCPackage + */ +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 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 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 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 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 created); + + /** + * Get the entity primarily responsible for making the content of the + * resource. + */ + public abstract Nullable 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 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 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 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 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 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 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 lastPrinted); + + /** + * Get the date on which the resource was changed. + */ + public abstract Nullable 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 modified); + + /** + * Get the revision number. + */ + public abstract Nullable getRevisionProperty(); + + /** + * Set the revision number. + */ + public abstract void setRevisionProperty(String revision); + + /** + * Get the topic of the content of the resource. + */ + public abstract Nullable 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 getTitleProperty(); + + /** + * Set the name given to the resource. + */ + public abstract void setTitleProperty(String title); + + /** + * Get the version number. + */ + public abstract Nullable getVersionProperty(); + + /** + * Set the version number. + */ + public abstract void setVersionProperty(String version); +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageRelationship.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageRelationship.java index b8f525a806..0deb737314 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageRelationship.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageRelationship.java @@ -1,227 +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; - - /** - * Reference to the 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 pkg - * @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 URL of the source part of this relationship - */ - public URI getSourceURI() { - if (source == null) { - return PackagingURIHelper.PACKAGE_ROOT_URI; - } - return source.partName.getURI(); - } - - /** - * public URI getSourceUri(){ } - * - * @return the targetMode - */ - public TargetMode getTargetMode() { - return targetMode; - } - - /** - * @return the targetUri - */ - public URI getTargetURI() { - // If it's an external target, we don't - // need to apply our normal validation rules - if(targetMode == TargetMode.EXTERNAL) { - return targetUri; - } - - // Internal target - // If it isn't absolute, resolve it relative - // to ourselves - if (!targetUri.toASCIIString().startsWith("/")) { - // So it's a relative part name, try to resolve it - return PackagingURIHelper.resolvePartUri(getSourceURI(), targetUri); - } - return targetUri; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(id == null ? "id=null" : "id=" + id); - sb.append(container == null ? " - container=null" : " - container=" - + container.toString()); - sb.append(relationshipType == null ? " - relationshipType=null" - : " - relationshipType=" + relationshipType.toString()); - sb.append(source == null ? " - source=null" : " - source=" - + getSourceURI().toASCIIString()); - sb.append(targetUri == null ? " - target=null" : " - target=" - + getTargetURI().toASCIIString()); - sb.append(targetMode == null ? ",targetMode=null" : ",targetMode=" - + targetMode.toString()); - return sb.toString(); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc; + +import java.net.URI; +import java.net.URISyntaxException; + +/** + * 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; + + /** + * Reference to the package. + */ + private OPCPackage 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 pkg + * @param sourcePart + * @param targetUri + * @param targetMode + * @param relationshipType + * @param id + */ + public PackageRelationship(OPCPackage 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 OPCPackage 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 URL of the source part of this relationship + */ + 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(); + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageRelationshipCollection.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageRelationshipCollection.java index 09f3280df2..8a11738711 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageRelationshipCollection.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageRelationshipCollection.java @@ -1,451 +1,451 @@ -/* ==================================================================== - 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.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; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.POILogFactory; - -/** - * 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 { - - private static POILogger logger = POILogFactory.getLogger(PackageRelationshipCollection.class); - - /** - * Package relationships ordered by ID. - */ - private TreeMap relationshipsByID; - - /** - * Package relationships ordered by type. - */ - private TreeMap 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(); - relationshipsByType = new TreeMap(); - } - - /** - * 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 null - * 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.log(POILogger.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 - .log(POILogger.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.log(POILogger.ERROR, "Cannot convert " + value - + " in a valid relationship URI-> ignored", e); - continue; - } - addRelationship(target, targetMode, type, id); - } - } catch (Exception e) { - logger.log(POILogger.ERROR, e); - throw new InvalidFormatException(e.getMessage()); - } - } - - /** - * Retrieves all relations with the specified type. - * - * @param typeFilter - * Relationship type filter. If null 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 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 iterator(String typeFilter) { - ArrayList retArr = new ArrayList(); - for (PackageRelationship rel : relationshipsByID.values()) { - if (rel.getRelationshipType().equals(typeFilter)) - retArr.add(rel); - } - return retArr.iterator(); - } - - /** - * Clear all relationships. - */ - public void clear() { - relationshipsByID.clear(); - relationshipsByType.clear(); - } - - @Override - public String toString() { - String str; - if (relationshipsByID == null) { - str = "relationshipsByID=null"; - } else { - str = relationshipsByID.size() + " relationship(s) = ["; - } - if ((relationshipPart != null) && (relationshipPart.partName != null)) { - str = str + "," + relationshipPart.partName; - } else { - str = str + ",relationshipPart=null"; - } - - // Source of this relationship - if ((sourcePart != null) && (sourcePart.partName != null)) { - str = str + "," + sourcePart.partName; - } else { - str = str + ",sourcePart=null"; - } - if (partName != null) { - str = str + "," + partName; - } else { - str = str + ",uri=null)"; - } - return str + "]"; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.openxml4j.opc; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.TreeMap; + +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; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.POILogFactory; + +/** + * 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 { + + private static POILogger logger = POILogFactory.getLogger(PackageRelationshipCollection.class); + + /** + * Package relationships ordered by ID. + */ + private TreeMap relationshipsByID; + + /** + * Package relationships ordered by type. + */ + private TreeMap relationshipsByType; + + /** + * This relationshipPart. + */ + private PackagePart relationshipPart; + + /** + * Source part. + */ + private PackagePart sourcePart; + + /** + * This part name. + */ + private PackagePartName partName; + + /** + * Reference to the package. + */ + private OPCPackage container; + + /** + * Constructor. + */ + PackageRelationshipCollection() { + relationshipsByID = new TreeMap(); + relationshipsByType = new TreeMap(); + } + + /** + * 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(OPCPackage 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 null + * 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(OPCPackage 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.log(POILogger.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 + .log(POILogger.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.log(POILogger.ERROR, "Cannot convert " + value + + " in a valid relationship URI-> ignored", e); + continue; + } + addRelationship(target, targetMode, type, id); + } + } catch (Exception e) { + logger.log(POILogger.ERROR, e); + throw new InvalidFormatException(e.getMessage()); + } + } + + /** + * Retrieves all relations with the specified type. + * + * @param typeFilter + * Relationship type filter. If null 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 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 iterator(String typeFilter) { + ArrayList retArr = new ArrayList(); + 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 + "]"; + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/ZipPackagePart.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/ZipPackagePart.java index 2c05898d14..a4e50ba0a8 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/ZipPackagePart.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/ZipPackagePart.java @@ -1,135 +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 null. Normally - * will never be called since the MemoryPackage is use instead. - * - * @return null - */ - @Override - protected OutputStream getOutputStreamImpl() { - return null; - } - - @Override - public boolean save(OutputStream os) throws OpenXML4JException { - return new ZipPartMarshaller().marshall(this, os); - } - - @Override - public boolean load(InputStream ios) throws InvalidFormatException { - throw new InvalidOperationException("Method not implemented !"); - } - - @Override - public void close() { - throw new InvalidOperationException("Method not implemented !"); - } - - @Override - public void flush() { - throw new InvalidOperationException("Method not implemented !"); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc; + +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(OPCPackage 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(OPCPackage 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 null. Normally + * will never be called since the MemoryPackage is use instead. + * + * @return null + */ + @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 !"); + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ContentTypeManager.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ContentTypeManager.java index 927102d6db..f36bf068ff 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ContentTypeManager.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ContentTypeManager.java @@ -1,496 +1,491 @@ -/* ==================================================================== - 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.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; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.POILogFactory; - -/** - * Manage package content types ([Content_Types].xml part). - * - * @author Julien Chable - * @version 1.0 - */ -public abstract class ContentTypeManager { - - private static POILogger logger = POILogFactory.getLogger(ContentTypeManager.class); - - /** - * 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. - */ - private TreeMap defaultContentType; - - /** - * Override content type tree. - */ - private TreeMap overrideContentType; - - /** - * Constructor. Parses the content of the specified input stream. - * - * @param in - * If different of null 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(); - if (in != null) { - try { - parseContentTypesFile(in); - } catch (InvalidFormatException e) { - throw new InvalidFormatException( - "Can't read content types part !"); - } - } - } - - /** - * Build association extention-> content type (will be stored in - * [Content_Types].xml) for example ContentType="image/png" Extension="png" - *

- * [M2.8]: When adding a new part to a package, the package implementer - * shall ensure that a content type for that part is specified in the - * Content Types stream; the package implementer shall perform the steps - * described in §9.1.2.3: - *

- * 1. Get the extension from the part name by taking the substring to the - * right of the rightmost occurrence of the dot character (.) from the - * rightmost segment. - *

- * 2. If a part name has no extension, a corresponding Override element - * shall be added to the Content Types stream. - *

- * 3. Compare the resulting extension with the values specified for the - * Extension attributes of the Default elements in the Content Types stream. - * The comparison shall be case-insensitive ASCII. - *

- * 4. If there is a Default element with a matching Extension attribute, - * then the content type of the new part shall be compared with the value of - * the ContentType attribute. The comparison might be case-sensitive and - * include every character regardless of the role it plays in the - * content-type grammar of RFC 2616, or it might follow the grammar of RFC - * 2616. - *

- * a. If the content types match, no further action is required. - *

- * b. If the content types do not match, a new Override element shall be - * added to the Content Types stream. . - *

- * 5. If there is no Default element with a matching Extension attribute, a - * new Default element or Override element shall be added to the Content - * Types stream. - *

- */ - 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(); - 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 partName - * 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 true if the specified content type is already - * register, then false. - */ - public boolean isContentTypeRegister(String contentType) { - if (contentType == null) - throw new IllegalArgumentException("contentType"); - - return (this.defaultContentType.values().contains(contentType) || (this.overrideContentType != null && this.overrideContentType - .values().contains(contentType))); - } - - /** - * Get the content type for the specified part, if any. - *

- * Rule [M2.9]: To get the content type of a part, the package implementer - * shall perform the steps described in §9.1.2.4: - *

- * 1. Compare the part name with the values specified for the PartName - * attribute of the Override elements. The comparison shall be - * case-insensitive ASCII. - *

- * 2. If there is an Override element with a matching PartName attribute, - * return the value of its ContentType attribute. No further action is - * required. - *

- * 3. If there is no Override element with a matching PartName attribute, - * then a. Get the extension from the part name by taking the substring to - * the right of the rightmost occurrence of the dot character (.) from the - * rightmost segment. b. Check the Default elements of the Content Types - * stream, comparing the extension with the value of the Extension - * attribute. The comparison shall be case-insensitive ASCII. - *

- * 4. If there is a Default element with a matching Extension attribute, - * return the value of its ContentType attribute. No further action is - * required. - *

- * 5. If neither Override nor Default elements with matching attributes are - * found for the specified part name, the implementation shall not map this - * part name to a part. - *

- * @param partName - * 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 null. - * - * @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 true if the operation success, else false. - */ - 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 entry : defaultContentType.entrySet()) { - appendDefaultType(typesElem, entry); - } - - // Adding specific types if any exist - if (overrideContentType != null) { - for (Entry 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(java.io.OutputStream) - */ - private void appendSpecificTypes(Element root, - Entry 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(java.io.OutputStream) - */ - private void appendDefaultType(Element root, Entry entry) { - root.addElement(DEFAULT_TAG_NAME).addAttribute( - EXTENSION_ATTRIBUTE_NAME, (String) entry.getKey()) - .addAttribute(CONTENT_TYPE_ATTRIBUTE_NAME, - (String) entry.getValue()); - - } - - /** - * Specific implementation of the save method. Call by the save() method, - * call before exiting. - * - * @param out - * The output stream use to write the content type XML. - */ - public abstract boolean saveImpl(Document content, OutputStream out); -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc.internal; + +import java.io.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 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.OPCPackage; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.openxml4j.opc.PackagePartName; +import org.apache.poi.openxml4j.opc.PackagingURIHelper; +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; + +/** + * Manage package content types ([Content_Types].xml part). + * + * @author Julien Chable + * @version 1.0 + */ +public abstract class ContentTypeManager { + + /** + * 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"; + + /** + * Reference to the package using this content type manager. + */ + protected OPCPackage container; + + /** + * Default content type tree. + */ + private TreeMap defaultContentType; + + /** + * Override content type tree. + */ + private TreeMap overrideContentType; + + /** + * Constructor. Parses the content of the specified input stream. + * + * @param in + * If different of null then the content types part is + * retrieve and parse. + * @throws InvalidFormatException + * If the content types part content is not valid. + */ + public ContentTypeManager(InputStream in, OPCPackage pkg) + throws InvalidFormatException { + this.container = pkg; + this.defaultContentType = new TreeMap(); + if (in != null) { + try { + parseContentTypesFile(in); + } catch (InvalidFormatException e) { + throw new InvalidFormatException( + "Can't read content types part !"); + } + } + } + + /** + * Build association extention-> content type (will be stored in + * [Content_Types].xml) for example ContentType="image/png" Extension="png" + *

+ * [M2.8]: When adding a new part to a package, the package implementer + * shall ensure that a content type for that part is specified in the + * Content Types stream; the package implementer shall perform the steps + * described in §9.1.2.3: + *

+ * 1. Get the extension from the part name by taking the substring to the + * right of the rightmost occurrence of the dot character (.) from the + * rightmost segment. + *

+ * 2. If a part name has no extension, a corresponding Override element + * shall be added to the Content Types stream. + *

+ * 3. Compare the resulting extension with the values specified for the + * Extension attributes of the Default elements in the Content Types stream. + * The comparison shall be case-insensitive ASCII. + *

+ * 4. If there is a Default element with a matching Extension attribute, + * then the content type of the new part shall be compared with the value of + * the ContentType attribute. The comparison might be case-sensitive and + * include every character regardless of the role it plays in the + * content-type grammar of RFC 2616, or it might follow the grammar of RFC + * 2616. + *

+ * a. If the content types match, no further action is required. + *

+ * b. If the content types do not match, a new Override element shall be + * added to the Content Types stream. . + *

+ * 5. If there is no Default element with a matching Extension attribute, a + * new Default element or Override element shall be added to the Content + * Types stream. + *

+ */ + 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(); + 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 partName + * 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 true if the specified content type is already + * register, then false. + */ + public boolean isContentTypeRegister(String contentType) { + if (contentType == null) + throw new IllegalArgumentException("contentType"); + + return (this.defaultContentType.values().contains(contentType) || (this.overrideContentType != null && this.overrideContentType + .values().contains(contentType))); + } + + /** + * Get the content type for the specified part, if any. + *

+ * Rule [M2.9]: To get the content type of a part, the package implementer + * shall perform the steps described in §9.1.2.4: + *

+ * 1. Compare the part name with the values specified for the PartName + * attribute of the Override elements. The comparison shall be + * case-insensitive ASCII. + *

+ * 2. If there is an Override element with a matching PartName attribute, + * return the value of its ContentType attribute. No further action is + * required. + *

+ * 3. If there is no Override element with a matching PartName attribute, + * then a. Get the extension from the part name by taking the substring to + * the right of the rightmost occurrence of the dot character (.) from the + * rightmost segment. b. Check the Default elements of the Content Types + * stream, comparing the extension with the value of the Extension + * attribute. The comparison shall be case-insensitive ASCII. + *

+ * 4. If there is a Default element with a matching Extension attribute, + * return the value of its ContentType attribute. No further action is + * required. + *

+ * 5. If neither Override nor Default elements with matching attributes are + * found for the specified part name, the implementation shall not map this + * part name to a part. + *

+ * @param partName + * 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 null. + * + * @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 true if the operation success, else false. + */ + 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 entry : defaultContentType.entrySet()) { + appendDefaultType(typesElem, entry); + } + + // Adding specific types if any exist + if (overrideContentType != null) { + for (Entry 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(java.io.OutputStream) + */ + private void appendSpecificTypes(Element root, + Entry 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(java.io.OutputStream) + */ + private void appendDefaultType(Element root, Entry 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); +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/MemoryPackagePart.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/MemoryPackagePart.java index 8f29a45875..0d7f8d39c1 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/MemoryPackagePart.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/MemoryPackagePart.java @@ -1,126 +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 - } -} +/* ==================================================================== + 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.OPCPackage; +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(OPCPackage 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(OPCPackage 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 + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/PackagePropertiesPart.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/PackagePropertiesPart.java index a9f60b011a..582fe507a2 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/PackagePropertiesPart.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/PackagePropertiesPart.java @@ -1,621 +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 category = new Nullable(); - - /** - * The status of the content. - * - * [Example: Values might include "Draft", "Reviewed", and "Final". end - * example] - */ - protected Nullable contentStatus = new Nullable(); - - /** - * 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 contentType = new Nullable(); - - /** - * Date of creation of the resource. - */ - protected Nullable created = new Nullable(); - - /** - * An entity primarily responsible for making the content of the resource. - */ - protected Nullable creator = new Nullable(); - - /** - * 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 description = new Nullable(); - - /** - * An unambiguous reference to the resource within a given context. - */ - protected Nullable identifier = new Nullable(); - - /** - * 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 keywords = new Nullable(); - - /** - * The language of the intellectual content of the resource. - * - * [Note: IETF RFC 3066 provides guidance on encoding to represent - * languages. end note] - */ - protected Nullable language = new Nullable(); - - /** - * 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 lastModifiedBy = new Nullable(); - - /** - * The date and time of the last printing. - */ - protected Nullable lastPrinted = new Nullable(); - - /** - * Date on which the resource was changed. - */ - protected Nullable modified = new Nullable(); - - /** - * 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 revision = new Nullable(); - - /** - * The topic of the content of the resource. - */ - protected Nullable subject = new Nullable(); - - /** - * The name given to the resource. - */ - protected Nullable title = new Nullable(); - - /** - * The version number. This value is set by the user or by the application. - */ - protected Nullable version = new Nullable(); - - /* - * Getters and setters - */ - - /** - * Get the category property. - * - * @see org.apache.poi.openxml4j.opc.PackageProperties#getCategoryProperty() - */ - public Nullable getCategoryProperty() { - return category; - } - - /** - * Get content status. - * - * @see org.apache.poi.openxml4j.opc.PackageProperties#getContentStatusProperty() - */ - public Nullable getContentStatusProperty() { - return contentStatus; - } - - /** - * Get content type. - * - * @see org.apache.poi.openxml4j.opc.PackageProperties#getContentTypeProperty() - */ - public Nullable getContentTypeProperty() { - return contentType; - } - - /** - * Get created date. - * - * @see org.apache.poi.openxml4j.opc.PackageProperties#getCreatedProperty() - */ - public Nullable 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 getCreatorProperty() { - return creator; - } - - /** - * Get description. - * - * @see org.apache.poi.openxml4j.opc.PackageProperties#getDescriptionProperty() - */ - public Nullable getDescriptionProperty() { - return description; - } - - /** - * Get identifier. - * - * @see org.apache.poi.openxml4j.opc.PackageProperties#getIdentifierProperty() - */ - public Nullable getIdentifierProperty() { - return identifier; - } - - /** - * Get keywords. - * - * @see org.apache.poi.openxml4j.opc.PackageProperties#getKeywordsProperty() - */ - public Nullable getKeywordsProperty() { - return keywords; - } - - /** - * Get the language. - * - * @see org.apache.poi.openxml4j.opc.PackageProperties#getLanguageProperty() - */ - public Nullable getLanguageProperty() { - return language; - } - - /** - * Get the author of last modifications. - * - * @see org.apache.poi.openxml4j.opc.PackageProperties#getLastModifiedByProperty() - */ - public Nullable getLastModifiedByProperty() { - return lastModifiedBy; - } - - /** - * Get last printed date. - * - * @see org.apache.poi.openxml4j.opc.PackageProperties#getLastPrintedProperty() - */ - public Nullable 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 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(new Date())); - else - return getDateValue(modified); - } - - /** - * Get revision. - * - * @see org.apache.poi.openxml4j.opc.PackageProperties#getRevisionProperty() - */ - public Nullable getRevisionProperty() { - return revision; - } - - /** - * Get subject. - * - * @see org.apache.poi.openxml4j.opc.PackageProperties#getSubjectProperty() - */ - public Nullable getSubjectProperty() { - return subject; - } - - /** - * Get title. - * - * @see org.apache.poi.openxml4j.opc.PackageProperties#getTitleProperty() - */ - public Nullable getTitleProperty() { - return title; - } - - /** - * Get version. - * - * @see org.apache.poi.openxml4j.opc.PackageProperties#getVersionProperty() - */ - public Nullable 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 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 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 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 - */ - private Nullable setStringValue(String s) { - if (s == null || s.equals("")) - return new Nullable(); - else - return new Nullable(s); - } - - /** - * Convert a string value represented a date into a Nullable. - * - * @throws InvalidFormatException - * Throws if the date format isnot valid. - */ - private Nullable setDateValue(String s) throws InvalidFormatException { - if (s == null || s.equals("")) - return new Nullable(); - 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(d); - } - } - - /** - * Convert a Nullable into a String. - * - * @param d - * The Date to convert. - * @return The formated date or null. - * @see java.util.SimpleDateFormat - */ - private String getDateValue(Nullable d) { - if (d == null || d.equals("")) - return ""; - else { - SimpleDateFormat df = new SimpleDateFormat( - "yyyy-MM-dd'T'HH:mm:ss'Z'"); - return df.format(d.getValue()); - } - } - - @Override - protected InputStream getInputStreamImpl() { - throw new InvalidOperationException("Operation not authorized"); - } - - @Override - protected OutputStream getOutputStreamImpl() { - throw new InvalidOperationException( - "Can't use output stream to set properties !"); - } - - @Override - public boolean save(OutputStream zos) throws OpenXML4JException { - throw new InvalidOperationException("Operation not authorized"); - } - - @Override - public boolean load(InputStream ios) throws InvalidFormatException { - throw new InvalidOperationException("Operation not authorized"); - } - - @Override - public void close() { - // Do nothing - } - - @Override - public void flush() { - // Do nothing - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc.internal; + +import java.io.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.OPCPackage; +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(OPCPackage 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 category = new Nullable(); + + /** + * The status of the content. + * + * [Example: Values might include "Draft", "Reviewed", and "Final". end + * example] + */ + protected Nullable contentStatus = new Nullable(); + + /** + * 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 contentType = new Nullable(); + + /** + * Date of creation of the resource. + */ + protected Nullable created = new Nullable(); + + /** + * An entity primarily responsible for making the content of the resource. + */ + protected Nullable creator = new Nullable(); + + /** + * 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 description = new Nullable(); + + /** + * An unambiguous reference to the resource within a given context. + */ + protected Nullable identifier = new Nullable(); + + /** + * 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 keywords = new Nullable(); + + /** + * The language of the intellectual content of the resource. + * + * [Note: IETF RFC 3066 provides guidance on encoding to represent + * languages. end note] + */ + protected Nullable language = new Nullable(); + + /** + * 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 lastModifiedBy = new Nullable(); + + /** + * The date and time of the last printing. + */ + protected Nullable lastPrinted = new Nullable(); + + /** + * Date on which the resource was changed. + */ + protected Nullable modified = new Nullable(); + + /** + * 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 revision = new Nullable(); + + /** + * The topic of the content of the resource. + */ + protected Nullable subject = new Nullable(); + + /** + * The name given to the resource. + */ + protected Nullable title = new Nullable(); + + /** + * The version number. This value is set by the user or by the application. + */ + protected Nullable version = new Nullable(); + + /* + * Getters and setters + */ + + /** + * Get the category property. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getCategoryProperty() + */ + public Nullable getCategoryProperty() { + return category; + } + + /** + * Get content status. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getContentStatusProperty() + */ + public Nullable getContentStatusProperty() { + return contentStatus; + } + + /** + * Get content type. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getContentTypeProperty() + */ + public Nullable getContentTypeProperty() { + return contentType; + } + + /** + * Get created date. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getCreatedProperty() + */ + public Nullable 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 getCreatorProperty() { + return creator; + } + + /** + * Get description. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getDescriptionProperty() + */ + public Nullable getDescriptionProperty() { + return description; + } + + /** + * Get identifier. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getIdentifierProperty() + */ + public Nullable getIdentifierProperty() { + return identifier; + } + + /** + * Get keywords. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getKeywordsProperty() + */ + public Nullable getKeywordsProperty() { + return keywords; + } + + /** + * Get the language. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getLanguageProperty() + */ + public Nullable getLanguageProperty() { + return language; + } + + /** + * Get the author of last modifications. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getLastModifiedByProperty() + */ + public Nullable getLastModifiedByProperty() { + return lastModifiedBy; + } + + /** + * Get last printed date. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getLastPrintedProperty() + */ + public Nullable 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 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(new Date())); + else + return getDateValue(modified); + } + + /** + * Get revision. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getRevisionProperty() + */ + public Nullable getRevisionProperty() { + return revision; + } + + /** + * Get subject. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getSubjectProperty() + */ + public Nullable getSubjectProperty() { + return subject; + } + + /** + * Get title. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getTitleProperty() + */ + public Nullable getTitleProperty() { + return title; + } + + /** + * Get version. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getVersionProperty() + */ + public Nullable 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 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 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 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 + */ + private Nullable setStringValue(String s) { + if (s == null || s.equals("")) + return new Nullable(); + else + return new Nullable(s); + } + + /** + * Convert a string value represented a date into a Nullable. + * + * @throws InvalidFormatException + * Throws if the date format isnot valid. + */ + private Nullable setDateValue(String s) throws InvalidFormatException { + if (s == null || s.equals("")) + return new Nullable(); + 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(d); + } + } + + /** + * Convert a Nullable into a String. + * + * @param d + * The Date to convert. + * @return The formated date or null. + * @see java.util.SimpleDateFormat + */ + private String getDateValue(Nullable 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 + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipContentTypeManager.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipContentTypeManager.java index d732357b22..7355c7e099 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipContentTypeManager.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipContentTypeManager.java @@ -1,93 +1,93 @@ -/* ==================================================================== - 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; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.POILogFactory; - -/** - * Zip implementation of the ContentTypeManager. - * - * @author Julien Chable - * @version 1.0 - * @see ContentTypeManager - */ -public class ZipContentTypeManager extends ContentTypeManager { - private static POILogger logger = POILogFactory.getLogger(ZipContentTypeManager.class); - - /** - * 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.log(POILogger.ERROR, "Cannot write: " + CONTENT_TYPES_PART_NAME - + " in Zip !", ioe); - return false; - } - return true; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc.internal; + +import java.io.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.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.openxml4j.opc.StreamHelper; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.dom4j.Document; + +/** + * Zip implementation of the ContentTypeManager. + * + * @author Julien Chable + * @version 1.0 + * @see ContentTypeManager + */ +public class ZipContentTypeManager extends ContentTypeManager { + private static POILogger logger = POILogFactory.getLogger(ZipContentTypeManager.class); + + /** + * 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, OPCPackage 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.log(POILogger.ERROR, "Cannot write: " + CONTENT_TYPES_PART_NAME + + " in Zip !", ioe); + return false; + } + return true; + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/unmarshallers/UnmarshallContext.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/unmarshallers/UnmarshallContext.java index 689a5c67da..c4e01ca7a5 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/unmarshallers/UnmarshallContext.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/unmarshallers/UnmarshallContext.java @@ -1,96 +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; - } -} +/* ==================================================================== + 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.OPCPackage; +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 OPCPackage _package; + + private PackagePartName partName; + + private ZipEntry zipEntry; + + /** + * Constructor. + * + * @param targetPackage + * Container. + * @param partName + * Name of the part to unmarshall. + */ + public UnmarshallContext(OPCPackage targetPackage, PackagePartName partName) { + this._package = targetPackage; + this.partName = partName; + } + + /** + * @return the container + */ + OPCPackage getPackage() { + return _package; + } + + /** + * @param container + * the container to set + */ + public void setPackage(OPCPackage 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; + } +} diff --git a/src/ooxml/java/org/apache/poi/ss/usermodel/WorkbookFactory.java b/src/ooxml/java/org/apache/poi/ss/usermodel/WorkbookFactory.java index 9b42f0ee74..a3ce259e54 100644 --- a/src/ooxml/java/org/apache/poi/ss/usermodel/WorkbookFactory.java +++ b/src/ooxml/java/org/apache/poi/ss/usermodel/WorkbookFactory.java @@ -22,10 +22,10 @@ import java.io.PushbackInputStream; import org.apache.poi.POIXMLDocument; import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.opc.Package; /** * Factory for creating the appropriate kind of Workbook @@ -41,7 +41,7 @@ public class WorkbookFactory { /** * Creates an XSSFWorkbook from the given OOXML Package */ - public static Workbook create(Package pkg) throws IOException { + public static Workbook create(OPCPackage pkg) throws IOException { return new XSSFWorkbook(pkg); } /** @@ -60,7 +60,7 @@ public class WorkbookFactory { return new HSSFWorkbook(inp); } if(POIXMLDocument.hasOOXMLHeader(inp)) { - return new XSSFWorkbook( Package.open(inp) ); + return new XSSFWorkbook(OPCPackage.open(inp)); } throw new IllegalArgumentException("Your InputStream was neither an OLE2 stream, nor an OOXML stream"); } diff --git a/src/ooxml/java/org/apache/poi/util/PackageHelper.java b/src/ooxml/java/org/apache/poi/util/PackageHelper.java index 5b1b7d7476..78468d5b94 100755 --- a/src/ooxml/java/org/apache/poi/util/PackageHelper.java +++ b/src/ooxml/java/org/apache/poi/util/PackageHelper.java @@ -1,144 +1,144 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.util; - -import 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.*; - -/** - * Provides handy methods to work with OOXML packages - * - * @author Yegor Kozlov - */ -public class PackageHelper { - - /** - * Clone the specified package. - * - * @param pkg the package to clone - * @return the cloned package - */ - public static Package clone(Package pkg) throws OpenXML4JException, IOException { - return clone(pkg, createTempFile()); - } - - /** - * Clone the specified package. - * - * @param pkg the package to clone - * @param file the destination file - * @return the cloned package - */ - public static Package clone(Package pkg, File file) throws OpenXML4JException, IOException { - - String path = file.getAbsolutePath(); - - Package dest = Package.create(path); - PackageRelationshipCollection rels = pkg.getRelationships(); - for (PackageRelationship rel : rels) { - PackagePart part = pkg.getPart(rel); - PackagePart part_tgt; - if (rel.getRelationshipType().equals(PackageRelationshipTypes.CORE_PROPERTIES)) { - copyProperties(pkg.getPackageProperties(), dest.getPackageProperties()); - continue; - } else { - dest.addRelationship(part.getPartName(), rel.getTargetMode(), rel.getRelationshipType()); - part_tgt = dest.createPart(part.getPartName(), part.getContentType()); - } - - OutputStream out = part_tgt.getOutputStream(); - IOUtils.copy(part.getInputStream(), out); - out.close(); - - if(part.hasRelationships()) { - copy(pkg, part, dest, part_tgt); - } - } - dest.close(); - - //the temp file will be deleted when JVM terminates - new File(path).deleteOnExit(); - return Package.open(path); - } - - /** - * Creates an empty file in the default temporary-file directory, - */ - public static File createTempFile() throws IOException { - File file = File.createTempFile("poi-ooxml-", ".tmp"); - //there is no way to pass an existing file to Package.create(file), - //delete first, the file will be re-created in Packe.create(file) - file.delete(); - file.deleteOnExit(); - return file; - - } - - /** - * Recursively copy package parts to the destination package - */ - private static void copy(Package pkg, PackagePart part, Package tgt, PackagePart part_tgt) throws OpenXML4JException, IOException { - PackageRelationshipCollection rels = part.getRelationships(); - if(rels != null) for (PackageRelationship rel : rels) { - PackagePart p; - if(rel.getTargetMode() == TargetMode.EXTERNAL){ - part_tgt.addExternalRelationship(rel.getTargetURI().toString(), rel.getRelationshipType(), rel.getId()); - //external relations don't have associated package parts - continue; - } else { - PackagePartName relName = PackagingURIHelper.createPartName(rel.getTargetURI()); - p = pkg.getPart(relName); - } - - part_tgt.addRelationship(p.getPartName(), rel.getTargetMode(), rel.getRelationshipType(), rel.getId()); - - PackagePart dest; - if(!tgt.containPart(p.getPartName())){ - dest = tgt.createPart(p.getPartName(), p.getContentType()); - OutputStream out = dest.getOutputStream(); - IOUtils.copy(p.getInputStream(), out); - out.close(); - copy(pkg, p, tgt, dest); - } - } - } - - /** - * Copy core package properties - * - * @param src source properties - * @param tgt target properties - */ - private static void copyProperties(PackageProperties src, PackageProperties tgt){ - tgt.setCategoryProperty(src.getCategoryProperty().getValue()); - tgt.setContentStatusProperty(src.getContentStatusProperty().getValue()); - tgt.setContentTypeProperty(src.getContentTypeProperty().getValue()); - tgt.setCreatorProperty(src.getCreatorProperty().getValue()); - tgt.setDescriptionProperty(src.getDescriptionProperty().getValue()); - tgt.setIdentifierProperty(src.getIdentifierProperty().getValue()); - tgt.setKeywordsProperty(src.getKeywordsProperty().getValue()); - tgt.setLanguageProperty(src.getLanguageProperty().getValue()); - tgt.setRevisionProperty(src.getRevisionProperty().getValue()); - tgt.setSubjectProperty(src.getSubjectProperty().getValue()); - tgt.setTitleProperty(src.getTitleProperty().getValue()); - tgt.setVersionProperty(src.getVersionProperty().getValue()); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.util; + +import org.apache.poi.openxml4j.opc.*; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.util.IOUtils; + +import java.io.*; + +/** + * Provides handy methods to work with OOXML packages + * + * @author Yegor Kozlov + */ +public class PackageHelper { + + /** + * Clone the specified package. + * + * @param pkg the package to clone + * @return the cloned package + */ + public static OPCPackage clone(OPCPackage pkg) throws OpenXML4JException, IOException { + return clone(pkg, createTempFile()); + } + + /** + * Clone the specified package. + * + * @param pkg the package to clone + * @param file the destination file + * @return the cloned package + */ + public static OPCPackage clone(OPCPackage pkg, File file) throws OpenXML4JException, IOException { + + String path = file.getAbsolutePath(); + + OPCPackage dest = OPCPackage.create(path); + PackageRelationshipCollection rels = pkg.getRelationships(); + for (PackageRelationship rel : rels) { + PackagePart part = pkg.getPart(rel); + PackagePart part_tgt; + if (rel.getRelationshipType().equals(PackageRelationshipTypes.CORE_PROPERTIES)) { + copyProperties(pkg.getPackageProperties(), dest.getPackageProperties()); + continue; + } else { + dest.addRelationship(part.getPartName(), rel.getTargetMode(), rel.getRelationshipType()); + part_tgt = dest.createPart(part.getPartName(), part.getContentType()); + } + + OutputStream out = part_tgt.getOutputStream(); + IOUtils.copy(part.getInputStream(), out); + out.close(); + + if(part.hasRelationships()) { + copy(pkg, part, dest, part_tgt); + } + } + dest.close(); + + //the temp file will be deleted when JVM terminates + new File(path).deleteOnExit(); + return OPCPackage.open(path); + } + + /** + * Creates an empty file in the default temporary-file directory, + */ + public static File createTempFile() throws IOException { + File file = File.createTempFile("poi-ooxml-", ".tmp"); + //there is no way to pass an existing file to Package.create(file), + //delete first, the file will be re-created in Packe.create(file) + file.delete(); + file.deleteOnExit(); + return file; + + } + + /** + * Recursively copy package parts to the destination package + */ + private static void copy(OPCPackage pkg, PackagePart part, OPCPackage tgt, PackagePart part_tgt) throws OpenXML4JException, IOException { + PackageRelationshipCollection rels = part.getRelationships(); + if(rels != null) for (PackageRelationship rel : rels) { + PackagePart p; + if(rel.getTargetMode() == TargetMode.EXTERNAL){ + part_tgt.addExternalRelationship(rel.getTargetURI().toString(), rel.getRelationshipType(), rel.getId()); + //external relations don't have associated package parts + continue; + } else { + PackagePartName relName = PackagingURIHelper.createPartName(rel.getTargetURI()); + p = pkg.getPart(relName); + } + + part_tgt.addRelationship(p.getPartName(), rel.getTargetMode(), rel.getRelationshipType(), rel.getId()); + + PackagePart dest; + if(!tgt.containPart(p.getPartName())){ + dest = tgt.createPart(p.getPartName(), p.getContentType()); + OutputStream out = dest.getOutputStream(); + IOUtils.copy(p.getInputStream(), out); + out.close(); + copy(pkg, p, tgt, dest); + } + } + } + + /** + * Copy core package properties + * + * @param src source properties + * @param tgt target properties + */ + private static void copyProperties(PackageProperties src, PackageProperties tgt){ + tgt.setCategoryProperty(src.getCategoryProperty().getValue()); + tgt.setContentStatusProperty(src.getContentStatusProperty().getValue()); + tgt.setContentTypeProperty(src.getContentTypeProperty().getValue()); + tgt.setCreatorProperty(src.getCreatorProperty().getValue()); + tgt.setDescriptionProperty(src.getDescriptionProperty().getValue()); + tgt.setIdentifierProperty(src.getIdentifierProperty().getValue()); + tgt.setKeywordsProperty(src.getKeywordsProperty().getValue()); + tgt.setLanguageProperty(src.getLanguageProperty().getValue()); + tgt.setRevisionProperty(src.getRevisionProperty().getValue()); + tgt.setSubjectProperty(src.getSubjectProperty().getValue()); + tgt.setTitleProperty(src.getTitleProperty().getValue()); + tgt.setVersionProperty(src.getVersionProperty().getValue()); + } +} diff --git a/src/ooxml/java/org/apache/poi/xslf/XSLFSlideShow.java b/src/ooxml/java/org/apache/poi/xslf/XSLFSlideShow.java index 7b66a3d5a4..57b801d942 100644 --- a/src/ooxml/java/org/apache/poi/xslf/XSLFSlideShow.java +++ b/src/ooxml/java/org/apache/poi/xslf/XSLFSlideShow.java @@ -17,17 +17,17 @@ package org.apache.poi.xslf; import java.io.IOException; -import java.util.List; import java.util.LinkedList; +import java.util.List; import org.apache.poi.POIXMLDocument; -import org.apache.xmlbeans.XmlException; 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.OPCPackage; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; +import org.apache.xmlbeans.XmlException; import org.openxmlformats.schemas.presentationml.x2006.main.CTCommentList; import org.openxmlformats.schemas.presentationml.x2006.main.CTNotesSlide; import org.openxmlformats.schemas.presentationml.x2006.main.CTPresentation; @@ -68,7 +68,7 @@ public class XSLFSlideShow extends POIXMLDocument { */ private List embedds; - public XSLFSlideShow(Package container) throws OpenXML4JException, IOException, XmlException { + public XSLFSlideShow(OPCPackage container) throws OpenXML4JException, IOException, XmlException { super(container); presentationDoc = diff --git a/src/ooxml/java/org/apache/poi/xslf/extractor/XSLFPowerPointExtractor.java b/src/ooxml/java/org/apache/poi/xslf/extractor/XSLFPowerPointExtractor.java index ad820bd2fb..bb3e9143d1 100644 --- a/src/ooxml/java/org/apache/poi/xslf/extractor/XSLFPowerPointExtractor.java +++ b/src/ooxml/java/org/apache/poi/xslf/extractor/XSLFPowerPointExtractor.java @@ -19,12 +19,12 @@ package org.apache.poi.xslf.extractor; import java.io.IOException; import org.apache.poi.POIXMLTextExtractor; +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.openxml4j.opc.OPCPackage; 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.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; @@ -48,7 +48,7 @@ public class XSLFPowerPointExtractor extends POIXMLTextExtractor { public XSLFPowerPointExtractor(XSLFSlideShow slideshow) throws XmlException, IOException { this(new XMLSlideShow(slideshow)); } - public XSLFPowerPointExtractor(Package container) throws XmlException, OpenXML4JException, IOException { + public XSLFPowerPointExtractor(OPCPackage container) throws XmlException, OpenXML4JException, IOException { this(new XSLFSlideShow(container)); } diff --git a/src/ooxml/java/org/apache/poi/xssf/eventusermodel/XSSFReader.java b/src/ooxml/java/org/apache/poi/xssf/eventusermodel/XSSFReader.java index 29f3bd0832..6814be8c91 100644 --- a/src/ooxml/java/org/apache/poi/xssf/eventusermodel/XSSFReader.java +++ b/src/ooxml/java/org/apache/poi/xssf/eventusermodel/XSSFReader.java @@ -18,24 +18,28 @@ package org.apache.poi.xssf.eventusermodel; import java.io.IOException; import java.io.InputStream; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; -import org.apache.poi.xssf.model.SharedStringsTable; -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.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.OPCPackage; 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.xssf.model.SharedStringsTable; +import org.apache.poi.xssf.model.StylesTable; +import org.apache.poi.xssf.usermodel.XSSFRelation; +import org.apache.xmlbeans.XmlException; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbook; import org.openxmlformats.schemas.spreadsheetml.x2006.main.WorkbookDocument; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet; /** * This class makes it easy to get at individual parts @@ -45,13 +49,13 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet; * for XSSF. */ public class XSSFReader { - private Package pkg; + private OPCPackage pkg; private PackagePart workbookPart; /** * Creates a new XSSFReader, for the given package */ - public XSSFReader(Package pkg) throws IOException, OpenXML4JException { + public XSSFReader(OPCPackage pkg) throws IOException, OpenXML4JException { this.pkg = pkg; PackageRelationship coreDocRelationship = this.pkg.getRelationshipsByType( diff --git a/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExcelExtractor.java b/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExcelExtractor.java index 80ba653118..4d38f6f471 100644 --- a/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExcelExtractor.java +++ b/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExcelExtractor.java @@ -21,6 +21,8 @@ import java.util.Iterator; import org.apache.poi.POIXMLTextExtractor; import org.apache.poi.hssf.extractor.ExcelExtractor; +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Comment; import org.apache.poi.ss.usermodel.HeaderFooter; @@ -29,8 +31,6 @@ 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.apache.poi.openxml4j.exceptions.OpenXML4JException; -import org.apache.poi.openxml4j.opc.Package; /** * Helper class to extract text from an OOXML Excel file @@ -44,7 +44,7 @@ public class XSSFExcelExtractor extends POIXMLTextExtractor implements org.apach public XSSFExcelExtractor(String path) throws XmlException, OpenXML4JException, IOException { this(new XSSFWorkbook(path)); } - public XSSFExcelExtractor(Package container) throws XmlException, OpenXML4JException, IOException { + public XSSFExcelExtractor(OPCPackage container) throws XmlException, OpenXML4JException, IOException { this(new XSSFWorkbook(container)); } public XSSFExcelExtractor(XSSFWorkbook workbook) { diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java index c2cdcd06d4..4f2cfd43fb 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java @@ -36,6 +36,14 @@ import org.apache.poi.POIXMLDocument; import org.apache.poi.POIXMLDocumentPart; import org.apache.poi.POIXMLException; import org.apache.poi.hssf.record.formula.SheetNameFormatter; +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.openxml4j.opc.OPCPackage; +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.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; @@ -45,20 +53,12 @@ import org.apache.poi.util.IOUtils; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.apache.poi.util.PackageHelper; +import org.apache.poi.xssf.model.CalculationChain; import org.apache.poi.xssf.model.SharedStringsTable; import org.apache.poi.xssf.model.StylesTable; -import org.apache.poi.xssf.model.CalculationChain; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.XmlOptions; -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; @@ -152,7 +152,7 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, IterablePackage object. */ - public XSSFWorkbook(Package pkg) throws IOException { + public XSSFWorkbook(OPCPackage pkg) throws IOException { super(ensureWriteAccess(pkg)); //build a tree of POIXMLDocumentParts, this workbook being the root @@ -240,9 +240,9 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable 200 + ExtractorFactory.createExtractor(OPCPackage.open(xlsx.toString())).getText().length() > 200 ); // Word assertTrue( - ExtractorFactory.createExtractor(Package.open(docx.toString())) + ExtractorFactory.createExtractor(OPCPackage.open(docx.toString())) instanceof XWPFWordExtractor ); assertTrue( - ExtractorFactory.createExtractor(Package.open(docx.toString())).getText().length() > 120 + ExtractorFactory.createExtractor(OPCPackage.open(docx.toString())).getText().length() > 120 ); // PowerPoint assertTrue( - ExtractorFactory.createExtractor(Package.open(pptx.toString())) + ExtractorFactory.createExtractor(OPCPackage.open(pptx.toString())) instanceof XSLFPowerPointExtractor ); assertTrue( - ExtractorFactory.createExtractor(Package.open(pptx.toString())).getText().length() > 120 + ExtractorFactory.createExtractor(OPCPackage.open(pptx.toString())).getText().length() > 120 ); // Text try { - ExtractorFactory.createExtractor(Package.open(txt.toString())); + ExtractorFactory.createExtractor(OPCPackage.open(txt.toString())); fail(); } catch(InvalidOperationException e) { // Good diff --git a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestListParts.java b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestListParts.java index c35f57833e..01e628eba4 100755 --- a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestListParts.java +++ b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestListParts.java @@ -1,103 +1,103 @@ -/* ==================================================================== - 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.util.TreeMap; - -import junit.framework.TestCase; - -import org.apache.log4j.Logger; -import org.apache.poi.openxml4j.OpenXML4JTestDataSamples; -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; - -public final class TestListParts extends TestCase { - private static Logger logger = Logger.getLogger("org.apache.poi.openxml4j.test"); - - private TreeMap expectedValues; - - private TreeMap values; - - @Override - protected void setUp() throws Exception { - values = new TreeMap(); - - // Expected values - expectedValues = new TreeMap(); - expectedValues.put(PackagingURIHelper.createPartName("/_rels/.rels"), - "application/vnd.openxmlformats-package.relationships+xml"); - - expectedValues - .put(PackagingURIHelper.createPartName("/docProps/app.xml"), - "application/vnd.openxmlformats-officedocument.extended-properties+xml"); - expectedValues.put(PackagingURIHelper - .createPartName("/docProps/core.xml"), - "application/vnd.openxmlformats-package.core-properties+xml"); - expectedValues.put(PackagingURIHelper - .createPartName("/word/_rels/document.xml.rels"), - "application/vnd.openxmlformats-package.relationships+xml"); - expectedValues - .put( - PackagingURIHelper.createPartName("/word/document.xml"), - "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"); - expectedValues - .put(PackagingURIHelper.createPartName("/word/fontTable.xml"), - "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml"); - expectedValues.put(PackagingURIHelper - .createPartName("/word/media/image1.gif"), "image/gif"); - expectedValues - .put(PackagingURIHelper.createPartName("/word/settings.xml"), - "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml"); - expectedValues - .put(PackagingURIHelper.createPartName("/word/styles.xml"), - "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"); - expectedValues.put(PackagingURIHelper - .createPartName("/word/theme/theme1.xml"), - "application/vnd.openxmlformats-officedocument.theme+xml"); - expectedValues - .put( - PackagingURIHelper - .createPartName("/word/webSettings.xml"), - "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml"); - } - - /** - * List all parts of a package. - */ - public void testListParts() throws InvalidFormatException { - InputStream is = OpenXML4JTestDataSamples.openSampleStream("sample.docx"); - - Package p; - try { - p = Package.open(is); - } catch (IOException e) { - throw new RuntimeException(e); - } - for (PackagePart part : p.getParts()) { - values.put(part.getPartName(), part.getContentType()); - logger.debug(part.getPartName()); - } - - // Compare expected values with values return by the package - for (PackagePartName partName : expectedValues.keySet()) { - assertNotNull(values.get(partName)); - assertEquals(expectedValues.get(partName), values.get(partName)); - } - } -} +/* ==================================================================== + 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.util.TreeMap; + +import junit.framework.TestCase; + +import org.apache.log4j.Logger; +import org.apache.poi.openxml4j.OpenXML4JTestDataSamples; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; + +public final class TestListParts extends TestCase { + private static Logger logger = Logger.getLogger("org.apache.poi.openxml4j.test"); + + private TreeMap expectedValues; + + private TreeMap values; + + @Override + protected void setUp() throws Exception { + values = new TreeMap(); + + // Expected values + expectedValues = new TreeMap(); + expectedValues.put(PackagingURIHelper.createPartName("/_rels/.rels"), + "application/vnd.openxmlformats-package.relationships+xml"); + + expectedValues + .put(PackagingURIHelper.createPartName("/docProps/app.xml"), + "application/vnd.openxmlformats-officedocument.extended-properties+xml"); + expectedValues.put(PackagingURIHelper + .createPartName("/docProps/core.xml"), + "application/vnd.openxmlformats-package.core-properties+xml"); + expectedValues.put(PackagingURIHelper + .createPartName("/word/_rels/document.xml.rels"), + "application/vnd.openxmlformats-package.relationships+xml"); + expectedValues + .put( + PackagingURIHelper.createPartName("/word/document.xml"), + "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"); + expectedValues + .put(PackagingURIHelper.createPartName("/word/fontTable.xml"), + "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml"); + expectedValues.put(PackagingURIHelper + .createPartName("/word/media/image1.gif"), "image/gif"); + expectedValues + .put(PackagingURIHelper.createPartName("/word/settings.xml"), + "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml"); + expectedValues + .put(PackagingURIHelper.createPartName("/word/styles.xml"), + "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"); + expectedValues.put(PackagingURIHelper + .createPartName("/word/theme/theme1.xml"), + "application/vnd.openxmlformats-officedocument.theme+xml"); + expectedValues + .put( + PackagingURIHelper + .createPartName("/word/webSettings.xml"), + "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml"); + } + + /** + * List all parts of a package. + */ + public void testListParts() throws InvalidFormatException { + InputStream is = OpenXML4JTestDataSamples.openSampleStream("sample.docx"); + + OPCPackage p; + try { + p = OPCPackage.open(is); + } catch (IOException e) { + throw new RuntimeException(e); + } + for (PackagePart part : p.getParts()) { + values.put(part.getPartName(), part.getContentType()); + logger.debug(part.getPartName()); + } + + // Compare expected values with values return by the package + for (PackagePartName partName : expectedValues.keySet()) { + assertNotNull(values.get(partName)); + assertEquals(expectedValues.get(partName), values.get(partName)); + } + } +} diff --git a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackage.java b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackage.java index 0b95bbe119..5f667deba9 100755 --- a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackage.java +++ b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackage.java @@ -1,417 +1,417 @@ -/* ==================================================================== - 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.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.lang.reflect.Field; -import java.net.URI; -import java.util.TreeMap; - -import junit.framework.TestCase; - -import org.apache.log4j.Logger; -import org.apache.poi.openxml4j.OpenXML4JTestDataSamples; -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.opc.internal.ContentTypeManager; -import org.apache.poi.openxml4j.opc.internal.FileHelper; -import org.dom4j.Document; -import org.dom4j.DocumentHelper; -import org.dom4j.Element; -import org.dom4j.Namespace; -import org.dom4j.QName; - -public final class TestPackage extends TestCase { - private static Logger logger = Logger.getLogger("org.apache.poi.openxml4j.test"); - - /** - * Test that just opening and closing the file doesn't alter the document. - */ - public void testOpenSave() throws Exception { - String originalFile = OpenXML4JTestDataSamples.getSampleFileName("TestPackageCommon.docx"); - File targetFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageOpenSaveTMP.docx"); - - Package p = Package.open(originalFile, PackageAccess.READ_WRITE); - p.save(targetFile.getAbsoluteFile()); - - // Compare the original and newly saved document - assertTrue(targetFile.exists()); - //ZipFileAssert.assertEquals(originalFile, targetFile); - assertTrue(targetFile.delete()); - } - - /** - * Test that when we create a new Package, we give it - * the correct default content types - */ - public void testCreateGetsContentTypes() throws Exception { - File targetFile = OpenXML4JTestDataSamples.getOutputFile("TestCreatePackageTMP.docx"); - - // Zap the target file, in case of an earlier run - if(targetFile.exists()) targetFile.delete(); - - Package pkg = Package.create(targetFile); - - // Check it has content types for rels and xml - ContentTypeManager ctm = getContentTypeManager(pkg); - assertEquals( - "application/xml", - ctm.getContentType( - PackagingURIHelper.createPartName("/foo.xml") - ) - ); - assertEquals( - ContentTypes.RELATIONSHIPS_PART, - ctm.getContentType( - PackagingURIHelper.createPartName("/foo.rels") - ) - ); - assertNull( - ctm.getContentType( - PackagingURIHelper.createPartName("/foo.txt") - ) - ); - } - - /** - * Test package creation. - */ - public void testCreatePackageAddPart() throws Exception { - File targetFile = OpenXML4JTestDataSamples.getOutputFile("TestCreatePackageTMP.docx"); - - File expectedFileFile = OpenXML4JTestDataSamples.getOutputFile("TestCreatePackageOUTPUT.docx"); - - // Zap the target file, in case of an earlier run - if(targetFile.exists()) targetFile.delete(); - - // Create a package - Package pkg = Package.create(targetFile); - PackagePartName corePartName = PackagingURIHelper - .createPartName("/word/document.xml"); - - pkg.addRelationship(corePartName, TargetMode.INTERNAL, - PackageRelationshipTypes.CORE_DOCUMENT, "rId1"); - - PackagePart corePart = pkg - .createPart( - corePartName, - "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"); - - Document doc = DocumentHelper.createDocument(); - Namespace nsWordprocessinML = new Namespace("w", - "http://schemas.openxmlformats.org/wordprocessingml/2006/main"); - Element elDocument = doc.addElement(new QName("document", - nsWordprocessinML)); - Element elBody = elDocument.addElement(new QName("body", - nsWordprocessinML)); - Element elParagraph = elBody.addElement(new QName("p", - nsWordprocessinML)); - Element elRun = elParagraph - .addElement(new QName("r", nsWordprocessinML)); - Element elText = elRun.addElement(new QName("t", nsWordprocessinML)); - elText.setText("Hello Open XML !"); - - StreamHelper.saveXmlInStream(doc, corePart.getOutputStream()); - pkg.close(); - - //ZipFileAssert.assertEquals(expectedFile, targetFile); - assertTrue(targetFile.delete()); - } - - /** - * Tests that we can create a new package, add a core - * document and another part, save and re-load and - * have everything setup as expected - */ - public void testCreatePackageWithCoreDocument() throws Exception { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - Package pkg = Package.create(baos); - - // Add a core document - PackagePartName corePartName = PackagingURIHelper.createPartName("/xl/workbook.xml"); - // Create main part relationship - pkg.addRelationship(corePartName, TargetMode.INTERNAL, PackageRelationshipTypes.CORE_DOCUMENT, "rId1"); - // Create main document part - PackagePart corePart = pkg.createPart(corePartName, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"); - // Put in some dummy content - OutputStream coreOut = corePart.getOutputStream(); - coreOut.write("".getBytes()); - coreOut.close(); - - // And another bit - PackagePartName sheetPartName = PackagingURIHelper.createPartName("/xl/worksheets/sheet1.xml"); - PackageRelationship rel = - corePart.addRelationship(sheetPartName, TargetMode.INTERNAL, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet", "rSheet1"); - PackagePart part = pkg.createPart(sheetPartName, "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"); - // Dummy content again - coreOut = corePart.getOutputStream(); - coreOut.write("".getBytes()); - coreOut.close(); - - - // Check things are as expected - PackageRelationshipCollection coreRels = - pkg.getRelationshipsByType(PackageRelationshipTypes.CORE_DOCUMENT); - assertEquals(1, coreRels.size()); - PackageRelationship coreRel = coreRels.getRelationship(0); - assertEquals("/", coreRel.getSourceURI().toString()); - assertEquals("/xl/workbook.xml", coreRel.getTargetURI().toString()); - assertNotNull(pkg.getPart(coreRel)); - - - // Save and re-load - pkg.close(); - FileOutputStream fout = new FileOutputStream(File.createTempFile("testCreatePackageWithCoreDocument", ".zip")); - fout.write(baos.toByteArray()); - fout.close(); - pkg = Package.open(new ByteArrayInputStream(baos.toByteArray())); - - - // Check still right - coreRels = pkg.getRelationshipsByType(PackageRelationshipTypes.CORE_DOCUMENT); - assertEquals(1, coreRels.size()); - coreRel = coreRels.getRelationship(0); - assertEquals("/", coreRel.getSourceURI().toString()); - assertEquals("/xl/workbook.xml", coreRel.getTargetURI().toString()); - assertNotNull(pkg.getPart(coreRel)); - } - - /** - * Test package opening. - */ - public void testOpenPackage() throws Exception { - File targetFile = OpenXML4JTestDataSamples.getOutputFile("TestOpenPackageTMP.docx"); - - File inputFile = OpenXML4JTestDataSamples.getSampleFile("TestOpenPackageINPUT.docx"); - - File expectedFile = OpenXML4JTestDataSamples.getOutputFile("TestOpenPackageOUTPUT.docx"); - - // Copy the input file in the output directory - FileHelper.copyFile(inputFile, targetFile); - - // Create a package - Package pkg = Package.open(targetFile.getAbsolutePath()); - - // Modify core part - PackagePartName corePartName = PackagingURIHelper - .createPartName("/word/document.xml"); - - PackagePart corePart = pkg.getPart(corePartName); - - // Delete some part to have a valid document - for (PackageRelationship rel : corePart.getRelationships()) { - corePart.removeRelationship(rel.getId()); - pkg.removePart(PackagingURIHelper.createPartName(PackagingURIHelper - .resolvePartUri(corePart.getPartName().getURI(), rel - .getTargetURI()))); - } - - // Create a content - Document doc = DocumentHelper.createDocument(); - Namespace nsWordprocessinML = new Namespace("w", - "http://schemas.openxmlformats.org/wordprocessingml/2006/main"); - Element elDocument = doc.addElement(new QName("document", - nsWordprocessinML)); - Element elBody = elDocument.addElement(new QName("body", - nsWordprocessinML)); - Element elParagraph = elBody.addElement(new QName("p", - nsWordprocessinML)); - Element elRun = elParagraph - .addElement(new QName("r", nsWordprocessinML)); - Element elText = elRun.addElement(new QName("t", nsWordprocessinML)); - elText.setText("Hello Open XML !"); - - StreamHelper.saveXmlInStream(doc, corePart.getOutputStream()); - - // Save and close - try { - pkg.close(); - } catch (IOException e) { - fail(); - } - - //ZipFileAssert.assertEquals(expectedFile, targetFile); - assertTrue(targetFile.delete()); - } - - /** - * Checks that we can write a package to a simple - * OutputStream, in addition to the normal writing - * to a file - */ - public void testSaveToOutputStream() throws Exception { - String originalFile = OpenXML4JTestDataSamples.getSampleFileName("TestPackageCommon.docx"); - File targetFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageOpenSaveTMP.docx"); - - Package p = Package.open(originalFile, PackageAccess.READ_WRITE); - FileOutputStream fout = new FileOutputStream(targetFile); - p.save(fout); - fout.close(); - - // Compare the original and newly saved document - assertTrue(targetFile.exists()); - //ZipFileAssert.assertEquals(originalFile, targetFile); - assertTrue(targetFile.delete()); - } - - /** - * Checks that we can open+read a package from a - * simple InputStream, in addition to the normal - * reading from a file - */ - public void testOpenFromInputStream() throws Exception { - String originalFile = OpenXML4JTestDataSamples.getSampleFileName("TestPackageCommon.docx"); - - FileInputStream finp = new FileInputStream(originalFile); - - Package p = Package.open(finp); - - assertNotNull(p); - assertNotNull(p.getRelationships()); - assertEquals(12, p.getParts().size()); - - // Check it has the usual bits - assertTrue(p.hasRelationships()); - assertTrue(p.containPart(PackagingURIHelper.createPartName("/_rels/.rels"))); - } - - /** - * TODO: fix and enable - */ - public void disabled_testRemovePartRecursive() throws Exception { - String originalFile = OpenXML4JTestDataSamples.getSampleFileName("TestPackageCommon.docx"); - File targetFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageRemovePartRecursiveOUTPUT.docx"); - File tempFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageRemovePartRecursiveTMP.docx"); - - Package p = Package.open(originalFile, PackageAccess.READ_WRITE); - p.removePartRecursive(PackagingURIHelper.createPartName(new URI( - "/word/document.xml"))); - p.save(tempFile.getAbsoluteFile()); - - // Compare the original and newly saved document - assertTrue(targetFile.exists()); - //ZipFileAssert.assertEquals(targetFile, tempFile); - assertTrue(targetFile.delete()); - } - - public void testDeletePart() throws InvalidFormatException { - TreeMap expectedValues; - TreeMap values; - - values = new TreeMap(); - - // Expected values - expectedValues = new TreeMap(); - expectedValues.put(PackagingURIHelper.createPartName("/_rels/.rels"), - "application/vnd.openxmlformats-package.relationships+xml"); - - expectedValues - .put(PackagingURIHelper.createPartName("/docProps/app.xml"), - "application/vnd.openxmlformats-officedocument.extended-properties+xml"); - expectedValues.put(PackagingURIHelper - .createPartName("/docProps/core.xml"), - "application/vnd.openxmlformats-package.core-properties+xml"); - expectedValues - .put(PackagingURIHelper.createPartName("/word/fontTable.xml"), - "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml"); - expectedValues.put(PackagingURIHelper - .createPartName("/word/media/image1.gif"), "image/gif"); - expectedValues - .put(PackagingURIHelper.createPartName("/word/settings.xml"), - "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml"); - expectedValues - .put(PackagingURIHelper.createPartName("/word/styles.xml"), - "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"); - expectedValues.put(PackagingURIHelper - .createPartName("/word/theme/theme1.xml"), - "application/vnd.openxmlformats-officedocument.theme+xml"); - expectedValues - .put( - PackagingURIHelper - .createPartName("/word/webSettings.xml"), - "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml"); - - String filepath = OpenXML4JTestDataSamples.getSampleFileName("sample.docx"); - - Package p = Package.open(filepath, PackageAccess.READ_WRITE); - // Remove the core part - p.deletePart(PackagingURIHelper.createPartName("/word/document.xml")); - - for (PackagePart part : p.getParts()) { - values.put(part.getPartName(), part.getContentType()); - logger.debug(part.getPartName()); - } - - // Compare expected values with values return by the package - for (PackagePartName partName : expectedValues.keySet()) { - assertNotNull(values.get(partName)); - assertEquals(expectedValues.get(partName), values.get(partName)); - } - // Don't save modifications - p.revert(); - } - - public void testDeletePartRecursive() throws InvalidFormatException { - TreeMap expectedValues; - TreeMap values; - - values = new TreeMap(); - - // Expected values - expectedValues = new TreeMap(); - expectedValues.put(PackagingURIHelper.createPartName("/_rels/.rels"), - "application/vnd.openxmlformats-package.relationships+xml"); - - expectedValues - .put(PackagingURIHelper.createPartName("/docProps/app.xml"), - "application/vnd.openxmlformats-officedocument.extended-properties+xml"); - expectedValues.put(PackagingURIHelper - .createPartName("/docProps/core.xml"), - "application/vnd.openxmlformats-package.core-properties+xml"); - - String filepath = OpenXML4JTestDataSamples.getSampleFileName("sample.docx"); - - Package p = Package.open(filepath, PackageAccess.READ_WRITE); - // Remove the core part - p.deletePartRecursive(PackagingURIHelper.createPartName("/word/document.xml")); - - for (PackagePart part : p.getParts()) { - values.put(part.getPartName(), part.getContentType()); - logger.debug(part.getPartName()); - } - - // Compare expected values with values return by the package - for (PackagePartName partName : expectedValues.keySet()) { - assertNotNull(values.get(partName)); - assertEquals(expectedValues.get(partName), values.get(partName)); - } - // Don't save modifications - p.revert(); - } - - private static ContentTypeManager getContentTypeManager(Package pkg) throws Exception { - Field f = Package.class.getDeclaredField("contentTypeManager"); - f.setAccessible(true); - return (ContentTypeManager)f.get(pkg); - } -} +/* ==================================================================== + 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.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.net.URI; +import java.util.TreeMap; + +import junit.framework.TestCase; + +import org.apache.log4j.Logger; +import org.apache.poi.openxml4j.OpenXML4JTestDataSamples; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.opc.internal.ContentTypeManager; +import org.apache.poi.openxml4j.opc.internal.FileHelper; +import org.dom4j.Document; +import org.dom4j.DocumentHelper; +import org.dom4j.Element; +import org.dom4j.Namespace; +import org.dom4j.QName; + +public final class TestPackage extends TestCase { + private static Logger logger = Logger.getLogger("org.apache.poi.openxml4j.test"); + + /** + * Test that just opening and closing the file doesn't alter the document. + */ + public void testOpenSave() throws Exception { + String originalFile = OpenXML4JTestDataSamples.getSampleFileName("TestPackageCommon.docx"); + File targetFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageOpenSaveTMP.docx"); + + OPCPackage p = OPCPackage.open(originalFile, PackageAccess.READ_WRITE); + p.save(targetFile.getAbsoluteFile()); + + // Compare the original and newly saved document + assertTrue(targetFile.exists()); + //ZipFileAssert.assertEquals(originalFile, targetFile); + assertTrue(targetFile.delete()); + } + + /** + * Test that when we create a new Package, we give it + * the correct default content types + */ + public void testCreateGetsContentTypes() throws Exception { + File targetFile = OpenXML4JTestDataSamples.getOutputFile("TestCreatePackageTMP.docx"); + + // Zap the target file, in case of an earlier run + if(targetFile.exists()) targetFile.delete(); + + OPCPackage pkg = OPCPackage.create(targetFile); + + // Check it has content types for rels and xml + ContentTypeManager ctm = getContentTypeManager(pkg); + assertEquals( + "application/xml", + ctm.getContentType( + PackagingURIHelper.createPartName("/foo.xml") + ) + ); + assertEquals( + ContentTypes.RELATIONSHIPS_PART, + ctm.getContentType( + PackagingURIHelper.createPartName("/foo.rels") + ) + ); + assertNull( + ctm.getContentType( + PackagingURIHelper.createPartName("/foo.txt") + ) + ); + } + + /** + * Test package creation. + */ + public void testCreatePackageAddPart() throws Exception { + File targetFile = OpenXML4JTestDataSamples.getOutputFile("TestCreatePackageTMP.docx"); + + File expectedFileFile = OpenXML4JTestDataSamples.getOutputFile("TestCreatePackageOUTPUT.docx"); + + // Zap the target file, in case of an earlier run + if(targetFile.exists()) targetFile.delete(); + + // Create a package + OPCPackage pkg = OPCPackage.create(targetFile); + PackagePartName corePartName = PackagingURIHelper + .createPartName("/word/document.xml"); + + pkg.addRelationship(corePartName, TargetMode.INTERNAL, + PackageRelationshipTypes.CORE_DOCUMENT, "rId1"); + + PackagePart corePart = pkg + .createPart( + corePartName, + "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"); + + Document doc = DocumentHelper.createDocument(); + Namespace nsWordprocessinML = new Namespace("w", + "http://schemas.openxmlformats.org/wordprocessingml/2006/main"); + Element elDocument = doc.addElement(new QName("document", + nsWordprocessinML)); + Element elBody = elDocument.addElement(new QName("body", + nsWordprocessinML)); + Element elParagraph = elBody.addElement(new QName("p", + nsWordprocessinML)); + Element elRun = elParagraph + .addElement(new QName("r", nsWordprocessinML)); + Element elText = elRun.addElement(new QName("t", nsWordprocessinML)); + elText.setText("Hello Open XML !"); + + StreamHelper.saveXmlInStream(doc, corePart.getOutputStream()); + pkg.close(); + + //ZipFileAssert.assertEquals(expectedFile, targetFile); + assertTrue(targetFile.delete()); + } + + /** + * Tests that we can create a new package, add a core + * document and another part, save and re-load and + * have everything setup as expected + */ + public void testCreatePackageWithCoreDocument() throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + OPCPackage pkg = OPCPackage.create(baos); + + // Add a core document + PackagePartName corePartName = PackagingURIHelper.createPartName("/xl/workbook.xml"); + // Create main part relationship + pkg.addRelationship(corePartName, TargetMode.INTERNAL, PackageRelationshipTypes.CORE_DOCUMENT, "rId1"); + // Create main document part + PackagePart corePart = pkg.createPart(corePartName, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"); + // Put in some dummy content + OutputStream coreOut = corePart.getOutputStream(); + coreOut.write("".getBytes()); + coreOut.close(); + + // And another bit + PackagePartName sheetPartName = PackagingURIHelper.createPartName("/xl/worksheets/sheet1.xml"); + PackageRelationship rel = + corePart.addRelationship(sheetPartName, TargetMode.INTERNAL, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet", "rSheet1"); + PackagePart part = pkg.createPart(sheetPartName, "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"); + // Dummy content again + coreOut = corePart.getOutputStream(); + coreOut.write("".getBytes()); + coreOut.close(); + + + // Check things are as expected + PackageRelationshipCollection coreRels = + pkg.getRelationshipsByType(PackageRelationshipTypes.CORE_DOCUMENT); + assertEquals(1, coreRels.size()); + PackageRelationship coreRel = coreRels.getRelationship(0); + assertEquals("/", coreRel.getSourceURI().toString()); + assertEquals("/xl/workbook.xml", coreRel.getTargetURI().toString()); + assertNotNull(pkg.getPart(coreRel)); + + + // Save and re-load + pkg.close(); + FileOutputStream fout = new FileOutputStream(File.createTempFile("testCreatePackageWithCoreDocument", ".zip")); + fout.write(baos.toByteArray()); + fout.close(); + pkg = OPCPackage.open(new ByteArrayInputStream(baos.toByteArray())); + + + // Check still right + coreRels = pkg.getRelationshipsByType(PackageRelationshipTypes.CORE_DOCUMENT); + assertEquals(1, coreRels.size()); + coreRel = coreRels.getRelationship(0); + assertEquals("/", coreRel.getSourceURI().toString()); + assertEquals("/xl/workbook.xml", coreRel.getTargetURI().toString()); + assertNotNull(pkg.getPart(coreRel)); + } + + /** + * Test package opening. + */ + public void testOpenPackage() throws Exception { + File targetFile = OpenXML4JTestDataSamples.getOutputFile("TestOpenPackageTMP.docx"); + + File inputFile = OpenXML4JTestDataSamples.getSampleFile("TestOpenPackageINPUT.docx"); + + File expectedFile = OpenXML4JTestDataSamples.getOutputFile("TestOpenPackageOUTPUT.docx"); + + // Copy the input file in the output directory + FileHelper.copyFile(inputFile, targetFile); + + // Create a package + OPCPackage pkg = OPCPackage.open(targetFile.getAbsolutePath()); + + // Modify core part + PackagePartName corePartName = PackagingURIHelper + .createPartName("/word/document.xml"); + + PackagePart corePart = pkg.getPart(corePartName); + + // Delete some part to have a valid document + for (PackageRelationship rel : corePart.getRelationships()) { + corePart.removeRelationship(rel.getId()); + pkg.removePart(PackagingURIHelper.createPartName(PackagingURIHelper + .resolvePartUri(corePart.getPartName().getURI(), rel + .getTargetURI()))); + } + + // Create a content + Document doc = DocumentHelper.createDocument(); + Namespace nsWordprocessinML = new Namespace("w", + "http://schemas.openxmlformats.org/wordprocessingml/2006/main"); + Element elDocument = doc.addElement(new QName("document", + nsWordprocessinML)); + Element elBody = elDocument.addElement(new QName("body", + nsWordprocessinML)); + Element elParagraph = elBody.addElement(new QName("p", + nsWordprocessinML)); + Element elRun = elParagraph + .addElement(new QName("r", nsWordprocessinML)); + Element elText = elRun.addElement(new QName("t", nsWordprocessinML)); + elText.setText("Hello Open XML !"); + + StreamHelper.saveXmlInStream(doc, corePart.getOutputStream()); + + // Save and close + try { + pkg.close(); + } catch (IOException e) { + fail(); + } + + //ZipFileAssert.assertEquals(expectedFile, targetFile); + assertTrue(targetFile.delete()); + } + + /** + * Checks that we can write a package to a simple + * OutputStream, in addition to the normal writing + * to a file + */ + public void testSaveToOutputStream() throws Exception { + String originalFile = OpenXML4JTestDataSamples.getSampleFileName("TestPackageCommon.docx"); + File targetFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageOpenSaveTMP.docx"); + + OPCPackage p = OPCPackage.open(originalFile, PackageAccess.READ_WRITE); + FileOutputStream fout = new FileOutputStream(targetFile); + p.save(fout); + fout.close(); + + // Compare the original and newly saved document + assertTrue(targetFile.exists()); + //ZipFileAssert.assertEquals(originalFile, targetFile); + assertTrue(targetFile.delete()); + } + + /** + * Checks that we can open+read a package from a + * simple InputStream, in addition to the normal + * reading from a file + */ + public void testOpenFromInputStream() throws Exception { + String originalFile = OpenXML4JTestDataSamples.getSampleFileName("TestPackageCommon.docx"); + + FileInputStream finp = new FileInputStream(originalFile); + + OPCPackage p = OPCPackage.open(finp); + + assertNotNull(p); + assertNotNull(p.getRelationships()); + assertEquals(12, p.getParts().size()); + + // Check it has the usual bits + assertTrue(p.hasRelationships()); + assertTrue(p.containPart(PackagingURIHelper.createPartName("/_rels/.rels"))); + } + + /** + * TODO: fix and enable + */ + public void disabled_testRemovePartRecursive() throws Exception { + String originalFile = OpenXML4JTestDataSamples.getSampleFileName("TestPackageCommon.docx"); + File targetFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageRemovePartRecursiveOUTPUT.docx"); + File tempFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageRemovePartRecursiveTMP.docx"); + + OPCPackage p = OPCPackage.open(originalFile, PackageAccess.READ_WRITE); + p.removePartRecursive(PackagingURIHelper.createPartName(new URI( + "/word/document.xml"))); + p.save(tempFile.getAbsoluteFile()); + + // Compare the original and newly saved document + assertTrue(targetFile.exists()); + //ZipFileAssert.assertEquals(targetFile, tempFile); + assertTrue(targetFile.delete()); + } + + public void testDeletePart() throws InvalidFormatException { + TreeMap expectedValues; + TreeMap values; + + values = new TreeMap(); + + // Expected values + expectedValues = new TreeMap(); + expectedValues.put(PackagingURIHelper.createPartName("/_rels/.rels"), + "application/vnd.openxmlformats-package.relationships+xml"); + + expectedValues + .put(PackagingURIHelper.createPartName("/docProps/app.xml"), + "application/vnd.openxmlformats-officedocument.extended-properties+xml"); + expectedValues.put(PackagingURIHelper + .createPartName("/docProps/core.xml"), + "application/vnd.openxmlformats-package.core-properties+xml"); + expectedValues + .put(PackagingURIHelper.createPartName("/word/fontTable.xml"), + "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml"); + expectedValues.put(PackagingURIHelper + .createPartName("/word/media/image1.gif"), "image/gif"); + expectedValues + .put(PackagingURIHelper.createPartName("/word/settings.xml"), + "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml"); + expectedValues + .put(PackagingURIHelper.createPartName("/word/styles.xml"), + "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"); + expectedValues.put(PackagingURIHelper + .createPartName("/word/theme/theme1.xml"), + "application/vnd.openxmlformats-officedocument.theme+xml"); + expectedValues + .put( + PackagingURIHelper + .createPartName("/word/webSettings.xml"), + "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml"); + + String filepath = OpenXML4JTestDataSamples.getSampleFileName("sample.docx"); + + OPCPackage p = OPCPackage.open(filepath, PackageAccess.READ_WRITE); + // Remove the core part + p.deletePart(PackagingURIHelper.createPartName("/word/document.xml")); + + for (PackagePart part : p.getParts()) { + values.put(part.getPartName(), part.getContentType()); + logger.debug(part.getPartName()); + } + + // Compare expected values with values return by the package + for (PackagePartName partName : expectedValues.keySet()) { + assertNotNull(values.get(partName)); + assertEquals(expectedValues.get(partName), values.get(partName)); + } + // Don't save modifications + p.revert(); + } + + public void testDeletePartRecursive() throws InvalidFormatException { + TreeMap expectedValues; + TreeMap values; + + values = new TreeMap(); + + // Expected values + expectedValues = new TreeMap(); + expectedValues.put(PackagingURIHelper.createPartName("/_rels/.rels"), + "application/vnd.openxmlformats-package.relationships+xml"); + + expectedValues + .put(PackagingURIHelper.createPartName("/docProps/app.xml"), + "application/vnd.openxmlformats-officedocument.extended-properties+xml"); + expectedValues.put(PackagingURIHelper + .createPartName("/docProps/core.xml"), + "application/vnd.openxmlformats-package.core-properties+xml"); + + String filepath = OpenXML4JTestDataSamples.getSampleFileName("sample.docx"); + + OPCPackage p = OPCPackage.open(filepath, PackageAccess.READ_WRITE); + // Remove the core part + p.deletePartRecursive(PackagingURIHelper.createPartName("/word/document.xml")); + + for (PackagePart part : p.getParts()) { + values.put(part.getPartName(), part.getContentType()); + logger.debug(part.getPartName()); + } + + // Compare expected values with values return by the package + for (PackagePartName partName : expectedValues.keySet()) { + assertNotNull(values.get(partName)); + assertEquals(expectedValues.get(partName), values.get(partName)); + } + // Don't save modifications + p.revert(); + } + + private static ContentTypeManager getContentTypeManager(OPCPackage pkg) throws Exception { + Field f = OPCPackage.class.getDeclaredField("contentTypeManager"); + f.setAccessible(true); + return (ContentTypeManager)f.get(pkg); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackageCoreProperties.java b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackageCoreProperties.java index 54e21b89d3..1014279981 100755 --- a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackageCoreProperties.java +++ b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackageCoreProperties.java @@ -1,121 +1,121 @@ -/* ==================================================================== - 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.text.ParsePosition; -import java.text.SimpleDateFormat; -import java.util.Date; - -import junit.framework.TestCase; - -import org.apache.log4j.Logger; -import org.apache.poi.openxml4j.OpenXML4JTestDataSamples; -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.exceptions.OpenXML4JException; -import org.apache.poi.openxml4j.util.Nullable; - -public final class TestPackageCoreProperties extends TestCase { - - /** - * Test package core properties getters. - */ - public void testGetProperties() { - try { - // Open the package - Package p = Package.open(OpenXML4JTestDataSamples.openSampleStream("TestPackageCoreProperiesGetters.docx")); - compareProperties(p); - p.revert(); - } catch (OpenXML4JException e) { - Logger.getLogger("org.apache.poi.openxml4j.demo").debug(e.getMessage()); - throw new RuntimeException(e); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - /** - * Test package core properties setters. - */ - public void testSetProperties() throws Exception { - String inputPath = OpenXML4JTestDataSamples.getSampleFileName("TestPackageCoreProperiesSetters.docx"); - - File outputFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageCoreProperiesSettersOUTPUT.docx"); - - // Open package - Package p = Package.open(inputPath, PackageAccess.READ_WRITE); - - SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); - Date dateToInsert = df.parse("2007-05-12T08:00:00Z", new ParsePosition( - 0)); - - PackageProperties props = p.getPackageProperties(); - props.setCategoryProperty("MyCategory"); - props.setContentStatusProperty("MyContentStatus"); - props.setContentTypeProperty("MyContentType"); - props.setCreatedProperty(new Nullable(dateToInsert)); - props.setCreatorProperty("MyCreator"); - props.setDescriptionProperty("MyDescription"); - props.setIdentifierProperty("MyIdentifier"); - props.setKeywordsProperty("MyKeywords"); - props.setLanguageProperty("MyLanguage"); - props.setLastModifiedByProperty("Julien Chable"); - props.setLastPrintedProperty(new Nullable(dateToInsert)); - props.setModifiedProperty(new Nullable(dateToInsert)); - props.setRevisionProperty("2"); - props.setTitleProperty("MyTitle"); - props.setSubjectProperty("MySubject"); - props.setVersionProperty("2"); - // Save the package in the output directory - p.save(outputFile); - - // Open the newly created file to check core properties saved values. - Package p2 = Package.open(outputFile.getAbsolutePath(), PackageAccess.READ); - compareProperties(p2); - p2.revert(); - outputFile.delete(); - } - - private void compareProperties(Package p) throws InvalidFormatException { - SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); - Date expectedDate = df.parse("2007-05-12T08:00:00Z", new ParsePosition( - 0)); - - // Gets the core properties - PackageProperties props = p.getPackageProperties(); - assertEquals("MyCategory", props.getCategoryProperty().getValue()); - assertEquals("MyContentStatus", props.getContentStatusProperty() - .getValue()); - assertEquals("MyContentType", props.getContentTypeProperty().getValue()); - assertEquals(expectedDate, props.getCreatedProperty().getValue()); - assertEquals("MyCreator", props.getCreatorProperty().getValue()); - assertEquals("MyDescription", props.getDescriptionProperty().getValue()); - assertEquals("MyIdentifier", props.getIdentifierProperty().getValue()); - assertEquals("MyKeywords", props.getKeywordsProperty().getValue()); - assertEquals("MyLanguage", props.getLanguageProperty().getValue()); - assertEquals("Julien Chable", props.getLastModifiedByProperty() - .getValue()); - assertEquals(expectedDate, props.getLastPrintedProperty().getValue()); - assertEquals(expectedDate, props.getModifiedProperty().getValue()); - assertEquals("2", props.getRevisionProperty().getValue()); - assertEquals("MySubject", props.getSubjectProperty().getValue()); - assertEquals("MyTitle", props.getTitleProperty().getValue()); - assertEquals("2", props.getVersionProperty().getValue()); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc; + +import java.io.File; +import java.io.IOException; +import java.text.ParsePosition; +import java.text.SimpleDateFormat; +import java.util.Date; + +import junit.framework.TestCase; + +import org.apache.log4j.Logger; +import org.apache.poi.openxml4j.OpenXML4JTestDataSamples; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.openxml4j.util.Nullable; + +public final class TestPackageCoreProperties extends TestCase { + + /** + * Test package core properties getters. + */ + public void testGetProperties() { + try { + // Open the package + OPCPackage p = OPCPackage.open(OpenXML4JTestDataSamples.openSampleStream("TestPackageCoreProperiesGetters.docx")); + compareProperties(p); + p.revert(); + } catch (OpenXML4JException e) { + Logger.getLogger("org.apache.poi.openxml4j.demo").debug(e.getMessage()); + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * Test package core properties setters. + */ + public void testSetProperties() throws Exception { + String inputPath = OpenXML4JTestDataSamples.getSampleFileName("TestPackageCoreProperiesSetters.docx"); + + File outputFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageCoreProperiesSettersOUTPUT.docx"); + + // Open package + OPCPackage p = OPCPackage.open(inputPath, PackageAccess.READ_WRITE); + + SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + Date dateToInsert = df.parse("2007-05-12T08:00:00Z", new ParsePosition( + 0)); + + PackageProperties props = p.getPackageProperties(); + props.setCategoryProperty("MyCategory"); + props.setContentStatusProperty("MyContentStatus"); + props.setContentTypeProperty("MyContentType"); + props.setCreatedProperty(new Nullable(dateToInsert)); + props.setCreatorProperty("MyCreator"); + props.setDescriptionProperty("MyDescription"); + props.setIdentifierProperty("MyIdentifier"); + props.setKeywordsProperty("MyKeywords"); + props.setLanguageProperty("MyLanguage"); + props.setLastModifiedByProperty("Julien Chable"); + props.setLastPrintedProperty(new Nullable(dateToInsert)); + props.setModifiedProperty(new Nullable(dateToInsert)); + props.setRevisionProperty("2"); + props.setTitleProperty("MyTitle"); + props.setSubjectProperty("MySubject"); + props.setVersionProperty("2"); + // Save the package in the output directory + p.save(outputFile); + + // Open the newly created file to check core properties saved values. + OPCPackage p2 = OPCPackage.open(outputFile.getAbsolutePath(), PackageAccess.READ); + compareProperties(p2); + p2.revert(); + outputFile.delete(); + } + + private void compareProperties(OPCPackage p) throws InvalidFormatException { + SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + Date expectedDate = df.parse("2007-05-12T08:00:00Z", new ParsePosition( + 0)); + + // Gets the core properties + PackageProperties props = p.getPackageProperties(); + assertEquals("MyCategory", props.getCategoryProperty().getValue()); + assertEquals("MyContentStatus", props.getContentStatusProperty() + .getValue()); + assertEquals("MyContentType", props.getContentTypeProperty().getValue()); + assertEquals(expectedDate, props.getCreatedProperty().getValue()); + assertEquals("MyCreator", props.getCreatorProperty().getValue()); + assertEquals("MyDescription", props.getDescriptionProperty().getValue()); + assertEquals("MyIdentifier", props.getIdentifierProperty().getValue()); + assertEquals("MyKeywords", props.getKeywordsProperty().getValue()); + assertEquals("MyLanguage", props.getLanguageProperty().getValue()); + assertEquals("Julien Chable", props.getLastModifiedByProperty() + .getValue()); + assertEquals(expectedDate, props.getLastPrintedProperty().getValue()); + assertEquals(expectedDate, props.getModifiedProperty().getValue()); + assertEquals("2", props.getRevisionProperty().getValue()); + assertEquals("MySubject", props.getSubjectProperty().getValue()); + assertEquals("MyTitle", props.getTitleProperty().getValue()); + assertEquals("2", props.getVersionProperty().getValue()); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackageThumbnail.java b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackageThumbnail.java index a7b9e7b6f6..01a44327c7 100755 --- a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackageThumbnail.java +++ b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackageThumbnail.java @@ -1,57 +1,57 @@ -/* ==================================================================== - 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 junit.framework.TestCase; - -import org.apache.poi.openxml4j.OpenXML4JTestDataSamples; - -/** - * Test the addition of thumbnail in a package. - * - * @author Julien Chable - */ -public final class TestPackageThumbnail extends TestCase { - - /** - * Test package addThumbnail() method. - */ - public void testSetProperties() throws Exception { - String inputPath = OpenXML4JTestDataSamples.getSampleFileName("TestPackageThumbnail.docx"); - - String imagePath = OpenXML4JTestDataSamples.getSampleFileName("thumbnail.jpg"); - - File outputFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageThumbnailOUTPUT.docx"); - - // Open package - Package p = Package.open(inputPath, PackageAccess.READ_WRITE); - p.addThumbnail(imagePath); - // Save the package in the output directory - p.save(outputFile); - - // Open the newly created file to check core properties saved values. - Package p2 = Package.open(outputFile.getAbsolutePath(), PackageAccess.READ); - if (p2.getRelationshipsByType(PackageRelationshipTypes.THUMBNAIL) - .size() == 0) - fail("Thumbnail not added to the package !"); - p2.revert(); - outputFile.delete(); - } -} +/* ==================================================================== + 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 junit.framework.TestCase; + +import org.apache.poi.openxml4j.OpenXML4JTestDataSamples; + +/** + * Test the addition of thumbnail in a package. + * + * @author Julien Chable + */ +public final class TestPackageThumbnail extends TestCase { + + /** + * Test package addThumbnail() method. + */ + public void testSetProperties() throws Exception { + String inputPath = OpenXML4JTestDataSamples.getSampleFileName("TestPackageThumbnail.docx"); + + String imagePath = OpenXML4JTestDataSamples.getSampleFileName("thumbnail.jpg"); + + File outputFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageThumbnailOUTPUT.docx"); + + // Open package + OPCPackage p = OPCPackage.open(inputPath, PackageAccess.READ_WRITE); + p.addThumbnail(imagePath); + // Save the package in the output directory + p.save(outputFile); + + // Open the newly created file to check core properties saved values. + OPCPackage p2 = OPCPackage.open(outputFile.getAbsolutePath(), PackageAccess.READ); + if (p2.getRelationshipsByType(PackageRelationshipTypes.THUMBNAIL) + .size() == 0) + fail("Thumbnail not added to the package !"); + p2.revert(); + outputFile.delete(); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackagingURIHelper.java b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackagingURIHelper.java index 478552f70f..48a4b4ecc1 100755 --- a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackagingURIHelper.java +++ b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackagingURIHelper.java @@ -1,117 +1,117 @@ -/* ==================================================================== - 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 junit.framework.TestCase; - -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -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.PackagingURIHelper; - -public class TestPackagingURIHelper extends TestCase { - - /** - * Test relativizePartName() method. - * - * TODO: fix and unable - */ - public void testRelativizeURI() throws Exception { - URI uri1 = new URI("/word/document.xml"); - URI uri2 = new URI("/word/media/image1.gif"); - - // Document to image is down a directory - URI retURI1to2 = PackagingURIHelper.relativizeURI(uri1, uri2); - assertEquals("media/image1.gif", retURI1to2.getPath()); - // Image to document is up a directory - URI retURI2to1 = PackagingURIHelper.relativizeURI(uri2, uri1); - assertEquals("../document.xml", retURI2to1.getPath()); - - // Document and CustomXML parts totally different [Julien C.] - URI uriCustomXml = new URI("/customXml/item1.xml"); - URI uriRes = PackagingURIHelper.relativizeURI(uri1, uriCustomXml); - assertEquals("../customXml/item1.xml", uriRes.toString()); - - // Document to itself is the same place (empty URI) - URI retURI2 = PackagingURIHelper.relativizeURI(uri1, uri1); - assertEquals("", retURI2.getPath()); - - // Document and root totally different - URI uri4 = new URI("/"); - try { - PackagingURIHelper.relativizeURI(uri1, uri4); - //TODO: figure oout why the assertion fails - //fail("Must throw an exception ! Can't relativize with an empty URI"); - } catch (Exception e) { - // Do nothing - } - try { - PackagingURIHelper.relativizeURI(uri4, uri1); - //TODO: figure oout why the assertion fails - //fail("Must throw an exception ! Can't relativize with an empty URI"); - } catch (Exception e) { - // Do nothing - } - } - - /** - * Test createPartName(String, y) - */ - public void testCreatePartNameRelativeString() - throws InvalidFormatException { - PackagePartName partNameToValid = PackagingURIHelper - .createPartName("/word/media/image1.gif"); - - Package pkg = Package.create("DELETEIFEXISTS.docx"); - // Base part - PackagePartName nameBase = PackagingURIHelper - .createPartName("/word/document.xml"); - PackagePart partBase = pkg.createPart(nameBase, ContentTypes.XML); - // Relative part name - PackagePartName relativeName = PackagingURIHelper.createPartName( - "media/image1.gif", partBase); - assertTrue("The part name must be equal to " - + partNameToValid.getName(), partNameToValid - .equals(relativeName)); - pkg.revert(); - } - - /** - * Test createPartName(URI, y) - */ - public void testCreatePartNameRelativeURI() throws Exception { - PackagePartName partNameToValid = PackagingURIHelper - .createPartName("/word/media/image1.gif"); - - Package pkg = Package.create("DELETEIFEXISTS.docx"); - // Base part - PackagePartName nameBase = PackagingURIHelper - .createPartName("/word/document.xml"); - PackagePart partBase = pkg.createPart(nameBase, ContentTypes.XML); - // Relative part name - PackagePartName relativeName = PackagingURIHelper.createPartName( - new URI("media/image1.gif"), partBase); - assertTrue("The part name must be equal to " - + partNameToValid.getName(), partNameToValid - .equals(relativeName)); - pkg.revert(); - } -} +/* ==================================================================== + 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 junit.framework.TestCase; + +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.opc.ContentTypes; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.openxml4j.opc.PackagePartName; +import org.apache.poi.openxml4j.opc.PackagingURIHelper; + +public class TestPackagingURIHelper extends TestCase { + + /** + * Test relativizePartName() method. + * + * TODO: fix and unable + */ + public void testRelativizeURI() throws Exception { + URI uri1 = new URI("/word/document.xml"); + URI uri2 = new URI("/word/media/image1.gif"); + + // Document to image is down a directory + URI retURI1to2 = PackagingURIHelper.relativizeURI(uri1, uri2); + assertEquals("media/image1.gif", retURI1to2.getPath()); + // Image to document is up a directory + URI retURI2to1 = PackagingURIHelper.relativizeURI(uri2, uri1); + assertEquals("../document.xml", retURI2to1.getPath()); + + // Document and CustomXML parts totally different [Julien C.] + URI uriCustomXml = new URI("/customXml/item1.xml"); + URI uriRes = PackagingURIHelper.relativizeURI(uri1, uriCustomXml); + assertEquals("../customXml/item1.xml", uriRes.toString()); + + // Document to itself is the same place (empty URI) + URI retURI2 = PackagingURIHelper.relativizeURI(uri1, uri1); + assertEquals("", retURI2.getPath()); + + // Document and root totally different + URI uri4 = new URI("/"); + try { + PackagingURIHelper.relativizeURI(uri1, uri4); + //TODO: figure oout why the assertion fails + //fail("Must throw an exception ! Can't relativize with an empty URI"); + } catch (Exception e) { + // Do nothing + } + try { + PackagingURIHelper.relativizeURI(uri4, uri1); + //TODO: figure oout why the assertion fails + //fail("Must throw an exception ! Can't relativize with an empty URI"); + } catch (Exception e) { + // Do nothing + } + } + + /** + * Test createPartName(String, y) + */ + public void testCreatePartNameRelativeString() + throws InvalidFormatException { + PackagePartName partNameToValid = PackagingURIHelper + .createPartName("/word/media/image1.gif"); + + OPCPackage pkg = OPCPackage.create("DELETEIFEXISTS.docx"); + // Base part + PackagePartName nameBase = PackagingURIHelper + .createPartName("/word/document.xml"); + PackagePart partBase = pkg.createPart(nameBase, ContentTypes.XML); + // Relative part name + PackagePartName relativeName = PackagingURIHelper.createPartName( + "media/image1.gif", partBase); + assertTrue("The part name must be equal to " + + partNameToValid.getName(), partNameToValid + .equals(relativeName)); + pkg.revert(); + } + + /** + * Test createPartName(URI, y) + */ + public void testCreatePartNameRelativeURI() throws Exception { + PackagePartName partNameToValid = PackagingURIHelper + .createPartName("/word/media/image1.gif"); + + OPCPackage pkg = OPCPackage.create("DELETEIFEXISTS.docx"); + // Base part + PackagePartName nameBase = PackagingURIHelper + .createPartName("/word/document.xml"); + PackagePart partBase = pkg.createPart(nameBase, ContentTypes.XML); + // Relative part name + PackagePartName relativeName = PackagingURIHelper.createPartName( + new URI("media/image1.gif"), partBase); + assertTrue("The part name must be equal to " + + partNameToValid.getName(), partNameToValid + .equals(relativeName)); + pkg.revert(); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestRelationships.java b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestRelationships.java index 972bd268a3..a4ef876b47 100755 --- a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestRelationships.java +++ b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestRelationships.java @@ -45,7 +45,7 @@ public class TestRelationships extends TestCase { */ public void testLoadRelationships() throws Exception { InputStream is = OpenXML4JTestDataSamples.openSampleStream("sample.xlsx"); - Package pkg = Package.open(is); + OPCPackage pkg = OPCPackage.open(is); logger.debug("1: " + pkg); PackageRelationshipCollection rels = pkg.getRelationshipsByType(PackageRelationshipTypes.CORE_DOCUMENT); PackageRelationship coreDocRelationship = rels.getRelationship(0); @@ -66,7 +66,7 @@ public class TestRelationships extends TestCase { */ public void testFetchFromCollection() throws Exception { InputStream is = OpenXML4JTestDataSamples.openSampleStream("ExcelWithHyperlinks.xlsx"); - Package pkg = Package.open(is); + OPCPackage pkg = OPCPackage.open(is); PackagePart sheet = pkg.getPart( PackagingURIHelper.createPartName(SHEET_WITH_COMMENTS)); assertNotNull(sheet); @@ -107,7 +107,7 @@ public class TestRelationships extends TestCase { */ public void testLoadExcelHyperlinkRelations() throws Exception { InputStream is = OpenXML4JTestDataSamples.openSampleStream("ExcelWithHyperlinks.xlsx"); - Package pkg = Package.open(is); + OPCPackage pkg = OPCPackage.open(is); PackagePart sheet = pkg.getPart( PackagingURIHelper.createPartName(SHEET_WITH_COMMENTS)); assertNotNull(sheet); @@ -141,7 +141,7 @@ public class TestRelationships extends TestCase { */ public void testCreateExcelHyperlinkRelations() throws Exception { String filepath = OpenXML4JTestDataSamples.getSampleFileName("ExcelWithHyperlinks.xlsx"); - Package pkg = Package.open(filepath, PackageAccess.READ_WRITE); + OPCPackage pkg = OPCPackage.open(filepath, PackageAccess.READ_WRITE); PackagePart sheet = pkg.getPart( PackagingURIHelper.createPartName(SHEET_WITH_COMMENTS)); assertNotNull(sheet); @@ -185,7 +185,7 @@ public class TestRelationships extends TestCase { ByteArrayOutputStream baos = new ByteArrayOutputStream(); pkg.save(baos); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); - pkg = Package.open(bais); + pkg = OPCPackage.open(bais); // Check again sheet = pkg.getPart( @@ -208,7 +208,7 @@ public class TestRelationships extends TestCase { public void testCreateRelationsFromScratch() throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); - Package pkg = Package.create(baos); + OPCPackage pkg = OPCPackage.create(baos); PackagePart partA = pkg.createPart(PackagingURIHelper.createPartName("/partA"), "text/plain"); @@ -235,7 +235,7 @@ public class TestRelationships extends TestCase { // Save, and re-load pkg.close(); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); - pkg = Package.open(bais); + pkg = OPCPackage.open(bais); partA = pkg.getPart(PackagingURIHelper.createPartName("/partA")); partB = pkg.getPart(PackagingURIHelper.createPartName("/partB")); diff --git a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/compliance/TestOPCComplianceCoreProperties.java b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/compliance/TestOPCComplianceCoreProperties.java index d2cb8f616e..7d26fddd7a 100755 --- a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/compliance/TestOPCComplianceCoreProperties.java +++ b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/compliance/TestOPCComplianceCoreProperties.java @@ -1,208 +1,208 @@ -/* ==================================================================== - 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.compliance; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.net.URISyntaxException; - -import junit.framework.AssertionFailedError; -import junit.framework.TestCase; - -import org.apache.poi.openxml4j.OpenXML4JTestDataSamples; -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.exceptions.InvalidOperationException; -import org.apache.poi.openxml4j.opc.ContentTypes; -import org.apache.poi.openxml4j.opc.Package; -import org.apache.poi.openxml4j.opc.PackageRelationshipTypes; -import org.apache.poi.openxml4j.opc.PackagingURIHelper; -import org.apache.poi.openxml4j.opc.TargetMode; - -/** - * Test core properties Open Packaging Convention compliance. - * - * M4.1: The format designer shall specify and the format producer shall create - * at most one core properties relationship for a package. A format consumer - * shall consider more than one core properties relationship for a package to be - * an error. If present, the relationship shall target the Core Properties part. - * - * M4.2: The format designer shall not specify and the format producer shall not - * create Core Properties that use the Markup Compatibility namespace as defined - * in Annex F, "Standard Namespaces and Content Types". A format consumer shall - * consider the use of the Markup Compatibility namespace to be an 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: - * and Consumers shall consider a document - * element that violates this constraint to be an 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. - * - * M4.5: Producers shall not create a document element that contains the - * xsi:type attribute, except for a or - * 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. - * - * @author Julien Chable - */ -public final class TestOPCComplianceCoreProperties extends TestCase { - - public void testCorePropertiesPart() { - Package pkg; - try { - InputStream is = OpenXML4JTestDataSamples.openComplianceSampleStream("OPCCompliance_CoreProperties_OnlyOneCorePropertiesPart.docx"); - pkg = Package.open(is); - } catch (InvalidFormatException e) { - throw new RuntimeException(e); - } catch (IOException e) { - throw new RuntimeException(e); - } - pkg.revert(); - } - - private static String extractInvalidFormatMessage(String sampleNameSuffix) { - - InputStream is = OpenXML4JTestDataSamples.openComplianceSampleStream("OPCCompliance_CoreProperties_" + sampleNameSuffix); - Package pkg; - try { - pkg = Package.open(is); - } catch (InvalidFormatException e) { - // expected during successful test - return e.getMessage(); - } catch (IOException e) { - throw new RuntimeException(e); - } - pkg.revert(); - // Normally must thrown an InvalidFormatException exception. - throw new AssertionFailedError("expected OPC compliance exception was not thrown"); - } - - /** - * Test M4.1 rule. - */ - public void testOnlyOneCorePropertiesPart() { - String msg = extractInvalidFormatMessage("OnlyOneCorePropertiesPartFAIL.docx"); - assertEquals("OPC Compliance error [M4.1]: there is more than one core properties relationship in the package !", msg); - } - - private static URI createURI(String text) { - try { - return new URI(text); - } catch (URISyntaxException e) { - throw new RuntimeException(e); - } - } - - /** - * Test M4.1 rule. - */ - public void testOnlyOneCorePropertiesPart_AddRelationship() { - InputStream is = OpenXML4JTestDataSamples.openComplianceSampleStream("OPCCompliance_CoreProperties_OnlyOneCorePropertiesPart.docx"); - Package pkg; - try { - pkg = Package.open(is); - } catch (InvalidFormatException e) { - throw new RuntimeException(e); - } catch (IOException e) { - throw new RuntimeException(e); - } - URI partUri = createURI("/docProps/core2.xml"); - try { - pkg.addRelationship(PackagingURIHelper.createPartName(partUri), TargetMode.INTERNAL, - PackageRelationshipTypes.CORE_PROPERTIES); - fail("expected OPC compliance exception was not thrown"); - } catch (InvalidFormatException e) { - throw new RuntimeException(e); - } catch (InvalidOperationException e) { - // expected during successful test - assertEquals("OPC Compliance error [M4.1]: can't add another core properties part ! Use the built-in package method instead.", e.getMessage()); - } - pkg.revert(); - } - - /** - * Test M4.1 rule. - */ - public void testOnlyOneCorePropertiesPart_AddPart() { - String sampleFileName = OpenXML4JTestDataSamples.getComplianceSampleFileName("OPCCompliance_CoreProperties_OnlyOneCorePropertiesPart.docx"); - Package pkg = null; - try { - pkg = Package.open(sampleFileName); - } catch (InvalidFormatException e) { - throw new RuntimeException(e); - } - - URI partUri = createURI("/docProps/core2.xml"); - try { - pkg.createPart(PackagingURIHelper.createPartName(partUri), - ContentTypes.CORE_PROPERTIES_PART); - fail("expected OPC compliance exception was not thrown"); - } catch (InvalidFormatException e) { - throw new RuntimeException(e); - } catch (InvalidOperationException e) { - // expected during successful test - assertEquals("OPC Compliance error [M4.1]: you try to add more than one core properties relationship in the package !", e.getMessage()); - } - pkg.revert(); - } - - /** - * Test M4.2 rule. - */ - public void testDoNotUseCompatibilityMarkup() { - String msg = extractInvalidFormatMessage("DoNotUseCompatibilityMarkupFAIL.docx"); - assertEquals("OPC Compliance error [M4.2]: A format consumer shall consider the use of the Markup Compatibility namespace to be an error.", msg); - } - - /** - * Test M4.3 rule. - */ - public void testDCTermsNamespaceLimitedUse() { - String msg = extractInvalidFormatMessage("DCTermsNamespaceLimitedUseFAIL.docx"); - assertEquals("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: and Consumers shall consider a document element that violates this constraint to be an error.", msg); - } - - /** - * Test M4.4 rule. - */ - public void testUnauthorizedXMLLangAttribute() { - String msg = extractInvalidFormatMessage("UnauthorizedXMLLangAttributeFAIL.docx"); - assertEquals("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.", msg); - } - - /** - * Test M4.5 rule. - */ - public void testLimitedXSITypeAttribute_NotPresent() { - String msg = extractInvalidFormatMessage("LimitedXSITypeAttribute_NotPresentFAIL.docx"); - assertEquals("The element 'created' must have the 'xsi:type' attribute present !", msg); - } - - /** - * Test M4.5 rule. - */ - public void testLimitedXSITypeAttribute_PresentWithUnauthorizedValue() { - String msg = extractInvalidFormatMessage("LimitedXSITypeAttribute_PresentWithUnauthorizedValueFAIL.docx"); - assertEquals("The element 'modified' must have the 'xsi:type' attribute with the value 'dcterms:W3CDTF' !", msg); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc.compliance; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; + +import junit.framework.AssertionFailedError; +import junit.framework.TestCase; + +import org.apache.poi.openxml4j.OpenXML4JTestDataSamples; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.exceptions.InvalidOperationException; +import org.apache.poi.openxml4j.opc.ContentTypes; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.openxml4j.opc.PackageRelationshipTypes; +import org.apache.poi.openxml4j.opc.PackagingURIHelper; +import org.apache.poi.openxml4j.opc.TargetMode; + +/** + * Test core properties Open Packaging Convention compliance. + * + * M4.1: The format designer shall specify and the format producer shall create + * at most one core properties relationship for a package. A format consumer + * shall consider more than one core properties relationship for a package to be + * an error. If present, the relationship shall target the Core Properties part. + * + * M4.2: The format designer shall not specify and the format producer shall not + * create Core Properties that use the Markup Compatibility namespace as defined + * in Annex F, "Standard Namespaces and Content Types". A format consumer shall + * consider the use of the Markup Compatibility namespace to be an 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: + * and Consumers shall consider a document + * element that violates this constraint to be an 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. + * + * M4.5: Producers shall not create a document element that contains the + * xsi:type attribute, except for a or + * 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. + * + * @author Julien Chable + */ +public final class TestOPCComplianceCoreProperties extends TestCase { + + public void testCorePropertiesPart() { + OPCPackage pkg; + try { + InputStream is = OpenXML4JTestDataSamples.openComplianceSampleStream("OPCCompliance_CoreProperties_OnlyOneCorePropertiesPart.docx"); + pkg = OPCPackage.open(is); + } catch (InvalidFormatException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + pkg.revert(); + } + + private static String extractInvalidFormatMessage(String sampleNameSuffix) { + + InputStream is = OpenXML4JTestDataSamples.openComplianceSampleStream("OPCCompliance_CoreProperties_" + sampleNameSuffix); + OPCPackage pkg; + try { + pkg = OPCPackage.open(is); + } catch (InvalidFormatException e) { + // expected during successful test + return e.getMessage(); + } catch (IOException e) { + throw new RuntimeException(e); + } + pkg.revert(); + // Normally must thrown an InvalidFormatException exception. + throw new AssertionFailedError("expected OPC compliance exception was not thrown"); + } + + /** + * Test M4.1 rule. + */ + public void testOnlyOneCorePropertiesPart() { + String msg = extractInvalidFormatMessage("OnlyOneCorePropertiesPartFAIL.docx"); + assertEquals("OPC Compliance error [M4.1]: there is more than one core properties relationship in the package !", msg); + } + + private static URI createURI(String text) { + try { + return new URI(text); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + + /** + * Test M4.1 rule. + */ + public void testOnlyOneCorePropertiesPart_AddRelationship() { + InputStream is = OpenXML4JTestDataSamples.openComplianceSampleStream("OPCCompliance_CoreProperties_OnlyOneCorePropertiesPart.docx"); + OPCPackage pkg; + try { + pkg = OPCPackage.open(is); + } catch (InvalidFormatException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + URI partUri = createURI("/docProps/core2.xml"); + try { + pkg.addRelationship(PackagingURIHelper.createPartName(partUri), TargetMode.INTERNAL, + PackageRelationshipTypes.CORE_PROPERTIES); + fail("expected OPC compliance exception was not thrown"); + } catch (InvalidFormatException e) { + throw new RuntimeException(e); + } catch (InvalidOperationException e) { + // expected during successful test + assertEquals("OPC Compliance error [M4.1]: can't add another core properties part ! Use the built-in package method instead.", e.getMessage()); + } + pkg.revert(); + } + + /** + * Test M4.1 rule. + */ + public void testOnlyOneCorePropertiesPart_AddPart() { + String sampleFileName = OpenXML4JTestDataSamples.getComplianceSampleFileName("OPCCompliance_CoreProperties_OnlyOneCorePropertiesPart.docx"); + OPCPackage pkg = null; + try { + pkg = OPCPackage.open(sampleFileName); + } catch (InvalidFormatException e) { + throw new RuntimeException(e); + } + + URI partUri = createURI("/docProps/core2.xml"); + try { + pkg.createPart(PackagingURIHelper.createPartName(partUri), + ContentTypes.CORE_PROPERTIES_PART); + fail("expected OPC compliance exception was not thrown"); + } catch (InvalidFormatException e) { + throw new RuntimeException(e); + } catch (InvalidOperationException e) { + // expected during successful test + assertEquals("OPC Compliance error [M4.1]: you try to add more than one core properties relationship in the package !", e.getMessage()); + } + pkg.revert(); + } + + /** + * Test M4.2 rule. + */ + public void testDoNotUseCompatibilityMarkup() { + String msg = extractInvalidFormatMessage("DoNotUseCompatibilityMarkupFAIL.docx"); + assertEquals("OPC Compliance error [M4.2]: A format consumer shall consider the use of the Markup Compatibility namespace to be an error.", msg); + } + + /** + * Test M4.3 rule. + */ + public void testDCTermsNamespaceLimitedUse() { + String msg = extractInvalidFormatMessage("DCTermsNamespaceLimitedUseFAIL.docx"); + assertEquals("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: and Consumers shall consider a document element that violates this constraint to be an error.", msg); + } + + /** + * Test M4.4 rule. + */ + public void testUnauthorizedXMLLangAttribute() { + String msg = extractInvalidFormatMessage("UnauthorizedXMLLangAttributeFAIL.docx"); + assertEquals("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.", msg); + } + + /** + * Test M4.5 rule. + */ + public void testLimitedXSITypeAttribute_NotPresent() { + String msg = extractInvalidFormatMessage("LimitedXSITypeAttribute_NotPresentFAIL.docx"); + assertEquals("The element 'created' must have the 'xsi:type' attribute present !", msg); + } + + /** + * Test M4.5 rule. + */ + public void testLimitedXSITypeAttribute_PresentWithUnauthorizedValue() { + String msg = extractInvalidFormatMessage("LimitedXSITypeAttribute_PresentWithUnauthorizedValueFAIL.docx"); + assertEquals("The element 'modified' must have the 'xsi:type' attribute with the value 'dcterms:W3CDTF' !", msg); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/compliance/TestOPCCompliancePackageModel.java b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/compliance/TestOPCCompliancePackageModel.java index f135b41388..332642f69a 100755 --- a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/compliance/TestOPCCompliancePackageModel.java +++ b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/compliance/TestOPCCompliancePackageModel.java @@ -1,162 +1,162 @@ -/* ==================================================================== - 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.compliance; - -import java.io.File; - -import junit.framework.TestCase; - -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.exceptions.InvalidOperationException; -import org.apache.poi.openxml4j.opc.ContentTypes; -import org.apache.poi.openxml4j.opc.Package; -import org.apache.poi.openxml4j.opc.PackagePartName; -import org.apache.poi.openxml4j.opc.PackageRelationshipTypes; -import org.apache.poi.openxml4j.opc.PackagingURIHelper; -import org.apache.poi.openxml4j.opc.TargetMode; - -/** - * Test Open Packaging Convention package model compliance. - * - * 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. - * - * @author Julien Chable - */ -public class TestOPCCompliancePackageModel extends TestCase { - - public TestOPCCompliancePackageModel(String name) { - super(name); - } - - /** - * A package implementer shall neither create nor recognize a part with a - * part name derived from another part name by appending segments to it. - * [M1.11] - */ - public void testPartNameDerivationAdditionFailure() { - Package pkg = Package.create("TODELETEIFEXIST.docx"); - try { - PackagePartName name = PackagingURIHelper - .createPartName("/word/document.xml"); - PackagePartName nameDerived = PackagingURIHelper - .createPartName("/word/document.xml/image1.gif"); - pkg.createPart(name, ContentTypes.XML); - pkg.createPart(nameDerived, ContentTypes.EXTENSION_GIF); - } catch (InvalidOperationException e) { - pkg.revert(); - return; - } catch (InvalidFormatException e) { - fail(e.getMessage()); - } - fail("A package implementer shall neither create nor recognize a part with a" - + " part name derived from another part name by appending segments to it." - + " [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. - * [M1.11] - */ - public void testPartNameDerivationReadingFailure() { - String filepath = System.getProperty("openxml4j.compliance.input") - + File.separator + "OPCCompliance_DerivedPartNameFAIL.docx"; - try { - Package.open(filepath); - } catch (InvalidFormatException e) { - return; - } - fail("A package implementer shall neither create nor recognize a part with a" - + " part name derived from another part name by appending segments to it." - + " [M1.11]"); - } - - /** - * Rule M1.12 : Packages shall not contain equivalent part names and package - * implementers shall neither create nor recognize packages with equivalent - * part names. - */ - public void testAddPackageAlreadyAddFailure() throws Exception { - Package pkg = Package.create("DELETEIFEXISTS.docx"); - PackagePartName name1 = null; - PackagePartName name2 = null; - try { - name1 = PackagingURIHelper.createPartName("/word/document.xml"); - name2 = PackagingURIHelper.createPartName("/word/document.xml"); - } catch (InvalidFormatException e) { - throw new Exception(e.getMessage()); - } - pkg.createPart(name1, ContentTypes.XML); - try { - pkg.createPart(name2, ContentTypes.XML); - } catch (InvalidOperationException e) { - return; - } - fail("Packages shall not contain equivalent part names and package implementers shall neither create nor recognize packages with equivalent part names. [M1.12]"); - } - - /** - * Rule M1.12 : Packages shall not contain equivalent part names and package - * implementers shall neither create nor recognize packages with equivalent - * part names. - */ - public void testAddPackageAlreadyAddFailure2() throws Exception { - Package pkg = Package.create("DELETEIFEXISTS.docx"); - PackagePartName partName = null; - try { - partName = PackagingURIHelper.createPartName("/word/document.xml"); - } catch (InvalidFormatException e) { - throw new Exception(e.getMessage()); - } - pkg.createPart(partName, ContentTypes.XML); - try { - pkg.createPart(partName, ContentTypes.XML); - } catch (InvalidOperationException e) { - return; - } - fail("Packages shall not contain equivalent part names and package implementers shall neither create nor recognize packages with equivalent part names. [M1.12]"); - } - - /** - * Try to add a relationship to a relationship 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. - */ - public void testAddRelationshipRelationshipsPartFailure() { - Package pkg = Package.create("DELETEIFEXISTS.docx"); - PackagePartName name1 = null; - try { - name1 = PackagingURIHelper - .createPartName("/test/_rels/document.xml.rels"); - } catch (InvalidFormatException e) { - fail("This exception should never happen !"); - } - - try { - pkg.addRelationship(name1, TargetMode.INTERNAL, - PackageRelationshipTypes.CORE_DOCUMENT); - } catch (InvalidOperationException e) { - return; - } - fail("Fail test -> M1.25: The Relationships part shall not have relationships to any other part"); - } -} +/* ==================================================================== + 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.compliance; + +import java.io.File; + +import junit.framework.TestCase; + +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.exceptions.InvalidOperationException; +import org.apache.poi.openxml4j.opc.ContentTypes; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.openxml4j.opc.PackagePartName; +import org.apache.poi.openxml4j.opc.PackageRelationshipTypes; +import org.apache.poi.openxml4j.opc.PackagingURIHelper; +import org.apache.poi.openxml4j.opc.TargetMode; + +/** + * Test Open Packaging Convention package model compliance. + * + * 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. + * + * @author Julien Chable + */ +public class TestOPCCompliancePackageModel extends TestCase { + + public TestOPCCompliancePackageModel(String name) { + super(name); + } + + /** + * A package implementer shall neither create nor recognize a part with a + * part name derived from another part name by appending segments to it. + * [M1.11] + */ + public void testPartNameDerivationAdditionFailure() { + OPCPackage pkg = OPCPackage.create("TODELETEIFEXIST.docx"); + try { + PackagePartName name = PackagingURIHelper + .createPartName("/word/document.xml"); + PackagePartName nameDerived = PackagingURIHelper + .createPartName("/word/document.xml/image1.gif"); + pkg.createPart(name, ContentTypes.XML); + pkg.createPart(nameDerived, ContentTypes.EXTENSION_GIF); + } catch (InvalidOperationException e) { + pkg.revert(); + return; + } catch (InvalidFormatException e) { + fail(e.getMessage()); + } + fail("A package implementer shall neither create nor recognize a part with a" + + " part name derived from another part name by appending segments to it." + + " [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. + * [M1.11] + */ + public void testPartNameDerivationReadingFailure() { + String filepath = System.getProperty("openxml4j.compliance.input") + + File.separator + "OPCCompliance_DerivedPartNameFAIL.docx"; + try { + OPCPackage.open(filepath); + } catch (InvalidFormatException e) { + return; + } + fail("A package implementer shall neither create nor recognize a part with a" + + " part name derived from another part name by appending segments to it." + + " [M1.11]"); + } + + /** + * Rule M1.12 : Packages shall not contain equivalent part names and package + * implementers shall neither create nor recognize packages with equivalent + * part names. + */ + public void testAddPackageAlreadyAddFailure() throws Exception { + OPCPackage pkg = OPCPackage.create("DELETEIFEXISTS.docx"); + PackagePartName name1 = null; + PackagePartName name2 = null; + try { + name1 = PackagingURIHelper.createPartName("/word/document.xml"); + name2 = PackagingURIHelper.createPartName("/word/document.xml"); + } catch (InvalidFormatException e) { + throw new Exception(e.getMessage()); + } + pkg.createPart(name1, ContentTypes.XML); + try { + pkg.createPart(name2, ContentTypes.XML); + } catch (InvalidOperationException e) { + return; + } + fail("Packages shall not contain equivalent part names and package implementers shall neither create nor recognize packages with equivalent part names. [M1.12]"); + } + + /** + * Rule M1.12 : Packages shall not contain equivalent part names and package + * implementers shall neither create nor recognize packages with equivalent + * part names. + */ + public void testAddPackageAlreadyAddFailure2() throws Exception { + OPCPackage pkg = OPCPackage.create("DELETEIFEXISTS.docx"); + PackagePartName partName = null; + try { + partName = PackagingURIHelper.createPartName("/word/document.xml"); + } catch (InvalidFormatException e) { + throw new Exception(e.getMessage()); + } + pkg.createPart(partName, ContentTypes.XML); + try { + pkg.createPart(partName, ContentTypes.XML); + } catch (InvalidOperationException e) { + return; + } + fail("Packages shall not contain equivalent part names and package implementers shall neither create nor recognize packages with equivalent part names. [M1.12]"); + } + + /** + * Try to add a relationship to a relationship 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. + */ + public void testAddRelationshipRelationshipsPartFailure() { + OPCPackage pkg = OPCPackage.create("DELETEIFEXISTS.docx"); + PackagePartName name1 = null; + try { + name1 = PackagingURIHelper + .createPartName("/test/_rels/document.xml.rels"); + } catch (InvalidFormatException e) { + fail("This exception should never happen !"); + } + + try { + pkg.addRelationship(name1, TargetMode.INTERNAL, + PackageRelationshipTypes.CORE_DOCUMENT); + } catch (InvalidOperationException e) { + return; + } + fail("Fail test -> M1.25: The Relationships part shall not have relationships to any other part"); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/ss/TestWorkbookFactory.java b/src/ooxml/testcases/org/apache/poi/ss/TestWorkbookFactory.java index f1553e0e16..af93ba9aa5 100644 --- a/src/ooxml/testcases/org/apache/poi/ss/TestWorkbookFactory.java +++ b/src/ooxml/testcases/org/apache/poi/ss/TestWorkbookFactory.java @@ -24,7 +24,7 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.WorkbookFactory; import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.apache.poi.openxml4j.opc.Package; +import org.apache.poi.openxml4j.opc.OPCPackage; import junit.framework.TestCase; @@ -63,7 +63,7 @@ public class TestWorkbookFactory extends TestCase { // Package -> xssf wb = WorkbookFactory.create( - Package.open(xlsx.toString()) + OPCPackage.open(xlsx.toString()) ); assertNotNull(wb); assertTrue(wb instanceof XSSFWorkbook); diff --git a/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFSlideShow.java b/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFSlideShow.java index 13971f7efe..e1e821323c 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFSlideShow.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFSlideShow.java @@ -18,14 +18,14 @@ package org.apache.poi.xslf; import java.io.File; +import junit.framework.TestCase; + import org.apache.poi.POIXMLDocument; -import org.apache.poi.openxml4j.opc.Package; +import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackagePart; import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideIdListEntry; import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideMasterIdListEntry; -import junit.framework.TestCase; - public class TestXSLFSlideShow extends TestCase { private String sampleFile; @@ -39,7 +39,7 @@ public class TestXSLFSlideShow extends TestCase { } public void testContainsMainContentType() throws Exception { - Package pack = POIXMLDocument.openPackage(sampleFile); + OPCPackage pack = POIXMLDocument.openPackage(sampleFile); boolean found = false; for(PackagePart part : pack.getParts()) { diff --git a/src/ooxml/testcases/org/apache/poi/xssf/XSSFTestDataSamples.java b/src/ooxml/testcases/org/apache/poi/xssf/XSSFTestDataSamples.java index 5214a22a2e..6c37c7086f 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/XSSFTestDataSamples.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/XSSFTestDataSamples.java @@ -1,75 +1,80 @@ -/* ==================================================================== - 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.xssf; - -import java.io.*; - -import org.apache.poi.hssf.HSSFTestDataSamples; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.opc.Package; - -/** - * Centralises logic for finding/opening sample files in the src/testcases/org/apache/poi/hssf/hssf/data folder. - * - * @author Josh Micich - */ -public class XSSFTestDataSamples { - public static final XSSFWorkbook openSampleWorkbook(String sampleName) { - InputStream is = HSSFTestDataSamples.openSampleFileStream(sampleName); - try { - Package pkg = Package.open(is); - return new XSSFWorkbook(pkg); - } catch (InvalidFormatException e) { - throw new RuntimeException(e); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - public static R writeOutAndReadBack(R wb) { - Workbook result; - try { - if (wb instanceof HSSFWorkbook) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(8192); - wb.write(baos); - InputStream is = new ByteArrayInputStream(baos.toByteArray()); - result = new HSSFWorkbook(is); - } else if (wb instanceof XSSFWorkbook) { - File tmp = File.createTempFile("poi-ooxml-", ".xlsx"); - tmp.deleteOnExit(); - FileOutputStream out = new FileOutputStream(tmp); - wb.write(out); - out.close(); - Package pkg = Package.open(tmp.getAbsolutePath()); - result = new XSSFWorkbook(pkg); - } else { - throw new RuntimeException("Unexpected workbook type (" - + wb.getClass().getName() + ")"); - } - } catch (InvalidFormatException e) { - throw new RuntimeException(e); - } catch (IOException e) { - throw new RuntimeException(e); - } - @SuppressWarnings("unchecked") - R r = (R) result; - return r; - } -} +/* ==================================================================== + 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.xssf; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; + +/** + * Centralises logic for finding/opening sample files in the src/testcases/org/apache/poi/hssf/hssf/data folder. + * + * @author Josh Micich + */ +public class XSSFTestDataSamples { + public static final XSSFWorkbook openSampleWorkbook(String sampleName) { + InputStream is = HSSFTestDataSamples.openSampleFileStream(sampleName); + try { + OPCPackage pkg = OPCPackage.open(is); + return new XSSFWorkbook(pkg); + } catch (InvalidFormatException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + public static R writeOutAndReadBack(R wb) { + Workbook result; + try { + if (wb instanceof HSSFWorkbook) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(8192); + wb.write(baos); + InputStream is = new ByteArrayInputStream(baos.toByteArray()); + result = new HSSFWorkbook(is); + } else if (wb instanceof XSSFWorkbook) { + File tmp = File.createTempFile("poi-ooxml-", ".xlsx"); + tmp.deleteOnExit(); + FileOutputStream out = new FileOutputStream(tmp); + wb.write(out); + out.close(); + OPCPackage pkg = OPCPackage.open(tmp.getAbsolutePath()); + result = new XSSFWorkbook(pkg); + } else { + throw new RuntimeException("Unexpected workbook type (" + + wb.getClass().getName() + ")"); + } + } catch (InvalidFormatException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + @SuppressWarnings("unchecked") + R r = (R) result; + return r; + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xssf/eventusermodel/TestXSSFReader.java b/src/ooxml/testcases/org/apache/poi/xssf/eventusermodel/TestXSSFReader.java index 9ad4af7baa..567cd014ea 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/eventusermodel/TestXSSFReader.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/eventusermodel/TestXSSFReader.java @@ -25,7 +25,7 @@ import junit.framework.TestCase; import org.apache.poi.util.IOUtils; import org.apache.poi.xssf.usermodel.XSSFRichTextString; -import org.apache.poi.openxml4j.opc.Package; +import org.apache.poi.openxml4j.opc.OPCPackage; /** * Tests for XSSFReader @@ -49,7 +49,7 @@ public class TestXSSFReader extends TestCase { public void testGetBits() throws Exception { File f = new File(dirName, "SampleSS.xlsx"); - Package pkg = Package.open(f.toString()); + OPCPackage pkg = OPCPackage.open(f.toString()); XSSFReader r = new XSSFReader(pkg); @@ -63,7 +63,7 @@ public class TestXSSFReader extends TestCase { public void testStyles() throws Exception { File f = new File(dirName, "SampleSS.xlsx"); - Package pkg = Package.open(f.toString()); + OPCPackage pkg = OPCPackage.open(f.toString()); XSSFReader r = new XSSFReader(pkg); @@ -73,7 +73,7 @@ public class TestXSSFReader extends TestCase { public void testStrings() throws Exception { File f = new File(dirName, "SampleSS.xlsx"); - Package pkg = Package.open(f.toString()); + OPCPackage pkg = OPCPackage.open(f.toString()); XSSFReader r = new XSSFReader(pkg); @@ -83,7 +83,7 @@ public class TestXSSFReader extends TestCase { public void testSheets() throws Exception { File f = new File(dirName, "SampleSS.xlsx"); - Package pkg = Package.open(f.toString()); + OPCPackage pkg = OPCPackage.open(f.toString()); XSSFReader r = new XSSFReader(pkg); byte[] data = new byte[4096]; @@ -116,7 +116,7 @@ public class TestXSSFReader extends TestCase { */ public void testOrderOfSheets() throws Exception { File f = new File(dirName, "reordered_sheets.xlsx"); - Package pkg = Package.open(f.toString()); + OPCPackage pkg = OPCPackage.open(f.toString()); XSSFReader r = new XSSFReader(pkg); diff --git a/src/ooxml/testcases/org/apache/poi/xssf/model/TestCommentsTable.java b/src/ooxml/testcases/org/apache/poi/xssf/model/TestCommentsTable.java index 062a93e7c0..05a85fc548 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/model/TestCommentsTable.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/model/TestCommentsTable.java @@ -32,7 +32,7 @@ import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.xssf.XSSFTestDataSamples; import org.apache.poi.POIXMLDocumentPart; -import org.apache.poi.openxml4j.opc.Package; +import org.apache.poi.openxml4j.opc.OPCPackage; import org.openxmlformats.schemas.spreadsheetml.x2006.main.*; import junit.framework.TestCase; @@ -125,7 +125,7 @@ public class TestCommentsTable extends TestCase { ); assertTrue(xml.exists()); - Package pkg = Package.open(xml.toString()); + OPCPackage pkg = OPCPackage.open(xml.toString()); XSSFWorkbook wb = new XSSFWorkbook(pkg); List rels = wb.getSheetAt(0).getRelations(); CommentsTable ct = null; diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestFormulaEvaluatorOnXSSF.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestFormulaEvaluatorOnXSSF.java index 01160f23f5..b6182cb418 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestFormulaEvaluatorOnXSSF.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestFormulaEvaluatorOnXSSF.java @@ -32,7 +32,7 @@ import org.apache.poi.ss.usermodel.CellValue; import org.apache.poi.ss.usermodel.FormulaEvaluator; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.openxml4j.opc.Package; +import org.apache.poi.openxml4j.opc.OPCPackage; /** * Performs much the same role as {@link TestFormulasFromSpreadsheet}, @@ -149,7 +149,7 @@ public final class TestFormulaEvaluatorOnXSSF extends TestCase { protected void setUp() throws Exception { if (workbook == null) { InputStream is = HSSFTestDataSamples.openSampleFileStream(SS.FILENAME); - Package pkg = Package.open(is); + OPCPackage pkg = OPCPackage.open(is); workbook = new XSSFWorkbook( pkg ); sheet = workbook.getSheetAt( 0 ); } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java index b35d59c5b4..3715410ef9 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java @@ -21,7 +21,8 @@ import java.io.File; import junit.framework.TestCase; -import org.apache.poi.openxml4j.opc.Package; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackagingURIHelper; import org.apache.poi.xssf.XSSFTestDataSamples; @@ -71,7 +72,7 @@ public class TestXSSFBugs extends TestCase { * We should carry vba macros over after save */ public void test45431() throws Exception { - Package pkg = Package.open(getFilePath("45431.xlsm")); + OPCPackage pkg = OPCPackage.open(getFilePath("45431.xlsm")); XSSFWorkbook wb = new XSSFWorkbook(pkg); assertTrue(wb.isMacroEnabled()); @@ -89,7 +90,7 @@ public class TestXSSFBugs extends TestCase { // Save and re-open, both still there XSSFWorkbook nwb = XSSFTestDataSamples.writeOutAndReadBack(wb); - Package nPkg = nwb.getPackage(); + OPCPackage nPkg = nwb.getPackage(); assertTrue(nwb.isMacroEnabled()); vba = nPkg.getPart( diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFDrawing.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFDrawing.java index e4d6bc091f..8b721b6199 100755 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFDrawing.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFDrawing.java @@ -1,77 +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.xssf.usermodel; - -import junit.framework.TestCase; -import org.apache.poi.xssf.XSSFTestDataSamples; -import org.apache.poi.POIXMLDocumentPart; - -import java.util.List; - -/** - * @author Yegor Kozlov - */ -public class TestXSSFDrawing extends TestCase { - public void testRead(){ - XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("WithDrawing.xlsx"); - XSSFSheet sheet = wb.getSheetAt(0); - //the sheet has one relationship and it is XSSFDrawing - List rels = sheet.getRelations(); - assertEquals(1, rels.size()); - assertTrue(rels.get(0) instanceof XSSFDrawing); - - XSSFDrawing drawing = (XSSFDrawing)rels.get(0); - //sheet.createDrawingPatriarch() should return the same instance of XSSFDrawing - assertSame(drawing, sheet.createDrawingPatriarch()); - String drawingId = drawing.getPackageRelationship().getId(); - - //there should be a relation to this drawing in the worksheet - assertTrue(sheet.getCTWorksheet().isSetDrawing()); - assertEquals(drawingId, sheet.getCTWorksheet().getDrawing().getId()); - - } - - public void testNew(){ - XSSFWorkbook wb = new XSSFWorkbook(); - XSSFSheet sheet = wb.createSheet(); - //multiple calls of createDrawingPatriarch should return the same instance of XSSFDrawing - XSSFDrawing dr1 = sheet.createDrawingPatriarch(); - XSSFDrawing dr2 = sheet.createDrawingPatriarch(); - assertSame(dr1, dr2); - - List rels = sheet.getRelations(); - assertEquals(1, rels.size()); - assertTrue(rels.get(0) instanceof XSSFDrawing); - - XSSFDrawing drawing = (XSSFDrawing)rels.get(0); - String drawingId = drawing.getPackageRelationship().getId(); - - //there should be a relation to this drawing in the worksheet - assertTrue(sheet.getCTWorksheet().isSetDrawing()); - assertEquals(drawingId, sheet.getCTWorksheet().getDrawing().getId()); - - } - public void testMultipleDrawings(){ - XSSFWorkbook wb = new XSSFWorkbook(); - for (int i = 0; i < 3; i++) { - XSSFSheet sheet = wb.createSheet(); - XSSFDrawing drawing = sheet.createDrawingPatriarch(); - } - org.apache.poi.openxml4j.opc.Package pkg = wb.getPackage(); - assertEquals(3, pkg.getPartsByContentType(XSSFRelation.DRAWINGS.getContentType()).size()); - } -} +/* ==================================================================== + 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.xssf.usermodel; + +import java.util.List; + +import junit.framework.TestCase; + +import org.apache.poi.POIXMLDocumentPart; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.xssf.XSSFTestDataSamples; + +/** + * @author Yegor Kozlov + */ +public class TestXSSFDrawing extends TestCase { + public void testRead(){ + XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("WithDrawing.xlsx"); + XSSFSheet sheet = wb.getSheetAt(0); + //the sheet has one relationship and it is XSSFDrawing + List rels = sheet.getRelations(); + assertEquals(1, rels.size()); + assertTrue(rels.get(0) instanceof XSSFDrawing); + + XSSFDrawing drawing = (XSSFDrawing)rels.get(0); + //sheet.createDrawingPatriarch() should return the same instance of XSSFDrawing + assertSame(drawing, sheet.createDrawingPatriarch()); + String drawingId = drawing.getPackageRelationship().getId(); + + //there should be a relation to this drawing in the worksheet + assertTrue(sheet.getCTWorksheet().isSetDrawing()); + assertEquals(drawingId, sheet.getCTWorksheet().getDrawing().getId()); + + } + + public void testNew(){ + XSSFWorkbook wb = new XSSFWorkbook(); + XSSFSheet sheet = wb.createSheet(); + //multiple calls of createDrawingPatriarch should return the same instance of XSSFDrawing + XSSFDrawing dr1 = sheet.createDrawingPatriarch(); + XSSFDrawing dr2 = sheet.createDrawingPatriarch(); + assertSame(dr1, dr2); + + List rels = sheet.getRelations(); + assertEquals(1, rels.size()); + assertTrue(rels.get(0) instanceof XSSFDrawing); + + XSSFDrawing drawing = (XSSFDrawing)rels.get(0); + String drawingId = drawing.getPackageRelationship().getId(); + + //there should be a relation to this drawing in the worksheet + assertTrue(sheet.getCTWorksheet().isSetDrawing()); + assertEquals(drawingId, sheet.getCTWorksheet().getDrawing().getId()); + + } + public void testMultipleDrawings(){ + XSSFWorkbook wb = new XSSFWorkbook(); + for (int i = 0; i < 3; i++) { + XSSFSheet sheet = wb.createSheet(); + XSSFDrawing drawing = sheet.createDrawingPatriarch(); + } + OPCPackage pkg = wb.getPackage(); + assertEquals(3, pkg.getPartsByContentType(XSSFRelation.DRAWINGS.getContentType()).size()); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java index 09acaac09e..73c181bd2b 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java @@ -29,7 +29,7 @@ import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.xssf.XSSFTestDataSamples; import org.apache.poi.xssf.model.StylesTable; import org.apache.poi.openxml4j.opc.ContentTypes; -import org.apache.poi.openxml4j.opc.Package; +import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackagingURIHelper; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet; @@ -251,7 +251,7 @@ public final class TestXSSFWorkbook extends TestCase { out.close(); // Check the package contains what we'd expect it to - Package pkg = Package.open(file.toString()); + OPCPackage pkg = OPCPackage.open(file.toString()); PackagePart wbRelPart = pkg.getPart(PackagingURIHelper.createPartName("/xl/_rels/workbook.xml.rels")); assertNotNull(wbRelPart); @@ -293,7 +293,7 @@ public final class TestXSSFWorkbook extends TestCase { assertNotNull(workbook.getStylesSource()); // And check a few low level bits too - Package pkg = Package.open(HSSFTestDataSamples.openSampleFileStream("Formatting.xlsx")); + OPCPackage pkg = OPCPackage.open(HSSFTestDataSamples.openSampleFileStream("Formatting.xlsx")); PackagePart wbPart = pkg.getPart(PackagingURIHelper.createPartName("/xl/workbook.xml")); diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/TestXWPFDocument.java b/src/ooxml/testcases/org/apache/poi/xwpf/TestXWPFDocument.java index 24fbfcc895..68df95786c 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/TestXWPFDocument.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/TestXWPFDocument.java @@ -18,13 +18,13 @@ package org.apache.poi.xwpf; import java.io.File; +import junit.framework.TestCase; + import org.apache.poi.POIXMLDocument; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFRelation; -import org.apache.poi.openxml4j.opc.Package; -import org.apache.poi.openxml4j.opc.PackagePart; - -import junit.framework.TestCase; public class TestXWPFDocument extends TestCase { private File sampleFile; @@ -47,7 +47,7 @@ public class TestXWPFDocument extends TestCase { } public void testContainsMainContentType() throws Exception { - Package pack = POIXMLDocument.openPackage(sampleFile.toString()); + OPCPackage pack = POIXMLDocument.openPackage(sampleFile.toString()); boolean found = false; for(PackagePart part : pack.getParts()) {