diff options
author | Josh Micich <josh@apache.org> | 2009-03-18 18:54:01 +0000 |
---|---|---|
committer | Josh Micich <josh@apache.org> | 2009-03-18 18:54:01 +0000 |
commit | aca8d5187d7d19b4baa52221194a0bd87b0bc038 (patch) | |
tree | fbf9115a6e4fde78414b20141a9561eddc3fee52 /src/ooxml/java/org | |
parent | ffb03d993ee10e1e128f6cec33a33479efd6a2af (diff) | |
download | poi-aca8d5187d7d19b4baa52221194a0bd87b0bc038.tar.gz poi-aca8d5187d7d19b4baa52221194a0bd87b0bc038.zip |
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
Diffstat (limited to 'src/ooxml/java/org')
26 files changed, 5171 insertions, 5005 deletions
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.
- *
- * <p>
- * Each POIXMLDocumentPart keeps a reference to the underlying a {@link org.apache.poi.openxml4j.opc.PackagePart}.
- * </p>
- *
- * @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<POIXMLDocumentPart> 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<POIXMLDocumentPart>();
- 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<POIXMLDocumentPart>();
- }
-
- /**
- * 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<POIXMLDocumentPart>();
- 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<POIXMLDocumentPart> 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 <code>null</code> 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:
- * <pre><code>
- * 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();
- * }
- * </code></pre>
- *
- */
- 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. + * + * <p> + * Each POIXMLDocumentPart keeps a reference to the underlying a {@link org.apache.poi.openxml4j.opc.PackagePart}. + * </p> + * + * @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<POIXMLDocumentPart> 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<POIXMLDocumentPart>(); + 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<POIXMLDocumentPart>(); + } + + /** + * 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<POIXMLDocumentPart>(); + 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<POIXMLDocumentPart> 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 <code>null</code> 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: + * <pre><code> + * 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(); + * } + * </code></pre> + * + */ + 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<ContentType, PartMarshaller> partMarshallers; + + /** + * Default part marshaller. + */ + protected PartMarshaller defaultPartMarshaller; + + /** + * Part unmarshallers by content type. + */ + protected Hashtable<ContentType, PartUnmarshaller> 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<ContentType, PartMarshaller>(5); + this.partUnmarshallers = new Hashtable<ContentType, PartUnmarshaller>(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 <b>null</b>. + * @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 <b>null</b>. + * @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<Date>( + 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 <code>null</code>. + */ + 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<PackagePart> getPartsByContentType(String contentType) { + ArrayList<PackagePart> retArr = new ArrayList<PackagePart>(); + 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 <code>null</code>. + */ + public ArrayList<PackagePart> getPartsByRelationshipType( + String relationshipType) { + if (relationshipType == null) + throw new IllegalArgumentException("relationshipType"); + ArrayList<PackagePart> retArr = new ArrayList<PackagePart>(); + 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<PackagePart> 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<PackagePart>(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 <code>null</code>, 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 <i>true</i> if the part is logically added to this package, else + * <i>false</i>. + */ + 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 <b>true</b> if the package is valid else <b>false</b> + */ + 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 <b>null</b>. + */ + 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<ContentType, PartMarshaller> partMarshallers;
-
- /**
- * Default part marshaller.
- */
- protected PartMarshaller defaultPartMarshaller;
-
- /**
- * Part unmarshallers by content type.
- */
- protected Hashtable<ContentType, PartUnmarshaller> 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<ContentType, PartMarshaller>(5);
- this.partUnmarshallers = new Hashtable<ContentType, PartUnmarshaller>(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 <b>null</b>.
- * @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 <b>null</b>.
- * @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<Date>(
- 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 <code>null</code>.
- */
- 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<PackagePart> getPartsByContentType(String contentType) {
- ArrayList<PackagePart> retArr = new ArrayList<PackagePart>();
- 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 <code>null</code>.
- */
- public ArrayList<PackagePart> getPartsByRelationshipType(
- String relationshipType) {
- if (relationshipType == null)
- throw new IllegalArgumentException("relationshipType");
- ArrayList<PackagePart> retArr = new ArrayList<PackagePart>();
- 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<PackagePart> 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<PackagePart>(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 <code>null</code>, 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 <i>true</i> if the part is logically added to this package, else
- * <i>false</i>.
- */
- 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 <b>true</b> if the package is valid else <b>false</b>
- */
- 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 <b>null</b>.
- */
- 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<Date>( + 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).
- * <p>
- * 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.
- * </p>
- * @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).
- * <p>
- * 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.
- * </p>
- * @param targetURI
- * URI of the target part. Must be relative to the source root
- * directory of the part.
- * @param targetMode
- * Mode [Internal|External].
- * @param relationshipType
- * Type of relationship.
- * @param id
- * Relationship unique id.
- * @return The newly created and added relationship
- *
- * @throws InvalidFormatException
- * If the URI point to a relationship part URI.
- * @see org.apache.poi.openxml4j.opc.RelationshipSource#addRelationship(org.apache.poi.openxml4j.opc.PackagePartName,
- * org.apache.poi.openxml4j.opc.TargetMode, java.lang.String, java.lang.String)
- */
- public PackageRelationship addRelationship(URI targetURI,
- TargetMode targetMode, String relationshipType, String id) {
- container.throwExceptionIfReadOnly();
-
- if (targetURI == null) {
- throw new IllegalArgumentException("targetPartName");
- }
- if (targetMode == null) {
- throw new IllegalArgumentException("targetMode");
- }
- if (relationshipType == null) {
- throw new IllegalArgumentException("relationshipType");
- }
-
- // Try to retrieve the target part
-
- if (this.isRelationshipPart
- || PackagingURIHelper.isRelationshipPartURI(targetURI)) {
- throw new InvalidOperationException(
- "Rule M1.25: The Relationships part shall not have relationships to any other part.");
- }
-
- if (relationships == null) {
- relationships = new PackageRelationshipCollection();
- }
-
- return relationships.addRelationship(targetURI,
- targetMode, relationshipType, id);
- }
-
- /**
- * @see org.apache.poi.openxml4j.opc.RelationshipSource#clearRelationships()
- */
- public void clearRelationships() {
- if (relationships != null) {
- relationships.clear();
- }
- }
-
- /**
- * Delete the relationship specified by its id.
- *
- * @param id
- * The ID identified the part to delete.
- * @see org.apache.poi.openxml4j.opc.RelationshipSource#removeRelationship(java.lang.String)
- */
- public void removeRelationship(String id) {
- this.container.throwExceptionIfReadOnly();
- if (this.relationships != null)
- this.relationships.removeRelationship(id);
- }
-
- /**
- * Retrieve all the relationships attached to this part.
- *
- * @return This part's relationships.
- * @throws OpenXML4JException
- * @see org.apache.poi.openxml4j.opc.RelationshipSource#getRelationships()
- */
- public PackageRelationshipCollection getRelationships()
- throws InvalidFormatException {
- return getRelationshipsCore(null);
- }
-
- /**
- * Retrieves a package relationship from its id.
- *
- * @param id
- * ID of the package relationship to retrieve.
- * @return The package relationship
- * @see org.apache.poi.openxml4j.opc.RelationshipSource#getRelationship(java.lang.String)
- */
- public PackageRelationship getRelationship(String id) {
- return this.relationships.getRelationshipByID(id);
- }
-
- /**
- * Retrieve all relationships attached to this part which have the specified
- * type.
- *
- * @param relationshipType
- * Relationship type filter.
- * @return All relationships from this part that have the specified type.
- * @throws InvalidFormatException
- * If an error occurs while parsing the part.
- * @throws InvalidOperationException
- * If the package is open in write only mode.
- * @see org.apache.poi.openxml4j.opc.RelationshipSource#getRelationshipsByType(java.lang.String)
- */
- public PackageRelationshipCollection getRelationshipsByType(
- String relationshipType) throws InvalidFormatException {
- container.throwExceptionIfWriteOnly();
-
- return getRelationshipsCore(relationshipType);
- }
-
- /**
- * Implementation of the getRelationships method().
- *
- * @param filter
- * Relationship type filter. If <i>null</i> then the filter is
- * disabled and return all the relationships.
- * @return All relationships from this part that have the specified type.
- * @throws InvalidFormatException
- * Throws if an error occurs during parsing the relationships
- * part.
- * @throws InvalidOperationException
- * Throws if the package is open en write only mode.
- * @see #getRelationshipsByType(String)
- */
- private PackageRelationshipCollection getRelationshipsCore(String filter)
- throws InvalidFormatException {
- this.container.throwExceptionIfWriteOnly();
- if (relationships == null) {
- this.throwExceptionIfRelationship();
- relationships = new PackageRelationshipCollection(this);
- }
- return new PackageRelationshipCollection(relationships, filter);
- }
-
- /**
- * Knows if the part have any relationships.
- *
- * @return <b>true</b> if the part have at least one relationship else
- * <b>false</b>.
- * @see org.apache.poi.openxml4j.opc.RelationshipSource#hasRelationships()
- */
- public boolean hasRelationships() {
- return (!this.isRelationshipPart && (relationships != null && relationships
- .size() > 0));
- }
-
- /**
- * Checks if the specified relationship is part of this package part.
- *
- * @param rel
- * The relationship to check.
- * @return <b>true</b> if the specified relationship exists in this part,
- * else returns <b>false</b>
- * @see org.apache.poi.openxml4j.opc.RelationshipSource#isRelationshipExists(org.apache.poi.openxml4j.opc.PackageRelationship)
- */
- @SuppressWarnings("finally")
- public boolean isRelationshipExists(PackageRelationship rel) {
- try {
- for (PackageRelationship r : this.getRelationships()) {
- if (r == rel)
- return true;
- }
- } finally {
- return false;
- }
- }
-
- /**
- * Get the input stream of this part to read its content.
- *
- * @return The input stream of the content of this part, else
- * <code>null</code>.
- */
- public InputStream getInputStream() throws IOException {
- InputStream inStream = this.getInputStreamImpl();
- if (inStream == null) {
- throw new IOException("Can't obtain the input stream from "
- + partName.getName());
- } else
- return inStream;
- }
-
- /**
- * Get the output stream of this part. If the part is originally embedded in
- * Zip package, it'll be transform intot a <i>MemoryPackagePart</i> in
- * order to write inside (the standard Java API doesn't allow to write in
- * the file)
- *
- * @see org.apache.poi.openxml4j.opc.internal.MemoryPackagePart
- */
- public OutputStream getOutputStream() {
- OutputStream outStream;
- // If this part is a zip package part (read only by design) we convert
- // this part into a MemoryPackagePart instance for write purpose.
- if (this instanceof ZipPackagePart) {
- // Delete logically this part
- this.container.removePart(this.partName);
-
- // Create a memory part
- PackagePart part = container.createPart(this.partName,
- this.contentType.toString(), false);
- part.relationships = this.relationships;
- if (part == null) {
- throw new InvalidOperationException(
- "Can't create a temporary part !");
- }
- outStream = part.getOutputStreamImpl();
- } else {
- outStream = this.getOutputStreamImpl();
- }
- return outStream;
- }
-
- /**
- * Throws an exception if this package part is a relationship part.
- *
- * @throws InvalidOperationException
- * If this part is a relationship part.
- */
- private void throwExceptionIfRelationship()
- throws InvalidOperationException {
- if (this.isRelationshipPart)
- throw new InvalidOperationException(
- "Can do this operation on a relationship part !");
- }
-
- /**
- * Ensure the package relationships collection instance is built.
- *
- * @throws InvalidFormatException
- * Throws if
- */
- private void loadRelationships() throws InvalidFormatException {
- if (this.relationships == null && !this.isRelationshipPart) {
- this.throwExceptionIfRelationship();
- relationships = new PackageRelationshipCollection(this);
- }
- }
-
- /*
- * Accessors
- */
-
- /**
- * @return the uri
- */
- public PackagePartName getPartName() {
- return partName;
- }
-
- /**
- * @return the contentType
- */
- public String getContentType() {
- return contentType.toString();
- }
-
- /**
- * Set the content type.
- *
- * @param contentType
- * the contentType to set
- *
- * @throws InvalidFormatException
- * Throws if the content type is not valid.
- * @throws InvalidOperationException
- * Throws if you try to change the content type whereas this
- * part is already attached to a package.
- */
- public void setContentType(String contentType)
- throws InvalidFormatException {
- if (container == null)
- this.contentType = new ContentType(contentType);
- else
- throw new InvalidOperationException(
- "You can't change the content type of a part.");
- }
-
- public Package getPackage() {
- return container;
- }
-
- /**
- * @return 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 <b>true</b> if the content has been successfully loaded, else
- * <b>false</b>.
- * @throws InvalidFormatException
- * Throws if the content format is invalid.
- */
- public abstract boolean load(InputStream ios) throws InvalidFormatException;
-
- /**
- * Close this part : flush this part, close the input stream and output
- * stream. After this method call, the part must be available for packaging.
- */
- public abstract void close();
-
- /**
- * Flush the content of this part. If the input stream and/or output stream
- * as in a waiting state to read or write, the must to empty their
- * respective buffer.
- */
- public abstract void flush();
-}
+/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc; + +import java.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). + * <p> + * 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. + * </p> + * @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). + * <p> + * 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. + * </p> + * @param targetURI + * URI of the target part. Must be relative to the source root + * directory of the part. + * @param targetMode + * Mode [Internal|External]. + * @param relationshipType + * Type of relationship. + * @param id + * Relationship unique id. + * @return The newly created and added relationship + * + * @throws InvalidFormatException + * If the URI point to a relationship part URI. + * @see org.apache.poi.openxml4j.opc.RelationshipSource#addRelationship(org.apache.poi.openxml4j.opc.PackagePartName, + * org.apache.poi.openxml4j.opc.TargetMode, java.lang.String, java.lang.String) + */ + public PackageRelationship addRelationship(URI targetURI, + TargetMode targetMode, String relationshipType, String id) { + container.throwExceptionIfReadOnly(); + + if (targetURI == null) { + throw new IllegalArgumentException("targetPartName"); + } + if (targetMode == null) { + throw new IllegalArgumentException("targetMode"); + } + if (relationshipType == null) { + throw new IllegalArgumentException("relationshipType"); + } + + // Try to retrieve the target part + + if (this.isRelationshipPart + || PackagingURIHelper.isRelationshipPartURI(targetURI)) { + throw new InvalidOperationException( + "Rule M1.25: The Relationships part shall not have relationships to any other part."); + } + + if (relationships == null) { + relationships = new PackageRelationshipCollection(); + } + + return relationships.addRelationship(targetURI, + targetMode, relationshipType, id); + } + + /** + * @see org.apache.poi.openxml4j.opc.RelationshipSource#clearRelationships() + */ + public void clearRelationships() { + if (relationships != null) { + relationships.clear(); + } + } + + /** + * Delete the relationship specified by its id. + * + * @param id + * The ID identified the part to delete. + * @see org.apache.poi.openxml4j.opc.RelationshipSource#removeRelationship(java.lang.String) + */ + public void removeRelationship(String id) { + this.container.throwExceptionIfReadOnly(); + if (this.relationships != null) + this.relationships.removeRelationship(id); + } + + /** + * Retrieve all the relationships attached to this part. + * + * @return This part's relationships. + * @throws OpenXML4JException + * @see org.apache.poi.openxml4j.opc.RelationshipSource#getRelationships() + */ + public PackageRelationshipCollection getRelationships() + throws InvalidFormatException { + return getRelationshipsCore(null); + } + + /** + * Retrieves a package relationship from its id. + * + * @param id + * ID of the package relationship to retrieve. + * @return The package relationship + * @see org.apache.poi.openxml4j.opc.RelationshipSource#getRelationship(java.lang.String) + */ + public PackageRelationship getRelationship(String id) { + return this.relationships.getRelationshipByID(id); + } + + /** + * Retrieve all relationships attached to this part which have the specified + * type. + * + * @param relationshipType + * Relationship type filter. + * @return All relationships from this part that have the specified type. + * @throws InvalidFormatException + * If an error occurs while parsing the part. + * @throws InvalidOperationException + * If the package is open in write only mode. + * @see org.apache.poi.openxml4j.opc.RelationshipSource#getRelationshipsByType(java.lang.String) + */ + public PackageRelationshipCollection getRelationshipsByType( + String relationshipType) throws InvalidFormatException { + container.throwExceptionIfWriteOnly(); + + return getRelationshipsCore(relationshipType); + } + + /** + * Implementation of the getRelationships method(). + * + * @param filter + * Relationship type filter. If <i>null</i> then the filter is + * disabled and return all the relationships. + * @return All relationships from this part that have the specified type. + * @throws InvalidFormatException + * Throws if an error occurs during parsing the relationships + * part. + * @throws InvalidOperationException + * Throws if the package is open en write only mode. + * @see #getRelationshipsByType(String) + */ + private PackageRelationshipCollection getRelationshipsCore(String filter) + throws InvalidFormatException { + this.container.throwExceptionIfWriteOnly(); + if (relationships == null) { + this.throwExceptionIfRelationship(); + relationships = new PackageRelationshipCollection(this); + } + return new PackageRelationshipCollection(relationships, filter); + } + + /** + * Knows if the part have any relationships. + * + * @return <b>true</b> if the part have at least one relationship else + * <b>false</b>. + * @see org.apache.poi.openxml4j.opc.RelationshipSource#hasRelationships() + */ + public boolean hasRelationships() { + return (!this.isRelationshipPart && (relationships != null && relationships + .size() > 0)); + } + + /** + * Checks if the specified relationship is part of this package part. + * + * @param rel + * The relationship to check. + * @return <b>true</b> if the specified relationship exists in this part, + * else returns <b>false</b> + * @see org.apache.poi.openxml4j.opc.RelationshipSource#isRelationshipExists(org.apache.poi.openxml4j.opc.PackageRelationship) + */ + @SuppressWarnings("finally") + public boolean isRelationshipExists(PackageRelationship rel) { + try { + for (PackageRelationship r : this.getRelationships()) { + if (r == rel) + return true; + } + } finally { + return false; + } + } + + /** + * Get the input stream of this part to read its content. + * + * @return The input stream of the content of this part, else + * <code>null</code>. + */ + public InputStream getInputStream() throws IOException { + InputStream inStream = this.getInputStreamImpl(); + if (inStream == null) { + throw new IOException("Can't obtain the input stream from " + + partName.getName()); + } else + return inStream; + } + + /** + * Get the output stream of this part. If the part is originally embedded in + * Zip package, it'll be transform intot a <i>MemoryPackagePart</i> in + * order to write inside (the standard Java API doesn't allow to write in + * the file) + * + * @see org.apache.poi.openxml4j.opc.internal.MemoryPackagePart + */ + public OutputStream getOutputStream() { + OutputStream outStream; + // If this part is a zip package part (read only by design) we convert + // this part into a MemoryPackagePart instance for write purpose. + if (this instanceof ZipPackagePart) { + // Delete logically this part + this.container.removePart(this.partName); + + // Create a memory part + PackagePart part = container.createPart(this.partName, + this.contentType.toString(), false); + part.relationships = this.relationships; + if (part == null) { + throw new InvalidOperationException( + "Can't create a temporary part !"); + } + outStream = part.getOutputStreamImpl(); + } else { + outStream = this.getOutputStreamImpl(); + } + return outStream; + } + + /** + * Throws an exception if this package part is a relationship part. + * + * @throws InvalidOperationException + * If this part is a relationship part. + */ + private void throwExceptionIfRelationship() + throws InvalidOperationException { + if (this.isRelationshipPart) + throw new InvalidOperationException( + "Can do this operation on a relationship part !"); + } + + /** + * Ensure the package relationships collection instance is built. + * + * @throws InvalidFormatException + * Throws if + */ + private void loadRelationships() throws InvalidFormatException { + if (this.relationships == null && !this.isRelationshipPart) { + this.throwExceptionIfRelationship(); + relationships = new PackageRelationshipCollection(this); + } + } + + /* + * Accessors + */ + + /** + * @return the uri + */ + public PackagePartName getPartName() { + return partName; + } + + /** + * @return the contentType + */ + public String getContentType() { + return contentType.toString(); + } + + /** + * Set the content type. + * + * @param contentType + * the contentType to set + * + * @throws InvalidFormatException + * Throws if the content type is not valid. + * @throws InvalidOperationException + * Throws if you try to change the content type whereas this + * part is already attached to a package. + */ + public void setContentType(String contentType) + throws InvalidFormatException { + if (container == null) + this.contentType = new ContentType(contentType); + else + throw new InvalidOperationException( + "You can't change the content type of a part."); + } + + public 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 <b>true</b> if the content has been successfully loaded, else + * <b>false</b>. + * @throws InvalidFormatException + * Throws if the content format is invalid. + */ + public abstract boolean load(InputStream ios) throws InvalidFormatException; + + /** + * Close this part : flush this part, close the input stream and output + * stream. After this method call, the part must be available for packaging. + */ + public abstract void close(); + + /** + * Flush the content of this part. If the input stream and/or output stream + * as in a waiting state to read or write, the must to empty their + * respective buffer. + */ + public abstract void flush(); +} 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<String> getCategoryProperty();
-
- /**
- * Set the category of the content of this package.
- */
- public abstract void setCategoryProperty(String category);
-
- /**
- * Set the status of the content.
- */
- public abstract Nullable<String> getContentStatusProperty();
-
- /**
- * Get the status of the content.
- */
- public abstract void setContentStatusProperty(String contentStatus);
-
- /**
- * Get the type of content represented, generally defined by a specific use
- * and intended audience.
- */
- public abstract Nullable<String> getContentTypeProperty();
-
- /**
- * Set the type of content represented, generally defined by a specific use
- * and intended audience.
- */
- public abstract void setContentTypeProperty(String contentType);
-
- /**
- * Get the date of creation of the resource.
- */
- public abstract Nullable<Date> getCreatedProperty();
-
- /**
- * Set the date of creation of the resource.
- */
- public abstract void setCreatedProperty(String created);
-
- /**
- * Set the date of creation of the resource.
- */
- public abstract void setCreatedProperty(Nullable<Date> created);
-
- /**
- * Get the entity primarily responsible for making the content of the
- * resource.
- */
- public abstract Nullable<String> getCreatorProperty();
-
- /**
- * Set the entity primarily responsible for making the content of the
- * resource.
- */
- public abstract void setCreatorProperty(String creator);
-
- /**
- * Get the explanation of the content of the resource.
- */
- public abstract Nullable<String> getDescriptionProperty();
-
- /**
- * Set the explanation of the content of the resource.
- */
- public abstract void setDescriptionProperty(String description);
-
- /**
- * Get an unambiguous reference to the resource within a given context.
- */
- public abstract Nullable<String> getIdentifierProperty();
-
- /**
- * Set an unambiguous reference to the resource within a given context.
- */
- public abstract void setIdentifierProperty(String identifier);
-
- /**
- * Get a delimited set of keywords to support searching and indexing. This
- * is typically a list of terms that are not available elsewhere in the
- * properties
- */
- public abstract Nullable<String> getKeywordsProperty();
-
- /**
- * Set a delimited set of keywords to support searching and indexing. This
- * is typically a list of terms that are not available elsewhere in the
- * properties
- */
- public abstract void setKeywordsProperty(String keywords);
-
- /**
- * Get the language of the intellectual content of the resource.
- */
- public abstract Nullable<String> getLanguageProperty();
-
- /**
- * Set the language of the intellectual content of the resource.
- */
- public abstract void setLanguageProperty(String language);
-
- /**
- * Get the user who performed the last modification.
- */
- public abstract Nullable<String> getLastModifiedByProperty();
-
- /**
- * Set the user who performed the last modification.
- */
- public abstract void setLastModifiedByProperty(String lastModifiedBy);
-
- /**
- * Get the date and time of the last printing.
- */
- public abstract Nullable<Date> getLastPrintedProperty();
-
- /**
- * Set the date and time of the last printing.
- */
- public abstract void setLastPrintedProperty(String lastPrinted);
-
- /**
- * Set the date and time of the last printing.
- */
- public abstract void setLastPrintedProperty(Nullable<Date> lastPrinted);
-
- /**
- * Get the date on which the resource was changed.
- */
- public abstract Nullable<Date> getModifiedProperty();
-
- /**
- * Set the date on which the resource was changed.
- */
- public abstract void setModifiedProperty(String modified);
-
- /**
- * Set the date on which the resource was changed.
- */
- public abstract void setModifiedProperty(Nullable<Date> modified);
-
- /**
- * Get the revision number.
- */
- public abstract Nullable<String> getRevisionProperty();
-
- /**
- * Set the revision number.
- */
- public abstract void setRevisionProperty(String revision);
-
- /**
- * Get the topic of the content of the resource.
- */
- public abstract Nullable<String> getSubjectProperty();
-
- /**
- * Set the topic of the content of the resource.
- */
- public abstract void setSubjectProperty(String subject);
-
- /**
- * Get the name given to the resource.
- */
- public abstract Nullable<String> getTitleProperty();
-
- /**
- * Set the name given to the resource.
- */
- public abstract void setTitleProperty(String title);
-
- /**
- * Get the version number.
- */
- public abstract Nullable<String> getVersionProperty();
-
- /**
- * Set the version number.
- */
- public abstract void setVersionProperty(String version);
-}
+/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc; + +import java.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<String> getCategoryProperty(); + + /** + * Set the category of the content of this package. + */ + public abstract void setCategoryProperty(String category); + + /** + * Set the status of the content. + */ + public abstract Nullable<String> getContentStatusProperty(); + + /** + * Get the status of the content. + */ + public abstract void setContentStatusProperty(String contentStatus); + + /** + * Get the type of content represented, generally defined by a specific use + * and intended audience. + */ + public abstract Nullable<String> getContentTypeProperty(); + + /** + * Set the type of content represented, generally defined by a specific use + * and intended audience. + */ + public abstract void setContentTypeProperty(String contentType); + + /** + * Get the date of creation of the resource. + */ + public abstract Nullable<Date> getCreatedProperty(); + + /** + * Set the date of creation of the resource. + */ + public abstract void setCreatedProperty(String created); + + /** + * Set the date of creation of the resource. + */ + public abstract void setCreatedProperty(Nullable<Date> created); + + /** + * Get the entity primarily responsible for making the content of the + * resource. + */ + public abstract Nullable<String> getCreatorProperty(); + + /** + * Set the entity primarily responsible for making the content of the + * resource. + */ + public abstract void setCreatorProperty(String creator); + + /** + * Get the explanation of the content of the resource. + */ + public abstract Nullable<String> getDescriptionProperty(); + + /** + * Set the explanation of the content of the resource. + */ + public abstract void setDescriptionProperty(String description); + + /** + * Get an unambiguous reference to the resource within a given context. + */ + public abstract Nullable<String> getIdentifierProperty(); + + /** + * Set an unambiguous reference to the resource within a given context. + */ + public abstract void setIdentifierProperty(String identifier); + + /** + * Get a delimited set of keywords to support searching and indexing. This + * is typically a list of terms that are not available elsewhere in the + * properties + */ + public abstract Nullable<String> getKeywordsProperty(); + + /** + * Set a delimited set of keywords to support searching and indexing. This + * is typically a list of terms that are not available elsewhere in the + * properties + */ + public abstract void setKeywordsProperty(String keywords); + + /** + * Get the language of the intellectual content of the resource. + */ + public abstract Nullable<String> getLanguageProperty(); + + /** + * Set the language of the intellectual content of the resource. + */ + public abstract void setLanguageProperty(String language); + + /** + * Get the user who performed the last modification. + */ + public abstract Nullable<String> getLastModifiedByProperty(); + + /** + * Set the user who performed the last modification. + */ + public abstract void setLastModifiedByProperty(String lastModifiedBy); + + /** + * Get the date and time of the last printing. + */ + public abstract Nullable<Date> getLastPrintedProperty(); + + /** + * Set the date and time of the last printing. + */ + public abstract void setLastPrintedProperty(String lastPrinted); + + /** + * Set the date and time of the last printing. + */ + public abstract void setLastPrintedProperty(Nullable<Date> lastPrinted); + + /** + * Get the date on which the resource was changed. + */ + public abstract Nullable<Date> getModifiedProperty(); + + /** + * Set the date on which the resource was changed. + */ + public abstract void setModifiedProperty(String modified); + + /** + * Set the date on which the resource was changed. + */ + public abstract void setModifiedProperty(Nullable<Date> modified); + + /** + * Get the revision number. + */ + public abstract Nullable<String> getRevisionProperty(); + + /** + * Set the revision number. + */ + public abstract void setRevisionProperty(String revision); + + /** + * Get the topic of the content of the resource. + */ + public abstract Nullable<String> getSubjectProperty(); + + /** + * Set the topic of the content of the resource. + */ + public abstract void setSubjectProperty(String subject); + + /** + * Get the name given to the resource. + */ + public abstract Nullable<String> getTitleProperty(); + + /** + * Set the name given to the resource. + */ + public abstract void setTitleProperty(String title); + + /** + * Get the version number. + */ + public abstract Nullable<String> getVersionProperty(); + + /** + * Set the version number. + */ + public abstract void setVersionProperty(String version); +} 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<PackageRelationship> {
-
- private static POILogger logger = POILogFactory.getLogger(PackageRelationshipCollection.class);
-
- /**
- * Package relationships ordered by ID.
- */
- private TreeMap<String, PackageRelationship> relationshipsByID;
-
- /**
- * Package relationships ordered by type.
- */
- private TreeMap<String, PackageRelationship> relationshipsByType;
-
- /**
- * This relationshipPart.
- */
- private PackagePart relationshipPart;
-
- /**
- * Source part.
- */
- private PackagePart sourcePart;
-
- /**
- * This part name.
- */
- private PackagePartName partName;
-
- /**
- * Reference to the package.
- */
- private Package container;
-
- /**
- * Constructor.
- */
- PackageRelationshipCollection() {
- relationshipsByID = new TreeMap<String, PackageRelationship>();
- relationshipsByType = new TreeMap<String, PackageRelationship>();
- }
-
- /**
- * Copy constructor.
- *
- * This collection will contain only elements from the specified collection
- * for which the type is compatible with the specified relationship type
- * filter.
- *
- * @param coll
- * Collection to import.
- * @param filter
- * Relationship type filter.
- */
- public PackageRelationshipCollection(PackageRelationshipCollection coll,
- String filter) {
- this();
- for (PackageRelationship rel : coll.relationshipsByID.values()) {
- if (filter == null || rel.getRelationshipType().equals(filter))
- addRelationship(rel);
- }
- }
-
- /**
- * Constructor.
- */
- public PackageRelationshipCollection(Package container)
- throws InvalidFormatException {
- this(container, null);
- }
-
- /**
- * Constructor.
- *
- * @throws InvalidFormatException
- * Throws if the format of the content part is invalid.
- *
- * @throws InvalidOperationException
- * Throws if the specified part is a relationship part.
- */
- public PackageRelationshipCollection(PackagePart part)
- throws InvalidFormatException {
- this(part.container, part);
- }
-
- /**
- * Constructor. Parse the existing package relationship part if one exists.
- *
- * @param container
- * The parent package.
- * @param part
- * The part that own this relationships collection. If <b>null</b>
- * then this part is considered as the package root.
- * @throws InvalidFormatException
- * If an error occurs during the parsing of the relatinships
- * part fo the specified part.
- */
- public PackageRelationshipCollection(Package container, PackagePart part)
- throws InvalidFormatException {
- this();
-
- if (container == null)
- throw new IllegalArgumentException("container");
-
- // Check if the specified part is not a relationship part
- if (part != null && part.isRelationshipPart())
- throw new IllegalArgumentException("part");
-
- this.container = container;
- this.sourcePart = part;
- this.partName = getRelationshipPartName(part);
- if ((container.getPackageAccess() != PackageAccess.WRITE)
- && container.containPart(this.partName)) {
- relationshipPart = container.getPart(this.partName);
- parseRelationshipsPart(relationshipPart);
- }
- }
-
- /**
- * Get the relationship part name of the specified part.
- *
- * @param part
- * The part .
- * @return The relationship part name of the specified part. Be careful,
- * only the correct name is returned, this method does not check if
- * the part really exist in a package !
- * @throws InvalidOperationException
- * Throws if the specified part is a relationship part.
- */
- private static PackagePartName getRelationshipPartName(PackagePart part)
- throws InvalidOperationException {
- PackagePartName partName;
- if (part == null) {
- partName = PackagingURIHelper.PACKAGE_ROOT_PART_NAME;
- } else {
- partName = part.getPartName();
- }
- return PackagingURIHelper.getRelationshipPartName(partName);
- }
-
- /**
- * Add the specified relationship to the collection.
- *
- * @param relPart
- * The relationship to add.
- */
- public void addRelationship(PackageRelationship relPart) {
- relationshipsByID.put(relPart.getId(), relPart);
- relationshipsByType.put(relPart.getRelationshipType(), relPart);
- }
-
- /**
- * Add a relationship to the collection.
- *
- * @param targetUri
- * Target URI.
- * @param targetMode
- * The target mode : INTERNAL or EXTERNAL
- * @param relationshipType
- * Relationship type.
- * @param id
- * Relationship ID.
- * @return The newly created relationship.
- * @see PackageAccess
- */
- public PackageRelationship addRelationship(URI targetUri,
- TargetMode targetMode, String relationshipType, String id) {
-
- if (id == null) {
- // Generate a unique ID is id parameter is null.
- int i = 0;
- do {
- id = "rId" + ++i;
- } while (relationshipsByID.get(id) != null);
- }
-
- PackageRelationship rel = new PackageRelationship(container,
- sourcePart, targetUri, targetMode, relationshipType, id);
- relationshipsByID.put(rel.getId(), rel);
- relationshipsByType.put(rel.getRelationshipType(), rel);
- return rel;
- }
-
- /**
- * Remove a relationship by its ID.
- *
- * @param id
- * The relationship ID to remove.
- */
- public void removeRelationship(String id) {
- if (relationshipsByID != null && relationshipsByType != null) {
- PackageRelationship rel = relationshipsByID.get(id);
- if (rel != null) {
- relationshipsByID.remove(rel.getId());
- relationshipsByType.values().remove(rel);
- }
- }
- }
-
- /**
- * Remove a relationship by its reference.
- *
- * @param rel
- * The relationship to delete.
- */
- public void removeRelationship(PackageRelationship rel) {
- if (rel == null)
- throw new IllegalArgumentException("rel");
-
- relationshipsByID.values().remove(rel);
- relationshipsByType.values().remove(rel);
- }
-
- /**
- * Retrieves a relationship by its index in the collection.
- *
- * @param index
- * Must be a value between [0-relationships_count-1]
- */
- public PackageRelationship getRelationship(int index) {
- if (index < 0 || index > relationshipsByID.values().size())
- throw new IllegalArgumentException("index");
-
- PackageRelationship retRel = null;
- int i = 0;
- for (PackageRelationship rel : relationshipsByID.values()) {
- if (index == i++)
- return rel;
- }
- return retRel;
- }
-
- /**
- * Retrieves a package relationship based on its id.
- *
- * @param id
- * ID of the package relationship to retrieve.
- * @return The package relationship identified by the specified id.
- */
- public PackageRelationship getRelationshipByID(String id) {
- return relationshipsByID.get(id);
- }
-
- /**
- * Get the numbe rof relationships in the collection.
- */
- public int size() {
- return relationshipsByID.values().size();
- }
-
- /**
- * Parse the relationship part and add all relationship in this collection.
- *
- * @param relPart
- * The package part to parse.
- * @throws InvalidFormatException
- * Throws if the relationship part is invalid.
- */
- private void parseRelationshipsPart(PackagePart relPart)
- throws InvalidFormatException {
- try {
- SAXReader reader = new SAXReader();
- logger.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 <b>null</b> then all
- * relationships are returned.
- * @return All relationships of the type specified by the filter.
- */
- public PackageRelationshipCollection getRelationships(String typeFilter) {
- PackageRelationshipCollection coll = new PackageRelationshipCollection(
- this, typeFilter);
- return coll;
- }
-
- /**
- * Get this collection's iterator.
- */
- public Iterator<PackageRelationship> iterator() {
- return relationshipsByID.values().iterator();
- }
-
- /**
- * Get an iterator of a collection with all relationship with the specified
- * type.
- *
- * @param typeFilter
- * Type filter.
- * @return An iterator to a collection containing all relationships with the
- * specified type contain in this collection.
- */
- public Iterator<PackageRelationship> iterator(String typeFilter) {
- ArrayList<PackageRelationship> retArr = new ArrayList<PackageRelationship>();
- for (PackageRelationship rel : relationshipsByID.values()) {
- if (rel.getRelationshipType().equals(typeFilter))
- retArr.add(rel);
- }
- return retArr.iterator();
- }
-
- /**
- * Clear all relationships.
- */
- public void clear() {
- relationshipsByID.clear();
- relationshipsByType.clear();
- }
-
- @Override
- public String toString() {
- String str;
- if (relationshipsByID == null) {
- str = "relationshipsByID=null";
- } else {
- str = relationshipsByID.size() + " relationship(s) = [";
- }
- if ((relationshipPart != null) && (relationshipPart.partName != null)) {
- str = str + "," + relationshipPart.partName;
- } else {
- str = str + ",relationshipPart=null";
- }
-
- // Source of this relationship
- if ((sourcePart != null) && (sourcePart.partName != null)) {
- str = str + "," + sourcePart.partName;
- } else {
- str = str + ",sourcePart=null";
- }
- if (partName != null) {
- str = str + "," + partName;
- } else {
- str = str + ",uri=null)";
- }
- return str + "]";
- }
-}
+/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.openxml4j.opc; + +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<PackageRelationship> { + + private static POILogger logger = POILogFactory.getLogger(PackageRelationshipCollection.class); + + /** + * Package relationships ordered by ID. + */ + private TreeMap<String, PackageRelationship> relationshipsByID; + + /** + * Package relationships ordered by type. + */ + private TreeMap<String, PackageRelationship> relationshipsByType; + + /** + * This relationshipPart. + */ + private PackagePart relationshipPart; + + /** + * Source part. + */ + private PackagePart sourcePart; + + /** + * This part name. + */ + private PackagePartName partName; + + /** + * Reference to the package. + */ + private OPCPackage container; + + /** + * Constructor. + */ + PackageRelationshipCollection() { + relationshipsByID = new TreeMap<String, PackageRelationship>(); + relationshipsByType = new TreeMap<String, PackageRelationship>(); + } + + /** + * Copy constructor. + * + * This collection will contain only elements from the specified collection + * for which the type is compatible with the specified relationship type + * filter. + * + * @param coll + * Collection to import. + * @param filter + * Relationship type filter. + */ + public PackageRelationshipCollection(PackageRelationshipCollection coll, + String filter) { + this(); + for (PackageRelationship rel : coll.relationshipsByID.values()) { + if (filter == null || rel.getRelationshipType().equals(filter)) + addRelationship(rel); + } + } + + /** + * Constructor. + */ + public PackageRelationshipCollection(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 <b>null</b> + * then this part is considered as the package root. + * @throws InvalidFormatException + * If an error occurs during the parsing of the relatinships + * part fo the specified part. + */ + public PackageRelationshipCollection(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 <b>null</b> then all + * relationships are returned. + * @return All relationships of the type specified by the filter. + */ + public PackageRelationshipCollection getRelationships(String typeFilter) { + PackageRelationshipCollection coll = new PackageRelationshipCollection( + this, typeFilter); + return coll; + } + + /** + * Get this collection's iterator. + */ + public Iterator<PackageRelationship> iterator() { + return relationshipsByID.values().iterator(); + } + + /** + * Get an iterator of a collection with all relationship with the specified + * type. + * + * @param typeFilter + * Type filter. + * @return An iterator to a collection containing all relationships with the + * specified type contain in this collection. + */ + public Iterator<PackageRelationship> iterator(String typeFilter) { + ArrayList<PackageRelationship> retArr = new ArrayList<PackageRelationship>(); + for (PackageRelationship rel : relationshipsByID.values()) { + if (rel.getRelationshipType().equals(typeFilter)) + retArr.add(rel); + } + return retArr.iterator(); + } + + /** + * Clear all relationships. + */ + public void clear() { + relationshipsByID.clear(); + relationshipsByType.clear(); + } + + @Override + public String toString() { + String str; + if (relationshipsByID == null) { + str = "relationshipsByID=null"; + } else { + str = relationshipsByID.size() + " relationship(s) = ["; + } + if ((relationshipPart != null) && (relationshipPart.partName != null)) { + str = str + "," + relationshipPart.partName; + } else { + str = str + ",relationshipPart=null"; + } + + // Source of this relationship + if ((sourcePart != null) && (sourcePart.partName != null)) { + str = str + "," + sourcePart.partName; + } else { + str = str + ",sourcePart=null"; + } + if (partName != null) { + str = str + "," + partName; + } else { + str = str + ",uri=null)"; + } + return str + "]"; + } +} 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 <b>null</b>. Normally
- * will never be called since the MemoryPackage is use instead.
- *
- * @return <b>null</b>
- */
- @Override
- protected OutputStream getOutputStreamImpl() {
- return null;
- }
-
- @Override
- public boolean save(OutputStream os) throws OpenXML4JException {
- return new ZipPartMarshaller().marshall(this, os);
- }
-
- @Override
- public boolean load(InputStream ios) throws InvalidFormatException {
- throw new InvalidOperationException("Method not implemented !");
- }
-
- @Override
- public void close() {
- throw new InvalidOperationException("Method not implemented !");
- }
-
- @Override
- public void flush() {
- throw new InvalidOperationException("Method not implemented !");
- }
-}
+/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc; + +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 <b>null</b>. Normally + * will never be called since the MemoryPackage is use instead. + * + * @return <b>null</b> + */ + @Override + protected OutputStream getOutputStreamImpl() { + return null; + } + + @Override + public boolean save(OutputStream os) throws OpenXML4JException { + return new ZipPartMarshaller().marshall(this, os); + } + + @Override + public boolean load(InputStream ios) throws InvalidFormatException { + throw new InvalidOperationException("Method not implemented !"); + } + + @Override + public void close() { + throw new InvalidOperationException("Method not implemented !"); + } + + @Override + public void flush() { + throw new InvalidOperationException("Method not implemented !"); + } +} 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. <Extension, ContentType>
- */
- private TreeMap<String, String> defaultContentType;
-
- /**
- * Override content type tree.
- */
- private TreeMap<PackagePartName, String> overrideContentType;
-
- /**
- * Constructor. Parses the content of the specified input stream.
- *
- * @param in
- * If different of <i>null</i> then the content types part is
- * retrieve and parse.
- * @throws InvalidFormatException
- * If the content types part content is not valid.
- */
- public ContentTypeManager(InputStream in, Package pkg)
- throws InvalidFormatException {
- this.container = pkg;
- this.defaultContentType = new TreeMap<String, String>();
- if (in != null) {
- try {
- parseContentTypesFile(in);
- } catch (InvalidFormatException e) {
- throw new InvalidFormatException(
- "Can't read content types part !");
- }
- }
- }
-
- /**
- * Build association extention-> content type (will be stored in
- * [Content_Types].xml) for example ContentType="image/png" Extension="png"
- * <p>
- * [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:
- * </p><p>
- * 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.
- * </p><p>
- * 2. If a part name has no extension, a corresponding Override element
- * shall be added to the Content Types stream.
- * </p><p>
- * 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.
- * </p><p>
- * 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.
- * </p><p>
- * a. If the content types match, no further action is required.
- * </p><p>
- * b. If the content types do not match, a new Override element shall be
- * added to the Content Types stream. .
- * </p><p>
- * 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.
- * </p>
- */
- public void addContentType(PackagePartName partName, String contentType) {
- boolean defaultCTExists = false;
- String extension = partName.getExtension().toLowerCase();
- if ((extension.length() == 0)
- || (this.defaultContentType.containsKey(extension) && !(defaultCTExists = this.defaultContentType
- .containsValue(contentType))))
- this.addOverrideContentType(partName, contentType);
- else if (!defaultCTExists)
- this.addDefaultContentType(extension, contentType);
- }
-
- /**
- * Add an override content type for a specific part.
- *
- * @param partName
- * Name of the part.
- * @param contentType
- * Content type of the part.
- */
- private void addOverrideContentType(PackagePartName partName,
- String contentType) {
- if (overrideContentType == null)
- overrideContentType = new TreeMap<PackagePartName, String>();
- overrideContentType.put(partName, contentType);
- }
-
- /**
- * Add a content type associated with the specified extension.
- *
- * @param extension
- * The part name extension to bind to a content type.
- * @param contentType
- * The content type associated with the specified extension.
- */
- private void addDefaultContentType(String extension, String contentType) {
- // Remark : Originally the latest parameter was :
- // contentType.toLowerCase(). Change due to a request ID 1996748.
- defaultContentType.put(extension.toLowerCase(), contentType);
- }
-
- /**
- * <p>
- * 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.
- * </p><p>
- * 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.
- * </p>
- * @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 <code>true</code> if the specified content type is already
- * register, then <code>false</code>.
- */
- public boolean isContentTypeRegister(String contentType) {
- if (contentType == null)
- throw new IllegalArgumentException("contentType");
-
- return (this.defaultContentType.values().contains(contentType) || (this.overrideContentType != null && this.overrideContentType
- .values().contains(contentType)));
- }
-
- /**
- * Get the content type for the specified part, if any.
- * <p>
- * Rule [M2.9]: To get the content type of a part, the package implementer
- * shall perform the steps described in §9.1.2.4:
- * </p><p>
- * 1. Compare the part name with the values specified for the PartName
- * attribute of the Override elements. The comparison shall be
- * case-insensitive ASCII.
- * </p><p>
- * 2. If there is an Override element with a matching PartName attribute,
- * return the value of its ContentType attribute. No further action is
- * required.
- * </p><p>
- * 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.
- * </p><p>
- * 4. If there is a Default element with a matching Extension attribute,
- * return the value of its ContentType attribute. No further action is
- * required.
- * </p><p>
- * 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.
- * </p>
- * @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 <code>null</code>.
- *
- * @exception OpenXML4JRuntimeException
- * Throws if the content type manager is not able to find the
- * content from an existing part.
- */
- public String getContentType(PackagePartName partName) {
- if (partName == null)
- throw new IllegalArgumentException("partName");
-
- if ((this.overrideContentType != null)
- && this.overrideContentType.containsKey(partName))
- return this.overrideContentType.get(partName);
-
- String extension = partName.getExtension().toLowerCase();
- if (this.defaultContentType.containsKey(extension))
- return this.defaultContentType.get(extension);
-
- /*
- * [M2.4] : The package implementer shall require that the Content Types
- * stream contain one of the following for every part in the package:
- * One matching Default element, One matching Override element, Both a
- * matching Default element and a matching Override element, in which
- * case the Override element takes precedence.
- */
- if (this.container != null && this.container.getPart(partName) != null) {
- throw new OpenXML4JRuntimeException(
- "Rule M2.4 exception : this error should NEVER happen, if so please send a mail to the developers team, thanks !");
- } else {
- return null;
- }
- }
-
- /**
- * Clear all content types.
- */
- public void clearAll() {
- this.defaultContentType.clear();
- if (this.overrideContentType != null)
- this.overrideContentType.clear();
- }
-
- /**
- * Clear all override content types.
- *
- */
- public void clearOverrideContentTypes() {
- if (this.overrideContentType != null)
- this.overrideContentType.clear();
- }
-
- /**
- * Parse the content types part.
- *
- * @throws InvalidFormatException
- * Throws if the content type doesn't exist or the XML format is
- * invalid.
- */
- private void parseContentTypesFile(InputStream in)
- throws InvalidFormatException {
- try {
- SAXReader xmlReader = new SAXReader();
- Document xmlContentTypetDoc = xmlReader.read(in);
-
- // Default content types
- List defaultTypes = xmlContentTypetDoc.getRootElement().elements(
- DEFAULT_TAG_NAME);
- Iterator elementIteratorDefault = defaultTypes.iterator();
- while (elementIteratorDefault.hasNext()) {
- Element element = (Element) elementIteratorDefault.next();
- String extension = element.attribute(EXTENSION_ATTRIBUTE_NAME)
- .getValue();
- String contentType = element.attribute(
- CONTENT_TYPE_ATTRIBUTE_NAME).getValue();
- addDefaultContentType(extension, contentType);
- }
-
- // Overriden content types
- List overrideTypes = xmlContentTypetDoc.getRootElement().elements(
- OVERRIDE_TAG_NAME);
- Iterator elementIteratorOverride = overrideTypes.iterator();
- while (elementIteratorOverride.hasNext()) {
- Element element = (Element) elementIteratorOverride.next();
- URI uri = new URI(element.attribute(PART_NAME_ATTRIBUTE_NAME)
- .getValue());
- PackagePartName partName = PackagingURIHelper
- .createPartName(uri);
- String contentType = element.attribute(
- CONTENT_TYPE_ATTRIBUTE_NAME).getValue();
- addOverrideContentType(partName, contentType);
- }
- } catch (URISyntaxException urie) {
- throw new InvalidFormatException(urie.getMessage());
- } catch (DocumentException e) {
- throw new InvalidFormatException(e.getMessage());
- }
- }
-
- /**
- * Save the contents type part.
- *
- * @param outStream
- * The output stream use to save the XML content of the content
- * types part.
- * @return <b>true</b> if the operation success, else <b>false</b>.
- */
- public boolean save(OutputStream outStream) {
- Document xmlOutDoc = DocumentHelper.createDocument();
-
- // Building namespace
- Namespace dfNs = Namespace.get("", TYPES_NAMESPACE_URI);
- Element typesElem = xmlOutDoc
- .addElement(new QName(TYPES_TAG_NAME, dfNs));
-
- // Adding default types
- for (Entry<String, String> entry : defaultContentType.entrySet()) {
- appendDefaultType(typesElem, entry);
- }
-
- // Adding specific types if any exist
- if (overrideContentType != null) {
- for (Entry<PackagePartName, String> entry : overrideContentType
- .entrySet()) {
- appendSpecificTypes(typesElem, entry);
- }
- }
- xmlOutDoc.normalize();
-
- // Save content in the specified output stream
- return this.saveImpl(xmlOutDoc, outStream);
- }
-
- /**
- * Use to append specific type XML elements, use by the save() method.
- *
- * @param root
- * XML parent element use to append this override type element.
- * @param entry
- * The values to append.
- * @see #save(java.io.OutputStream)
- */
- private void appendSpecificTypes(Element root,
- Entry<PackagePartName, String> entry) {
- root.addElement(OVERRIDE_TAG_NAME).addAttribute(
- PART_NAME_ATTRIBUTE_NAME,
- ((PackagePartName) entry.getKey()).getName()).addAttribute(
- CONTENT_TYPE_ATTRIBUTE_NAME, (String) entry.getValue());
- }
-
- /**
- * Use to append default types XML elements, use by the save() metid.
- *
- * @param root
- * XML parent element use to append this default type element.
- * @param entry
- * The values to append.
- * @see #save(java.io.OutputStream)
- */
- private void appendDefaultType(Element root, Entry<String, String> entry) {
- root.addElement(DEFAULT_TAG_NAME).addAttribute(
- EXTENSION_ATTRIBUTE_NAME, (String) entry.getKey())
- .addAttribute(CONTENT_TYPE_ATTRIBUTE_NAME,
- (String) entry.getValue());
-
- }
-
- /**
- * Specific implementation of the save method. Call by the save() method,
- * call before exiting.
- *
- * @param out
- * The output stream use to write the content type XML.
- */
- public abstract boolean saveImpl(Document content, OutputStream out);
-}
+/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc.internal; + +import java.io.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. <Extension, ContentType> + */ + private TreeMap<String, String> defaultContentType; + + /** + * Override content type tree. + */ + private TreeMap<PackagePartName, String> overrideContentType; + + /** + * Constructor. Parses the content of the specified input stream. + * + * @param in + * If different of <i>null</i> then the content types part is + * retrieve and parse. + * @throws InvalidFormatException + * If the content types part content is not valid. + */ + public ContentTypeManager(InputStream in, OPCPackage pkg) + throws InvalidFormatException { + this.container = pkg; + this.defaultContentType = new TreeMap<String, String>(); + if (in != null) { + try { + parseContentTypesFile(in); + } catch (InvalidFormatException e) { + throw new InvalidFormatException( + "Can't read content types part !"); + } + } + } + + /** + * Build association extention-> content type (will be stored in + * [Content_Types].xml) for example ContentType="image/png" Extension="png" + * <p> + * [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: + * </p><p> + * 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. + * </p><p> + * 2. If a part name has no extension, a corresponding Override element + * shall be added to the Content Types stream. + * </p><p> + * 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. + * </p><p> + * 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. + * </p><p> + * a. If the content types match, no further action is required. + * </p><p> + * b. If the content types do not match, a new Override element shall be + * added to the Content Types stream. . + * </p><p> + * 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. + * </p> + */ + public void addContentType(PackagePartName partName, String contentType) { + boolean defaultCTExists = false; + String extension = partName.getExtension().toLowerCase(); + if ((extension.length() == 0) + || (this.defaultContentType.containsKey(extension) && !(defaultCTExists = this.defaultContentType + .containsValue(contentType)))) + this.addOverrideContentType(partName, contentType); + else if (!defaultCTExists) + this.addDefaultContentType(extension, contentType); + } + + /** + * Add an override content type for a specific part. + * + * @param partName + * Name of the part. + * @param contentType + * Content type of the part. + */ + private void addOverrideContentType(PackagePartName partName, + String contentType) { + if (overrideContentType == null) + overrideContentType = new TreeMap<PackagePartName, String>(); + overrideContentType.put(partName, contentType); + } + + /** + * Add a content type associated with the specified extension. + * + * @param extension + * The part name extension to bind to a content type. + * @param contentType + * The content type associated with the specified extension. + */ + private void addDefaultContentType(String extension, String contentType) { + // Remark : Originally the latest parameter was : + // contentType.toLowerCase(). Change due to a request ID 1996748. + defaultContentType.put(extension.toLowerCase(), contentType); + } + + /** + * <p> + * 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. + * </p><p> + * 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. + * </p> + * @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 <code>true</code> if the specified content type is already + * register, then <code>false</code>. + */ + public boolean isContentTypeRegister(String contentType) { + if (contentType == null) + throw new IllegalArgumentException("contentType"); + + return (this.defaultContentType.values().contains(contentType) || (this.overrideContentType != null && this.overrideContentType + .values().contains(contentType))); + } + + /** + * Get the content type for the specified part, if any. + * <p> + * Rule [M2.9]: To get the content type of a part, the package implementer + * shall perform the steps described in §9.1.2.4: + * </p><p> + * 1. Compare the part name with the values specified for the PartName + * attribute of the Override elements. The comparison shall be + * case-insensitive ASCII. + * </p><p> + * 2. If there is an Override element with a matching PartName attribute, + * return the value of its ContentType attribute. No further action is + * required. + * </p><p> + * 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. + * </p><p> + * 4. If there is a Default element with a matching Extension attribute, + * return the value of its ContentType attribute. No further action is + * required. + * </p><p> + * 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. + * </p> + * @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 <code>null</code>. + * + * @exception OpenXML4JRuntimeException + * Throws if the content type manager is not able to find the + * content from an existing part. + */ + public String getContentType(PackagePartName partName) { + if (partName == null) + throw new IllegalArgumentException("partName"); + + if ((this.overrideContentType != null) + && this.overrideContentType.containsKey(partName)) + return this.overrideContentType.get(partName); + + String extension = partName.getExtension().toLowerCase(); + if (this.defaultContentType.containsKey(extension)) + return this.defaultContentType.get(extension); + + /* + * [M2.4] : The package implementer shall require that the Content Types + * stream contain one of the following for every part in the package: + * One matching Default element, One matching Override element, Both a + * matching Default element and a matching Override element, in which + * case the Override element takes precedence. + */ + if (this.container != null && this.container.getPart(partName) != null) { + throw new OpenXML4JRuntimeException( + "Rule M2.4 exception : this error should NEVER happen, if so please send a mail to the developers team, thanks !"); + } else { + return null; + } + } + + /** + * Clear all content types. + */ + public void clearAll() { + this.defaultContentType.clear(); + if (this.overrideContentType != null) + this.overrideContentType.clear(); + } + + /** + * Clear all override content types. + * + */ + public void clearOverrideContentTypes() { + if (this.overrideContentType != null) + this.overrideContentType.clear(); + } + + /** + * Parse the content types part. + * + * @throws InvalidFormatException + * Throws if the content type doesn't exist or the XML format is + * invalid. + */ + private void parseContentTypesFile(InputStream in) + throws InvalidFormatException { + try { + SAXReader xmlReader = new SAXReader(); + Document xmlContentTypetDoc = xmlReader.read(in); + + // Default content types + List defaultTypes = xmlContentTypetDoc.getRootElement().elements( + DEFAULT_TAG_NAME); + Iterator elementIteratorDefault = defaultTypes.iterator(); + while (elementIteratorDefault.hasNext()) { + Element element = (Element) elementIteratorDefault.next(); + String extension = element.attribute(EXTENSION_ATTRIBUTE_NAME) + .getValue(); + String contentType = element.attribute( + CONTENT_TYPE_ATTRIBUTE_NAME).getValue(); + addDefaultContentType(extension, contentType); + } + + // Overriden content types + List overrideTypes = xmlContentTypetDoc.getRootElement().elements( + OVERRIDE_TAG_NAME); + Iterator elementIteratorOverride = overrideTypes.iterator(); + while (elementIteratorOverride.hasNext()) { + Element element = (Element) elementIteratorOverride.next(); + URI uri = new URI(element.attribute(PART_NAME_ATTRIBUTE_NAME) + .getValue()); + PackagePartName partName = PackagingURIHelper + .createPartName(uri); + String contentType = element.attribute( + CONTENT_TYPE_ATTRIBUTE_NAME).getValue(); + addOverrideContentType(partName, contentType); + } + } catch (URISyntaxException urie) { + throw new InvalidFormatException(urie.getMessage()); + } catch (DocumentException e) { + throw new InvalidFormatException(e.getMessage()); + } + } + + /** + * Save the contents type part. + * + * @param outStream + * The output stream use to save the XML content of the content + * types part. + * @return <b>true</b> if the operation success, else <b>false</b>. + */ + public boolean save(OutputStream outStream) { + Document xmlOutDoc = DocumentHelper.createDocument(); + + // Building namespace + Namespace dfNs = Namespace.get("", TYPES_NAMESPACE_URI); + Element typesElem = xmlOutDoc + .addElement(new QName(TYPES_TAG_NAME, dfNs)); + + // Adding default types + for (Entry<String, String> entry : defaultContentType.entrySet()) { + appendDefaultType(typesElem, entry); + } + + // Adding specific types if any exist + if (overrideContentType != null) { + for (Entry<PackagePartName, String> entry : overrideContentType + .entrySet()) { + appendSpecificTypes(typesElem, entry); + } + } + xmlOutDoc.normalize(); + + // Save content in the specified output stream + return this.saveImpl(xmlOutDoc, outStream); + } + + /** + * Use to append specific type XML elements, use by the save() method. + * + * @param root + * XML parent element use to append this override type element. + * @param entry + * The values to append. + * @see #save(java.io.OutputStream) + */ + private void appendSpecificTypes(Element root, + Entry<PackagePartName, String> entry) { + root.addElement(OVERRIDE_TAG_NAME).addAttribute( + PART_NAME_ATTRIBUTE_NAME, + ((PackagePartName) entry.getKey()).getName()).addAttribute( + CONTENT_TYPE_ATTRIBUTE_NAME, (String) entry.getValue()); + } + + /** + * Use to append default types XML elements, use by the save() metid. + * + * @param root + * XML parent element use to append this default type element. + * @param entry + * The values to append. + * @see #save(java.io.OutputStream) + */ + private void appendDefaultType(Element root, Entry<String, String> entry) { + root.addElement(DEFAULT_TAG_NAME).addAttribute( + EXTENSION_ATTRIBUTE_NAME, (String) entry.getKey()) + .addAttribute(CONTENT_TYPE_ATTRIBUTE_NAME, + (String) entry.getValue()); + + } + + /** + * Specific implementation of the save method. Call by the save() method, + * call before exiting. + * + * @param out + * The output stream use to write the content type XML. + */ + public abstract boolean saveImpl(Document content, OutputStream out); +} 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<String> category = new Nullable<String>();
-
- /**
- * The status of the content.
- *
- * [Example: Values might include "Draft", "Reviewed", and "Final". end
- * example]
- */
- protected Nullable<String> contentStatus = new Nullable<String>();
-
- /**
- * The type of content represented, generally defined by a specific use and
- * intended audience.
- *
- * [Example: Values might include "Whitepaper", "Security Bulletin", and
- * "Exam". end example] [Note: This property is distinct from MIME content
- * types as defined in RFC 2616. end note]
- */
- protected Nullable<String> contentType = new Nullable<String>();
-
- /**
- * Date of creation of the resource.
- */
- protected Nullable<Date> created = new Nullable<Date>();
-
- /**
- * An entity primarily responsible for making the content of the resource.
- */
- protected Nullable<String> creator = new Nullable<String>();
-
- /**
- * An explanation of the content of the resource.
- *
- * [Example: Values might include an abstract, table of contents, reference
- * to a graphical representation of content, and a free-text account of the
- * content. end example]
- */
- protected Nullable<String> description = new Nullable<String>();
-
- /**
- * An unambiguous reference to the resource within a given context.
- */
- protected Nullable<String> identifier = new Nullable<String>();
-
- /**
- * A delimited set of keywords to support searching and indexing. This is
- * typically a list of terms that are not available elsewhere in the
- * properties.
- */
- protected Nullable<String> keywords = new Nullable<String>();
-
- /**
- * The language of the intellectual content of the resource.
- *
- * [Note: IETF RFC 3066 provides guidance on encoding to represent
- * languages. end note]
- */
- protected Nullable<String> language = new Nullable<String>();
-
- /**
- * The user who performed the last modification. The identification is
- * environment-specific.
- *
- * [Example: A name, email address, or employee ID. end example] It is
- * recommended that this value be as concise as possible.
- */
- protected Nullable<String> lastModifiedBy = new Nullable<String>();
-
- /**
- * The date and time of the last printing.
- */
- protected Nullable<Date> lastPrinted = new Nullable<Date>();
-
- /**
- * Date on which the resource was changed.
- */
- protected Nullable<Date> modified = new Nullable<Date>();
-
- /**
- * The revision number.
- *
- * [Example: This value might indicate the number of saves or revisions,
- * provided the application updates it after each revision. end example]
- */
- protected Nullable<String> revision = new Nullable<String>();
-
- /**
- * The topic of the content of the resource.
- */
- protected Nullable<String> subject = new Nullable<String>();
-
- /**
- * The name given to the resource.
- */
- protected Nullable<String> title = new Nullable<String>();
-
- /**
- * The version number. This value is set by the user or by the application.
- */
- protected Nullable<String> version = new Nullable<String>();
-
- /*
- * Getters and setters
- */
-
- /**
- * Get the category property.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#getCategoryProperty()
- */
- public Nullable<String> getCategoryProperty() {
- return category;
- }
-
- /**
- * Get content status.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#getContentStatusProperty()
- */
- public Nullable<String> getContentStatusProperty() {
- return contentStatus;
- }
-
- /**
- * Get content type.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#getContentTypeProperty()
- */
- public Nullable<String> getContentTypeProperty() {
- return contentType;
- }
-
- /**
- * Get created date.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#getCreatedProperty()
- */
- public Nullable<Date> getCreatedProperty() {
- return created;
- }
-
- /**
- * Get created date formated into a String.
- *
- * @return A string representation of the created date.
- */
- public String getCreatedPropertyString() {
- return getDateValue(created);
- }
-
- /**
- * Get creator.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#getCreatorProperty()
- */
- public Nullable<String> getCreatorProperty() {
- return creator;
- }
-
- /**
- * Get description.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#getDescriptionProperty()
- */
- public Nullable<String> getDescriptionProperty() {
- return description;
- }
-
- /**
- * Get identifier.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#getIdentifierProperty()
- */
- public Nullable<String> getIdentifierProperty() {
- return identifier;
- }
-
- /**
- * Get keywords.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#getKeywordsProperty()
- */
- public Nullable<String> getKeywordsProperty() {
- return keywords;
- }
-
- /**
- * Get the language.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#getLanguageProperty()
- */
- public Nullable<String> getLanguageProperty() {
- return language;
- }
-
- /**
- * Get the author of last modifications.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#getLastModifiedByProperty()
- */
- public Nullable<String> getLastModifiedByProperty() {
- return lastModifiedBy;
- }
-
- /**
- * Get last printed date.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#getLastPrintedProperty()
- */
- public Nullable<Date> getLastPrintedProperty() {
- return lastPrinted;
- }
-
- /**
- * Get last printed date formated into a String.
- *
- * @return A string representation of the last printed date.
- */
- public String getLastPrintedPropertyString() {
- return getDateValue(created);
- }
-
- /**
- * Get modified date.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#getModifiedProperty()
- */
- public Nullable<Date> getModifiedProperty() {
- return modified;
- }
-
- /**
- * Get modified date formated into a String.
- *
- * @return A string representation of the modified date.
- */
- public String getModifiedPropertyString() {
- if (!modified.hasValue())
- return getDateValue(new Nullable<Date>(new Date()));
- else
- return getDateValue(modified);
- }
-
- /**
- * Get revision.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#getRevisionProperty()
- */
- public Nullable<String> getRevisionProperty() {
- return revision;
- }
-
- /**
- * Get subject.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#getSubjectProperty()
- */
- public Nullable<String> getSubjectProperty() {
- return subject;
- }
-
- /**
- * Get title.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#getTitleProperty()
- */
- public Nullable<String> getTitleProperty() {
- return title;
- }
-
- /**
- * Get version.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#getVersionProperty()
- */
- public Nullable<String> getVersionProperty() {
- return version;
- }
-
- /**
- * Set the category.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#setCategoryProperty(java.lang.String)
- */
- public void setCategoryProperty(String category) {
- this.category = setStringValue(category);
- }
-
- /**
- * Set the content status.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#setContentStatusProperty(java.lang.String)
- */
- public void setContentStatusProperty(String contentStatus) {
- this.contentStatus = setStringValue(contentStatus);
- }
-
- /**
- * Set the content type.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#setContentTypeProperty(java.lang.String)
- */
- public void setContentTypeProperty(String contentType) {
- this.contentType = setStringValue(contentType);
- }
-
- /**
- * Set the created date.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#setCreatedProperty(org.apache.poi.openxml4j.util.Nullable)
- */
- public void setCreatedProperty(String created) {
- try {
- this.created = setDateValue(created);
- } catch (InvalidFormatException e) {
- new IllegalArgumentException("created : "
- + e.getLocalizedMessage());
- }
- }
-
- /**
- * Set the created date.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#setCreatedProperty(org.apache.poi.openxml4j.util.Nullable)
- */
- public void setCreatedProperty(Nullable<Date> created) {
- if (created.hasValue())
- this.created = created;
- }
-
- /**
- * Set the creator.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#setCreatorProperty(java.lang.String)
- */
- public void setCreatorProperty(String creator) {
- this.creator = setStringValue(creator);
- }
-
- /**
- * Set the description.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#setDescriptionProperty(java.lang.String)
- */
- public void setDescriptionProperty(String description) {
- this.description = setStringValue(description);
- }
-
- /**
- * Set identifier.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#setIdentifierProperty(java.lang.String)
- */
- public void setIdentifierProperty(String identifier) {
- this.identifier = setStringValue(identifier);
- }
-
- /**
- * Set keywords.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#setKeywordsProperty(java.lang.String)
- */
- public void setKeywordsProperty(String keywords) {
- this.keywords = setStringValue(keywords);
- }
-
- /**
- * Set language.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#setLanguageProperty(java.lang.String)
- */
- public void setLanguageProperty(String language) {
- this.language = setStringValue(language);
- }
-
- /**
- * Set last modifications author.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#setLastModifiedByProperty(java.lang.String)
- */
- public void setLastModifiedByProperty(String lastModifiedBy) {
- this.lastModifiedBy = setStringValue(lastModifiedBy);
- }
-
- /**
- * Set last printed date.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#setLastPrintedProperty(org.apache.poi.openxml4j.util.Nullable)
- */
- public void setLastPrintedProperty(String lastPrinted) {
- try {
- this.lastPrinted = setDateValue(lastPrinted);
- } catch (InvalidFormatException e) {
- new IllegalArgumentException("lastPrinted : "
- + e.getLocalizedMessage());
- }
- }
-
- /**
- * Set last printed date.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#setLastPrintedProperty(org.apache.poi.openxml4j.util.Nullable)
- */
- public void setLastPrintedProperty(Nullable<Date> lastPrinted) {
- if (lastPrinted.hasValue())
- this.lastPrinted = lastPrinted;
- }
-
- /**
- * Set last modification date.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#setModifiedProperty(org.apache.poi.openxml4j.util.Nullable)
- */
- public void setModifiedProperty(String modified) {
- try {
- this.modified = setDateValue(modified);
- } catch (InvalidFormatException e) {
- new IllegalArgumentException("modified : "
- + e.getLocalizedMessage());
- }
- }
-
- /**
- * Set last modification date.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#setModifiedProperty(org.apache.poi.openxml4j.util.Nullable)
- */
- public void setModifiedProperty(Nullable<Date> modified) {
- if (modified.hasValue())
- this.modified = modified;
- }
-
- /**
- * Set revision.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#setRevisionProperty(java.lang.String)
- */
- public void setRevisionProperty(String revision) {
- this.revision = setStringValue(revision);
- }
-
- /**
- * Set subject.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#setSubjectProperty(java.lang.String)
- */
- public void setSubjectProperty(String subject) {
- this.subject = setStringValue(subject);
- }
-
- /**
- * Set title.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#setTitleProperty(java.lang.String)
- */
- public void setTitleProperty(String title) {
- this.title = setStringValue(title);
- }
-
- /**
- * Set version.
- *
- * @see org.apache.poi.openxml4j.opc.PackageProperties#setVersionProperty(java.lang.String)
- */
- public void setVersionProperty(String version) {
- this.version = setStringValue(version);
- }
-
- /**
- * Convert a strig value into a Nullable<String>
- */
- private Nullable<String> setStringValue(String s) {
- if (s == null || s.equals(""))
- return new Nullable<String>();
- else
- return new Nullable<String>(s);
- }
-
- /**
- * Convert a string value represented a date into a Nullable<Date>.
- *
- * @throws InvalidFormatException
- * Throws if the date format isnot valid.
- */
- private Nullable<Date> setDateValue(String s) throws InvalidFormatException {
- if (s == null || s.equals(""))
- return new Nullable<Date>();
- else {
- SimpleDateFormat df = new SimpleDateFormat(
- "yyyy-MM-dd'T'HH:mm:ss'Z'");
- Date d = df.parse(s, new ParsePosition(0));
- if (d == null)
- throw new InvalidFormatException("Date not well formated");
- return new Nullable<Date>(d);
- }
- }
-
- /**
- * Convert a Nullable<Date> into a String.
- *
- * @param d
- * The Date to convert.
- * @return The formated date or null.
- * @see java.util.SimpleDateFormat
- */
- private String getDateValue(Nullable<Date> d) {
- if (d == null || d.equals(""))
- return "";
- else {
- SimpleDateFormat df = new SimpleDateFormat(
- "yyyy-MM-dd'T'HH:mm:ss'Z'");
- return df.format(d.getValue());
- }
- }
-
- @Override
- protected InputStream getInputStreamImpl() {
- throw new InvalidOperationException("Operation not authorized");
- }
-
- @Override
- protected OutputStream getOutputStreamImpl() {
- throw new InvalidOperationException(
- "Can't use output stream to set properties !");
- }
-
- @Override
- public boolean save(OutputStream zos) throws OpenXML4JException {
- throw new InvalidOperationException("Operation not authorized");
- }
-
- @Override
- public boolean load(InputStream ios) throws InvalidFormatException {
- throw new InvalidOperationException("Operation not authorized");
- }
-
- @Override
- public void close() {
- // Do nothing
- }
-
- @Override
- public void flush() {
- // Do nothing
- }
-}
+/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc.internal; + +import java.io.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<String> category = new Nullable<String>(); + + /** + * The status of the content. + * + * [Example: Values might include "Draft", "Reviewed", and "Final". end + * example] + */ + protected Nullable<String> contentStatus = new Nullable<String>(); + + /** + * The type of content represented, generally defined by a specific use and + * intended audience. + * + * [Example: Values might include "Whitepaper", "Security Bulletin", and + * "Exam". end example] [Note: This property is distinct from MIME content + * types as defined in RFC 2616. end note] + */ + protected Nullable<String> contentType = new Nullable<String>(); + + /** + * Date of creation of the resource. + */ + protected Nullable<Date> created = new Nullable<Date>(); + + /** + * An entity primarily responsible for making the content of the resource. + */ + protected Nullable<String> creator = new Nullable<String>(); + + /** + * An explanation of the content of the resource. + * + * [Example: Values might include an abstract, table of contents, reference + * to a graphical representation of content, and a free-text account of the + * content. end example] + */ + protected Nullable<String> description = new Nullable<String>(); + + /** + * An unambiguous reference to the resource within a given context. + */ + protected Nullable<String> identifier = new Nullable<String>(); + + /** + * A delimited set of keywords to support searching and indexing. This is + * typically a list of terms that are not available elsewhere in the + * properties. + */ + protected Nullable<String> keywords = new Nullable<String>(); + + /** + * The language of the intellectual content of the resource. + * + * [Note: IETF RFC 3066 provides guidance on encoding to represent + * languages. end note] + */ + protected Nullable<String> language = new Nullable<String>(); + + /** + * The user who performed the last modification. The identification is + * environment-specific. + * + * [Example: A name, email address, or employee ID. end example] It is + * recommended that this value be as concise as possible. + */ + protected Nullable<String> lastModifiedBy = new Nullable<String>(); + + /** + * The date and time of the last printing. + */ + protected Nullable<Date> lastPrinted = new Nullable<Date>(); + + /** + * Date on which the resource was changed. + */ + protected Nullable<Date> modified = new Nullable<Date>(); + + /** + * The revision number. + * + * [Example: This value might indicate the number of saves or revisions, + * provided the application updates it after each revision. end example] + */ + protected Nullable<String> revision = new Nullable<String>(); + + /** + * The topic of the content of the resource. + */ + protected Nullable<String> subject = new Nullable<String>(); + + /** + * The name given to the resource. + */ + protected Nullable<String> title = new Nullable<String>(); + + /** + * The version number. This value is set by the user or by the application. + */ + protected Nullable<String> version = new Nullable<String>(); + + /* + * Getters and setters + */ + + /** + * Get the category property. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getCategoryProperty() + */ + public Nullable<String> getCategoryProperty() { + return category; + } + + /** + * Get content status. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getContentStatusProperty() + */ + public Nullable<String> getContentStatusProperty() { + return contentStatus; + } + + /** + * Get content type. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getContentTypeProperty() + */ + public Nullable<String> getContentTypeProperty() { + return contentType; + } + + /** + * Get created date. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getCreatedProperty() + */ + public Nullable<Date> getCreatedProperty() { + return created; + } + + /** + * Get created date formated into a String. + * + * @return A string representation of the created date. + */ + public String getCreatedPropertyString() { + return getDateValue(created); + } + + /** + * Get creator. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getCreatorProperty() + */ + public Nullable<String> getCreatorProperty() { + return creator; + } + + /** + * Get description. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getDescriptionProperty() + */ + public Nullable<String> getDescriptionProperty() { + return description; + } + + /** + * Get identifier. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getIdentifierProperty() + */ + public Nullable<String> getIdentifierProperty() { + return identifier; + } + + /** + * Get keywords. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getKeywordsProperty() + */ + public Nullable<String> getKeywordsProperty() { + return keywords; + } + + /** + * Get the language. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getLanguageProperty() + */ + public Nullable<String> getLanguageProperty() { + return language; + } + + /** + * Get the author of last modifications. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getLastModifiedByProperty() + */ + public Nullable<String> getLastModifiedByProperty() { + return lastModifiedBy; + } + + /** + * Get last printed date. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getLastPrintedProperty() + */ + public Nullable<Date> getLastPrintedProperty() { + return lastPrinted; + } + + /** + * Get last printed date formated into a String. + * + * @return A string representation of the last printed date. + */ + public String getLastPrintedPropertyString() { + return getDateValue(created); + } + + /** + * Get modified date. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getModifiedProperty() + */ + public Nullable<Date> getModifiedProperty() { + return modified; + } + + /** + * Get modified date formated into a String. + * + * @return A string representation of the modified date. + */ + public String getModifiedPropertyString() { + if (!modified.hasValue()) + return getDateValue(new Nullable<Date>(new Date())); + else + return getDateValue(modified); + } + + /** + * Get revision. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getRevisionProperty() + */ + public Nullable<String> getRevisionProperty() { + return revision; + } + + /** + * Get subject. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getSubjectProperty() + */ + public Nullable<String> getSubjectProperty() { + return subject; + } + + /** + * Get title. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getTitleProperty() + */ + public Nullable<String> getTitleProperty() { + return title; + } + + /** + * Get version. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#getVersionProperty() + */ + public Nullable<String> getVersionProperty() { + return version; + } + + /** + * Set the category. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#setCategoryProperty(java.lang.String) + */ + public void setCategoryProperty(String category) { + this.category = setStringValue(category); + } + + /** + * Set the content status. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#setContentStatusProperty(java.lang.String) + */ + public void setContentStatusProperty(String contentStatus) { + this.contentStatus = setStringValue(contentStatus); + } + + /** + * Set the content type. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#setContentTypeProperty(java.lang.String) + */ + public void setContentTypeProperty(String contentType) { + this.contentType = setStringValue(contentType); + } + + /** + * Set the created date. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#setCreatedProperty(org.apache.poi.openxml4j.util.Nullable) + */ + public void setCreatedProperty(String created) { + try { + this.created = setDateValue(created); + } catch (InvalidFormatException e) { + new IllegalArgumentException("created : " + + e.getLocalizedMessage()); + } + } + + /** + * Set the created date. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#setCreatedProperty(org.apache.poi.openxml4j.util.Nullable) + */ + public void setCreatedProperty(Nullable<Date> created) { + if (created.hasValue()) + this.created = created; + } + + /** + * Set the creator. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#setCreatorProperty(java.lang.String) + */ + public void setCreatorProperty(String creator) { + this.creator = setStringValue(creator); + } + + /** + * Set the description. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#setDescriptionProperty(java.lang.String) + */ + public void setDescriptionProperty(String description) { + this.description = setStringValue(description); + } + + /** + * Set identifier. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#setIdentifierProperty(java.lang.String) + */ + public void setIdentifierProperty(String identifier) { + this.identifier = setStringValue(identifier); + } + + /** + * Set keywords. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#setKeywordsProperty(java.lang.String) + */ + public void setKeywordsProperty(String keywords) { + this.keywords = setStringValue(keywords); + } + + /** + * Set language. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#setLanguageProperty(java.lang.String) + */ + public void setLanguageProperty(String language) { + this.language = setStringValue(language); + } + + /** + * Set last modifications author. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#setLastModifiedByProperty(java.lang.String) + */ + public void setLastModifiedByProperty(String lastModifiedBy) { + this.lastModifiedBy = setStringValue(lastModifiedBy); + } + + /** + * Set last printed date. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#setLastPrintedProperty(org.apache.poi.openxml4j.util.Nullable) + */ + public void setLastPrintedProperty(String lastPrinted) { + try { + this.lastPrinted = setDateValue(lastPrinted); + } catch (InvalidFormatException e) { + new IllegalArgumentException("lastPrinted : " + + e.getLocalizedMessage()); + } + } + + /** + * Set last printed date. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#setLastPrintedProperty(org.apache.poi.openxml4j.util.Nullable) + */ + public void setLastPrintedProperty(Nullable<Date> lastPrinted) { + if (lastPrinted.hasValue()) + this.lastPrinted = lastPrinted; + } + + /** + * Set last modification date. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#setModifiedProperty(org.apache.poi.openxml4j.util.Nullable) + */ + public void setModifiedProperty(String modified) { + try { + this.modified = setDateValue(modified); + } catch (InvalidFormatException e) { + new IllegalArgumentException("modified : " + + e.getLocalizedMessage()); + } + } + + /** + * Set last modification date. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#setModifiedProperty(org.apache.poi.openxml4j.util.Nullable) + */ + public void setModifiedProperty(Nullable<Date> modified) { + if (modified.hasValue()) + this.modified = modified; + } + + /** + * Set revision. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#setRevisionProperty(java.lang.String) + */ + public void setRevisionProperty(String revision) { + this.revision = setStringValue(revision); + } + + /** + * Set subject. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#setSubjectProperty(java.lang.String) + */ + public void setSubjectProperty(String subject) { + this.subject = setStringValue(subject); + } + + /** + * Set title. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#setTitleProperty(java.lang.String) + */ + public void setTitleProperty(String title) { + this.title = setStringValue(title); + } + + /** + * Set version. + * + * @see org.apache.poi.openxml4j.opc.PackageProperties#setVersionProperty(java.lang.String) + */ + public void setVersionProperty(String version) { + this.version = setStringValue(version); + } + + /** + * Convert a strig value into a Nullable<String> + */ + private Nullable<String> setStringValue(String s) { + if (s == null || s.equals("")) + return new Nullable<String>(); + else + return new Nullable<String>(s); + } + + /** + * Convert a string value represented a date into a Nullable<Date>. + * + * @throws InvalidFormatException + * Throws if the date format isnot valid. + */ + private Nullable<Date> setDateValue(String s) throws InvalidFormatException { + if (s == null || s.equals("")) + return new Nullable<Date>(); + else { + SimpleDateFormat df = new SimpleDateFormat( + "yyyy-MM-dd'T'HH:mm:ss'Z'"); + Date d = df.parse(s, new ParsePosition(0)); + if (d == null) + throw new InvalidFormatException("Date not well formated"); + return new Nullable<Date>(d); + } + } + + /** + * Convert a Nullable<Date> into a String. + * + * @param d + * The Date to convert. + * @return The formated date or null. + * @see java.util.SimpleDateFormat + */ + private String getDateValue(Nullable<Date> d) { + if (d == null || d.equals("")) + return ""; + else { + SimpleDateFormat df = new SimpleDateFormat( + "yyyy-MM-dd'T'HH:mm:ss'Z'"); + return df.format(d.getValue()); + } + } + + @Override + protected InputStream getInputStreamImpl() { + throw new InvalidOperationException("Operation not authorized"); + } + + @Override + protected OutputStream getOutputStreamImpl() { + throw new InvalidOperationException( + "Can't use output stream to set properties !"); + } + + @Override + public boolean save(OutputStream zos) throws OpenXML4JException { + throw new InvalidOperationException("Operation not authorized"); + } + + @Override + public boolean load(InputStream ios) throws InvalidFormatException { + throw new InvalidOperationException("Operation not authorized"); + } + + @Override + public void close() { + // Do nothing + } + + @Override + public void flush() { + // Do nothing + } +} 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<PackagePart> 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, Iterable<X * * @param pkg the OpenXML4J <code>Package</code> 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<X /** * Create a new SpreadsheetML package and setup the default minimal content */ - protected static Package newPackage() { + protected static OPCPackage newPackage() { try { - Package pkg = Package.create(PackageHelper.createTempFile()); + OPCPackage pkg = OPCPackage.create(PackageHelper.createTempFile()); // Main part PackagePartName corePartName = PackagingURIHelper.createPartName(XSSFRelation.WORKBOOK.getDefaultFileName()); // Create main part relationship diff --git a/src/ooxml/java/org/apache/poi/xwpf/extractor/XWPFWordExtractor.java b/src/ooxml/java/org/apache/poi/xwpf/extractor/XWPFWordExtractor.java index 1e97b129ef..63059653f7 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/extractor/XWPFWordExtractor.java +++ b/src/ooxml/java/org/apache/poi/xwpf/extractor/XWPFWordExtractor.java @@ -21,16 +21,16 @@ import java.util.Iterator; import org.apache.poi.POIXMLDocument; import org.apache.poi.POIXMLTextExtractor; -import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.xwpf.model.XWPFCommentsDecorator; import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy; import org.apache.poi.xwpf.model.XWPFHyperlinkDecorator; import org.apache.poi.xwpf.model.XWPFParagraphDecorator; +import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFTable; 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 Word file @@ -39,7 +39,7 @@ public class XWPFWordExtractor extends POIXMLTextExtractor { private XWPFDocument document; private boolean fetchHyperlinks = false; - public XWPFWordExtractor(Package container) throws XmlException, OpenXML4JException, IOException { + public XWPFWordExtractor(OPCPackage container) throws XmlException, OpenXML4JException, IOException { this(new XWPFDocument(container)); } public XWPFWordExtractor(XWPFDocument document) { diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java index f1921783d8..63ba925f8d 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java @@ -30,7 +30,6 @@ import org.apache.xmlbeans.XmlOptions; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.exceptions.OpenXML4JException; import org.apache.poi.openxml4j.opc.*; -import org.apache.poi.openxml4j.opc.Package; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTComment; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDocument1; @@ -65,7 +64,7 @@ public class XWPFDocument extends POIXMLDocument { /** Handles the joy of different headers/footers for different pages */ private XWPFHeaderFooterPolicy headerFooterPolicy; - public XWPFDocument(Package pkg) throws IOException { + public XWPFDocument(OPCPackage pkg) throws IOException { super(ensureWriteAccess(pkg)); //build a tree of POIXMLDocumentParts, this document being the root @@ -143,9 +142,9 @@ public class XWPFDocument extends POIXMLDocument { /** * Create a new SpreadsheetML package and setup the default minimal content */ - protected static Package newPackage() { + protected static OPCPackage newPackage() { try { - Package pkg = Package.create(PackageHelper.createTempFile()); + OPCPackage pkg = OPCPackage.create(PackageHelper.createTempFile()); // Main part PackagePartName corePartName = PackagingURIHelper.createPartName(XWPFRelation.DOCUMENT.getDefaultFileName()); // Create main part relationship |