You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by fa...@apache.org on 2021/05/22 20:22:17 UTC
svn commit: r1890119 [2/10] - in /poi/trunk/poi-ooxml/src:
main/java/org/apache/poi/ooxml/extractor/
main/java/org/apache/poi/ooxml/util/
main/java/org/apache/poi/openxml4j/exceptions/
main/java/org/apache/poi/openxml4j/opc/ main/java/org/apache/poi/op...
Modified: poi/trunk/poi-ooxml/src/main/java/org/apache/poi/openxml4j/opc/OPCPackage.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi-ooxml/src/main/java/org/apache/poi/openxml4j/opc/OPCPackage.java?rev=1890119&r1=1890118&r2=1890119&view=diff
==============================================================================
--- poi/trunk/poi-ooxml/src/main/java/org/apache/poi/openxml4j/opc/OPCPackage.java (original)
+++ poi/trunk/poi-ooxml/src/main/java/org/apache/poi/openxml4j/opc/OPCPackage.java Sat May 22 20:22:16 2021
@@ -67,115 +67,115 @@ import org.apache.poi.util.NotImplemente
*/
public abstract class OPCPackage implements RelationshipSource, Closeable {
- /**
- * Logger.
- */
+ /**
+ * Logger.
+ */
private static final Logger LOG = LogManager.getLogger(OPCPackage.class);
- /**
- * Default package access.
- */
- protected static final PackageAccess defaultPackageAccess = PackageAccess.READ_WRITE;
-
- /**
- * Package access.
- */
- private final PackageAccess packageAccess;
-
- /**
- * Package parts collection.
- */
- private PackagePartCollection partList;
-
- /**
- * Package relationships.
- */
- protected PackageRelationshipCollection relationships;
-
- /**
- * Part marshallers by content type.
- */
- protected final Map<ContentType, PartMarshaller> partMarshallers = new HashMap<>(5);
-
- /**
- * Default part marshaller.
- */
- protected final PartMarshaller defaultPartMarshaller = new DefaultMarshaller();
-
- /**
- * Part unmarshallers by content type.
- */
- protected final Map<ContentType, PartUnmarshaller> partUnmarshallers = new HashMap<>(2);
-
- /**
- * 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;
-
- /**
- * 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");
- }
- this.packageAccess = access;
-
- final ContentType contentType = newCorePropertiesPart();
- // TODO Delocalize specialized marshallers
- this.partUnmarshallers.put(contentType, new PackagePropertiesUnmarshaller());
- this.partMarshallers.put(contentType, new ZipPackagePropertiesMarshaller());
- }
-
- private static ContentType newCorePropertiesPart() {
- try {
- return new ContentType(ContentTypes.CORE_PROPERTIES_PART);
- } 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. : " +
- e.getMessage(), e
- );
- }
- }
-
- /**
- * 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);
- }
+ /**
+ * Default package access.
+ */
+ protected static final PackageAccess defaultPackageAccess = PackageAccess.READ_WRITE;
+
+ /**
+ * Package access.
+ */
+ private final PackageAccess packageAccess;
+
+ /**
+ * Package parts collection.
+ */
+ private PackagePartCollection partList;
+
+ /**
+ * Package relationships.
+ */
+ protected PackageRelationshipCollection relationships;
+
+ /**
+ * Part marshallers by content type.
+ */
+ protected final Map<ContentType, PartMarshaller> partMarshallers = new HashMap<>(5);
+
+ /**
+ * Default part marshaller.
+ */
+ protected final PartMarshaller defaultPartMarshaller = new DefaultMarshaller();
+
+ /**
+ * Part unmarshallers by content type.
+ */
+ protected final Map<ContentType, PartUnmarshaller> partUnmarshallers = new HashMap<>(2);
+
+ /**
+ * 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;
+
+ /**
+ * 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");
+ }
+ this.packageAccess = access;
+
+ final ContentType contentType = newCorePropertiesPart();
+ // TODO Delocalize specialized marshallers
+ this.partUnmarshallers.put(contentType, new PackagePropertiesUnmarshaller());
+ this.partMarshallers.put(contentType, new ZipPackagePropertiesMarshaller());
+ }
+
+ private static ContentType newCorePropertiesPart() {
+ try {
+ return new ContentType(ContentTypes.CORE_PROPERTIES_PART);
+ } 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. : " +
+ e.getMessage(), e
+ );
+ }
+ }
+
+ /**
+ * 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 with read/write permission.
@@ -211,52 +211,52 @@ public abstract class OPCPackage impleme
// pack.originalPackagePath = file.getAbsolutePath();
return pack;
} catch (InvalidFormatException | RuntimeException e) {
- IOUtils.closeQuietly(pack);
+ IOUtils.closeQuietly(pack);
throw e;
}
}
- /**
- * 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.
- * @throws InvalidOperationException If the zip file cannot be opened.
- * @throws InvalidFormatException if the package is not valid.
- */
- public static OPCPackage open(String path, PackageAccess access)
- throws InvalidFormatException, InvalidOperationException {
- if (path == null || path.trim().isEmpty()) {
- throw new IllegalArgumentException("'path' must be given");
- }
-
- File file = new File(path);
- if (file.exists() && file.isDirectory()) {
- throw new IllegalArgumentException("path must not be a directory");
- }
-
- OPCPackage pack = new ZipPackage(path, access); // NOSONAR
- boolean success = false;
- if (pack.partList == null && access != PackageAccess.WRITE) {
- try {
- pack.getParts();
- success = true;
- } finally {
- if (! success) {
- IOUtils.closeQuietly(pack);
- }
- }
- }
-
- pack.originalPackagePath = new File(path).getAbsolutePath();
- return pack;
- }
+ /**
+ * 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.
+ * @throws InvalidOperationException If the zip file cannot be opened.
+ * @throws InvalidFormatException if the package is not valid.
+ */
+ public static OPCPackage open(String path, PackageAccess access)
+ throws InvalidFormatException, InvalidOperationException {
+ if (path == null || path.trim().isEmpty()) {
+ throw new IllegalArgumentException("'path' must be given");
+ }
+
+ File file = new File(path);
+ if (file.exists() && file.isDirectory()) {
+ throw new IllegalArgumentException("path must not be a directory");
+ }
+
+ OPCPackage pack = new ZipPackage(path, access); // NOSONAR
+ boolean success = false;
+ if (pack.partList == null && access != PackageAccess.WRITE) {
+ try {
+ pack.getParts();
+ success = true;
+ } finally {
+ if (! success) {
+ IOUtils.closeQuietly(pack);
+ }
+ }
+ }
+
+ pack.originalPackagePath = new File(path).getAbsolutePath();
+ return pack;
+ }
/**
* Open a package.
@@ -280,200 +280,200 @@ public abstract class OPCPackage impleme
}
OPCPackage pack = new ZipPackage(file, access);
- try {
- if (pack.partList == null && access != PackageAccess.WRITE) {
- pack.getParts();
- }
- pack.originalPackagePath = file.getAbsolutePath();
- return pack;
- } catch (InvalidFormatException | RuntimeException e) {
- IOUtils.closeQuietly(pack);
- throw e;
- }
+ try {
+ if (pack.partList == null && access != PackageAccess.WRITE) {
+ pack.getParts();
+ }
+ pack.originalPackagePath = file.getAbsolutePath();
+ return pack;
+ } catch (InvalidFormatException | RuntimeException e) {
+ IOUtils.closeQuietly(pack);
+ throw e;
+ }
}
- /**
- * 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
- *
- * @throws InvalidFormatException
- * Throws if the specified file exist and is not valid.
- * @throws IOException If reading the stream fails
- */
- public static OPCPackage open(InputStream in) throws InvalidFormatException,
- IOException {
- OPCPackage pack = new ZipPackage(in, PackageAccess.READ_WRITE);
- try {
- if (pack.partList == null) {
- pack.getParts();
- }
- } catch (InvalidFormatException | RuntimeException e) {
- IOUtils.closeQuietly(pack);
- throw e;
- }
- 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 {
- if (file.exists()) {
- return open(file.getAbsolutePath());
- } else {
- return create(file);
- }
- }
-
- /**
- * 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 = new ZipPackage();
- pkg.originalPackagePath = file.getAbsolutePath();
-
- configurePackage(pkg);
- return pkg;
- }
-
- public static OPCPackage create(OutputStream output) {
- OPCPackage pkg = new ZipPackage();
- pkg.originalPackagePath = null;
- pkg.output = output;
-
- configurePackage(pkg);
- return 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),
- RELATIONSHIPS_PART);
- pkg.contentTypeManager.addContentType(
- PackagingURIHelper.createPartName("/default.xml"),
- PLAIN_OLD_XML);
-
- // Initialise some PackageBase properties
- pkg.packageProperties = new PackagePropertiesPart(pkg,
- PackagingURIHelper.CORE_PROPERTIES_PART_NAME);
- pkg.packageProperties.setCreatorProperty("Generated by Apache POI OpenXML4J");
- pkg.packageProperties.setCreatedProperty(Optional.of(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 open, writable package and save its content.
- *
- * If your package is open read only, then you should call {@link #revert()}
- * when finished with the package.
- *
- * This method is not thread-safe.
- *
- * @throws IOException
- * If an IO exception occur during the saving process.
- */
- @Override
+ /**
+ * 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
+ *
+ * @throws InvalidFormatException
+ * Throws if the specified file exist and is not valid.
+ * @throws IOException If reading the stream fails
+ */
+ public static OPCPackage open(InputStream in) throws InvalidFormatException,
+ IOException {
+ OPCPackage pack = new ZipPackage(in, PackageAccess.READ_WRITE);
+ try {
+ if (pack.partList == null) {
+ pack.getParts();
+ }
+ } catch (InvalidFormatException | RuntimeException e) {
+ IOUtils.closeQuietly(pack);
+ throw e;
+ }
+ 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 {
+ if (file.exists()) {
+ return open(file.getAbsolutePath());
+ } else {
+ return create(file);
+ }
+ }
+
+ /**
+ * 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 = new ZipPackage();
+ pkg.originalPackagePath = file.getAbsolutePath();
+
+ configurePackage(pkg);
+ return pkg;
+ }
+
+ public static OPCPackage create(OutputStream output) {
+ OPCPackage pkg = new ZipPackage();
+ pkg.originalPackagePath = null;
+ pkg.output = output;
+
+ configurePackage(pkg);
+ return 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),
+ RELATIONSHIPS_PART);
+ pkg.contentTypeManager.addContentType(
+ PackagingURIHelper.createPartName("/default.xml"),
+ PLAIN_OLD_XML);
+
+ // Initialise some PackageBase properties
+ pkg.packageProperties = new PackagePropertiesPart(pkg,
+ PackagingURIHelper.CORE_PROPERTIES_PART_NAME);
+ pkg.packageProperties.setCreatorProperty("Generated by Apache POI OpenXML4J");
+ pkg.packageProperties.setCreatedProperty(Optional.of(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 open, writable package and save its content.
+ *
+ * If your package is open read only, then you should call {@link #revert()}
+ * when finished with the package.
+ *
+ * This method is not thread-safe.
+ *
+ * @throws IOException
+ * If an IO exception occur during the saving process.
+ */
+ @Override
public void close() throws IOException {
- if (isClosed()) {
- return;
- }
-
- if (this.packageAccess == PackageAccess.READ) {
- LOG.atWarn().log("The close() method is intended to SAVE a package. This package is open in READ ONLY mode, use the revert() method instead!");
- revert();
- return;
- }
- if (this.contentTypeManager == null) {
- LOG.atWarn().log("Unable to call close() on a package that hasn't been fully opened yet");
- revert();
- return;
- }
-
- if (this.originalPackagePath != null
- && !this.originalPackagePath.trim().isEmpty()) {
- 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);
- output.close();
- }
+ if (isClosed()) {
+ return;
+ }
- // ensure all held resources are freed
+ if (this.packageAccess == PackageAccess.READ) {
+ LOG.atWarn().log("The close() method is intended to SAVE a package. This package is open in READ ONLY mode, use the revert() method instead!");
+ revert();
+ return;
+ }
+ if (this.contentTypeManager == null) {
+ LOG.atWarn().log("Unable to call close() on a package that hasn't been fully opened yet");
+ revert();
+ return;
+ }
+
+ if (this.originalPackagePath != null
+ && !this.originalPackagePath.trim().isEmpty()) {
+ 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);
+ output.close();
+ }
+
+ // ensure all held resources are freed
revert();
- // Clear
- this.contentTypeManager.clearAll();
- }
+ // Clear
+ this.contentTypeManager.clearAll();
+ }
/**
* Close the package WITHOUT saving its content. Reinitialize this package
@@ -497,9 +497,9 @@ public abstract class OPCPackage impleme
}
String name = path.substring(path.lastIndexOf(File.separatorChar) + 1);
- try (FileInputStream is = new FileInputStream(path)) {
- addThumbnail(name, is);
- }
+ try (FileInputStream is = new FileInputStream(path)) {
+ addThumbnail(name, is);
+ }
}
/**
* Add a thumbnail to the package. This method is provided to make easier
@@ -566,792 +566,792 @@ public abstract class OPCPackage impleme
}
}
- /**
- * 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 if a read operation is done on a write only package.
- * @see 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}.
- */
- 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 partList.get(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<>();
- for (PackagePart part : partList.sortedValues()) {
- if (part.getContentType().equals(contentType)) {
- retArr.add(part);
- }
- }
- return retArr;
- }
-
- /**
- * Retrieve parts by relationship type.
- *
- * @param relationshipType
- * Relationship type. Must not be {@code null}.
- * @return All parts which are the target of a relationship with the
- * specified type. If no such parts are found, the list is empty.
- * @throws InvalidOperationException If called on a write-only package.
- * @throws IllegalArgumentException if relationshipType input param is null.
- */
- public ArrayList<PackagePart> getPartsByRelationshipType(
- String relationshipType) {
- if (relationshipType == null) {
- throw new IllegalArgumentException("relationshipType");
- }
- ArrayList<PackagePart> retArr = new ArrayList<>();
- for (PackageRelationship rel : getRelationshipsByType(relationshipType)) {
- PackagePart part = getPart(rel);
- if (part != null) {
- retArr.add(part);
- }
- }
- Collections.sort(retArr);
- return retArr;
- }
-
- /**
- * Retrieve parts by name
- *
- * @param namePattern
- * The pattern for matching the names
- * @return All parts associated to the specified content type, sorted
- * in alphanumerically by the part-name
- */
- public List<PackagePart> getPartsByName(final Pattern namePattern) {
- if (namePattern == null) {
- throw new IllegalArgumentException("name pattern must not be null");
- }
- Matcher matcher = namePattern.matcher("");
- ArrayList<PackagePart> result = new ArrayList<>();
- for (PackagePart part : partList.sortedValues()) {
- PackagePartName partName = part.getPartName();
- if (matcher.reset(partName.getName()).matches()) {
- result.add(part);
- }
- }
- return result;
- }
-
- /**
- * 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.
- *
- * Note - Rule M4.1 states that there may only ever be one Core
- * Properties Part, but Office produced files will sometimes
- * have multiple! As Office ignores all but the first, we relax
- * Compliance with Rule M4.1, and ignore all others silently too.
- *
- * @return All this package's parts.
- * @throws InvalidFormatException if the package is not valid.
- */
- 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 */
-
- // Check rule M4.1 -> A format consumer shall consider more than
- // one core properties relationship for a package to be an error
- // (We just log it and move on, as real files break this!)
- boolean hasCorePropertiesPart = false;
- boolean needCorePropertiesPart = true;
-
- partList = getPartsImpl();
- for (PackagePart part : new ArrayList<>(partList.sortedValues())) {
- part.loadRelationships();
-
- // Check OPC compliance rule M4.1
- if (ContentTypes.CORE_PROPERTIES_PART.equals(part.getContentType())) {
- if (!hasCorePropertiesPart) {
- hasCorePropertiesPart = true;
- } else {
- LOG.atWarn().log("OPC Compliance error [M4.1]: " +
- "there is more than one core properties relationship in the package! " +
- "POI will use only the first, but other software may reject this file.");
- }
- }
-
- 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.remove(part.getPartName());
- partList.put(unmarshallPart._partName, unmarshallPart);
-
- // Core properties case-- use first CoreProperties part we come across
- // and ignore any subsequent ones
- if (unmarshallPart instanceof PackagePropertiesPart &&
- hasCorePropertiesPart &&
- needCorePropertiesPart) {
- this.packageProperties = (PackagePropertiesPart) unmarshallPart;
- needCorePropertiesPart = false;
- }
- } catch (IOException ioe) {
- LOG.atWarn().log("Unmarshall operation : IOException for {}", part._partName);
- } catch (InvalidOperationException invoe) {
- throw new InvalidFormatException(invoe.getMessage(), invoe);
- }
- }
- }
- }
- return new ArrayList<>(partList.sortedValues());
- }
-
- /**
- * 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 PartAlreadyExistsException
- * 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 PartAlreadyExistsException
- * 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)
- */
- PackagePart createPart(PackagePartName partName, String contentType,
- boolean loadRelationships) {
- throwExceptionIfReadOnly();
- if (partName == null) {
- throw new IllegalArgumentException("partName");
- }
-
- if (contentType == null || contentType.isEmpty()) {
- throw new IllegalArgumentException("contentType");
- }
-
- // Check if the specified part name already exists
- if (partList.containsKey(partName)
- && !partList.get(partName).isDeleted()) {
- throw new PartAlreadyExistsException(
- "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.
- // Note - POI will read files with more than one Core Properties, which
- // Office sometimes produces, but is strict on generation
- if (contentType.equals(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);
-
- /* check/create default entries - for bug54803 */
- try {
- PackagePartName ppn = PackagingURIHelper.createPartName("/."+EXTENSION_XML);
- contentTypeManager.addContentType(ppn, PLAIN_OLD_XML);
- ppn = PackagingURIHelper.createPartName("/"+RELATIONSHIP_PART_EXTENSION_NAME);
- contentTypeManager.addContentType(ppn, RELATIONSHIPS_PART);
- } catch (InvalidFormatException e) {
- throw new InvalidOperationException("unable to create default content-type entries.", e);
- }
-
- 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;
- }
- content.writeTo(partOutput);
- } catch (IOException ignored) {
- 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 InvalidOperationException
- * 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}, 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) {
- LOG.atError().log("Part name URI '{}' is not valid! This message is not intended to be displayed!", sourceURI);
- 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) {
- LOG.atWarn().withThrowable(e).log("An exception occurs while deleting part '{}'. Some parts may remain in the package.", partName.getName());
- 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
- */
- @Override
+ /**
+ * 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 if a read operation is done on a write only package.
+ * @see 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}.
+ */
+ 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 partList.get(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<>();
+ for (PackagePart part : partList.sortedValues()) {
+ if (part.getContentType().equals(contentType)) {
+ retArr.add(part);
+ }
+ }
+ return retArr;
+ }
+
+ /**
+ * Retrieve parts by relationship type.
+ *
+ * @param relationshipType
+ * Relationship type. Must not be {@code null}.
+ * @return All parts which are the target of a relationship with the
+ * specified type. If no such parts are found, the list is empty.
+ * @throws InvalidOperationException If called on a write-only package.
+ * @throws IllegalArgumentException if relationshipType input param is null.
+ */
+ public ArrayList<PackagePart> getPartsByRelationshipType(
+ String relationshipType) {
+ if (relationshipType == null) {
+ throw new IllegalArgumentException("relationshipType");
+ }
+ ArrayList<PackagePart> retArr = new ArrayList<>();
+ for (PackageRelationship rel : getRelationshipsByType(relationshipType)) {
+ PackagePart part = getPart(rel);
+ if (part != null) {
+ retArr.add(part);
+ }
+ }
+ Collections.sort(retArr);
+ return retArr;
+ }
+
+ /**
+ * Retrieve parts by name
+ *
+ * @param namePattern
+ * The pattern for matching the names
+ * @return All parts associated to the specified content type, sorted
+ * in alphanumerically by the part-name
+ */
+ public List<PackagePart> getPartsByName(final Pattern namePattern) {
+ if (namePattern == null) {
+ throw new IllegalArgumentException("name pattern must not be null");
+ }
+ Matcher matcher = namePattern.matcher("");
+ ArrayList<PackagePart> result = new ArrayList<>();
+ for (PackagePart part : partList.sortedValues()) {
+ PackagePartName partName = part.getPartName();
+ if (matcher.reset(partName.getName()).matches()) {
+ result.add(part);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * 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.
+ *
+ * Note - Rule M4.1 states that there may only ever be one Core
+ * Properties Part, but Office produced files will sometimes
+ * have multiple! As Office ignores all but the first, we relax
+ * Compliance with Rule M4.1, and ignore all others silently too.
+ *
+ * @return All this package's parts.
+ * @throws InvalidFormatException if the package is not valid.
+ */
+ 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 */
+
+ // Check rule M4.1 -> A format consumer shall consider more than
+ // one core properties relationship for a package to be an error
+ // (We just log it and move on, as real files break this!)
+ boolean hasCorePropertiesPart = false;
+ boolean needCorePropertiesPart = true;
+
+ partList = getPartsImpl();
+ for (PackagePart part : new ArrayList<>(partList.sortedValues())) {
+ part.loadRelationships();
+
+ // Check OPC compliance rule M4.1
+ if (ContentTypes.CORE_PROPERTIES_PART.equals(part.getContentType())) {
+ if (!hasCorePropertiesPart) {
+ hasCorePropertiesPart = true;
+ } else {
+ LOG.atWarn().log("OPC Compliance error [M4.1]: " +
+ "there is more than one core properties relationship in the package! " +
+ "POI will use only the first, but other software may reject this file.");
+ }
+ }
+
+ 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.remove(part.getPartName());
+ partList.put(unmarshallPart._partName, unmarshallPart);
+
+ // Core properties case-- use first CoreProperties part we come across
+ // and ignore any subsequent ones
+ if (unmarshallPart instanceof PackagePropertiesPart &&
+ hasCorePropertiesPart &&
+ needCorePropertiesPart) {
+ this.packageProperties = (PackagePropertiesPart) unmarshallPart;
+ needCorePropertiesPart = false;
+ }
+ } catch (IOException ioe) {
+ LOG.atWarn().log("Unmarshall operation : IOException for {}", part._partName);
+ } catch (InvalidOperationException invoe) {
+ throw new InvalidFormatException(invoe.getMessage(), invoe);
+ }
+ }
+ }
+ }
+ return new ArrayList<>(partList.sortedValues());
+ }
+
+ /**
+ * 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 PartAlreadyExistsException
+ * 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 PartAlreadyExistsException
+ * 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)
+ */
+ PackagePart createPart(PackagePartName partName, String contentType,
+ boolean loadRelationships) {
+ throwExceptionIfReadOnly();
+ if (partName == null) {
+ throw new IllegalArgumentException("partName");
+ }
+
+ if (contentType == null || contentType.isEmpty()) {
+ throw new IllegalArgumentException("contentType");
+ }
+
+ // Check if the specified part name already exists
+ if (partList.containsKey(partName)
+ && !partList.get(partName).isDeleted()) {
+ throw new PartAlreadyExistsException(
+ "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.
+ // Note - POI will read files with more than one Core Properties, which
+ // Office sometimes produces, but is strict on generation
+ if (contentType.equals(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);
+
+ /* check/create default entries - for bug54803 */
+ try {
+ PackagePartName ppn = PackagingURIHelper.createPartName("/."+EXTENSION_XML);
+ contentTypeManager.addContentType(ppn, PLAIN_OLD_XML);
+ ppn = PackagingURIHelper.createPartName("/"+RELATIONSHIP_PART_EXTENSION_NAME);
+ contentTypeManager.addContentType(ppn, RELATIONSHIPS_PART);
+ } catch (InvalidFormatException e) {
+ throw new InvalidOperationException("unable to create default content-type entries.", e);
+ }
+
+ 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;
+ }
+ content.writeTo(partOutput);
+ } catch (IOException ignored) {
+ 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 InvalidOperationException
+ * 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}, 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) {
+ LOG.atError().log("Part name URI '{}' is not valid! This message is not intended to be displayed!", sourceURI);
+ 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) {
+ LOG.atWarn().withThrowable(e).log("An exception occurs while deleting part '{}'. Some parts may remain in the package.", partName.getName());
+ 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
+ */
+ @Override
public PackageRelationship addRelationship(PackagePartName targetPartName,
- TargetMode targetMode, String relationshipType, String relID) {
- /* Check OPC compliance */
+ 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
- */
- @Override
+ // 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
+ */
+ @Override
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
- */
- @Override
+ 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
+ */
+ @Override
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 RelationshipSource#addExternalRelationship(String,
- * String)
- */
- @Override
+ 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 RelationshipSource#addExternalRelationship(String,
+ * String)
+ */
+ @Override
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.
- */
- @Override
+ 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.
+ */
+ @Override
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.
+ if (relationships != null) {
+ relationships.removeRelationship(id);
+ this.isDirty = true;
+ }
+ }
+
+ /**
+ * Retrieves all package relationships.
+ *
+ * @return All package relationships of this package.
* @throws InvalidOperationException if a read operation is done on a write only package.
- * @see #getRelationshipsHelper(String)
- */
- @Override
+ * @see #getRelationshipsHelper(String)
+ */
+ @Override
public PackageRelationshipCollection getRelationships() {
- return getRelationshipsHelper(null);
- }
+ 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.
- */
- @Override
+ /**
+ * Retrieves all relationships with the specified type.
+ *
+ * @param relationshipType
+ * The filter specifying the relationship type.
+ * @return All relationships with the specified relationship type.
+ */
+ @Override
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.
- */
- @Override
+ 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.
+ */
+ @Override
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();
- }
- }
- }
+ if (relationships != null) {
+ relationships.clear();
+ this.isDirty = true;
+ }
+ }
- @Override
+ /**
+ * 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();
+ }
+ }
+ }
+
+ @Override
public PackageRelationship getRelationship(String id) {
- return this.relationships.getRelationshipByID(id);
- }
+ return this.relationships.getRelationshipByID(id);
+ }
- @Override
+ @Override
public boolean hasRelationships() {
- return (relationships.size() > 0);
- }
+ return (relationships.size() > 0);
+ }
- @Override
+ @Override
public boolean isRelationshipExists(PackageRelationship rel) {
for (PackageRelationship r : relationships) {
if (r == rel) {
@@ -1359,201 +1359,201 @@ public abstract class OPCPackage impleme
}
}
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) {
+ LOG.atWarn().log("The specified content type is not valid: '{}'. The marshaller will not be added !", e.getMessage());
+ }
+ }
+
+ /**
+ * 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) {
+ LOG.atWarn().log("The specified content type is not valid: '{}'. The unmarshaller will not be added !", e.getMessage());
+ }
+ }
- /**
- * 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) {
- LOG.atWarn().log("The specified content type is not valid: '{}'. The marshaller will not be added !", e.getMessage());
- }
- }
-
- /**
- * 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) {
- LOG.atWarn().log("The specified content type is not valid: '{}'. The unmarshaller will not be added !", e.getMessage());
- }
- }
-
- /**
- * Remove a marshaller by its content type.
- *
- * @param contentType
- * The content type associated with the marshaller to remove.
- */
- public void removeMarshaller(String contentType) {
- try {
+ /**
+ * Remove a marshaller by its content type.
+ *
+ * @param contentType
+ * The content type associated with the marshaller to remove.
+ */
+ public void removeMarshaller(String contentType) {
+ try {
partMarshallers.remove(new ContentType(contentType));
} catch (InvalidFormatException e) {
throw new RuntimeException(e);
}
- }
+ }
- /**
- * Remove an unmarshaller by its content type.
- *
- * @param contentType
- * The content type associated with the unmarshaller to remove.
- */
- public void removeUnmarshaller(String contentType) {
+ /**
+ * Remove an unmarshaller by its content type.
+ *
+ * @param contentType
+ * The content type associated with the unmarshaller to remove.
+ */
+ public void removeUnmarshaller(String contentType) {
try {
partUnmarshallers.remove(new ContentType(contentType));
} catch (InvalidFormatException e) {
throw new RuntimeException(e);
}
- }
+ }
+
+
+ /* 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>
+ */
+ @NotImplemented
+ 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();
- /* Accesseurs */
+ // You shouldn't save the the same file, do a close instead
+ if(targetFile.exists() &&
+ targetFile.getAbsolutePath().equals(this.originalPackagePath)) {
+ throw new InvalidOperationException(
+ "You can't call save(File) to save to the currently open " +
+ "file. To save to the current file, please just call close()"
+ );
+ }
- /**
- * 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>
- */
- @NotImplemented
- 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();
-
- // You shouldn't save the the same file, do a close instead
- if(targetFile.exists() &&
- targetFile.getAbsolutePath().equals(this.originalPackagePath)) {
- throw new InvalidOperationException(
- "You can't call save(File) to save to the currently open " +
- "file. To save to the current file, please just call close()"
- );
- }
-
- // Do the save
- try (FileOutputStream fos = new FileOutputStream(targetFile)) {
- 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 all parts link to the package.
- *
- * @return A list of the part owned by the package.
- */
- protected abstract PackagePartCollection getPartsImpl()
- throws InvalidFormatException;
+ // Do the save
+ try (FileOutputStream fos = new FileOutputStream(targetFile)) {
+ 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.
+ */
[... 107 lines stripped ...]
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org