From 95a7539c30cec7b75c7df117d732e42598cdc3cc Mon Sep 17 00:00:00 2001 From: Josh Micich Date: Wed, 20 May 2009 08:02:35 +0000 Subject: [PATCH] Changed CRLF to LF in ooxml/java. Minor fixes for compiler warnings and formatting git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@776607 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/org/apache/poi/POIXMLException.java | 138 +- .../java/org/apache/poi/POIXMLFactory.java | 95 +- .../java/org/apache/poi/POIXMLRelation.java | 244 ++-- .../exceptions/InvalidFormatException.java | 53 +- .../exceptions/InvalidOperationException.java | 64 +- .../exceptions/OpenXML4JException.java | 68 +- .../exceptions/OpenXML4JRuntimeException.java | 68 +- .../opc/CertificateEmbeddingOption.java | 65 +- .../poi/openxml4j/opc/CompressionOption.java | 94 +- .../poi/openxml4j/opc/Configuration.java | 86 +- .../poi/openxml4j/opc/ContentTypes.java | 261 ++-- .../poi/openxml4j/opc/EncryptionOption.java | 58 +- .../poi/openxml4j/opc/PackageAccess.java | 66 +- .../poi/openxml4j/opc/PackageNamespaces.java | 104 +- .../openxml4j/opc/PackagePartCollection.java | 162 +-- .../poi/openxml4j/opc/PackagePartName.java | 1015 +++++++------ .../opc/PackageRelationshipTypes.java | 154 +- .../poi/openxml4j/opc/PackagingURIHelper.java | 1244 ++++++++-------- .../poi/openxml4j/opc/StreamHelper.java | 154 +- .../apache/poi/openxml4j/opc/TargetMode.java | 64 +- .../apache/poi/openxml4j/opc/ZipPackage.java | 925 ++++++------ .../openxml4j/opc/internal/ContentType.java | 448 +++--- .../openxml4j/opc/internal/FileHelper.java | 182 +-- .../MemoryPackagePartOutputStream.java | 192 +-- .../opc/internal/PartMarshaller.java | 98 +- .../opc/internal/PartUnmarshaller.java | 100 +- .../poi/openxml4j/opc/internal/ZipHelper.java | 326 ++--- .../marshallers/DefaultMarshaller.java | 90 +- .../PackagePropertiesMarshaller.java | 867 ++++++------ .../ZipPackagePropertiesMarshaller.java | 127 +- .../marshallers/ZipPartMarshaller.java | 384 +++-- .../signature/DigitalCertificatePart.java | 156 +- .../signature/DigitalSignatureOriginPart.java | 56 +- .../PackagePropertiesUnmarshaller.java | 784 ++++++----- .../signature/PackageDigitalSignature.java | 140 +- .../PackageDigitalSignatureManager.java | 44 +- .../apache/poi/openxml4j/util/Nullable.java | 143 +- .../org/apache/poi/xssf/dev/XSSFDump.java | 181 +-- .../org/apache/poi/xssf/dev/XSSFSave.java | 85 +- .../apache/poi/xssf/usermodel/XSSFAnchor.java | 73 +- .../poi/xssf/usermodel/XSSFChildAnchor.java | 163 +-- .../poi/xssf/usermodel/XSSFClientAnchor.java | 439 +++--- .../poi/xssf/usermodel/XSSFConnector.java | 243 ++-- .../poi/xssf/usermodel/XSSFDrawing.java | 495 +++---- .../usermodel/XSSFEvaluationWorkbook.java | 360 ++--- .../poi/xssf/usermodel/XSSFFactory.java | 149 +- .../poi/xssf/usermodel/XSSFPicture.java | 699 ++++----- .../apache/poi/xssf/usermodel/XSSFShape.java | 301 ++-- .../poi/xssf/usermodel/XSSFShapeGroup.java | 371 ++--- .../poi/xssf/usermodel/XSSFSimpleShape.java | 359 ++--- .../poi/xssf/usermodel/XSSFTextBox.java | 64 +- .../usermodel/helpers/XSSFRowShifter.java | 379 ++--- .../apache/poi/xwpf/usermodel/Borders.java | 1252 ++++++++--------- .../xwpf/usermodel/ParagraphAlignment.java | 131 +- .../poi/xwpf/usermodel/XWPFFactory.java | 147 +- .../poi/xwpf/usermodel/XWPFRelation.java | 219 +-- 56 files changed, 7716 insertions(+), 7713 deletions(-) diff --git a/src/ooxml/java/org/apache/poi/POIXMLException.java b/src/ooxml/java/org/apache/poi/POIXMLException.java index 1a4bf7ff1d..0c5ad44a51 100755 --- a/src/ooxml/java/org/apache/poi/POIXMLException.java +++ b/src/ooxml/java/org/apache/poi/POIXMLException.java @@ -1,69 +1,69 @@ -/* ==================================================================== - 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; - -/** - * Indicates a generic OOXML error. - * - * @author Yegor Kozlov - */ -public class POIXMLException extends RuntimeException{ - /** - * Create a new POIXMLException with no - * detail mesage. - */ - public POIXMLException() { - super(); - } - - /** - * Create a new POIXMLException with - * the String specified as an error message. - * - * @param msg The error message for the exception. - */ - public POIXMLException(String msg) { - super(msg); - } - - /** - * Create a new POIXMLException with - * the String specified as an error message and the cause. - * - * @param msg The error message for the exception. - * @param cause the cause (which is saved for later retrieval by the - * {@link #getCause()} method). (A null value is - * permitted, and indicates that the cause is nonexistent or - * unknown.) - */ - public POIXMLException(String msg, Throwable cause) { - super(msg, cause); - } - - /** - * Create a new POIXMLException with - * the specified cause. - * - * @param cause the cause (which is saved for later retrieval by the - * {@link #getCause()} method). (A null value is - * permitted, and indicates that the cause is nonexistent or - * unknown.) - */ - public POIXMLException(Throwable cause) { - super(cause); - } -} +/* ==================================================================== + 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; + +/** + * Indicates a generic OOXML error. + * + * @author Yegor Kozlov + */ +public final class POIXMLException extends RuntimeException{ + /** + * Create a new POIXMLException with no + * detail mesage. + */ + public POIXMLException() { + super(); + } + + /** + * Create a new POIXMLException with + * the String specified as an error message. + * + * @param msg The error message for the exception. + */ + public POIXMLException(String msg) { + super(msg); + } + + /** + * Create a new POIXMLException with + * the String specified as an error message and the cause. + * + * @param msg The error message for the exception. + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A null value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + */ + public POIXMLException(String msg, Throwable cause) { + super(msg, cause); + } + + /** + * Create a new POIXMLException with + * the specified cause. + * + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A null value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + */ + public POIXMLException(Throwable cause) { + super(cause); + } +} diff --git a/src/ooxml/java/org/apache/poi/POIXMLFactory.java b/src/ooxml/java/org/apache/poi/POIXMLFactory.java index f10cf0ca01..d8b3111908 100755 --- a/src/ooxml/java/org/apache/poi/POIXMLFactory.java +++ b/src/ooxml/java/org/apache/poi/POIXMLFactory.java @@ -1,48 +1,47 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi; - -import org.apache.poi.openxml4j.opc.PackageRelationship; -import org.apache.poi.openxml4j.opc.PackagePart; - - -/** - * Defines a factory API that enables sub-classes to create instances of POIXMLDocumentPart - * - * @author Yegor Kozlov - */ -public abstract class POIXMLFactory { - - /** - * Create a POIXMLDocumentPart from existing package part and relation. This method is called - * from {@link POIXMLDocumentPart#read(POIXMLFactory)} when parsing a document - * - * @param rel the package part relationship - * @param part the PackagePart representing the created instance - * @return A new instance of a POIXMLDocumentPart. - */ - public abstract POIXMLDocumentPart createDocumentPart(PackageRelationship rel, PackagePart part); - - /** - * Create a new POIXMLDocumentPart using the supplied descriptor. This method is used when adding new parts - * to a document, for example, when adding a sheet to a workbook, slide to a presentation, etc. - * - * @param descriptor describes the object to create - * @return A new instance of a POIXMLDocumentPart. - */ - public abstract POIXMLDocumentPart newDocumentPart(POIXMLRelation descriptor); -} +/* ==================================================================== + 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 org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.openxml4j.opc.PackagePart; + +/** + * Defines a factory API that enables sub-classes to create instances of POIXMLDocumentPart + * + * @author Yegor Kozlov + */ +public abstract class POIXMLFactory { + + /** + * Create a POIXMLDocumentPart from existing package part and relation. This method is called + * from {@link POIXMLDocumentPart#read(POIXMLFactory)} when parsing a document + * + * @param rel the package part relationship + * @param part the PackagePart representing the created instance + * @return A new instance of a POIXMLDocumentPart. + */ + public abstract POIXMLDocumentPart createDocumentPart(PackageRelationship rel, PackagePart part); + + /** + * Create a new POIXMLDocumentPart using the supplied descriptor. This method is used when adding new parts + * to a document, for example, when adding a sheet to a workbook, slide to a presentation, etc. + * + * @param descriptor describes the object to create + * @return A new instance of a POIXMLDocumentPart. + */ + public abstract POIXMLDocumentPart newDocumentPart(POIXMLRelation descriptor); +} diff --git a/src/ooxml/java/org/apache/poi/POIXMLRelation.java b/src/ooxml/java/org/apache/poi/POIXMLRelation.java index a11c49ca18..e89090960c 100755 --- a/src/ooxml/java/org/apache/poi/POIXMLRelation.java +++ b/src/ooxml/java/org/apache/poi/POIXMLRelation.java @@ -1,122 +1,122 @@ -/* ==================================================================== - 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; - -/** - * Represents a descriptor of a OOXML relation. - * - * @author Yegor Kozlov - */ -public abstract class POIXMLRelation { - - /** - * Describes the content stored in a part. - */ - protected String _type; - - /** - * The kind of connection between a source part and a target part in a package. - */ - protected String _relation; - - /** - * The path component of a pack URI. - */ - protected String _defaultName; - - /** - * Defines what object is used to construct instances of this relationship - */ - private Class _cls; - - /** - * Instantiates a POIXMLRelation. - * - * @param type content type - * @param rel relationship - * @param defaultName default item name - * @param cls defines what object is used to construct instances of this relationship - */ - public POIXMLRelation(String type, String rel, String defaultName, Class cls) { - _type = type; - _relation = rel; - _defaultName = defaultName; - _cls = cls; - } - - /** - * Instantiates a POIXMLRelation. - * - * @param type content type - * @param rel relationship - * @param defaultName default item name - */ - public POIXMLRelation(String type, String rel, String defaultName) { - this(type, rel, defaultName, null); - } - /** - * Return the content type. Content types define a media type, a subtype, and an - * optional set of parameters, as defined in RFC 2616. - * - * @return the content type - */ - public String getContentType() { - return _type; - } - - /** - * Return the relationship, the kind of connection between a source part and a target part in a package. - * Relationships make the connections between parts directly discoverable without looking at the content - * in the parts, and without altering the parts themselves. - * - * @return the relationship - */ - public String getRelation() { - return _relation; - } - - /** - * Return the default part name. Part names are used to refer to a part in the context of a - * package, typically as part of a URI. - * - * @return the default part name - */ - public String getDefaultFileName() { - return _defaultName; - } - - /** - * Returns the filename for the nth one of these, - * eg /xl/comments4.xml - */ - public String getFileName(int index) { - if(_defaultName.indexOf("#") == -1) { - // Generic filename in all cases - return getDefaultFileName(); - } - return _defaultName.replace("#", Integer.toString(index)); - } - - /** - * Return type of the obejct used to construct instances of this relationship - * - * @return the class of the object used to construct instances of this relation - */ - public Class getRelationClass(){ - return _cls; - } -} +/* ==================================================================== + 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; + +/** + * Represents a descriptor of a OOXML relation. + * + * @author Yegor Kozlov + */ +public abstract class POIXMLRelation { + + /** + * Describes the content stored in a part. + */ + protected String _type; + + /** + * The kind of connection between a source part and a target part in a package. + */ + protected String _relation; + + /** + * The path component of a pack URI. + */ + protected String _defaultName; + + /** + * Defines what object is used to construct instances of this relationship + */ + private Class _cls; + + /** + * Instantiates a POIXMLRelation. + * + * @param type content type + * @param rel relationship + * @param defaultName default item name + * @param cls defines what object is used to construct instances of this relationship + */ + public POIXMLRelation(String type, String rel, String defaultName, Class cls) { + _type = type; + _relation = rel; + _defaultName = defaultName; + _cls = cls; + } + + /** + * Instantiates a POIXMLRelation. + * + * @param type content type + * @param rel relationship + * @param defaultName default item name + */ + public POIXMLRelation(String type, String rel, String defaultName) { + this(type, rel, defaultName, null); + } + /** + * Return the content type. Content types define a media type, a subtype, and an + * optional set of parameters, as defined in RFC 2616. + * + * @return the content type + */ + public String getContentType() { + return _type; + } + + /** + * Return the relationship, the kind of connection between a source part and a target part in a package. + * Relationships make the connections between parts directly discoverable without looking at the content + * in the parts, and without altering the parts themselves. + * + * @return the relationship + */ + public String getRelation() { + return _relation; + } + + /** + * Return the default part name. Part names are used to refer to a part in the context of a + * package, typically as part of a URI. + * + * @return the default part name + */ + public String getDefaultFileName() { + return _defaultName; + } + + /** + * Returns the filename for the nth one of these, + * e.g. /xl/comments4.xml + */ + public String getFileName(int index) { + if(_defaultName.indexOf("#") == -1) { + // Generic filename in all cases + return getDefaultFileName(); + } + return _defaultName.replace("#", Integer.toString(index)); + } + + /** + * Return type of the obejct used to construct instances of this relationship + * + * @return the class of the object used to construct instances of this relation + */ + public Class getRelationClass(){ + return _cls; + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/exceptions/InvalidFormatException.java b/src/ooxml/java/org/apache/poi/openxml4j/exceptions/InvalidFormatException.java index 689f8f33db..13ed195c22 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/exceptions/InvalidFormatException.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/exceptions/InvalidFormatException.java @@ -1,27 +1,26 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== - */ - -package org.apache.poi.openxml4j.exceptions; - -@SuppressWarnings("serial") -public class InvalidFormatException extends OpenXML4JException{ - - public InvalidFormatException(String message){ - super(message); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.exceptions; + +@SuppressWarnings("serial") +public final class InvalidFormatException extends OpenXML4JException{ + + public InvalidFormatException(String message){ + super(message); + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/exceptions/InvalidOperationException.java b/src/ooxml/java/org/apache/poi/openxml4j/exceptions/InvalidOperationException.java index 9e45ccf4b3..814edd1179 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/exceptions/InvalidOperationException.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/exceptions/InvalidOperationException.java @@ -1,32 +1,32 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.exceptions; - -/** - * Throw when an invalid operation is done. - * - * @author Julien Chable - * @version 1.0 - */ -@SuppressWarnings("serial") -public class InvalidOperationException extends OpenXML4JRuntimeException{ - - public InvalidOperationException(String message){ - super(message); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.exceptions; + +/** + * Throw when an invalid operation is done. + * + * @author Julien Chable + * @version 1.0 + */ +@SuppressWarnings("serial") +public final class InvalidOperationException extends OpenXML4JRuntimeException{ + + public InvalidOperationException(String message){ + super(message); + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/exceptions/OpenXML4JException.java b/src/ooxml/java/org/apache/poi/openxml4j/exceptions/OpenXML4JException.java index d2fa0e1446..09979d96de 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/exceptions/OpenXML4JException.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/exceptions/OpenXML4JException.java @@ -1,34 +1,34 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.exceptions; - -/** - * Global exception throws when a critical error occurs. (this exception is not - * set as Runtime in order to force user to manage the exception in a - * try/catch). - * - * @author CDubettier, Julien Chable - * @version 1.0 - */ -@SuppressWarnings("serial") -public class OpenXML4JException extends Exception { - - public OpenXML4JException(String msg) { - super(msg); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.exceptions; + +/** + * Global exception throws when a critical error occurs. (this exception is not + * set as Runtime in order to force user to manage the exception in a + * try/catch). + * + * @author CDubettier, Julien Chable + * @version 1.0 + */ +@SuppressWarnings("serial") +public class OpenXML4JException extends Exception { + + public OpenXML4JException(String msg) { + super(msg); + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/exceptions/OpenXML4JRuntimeException.java b/src/ooxml/java/org/apache/poi/openxml4j/exceptions/OpenXML4JRuntimeException.java index c68d85ecbb..7e95153fa6 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/exceptions/OpenXML4JRuntimeException.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/exceptions/OpenXML4JRuntimeException.java @@ -1,34 +1,34 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.exceptions; - -/** - * Global exception throws when a critical error occurs (this exception is - * set as Runtime in order not to force the user to manage the exception in a - * try/catch). - * - * @author Julien Chable - * @version 1.0 - */ -@SuppressWarnings("serial") -public class OpenXML4JRuntimeException extends RuntimeException { - - public OpenXML4JRuntimeException(String msg) { - super(msg); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.exceptions; + +/** + * Global exception throws when a critical error occurs (this exception is + * set as Runtime in order not to force the user to manage the exception in a + * try/catch). + * + * @author Julien Chable + * @version 1.0 + */ +@SuppressWarnings("serial") +public class OpenXML4JRuntimeException extends RuntimeException { + + public OpenXML4JRuntimeException(String msg) { + super(msg); + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/CertificateEmbeddingOption.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/CertificateEmbeddingOption.java index 8b946e6d08..cd7b456941 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/CertificateEmbeddingOption.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/CertificateEmbeddingOption.java @@ -1,33 +1,32 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc; - -/** - * Specifies the location where the X.509 certificate that is used in signing is stored. - * - * @author Julien Chable - * @version 1.0 - */ -public enum CertificateEmbeddingOption { - /** The certificate is embedded in its own PackagePart. */ - IN_CERTIFICATE_PART, - /** The certificate is embedded in the SignaturePart that is created for the signature being added. */ - IN_SIGNATURE_PART, - /** The certificate in not embedded in the package. */ - NOT_EMBEDDED -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc; + +/** + * Specifies the location where the X.509 certificate that is used in signing is stored. + * + * @author Julien Chable + */ +public enum CertificateEmbeddingOption { + /** The certificate is embedded in its own PackagePart. */ + IN_CERTIFICATE_PART, + /** The certificate is embedded in the SignaturePart that is created for the signature being added. */ + IN_SIGNATURE_PART, + /** The certificate in not embedded in the package. */ + NOT_EMBEDDED +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/CompressionOption.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/CompressionOption.java index b6c5b30f7d..583b5c51de 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/CompressionOption.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/CompressionOption.java @@ -1,47 +1,47 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc; - -import java.util.zip.Deflater; - -/** - * Specifies the compression level for content that is stored in a PackagePart. - * - * @author Julien Chable - * @version 1.0 - */ -public enum CompressionOption { - /** Compression is optimized for performance. */ - FAST(Deflater.BEST_SPEED), - /** Compression is optimized for size. */ - MAXIMUM(Deflater.BEST_COMPRESSION), - /** Compression is optimized for a balance between size and performance. */ - NORMAL(Deflater.DEFAULT_COMPRESSION), - /** Compression is turned off. */ - NOT_COMPRESSED(Deflater.NO_COMPRESSION); - - private final int value; - - CompressionOption(int value) { - this.value = value; - } - - public int value() { - return this.value; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc; + +import java.util.zip.Deflater; + +/** + * Specifies the compression level for content that is stored in a PackagePart. + * + * @author Julien Chable + * @version 1.0 + */ +public enum CompressionOption { + /** Compression is optimized for performance. */ + FAST(Deflater.BEST_SPEED), + /** Compression is optimized for size. */ + MAXIMUM(Deflater.BEST_COMPRESSION), + /** Compression is optimized for a balance between size and performance. */ + NORMAL(Deflater.DEFAULT_COMPRESSION), + /** Compression is turned off. */ + NOT_COMPRESSED(Deflater.NO_COMPRESSION); + + private final int value; + + CompressionOption(int value) { + this.value = value; + } + + public int value() { + return this.value; + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/Configuration.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/Configuration.java index 72241b38d9..40141befc8 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/Configuration.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/Configuration.java @@ -1,43 +1,43 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc; - -import java.io.File; - -/** - * Storage class for configuration storage parameters. - * TODO xml syntax checking is no longer done with DOM4j parser -> remove the schema or do it ? - * - * @author CDubettier, Julen Chable - * @version 1.0 - */ -public class Configuration { - // TODO configuration by default. should be clearly stated that it should be - // changed to match installation path - // as schemas dir is needed in runtime - static private String pathForXmlSchema = System.getProperty("user.dir") - + File.separator + "src" + File.separator + "schemas"; - - public static String getPathForXmlSchema() { - return pathForXmlSchema; - } - - public static void setPathForXmlSchema(String pathForXmlSchema) { - Configuration.pathForXmlSchema = pathForXmlSchema; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc; + +import java.io.File; + +/** + * Storage class for configuration storage parameters. + * TODO xml syntax checking is no longer done with DOM4j parser -> remove the schema or do it ? + * + * @author CDubettier, Julen Chable + * @version 1.0 + */ +public final class Configuration { + // TODO configuration by default. should be clearly stated that it should be + // changed to match installation path + // as schemas dir is needed in runtime + static private String pathForXmlSchema = System.getProperty("user.dir") + + File.separator + "src" + File.separator + "schemas"; + + public static String getPathForXmlSchema() { + return pathForXmlSchema; + } + + public static void setPathForXmlSchema(String pathForXmlSchema) { + Configuration.pathForXmlSchema = pathForXmlSchema; + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/ContentTypes.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/ContentTypes.java index 9671d3a67a..3754ce8a9a 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/ContentTypes.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/ContentTypes.java @@ -1,131 +1,130 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc; - -/** - * Open Packaging Convention content types (see Annex F : Standard Namespaces - * and Content Types). - * - * @author CDubettier define some constants, Julien Chable - * @version 0.1 - */ -public class ContentTypes { - - /* - * Open Packaging Convention (Annex F : Standard Namespaces and Content - * Types) - */ - - /** - * Core Properties part. - */ - public static final String CORE_PROPERTIES_PART = "application/vnd.openxmlformats-package.core-properties+xml"; - - /** - * Digital Signature Certificate part. - */ - public static final String DIGITAL_SIGNATURE_CERTIFICATE_PART = "application/vnd.openxmlformats-package.digital-signature-certificate"; - - /** - * Digital Signature Origin part. - */ - public static final String DIGITAL_SIGNATURE_ORIGIN_PART = "application/vnd.openxmlformats-package.digital-signature-origin"; - - /** - * Digital Signature XML Signature part. - */ - public static final String DIGITAL_SIGNATURE_XML_SIGNATURE_PART = "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml"; - - /** - * Relationships part. - */ - public static final String RELATIONSHIPS_PART = "application/vnd.openxmlformats-package.relationships+xml"; - - /** - * Custom XML part. - */ - public static final String CUSTOM_XML_PART = "application/vnd.openxmlformats-officedocument.customXmlProperties+xml"; - - /** - * Plain old xml. Note - OOXML uses application/xml, and not text/xml! - */ - public static final String PLAIN_OLD_XML = "application/xml"; - - public static final String IMAGE_JPEG = "image/jpeg"; - - public static final String EXTENSION_JPG_1 = "jpg"; - - public static final String EXTENSION_JPG_2 = "jpeg"; - - // image/png ISO/IEC 15948:2003 http://www.libpng.org/pub/png/spec/ - public static final String IMAGE_PNG = "image/png"; - - public static final String EXTENSION_PNG = "png"; - - // image/gif http://www.w3.org/Graphics/GIF/spec-gif89a.txt - public static final String IMAGE_GIF = "image/gif"; - - public static final String EXTENSION_GIF = "gif"; - - /** - * TIFF image format. - * - * @see - * http://partners.adobe.com/public/developer/tiff/index.html#spec - */ - public static final String IMAGE_TIFF = "image/tiff"; - - public static final String EXTENSION_TIFF = "tiff"; - - /** - * Pict image format. - * - * @see - * http://developer.apple.com/documentation/mac/QuickDraw/QuickDraw-2.html - */ - public static final String IMAGE_PICT = "image/pict"; - - public static final String EXTENSION_PICT = "tiff"; - - /** - * XML file. - */ - public static final String XML = "text/xml"; - - public static final String EXTENSION_XML = "xml"; - - public static String getContentTypeFromFileExtension(String filename) { - String extension = filename.substring(filename.lastIndexOf(".") + 1) - .toLowerCase(); - if (extension.equals(EXTENSION_JPG_1) - || extension.equals(EXTENSION_JPG_2)) - return IMAGE_JPEG; - else if (extension.equals(EXTENSION_GIF)) - return IMAGE_GIF; - else if (extension.equals(EXTENSION_PICT)) - return IMAGE_PICT; - else if (extension.equals(EXTENSION_PNG)) - return IMAGE_PNG; - else if (extension.equals(EXTENSION_TIFF)) - return IMAGE_TIFF; - else if (extension.equals(EXTENSION_XML)) - return XML; - else - return null; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc; + +/** + * Open Packaging Convention content types (see Annex F : Standard Namespaces + * and Content Types). + * + * @author CDubettier define some constants, Julien Chable + */ +public final class ContentTypes { + + /* + * Open Packaging Convention (Annex F : Standard Namespaces and Content + * Types) + */ + + /** + * Core Properties part. + */ + public static final String CORE_PROPERTIES_PART = "application/vnd.openxmlformats-package.core-properties+xml"; + + /** + * Digital Signature Certificate part. + */ + public static final String DIGITAL_SIGNATURE_CERTIFICATE_PART = "application/vnd.openxmlformats-package.digital-signature-certificate"; + + /** + * Digital Signature Origin part. + */ + public static final String DIGITAL_SIGNATURE_ORIGIN_PART = "application/vnd.openxmlformats-package.digital-signature-origin"; + + /** + * Digital Signature XML Signature part. + */ + public static final String DIGITAL_SIGNATURE_XML_SIGNATURE_PART = "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml"; + + /** + * Relationships part. + */ + public static final String RELATIONSHIPS_PART = "application/vnd.openxmlformats-package.relationships+xml"; + + /** + * Custom XML part. + */ + public static final String CUSTOM_XML_PART = "application/vnd.openxmlformats-officedocument.customXmlProperties+xml"; + + /** + * Plain old xml. Note - OOXML uses application/xml, and not text/xml! + */ + public static final String PLAIN_OLD_XML = "application/xml"; + + public static final String IMAGE_JPEG = "image/jpeg"; + + public static final String EXTENSION_JPG_1 = "jpg"; + + public static final String EXTENSION_JPG_2 = "jpeg"; + + // image/png ISO/IEC 15948:2003 http://www.libpng.org/pub/png/spec/ + public static final String IMAGE_PNG = "image/png"; + + public static final String EXTENSION_PNG = "png"; + + // image/gif http://www.w3.org/Graphics/GIF/spec-gif89a.txt + public static final String IMAGE_GIF = "image/gif"; + + public static final String EXTENSION_GIF = "gif"; + + /** + * TIFF image format. + * + * @see + * http://partners.adobe.com/public/developer/tiff/index.html#spec + */ + public static final String IMAGE_TIFF = "image/tiff"; + + public static final String EXTENSION_TIFF = "tiff"; + + /** + * Pict image format. + * + * @see + * http://developer.apple.com/documentation/mac/QuickDraw/QuickDraw-2.html + */ + public static final String IMAGE_PICT = "image/pict"; + + public static final String EXTENSION_PICT = "tiff"; + + /** + * XML file. + */ + public static final String XML = "text/xml"; + + public static final String EXTENSION_XML = "xml"; + + public static String getContentTypeFromFileExtension(String filename) { + String extension = filename.substring(filename.lastIndexOf(".") + 1) + .toLowerCase(); + if (extension.equals(EXTENSION_JPG_1) + || extension.equals(EXTENSION_JPG_2)) + return IMAGE_JPEG; + else if (extension.equals(EXTENSION_GIF)) + return IMAGE_GIF; + else if (extension.equals(EXTENSION_PICT)) + return IMAGE_PICT; + else if (extension.equals(EXTENSION_PNG)) + return IMAGE_PNG; + else if (extension.equals(EXTENSION_TIFF)) + return IMAGE_TIFF; + else if (extension.equals(EXTENSION_XML)) + return XML; + else + return null; + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/EncryptionOption.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/EncryptionOption.java index 0e15332f32..bc994e0f1c 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/EncryptionOption.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/EncryptionOption.java @@ -1,29 +1,29 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc; - -/** - * Specifies the encryption option for parts in a Package. - * - * @author Julien Chable - * @version 0.1 - */ -public enum EncryptionOption { - /** No encryption. */ - NONE -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc; + +/** + * Specifies the encryption option for parts in a Package. + * + * @author Julien Chable + * @version 0.1 + */ +public enum EncryptionOption { + /** No encryption. */ + NONE +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageAccess.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageAccess.java index a40f4ac436..2568822285 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageAccess.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageAccess.java @@ -1,33 +1,33 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc; - -/** - * Specifies package access. - * - * @author Julien Chable - * @version 1.0 - */ -public enum PackageAccess { - /** Read only. Write not authorized. */ - READ, - /** Write only. Read not authorized. */ - WRITE, - /** Read and Write mode. */ - READ_WRITE -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc; + +/** + * Specifies package access. + * + * @author Julien Chable + * @version 1.0 + */ +public enum PackageAccess { + /** Read only. Write not authorized. */ + READ, + /** Write only. Read not authorized. */ + WRITE, + /** Read and Write mode. */ + READ_WRITE +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageNamespaces.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageNamespaces.java index 5f53781eb8..d1adc519fc 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageNamespaces.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageNamespaces.java @@ -1,52 +1,52 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc; - -/** - * Open Packaging Convention namespaces URI. - * - * @author Julien Chable - * @version 1.0 - */ -public interface PackageNamespaces { - - /** - * Content Types. - */ - public static final String CONTENT_TYPES = "http://schemas.openxmlformats.org/package/2006/content-types"; - - /** - * Core Properties. - */ - public static final String CORE_PROPERTIES = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties"; - - /** - * Digital Signatures. - */ - public static final String DIGITAL_SIGNATURE = "http://schemas.openxmlformats.org/package/2006/digital-signature"; - - /** - * Relationships. - */ - public static final String RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships"; - - /** - * Markup Compatibility. - */ - public static final String MARKUP_COMPATIBILITY = "http://schemas.openxmlformats.org/markup-compatibility/2006"; -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc; + +/** + * Open Packaging Convention namespaces URI. + * + * @author Julien Chable + * @version 1.0 + */ +public interface PackageNamespaces { + + /** + * Content Types. + */ + public static final String CONTENT_TYPES = "http://schemas.openxmlformats.org/package/2006/content-types"; + + /** + * Core Properties. + */ + public static final String CORE_PROPERTIES = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties"; + + /** + * Digital Signatures. + */ + public static final String DIGITAL_SIGNATURE = "http://schemas.openxmlformats.org/package/2006/digital-signature"; + + /** + * Relationships. + */ + public static final String RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships"; + + /** + * Markup Compatibility. + */ + public static final String MARKUP_COMPATIBILITY = "http://schemas.openxmlformats.org/markup-compatibility/2006"; +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackagePartCollection.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackagePartCollection.java index 54021302bf..e4ecbd44b8 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackagePartCollection.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackagePartCollection.java @@ -1,81 +1,81 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc; - -import java.util.ArrayList; -import java.util.TreeMap; - -import org.apache.poi.openxml4j.exceptions.InvalidOperationException; - -/** - * A package part collection. - * - * @author Julien Chable - * @version 0.1 - */ -public final class PackagePartCollection extends - TreeMap { - - private static final long serialVersionUID = 2515031135957635515L; - - /** - * Arraylist use to store this collection part names as string for rule - * M1.11 optimized checking. - */ - private ArrayList registerPartNameStr = new ArrayList(); - - @Override - public Object clone() { - return super.clone(); - } - - /** - * Check rule [M1.11]: a package implementer shall neither create nor - * recognize a part with a part name derived from another part name by - * appending segments to it. - * - * @exception InvalidOperationException - * Throws if you try to add a part with a name derived from - * another part name. - */ - @Override - public PackagePart put(PackagePartName partName, PackagePart part) { - String[] segments = partName.getURI().toASCIIString().split( - PackagingURIHelper.FORWARD_SLASH_STRING); - StringBuffer concatSeg = new StringBuffer(); - for (String seg : segments) { - if (!seg.equals("")) - concatSeg.append(PackagingURIHelper.FORWARD_SLASH_CHAR); - concatSeg.append(seg); - if (this.registerPartNameStr.contains(concatSeg.toString())) { - throw new InvalidOperationException( - "You can't add a part with a part name derived from another part ! [M1.11]"); - } - } - this.registerPartNameStr.add(partName.getName()); - return super.put(partName, part); - } - - @Override - public PackagePart remove(Object key) { - if (key instanceof PackagePartName) { - this.registerPartNameStr.remove(((PackagePartName) key).getName()); - } - return super.remove(key); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc; + +import java.util.ArrayList; +import java.util.TreeMap; + +import org.apache.poi.openxml4j.exceptions.InvalidOperationException; + +/** + * A package part collection. + * + * @author Julien Chable + * @version 0.1 + */ +public final class PackagePartCollection extends + TreeMap { + + private static final long serialVersionUID = 2515031135957635515L; + + /** + * Arraylist use to store this collection part names as string for rule + * M1.11 optimized checking. + */ + private ArrayList registerPartNameStr = new ArrayList(); + + @Override + public Object clone() { + return super.clone(); + } + + /** + * Check rule [M1.11]: a package implementer shall neither create nor + * recognize a part with a part name derived from another part name by + * appending segments to it. + * + * @exception InvalidOperationException + * Throws if you try to add a part with a name derived from + * another part name. + */ + @Override + public PackagePart put(PackagePartName partName, PackagePart part) { + String[] segments = partName.getURI().toASCIIString().split( + PackagingURIHelper.FORWARD_SLASH_STRING); + StringBuffer concatSeg = new StringBuffer(); + for (String seg : segments) { + if (!seg.equals("")) + concatSeg.append(PackagingURIHelper.FORWARD_SLASH_CHAR); + concatSeg.append(seg); + if (this.registerPartNameStr.contains(concatSeg.toString())) { + throw new InvalidOperationException( + "You can't add a part with a part name derived from another part ! [M1.11]"); + } + } + this.registerPartNameStr.add(partName.getName()); + return super.put(partName, part); + } + + @Override + public PackagePart remove(Object key) { + if (key instanceof PackagePartName) { + this.registerPartNameStr.remove(((PackagePartName) key).getName()); + } + return super.remove(key); + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackagePartName.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackagePartName.java index f1cc7fdaad..4b1a8448d9 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackagePartName.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackagePartName.java @@ -1,509 +1,506 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc; - -import java.net.URI; -import java.net.URISyntaxException; - -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException; - -/** - * An immutable Open Packaging Convention compliant part name. - * - * @author Julien Chable - * @version 0.1 - * - * @see http://www.ietf.org/rfc/rfc3986.txt - */ -public final class PackagePartName implements Comparable { - - /** - * Part name stored as an URI. - */ - private URI partNameURI; - - /* - * URI Characters definition (RFC 3986) - */ - - /** - * Reserved characters for sub delimitations. - */ - private static String[] RFC3986_PCHAR_SUB_DELIMS = { "!", "$", "&", "'", - "(", ")", "*", "+", ",", ";", "=" }; - - /** - * Unreserved character (+ ALPHA & DIGIT). - */ - private static String[] RFC3986_PCHAR_UNRESERVED_SUP = { "-", ".", "_", "~" }; - - /** - * Authorized reserved characters for pChar. - */ - private static String[] RFC3986_PCHAR_AUTHORIZED_SUP = { ":", "@" }; - - /** - * Flag to know if this part name is from a relationship part name. - */ - private boolean isRelationship; - - /** - * Constructor. Makes a ValidPartName object from a java.net.URI - * - * @param uri - * The URI to validate and to transform into ValidPartName. - * @param checkConformance - * Flag to specify if the contructor have to validate the OPC - * conformance. Must be always true except for - * special URI like '/' which is needed for internal use by - * OpenXML4J but is not valid. - * @throws InvalidFormatException - * Throw if the specified part name is not conform to Open - * Packaging Convention specifications. - * @see java.net.URI - */ - PackagePartName(URI uri, boolean checkConformance) - throws InvalidFormatException { - if (checkConformance) { - throwExceptionIfInvalidPartUri(uri); - } else { - if (!PackagingURIHelper.PACKAGE_ROOT_URI.equals(uri)) { - throw new OpenXML4JRuntimeException( - "OCP conformance must be check for ALL part name except special cases : ['/']"); - } - } - this.partNameURI = uri; - this.isRelationship = isRelationshipPartURI(this.partNameURI); - } - - /** - * Constructor. Makes a ValidPartName object from a String part name. - * - * @param partName - * Part name to valid and to create. - * @param checkConformance - * Flag to specify if the contructor have to validate the OPC - * conformance. Must be always true except for - * special URI like '/' which is needed for internal use by - * OpenXML4J but is not valid. - * @throws InvalidFormatException - * Throw if the specified part name is not conform to Open - * Packaging Convention specifications. - */ - PackagePartName(String partName, boolean checkConformance) - throws InvalidFormatException { - URI partURI; - try { - partURI = new URI(partName); - } catch (URISyntaxException e) { - throw new IllegalArgumentException( - "partName argmument is not a valid OPC part name !"); - } - - if (checkConformance) { - throwExceptionIfInvalidPartUri(partURI); - } else { - if (!PackagingURIHelper.PACKAGE_ROOT_URI.equals(partURI)) { - throw new OpenXML4JRuntimeException( - "OCP conformance must be check for ALL part name except special cases : ['/']"); - } - } - this.partNameURI = partURI; - this.isRelationship = isRelationshipPartURI(this.partNameURI); - } - - /** - * Check if the specified part name is a relationship part name. - * - * @param partUri - * The URI to check. - * @return true if this part name respect the relationship - * part naming convention else false. - */ - private boolean isRelationshipPartURI(URI partUri) { - if (partUri == null) - throw new IllegalArgumentException("partUri"); - - return partUri.getPath().matches( - "^.*/" + PackagingURIHelper.RELATIONSHIP_PART_SEGMENT_NAME + "/.*\\" - + PackagingURIHelper.RELATIONSHIP_PART_EXTENSION_NAME - + "$"); - } - - /** - * Know if this part name is a relationship part name. - * - * @return true if this part name respect the relationship - * part naming convention else false. - */ - public boolean isRelationshipPartURI() { - return this.isRelationship; - } - - /** - * Throws an exception (of any kind) if the specified part name does not - * follow the Open Packaging Convention specifications naming rules. - * - * @param partUri - * The part name to check. - * @throws Exception - * Throws if the part name is invalid. - */ - private static void throwExceptionIfInvalidPartUri(URI partUri) - throws InvalidFormatException { - if (partUri == null) - throw new IllegalArgumentException("partUri"); - // Check if the part name URI is empty [M1.1] - throwExceptionIfEmptyURI(partUri); - - // Check if the part name URI is absolute - throwExceptionIfAbsoluteUri(partUri); - - // Check if the part name URI starts with a forward slash [M1.4] - throwExceptionIfPartNameNotStartsWithForwardSlashChar(partUri); - - // Check if the part name URI ends with a forward slash [M1.5] - throwExceptionIfPartNameEndsWithForwardSlashChar(partUri); - - // Check if the part name does not have empty segments. [M1.3] - // Check if a segment ends with a dot ('.') character. [M1.9] - throwExceptionIfPartNameHaveInvalidSegments(partUri); - } - - /** - * Throws an exception if the specified URI is empty. [M1.1] - * - * @param partURI - * Part URI to check. - * @throws InvalidFormatException - * If the specified URI is empty. - */ - private static void throwExceptionIfEmptyURI(URI partURI) - throws InvalidFormatException { - if (partURI == null) - throw new IllegalArgumentException("partURI"); - - String uriPath = partURI.getPath(); - if (uriPath.length() == 0 - || ((uriPath.length() == 1) && (uriPath.charAt(0) == PackagingURIHelper.FORWARD_SLASH_CHAR))) - throw new InvalidFormatException( - "A part name shall not be empty [M1.1]: " - + partURI.getPath()); - } - - /** - * Throws an exception if the part name has empty segments. [M1.3] - * - * Throws an exception if a segment any characters other than pchar - * characters. [M1.6] - * - * Throws an exception if a segment contain percent-encoded forward slash - * ('/'), or backward slash ('\') characters. [M1.7] - * - * Throws an exception if a segment contain percent-encoded unreserved - * characters. [M1.8] - * - * Throws an exception if the specified part name's segments end with a dot - * ('.') character. [M1.9] - * - * Throws an exception if a segment doesn't include at least one non-dot - * character. [M1.10] - * - * @param partUri - * The part name to check. - * @throws InvalidFormatException - * if the specified URI contain an empty segments or if one the - * segments contained in the part name, ends with a dot ('.') - * character. - */ - private static void throwExceptionIfPartNameHaveInvalidSegments(URI partUri) - throws InvalidFormatException { - if (partUri == null || "".equals(partUri)) { - throw new IllegalArgumentException("partUri"); - } - - // Split the URI into several part and analyze each - String[] segments = partUri.toASCIIString().split("/"); - if (segments.length <= 1 || !segments[0].equals("")) - throw new InvalidFormatException( - "A part name shall not have empty segments [M1.3]: " - + partUri.getPath()); - - for (int i = 1; i < segments.length; ++i) { - String seg = segments[i]; - if (seg == null || "".equals(seg)) { - throw new InvalidFormatException( - "A part name shall not have empty segments [M1.3]: " - + partUri.getPath()); - } - - if (seg.endsWith(".")) { - throw new InvalidFormatException( - "A segment shall not end with a dot ('.') character [M1.9]: " - + partUri.getPath()); - } - - if ("".equals(seg.replaceAll("\\\\.", ""))) { - // Normally will never been invoked with the previous - // implementation rule [M1.9] - throw new InvalidFormatException( - "A segment shall include at least one non-dot character. [M1.10]: " - + partUri.getPath()); - } - - /* - * Check for rule M1.6, M1.7, M1.8 - */ - checkPCharCompliance(seg); - } - } - - /** - * Throws an exception if a segment any characters other than pchar - * characters. [M1.6] - * - * Throws an exception if a segment contain percent-encoded forward slash - * ('/'), or backward slash ('\') characters. [M1.7] - * - * Throws an exception if a segment contain percent-encoded unreserved - * characters. [M1.8] - * - * @param segment - * The segment to check - */ - private static void checkPCharCompliance(String segment) - throws InvalidFormatException { - boolean errorFlag; - for (int i = 0; i < segment.length(); ++i) { - char c = segment.charAt(i); - errorFlag = true; - - /* Check rule M1.6 */ - - // Check for digit or letter - if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') - || (c >= '0' && c <= '9')) { - errorFlag = false; - } else { - // Check "-", ".", "_", "~" - for (int j = 0; j < RFC3986_PCHAR_UNRESERVED_SUP.length; ++j) { - if (c == RFC3986_PCHAR_UNRESERVED_SUP[j].charAt(0)) { - errorFlag = false; - break; - } - } - - // Check ":", "@" - for (int j = 0; errorFlag - && j < RFC3986_PCHAR_AUTHORIZED_SUP.length; ++j) { - if (c == RFC3986_PCHAR_AUTHORIZED_SUP[j].charAt(0)) { - errorFlag = false; - } - } - - // Check "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "=" - for (int j = 0; errorFlag - && j < RFC3986_PCHAR_SUB_DELIMS.length; ++j) { - if (c == RFC3986_PCHAR_SUB_DELIMS[j].charAt(0)) { - errorFlag = false; - } - } - } - - if (errorFlag && c == '%') { - // We certainly found an encoded character, check for length - // now ( '%' HEXDIGIT HEXDIGIT) - if (((segment.length() - i) < 2)) { - throw new InvalidFormatException("The segment " + segment - + " contain invalid encoded character !"); - } - - // If not percent encoded character error occur then reset the - // flag -> the character is valid - errorFlag = false; - - // Decode the encoded character - char decodedChar = (char) Integer.parseInt(segment.substring( - i + 1, i + 3), 16); - i += 2; - - /* Check rule M1.7 */ - if (decodedChar == '/' || decodedChar == '\\') - throw new InvalidFormatException( - "A segment shall not contain percent-encoded forward slash ('/'), or backward slash ('\') characters. [M1.7]"); - - /* Check rule M1.8 */ - - // Check for unreserved character like define in RFC3986 - if ((decodedChar >= 'A' && decodedChar <= 'Z') - || (decodedChar >= 'a' && decodedChar <= 'z') - || (decodedChar >= '0' && decodedChar <= '9')) - errorFlag = true; - - // Check for unreserved character "-", ".", "_", "~" - for (int j = 0; !errorFlag - && j < RFC3986_PCHAR_UNRESERVED_SUP.length; ++j) { - if (c == RFC3986_PCHAR_UNRESERVED_SUP[j].charAt(0)) { - errorFlag = true; - break; - } - } - if (errorFlag) - throw new InvalidFormatException( - "A segment shall not contain percent-encoded unreserved characters. [M1.8]"); - } - - if (errorFlag) - throw new InvalidFormatException( - "A segment shall not hold any characters other than pchar characters. [M1.6]"); - } - } - - /** - * Throws an exception if the specified part name doesn't start with a - * forward slash character '/'. [M1.4] - * - * @param partUri - * The part name to check. - * @throws InvalidFormatException - * If the specified part name doesn't start with a forward slash - * character '/'. - */ - private static void throwExceptionIfPartNameNotStartsWithForwardSlashChar( - URI partUri) throws InvalidFormatException { - String uriPath = partUri.getPath(); - if (uriPath.length() > 0 - && uriPath.charAt(0) != PackagingURIHelper.FORWARD_SLASH_CHAR) - throw new InvalidFormatException( - "A part name shall start with a forward slash ('/') character [M1.4]: " - + partUri.getPath()); - } - - /** - * Throws an exception if the specified part name ends with a forwar slash - * character '/'. [M1.5] - * - * @param partUri - * The part name to check. - * @throws InvalidFormatException - * If the specified part name ends with a forwar slash character - * '/'. - */ - private static void throwExceptionIfPartNameEndsWithForwardSlashChar( - URI partUri) throws InvalidFormatException { - String uriPath = partUri.getPath(); - if (uriPath.length() > 0 - && uriPath.charAt(uriPath.length() - 1) == PackagingURIHelper.FORWARD_SLASH_CHAR) - throw new InvalidFormatException( - "A part name shall not have a forward slash as the last character [M1.5]: " - + partUri.getPath()); - } - - /** - * Throws an exception if the specified URI is absolute. - * - * @param partUri - * The URI to check. - * @throws InvalidFormatException - * Throws if the specified URI is absolute. - */ - private static void throwExceptionIfAbsoluteUri(URI partUri) - throws InvalidFormatException { - if (partUri.isAbsolute()) - throw new InvalidFormatException("Absolute URI forbidden: " - + partUri); - } - - /** - * Compare two part name following the rule M1.12 : - * - * Part name equivalence is determined by comparing part names as - * case-insensitive ASCII strings. Packages shall not contain equivalent - * part names and package implementers shall neither create nor recognize - * packages with equivalent part names. [M1.12] - */ - public int compareTo(PackagePartName otherPartName) { - if (otherPartName == null) - return -1; - return this.partNameURI.toASCIIString().toLowerCase().compareTo( - otherPartName.partNameURI.toASCIIString().toLowerCase()); - } - - /** - * Retrieves the extension of the part name if any. If there is no extension - * returns an empty String. Example : '/document/content.xml' => 'xml' - * - * @return The extension of the part name. - */ - public String getExtension() { - String fragment = this.partNameURI.getPath(); - if (fragment.length() > 0) { - int i = fragment.lastIndexOf("."); - if (i > -1) - return fragment.substring(i + 1); - } - return ""; - } - - /** - * Get this part name. - * - * @return The name of this part name. - */ - public String getName() { - return this.partNameURI.toASCIIString(); - } - - /** - * Part name equivalence is determined by comparing part names as - * case-insensitive ASCII strings. Packages shall not contain equivalent - * part names and package implementers shall neither create nor recognize - * packages with equivalent part names. [M1.12] - */ - @Override - public boolean equals(Object otherPartName) { - if (otherPartName == null - || !(otherPartName instanceof PackagePartName)) - return false; - return this.partNameURI.toASCIIString().toLowerCase().equals( - ((PackagePartName) otherPartName).partNameURI.toASCIIString() - .toLowerCase()); - } - - @Override - public int hashCode() { - return this.partNameURI.toASCIIString().toLowerCase().hashCode(); - } - - @Override - public String toString() { - return getName(); - } - - /* Getters and setters */ - - /** - * Part name property getter. - * - * @return This part name URI. - */ - public URI getURI() { - return this.partNameURI; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc; + +import java.net.URI; +import java.net.URISyntaxException; + +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException; + +/** + * An immutable Open Packaging Convention compliant part name. + * + * @author Julien Chable + * + * @see http://www.ietf.org/rfc/rfc3986.txt + */ +public final class PackagePartName implements Comparable { + + /** + * Part name stored as an URI. + */ + private URI partNameURI; + + /* + * URI Characters definition (RFC 3986) + */ + + /** + * Reserved characters for sub delimitations. + */ + private static String[] RFC3986_PCHAR_SUB_DELIMS = { "!", "$", "&", "'", + "(", ")", "*", "+", ",", ";", "=" }; + + /** + * Unreserved character (+ ALPHA & DIGIT). + */ + private static String[] RFC3986_PCHAR_UNRESERVED_SUP = { "-", ".", "_", "~" }; + + /** + * Authorized reserved characters for pChar. + */ + private static String[] RFC3986_PCHAR_AUTHORIZED_SUP = { ":", "@" }; + + /** + * Flag to know if this part name is from a relationship part name. + */ + private boolean isRelationship; + + /** + * Constructor. Makes a ValidPartName object from a java.net.URI + * + * @param uri + * The URI to validate and to transform into ValidPartName. + * @param checkConformance + * Flag to specify if the contructor have to validate the OPC + * conformance. Must be always true except for + * special URI like '/' which is needed for internal use by + * OpenXML4J but is not valid. + * @throws InvalidFormatException + * Throw if the specified part name is not conform to Open + * Packaging Convention specifications. + * @see java.net.URI + */ + PackagePartName(URI uri, boolean checkConformance) + throws InvalidFormatException { + if (checkConformance) { + throwExceptionIfInvalidPartUri(uri); + } else { + if (!PackagingURIHelper.PACKAGE_ROOT_URI.equals(uri)) { + throw new OpenXML4JRuntimeException( + "OCP conformance must be check for ALL part name except special cases : ['/']"); + } + } + this.partNameURI = uri; + this.isRelationship = isRelationshipPartURI(this.partNameURI); + } + + /** + * Constructor. Makes a ValidPartName object from a String part name. + * + * @param partName + * Part name to valid and to create. + * @param checkConformance + * Flag to specify if the contructor have to validate the OPC + * conformance. Must be always true except for + * special URI like '/' which is needed for internal use by + * OpenXML4J but is not valid. + * @throws InvalidFormatException + * Throw if the specified part name is not conform to Open + * Packaging Convention specifications. + */ + PackagePartName(String partName, boolean checkConformance) + throws InvalidFormatException { + URI partURI; + try { + partURI = new URI(partName); + } catch (URISyntaxException e) { + throw new IllegalArgumentException( + "partName argmument is not a valid OPC part name !"); + } + + if (checkConformance) { + throwExceptionIfInvalidPartUri(partURI); + } else { + if (!PackagingURIHelper.PACKAGE_ROOT_URI.equals(partURI)) { + throw new OpenXML4JRuntimeException( + "OCP conformance must be check for ALL part name except special cases : ['/']"); + } + } + this.partNameURI = partURI; + this.isRelationship = isRelationshipPartURI(this.partNameURI); + } + + /** + * Check if the specified part name is a relationship part name. + * + * @param partUri + * The URI to check. + * @return true if this part name respect the relationship + * part naming convention else false. + */ + private boolean isRelationshipPartURI(URI partUri) { + if (partUri == null) + throw new IllegalArgumentException("partUri"); + + return partUri.getPath().matches( + "^.*/" + PackagingURIHelper.RELATIONSHIP_PART_SEGMENT_NAME + "/.*\\" + + PackagingURIHelper.RELATIONSHIP_PART_EXTENSION_NAME + + "$"); + } + + /** + * Know if this part name is a relationship part name. + * + * @return true if this part name respect the relationship + * part naming convention else false. + */ + public boolean isRelationshipPartURI() { + return this.isRelationship; + } + + /** + * Throws an exception (of any kind) if the specified part name does not + * follow the Open Packaging Convention specifications naming rules. + * + * @param partUri + * The part name to check. + * @throws Exception + * Throws if the part name is invalid. + */ + private static void throwExceptionIfInvalidPartUri(URI partUri) + throws InvalidFormatException { + if (partUri == null) + throw new IllegalArgumentException("partUri"); + // Check if the part name URI is empty [M1.1] + throwExceptionIfEmptyURI(partUri); + + // Check if the part name URI is absolute + throwExceptionIfAbsoluteUri(partUri); + + // Check if the part name URI starts with a forward slash [M1.4] + throwExceptionIfPartNameNotStartsWithForwardSlashChar(partUri); + + // Check if the part name URI ends with a forward slash [M1.5] + throwExceptionIfPartNameEndsWithForwardSlashChar(partUri); + + // Check if the part name does not have empty segments. [M1.3] + // Check if a segment ends with a dot ('.') character. [M1.9] + throwExceptionIfPartNameHaveInvalidSegments(partUri); + } + + /** + * Throws an exception if the specified URI is empty. [M1.1] + * + * @param partURI + * Part URI to check. + * @throws InvalidFormatException + * If the specified URI is empty. + */ + private static void throwExceptionIfEmptyURI(URI partURI) + throws InvalidFormatException { + if (partURI == null) + throw new IllegalArgumentException("partURI"); + + String uriPath = partURI.getPath(); + if (uriPath.length() == 0 + || ((uriPath.length() == 1) && (uriPath.charAt(0) == PackagingURIHelper.FORWARD_SLASH_CHAR))) + throw new InvalidFormatException( + "A part name shall not be empty [M1.1]: " + + partURI.getPath()); + } + + /** + * Throws an exception if the part name has empty segments. [M1.3] + * + * Throws an exception if a segment any characters other than pchar + * characters. [M1.6] + * + * Throws an exception if a segment contain percent-encoded forward slash + * ('/'), or backward slash ('\') characters. [M1.7] + * + * Throws an exception if a segment contain percent-encoded unreserved + * characters. [M1.8] + * + * Throws an exception if the specified part name's segments end with a dot + * ('.') character. [M1.9] + * + * Throws an exception if a segment doesn't include at least one non-dot + * character. [M1.10] + * + * @param partUri + * The part name to check. + * @throws InvalidFormatException + * if the specified URI contain an empty segments or if one the + * segments contained in the part name, ends with a dot ('.') + * character. + */ + private static void throwExceptionIfPartNameHaveInvalidSegments(URI partUri) + throws InvalidFormatException { + if (partUri == null || "".equals(partUri)) { + throw new IllegalArgumentException("partUri"); + } + + // Split the URI into several part and analyze each + String[] segments = partUri.toASCIIString().split("/"); + if (segments.length <= 1 || !segments[0].equals("")) + throw new InvalidFormatException( + "A part name shall not have empty segments [M1.3]: " + + partUri.getPath()); + + for (int i = 1; i < segments.length; ++i) { + String seg = segments[i]; + if (seg == null || "".equals(seg)) { + throw new InvalidFormatException( + "A part name shall not have empty segments [M1.3]: " + + partUri.getPath()); + } + + if (seg.endsWith(".")) { + throw new InvalidFormatException( + "A segment shall not end with a dot ('.') character [M1.9]: " + + partUri.getPath()); + } + + if ("".equals(seg.replaceAll("\\\\.", ""))) { + // Normally will never been invoked with the previous + // implementation rule [M1.9] + throw new InvalidFormatException( + "A segment shall include at least one non-dot character. [M1.10]: " + + partUri.getPath()); + } + + // Check for rule M1.6, M1.7, M1.8 + checkPCharCompliance(seg); + } + } + + /** + * Throws an exception if a segment any characters other than pchar + * characters. [M1.6] + * + * Throws an exception if a segment contain percent-encoded forward slash + * ('/'), or backward slash ('\') characters. [M1.7] + * + * Throws an exception if a segment contain percent-encoded unreserved + * characters. [M1.8] + * + * @param segment + * The segment to check + */ + private static void checkPCharCompliance(String segment) + throws InvalidFormatException { + boolean errorFlag; + for (int i = 0; i < segment.length(); ++i) { + char c = segment.charAt(i); + errorFlag = true; + + /* Check rule M1.6 */ + + // Check for digit or letter + if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') + || (c >= '0' && c <= '9')) { + errorFlag = false; + } else { + // Check "-", ".", "_", "~" + for (int j = 0; j < RFC3986_PCHAR_UNRESERVED_SUP.length; ++j) { + if (c == RFC3986_PCHAR_UNRESERVED_SUP[j].charAt(0)) { + errorFlag = false; + break; + } + } + + // Check ":", "@" + for (int j = 0; errorFlag + && j < RFC3986_PCHAR_AUTHORIZED_SUP.length; ++j) { + if (c == RFC3986_PCHAR_AUTHORIZED_SUP[j].charAt(0)) { + errorFlag = false; + } + } + + // Check "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "=" + for (int j = 0; errorFlag + && j < RFC3986_PCHAR_SUB_DELIMS.length; ++j) { + if (c == RFC3986_PCHAR_SUB_DELIMS[j].charAt(0)) { + errorFlag = false; + } + } + } + + if (errorFlag && c == '%') { + // We certainly found an encoded character, check for length + // now ( '%' HEXDIGIT HEXDIGIT) + if (((segment.length() - i) < 2)) { + throw new InvalidFormatException("The segment " + segment + + " contain invalid encoded character !"); + } + + // If not percent encoded character error occur then reset the + // flag -> the character is valid + errorFlag = false; + + // Decode the encoded character + char decodedChar = (char) Integer.parseInt(segment.substring( + i + 1, i + 3), 16); + i += 2; + + /* Check rule M1.7 */ + if (decodedChar == '/' || decodedChar == '\\') + throw new InvalidFormatException( + "A segment shall not contain percent-encoded forward slash ('/'), or backward slash ('\') characters. [M1.7]"); + + /* Check rule M1.8 */ + + // Check for unreserved character like define in RFC3986 + if ((decodedChar >= 'A' && decodedChar <= 'Z') + || (decodedChar >= 'a' && decodedChar <= 'z') + || (decodedChar >= '0' && decodedChar <= '9')) + errorFlag = true; + + // Check for unreserved character "-", ".", "_", "~" + for (int j = 0; !errorFlag + && j < RFC3986_PCHAR_UNRESERVED_SUP.length; ++j) { + if (c == RFC3986_PCHAR_UNRESERVED_SUP[j].charAt(0)) { + errorFlag = true; + break; + } + } + if (errorFlag) + throw new InvalidFormatException( + "A segment shall not contain percent-encoded unreserved characters. [M1.8]"); + } + + if (errorFlag) + throw new InvalidFormatException( + "A segment shall not hold any characters other than pchar characters. [M1.6]"); + } + } + + /** + * Throws an exception if the specified part name doesn't start with a + * forward slash character '/'. [M1.4] + * + * @param partUri + * The part name to check. + * @throws InvalidFormatException + * If the specified part name doesn't start with a forward slash + * character '/'. + */ + private static void throwExceptionIfPartNameNotStartsWithForwardSlashChar( + URI partUri) throws InvalidFormatException { + String uriPath = partUri.getPath(); + if (uriPath.length() > 0 + && uriPath.charAt(0) != PackagingURIHelper.FORWARD_SLASH_CHAR) + throw new InvalidFormatException( + "A part name shall start with a forward slash ('/') character [M1.4]: " + + partUri.getPath()); + } + + /** + * Throws an exception if the specified part name ends with a forwar slash + * character '/'. [M1.5] + * + * @param partUri + * The part name to check. + * @throws InvalidFormatException + * If the specified part name ends with a forwar slash character + * '/'. + */ + private static void throwExceptionIfPartNameEndsWithForwardSlashChar( + URI partUri) throws InvalidFormatException { + String uriPath = partUri.getPath(); + if (uriPath.length() > 0 + && uriPath.charAt(uriPath.length() - 1) == PackagingURIHelper.FORWARD_SLASH_CHAR) + throw new InvalidFormatException( + "A part name shall not have a forward slash as the last character [M1.5]: " + + partUri.getPath()); + } + + /** + * Throws an exception if the specified URI is absolute. + * + * @param partUri + * The URI to check. + * @throws InvalidFormatException + * Throws if the specified URI is absolute. + */ + private static void throwExceptionIfAbsoluteUri(URI partUri) + throws InvalidFormatException { + if (partUri.isAbsolute()) + throw new InvalidFormatException("Absolute URI forbidden: " + + partUri); + } + + /** + * Compare two part name following the rule M1.12 : + * + * Part name equivalence is determined by comparing part names as + * case-insensitive ASCII strings. Packages shall not contain equivalent + * part names and package implementers shall neither create nor recognize + * packages with equivalent part names. [M1.12] + */ + public int compareTo(PackagePartName otherPartName) { + if (otherPartName == null) + return -1; + return this.partNameURI.toASCIIString().toLowerCase().compareTo( + otherPartName.partNameURI.toASCIIString().toLowerCase()); + } + + /** + * Retrieves the extension of the part name if any. If there is no extension + * returns an empty String. Example : '/document/content.xml' => 'xml' + * + * @return The extension of the part name. + */ + public String getExtension() { + String fragment = this.partNameURI.getPath(); + if (fragment.length() > 0) { + int i = fragment.lastIndexOf("."); + if (i > -1) + return fragment.substring(i + 1); + } + return ""; + } + + /** + * Get this part name. + * + * @return The name of this part name. + */ + public String getName() { + return this.partNameURI.toASCIIString(); + } + + /** + * Part name equivalence is determined by comparing part names as + * case-insensitive ASCII strings. Packages shall not contain equivalent + * part names and package implementers shall neither create nor recognize + * packages with equivalent part names. [M1.12] + */ + @Override + public boolean equals(Object otherPartName) { + if (otherPartName == null + || !(otherPartName instanceof PackagePartName)) + return false; + return this.partNameURI.toASCIIString().toLowerCase().equals( + ((PackagePartName) otherPartName).partNameURI.toASCIIString() + .toLowerCase()); + } + + @Override + public int hashCode() { + return this.partNameURI.toASCIIString().toLowerCase().hashCode(); + } + + @Override + public String toString() { + return getName(); + } + + /* Getters and setters */ + + /** + * Part name property getter. + * + * @return This part name URI. + */ + public URI getURI() { + return this.partNameURI; + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageRelationshipTypes.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageRelationshipTypes.java index e5ecaacc45..e36c025191 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageRelationshipTypes.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageRelationshipTypes.java @@ -1,77 +1,77 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc; - -/** - * Relationship types. - * - * @author Julien Chable - * @version 0.2 - */ -public interface PackageRelationshipTypes { - - /** - * Core properties relationship type. - */ - String CORE_PROPERTIES = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"; - - /** - * Digital signature relationship type. - */ - String DIGITAL_SIGNATURE = "http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/signature"; - - /** - * Digital signature certificate relationship type. - */ - String DIGITAL_SIGNATURE_CERTIFICATE = "http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/certificate"; - - /** - * Digital signature origin relationship type. - */ - String DIGITAL_SIGNATURE_ORIGIN = "http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin"; - - /** - * Thumbnail relationship type. - */ - String THUMBNAIL = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"; - - /** - * Extended properties relationship type. - */ - String EXTENDED_PROPERTIES = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties"; - - /** - * Core properties relationship type. - */ - String CORE_DOCUMENT = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"; - - /** - * Custom XML relationship type. - */ - String CUSTOM_XML = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml"; - - /** - * Image type. - */ - String IMAGE_PART = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"; - - /** - * Style type. - */ - String STYLE_PART = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"; -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc; + +/** + * Relationship types. + * + * @author Julien Chable + * @version 0.2 + */ +public interface PackageRelationshipTypes { + + /** + * Core properties relationship type. + */ + String CORE_PROPERTIES = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"; + + /** + * Digital signature relationship type. + */ + String DIGITAL_SIGNATURE = "http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/signature"; + + /** + * Digital signature certificate relationship type. + */ + String DIGITAL_SIGNATURE_CERTIFICATE = "http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/certificate"; + + /** + * Digital signature origin relationship type. + */ + String DIGITAL_SIGNATURE_ORIGIN = "http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin"; + + /** + * Thumbnail relationship type. + */ + String THUMBNAIL = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"; + + /** + * Extended properties relationship type. + */ + String EXTENDED_PROPERTIES = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties"; + + /** + * Core properties relationship type. + */ + String CORE_DOCUMENT = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"; + + /** + * Custom XML relationship type. + */ + String CUSTOM_XML = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml"; + + /** + * Image type. + */ + String IMAGE_PART = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"; + + /** + * Style type. + */ + String STYLE_PART = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"; +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackagingURIHelper.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackagingURIHelper.java index 58f6066aad..b53903df92 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackagingURIHelper.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackagingURIHelper.java @@ -1,622 +1,622 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc; - -import java.net.URI; -import java.net.URISyntaxException; - -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.exceptions.InvalidOperationException; - -/** - * Helper for part and pack URI. - * - * @author Julien Chable, CDubet, Kim Ung - * @version 0.1 - */ -public final class PackagingURIHelper { - - /** - * Package root URI. - */ - private static URI packageRootUri; - - /** - * Extension name of a relationship part. - */ - public static final String RELATIONSHIP_PART_EXTENSION_NAME; - - /** - * Segment name of a relationship part. - */ - public static final String RELATIONSHIP_PART_SEGMENT_NAME; - - /** - * Segment name of the package properties folder. - */ - public static final String PACKAGE_PROPERTIES_SEGMENT_NAME; - - /** - * Core package properties art name. - */ - public static final String PACKAGE_CORE_PROPERTIES_NAME; - - /** - * Forward slash URI separator. - */ - public static final char FORWARD_SLASH_CHAR; - - /** - * Forward slash URI separator. - */ - public static final String FORWARD_SLASH_STRING; - - /** - * Package relationships part URI - */ - public static final URI PACKAGE_RELATIONSHIPS_ROOT_URI; - - /** - * Package relationships part name. - */ - public static final PackagePartName PACKAGE_RELATIONSHIPS_ROOT_PART_NAME; - - /** - * Core properties part URI. - */ - public static final URI CORE_PROPERTIES_URI; - - /** - * Core properties partname. - */ - public static final PackagePartName CORE_PROPERTIES_PART_NAME; - - /** - * Root package URI. - */ - public static final URI PACKAGE_ROOT_URI; - - /** - * Root package part name. - */ - public static final PackagePartName PACKAGE_ROOT_PART_NAME; - - /* Static initialization */ - static { - RELATIONSHIP_PART_SEGMENT_NAME = "_rels"; - RELATIONSHIP_PART_EXTENSION_NAME = ".rels"; - FORWARD_SLASH_CHAR = '/'; - FORWARD_SLASH_STRING = "/"; - PACKAGE_PROPERTIES_SEGMENT_NAME = "docProps"; - PACKAGE_CORE_PROPERTIES_NAME = "core.xml"; - - // Make URI - URI uriPACKAGE_ROOT_URI = null; - URI uriPACKAGE_RELATIONSHIPS_ROOT_URI = null; - URI uriPACKAGE_PROPERTIES_URI = null; - try { - uriPACKAGE_ROOT_URI = new URI("/"); - uriPACKAGE_RELATIONSHIPS_ROOT_URI = new URI(FORWARD_SLASH_CHAR - + RELATIONSHIP_PART_SEGMENT_NAME + FORWARD_SLASH_CHAR - + RELATIONSHIP_PART_EXTENSION_NAME); - packageRootUri = new URI("/"); - uriPACKAGE_PROPERTIES_URI = new URI(FORWARD_SLASH_CHAR - + PACKAGE_PROPERTIES_SEGMENT_NAME + FORWARD_SLASH_CHAR - + PACKAGE_CORE_PROPERTIES_NAME); - } catch (URISyntaxException e) { - // Should never happen in production as all data are fixed - } - PACKAGE_ROOT_URI = uriPACKAGE_ROOT_URI; - PACKAGE_RELATIONSHIPS_ROOT_URI = uriPACKAGE_RELATIONSHIPS_ROOT_URI; - CORE_PROPERTIES_URI = uriPACKAGE_PROPERTIES_URI; - - // Make part name from previous URI - PackagePartName tmpPACKAGE_ROOT_PART_NAME = null; - PackagePartName tmpPACKAGE_RELATIONSHIPS_ROOT_PART_NAME = null; - PackagePartName tmpCORE_PROPERTIES_URI = null; - try { - tmpPACKAGE_RELATIONSHIPS_ROOT_PART_NAME = createPartName(PACKAGE_RELATIONSHIPS_ROOT_URI); - tmpCORE_PROPERTIES_URI = createPartName(CORE_PROPERTIES_URI); - tmpPACKAGE_ROOT_PART_NAME = new PackagePartName(PACKAGE_ROOT_URI, - false); - } catch (InvalidFormatException e) { - // Should never happen in production as all data are fixed - } - PACKAGE_RELATIONSHIPS_ROOT_PART_NAME = tmpPACKAGE_RELATIONSHIPS_ROOT_PART_NAME; - CORE_PROPERTIES_PART_NAME = tmpCORE_PROPERTIES_URI; - PACKAGE_ROOT_PART_NAME = tmpPACKAGE_ROOT_PART_NAME; - } - - /** - * Gets the URI for the package root. - * - * @return URI of the package root. - */ - public static URI getPackageRootUri() { - return packageRootUri; - } - - /** - * Know if the specified URI is a relationship part name. - * - * @param partUri - * URI to check. - * @return true if the URI false. - */ - public static boolean isRelationshipPartURI(URI partUri) { - if (partUri == null) - throw new IllegalArgumentException("partUri"); - - return partUri.getPath().matches( - ".*" + RELATIONSHIP_PART_SEGMENT_NAME + ".*" - + RELATIONSHIP_PART_EXTENSION_NAME + "$"); - } - - /** - * Get file name from the specified URI. - */ - public static String getFilename(URI uri) { - if (uri != null) { - String path = uri.getPath(); - int len = path.length(); - int num2 = len; - while (--num2 >= 0) { - char ch1 = path.charAt(num2); - if (ch1 == PackagingURIHelper.FORWARD_SLASH_CHAR) - return path.substring(num2 + 1, len); - } - } - return ""; - } - - /** - * Get the file name without the trailing extension. - */ - public static String getFilenameWithoutExtension(URI uri) { - String filename = getFilename(uri); - int dotIndex = filename.lastIndexOf("."); - if (dotIndex == -1) - return filename; - return filename.substring(0, dotIndex); - } - - /** - * Get the directory path from the specified URI. - */ - public static URI getPath(URI uri) { - if (uri != null) { - String path = uri.getPath(); - int len = path.length(); - int num2 = len; - while (--num2 >= 0) { - char ch1 = path.charAt(num2); - if (ch1 == PackagingURIHelper.FORWARD_SLASH_CHAR) { - try { - return new URI(path.substring(0, num2)); - } catch (URISyntaxException e) { - return null; - } - } - } - } - return null; - } - - /** - * Combine two URIs. - * - * @param prefix the prefix URI - * @param suffix the suffix URI - * - * @return the combined URI - */ - public static URI combine(URI prefix, URI suffix) { - URI retUri = null; - try { - retUri = new URI(combine(prefix.getPath(), suffix.getPath())); - } catch (URISyntaxException e) { - throw new IllegalArgumentException( - "Prefix and suffix can't be combine !"); - } - return retUri; - } - - /** - * Combine a string URI with a prefix and a suffix. - */ - public static String combine(String prefix, String suffix) { - if (!prefix.endsWith("" + FORWARD_SLASH_CHAR) - && !suffix.startsWith("" + FORWARD_SLASH_CHAR)) - return prefix + FORWARD_SLASH_CHAR + suffix; - else if ((!prefix.endsWith("" + FORWARD_SLASH_CHAR) - && suffix.startsWith("" + FORWARD_SLASH_CHAR) || (prefix - .endsWith("" + FORWARD_SLASH_CHAR) && !suffix.startsWith("" - + FORWARD_SLASH_CHAR)))) - return prefix + suffix; - else - return ""; - } - - /** - * Fully relativize the source part URI against the target part URI. - * - * @param sourceURI - * The source part URI. - * @param targetURI - * The target part URI. - * @return A fully relativize part name URI ('word/media/image1.gif', - * '/word/document.xml' => 'media/image1.gif') else - * null. - */ - public static URI relativizeURI(URI sourceURI, URI targetURI) { - StringBuilder retVal = new StringBuilder(); - String[] segmentsSource = sourceURI.getPath().split("/", -1); - String[] segmentsTarget = targetURI.getPath().split("/", -1); - - // If the source URI is empty - if (segmentsSource.length == 0) { - throw new IllegalArgumentException( - "Can't relativize an empty source URI !"); - } - - // If target URI is empty - if (segmentsTarget.length == 0) { - throw new IllegalArgumentException( - "Can't relativize an empty target URI !"); - } - - // If the source is the root, then the relativized - // form must actually be an absolute URI - if(sourceURI.toString().equals("/")) { - return targetURI; - } - - - // Relativize the source URI against the target URI. - // First up, figure out how many steps along we can go - // and still have them be the same - int segmentsTheSame = 0; - for (int i = 0; i < segmentsSource.length && i < segmentsTarget.length; i++) { - if (segmentsSource[i].equals(segmentsTarget[i])) { - // Match so far, good - segmentsTheSame++; - } else { - break; - } - } - - // If we didn't have a good match or at least except a first empty element - if ((segmentsTheSame == 0 || segmentsTheSame == 1) && - segmentsSource[0].equals("") && segmentsTarget[0].equals("")) { - for (int i = 0; i < segmentsSource.length - 2; i++) { - retVal.append("../"); - } - for (int i = 0; i < segmentsTarget.length; i++) { - if (segmentsTarget[i].equals("")) - continue; - retVal.append(segmentsTarget[i]); - if (i != segmentsTarget.length - 1) - retVal.append("/"); - } - - try { - return new URI(retVal.toString()); - } catch (Exception e) { - System.err.println(e); - return null; - } - } - - // Special case for where the two are the same - if (segmentsTheSame == segmentsSource.length - && segmentsTheSame == segmentsTarget.length) { - retVal.append(""); - } else { - // Matched for so long, but no more - - // Do we need to go up a directory or two from - // the source to get here? - // (If it's all the way up, then don't bother!) - if (segmentsTheSame == 1) { - retVal.append("/"); - } else { - for (int j = segmentsTheSame; j < segmentsSource.length - 1; j++) { - retVal.append("../"); - } - } - - // Now go from here on down - for (int j = segmentsTheSame; j < segmentsTarget.length; j++) { - if (retVal.length() > 0 - && retVal.charAt(retVal.length() - 1) != '/') { - retVal.append("/"); - } - retVal.append(segmentsTarget[j]); - } - } - - try { - return new URI(retVal.toString()); - } catch (Exception e) { - System.err.println(e); - return null; - } - } - - /** - * Resolve a source uri against a target. - * - * @param sourcePartUri - * The source URI. - * @param targetUri - * The target URI. - * @return The resolved URI. - */ - public static URI resolvePartUri(URI sourcePartUri, URI targetUri) { - if (sourcePartUri == null || sourcePartUri.isAbsolute()) { - throw new IllegalArgumentException("sourcePartUri invalid - " - + sourcePartUri); - } - - if (targetUri == null || targetUri.isAbsolute()) { - throw new IllegalArgumentException("targetUri invalid - " - + targetUri); - } - - return sourcePartUri.resolve(targetUri); - } - - /** - * Get URI from a string path. - */ - public static URI getURIFromPath(String path) { - URI retUri = null; - try { - retUri = new URI(path); - } catch (URISyntaxException e) { - throw new IllegalArgumentException("path"); - } - return retUri; - } - - /** - * Get the source part URI from a specified relationships part. - * - * @param relationshipPartUri - * The relationship part use to retrieve the source part. - * @return The source part URI from the specified relationships part. - */ - public static URI getSourcePartUriFromRelationshipPartUri( - URI relationshipPartUri) { - if (relationshipPartUri == null) - throw new IllegalArgumentException( - "Must not be null"); - - if (!isRelationshipPartURI(relationshipPartUri)) - throw new IllegalArgumentException( - "Must be a relationship part"); - - if (relationshipPartUri.compareTo(PACKAGE_RELATIONSHIPS_ROOT_URI) == 0) - return PACKAGE_ROOT_URI; - - String filename = relationshipPartUri.getPath(); - String filenameWithoutExtension = getFilenameWithoutExtension(relationshipPartUri); - filename = filename - .substring(0, ((filename.length() - filenameWithoutExtension - .length()) - RELATIONSHIP_PART_EXTENSION_NAME.length())); - filename = filename.substring(0, filename.length() - - RELATIONSHIP_PART_SEGMENT_NAME.length() - 1); - filename = combine(filename, filenameWithoutExtension); - return getURIFromPath(filename); - } - - /** - * Create an OPC compliant part name by throwing an exception if the URI is - * not valid. - * - * @param partUri - * The part name URI to validate. - * @return A valid part name object, else null. - * @throws InvalidFormatException - * Throws if the specified URI is not OPC compliant. - */ - public static PackagePartName createPartName(URI partUri) - throws InvalidFormatException { - if (partUri == null) - throw new IllegalArgumentException("partName"); - - return new PackagePartName(partUri, true); - } - - /** - * Create an OPC compliant part name. - * - * @param partName - * The part name to validate. - * @return The correspondant part name if valid, else null. - * @throws InvalidFormatException - * Throws if the specified part name is not OPC compliant. - * @see #createPartName(URI) - */ - public static PackagePartName createPartName(String partName) - throws InvalidFormatException { - URI partNameURI; - try { - partNameURI = new URI(partName); - } catch (URISyntaxException e) { - throw new InvalidFormatException(e.getMessage()); - } - return createPartName(partNameURI); - } - - /** - * Create an OPC compliant part name by resolving it using a base part. - * - * @param partName - * The part name to validate. - * @param relativePart - * The relative base part. - * @return The correspondant part name if valid, else null. - * @throws InvalidFormatException - * Throws if the specified part name is not OPC compliant. - * @see #createPartName(URI) - */ - public static PackagePartName createPartName(String partName, - PackagePart relativePart) throws InvalidFormatException { - URI newPartNameURI; - try { - newPartNameURI = resolvePartUri( - relativePart.getPartName().getURI(), new URI(partName)); - } catch (URISyntaxException e) { - throw new InvalidFormatException(e.getMessage()); - } - return createPartName(newPartNameURI); - } - - /** - * Create an OPC compliant part name by resolving it using a base part. - * - * @param partName - * The part name URI to validate. - * @param relativePart - * The relative base part. - * @return The correspondant part name if valid, else null. - * @throws InvalidFormatException - * Throws if the specified part name is not OPC compliant. - * @see #createPartName(URI) - */ - public static PackagePartName createPartName(URI partName, - PackagePart relativePart) throws InvalidFormatException { - URI newPartNameURI = resolvePartUri( - relativePart.getPartName().getURI(), partName); - return createPartName(newPartNameURI); - } - - /** - * Validate a part URI by returning a boolean. - * ([M1.1],[M1.3],[M1.4],[M1.5],[M1.6]) - * - * (OPC Specifications 8.1.1 Part names) : - * - * Part Name Syntax - * - * The part name grammar is defined as follows: - * - * part_name = 1*( "/" segment ) - * - * segment = 1*( pchar ) - * - * - * (pchar is defined in RFC 3986) - * - * @param partUri - * The URI to validate. - * @return true if the URI is valid to the OPC Specifications, else - * false - * - * @see #createPartName(URI) - */ - public static boolean isValidPartName(URI partUri) { - if (partUri == null) - throw new IllegalArgumentException("partUri"); - - try { - createPartName(partUri); - return true; - } catch (Exception e) { - return false; - } - } - - /** - * Decode a URI by converting all percent encoded character into a String - * character. - * - * @param uri - * The URI to decode. - * @return The specified URI in a String with converted percent encoded - * characters. - */ - public static String decodeURI(URI uri) { - StringBuffer retVal = new StringBuffer(); - String uriStr = uri.toASCIIString(); - char c; - for (int i = 0; i < uriStr.length(); ++i) { - c = uriStr.charAt(i); - if (c == '%') { - // We certainly found an encoded character, check for length - // now ( '%' HEXDIGIT HEXDIGIT) - if (((uriStr.length() - i) < 2)) { - throw new IllegalArgumentException("The uri " + uriStr - + " contain invalid encoded character !"); - } - - // Decode the encoded character - char decodedChar = (char) Integer.parseInt(uriStr.substring( - i + 1, i + 3), 16); - retVal.append(decodedChar); - i += 2; - continue; - } - retVal.append(c); - } - return retVal.toString(); - } - - /** - * Build a part name where the relationship should be stored ((ex - * /word/document.xml -> /word/_rels/document.xml.rels) - * - * @param partName - * Source part URI - * @return the full path (as URI) of the relation file - * @throws InvalidOperationException - * Throws if the specified URI is a relationshp part. - */ - public static PackagePartName getRelationshipPartName( - PackagePartName partName) { - if (partName == null) - throw new IllegalArgumentException("partName"); - - if (PackagingURIHelper.PACKAGE_ROOT_URI.getPath() == partName.getURI() - .getPath()) - return PackagingURIHelper.PACKAGE_RELATIONSHIPS_ROOT_PART_NAME; - - if (partName.isRelationshipPartURI()) - throw new InvalidOperationException("Can't be a relationship part"); - - String fullPath = partName.getURI().getPath(); - String filename = getFilename(partName.getURI()); - fullPath = fullPath.substring(0, fullPath.length() - filename.length()); - fullPath = combine(fullPath, - PackagingURIHelper.RELATIONSHIP_PART_SEGMENT_NAME); - fullPath = combine(fullPath, filename); - fullPath = fullPath - + PackagingURIHelper.RELATIONSHIP_PART_EXTENSION_NAME; - - PackagePartName retPartName; - try { - retPartName = createPartName(fullPath); - } catch (InvalidFormatException e) { - // Should never happen in production as all data are fixed but in - // case of return null: - return null; - } - return retPartName; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc; + +import java.net.URI; +import java.net.URISyntaxException; + +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.exceptions.InvalidOperationException; + +/** + * Helper for part and pack URI. + * + * @author Julien Chable, CDubet, Kim Ung + * @version 0.1 + */ +public final class PackagingURIHelper { + + /** + * Package root URI. + */ + private static URI packageRootUri; + + /** + * Extension name of a relationship part. + */ + public static final String RELATIONSHIP_PART_EXTENSION_NAME; + + /** + * Segment name of a relationship part. + */ + public static final String RELATIONSHIP_PART_SEGMENT_NAME; + + /** + * Segment name of the package properties folder. + */ + public static final String PACKAGE_PROPERTIES_SEGMENT_NAME; + + /** + * Core package properties art name. + */ + public static final String PACKAGE_CORE_PROPERTIES_NAME; + + /** + * Forward slash URI separator. + */ + public static final char FORWARD_SLASH_CHAR; + + /** + * Forward slash URI separator. + */ + public static final String FORWARD_SLASH_STRING; + + /** + * Package relationships part URI + */ + public static final URI PACKAGE_RELATIONSHIPS_ROOT_URI; + + /** + * Package relationships part name. + */ + public static final PackagePartName PACKAGE_RELATIONSHIPS_ROOT_PART_NAME; + + /** + * Core properties part URI. + */ + public static final URI CORE_PROPERTIES_URI; + + /** + * Core properties partname. + */ + public static final PackagePartName CORE_PROPERTIES_PART_NAME; + + /** + * Root package URI. + */ + public static final URI PACKAGE_ROOT_URI; + + /** + * Root package part name. + */ + public static final PackagePartName PACKAGE_ROOT_PART_NAME; + + /* Static initialization */ + static { + RELATIONSHIP_PART_SEGMENT_NAME = "_rels"; + RELATIONSHIP_PART_EXTENSION_NAME = ".rels"; + FORWARD_SLASH_CHAR = '/'; + FORWARD_SLASH_STRING = "/"; + PACKAGE_PROPERTIES_SEGMENT_NAME = "docProps"; + PACKAGE_CORE_PROPERTIES_NAME = "core.xml"; + + // Make URI + URI uriPACKAGE_ROOT_URI = null; + URI uriPACKAGE_RELATIONSHIPS_ROOT_URI = null; + URI uriPACKAGE_PROPERTIES_URI = null; + try { + uriPACKAGE_ROOT_URI = new URI("/"); + uriPACKAGE_RELATIONSHIPS_ROOT_URI = new URI(FORWARD_SLASH_CHAR + + RELATIONSHIP_PART_SEGMENT_NAME + FORWARD_SLASH_CHAR + + RELATIONSHIP_PART_EXTENSION_NAME); + packageRootUri = new URI("/"); + uriPACKAGE_PROPERTIES_URI = new URI(FORWARD_SLASH_CHAR + + PACKAGE_PROPERTIES_SEGMENT_NAME + FORWARD_SLASH_CHAR + + PACKAGE_CORE_PROPERTIES_NAME); + } catch (URISyntaxException e) { + // Should never happen in production as all data are fixed + } + PACKAGE_ROOT_URI = uriPACKAGE_ROOT_URI; + PACKAGE_RELATIONSHIPS_ROOT_URI = uriPACKAGE_RELATIONSHIPS_ROOT_URI; + CORE_PROPERTIES_URI = uriPACKAGE_PROPERTIES_URI; + + // Make part name from previous URI + PackagePartName tmpPACKAGE_ROOT_PART_NAME = null; + PackagePartName tmpPACKAGE_RELATIONSHIPS_ROOT_PART_NAME = null; + PackagePartName tmpCORE_PROPERTIES_URI = null; + try { + tmpPACKAGE_RELATIONSHIPS_ROOT_PART_NAME = createPartName(PACKAGE_RELATIONSHIPS_ROOT_URI); + tmpCORE_PROPERTIES_URI = createPartName(CORE_PROPERTIES_URI); + tmpPACKAGE_ROOT_PART_NAME = new PackagePartName(PACKAGE_ROOT_URI, + false); + } catch (InvalidFormatException e) { + // Should never happen in production as all data are fixed + } + PACKAGE_RELATIONSHIPS_ROOT_PART_NAME = tmpPACKAGE_RELATIONSHIPS_ROOT_PART_NAME; + CORE_PROPERTIES_PART_NAME = tmpCORE_PROPERTIES_URI; + PACKAGE_ROOT_PART_NAME = tmpPACKAGE_ROOT_PART_NAME; + } + + /** + * Gets the URI for the package root. + * + * @return URI of the package root. + */ + public static URI getPackageRootUri() { + return packageRootUri; + } + + /** + * Know if the specified URI is a relationship part name. + * + * @param partUri + * URI to check. + * @return true if the URI false. + */ + public static boolean isRelationshipPartURI(URI partUri) { + if (partUri == null) + throw new IllegalArgumentException("partUri"); + + return partUri.getPath().matches( + ".*" + RELATIONSHIP_PART_SEGMENT_NAME + ".*" + + RELATIONSHIP_PART_EXTENSION_NAME + "$"); + } + + /** + * Get file name from the specified URI. + */ + public static String getFilename(URI uri) { + if (uri != null) { + String path = uri.getPath(); + int len = path.length(); + int num2 = len; + while (--num2 >= 0) { + char ch1 = path.charAt(num2); + if (ch1 == PackagingURIHelper.FORWARD_SLASH_CHAR) + return path.substring(num2 + 1, len); + } + } + return ""; + } + + /** + * Get the file name without the trailing extension. + */ + public static String getFilenameWithoutExtension(URI uri) { + String filename = getFilename(uri); + int dotIndex = filename.lastIndexOf("."); + if (dotIndex == -1) + return filename; + return filename.substring(0, dotIndex); + } + + /** + * Get the directory path from the specified URI. + */ + public static URI getPath(URI uri) { + if (uri != null) { + String path = uri.getPath(); + int len = path.length(); + int num2 = len; + while (--num2 >= 0) { + char ch1 = path.charAt(num2); + if (ch1 == PackagingURIHelper.FORWARD_SLASH_CHAR) { + try { + return new URI(path.substring(0, num2)); + } catch (URISyntaxException e) { + return null; + } + } + } + } + return null; + } + + /** + * Combine two URIs. + * + * @param prefix the prefix URI + * @param suffix the suffix URI + * + * @return the combined URI + */ + public static URI combine(URI prefix, URI suffix) { + URI retUri = null; + try { + retUri = new URI(combine(prefix.getPath(), suffix.getPath())); + } catch (URISyntaxException e) { + throw new IllegalArgumentException( + "Prefix and suffix can't be combine !"); + } + return retUri; + } + + /** + * Combine a string URI with a prefix and a suffix. + */ + public static String combine(String prefix, String suffix) { + if (!prefix.endsWith("" + FORWARD_SLASH_CHAR) + && !suffix.startsWith("" + FORWARD_SLASH_CHAR)) + return prefix + FORWARD_SLASH_CHAR + suffix; + else if ((!prefix.endsWith("" + FORWARD_SLASH_CHAR) + && suffix.startsWith("" + FORWARD_SLASH_CHAR) || (prefix + .endsWith("" + FORWARD_SLASH_CHAR) && !suffix.startsWith("" + + FORWARD_SLASH_CHAR)))) + return prefix + suffix; + else + return ""; + } + + /** + * Fully relativize the source part URI against the target part URI. + * + * @param sourceURI + * The source part URI. + * @param targetURI + * The target part URI. + * @return A fully relativize part name URI ('word/media/image1.gif', + * '/word/document.xml' => 'media/image1.gif') else + * null. + */ + public static URI relativizeURI(URI sourceURI, URI targetURI) { + StringBuilder retVal = new StringBuilder(); + String[] segmentsSource = sourceURI.getPath().split("/", -1); + String[] segmentsTarget = targetURI.getPath().split("/", -1); + + // If the source URI is empty + if (segmentsSource.length == 0) { + throw new IllegalArgumentException( + "Can't relativize an empty source URI !"); + } + + // If target URI is empty + if (segmentsTarget.length == 0) { + throw new IllegalArgumentException( + "Can't relativize an empty target URI !"); + } + + // If the source is the root, then the relativized + // form must actually be an absolute URI + if(sourceURI.toString().equals("/")) { + return targetURI; + } + + + // Relativize the source URI against the target URI. + // First up, figure out how many steps along we can go + // and still have them be the same + int segmentsTheSame = 0; + for (int i = 0; i < segmentsSource.length && i < segmentsTarget.length; i++) { + if (segmentsSource[i].equals(segmentsTarget[i])) { + // Match so far, good + segmentsTheSame++; + } else { + break; + } + } + + // If we didn't have a good match or at least except a first empty element + if ((segmentsTheSame == 0 || segmentsTheSame == 1) && + segmentsSource[0].equals("") && segmentsTarget[0].equals("")) { + for (int i = 0; i < segmentsSource.length - 2; i++) { + retVal.append("../"); + } + for (int i = 0; i < segmentsTarget.length; i++) { + if (segmentsTarget[i].equals("")) + continue; + retVal.append(segmentsTarget[i]); + if (i != segmentsTarget.length - 1) + retVal.append("/"); + } + + try { + return new URI(retVal.toString()); + } catch (Exception e) { + System.err.println(e); + return null; + } + } + + // Special case for where the two are the same + if (segmentsTheSame == segmentsSource.length + && segmentsTheSame == segmentsTarget.length) { + retVal.append(""); + } else { + // Matched for so long, but no more + + // Do we need to go up a directory or two from + // the source to get here? + // (If it's all the way up, then don't bother!) + if (segmentsTheSame == 1) { + retVal.append("/"); + } else { + for (int j = segmentsTheSame; j < segmentsSource.length - 1; j++) { + retVal.append("../"); + } + } + + // Now go from here on down + for (int j = segmentsTheSame; j < segmentsTarget.length; j++) { + if (retVal.length() > 0 + && retVal.charAt(retVal.length() - 1) != '/') { + retVal.append("/"); + } + retVal.append(segmentsTarget[j]); + } + } + + try { + return new URI(retVal.toString()); + } catch (Exception e) { + System.err.println(e); + return null; + } + } + + /** + * Resolve a source uri against a target. + * + * @param sourcePartUri + * The source URI. + * @param targetUri + * The target URI. + * @return The resolved URI. + */ + public static URI resolvePartUri(URI sourcePartUri, URI targetUri) { + if (sourcePartUri == null || sourcePartUri.isAbsolute()) { + throw new IllegalArgumentException("sourcePartUri invalid - " + + sourcePartUri); + } + + if (targetUri == null || targetUri.isAbsolute()) { + throw new IllegalArgumentException("targetUri invalid - " + + targetUri); + } + + return sourcePartUri.resolve(targetUri); + } + + /** + * Get URI from a string path. + */ + public static URI getURIFromPath(String path) { + URI retUri = null; + try { + retUri = new URI(path); + } catch (URISyntaxException e) { + throw new IllegalArgumentException("path"); + } + return retUri; + } + + /** + * Get the source part URI from a specified relationships part. + * + * @param relationshipPartUri + * The relationship part use to retrieve the source part. + * @return The source part URI from the specified relationships part. + */ + public static URI getSourcePartUriFromRelationshipPartUri( + URI relationshipPartUri) { + if (relationshipPartUri == null) + throw new IllegalArgumentException( + "Must not be null"); + + if (!isRelationshipPartURI(relationshipPartUri)) + throw new IllegalArgumentException( + "Must be a relationship part"); + + if (relationshipPartUri.compareTo(PACKAGE_RELATIONSHIPS_ROOT_URI) == 0) + return PACKAGE_ROOT_URI; + + String filename = relationshipPartUri.getPath(); + String filenameWithoutExtension = getFilenameWithoutExtension(relationshipPartUri); + filename = filename + .substring(0, ((filename.length() - filenameWithoutExtension + .length()) - RELATIONSHIP_PART_EXTENSION_NAME.length())); + filename = filename.substring(0, filename.length() + - RELATIONSHIP_PART_SEGMENT_NAME.length() - 1); + filename = combine(filename, filenameWithoutExtension); + return getURIFromPath(filename); + } + + /** + * Create an OPC compliant part name by throwing an exception if the URI is + * not valid. + * + * @param partUri + * The part name URI to validate. + * @return A valid part name object, else null. + * @throws InvalidFormatException + * Throws if the specified URI is not OPC compliant. + */ + public static PackagePartName createPartName(URI partUri) + throws InvalidFormatException { + if (partUri == null) + throw new IllegalArgumentException("partName"); + + return new PackagePartName(partUri, true); + } + + /** + * Create an OPC compliant part name. + * + * @param partName + * The part name to validate. + * @return The correspondant part name if valid, else null. + * @throws InvalidFormatException + * Throws if the specified part name is not OPC compliant. + * @see #createPartName(URI) + */ + public static PackagePartName createPartName(String partName) + throws InvalidFormatException { + URI partNameURI; + try { + partNameURI = new URI(partName); + } catch (URISyntaxException e) { + throw new InvalidFormatException(e.getMessage()); + } + return createPartName(partNameURI); + } + + /** + * Create an OPC compliant part name by resolving it using a base part. + * + * @param partName + * The part name to validate. + * @param relativePart + * The relative base part. + * @return The correspondant part name if valid, else null. + * @throws InvalidFormatException + * Throws if the specified part name is not OPC compliant. + * @see #createPartName(URI) + */ + public static PackagePartName createPartName(String partName, + PackagePart relativePart) throws InvalidFormatException { + URI newPartNameURI; + try { + newPartNameURI = resolvePartUri( + relativePart.getPartName().getURI(), new URI(partName)); + } catch (URISyntaxException e) { + throw new InvalidFormatException(e.getMessage()); + } + return createPartName(newPartNameURI); + } + + /** + * Create an OPC compliant part name by resolving it using a base part. + * + * @param partName + * The part name URI to validate. + * @param relativePart + * The relative base part. + * @return The correspondant part name if valid, else null. + * @throws InvalidFormatException + * Throws if the specified part name is not OPC compliant. + * @see #createPartName(URI) + */ + public static PackagePartName createPartName(URI partName, + PackagePart relativePart) throws InvalidFormatException { + URI newPartNameURI = resolvePartUri( + relativePart.getPartName().getURI(), partName); + return createPartName(newPartNameURI); + } + + /** + * Validate a part URI by returning a boolean. + * ([M1.1],[M1.3],[M1.4],[M1.5],[M1.6]) + * + * (OPC Specifications 8.1.1 Part names) : + * + * Part Name Syntax + * + * The part name grammar is defined as follows: + * + * part_name = 1*( "/" segment ) + * + * segment = 1*( pchar ) + * + * + * (pchar is defined in RFC 3986) + * + * @param partUri + * The URI to validate. + * @return true if the URI is valid to the OPC Specifications, else + * false + * + * @see #createPartName(URI) + */ + public static boolean isValidPartName(URI partUri) { + if (partUri == null) + throw new IllegalArgumentException("partUri"); + + try { + createPartName(partUri); + return true; + } catch (Exception e) { + return false; + } + } + + /** + * Decode a URI by converting all percent encoded character into a String + * character. + * + * @param uri + * The URI to decode. + * @return The specified URI in a String with converted percent encoded + * characters. + */ + public static String decodeURI(URI uri) { + StringBuffer retVal = new StringBuffer(); + String uriStr = uri.toASCIIString(); + char c; + for (int i = 0; i < uriStr.length(); ++i) { + c = uriStr.charAt(i); + if (c == '%') { + // We certainly found an encoded character, check for length + // now ( '%' HEXDIGIT HEXDIGIT) + if (((uriStr.length() - i) < 2)) { + throw new IllegalArgumentException("The uri " + uriStr + + " contain invalid encoded character !"); + } + + // Decode the encoded character + char decodedChar = (char) Integer.parseInt(uriStr.substring( + i + 1, i + 3), 16); + retVal.append(decodedChar); + i += 2; + continue; + } + retVal.append(c); + } + return retVal.toString(); + } + + /** + * Build a part name where the relationship should be stored ((ex + * /word/document.xml -> /word/_rels/document.xml.rels) + * + * @param partName + * Source part URI + * @return the full path (as URI) of the relation file + * @throws InvalidOperationException + * Throws if the specified URI is a relationshp part. + */ + public static PackagePartName getRelationshipPartName( + PackagePartName partName) { + if (partName == null) + throw new IllegalArgumentException("partName"); + + if (PackagingURIHelper.PACKAGE_ROOT_URI.getPath() == partName.getURI() + .getPath()) + return PackagingURIHelper.PACKAGE_RELATIONSHIPS_ROOT_PART_NAME; + + if (partName.isRelationshipPartURI()) + throw new InvalidOperationException("Can't be a relationship part"); + + String fullPath = partName.getURI().getPath(); + String filename = getFilename(partName.getURI()); + fullPath = fullPath.substring(0, fullPath.length() - filename.length()); + fullPath = combine(fullPath, + PackagingURIHelper.RELATIONSHIP_PART_SEGMENT_NAME); + fullPath = combine(fullPath, filename); + fullPath = fullPath + + PackagingURIHelper.RELATIONSHIP_PART_EXTENSION_NAME; + + PackagePartName retPartName; + try { + retPartName = createPartName(fullPath); + } catch (InvalidFormatException e) { + // Should never happen in production as all data are fixed but in + // case of return null: + return null; + } + return retPartName; + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/StreamHelper.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/StreamHelper.java index 1d55c7bb7f..a02264ea68 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/StreamHelper.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/StreamHelper.java @@ -1,77 +1,77 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc; - -import java.io.InputStream; -import java.io.OutputStream; - -import org.dom4j.Document; -import org.dom4j.io.OutputFormat; -import org.dom4j.io.XMLWriter; - -public final class StreamHelper { - - private StreamHelper() { - // Do nothing - } - - /** - * Turning the DOM4j object in the specified output stream. - * - * @param xmlContent - * The XML document. - * @param outStream - * The OutputStream in which the XML document will be written. - * @return true if the xml is successfully written in the stream, - * else false. - */ - public static boolean saveXmlInStream(Document xmlContent, - OutputStream outStream) { - try { - OutputFormat outformat = OutputFormat.createPrettyPrint(); - outformat.setEncoding("UTF-8"); - XMLWriter writer = new XMLWriter(outStream, outformat); - writer.write(xmlContent); - } catch (Exception e) { - return false; - } - return true; - } - - /** - * Copy the input stream into the output stream. - * - * @param inStream - * The source stream. - * @param outStream - * The destination stream. - * @return true if the operation succeed, else return false. - */ - public static boolean copyStream(InputStream inStream, OutputStream outStream) { - try { - byte[] buffer = new byte[1024]; - int bytesRead; - while ((bytesRead = inStream.read(buffer)) >= 0) { - outStream.write(buffer, 0, bytesRead); - } - } catch (Exception e) { - return false; - } - return true; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc; + +import java.io.InputStream; +import java.io.OutputStream; + +import org.dom4j.Document; +import org.dom4j.io.OutputFormat; +import org.dom4j.io.XMLWriter; + +public final class StreamHelper { + + private StreamHelper() { + // Do nothing + } + + /** + * Turning the DOM4j object in the specified output stream. + * + * @param xmlContent + * The XML document. + * @param outStream + * The OutputStream in which the XML document will be written. + * @return true if the xml is successfully written in the stream, + * else false. + */ + public static boolean saveXmlInStream(Document xmlContent, + OutputStream outStream) { + try { + OutputFormat outformat = OutputFormat.createPrettyPrint(); + outformat.setEncoding("UTF-8"); + XMLWriter writer = new XMLWriter(outStream, outformat); + writer.write(xmlContent); + } catch (Exception e) { + return false; + } + return true; + } + + /** + * Copy the input stream into the output stream. + * + * @param inStream + * The source stream. + * @param outStream + * The destination stream. + * @return true if the operation succeed, else return false. + */ + public static boolean copyStream(InputStream inStream, OutputStream outStream) { + try { + byte[] buffer = new byte[1024]; + int bytesRead; + while ((bytesRead = inStream.read(buffer)) >= 0) { + outStream.write(buffer, 0, bytesRead); + } + } catch (Exception e) { + return false; + } + return true; + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/TargetMode.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/TargetMode.java index 12a5a55ffa..834c2ad66e 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/TargetMode.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/TargetMode.java @@ -1,32 +1,32 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc; - -/** - * Specifies whether the target of a PackageRelationship is inside or outside a - * Package. - * - * @author Julien Chable - * @version 1.0 - */ -public enum TargetMode { - /** The relationship references a resource that is external to the package. */ - INTERNAL, - /** The relationship references a part that is inside the package. */ - EXTERNAL -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc; + +/** + * Specifies whether the target of a PackageRelationship is inside or outside a + * Package. + * + * @author Julien Chable + * @version 1.0 + */ +public enum TargetMode { + /** The relationship references a resource that is external to the package. */ + INTERNAL, + /** The relationship references a part that is inside the package. */ + EXTERNAL +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/ZipPackage.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/ZipPackage.java index f3e9a578ce..6e676cc9b2 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/ZipPackage.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/ZipPackage.java @@ -1,465 +1,460 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.URI; -import java.util.Enumeration; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import java.util.zip.ZipInputStream; -import java.util.zip.ZipOutputStream; - -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.exceptions.InvalidOperationException; -import org.apache.poi.openxml4j.exceptions.OpenXML4JException; -import org.apache.poi.openxml4j.opc.internal.ContentTypeManager; -import org.apache.poi.openxml4j.opc.internal.FileHelper; -import org.apache.poi.openxml4j.opc.internal.MemoryPackagePart; -import org.apache.poi.openxml4j.opc.internal.PartMarshaller; -import org.apache.poi.openxml4j.opc.internal.ZipContentTypeManager; -import org.apache.poi.openxml4j.opc.internal.ZipHelper; -import org.apache.poi.openxml4j.opc.internal.marshallers.ZipPackagePropertiesMarshaller; -import org.apache.poi.openxml4j.opc.internal.marshallers.ZipPartMarshaller; -import org.apache.poi.openxml4j.util.ZipEntrySource; -import org.apache.poi.openxml4j.util.ZipFileZipEntrySource; -import org.apache.poi.openxml4j.util.ZipInputStreamZipEntrySource; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.POILogFactory; - -/** - * Physical zip package. - * - * @author Julien Chable - * @version 0.2 - */ -public final class ZipPackage extends Package { - - private static POILogger logger = POILogFactory.getLogger(ZipPackage.class); - - /** - * Zip archive, as either a file on disk, - * or a stream - */ - private final ZipEntrySource zipArchive; - - /** - * Constructor. Creates a new ZipPackage. - */ - public ZipPackage() { - super(defaultPackageAccess); - this.zipArchive = null; - } - - /** - * Constructor. Operation not supported. - * - * @param in - * Zip input stream to load. - * @param access - * @throws IllegalArgumentException - * If the specified input stream not an instance of - * ZipInputStream. - */ - ZipPackage(InputStream in, PackageAccess access) throws IOException { - super(access); - this.zipArchive = new ZipInputStreamZipEntrySource( - new ZipInputStream(in) - ); - } - - /** - * Constructor. Opens a Zip based Open XML document. - * - * @param path - * The path of the file to open or create. - * @param access - * The package access mode. - * @throws InvalidFormatException - * If the content type part parsing encounters an error. - */ - ZipPackage(String path, PackageAccess access) throws InvalidFormatException { - super(access); - - ZipFile zipFile = ZipHelper.openZipFile(path); - if (zipFile == null) - throw new InvalidOperationException( - "Can't open the specified file: '" + path + "'"); - this.zipArchive = new ZipFileZipEntrySource(zipFile); - } - - /** - * Retrieves the parts from this package. We assume that the package has not - * been yet inspect to retrieve all the parts, this method will open the - * archive and look for all parts contain inside it. If the package part - * list is not empty, it will be emptied. - * - * @return All parts contain in this package. - * @throws InvalidFormatException - * Throws if the package is not valid. - */ - @Override - protected PackagePart[] getPartsImpl() throws InvalidFormatException { - if (this.partList == null) { - // The package has just been created, we create an empty part - // list. - this.partList = new PackagePartCollection(); - } - - if (this.zipArchive == null) { - return this.partList.values().toArray( - new PackagePart[this.partList.values().size()]); - } else { - // First we need to parse the content type part - Enumeration entries = this.zipArchive.getEntries(); - while (entries.hasMoreElements()) { - ZipEntry entry = entries.nextElement(); - if (entry.getName().equals( - ContentTypeManager.CONTENT_TYPES_PART_NAME)) { - try { - this.contentTypeManager = new ZipContentTypeManager( - getZipArchive().getInputStream(entry), this); - } catch (IOException e) { - throw new InvalidFormatException(e.getMessage()); - } - break; - } - } - - // At this point, we should have loaded the content type part - if (this.contentTypeManager == null) { - throw new InvalidFormatException( - "Package should contain a content type part [M1.13]"); - } - - // Now create all the relationships - // (Need to create relationships before other - // parts, otherwise we might create a part before - // its relationship exists, and then it won't tie up) - entries = this.zipArchive.getEntries(); - while (entries.hasMoreElements()) { - ZipEntry entry = (ZipEntry) entries.nextElement(); - PackagePartName partName = buildPartName(entry); - if(partName == null) continue; - - // Only proceed for Relationships at this stage - String contentType = contentTypeManager.getContentType(partName); - if (contentType != null && contentType.equals(ContentTypes.RELATIONSHIPS_PART)) { - try { - partList.put(partName, new ZipPackagePart(this, entry, - partName, contentType)); - } catch (InvalidOperationException e) { - throw new InvalidFormatException(e.getMessage()); - } - } - } - - // Then we can go through all the other parts - entries = this.zipArchive.getEntries(); - while (entries.hasMoreElements()) { - ZipEntry entry = (ZipEntry) entries.nextElement(); - PackagePartName partName = buildPartName(entry); - if(partName == null) continue; - - String contentType = contentTypeManager - .getContentType(partName); - if (contentType != null && contentType.equals(ContentTypes.RELATIONSHIPS_PART)) { - // Already handled - } - else if (contentType != null) { - try { - partList.put(partName, new ZipPackagePart(this, entry, - partName, contentType)); - } catch (InvalidOperationException e) { - throw new InvalidFormatException(e.getMessage()); - } - } else { - throw new InvalidFormatException( - "The part " - + partName.getURI().getPath() - + " does not have any content type ! Rule: Package require content types when retrieving a part from a package. [M.1.14]"); - } - } - - return (ZipPackagePart[]) partList.values().toArray( - new ZipPackagePart[partList.size()]); - } - } - - /** - * Builds a PackagePartName for the given ZipEntry, - * or null if it's the content types / invalid part - */ - private PackagePartName buildPartName(ZipEntry entry) { - try { - // We get an error when we parse [Content_Types].xml - // because it's not a valid URI. - if (entry.getName().equals( - ContentTypeManager.CONTENT_TYPES_PART_NAME)) { - return null; - } else { - return PackagingURIHelper.createPartName(ZipHelper - .getOPCNameFromZipItemName(entry.getName())); - } - } catch (Exception e) { - // We assume we can continue, even in degraded mode ... - logger.log(POILogger.WARN,"Entry " - + entry.getName() - + " is not valid, so this part won't be add to the package."); - return null; - } - } - - /** - * Create a new MemoryPackagePart from the specified URI and content type - * - * - * aram partName The part URI. - * - * @param contentType - * The part content type. - * @return The newly created zip package part, else null. - */ - @Override - protected PackagePart createPartImpl(PackagePartName partName, - String contentType, boolean loadRelationships) { - if (contentType == null) - throw new IllegalArgumentException("contentType"); - - if (partName == null) - throw new IllegalArgumentException("partName"); - - try { - return new MemoryPackagePart(this, partName, contentType, - loadRelationships); - } catch (InvalidFormatException e) { - // TODO - don't use system.err. Is it valid to return null when this exception occurs? - System.err.println(e); - return null; - } - } - - /** - * Delete a part from the package - * - * @throws IllegalArgumentException - * Throws if the part URI is nulll or invalid. - */ - @Override - protected void removePartImpl(PackagePartName partName) { - if (partName == null) - throw new IllegalArgumentException("partUri"); - } - - /** - * Flush the package. Do nothing. - */ - @Override - protected void flushImpl() { - // Do nothing - } - - /** - * Close and save the package. - * - * @see #close() - */ - @Override - protected void closeImpl() throws IOException { - // Flush the package - flush(); - - // Save the content - if (this.originalPackagePath != null - && !"".equals(this.originalPackagePath)) { - File targetFile = new File(this.originalPackagePath); - if (targetFile.exists()) { - // Case of a package previously open - - File tempFile = File.createTempFile( - generateTempFileName(FileHelper - .getDirectory(targetFile)), ".tmp"); - - // Save the final package to a temporary file - try { - save(tempFile); - this.zipArchive.close(); // Close the zip archive to be - // able to delete it - FileHelper.copyFile(tempFile, targetFile); - } finally { - // Either the save operation succeed or not, we delete the - // temporary file - if (!tempFile.delete()) { - logger - .log(POILogger.WARN,"The temporary file: '" - + targetFile.getAbsolutePath() - + "' cannot be deleted ! Make sure that no other application use it."); - } - } - } else { - throw new InvalidOperationException( - "Can't close a package not previously open with the open() method !"); - } - } - } - - /** - * Create a unique identifier to be use as a temp file name. - * - * @return A unique identifier use to be use as a temp file name. - */ - private synchronized String generateTempFileName(File directory) { - File tmpFilename; - do { - tmpFilename = new File(directory.getAbsoluteFile() + File.separator - + "OpenXML4J" + System.nanoTime()); - } while (tmpFilename.exists()); - return FileHelper.getFilename(tmpFilename.getAbsoluteFile()); - } - - /** - * Close the package without saving the document. Discard all the changes - * made to this package. - */ - @Override - protected void revertImpl() { - try { - if (this.zipArchive != null) - this.zipArchive.close(); - } catch (IOException e) { - // Do nothing, user dont have to know - } - } - - /** - * Implement the getPart() method to retrieve a part from its URI in the - * current package - * - * - * @see #getPart(PackageRelationship) - */ - @Override - protected PackagePart getPartImpl(PackagePartName partName) { - if (partList.containsKey(partName)) { - return partList.get(partName); - } - return null; - } - - /** - * Save this package into the specified stream - * - * - * @param outputStream - * The stream use to save this package. - * - * @see #save(OutputStream) - */ - @Override - public void saveImpl(OutputStream outputStream) { - // Check that the document was open in write mode - throwExceptionIfReadOnly(); - ZipOutputStream zos = null; - - try { - if (!(outputStream instanceof ZipOutputStream)) - zos = new ZipOutputStream(outputStream); - else - zos = (ZipOutputStream) outputStream; - - // If the core properties part does not exist in the part list, - // we save it as well - if (this.getPartsByRelationshipType( - PackageRelationshipTypes.CORE_PROPERTIES).size() == 0) { - logger.log(POILogger.DEBUG,"Save core properties part"); - - // We have to save the core properties part ... - new ZipPackagePropertiesMarshaller().marshall( - this.packageProperties, zos); - // ... and to add its relationship ... - this.relationships.addRelationship(this.packageProperties - .getPartName().getURI(), TargetMode.INTERNAL, - PackageRelationshipTypes.CORE_PROPERTIES, null); - // ... and the content if it has not been added yet. - if (!this.contentTypeManager - .isContentTypeRegister(ContentTypes.CORE_PROPERTIES_PART)) { - this.contentTypeManager.addContentType( - this.packageProperties.getPartName(), - ContentTypes.CORE_PROPERTIES_PART); - } - } - - // Save package relationships part. - logger.log(POILogger.DEBUG,"Save package relationships"); - ZipPartMarshaller.marshallRelationshipPart(this.getRelationships(), - PackagingURIHelper.PACKAGE_RELATIONSHIPS_ROOT_PART_NAME, - zos); - - // Save content type part. - logger.log(POILogger.DEBUG,"Save content types part"); - this.contentTypeManager.save(zos); - - // Save parts. - for (PackagePart part : getParts()) { - // If the part is a relationship part, we don't save it, it's - // the source part that will do the job. - if (part.isRelationshipPart()) - continue; - - logger.log(POILogger.DEBUG,"Save part '" - + ZipHelper.getZipItemNameFromOPCName(part - .getPartName().getName()) + "'"); - PartMarshaller marshaller = partMarshallers - .get(part.contentType); - if (marshaller != null) { - if (!marshaller.marshall(part, zos)) { - throw new OpenXML4JException( - "The part " - + part.getPartName().getURI() - + " fail to be saved in the stream with marshaller " - + marshaller); - } - } else { - if (!defaultPartMarshaller.marshall(part, zos)) - throw new OpenXML4JException( - "The part " - + part.getPartName().getURI() - + " fail to be saved in the stream with marshaller " - + defaultPartMarshaller); - } - } - zos.close(); - } catch (Exception e) { - logger - .log(POILogger.ERROR,"Fail to save: an error occurs while saving the package : " - + e.getMessage()); - } - } - - /** - * Get the zip archive - * - * @return The zip archive. - */ - public ZipEntrySource getZipArchive() { - return zipArchive; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Enumeration; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.exceptions.InvalidOperationException; +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.openxml4j.opc.internal.ContentTypeManager; +import org.apache.poi.openxml4j.opc.internal.FileHelper; +import org.apache.poi.openxml4j.opc.internal.MemoryPackagePart; +import org.apache.poi.openxml4j.opc.internal.PartMarshaller; +import org.apache.poi.openxml4j.opc.internal.ZipContentTypeManager; +import org.apache.poi.openxml4j.opc.internal.ZipHelper; +import org.apache.poi.openxml4j.opc.internal.marshallers.ZipPackagePropertiesMarshaller; +import org.apache.poi.openxml4j.opc.internal.marshallers.ZipPartMarshaller; +import org.apache.poi.openxml4j.util.ZipEntrySource; +import org.apache.poi.openxml4j.util.ZipFileZipEntrySource; +import org.apache.poi.openxml4j.util.ZipInputStreamZipEntrySource; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.POILogFactory; + +/** + * Physical zip package. + * + * @author Julien Chable + */ +public final class ZipPackage extends Package { + + private static POILogger logger = POILogFactory.getLogger(ZipPackage.class); + + /** + * Zip archive, as either a file on disk, + * or a stream + */ + private final ZipEntrySource zipArchive; + + /** + * Constructor. Creates a new ZipPackage. + */ + public ZipPackage() { + super(defaultPackageAccess); + this.zipArchive = null; + } + + /** + * Constructor. Operation not supported. + * + * @param in + * Zip input stream to load. + * @param access + * @throws IllegalArgumentException + * If the specified input stream not an instance of + * ZipInputStream. + */ + ZipPackage(InputStream in, PackageAccess access) throws IOException { + super(access); + this.zipArchive = new ZipInputStreamZipEntrySource( + new ZipInputStream(in) + ); + } + + /** + * Constructor. Opens a Zip based Open XML document. + * + * @param path + * The path of the file to open or create. + * @param access + * The package access mode. + * @throws InvalidFormatException + * If the content type part parsing encounters an error. + */ + ZipPackage(String path, PackageAccess access) throws InvalidFormatException { + super(access); + + ZipFile zipFile = ZipHelper.openZipFile(path); + if (zipFile == null) + throw new InvalidOperationException( + "Can't open the specified file: '" + path + "'"); + this.zipArchive = new ZipFileZipEntrySource(zipFile); + } + + /** + * Retrieves the parts from this package. We assume that the package has not + * been yet inspect to retrieve all the parts, this method will open the + * archive and look for all parts contain inside it. If the package part + * list is not empty, it will be emptied. + * + * @return All parts contain in this package. + * @throws InvalidFormatException + * Throws if the package is not valid. + */ + @Override + protected PackagePart[] getPartsImpl() throws InvalidFormatException { + if (this.partList == null) { + // The package has just been created, we create an empty part + // list. + this.partList = new PackagePartCollection(); + } + + if (this.zipArchive == null) { + return this.partList.values().toArray( + new PackagePart[this.partList.values().size()]); + } + // First we need to parse the content type part + Enumeration entries = this.zipArchive.getEntries(); + while (entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + if (entry.getName().equals( + ContentTypeManager.CONTENT_TYPES_PART_NAME)) { + try { + this.contentTypeManager = new ZipContentTypeManager( + getZipArchive().getInputStream(entry), this); + } catch (IOException e) { + throw new InvalidFormatException(e.getMessage()); + } + break; + } + } + + // At this point, we should have loaded the content type part + if (this.contentTypeManager == null) { + throw new InvalidFormatException( + "Package should contain a content type part [M1.13]"); + } + + // Now create all the relationships + // (Need to create relationships before other + // parts, otherwise we might create a part before + // its relationship exists, and then it won't tie up) + entries = this.zipArchive.getEntries(); + while (entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + PackagePartName partName = buildPartName(entry); + if(partName == null) continue; + + // Only proceed for Relationships at this stage + String contentType = contentTypeManager.getContentType(partName); + if (contentType != null && contentType.equals(ContentTypes.RELATIONSHIPS_PART)) { + try { + partList.put(partName, new ZipPackagePart(this, entry, + partName, contentType)); + } catch (InvalidOperationException e) { + throw new InvalidFormatException(e.getMessage()); + } + } + } + + // Then we can go through all the other parts + entries = this.zipArchive.getEntries(); + while (entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + PackagePartName partName = buildPartName(entry); + if(partName == null) continue; + + String contentType = contentTypeManager + .getContentType(partName); + if (contentType != null && contentType.equals(ContentTypes.RELATIONSHIPS_PART)) { + // Already handled + } + else if (contentType != null) { + try { + partList.put(partName, new ZipPackagePart(this, entry, + partName, contentType)); + } catch (InvalidOperationException e) { + throw new InvalidFormatException(e.getMessage()); + } + } else { + throw new InvalidFormatException( + "The part " + + partName.getURI().getPath() + + " does not have any content type ! Rule: Package require content types when retrieving a part from a package. [M.1.14]"); + } + } + + return partList.values().toArray(new ZipPackagePart[partList.size()]); + } + + /** + * Builds a PackagePartName for the given ZipEntry, + * or null if it's the content types / invalid part + */ + private PackagePartName buildPartName(ZipEntry entry) { + try { + // We get an error when we parse [Content_Types].xml + // because it's not a valid URI. + if (entry.getName().equals( + ContentTypeManager.CONTENT_TYPES_PART_NAME)) { + return null; + } + return PackagingURIHelper.createPartName(ZipHelper + .getOPCNameFromZipItemName(entry.getName())); + } catch (Exception e) { + // We assume we can continue, even in degraded mode ... + logger.log(POILogger.WARN,"Entry " + + entry.getName() + + " is not valid, so this part won't be add to the package."); + return null; + } + } + + /** + * Create a new MemoryPackagePart from the specified URI and content type + * + * + * aram partName The part URI. + * + * @param contentType + * The part content type. + * @return The newly created zip package part, else null. + */ + @Override + protected PackagePart createPartImpl(PackagePartName partName, + String contentType, boolean loadRelationships) { + if (contentType == null) + throw new IllegalArgumentException("contentType"); + + if (partName == null) + throw new IllegalArgumentException("partName"); + + try { + return new MemoryPackagePart(this, partName, contentType, + loadRelationships); + } catch (InvalidFormatException e) { + // TODO - don't use system.err. Is it valid to return null when this exception occurs? + System.err.println(e); + return null; + } + } + + /** + * Delete a part from the package + * + * @throws IllegalArgumentException + * Throws if the part URI is nulll or invalid. + */ + @Override + protected void removePartImpl(PackagePartName partName) { + if (partName == null) + throw new IllegalArgumentException("partUri"); + } + + /** + * Flush the package. Do nothing. + */ + @Override + protected void flushImpl() { + // Do nothing + } + + /** + * Close and save the package. + * + * @see #close() + */ + @Override + protected void closeImpl() throws IOException { + // Flush the package + flush(); + + // Save the content + if (this.originalPackagePath != null + && !"".equals(this.originalPackagePath)) { + File targetFile = new File(this.originalPackagePath); + if (targetFile.exists()) { + // Case of a package previously open + + File tempFile = File.createTempFile( + generateTempFileName(FileHelper + .getDirectory(targetFile)), ".tmp"); + + // Save the final package to a temporary file + try { + save(tempFile); + this.zipArchive.close(); // Close the zip archive to be + // able to delete it + FileHelper.copyFile(tempFile, targetFile); + } finally { + // Either the save operation succeed or not, we delete the + // temporary file + if (!tempFile.delete()) { + logger + .log(POILogger.WARN,"The temporary file: '" + + targetFile.getAbsolutePath() + + "' cannot be deleted ! Make sure that no other application use it."); + } + } + } else { + throw new InvalidOperationException( + "Can't close a package not previously open with the open() method !"); + } + } + } + + /** + * Create a unique identifier to be use as a temp file name. + * + * @return A unique identifier use to be use as a temp file name. + */ + private synchronized String generateTempFileName(File directory) { + File tmpFilename; + do { + tmpFilename = new File(directory.getAbsoluteFile() + File.separator + + "OpenXML4J" + System.nanoTime()); + } while (tmpFilename.exists()); + return FileHelper.getFilename(tmpFilename.getAbsoluteFile()); + } + + /** + * Close the package without saving the document. Discard all the changes + * made to this package. + */ + @Override + protected void revertImpl() { + try { + if (this.zipArchive != null) + this.zipArchive.close(); + } catch (IOException e) { + // Do nothing, user dont have to know + } + } + + /** + * Implement the getPart() method to retrieve a part from its URI in the + * current package + * + * + * @see #getPart(PackageRelationship) + */ + @Override + protected PackagePart getPartImpl(PackagePartName partName) { + if (partList.containsKey(partName)) { + return partList.get(partName); + } + return null; + } + + /** + * Save this package into the specified stream + * + * + * @param outputStream + * The stream use to save this package. + * + * @see #save(OutputStream) + */ + @Override + public void saveImpl(OutputStream outputStream) { + // Check that the document was open in write mode + throwExceptionIfReadOnly(); + ZipOutputStream zos = null; + + try { + if (!(outputStream instanceof ZipOutputStream)) + zos = new ZipOutputStream(outputStream); + else + zos = (ZipOutputStream) outputStream; + + // If the core properties part does not exist in the part list, + // we save it as well + if (this.getPartsByRelationshipType( + PackageRelationshipTypes.CORE_PROPERTIES).size() == 0) { + logger.log(POILogger.DEBUG,"Save core properties part"); + + // We have to save the core properties part ... + new ZipPackagePropertiesMarshaller().marshall( + this.packageProperties, zos); + // ... and to add its relationship ... + this.relationships.addRelationship(this.packageProperties + .getPartName().getURI(), TargetMode.INTERNAL, + PackageRelationshipTypes.CORE_PROPERTIES, null); + // ... and the content if it has not been added yet. + if (!this.contentTypeManager + .isContentTypeRegister(ContentTypes.CORE_PROPERTIES_PART)) { + this.contentTypeManager.addContentType( + this.packageProperties.getPartName(), + ContentTypes.CORE_PROPERTIES_PART); + } + } + + // Save package relationships part. + logger.log(POILogger.DEBUG,"Save package relationships"); + ZipPartMarshaller.marshallRelationshipPart(this.getRelationships(), + PackagingURIHelper.PACKAGE_RELATIONSHIPS_ROOT_PART_NAME, + zos); + + // Save content type part. + logger.log(POILogger.DEBUG,"Save content types part"); + this.contentTypeManager.save(zos); + + // Save parts. + for (PackagePart part : getParts()) { + // If the part is a relationship part, we don't save it, it's + // the source part that will do the job. + if (part.isRelationshipPart()) + continue; + + logger.log(POILogger.DEBUG,"Save part '" + + ZipHelper.getZipItemNameFromOPCName(part + .getPartName().getName()) + "'"); + PartMarshaller marshaller = partMarshallers + .get(part.contentType); + if (marshaller != null) { + if (!marshaller.marshall(part, zos)) { + throw new OpenXML4JException( + "The part " + + part.getPartName().getURI() + + " fail to be saved in the stream with marshaller " + + marshaller); + } + } else { + if (!defaultPartMarshaller.marshall(part, zos)) + throw new OpenXML4JException( + "The part " + + part.getPartName().getURI() + + " fail to be saved in the stream with marshaller " + + defaultPartMarshaller); + } + } + zos.close(); + } catch (Exception e) { + logger + .log(POILogger.ERROR,"Fail to save: an error occurs while saving the package : " + + e.getMessage()); + } + } + + /** + * Get the zip archive + * + * @return The zip archive. + */ + public ZipEntrySource getZipArchive() { + return zipArchive; + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ContentType.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ContentType.java index 5f40940b47..ecf45af549 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ContentType.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ContentType.java @@ -1,224 +1,224 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc.internal; - -import java.io.UnsupportedEncodingException; -import java.util.Hashtable; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; - -/** - * Represents a immutable MIME ContentType value (RFC 2616 §3.7) - *

- * media-type = type "/" subtype *( ";" parameter ) type = token
- * subtype = token
- *

- * Rule M1.13 : Package implementers shall only create and only recognize parts - * with a content type; format designers shall specify a content type for each - * part included in the format. Content types for package parts shall fit the - * definition and syntax for media types as specified in RFC 2616, \§3.7. - *

- * Rule M1.14: Content types shall not use linear white space either between the - * type and subtype or between an attribute and its value. Content types also - * shall not have leading or trailing white spaces. Package implementers shall - * create only such content types and shall require such content types when - * retrieving a part from a package; format designers shall specify only such - * content types for inclusion in the format. - *

- * @author Julien Chable - * @version 0.1 - * - * @see http://www.ietf.org/rfc/rfc2045.txt - * @see http://www.ietf.org/rfc/rfc2616.txt - */ -public final class ContentType { - - /** - * Type in Type/Subtype. - */ - private String type; - - /** - * Subtype - */ - private String subType; - - /** - * Parameters - */ - private Hashtable parameters; - - /** - * Media type compiled pattern for parameters. - */ - private final static Pattern patternMediaType; - - static { - /* - * token = 1* - * - * separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | - * <"> | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT - * - * CTL = - * - * CHAR = - */ - String token = "[\\x21-\\x7E&&[^\\(\\)<>@,;:\\\\/\"\\[\\]\\?={}\\x20\\x09]]"; - - /* - * parameter = attribute "=" value - * - * attribute = token - * - * value = token | quoted-string - */ - // Keep for future use with parameter: - // String parameter = "(" + token + "+)=(\"?" + token + "+\"?)"; - /* - * Pattern for media type. - * - * Don't allow comment, rule M1.15: The package implementer shall - * require a content type that does not include comments and the format - * designer shall specify such a content type. - * - * comment = "(" *( ctext | quoted-pair | comment ) ")" - * - * ctext = - * - * TEXT = - * - * LWS = [CRLF] 1*( SP | HT ) - * - * CR = - * - * LF = - * - * SP = - * - * HT = - * - * quoted-pair = "\" CHAR - */ - - // Keep for future use with parameter: - // patternMediaType = Pattern.compile("^(" + token + "+)/(" + token - // + "+)(;" + parameter + ")*$"); - patternMediaType = Pattern.compile("^(" + token + "+)/(" + token - + "+)$"); - } - - /** - * Constructor. Check the input with the RFC 2616 grammar. - * - * @param contentType - * The content type to store. - * @throws InvalidFormatException - * If the specified content type is not valid with RFC 2616. - */ - public ContentType(String contentType) throws InvalidFormatException { - // Conversion en US-ASCII - String contentTypeASCII = null; - try { - contentTypeASCII = new String(contentType.getBytes(), "US-ASCII"); - } catch (UnsupportedEncodingException e) { - throw new InvalidFormatException( - "The specified content type is not an ASCII value."); - } - - Matcher mMediaType = patternMediaType.matcher(contentTypeASCII); - if (!mMediaType.matches()) - throw new InvalidFormatException( - "The specified content type '" - + contentType - + "' is not compliant with RFC 2616: malformed content type."); - - // Type/subtype - if (mMediaType.groupCount() >= 2) { - this.type = mMediaType.group(1); - this.subType = mMediaType.group(2); - // Parameters - this.parameters = new Hashtable(1); - for (int i = 4; i <= mMediaType.groupCount() - && (mMediaType.group(i) != null); i += 2) { - this.parameters.put(mMediaType.group(i), mMediaType - .group(i + 1)); - } - } - } - - @Override - public final String toString() { - StringBuffer retVal = new StringBuffer(); - retVal.append(this.getType()); - retVal.append("/"); - retVal.append(this.getSubType()); - // Keep for future implementation if needed - // for (String key : parameters.keySet()) { - // retVal.append(";"); - // retVal.append(key); - // retVal.append("="); - // retVal.append(parameters.get(key)); - // } - return retVal.toString(); - } - - @Override - public boolean equals(Object obj) { - return (!(obj instanceof ContentType)) - || (this.toString().equalsIgnoreCase(obj.toString())); - } - - @Override - public int hashCode() { - return this.toString().hashCode(); - } - - /* Getters */ - - /** - * Get the subtype. - * - * @return The subtype of this content type. - */ - public String getSubType() { - return this.subType; - } - - /** - * Get the type. - * - * @return The type of this content type. - */ - public String getType() { - return this.type; - } - - /** - * Gets the value associated to the specified key. - * - * @param key - * The key of the key/value pair. - * @return The value associated to the specified key. - */ - public String getParameters(String key) { - return parameters.get(key); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc.internal; + +import java.io.UnsupportedEncodingException; +import java.util.Hashtable; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; + +/** + * Represents a immutable MIME ContentType value (RFC 2616 §3.7) + *

+ * media-type = type "/" subtype *( ";" parameter ) type = token
+ * subtype = token
+ *

+ * Rule M1.13 : Package implementers shall only create and only recognize parts + * with a content type; format designers shall specify a content type for each + * part included in the format. Content types for package parts shall fit the + * definition and syntax for media types as specified in RFC 2616, \§3.7. + *

+ * Rule M1.14: Content types shall not use linear white space either between the + * type and subtype or between an attribute and its value. Content types also + * shall not have leading or trailing white spaces. Package implementers shall + * create only such content types and shall require such content types when + * retrieving a part from a package; format designers shall specify only such + * content types for inclusion in the format. + *

+ * @author Julien Chable + * @version 0.1 + * + * @see http://www.ietf.org/rfc/rfc2045.txt + * @see http://www.ietf.org/rfc/rfc2616.txt + */ +public final class ContentType { + + /** + * Type in Type/Subtype. + */ + private String type; + + /** + * Subtype + */ + private String subType; + + /** + * Parameters + */ + private Hashtable parameters; + + /** + * Media type compiled pattern for parameters. + */ + private final static Pattern patternMediaType; + + static { + /* + * token = 1* + * + * separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | + * <"> | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT + * + * CTL = + * + * CHAR = + */ + String token = "[\\x21-\\x7E&&[^\\(\\)<>@,;:\\\\/\"\\[\\]\\?={}\\x20\\x09]]"; + + /* + * parameter = attribute "=" value + * + * attribute = token + * + * value = token | quoted-string + */ + // Keep for future use with parameter: + // String parameter = "(" + token + "+)=(\"?" + token + "+\"?)"; + /* + * Pattern for media type. + * + * Don't allow comment, rule M1.15: The package implementer shall + * require a content type that does not include comments and the format + * designer shall specify such a content type. + * + * comment = "(" *( ctext | quoted-pair | comment ) ")" + * + * ctext = + * + * TEXT = + * + * LWS = [CRLF] 1*( SP | HT ) + * + * CR = + * + * LF = + * + * SP = + * + * HT = + * + * quoted-pair = "\" CHAR + */ + + // Keep for future use with parameter: + // patternMediaType = Pattern.compile("^(" + token + "+)/(" + token + // + "+)(;" + parameter + ")*$"); + patternMediaType = Pattern.compile("^(" + token + "+)/(" + token + + "+)$"); + } + + /** + * Constructor. Check the input with the RFC 2616 grammar. + * + * @param contentType + * The content type to store. + * @throws InvalidFormatException + * If the specified content type is not valid with RFC 2616. + */ + public ContentType(String contentType) throws InvalidFormatException { + // Conversion en US-ASCII + String contentTypeASCII = null; + try { + contentTypeASCII = new String(contentType.getBytes(), "US-ASCII"); + } catch (UnsupportedEncodingException e) { + throw new InvalidFormatException( + "The specified content type is not an ASCII value."); + } + + Matcher mMediaType = patternMediaType.matcher(contentTypeASCII); + if (!mMediaType.matches()) + throw new InvalidFormatException( + "The specified content type '" + + contentType + + "' is not compliant with RFC 2616: malformed content type."); + + // Type/subtype + if (mMediaType.groupCount() >= 2) { + this.type = mMediaType.group(1); + this.subType = mMediaType.group(2); + // Parameters + this.parameters = new Hashtable(1); + for (int i = 4; i <= mMediaType.groupCount() + && (mMediaType.group(i) != null); i += 2) { + this.parameters.put(mMediaType.group(i), mMediaType + .group(i + 1)); + } + } + } + + @Override + public final String toString() { + StringBuffer retVal = new StringBuffer(); + retVal.append(this.getType()); + retVal.append("/"); + retVal.append(this.getSubType()); + // Keep for future implementation if needed + // for (String key : parameters.keySet()) { + // retVal.append(";"); + // retVal.append(key); + // retVal.append("="); + // retVal.append(parameters.get(key)); + // } + return retVal.toString(); + } + + @Override + public boolean equals(Object obj) { + return (!(obj instanceof ContentType)) + || (this.toString().equalsIgnoreCase(obj.toString())); + } + + @Override + public int hashCode() { + return this.toString().hashCode(); + } + + /* Getters */ + + /** + * Get the subtype. + * + * @return The subtype of this content type. + */ + public String getSubType() { + return this.subType; + } + + /** + * Get the type. + * + * @return The type of this content type. + */ + public String getType() { + return this.type; + } + + /** + * Gets the value associated to the specified key. + * + * @param key + * The key of the key/value pair. + * @return The value associated to the specified key. + */ + public String getParameters(String key) { + return parameters.get(key); + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/FileHelper.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/FileHelper.java index ad31157372..cc41e43520 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/FileHelper.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/FileHelper.java @@ -1,91 +1,91 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc.internal; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.channels.FileChannel; - -/** - * Provide useful method to manage file. - * - * @author Julien Chable - * @version 0.1 - */ -public final class FileHelper { - - /** - * Get the directory part of the specified file path. - * - * @param f - * File to process. - * @return The directory path from the specified - */ - public static File getDirectory(File f) { - if (f != null) { - String path = f.getPath(); - int len = path.length(); - int num2 = len; - while (--num2 >= 0) { - char ch1 = path.charAt(num2); - if (ch1 == File.separatorChar) { - return new File(path.substring(0, num2)); - } - } - } - return null; - } - - /** - * Copy a file. - * - * @param in - * The source file. - * @param out - * The target location. - * @throws IOException - * If an I/O error occur. - */ - public static void copyFile(File in, File out) throws IOException { - FileChannel sourceChannel = new FileInputStream(in).getChannel(); - FileChannel destinationChannel = new FileOutputStream(out).getChannel(); - sourceChannel.transferTo(0, sourceChannel.size(), destinationChannel); - sourceChannel.close(); - destinationChannel.close(); - } - - /** - * Get file name from the specified File object. - */ - public static String getFilename(File file) { - if (file != null) { - String path = file.getPath(); - int len = path.length(); - int num2 = len; - while (--num2 >= 0) { - char ch1 = path.charAt(num2); - if (ch1 == File.separatorChar) - return path.substring(num2 + 1, len); - } - } - return ""; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc.internal; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.channels.FileChannel; + +/** + * Provide useful method to manage file. + * + * @author Julien Chable + * @version 0.1 + */ +public final class FileHelper { + + /** + * Get the directory part of the specified file path. + * + * @param f + * File to process. + * @return The directory path from the specified + */ + public static File getDirectory(File f) { + if (f != null) { + String path = f.getPath(); + int len = path.length(); + int num2 = len; + while (--num2 >= 0) { + char ch1 = path.charAt(num2); + if (ch1 == File.separatorChar) { + return new File(path.substring(0, num2)); + } + } + } + return null; + } + + /** + * Copy a file. + * + * @param in + * The source file. + * @param out + * The target location. + * @throws IOException + * If an I/O error occur. + */ + public static void copyFile(File in, File out) throws IOException { + FileChannel sourceChannel = new FileInputStream(in).getChannel(); + FileChannel destinationChannel = new FileOutputStream(out).getChannel(); + sourceChannel.transferTo(0, sourceChannel.size(), destinationChannel); + sourceChannel.close(); + destinationChannel.close(); + } + + /** + * Get file name from the specified File object. + */ + public static String getFilename(File file) { + if (file != null) { + String path = file.getPath(); + int len = path.length(); + int num2 = len; + while (--num2 >= 0) { + char ch1 = path.charAt(num2); + if (ch1 == File.separatorChar) + return path.substring(num2 + 1, len); + } + } + return ""; + } + +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/MemoryPackagePartOutputStream.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/MemoryPackagePartOutputStream.java index debe3d185e..ed0bc6a74a 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/MemoryPackagePartOutputStream.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/MemoryPackagePartOutputStream.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; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * Build an output stream for MemoryPackagePart. - * - * @author Julien Chable - * @version 1.0 - */ -public final class MemoryPackagePartOutputStream extends OutputStream { - - private MemoryPackagePart part; - - private ByteArrayOutputStream buff; - - public MemoryPackagePartOutputStream(MemoryPackagePart part) { - this.part = part; - buff = new ByteArrayOutputStream(); - } - - @Override - public void write(int b) throws IOException { - buff.write(b); - } - - /** - * Close this stream and flush the content. - * @see #flush() - */ - @Override - public void close() throws IOException { - this.flush(); - } - - /** - * Flush this output stream. This method is called by the close() method. - * Warning : don't call this method for output consistency. - * @see #close() - */ - @Override - public void flush() throws IOException { - buff.flush(); - if (part.data != null) { - byte[] newArray = new byte[part.data.length + buff.size()]; - // copy the previous contents of part.data in newArray - System.arraycopy(part.data, 0, newArray, 0, part.data.length); - - // append the newly added data - byte[] buffArr = buff.toByteArray(); - System.arraycopy(buffArr, 0, newArray, part.data.length, - buffArr.length); - - // save the result as new data - part.data = newArray; - } else { - // was empty, just fill it - part.data = buff.toByteArray(); - } - - /* - * Clear this streams buffer, in case flush() is called a second time - * Fix bug 1921637 - provided by Rainer Schwarze - */ - buff.reset(); - } - - @Override - public void write(byte[] b, int off, int len) throws IOException { - buff.write(b, off, len); - } - - @Override - public void write(byte[] b) throws IOException { - buff.write(b); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc.internal; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * Build an output stream for MemoryPackagePart. + * + * @author Julien Chable + * @version 1.0 + */ +public final class MemoryPackagePartOutputStream extends OutputStream { + + private MemoryPackagePart part; + + private ByteArrayOutputStream buff; + + public MemoryPackagePartOutputStream(MemoryPackagePart part) { + this.part = part; + buff = new ByteArrayOutputStream(); + } + + @Override + public void write(int b) throws IOException { + buff.write(b); + } + + /** + * Close this stream and flush the content. + * @see #flush() + */ + @Override + public void close() throws IOException { + this.flush(); + } + + /** + * Flush this output stream. This method is called by the close() method. + * Warning : don't call this method for output consistency. + * @see #close() + */ + @Override + public void flush() throws IOException { + buff.flush(); + if (part.data != null) { + byte[] newArray = new byte[part.data.length + buff.size()]; + // copy the previous contents of part.data in newArray + System.arraycopy(part.data, 0, newArray, 0, part.data.length); + + // append the newly added data + byte[] buffArr = buff.toByteArray(); + System.arraycopy(buffArr, 0, newArray, part.data.length, + buffArr.length); + + // save the result as new data + part.data = newArray; + } else { + // was empty, just fill it + part.data = buff.toByteArray(); + } + + /* + * Clear this streams buffer, in case flush() is called a second time + * Fix bug 1921637 - provided by Rainer Schwarze + */ + buff.reset(); + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + buff.write(b, off, len); + } + + @Override + public void write(byte[] b) throws IOException { + buff.write(b); + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/PartMarshaller.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/PartMarshaller.java index 70bbcae6b6..e30d71783a 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/PartMarshaller.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/PartMarshaller.java @@ -1,49 +1,49 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc.internal; - -import java.io.OutputStream; - -import org.apache.poi.openxml4j.exceptions.OpenXML4JException; -import org.apache.poi.openxml4j.opc.PackagePart; - -/** - * Object implemented this interface are considered as part marshaller. A part - * marshaller is responsible to marshall a part in order to be save in a - * package. - * - * @author Julien Chable - * @version 0.1 - */ -public interface PartMarshaller { - - /** - * Save the content of the package in the stream - * - * @param part - * Part to marshall. - * @param out - * The output stream into which the part will be marshall. - * @return false if any marshall error occurs, else true - * @throws OpenXML4JException - * Throws only if any other exceptions are thrown by inner - * methods. - */ - public boolean marshall(PackagePart part, OutputStream out) - throws OpenXML4JException; -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc.internal; + +import java.io.OutputStream; + +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.openxml4j.opc.PackagePart; + +/** + * Object implemented this interface are considered as part marshaller. A part + * marshaller is responsible to marshall a part in order to be save in a + * package. + * + * @author Julien Chable + * @version 0.1 + */ +public interface PartMarshaller { + + /** + * Save the content of the package in the stream + * + * @param part + * Part to marshall. + * @param out + * The output stream into which the part will be marshall. + * @return false if any marshall error occurs, else true + * @throws OpenXML4JException + * Throws only if any other exceptions are thrown by inner + * methods. + */ + public boolean marshall(PackagePart part, OutputStream out) + throws OpenXML4JException; +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/PartUnmarshaller.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/PartUnmarshaller.java index 0b17cb8926..e5487a6381 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/PartUnmarshaller.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/PartUnmarshaller.java @@ -1,50 +1,50 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc.internal; - -import java.io.IOException; -import java.io.InputStream; - -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.exceptions.OpenXML4JException; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.internal.unmarshallers.UnmarshallContext; - -/** - * Object implemented this interface are considered as part unmarshaller. A part - * unmarshaller is responsible to unmarshall a part in order to load it from a - * package. - * - * @author Julien Chable - * @version 0.1 - */ -public interface PartUnmarshaller { - - /** - * Save the content of the package in the stream - * - * @param in - * The input stream from which the part will be unmarshall. - * @return The part freshly unmarshall from the input stream. - * @throws OpenXML4JException - * Throws only if any other exceptions are thrown by inner - * methods. - */ - public PackagePart unmarshall(UnmarshallContext context, InputStream in) - throws InvalidFormatException, IOException; -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc.internal; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.openxml4j.opc.internal.unmarshallers.UnmarshallContext; + +/** + * Object implemented this interface are considered as part unmarshaller. A part + * unmarshaller is responsible to unmarshall a part in order to load it from a + * package. + * + * @author Julien Chable + * @version 0.1 + */ +public interface PartUnmarshaller { + + /** + * Save the content of the package in the stream + * + * @param in + * The input stream from which the part will be unmarshall. + * @return The part freshly unmarshall from the input stream. + * @throws OpenXML4JException + * Throws only if any other exceptions are thrown by inner + * methods. + */ + public PackagePart unmarshall(UnmarshallContext context, InputStream in) + throws InvalidFormatException, IOException; +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipHelper.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipHelper.java index 10b2339ec4..ab867ad250 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipHelper.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipHelper.java @@ -1,163 +1,163 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc.internal; - -import java.io.File; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Enumeration; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -import org.apache.poi.openxml4j.exceptions.OpenXML4JException; -import org.apache.poi.openxml4j.opc.PackageRelationship; -import org.apache.poi.openxml4j.opc.PackageRelationshipTypes; -import org.apache.poi.openxml4j.opc.ZipPackage; - -public final class ZipHelper { - - /** - * Forward slash use to convert part name between OPC and zip item naming - * conventions. - */ - private final static String FORWARD_SLASH = "/"; - - /** - * Buffer to read data from file. Use big buffer to improve performaces. the - * InputStream class is reading only 8192 bytes per read call (default value - * set by sun) - */ - public static final int READ_WRITE_FILE_BUFFER_SIZE = 8192; - - /** - * Prevent this class to be instancied. - */ - private ZipHelper() { - // Do nothing - } - - /** - * Retrieve the zip entry of the core properties part. - * - * @throws OpenXML4JException - * Throws if internal error occurs. - */ - public static ZipEntry getCorePropertiesZipEntry(ZipPackage pkg) - throws OpenXML4JException { - PackageRelationship corePropsRel = pkg.getRelationshipsByType( - PackageRelationshipTypes.CORE_PROPERTIES).getRelationship(0); - - if (corePropsRel == null) - return null; - - return new ZipEntry(corePropsRel.getTargetURI().getPath()); - } - - /** - * Retrieve the Zip entry of the content types part. - */ - public static ZipEntry getContentTypeZipEntry(ZipPackage pkg) { - Enumeration entries = pkg.getZipArchive().getEntries(); - // Enumerate through the Zip entries until we find the one named - // '[Content_Types].xml'. - while (entries.hasMoreElements()) { - ZipEntry entry = (ZipEntry) entries.nextElement(); - if (entry.getName().equals( - ContentTypeManager.CONTENT_TYPES_PART_NAME)) - return entry; - } - return null; - } - - /** - * Convert a zip name into an OPC name by adding a leading forward slash to - * the specified item name. - * - * @param zipItemName - * Zip item name to convert. - * @return An OPC compliant name. - */ - public static String getOPCNameFromZipItemName(String zipItemName) { - if (zipItemName == null) - throw new IllegalArgumentException("zipItemName"); - if (zipItemName.startsWith(FORWARD_SLASH)) - return zipItemName; - else - return FORWARD_SLASH + zipItemName; - } - - /** - * Convert an OPC item name into a zip item name by removing any leading - * forward slash if it exist. - * - * @param opcItemName - * The OPC item name to convert. - * @return A zip item name without any leading slashes. - */ - public static String getZipItemNameFromOPCName(String opcItemName) { - if (opcItemName == null) - throw new IllegalArgumentException("opcItemName"); - - String retVal = new String(opcItemName); - while (retVal.startsWith(FORWARD_SLASH)) - retVal = retVal.substring(1); - return retVal; - } - - /** - * Convert an OPC item name into a zip URI by removing any leading forward - * slash if it exist. - * - * @param opcItemName - * The OPC item name to convert. - * @return A zip URI without any leading slashes. - */ - public static URI getZipURIFromOPCName(String opcItemName) { - if (opcItemName == null) - throw new IllegalArgumentException("opcItemName"); - - String retVal = new String(opcItemName); - while (retVal.startsWith(FORWARD_SLASH)) - retVal = retVal.substring(1); - try { - return new URI(retVal); - } catch (URISyntaxException e) { - return null; - } - } - - /** - * Retrieve and open a zip file with the specified path. - * - * @param path - * The file path. - * @return The zip archive freshly open. - */ - public static ZipFile openZipFile(String path) { - File f = new File(path); - try { - if (!f.exists()) { - return null; - } - return new ZipFile(f); - } catch (IOException ioe) { - return null; - } - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc.internal; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Enumeration; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.openxml4j.opc.PackageRelationshipTypes; +import org.apache.poi.openxml4j.opc.ZipPackage; + +public final class ZipHelper { + + /** + * Forward slash use to convert part name between OPC and zip item naming + * conventions. + */ + private final static String FORWARD_SLASH = "/"; + + /** + * Buffer to read data from file. Use big buffer to improve performaces. the + * InputStream class is reading only 8192 bytes per read call (default value + * set by sun) + */ + public static final int READ_WRITE_FILE_BUFFER_SIZE = 8192; + + /** + * Prevent this class to be instancied. + */ + private ZipHelper() { + // Do nothing + } + + /** + * Retrieve the zip entry of the core properties part. + * + * @throws OpenXML4JException + * Throws if internal error occurs. + */ + public static ZipEntry getCorePropertiesZipEntry(ZipPackage pkg) + throws OpenXML4JException { + PackageRelationship corePropsRel = pkg.getRelationshipsByType( + PackageRelationshipTypes.CORE_PROPERTIES).getRelationship(0); + + if (corePropsRel == null) + return null; + + return new ZipEntry(corePropsRel.getTargetURI().getPath()); + } + + /** + * Retrieve the Zip entry of the content types part. + */ + public static ZipEntry getContentTypeZipEntry(ZipPackage pkg) { + Enumeration entries = pkg.getZipArchive().getEntries(); + // Enumerate through the Zip entries until we find the one named + // '[Content_Types].xml'. + while (entries.hasMoreElements()) { + ZipEntry entry = (ZipEntry) entries.nextElement(); + if (entry.getName().equals( + ContentTypeManager.CONTENT_TYPES_PART_NAME)) + return entry; + } + return null; + } + + /** + * Convert a zip name into an OPC name by adding a leading forward slash to + * the specified item name. + * + * @param zipItemName + * Zip item name to convert. + * @return An OPC compliant name. + */ + public static String getOPCNameFromZipItemName(String zipItemName) { + if (zipItemName == null) + throw new IllegalArgumentException("zipItemName"); + if (zipItemName.startsWith(FORWARD_SLASH)) + return zipItemName; + else + return FORWARD_SLASH + zipItemName; + } + + /** + * Convert an OPC item name into a zip item name by removing any leading + * forward slash if it exist. + * + * @param opcItemName + * The OPC item name to convert. + * @return A zip item name without any leading slashes. + */ + public static String getZipItemNameFromOPCName(String opcItemName) { + if (opcItemName == null) + throw new IllegalArgumentException("opcItemName"); + + String retVal = new String(opcItemName); + while (retVal.startsWith(FORWARD_SLASH)) + retVal = retVal.substring(1); + return retVal; + } + + /** + * Convert an OPC item name into a zip URI by removing any leading forward + * slash if it exist. + * + * @param opcItemName + * The OPC item name to convert. + * @return A zip URI without any leading slashes. + */ + public static URI getZipURIFromOPCName(String opcItemName) { + if (opcItemName == null) + throw new IllegalArgumentException("opcItemName"); + + String retVal = new String(opcItemName); + while (retVal.startsWith(FORWARD_SLASH)) + retVal = retVal.substring(1); + try { + return new URI(retVal); + } catch (URISyntaxException e) { + return null; + } + } + + /** + * Retrieve and open a zip file with the specified path. + * + * @param path + * The file path. + * @return The zip archive freshly open. + */ + public static ZipFile openZipFile(String path) { + File f = new File(path); + try { + if (!f.exists()) { + return null; + } + return new ZipFile(f); + } catch (IOException ioe) { + return null; + } + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/DefaultMarshaller.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/DefaultMarshaller.java index 8138cda8be..8cd2f7d245 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/DefaultMarshaller.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/DefaultMarshaller.java @@ -1,45 +1,45 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc.internal.marshallers; - -import java.io.OutputStream; - -import org.apache.poi.openxml4j.exceptions.OpenXML4JException; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.internal.PartMarshaller; - -/** - * Default marshaller that specified that the part is responsible to marshall its content. - * - * @author Julien Chable - * @version 1.0 - * @see PartMarshaller - */ -public class DefaultMarshaller implements PartMarshaller { - - /** - * Save part in the output stream by using the save() method of the part. - * - * @throws OpenXML4JException - * If any error occur. - */ - public boolean marshall(PackagePart part, OutputStream out) - throws OpenXML4JException { - return part.save(out); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc.internal.marshallers; + +import java.io.OutputStream; + +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.openxml4j.opc.internal.PartMarshaller; + +/** + * Default marshaller that specified that the part is responsible to marshall its content. + * + * @author Julien Chable + * @version 1.0 + * @see PartMarshaller + */ +public final class DefaultMarshaller implements PartMarshaller { + + /** + * Save part in the output stream by using the save() method of the part. + * + * @throws OpenXML4JException + * If any error occur. + */ + public boolean marshall(PackagePart part, OutputStream out) + throws OpenXML4JException { + return part.save(out); + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/PackagePropertiesMarshaller.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/PackagePropertiesMarshaller.java index 438cc5dcbb..1ad4d26b71 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/PackagePropertiesMarshaller.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/PackagePropertiesMarshaller.java @@ -1,434 +1,433 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc.internal.marshallers; - -import java.io.OutputStream; - -import org.dom4j.Document; -import org.dom4j.DocumentHelper; -import org.dom4j.Element; -import org.dom4j.Namespace; -import org.dom4j.QName; -import org.apache.poi.openxml4j.exceptions.OpenXML4JException; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart; -import org.apache.poi.openxml4j.opc.internal.PartMarshaller; - -/** - * Package properties marshaller. - * - * @author CDubet, Julien Chable - * @version 1.0 - */ -public class PackagePropertiesMarshaller implements PartMarshaller { - - private final static Namespace namespaceDC = new Namespace("dc", - PackagePropertiesPart.NAMESPACE_DC_URI); - - private final static Namespace namespaceCoreProperties = new Namespace("", - PackagePropertiesPart.NAMESPACE_CP_URI); - - private final static Namespace namespaceDcTerms = new Namespace("dcterms", - PackagePropertiesPart.NAMESPACE_DCTERMS_URI); - - private final static Namespace namespaceXSI = new Namespace("xsi", - PackagePropertiesPart.NAMESPACE_XSI_URI); - - protected static final String KEYWORD_CATEGORY = "category"; - - protected static final String KEYWORD_CONTENT_STATUS = "contentStatus"; - - protected static final String KEYWORD_CONTENT_TYPE = "contentType"; - - protected static final String KEYWORD_CREATED = "created"; - - protected static final String KEYWORD_CREATOR = "creator"; - - protected static final String KEYWORD_DESCRIPTION = "description"; - - protected static final String KEYWORD_IDENTIFIER = "identifier"; - - protected static final String KEYWORD_KEYWORDS = "keywords"; - - protected static final String KEYWORD_LANGUAGE = "language"; - - protected static final String KEYWORD_LAST_MODIFIED_BY = "lastModifiedBy"; - - protected static final String KEYWORD_LAST_PRINTED = "lastPrinted"; - - protected static final String KEYWORD_MODIFIED = "modified"; - - protected static final String KEYWORD_REVISION = "revision"; - - protected static final String KEYWORD_SUBJECT = "subject"; - - protected static final String KEYWORD_TITLE = "title"; - - protected static final String KEYWORD_VERSION = "version"; - - PackagePropertiesPart propsPart; - - // The document - Document xmlDoc = null; - - /** - * Marshall package core properties to an XML document. Always return - * true. - */ - public boolean marshall(PackagePart part, OutputStream out) - throws OpenXML4JException { - if (!(part instanceof PackagePropertiesPart)) - throw new IllegalArgumentException( - "'part' must be a PackagePropertiesPart instance."); - propsPart = (PackagePropertiesPart) part; - - // Configure the document - xmlDoc = DocumentHelper.createDocument(); - Element rootElem = xmlDoc.addElement(new QName("coreProperties", - namespaceCoreProperties)); - rootElem.addNamespace("cp", PackagePropertiesPart.NAMESPACE_CP_URI); - rootElem.addNamespace("dc", PackagePropertiesPart.NAMESPACE_DC_URI); - rootElem.addNamespace("dcterms", - PackagePropertiesPart.NAMESPACE_DCTERMS_URI); - rootElem.addNamespace("xsi", PackagePropertiesPart.NAMESPACE_XSI_URI); - - addCategory(); - addContentStatus(); - addContentType(); - addCreated(); - addCreator(); - addDescription(); - addIdentifier(); - addKeywords(); - addLanguage(); - addLastModifiedBy(); - addLastPrinted(); - addModified(); - addRevision(); - addSubject(); - addTitle(); - addVersion(); - return true; - } - - /** - * Add category property element if needed. - */ - private void addCategory() { - if (!propsPart.getCategoryProperty().hasValue()) - return; - - Element elem = xmlDoc.getRootElement().element( - new QName(KEYWORD_CATEGORY, namespaceCoreProperties)); - if (elem == null) { - // Missing, we add it - elem = xmlDoc.getRootElement().addElement( - new QName(KEYWORD_CATEGORY, namespaceCoreProperties)); - } else { - elem.clearContent();// clear the old value - } - elem.addText(propsPart.getCategoryProperty().getValue()); - } - - /** - * Add content status property element if needed. - */ - private void addContentStatus() { - if (!propsPart.getContentStatusProperty().hasValue()) - return; - - Element elem = xmlDoc.getRootElement().element( - new QName(KEYWORD_CONTENT_STATUS, namespaceCoreProperties)); - if (elem == null) { - // Missing, we add it - elem = xmlDoc.getRootElement().addElement( - new QName(KEYWORD_CONTENT_STATUS, namespaceCoreProperties)); - } else { - elem.clearContent();// clear the old value - } - elem.addText(propsPart.getContentStatusProperty().getValue()); - } - - /** - * Add content type property element if needed. - */ - private void addContentType() { - if (!propsPart.getContentTypeProperty().hasValue()) - return; - - Element elem = xmlDoc.getRootElement().element( - new QName(KEYWORD_CONTENT_TYPE, namespaceCoreProperties)); - if (elem == null) { - // Missing, we add it - elem = xmlDoc.getRootElement().addElement( - new QName(KEYWORD_CONTENT_TYPE, namespaceCoreProperties)); - } else { - elem.clearContent();// clear the old value - } - elem.addText(propsPart.getContentTypeProperty().getValue()); - } - - /** - * Add created property element if needed. - */ - private void addCreated() { - if (!propsPart.getCreatedProperty().hasValue()) - return; - - Element elem = xmlDoc.getRootElement().element( - new QName(KEYWORD_CREATED, namespaceDcTerms)); - if (elem == null) { - // missing, we add it - elem = xmlDoc.getRootElement().addElement( - new QName(KEYWORD_CREATED, namespaceDcTerms)); - } else { - elem.clearContent();// clear the old value - } - elem.addAttribute(new QName("type", namespaceXSI), "dcterms:W3CDTF"); - elem.addText(propsPart.getCreatedPropertyString()); - } - - /** - * Add creator property element if needed. - */ - private void addCreator() { - if (!propsPart.getCreatorProperty().hasValue()) - return; - - Element elem = xmlDoc.getRootElement().element( - new QName(KEYWORD_CREATOR, namespaceDC)); - if (elem == null) { - // missing, we add it - elem = xmlDoc.getRootElement().addElement( - new QName(KEYWORD_CREATOR, namespaceDC)); - } else { - elem.clearContent();// clear the old value - } - elem.addText(propsPart.getCreatorProperty().getValue()); - } - - /** - * Add description property element if needed. - */ - private void addDescription() { - if (!propsPart.getDescriptionProperty().hasValue()) - return; - - Element elem = xmlDoc.getRootElement().element( - new QName(KEYWORD_DESCRIPTION, namespaceDC)); - if (elem == null) { - // missing, we add it - elem = xmlDoc.getRootElement().addElement( - new QName(KEYWORD_DESCRIPTION, namespaceDC)); - } else { - elem.clearContent();// clear the old value - } - elem.addText(propsPart.getDescriptionProperty().getValue()); - } - - /** - * Add identifier property element if needed. - */ - private void addIdentifier() { - if (!propsPart.getIdentifierProperty().hasValue()) - return; - - Element elem = xmlDoc.getRootElement().element( - new QName(KEYWORD_IDENTIFIER, namespaceDC)); - if (elem == null) { - // missing, we add it - elem = xmlDoc.getRootElement().addElement( - new QName(KEYWORD_IDENTIFIER, namespaceDC)); - } else { - elem.clearContent();// clear the old value - } - elem.addText(propsPart.getIdentifierProperty().getValue()); - } - - /** - * Add keywords property element if needed. - */ - private void addKeywords() { - if (!propsPart.getKeywordsProperty().hasValue()) - return; - - Element elem = xmlDoc.getRootElement().element( - new QName(KEYWORD_KEYWORDS, namespaceCoreProperties)); - if (elem == null) { - // missing, we add it - elem = xmlDoc.getRootElement().addElement( - new QName(KEYWORD_KEYWORDS, namespaceCoreProperties)); - } else { - elem.clearContent();// clear the old value - } - elem.addText(propsPart.getKeywordsProperty().getValue()); - } - - /** - * Add language property element if needed. - */ - private void addLanguage() { - if (!propsPart.getLanguageProperty().hasValue()) - return; - - Element elem = xmlDoc.getRootElement().element( - new QName(KEYWORD_LANGUAGE, namespaceDC)); - if (elem == null) { - // missing, we add it - elem = xmlDoc.getRootElement().addElement( - new QName(KEYWORD_LANGUAGE, namespaceDC)); - } else { - elem.clearContent();// clear the old value - } - elem.addText(propsPart.getLanguageProperty().getValue()); - } - - /** - * Add 'last modified by' property if needed. - */ - private void addLastModifiedBy() { - if (!propsPart.getLastModifiedByProperty().hasValue()) - return; - - Element elem = xmlDoc.getRootElement().element( - new QName(KEYWORD_LAST_MODIFIED_BY, namespaceCoreProperties)); - if (elem == null) { - // missing, we add it - elem = xmlDoc.getRootElement() - .addElement( - new QName(KEYWORD_LAST_MODIFIED_BY, - namespaceCoreProperties)); - } else { - elem.clearContent();// clear the old value - } - elem.addText(propsPart.getLastModifiedByProperty().getValue()); - } - - /** - * Add 'last printed' property if needed. - * - */ - private void addLastPrinted() { - if (!propsPart.getLastPrintedProperty().hasValue()) - return; - - Element elem = xmlDoc.getRootElement().element( - new QName(KEYWORD_LAST_PRINTED, namespaceCoreProperties)); - if (elem == null) { - // missing, we add it - elem = xmlDoc.getRootElement().addElement( - new QName(KEYWORD_LAST_PRINTED, namespaceCoreProperties)); - } else { - elem.clearContent();// clear the old value - } - elem.addText(propsPart.getLastPrintedPropertyString()); - } - - /** - * Add modified property element if needed. - */ - private void addModified() { - if (!propsPart.getModifiedProperty().hasValue()) - return; - - Element elem = xmlDoc.getRootElement().element( - new QName(KEYWORD_MODIFIED, namespaceDcTerms)); - if (elem == null) { - // missing, we add it - elem = xmlDoc.getRootElement().addElement( - new QName(KEYWORD_MODIFIED, namespaceDcTerms)); - } else { - elem.clearContent();// clear the old value - } - elem.addAttribute(new QName("type", namespaceXSI), "dcterms:W3CDTF"); - elem.addText(propsPart.getModifiedPropertyString()); - } - - /** - * Add revision property if needed. - */ - private void addRevision() { - if (!propsPart.getRevisionProperty().hasValue()) - return; - - Element elem = xmlDoc.getRootElement().element( - new QName(KEYWORD_REVISION, namespaceCoreProperties)); - if (elem == null) { - // missing, we add it - elem = xmlDoc.getRootElement().addElement( - new QName(KEYWORD_REVISION, namespaceCoreProperties)); - } else { - elem.clearContent();// clear the old value - } - elem.addText(propsPart.getRevisionProperty().getValue()); - } - - /** - * Add subject property if needed. - */ - private void addSubject() { - if (!propsPart.getSubjectProperty().hasValue()) - return; - - Element elem = xmlDoc.getRootElement().element( - new QName(KEYWORD_SUBJECT, namespaceDC)); - if (elem == null) { - // missing, we add it - elem = xmlDoc.getRootElement().addElement( - new QName(KEYWORD_SUBJECT, namespaceDC)); - } else { - elem.clearContent();// clear the old value - } - elem.addText(propsPart.getSubjectProperty().getValue()); - } - - /** - * Add title property if needed. - */ - private void addTitle() { - if (!propsPart.getTitleProperty().hasValue()) - return; - - Element elem = xmlDoc.getRootElement().element( - new QName(KEYWORD_TITLE, namespaceDC)); - if (elem == null) { - // missing, we add it - elem = xmlDoc.getRootElement().addElement( - new QName(KEYWORD_TITLE, namespaceDC)); - } else { - elem.clearContent();// clear the old value - } - elem.addText(propsPart.getTitleProperty().getValue()); - } - - private void addVersion() { - if (!propsPart.getVersionProperty().hasValue()) - return; - - Element elem = xmlDoc.getRootElement().element( - new QName(KEYWORD_VERSION, namespaceCoreProperties)); - if (elem == null) { - // missing, we add it - elem = xmlDoc.getRootElement().addElement( - new QName(KEYWORD_VERSION, namespaceCoreProperties)); - } else { - elem.clearContent();// clear the old value - } - elem.addText(propsPart.getVersionProperty().getValue()); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc.internal.marshallers; + +import java.io.OutputStream; + +import org.dom4j.Document; +import org.dom4j.DocumentHelper; +import org.dom4j.Element; +import org.dom4j.Namespace; +import org.dom4j.QName; +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart; +import org.apache.poi.openxml4j.opc.internal.PartMarshaller; + +/** + * Package properties marshaller. + * + * @author CDubet, Julien Chable + */ +public class PackagePropertiesMarshaller implements PartMarshaller { + + private final static Namespace namespaceDC = new Namespace("dc", + PackagePropertiesPart.NAMESPACE_DC_URI); + + private final static Namespace namespaceCoreProperties = new Namespace("", + PackagePropertiesPart.NAMESPACE_CP_URI); + + private final static Namespace namespaceDcTerms = new Namespace("dcterms", + PackagePropertiesPart.NAMESPACE_DCTERMS_URI); + + private final static Namespace namespaceXSI = new Namespace("xsi", + PackagePropertiesPart.NAMESPACE_XSI_URI); + + protected static final String KEYWORD_CATEGORY = "category"; + + protected static final String KEYWORD_CONTENT_STATUS = "contentStatus"; + + protected static final String KEYWORD_CONTENT_TYPE = "contentType"; + + protected static final String KEYWORD_CREATED = "created"; + + protected static final String KEYWORD_CREATOR = "creator"; + + protected static final String KEYWORD_DESCRIPTION = "description"; + + protected static final String KEYWORD_IDENTIFIER = "identifier"; + + protected static final String KEYWORD_KEYWORDS = "keywords"; + + protected static final String KEYWORD_LANGUAGE = "language"; + + protected static final String KEYWORD_LAST_MODIFIED_BY = "lastModifiedBy"; + + protected static final String KEYWORD_LAST_PRINTED = "lastPrinted"; + + protected static final String KEYWORD_MODIFIED = "modified"; + + protected static final String KEYWORD_REVISION = "revision"; + + protected static final String KEYWORD_SUBJECT = "subject"; + + protected static final String KEYWORD_TITLE = "title"; + + protected static final String KEYWORD_VERSION = "version"; + + PackagePropertiesPart propsPart; + + // The document + Document xmlDoc = null; + + /** + * Marshall package core properties to an XML document. Always return + * true. + */ + public boolean marshall(PackagePart part, OutputStream out) + throws OpenXML4JException { + if (!(part instanceof PackagePropertiesPart)) + throw new IllegalArgumentException( + "'part' must be a PackagePropertiesPart instance."); + propsPart = (PackagePropertiesPart) part; + + // Configure the document + xmlDoc = DocumentHelper.createDocument(); + Element rootElem = xmlDoc.addElement(new QName("coreProperties", + namespaceCoreProperties)); + rootElem.addNamespace("cp", PackagePropertiesPart.NAMESPACE_CP_URI); + rootElem.addNamespace("dc", PackagePropertiesPart.NAMESPACE_DC_URI); + rootElem.addNamespace("dcterms", + PackagePropertiesPart.NAMESPACE_DCTERMS_URI); + rootElem.addNamespace("xsi", PackagePropertiesPart.NAMESPACE_XSI_URI); + + addCategory(); + addContentStatus(); + addContentType(); + addCreated(); + addCreator(); + addDescription(); + addIdentifier(); + addKeywords(); + addLanguage(); + addLastModifiedBy(); + addLastPrinted(); + addModified(); + addRevision(); + addSubject(); + addTitle(); + addVersion(); + return true; + } + + /** + * Add category property element if needed. + */ + private void addCategory() { + if (!propsPart.getCategoryProperty().hasValue()) + return; + + Element elem = xmlDoc.getRootElement().element( + new QName(KEYWORD_CATEGORY, namespaceCoreProperties)); + if (elem == null) { + // Missing, we add it + elem = xmlDoc.getRootElement().addElement( + new QName(KEYWORD_CATEGORY, namespaceCoreProperties)); + } else { + elem.clearContent();// clear the old value + } + elem.addText(propsPart.getCategoryProperty().getValue()); + } + + /** + * Add content status property element if needed. + */ + private void addContentStatus() { + if (!propsPart.getContentStatusProperty().hasValue()) + return; + + Element elem = xmlDoc.getRootElement().element( + new QName(KEYWORD_CONTENT_STATUS, namespaceCoreProperties)); + if (elem == null) { + // Missing, we add it + elem = xmlDoc.getRootElement().addElement( + new QName(KEYWORD_CONTENT_STATUS, namespaceCoreProperties)); + } else { + elem.clearContent();// clear the old value + } + elem.addText(propsPart.getContentStatusProperty().getValue()); + } + + /** + * Add content type property element if needed. + */ + private void addContentType() { + if (!propsPart.getContentTypeProperty().hasValue()) + return; + + Element elem = xmlDoc.getRootElement().element( + new QName(KEYWORD_CONTENT_TYPE, namespaceCoreProperties)); + if (elem == null) { + // Missing, we add it + elem = xmlDoc.getRootElement().addElement( + new QName(KEYWORD_CONTENT_TYPE, namespaceCoreProperties)); + } else { + elem.clearContent();// clear the old value + } + elem.addText(propsPart.getContentTypeProperty().getValue()); + } + + /** + * Add created property element if needed. + */ + private void addCreated() { + if (!propsPart.getCreatedProperty().hasValue()) + return; + + Element elem = xmlDoc.getRootElement().element( + new QName(KEYWORD_CREATED, namespaceDcTerms)); + if (elem == null) { + // missing, we add it + elem = xmlDoc.getRootElement().addElement( + new QName(KEYWORD_CREATED, namespaceDcTerms)); + } else { + elem.clearContent();// clear the old value + } + elem.addAttribute(new QName("type", namespaceXSI), "dcterms:W3CDTF"); + elem.addText(propsPart.getCreatedPropertyString()); + } + + /** + * Add creator property element if needed. + */ + private void addCreator() { + if (!propsPart.getCreatorProperty().hasValue()) + return; + + Element elem = xmlDoc.getRootElement().element( + new QName(KEYWORD_CREATOR, namespaceDC)); + if (elem == null) { + // missing, we add it + elem = xmlDoc.getRootElement().addElement( + new QName(KEYWORD_CREATOR, namespaceDC)); + } else { + elem.clearContent();// clear the old value + } + elem.addText(propsPart.getCreatorProperty().getValue()); + } + + /** + * Add description property element if needed. + */ + private void addDescription() { + if (!propsPart.getDescriptionProperty().hasValue()) + return; + + Element elem = xmlDoc.getRootElement().element( + new QName(KEYWORD_DESCRIPTION, namespaceDC)); + if (elem == null) { + // missing, we add it + elem = xmlDoc.getRootElement().addElement( + new QName(KEYWORD_DESCRIPTION, namespaceDC)); + } else { + elem.clearContent();// clear the old value + } + elem.addText(propsPart.getDescriptionProperty().getValue()); + } + + /** + * Add identifier property element if needed. + */ + private void addIdentifier() { + if (!propsPart.getIdentifierProperty().hasValue()) + return; + + Element elem = xmlDoc.getRootElement().element( + new QName(KEYWORD_IDENTIFIER, namespaceDC)); + if (elem == null) { + // missing, we add it + elem = xmlDoc.getRootElement().addElement( + new QName(KEYWORD_IDENTIFIER, namespaceDC)); + } else { + elem.clearContent();// clear the old value + } + elem.addText(propsPart.getIdentifierProperty().getValue()); + } + + /** + * Add keywords property element if needed. + */ + private void addKeywords() { + if (!propsPart.getKeywordsProperty().hasValue()) + return; + + Element elem = xmlDoc.getRootElement().element( + new QName(KEYWORD_KEYWORDS, namespaceCoreProperties)); + if (elem == null) { + // missing, we add it + elem = xmlDoc.getRootElement().addElement( + new QName(KEYWORD_KEYWORDS, namespaceCoreProperties)); + } else { + elem.clearContent();// clear the old value + } + elem.addText(propsPart.getKeywordsProperty().getValue()); + } + + /** + * Add language property element if needed. + */ + private void addLanguage() { + if (!propsPart.getLanguageProperty().hasValue()) + return; + + Element elem = xmlDoc.getRootElement().element( + new QName(KEYWORD_LANGUAGE, namespaceDC)); + if (elem == null) { + // missing, we add it + elem = xmlDoc.getRootElement().addElement( + new QName(KEYWORD_LANGUAGE, namespaceDC)); + } else { + elem.clearContent();// clear the old value + } + elem.addText(propsPart.getLanguageProperty().getValue()); + } + + /** + * Add 'last modified by' property if needed. + */ + private void addLastModifiedBy() { + if (!propsPart.getLastModifiedByProperty().hasValue()) + return; + + Element elem = xmlDoc.getRootElement().element( + new QName(KEYWORD_LAST_MODIFIED_BY, namespaceCoreProperties)); + if (elem == null) { + // missing, we add it + elem = xmlDoc.getRootElement() + .addElement( + new QName(KEYWORD_LAST_MODIFIED_BY, + namespaceCoreProperties)); + } else { + elem.clearContent();// clear the old value + } + elem.addText(propsPart.getLastModifiedByProperty().getValue()); + } + + /** + * Add 'last printed' property if needed. + * + */ + private void addLastPrinted() { + if (!propsPart.getLastPrintedProperty().hasValue()) + return; + + Element elem = xmlDoc.getRootElement().element( + new QName(KEYWORD_LAST_PRINTED, namespaceCoreProperties)); + if (elem == null) { + // missing, we add it + elem = xmlDoc.getRootElement().addElement( + new QName(KEYWORD_LAST_PRINTED, namespaceCoreProperties)); + } else { + elem.clearContent();// clear the old value + } + elem.addText(propsPart.getLastPrintedPropertyString()); + } + + /** + * Add modified property element if needed. + */ + private void addModified() { + if (!propsPart.getModifiedProperty().hasValue()) + return; + + Element elem = xmlDoc.getRootElement().element( + new QName(KEYWORD_MODIFIED, namespaceDcTerms)); + if (elem == null) { + // missing, we add it + elem = xmlDoc.getRootElement().addElement( + new QName(KEYWORD_MODIFIED, namespaceDcTerms)); + } else { + elem.clearContent();// clear the old value + } + elem.addAttribute(new QName("type", namespaceXSI), "dcterms:W3CDTF"); + elem.addText(propsPart.getModifiedPropertyString()); + } + + /** + * Add revision property if needed. + */ + private void addRevision() { + if (!propsPart.getRevisionProperty().hasValue()) + return; + + Element elem = xmlDoc.getRootElement().element( + new QName(KEYWORD_REVISION, namespaceCoreProperties)); + if (elem == null) { + // missing, we add it + elem = xmlDoc.getRootElement().addElement( + new QName(KEYWORD_REVISION, namespaceCoreProperties)); + } else { + elem.clearContent();// clear the old value + } + elem.addText(propsPart.getRevisionProperty().getValue()); + } + + /** + * Add subject property if needed. + */ + private void addSubject() { + if (!propsPart.getSubjectProperty().hasValue()) + return; + + Element elem = xmlDoc.getRootElement().element( + new QName(KEYWORD_SUBJECT, namespaceDC)); + if (elem == null) { + // missing, we add it + elem = xmlDoc.getRootElement().addElement( + new QName(KEYWORD_SUBJECT, namespaceDC)); + } else { + elem.clearContent();// clear the old value + } + elem.addText(propsPart.getSubjectProperty().getValue()); + } + + /** + * Add title property if needed. + */ + private void addTitle() { + if (!propsPart.getTitleProperty().hasValue()) + return; + + Element elem = xmlDoc.getRootElement().element( + new QName(KEYWORD_TITLE, namespaceDC)); + if (elem == null) { + // missing, we add it + elem = xmlDoc.getRootElement().addElement( + new QName(KEYWORD_TITLE, namespaceDC)); + } else { + elem.clearContent();// clear the old value + } + elem.addText(propsPart.getTitleProperty().getValue()); + } + + private void addVersion() { + if (!propsPart.getVersionProperty().hasValue()) + return; + + Element elem = xmlDoc.getRootElement().element( + new QName(KEYWORD_VERSION, namespaceCoreProperties)); + if (elem == null) { + // missing, we add it + elem = xmlDoc.getRootElement().addElement( + new QName(KEYWORD_VERSION, namespaceCoreProperties)); + } else { + elem.clearContent();// clear the old value + } + elem.addText(propsPart.getVersionProperty().getValue()); + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/ZipPackagePropertiesMarshaller.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/ZipPackagePropertiesMarshaller.java index 39e8fa3f3d..07123b22dc 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/ZipPackagePropertiesMarshaller.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/ZipPackagePropertiesMarshaller.java @@ -1,64 +1,63 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc.internal.marshallers; - -import java.io.IOException; -import java.io.OutputStream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -import org.apache.poi.openxml4j.exceptions.OpenXML4JException; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.StreamHelper; -import org.apache.poi.openxml4j.opc.internal.ZipHelper; - -/** - * Package core properties marshaller specialized for zipped package. - * - * @author Julien Chable - * @version 1.0 - */ -public class ZipPackagePropertiesMarshaller extends PackagePropertiesMarshaller { - - @Override - public boolean marshall(PackagePart part, OutputStream out) - throws OpenXML4JException { - if (!(out instanceof ZipOutputStream)) { - throw new IllegalArgumentException("ZipOutputStream expected!"); - } - ZipOutputStream zos = (ZipOutputStream) out; - - // Saving the part in the zip file - ZipEntry ctEntry = new ZipEntry(ZipHelper - .getZipItemNameFromOPCName(part.getPartName().getURI() - .toString())); - try { - // Save in ZIP - zos.putNextEntry(ctEntry); // Add entry in ZIP - super.marshall(part, out); // Marshall the properties inside a XML - // Document - if (!StreamHelper.saveXmlInStream(xmlDoc, out)) { - return false; - } - zos.closeEntry(); - } catch (IOException e) { - throw new OpenXML4JException(e.getLocalizedMessage()); - } - return true; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc.internal.marshallers; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.openxml4j.opc.StreamHelper; +import org.apache.poi.openxml4j.opc.internal.ZipHelper; + +/** + * Package core properties marshaller specialized for zipped package. + * + * @author Julien Chable + */ +public final class ZipPackagePropertiesMarshaller extends PackagePropertiesMarshaller { + + @Override + public boolean marshall(PackagePart part, OutputStream out) + throws OpenXML4JException { + if (!(out instanceof ZipOutputStream)) { + throw new IllegalArgumentException("ZipOutputStream expected!"); + } + ZipOutputStream zos = (ZipOutputStream) out; + + // Saving the part in the zip file + ZipEntry ctEntry = new ZipEntry(ZipHelper + .getZipItemNameFromOPCName(part.getPartName().getURI() + .toString())); + try { + // Save in ZIP + zos.putNextEntry(ctEntry); // Add entry in ZIP + super.marshall(part, out); // Marshall the properties inside a XML + // Document + if (!StreamHelper.saveXmlInStream(xmlDoc, out)) { + return false; + } + zos.closeEntry(); + } catch (IOException e) { + throw new OpenXML4JException(e.getLocalizedMessage()); + } + return true; + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/ZipPartMarshaller.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/ZipPartMarshaller.java index c226ba5a42..b59a78b74c 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/ZipPartMarshaller.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/ZipPartMarshaller.java @@ -1,193 +1,191 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc.internal.marshallers; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.URI; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -import org.dom4j.Document; -import org.dom4j.DocumentHelper; -import org.dom4j.Element; -import org.dom4j.Namespace; -import org.dom4j.QName; -import org.apache.poi.openxml4j.exceptions.OpenXML4JException; -import org.apache.poi.openxml4j.opc.PackageNamespaces; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.PackagePartName; -import org.apache.poi.openxml4j.opc.PackageRelationship; -import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; -import org.apache.poi.openxml4j.opc.PackagingURIHelper; -import org.apache.poi.openxml4j.opc.StreamHelper; -import org.apache.poi.openxml4j.opc.TargetMode; -import org.apache.poi.openxml4j.opc.internal.PartMarshaller; -import org.apache.poi.openxml4j.opc.internal.ZipHelper; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.POILogFactory; - -/** - * Zip part marshaller. This marshaller is use to save any part in a zip stream. - * - * @author Julien Chable - * @version 0.1 - */ -public class ZipPartMarshaller implements PartMarshaller { - private static POILogger logger = POILogFactory.getLogger(ZipPartMarshaller.class); - - /** - * Save the specified part. - * - * @throws OpenXML4JException - * Throws if an internal exception is thrown. - */ - public boolean marshall(PackagePart part, OutputStream os) - throws OpenXML4JException { - if (!(os instanceof ZipOutputStream)) { - logger.log(POILogger.ERROR,"Unexpected class " + os.getClass().getName()); - throw new OpenXML4JException("ZipOutputStream expected !"); - // Normally should happen only in developpement phase, so just throw - // exception - } - - ZipOutputStream zos = (ZipOutputStream) os; - ZipEntry partEntry = new ZipEntry(ZipHelper - .getZipItemNameFromOPCName(part.getPartName().getURI() - .getPath())); - try { - // Create next zip entry - zos.putNextEntry(partEntry); - - // Saving data in the ZIP file - InputStream ins = part.getInputStream(); - byte[] buff = new byte[ZipHelper.READ_WRITE_FILE_BUFFER_SIZE]; - while (ins.available() > 0) { - int resultRead = ins.read(buff); - if (resultRead == -1) { - // End of file reached - break; - } else { - zos.write(buff, 0, resultRead); - } - } - zos.closeEntry(); - } catch (IOException ioe) { - logger.log(POILogger.ERROR,"Cannot write: " + part.getPartName() + ": in ZIP", - ioe); - return false; - } - - // Saving relationship part - if (part.hasRelationships()) { - PackagePartName relationshipPartName = PackagingURIHelper - .getRelationshipPartName(part.getPartName()); - - marshallRelationshipPart(part.getRelationships(), - relationshipPartName, zos); - - } - return true; - } - - /** - * Save relationships into the part. - * - * @param rels - * The relationships collection to marshall. - * @param relPartName - * Part name of the relationship part to marshall. - * @param zos - * Zip output stream in which to save the XML content of the - * relationships serialization. - */ - public static boolean marshallRelationshipPart( - PackageRelationshipCollection rels, PackagePartName relPartName, - ZipOutputStream zos) { - // Building xml - Document xmlOutDoc = DocumentHelper.createDocument(); - // make something like - Namespace dfNs = Namespace.get("", PackageNamespaces.RELATIONSHIPS); - Element root = xmlOutDoc.addElement(new QName( - PackageRelationship.RELATIONSHIPS_TAG_NAME, dfNs)); - - // - - URI sourcePartURI = PackagingURIHelper - .getSourcePartUriFromRelationshipPartUri(relPartName.getURI()); - - for (PackageRelationship rel : rels) { - // the relationship element - Element relElem = root - .addElement(PackageRelationship.RELATIONSHIP_TAG_NAME); - - // the relationship ID - relElem.addAttribute(PackageRelationship.ID_ATTRIBUTE_NAME, rel - .getId()); - - // the relationship Type - relElem.addAttribute(PackageRelationship.TYPE_ATTRIBUTE_NAME, rel - .getRelationshipType()); - - // the relationship Target - String targetValue; - URI uri = rel.getTargetURI(); - if (rel.getTargetMode() == TargetMode.EXTERNAL) { - // Save the target as-is - we don't need to validate it, - // alter it etc - targetValue = uri.toString(); - - // add TargetMode attribute (as it is external link external) - relElem.addAttribute( - PackageRelationship.TARGET_MODE_ATTRIBUTE_NAME, - "External"); - } else { - targetValue = PackagingURIHelper.relativizeURI( - sourcePartURI, rel.getTargetURI()).getPath(); - } - relElem.addAttribute(PackageRelationship.TARGET_ATTRIBUTE_NAME, - targetValue); - } - - xmlOutDoc.normalize(); - - // String schemaFilename = Configuration.getPathForXmlSchema()+ - // File.separator + "opc-relationships.xsd"; - - // Save part in zip - ZipEntry ctEntry = new ZipEntry(ZipHelper.getZipURIFromOPCName( - relPartName.getURI().toASCIIString()).getPath()); - try { - zos.putNextEntry(ctEntry); - if (!StreamHelper.saveXmlInStream(xmlOutDoc, zos)) { - return false; - } - zos.closeEntry(); - } catch (IOException e) { - logger.log(POILogger.ERROR,"Cannot create zip entry " + relPartName, e); - return false; - } - return true; // success - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc.internal.marshallers; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import org.dom4j.Document; +import org.dom4j.DocumentHelper; +import org.dom4j.Element; +import org.dom4j.Namespace; +import org.dom4j.QName; +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.openxml4j.opc.PackageNamespaces; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.openxml4j.opc.PackagePartName; +import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; +import org.apache.poi.openxml4j.opc.PackagingURIHelper; +import org.apache.poi.openxml4j.opc.StreamHelper; +import org.apache.poi.openxml4j.opc.TargetMode; +import org.apache.poi.openxml4j.opc.internal.PartMarshaller; +import org.apache.poi.openxml4j.opc.internal.ZipHelper; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.POILogFactory; + +/** + * Zip part marshaller. This marshaller is use to save any part in a zip stream. + * + * @author Julien Chable + */ +public final class ZipPartMarshaller implements PartMarshaller { + private static POILogger logger = POILogFactory.getLogger(ZipPartMarshaller.class); + + /** + * Save the specified part. + * + * @throws OpenXML4JException + * Throws if an internal exception is thrown. + */ + public boolean marshall(PackagePart part, OutputStream os) + throws OpenXML4JException { + if (!(os instanceof ZipOutputStream)) { + logger.log(POILogger.ERROR,"Unexpected class " + os.getClass().getName()); + throw new OpenXML4JException("ZipOutputStream expected !"); + // Normally should happen only in developement phase, so just throw + // exception + } + + ZipOutputStream zos = (ZipOutputStream) os; + ZipEntry partEntry = new ZipEntry(ZipHelper + .getZipItemNameFromOPCName(part.getPartName().getURI() + .getPath())); + try { + // Create next zip entry + zos.putNextEntry(partEntry); + + // Saving data in the ZIP file + InputStream ins = part.getInputStream(); + byte[] buff = new byte[ZipHelper.READ_WRITE_FILE_BUFFER_SIZE]; + while (ins.available() > 0) { + int resultRead = ins.read(buff); + if (resultRead == -1) { + // End of file reached + break; + } + zos.write(buff, 0, resultRead); + } + zos.closeEntry(); + } catch (IOException ioe) { + logger.log(POILogger.ERROR,"Cannot write: " + part.getPartName() + ": in ZIP", + ioe); + return false; + } + + // Saving relationship part + if (part.hasRelationships()) { + PackagePartName relationshipPartName = PackagingURIHelper + .getRelationshipPartName(part.getPartName()); + + marshallRelationshipPart(part.getRelationships(), + relationshipPartName, zos); + + } + return true; + } + + /** + * Save relationships into the part. + * + * @param rels + * The relationships collection to marshall. + * @param relPartName + * Part name of the relationship part to marshall. + * @param zos + * Zip output stream in which to save the XML content of the + * relationships serialization. + */ + public static boolean marshallRelationshipPart( + PackageRelationshipCollection rels, PackagePartName relPartName, + ZipOutputStream zos) { + // Building xml + Document xmlOutDoc = DocumentHelper.createDocument(); + // make something like + Namespace dfNs = Namespace.get("", PackageNamespaces.RELATIONSHIPS); + Element root = xmlOutDoc.addElement(new QName( + PackageRelationship.RELATIONSHIPS_TAG_NAME, dfNs)); + + // + + URI sourcePartURI = PackagingURIHelper + .getSourcePartUriFromRelationshipPartUri(relPartName.getURI()); + + for (PackageRelationship rel : rels) { + // the relationship element + Element relElem = root + .addElement(PackageRelationship.RELATIONSHIP_TAG_NAME); + + // the relationship ID + relElem.addAttribute(PackageRelationship.ID_ATTRIBUTE_NAME, rel + .getId()); + + // the relationship Type + relElem.addAttribute(PackageRelationship.TYPE_ATTRIBUTE_NAME, rel + .getRelationshipType()); + + // the relationship Target + String targetValue; + URI uri = rel.getTargetURI(); + if (rel.getTargetMode() == TargetMode.EXTERNAL) { + // Save the target as-is - we don't need to validate it, + // alter it etc + targetValue = uri.toString(); + + // add TargetMode attribute (as it is external link external) + relElem.addAttribute( + PackageRelationship.TARGET_MODE_ATTRIBUTE_NAME, + "External"); + } else { + targetValue = PackagingURIHelper.relativizeURI( + sourcePartURI, rel.getTargetURI()).getPath(); + } + relElem.addAttribute(PackageRelationship.TARGET_ATTRIBUTE_NAME, + targetValue); + } + + xmlOutDoc.normalize(); + + // String schemaFilename = Configuration.getPathForXmlSchema()+ + // File.separator + "opc-relationships.xsd"; + + // Save part in zip + ZipEntry ctEntry = new ZipEntry(ZipHelper.getZipURIFromOPCName( + relPartName.getURI().toASCIIString()).getPath()); + try { + zos.putNextEntry(ctEntry); + if (!StreamHelper.saveXmlInStream(xmlOutDoc, zos)) { + return false; + } + zos.closeEntry(); + } catch (IOException e) { + logger.log(POILogger.ERROR,"Cannot create zip entry " + relPartName, e); + return false; + } + return true; // success + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/signature/DigitalCertificatePart.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/signature/DigitalCertificatePart.java index bce033e3e3..19ba500f2e 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/signature/DigitalCertificatePart.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/signature/DigitalCertificatePart.java @@ -1,78 +1,78 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc.internal.signature; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.exceptions.OpenXML4JException; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.internal.ContentType; - -/** - * Digital certificate part. - * - * @author Julien Chable - * @version 0.1 - */ -public final class DigitalCertificatePart extends PackagePart { - - public DigitalCertificatePart() throws InvalidFormatException{ - super(null, null, new ContentType("")); - // Review constructor - } - - @Override - public void close() { - // TODO Auto-generated method stub - - } - - @Override - public void flush() { - // TODO Auto-generated method stub - - } - - @Override - protected InputStream getInputStreamImpl() throws IOException { - // TODO Auto-generated method stub - return null; - } - - @Override - protected OutputStream getOutputStreamImpl() { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean load(InputStream ios) throws InvalidFormatException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean save(OutputStream zos) throws OpenXML4JException { - // TODO Auto-generated method stub - return false; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc.internal.signature; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.openxml4j.opc.internal.ContentType; + +/** + * Digital certificate part. + * + * @author Julien Chable + * @version 0.1 + */ +public final class DigitalCertificatePart extends PackagePart { + + public DigitalCertificatePart() throws InvalidFormatException{ + super(null, null, new ContentType("")); + // Review constructor + } + + @Override + public void close() { + // TODO Auto-generated method stub + + } + + @Override + public void flush() { + // TODO Auto-generated method stub + + } + + @Override + protected InputStream getInputStreamImpl() throws IOException { + // TODO Auto-generated method stub + return null; + } + + @Override + protected OutputStream getOutputStreamImpl() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean load(InputStream ios) throws InvalidFormatException { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean save(OutputStream zos) throws OpenXML4JException { + // TODO Auto-generated method stub + return false; + } + +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/signature/DigitalSignatureOriginPart.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/signature/DigitalSignatureOriginPart.java index 718e78b765..b6c1a8ac87 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/signature/DigitalSignatureOriginPart.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/signature/DigitalSignatureOriginPart.java @@ -1,28 +1,28 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc.internal.signature; - -/** - * Represents a digital signature origin part. - * - * @author Julien Chable - * @version 0.1 - */ -public class DigitalSignatureOriginPart { - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc.internal.signature; + +/** + * Represents a digital signature origin part. + * + * @author Julien Chable + * @version 0.1 + */ +public final class DigitalSignatureOriginPart { + +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/unmarshallers/PackagePropertiesUnmarshaller.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/unmarshallers/PackagePropertiesUnmarshaller.java index fc03b022ff..a86f56d0af 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/unmarshallers/PackagePropertiesUnmarshaller.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/unmarshallers/PackagePropertiesUnmarshaller.java @@ -1,391 +1,393 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc.internal.unmarshallers; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Iterator; -import java.util.List; -import java.util.zip.ZipEntry; - -import org.dom4j.Attribute; -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.Element; -import org.dom4j.Namespace; -import org.dom4j.QName; -import org.dom4j.io.SAXReader; -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.exceptions.OpenXML4JException; -import org.apache.poi.openxml4j.opc.PackageNamespaces; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.PackageProperties; -import org.apache.poi.openxml4j.opc.ZipPackage; -import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart; -import org.apache.poi.openxml4j.opc.internal.PartUnmarshaller; -import org.apache.poi.openxml4j.opc.internal.ZipHelper; - -/** - * Package properties unmarshaller. - * - * @author Julien Chable - * @version 1.0 - */ -public class PackagePropertiesUnmarshaller implements PartUnmarshaller { - - private final static Namespace namespaceDC = new Namespace("dc", - PackageProperties.NAMESPACE_DC); - - private final static Namespace namespaceCP = new Namespace("cp", - PackageNamespaces.CORE_PROPERTIES); - - private final static Namespace namespaceDcTerms = new Namespace("dcterms", - PackageProperties.NAMESPACE_DCTERMS); - - private final static Namespace namespaceXML = new Namespace("xml", - "http://www.w3.org/XML/1998/namespace"); - - private final static Namespace namespaceXSI = new Namespace("xsi", - "http://www.w3.org/2001/XMLSchema-instance"); - - protected static final String KEYWORD_CATEGORY = "category"; - - protected static final String KEYWORD_CONTENT_STATUS = "contentStatus"; - - protected static final String KEYWORD_CONTENT_TYPE = "contentType"; - - protected static final String KEYWORD_CREATED = "created"; - - protected static final String KEYWORD_CREATOR = "creator"; - - protected static final String KEYWORD_DESCRIPTION = "description"; - - protected static final String KEYWORD_IDENTIFIER = "identifier"; - - protected static final String KEYWORD_KEYWORDS = "keywords"; - - protected static final String KEYWORD_LANGUAGE = "language"; - - protected static final String KEYWORD_LAST_MODIFIED_BY = "lastModifiedBy"; - - protected static final String KEYWORD_LAST_PRINTED = "lastPrinted"; - - protected static final String KEYWORD_MODIFIED = "modified"; - - protected static final String KEYWORD_REVISION = "revision"; - - protected static final String KEYWORD_SUBJECT = "subject"; - - protected static final String KEYWORD_TITLE = "title"; - - protected static final String KEYWORD_VERSION = "version"; - - // TODO Load element with XMLBeans or dynamic table - // TODO Check every element/namespace for compliance - public PackagePart unmarshall(UnmarshallContext context, InputStream in) - throws InvalidFormatException, IOException { - PackagePropertiesPart coreProps = new PackagePropertiesPart(context - .getPackage(), context.getPartName()); - - // If the input stream is null then we try to get it from the - // package. - if (in == null) { - if (context.getZipEntry() != null) { - in = ((ZipPackage) context.getPackage()).getZipArchive() - .getInputStream(context.getZipEntry()); - } else if (context.getPackage() != null) { - // Try to retrieve the part inputstream from the URI - ZipEntry zipEntry; - try { - zipEntry = ZipHelper - .getCorePropertiesZipEntry((ZipPackage) context - .getPackage()); - } catch (OpenXML4JException e) { - throw new IOException( - "Error while trying to get the part input stream."); - } - in = ((ZipPackage) context.getPackage()).getZipArchive() - .getInputStream(zipEntry); - } else - throw new IOException( - "Error while trying to get the part input stream."); - } - - SAXReader xmlReader = new SAXReader(); - Document xmlDoc; - try { - xmlDoc = xmlReader.read(in); - - /* Check OPC compliance */ - - // Rule M4.2, M4.3, M4.4 and M4.5/ - checkElementForOPCCompliance(xmlDoc.getRootElement()); - - /* End OPC compliance */ - - } catch (DocumentException e) { - throw new IOException(e.getMessage()); - } - - coreProps.setCategoryProperty(loadCategory(xmlDoc)); - coreProps.setContentStatusProperty(loadContentStatus(xmlDoc)); - coreProps.setContentTypeProperty(loadContentType(xmlDoc)); - coreProps.setCreatedProperty(loadCreated(xmlDoc)); - coreProps.setCreatorProperty(loadCreator(xmlDoc)); - coreProps.setDescriptionProperty(loadDescription(xmlDoc)); - coreProps.setIdentifierProperty(loadIdentifier(xmlDoc)); - coreProps.setKeywordsProperty(loadKeywords(xmlDoc)); - coreProps.setLanguageProperty(loadLanguage(xmlDoc)); - coreProps.setLastModifiedByProperty(loadLastModifiedBy(xmlDoc)); - coreProps.setLastPrintedProperty(loadLastPrinted(xmlDoc)); - coreProps.setModifiedProperty(loadModified(xmlDoc)); - coreProps.setRevisionProperty(loadRevision(xmlDoc)); - coreProps.setSubjectProperty(loadSubject(xmlDoc)); - coreProps.setTitleProperty(loadTitle(xmlDoc)); - coreProps.setVersionProperty(loadVersion(xmlDoc)); - - return coreProps; - } - - private String loadCategory(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_CATEGORY, namespaceCP)); - if (el != null) - return el.getStringValue(); - else - return null; - } - - private String loadContentStatus(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_CONTENT_STATUS, namespaceCP)); - if (el != null) - return el.getStringValue(); - else - return null; - } - - private String loadContentType(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_CONTENT_TYPE, namespaceCP)); - if (el != null) - return el.getStringValue(); - else - return null; - } - - private String loadCreated(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_CREATED, namespaceDcTerms)); - if (el != null) - return el.getStringValue(); - else - return null; - } - - private String loadCreator(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_CREATOR, namespaceDC)); - if (el != null) - return el.getStringValue(); - else - return null; - } - - private String loadDescription(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_DESCRIPTION, namespaceDC)); - if (el != null) - return el.getStringValue(); - else - return null; - } - - private String loadIdentifier(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_IDENTIFIER, namespaceDC)); - if (el != null) - return el.getStringValue(); - else - return null; - } - - private String loadKeywords(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_KEYWORDS, namespaceCP)); - if (el != null) - return el.getStringValue(); - else - return null; - } - - private String loadLanguage(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_LANGUAGE, namespaceDC)); - if (el != null) - return el.getStringValue(); - else - return null; - } - - private String loadLastModifiedBy(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_LAST_MODIFIED_BY, namespaceCP)); - if (el != null) - return el.getStringValue(); - else - return null; - } - - private String loadLastPrinted(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_LAST_PRINTED, namespaceCP)); - if (el != null) - return el.getStringValue(); - else - return null; - } - - private String loadModified(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_MODIFIED, namespaceDcTerms)); - if (el != null) - return el.getStringValue(); - else - return null; - } - - private String loadRevision(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_REVISION, namespaceCP)); - if (el != null) - return el.getStringValue(); - else - return null; - } - - private String loadSubject(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_SUBJECT, namespaceDC)); - if (el != null) - return el.getStringValue(); - else - return null; - } - - private String loadTitle(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_TITLE, namespaceDC)); - if (el != null) - return el.getStringValue(); - else - return null; - } - - private String loadVersion(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_VERSION, namespaceCP)); - if (el != null) - return el.getStringValue(); - else - return null; - } - - /* OPC Compliance methods */ - - /** - * Check the element for the following OPC compliance rules: - *

- * Rule M4.2: A format consumer shall consider the use of the Markup - * Compatibility namespace to be an error. - *

- * Rule M4.3: Producers shall not create a document element that contains - * refinements to the Dublin Core elements, except for the two specified in - * the schema: and Consumers shall - * consider a document element that violates this constraint to be an error. - *

- * Rule M4.4: Producers shall not create a document element that contains - * the xml:lang attribute. Consumers shall consider a document element that - * violates this constraint to be an error. - *

- * Rule M4.5: Producers shall not create a document element that contains - * the xsi:type attribute, except for a or - * element where the xsi:type attribute shall be present - * and shall hold the value dcterms:W3CDTF, where dcterms is the namespace - * prefix of the Dublin Core namespace. Consumers shall consider a document - * element that violates this constraint to be an error. - *

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

+ * Rule M4.2: A format consumer shall consider the use of the Markup + * Compatibility namespace to be an error. + *

+ * Rule M4.3: Producers shall not create a document element that contains + * refinements to the Dublin Core elements, except for the two specified in + * the schema: and Consumers shall + * consider a document element that violates this constraint to be an error. + *

+ * Rule M4.4: Producers shall not create a document element that contains + * the xml:lang attribute. Consumers shall consider a document element that + * violates this constraint to be an error. + *

+ * Rule M4.5: Producers shall not create a document element that contains + * the xsi:type attribute, except for a or + * element where the xsi:type attribute shall be present + * and shall hold the value dcterms:W3CDTF, where dcterms is the namespace + * prefix of the Dublin Core namespace. Consumers shall consider a document + * element that violates this constraint to be an error. + *

+ */ + public void checkElementForOPCCompliance(Element el) + throws InvalidFormatException { + // Check the current element + @SuppressWarnings("unchecked") + List declaredNamespaces = el.declaredNamespaces(); + Iterator itNS = declaredNamespaces.iterator(); + while (itNS.hasNext()) { + Namespace ns = itNS.next(); + + // Rule M4.2 + if (ns.getURI().equals(PackageNamespaces.MARKUP_COMPATIBILITY)) + throw new InvalidFormatException( + "OPC Compliance error [M4.2]: A format consumer shall consider the use of the Markup Compatibility namespace to be an error."); + } + + // Rule M4.3 + if (el.getNamespace().getURI().equals( + PackageProperties.NAMESPACE_DCTERMS) + && !(el.getName().equals(KEYWORD_CREATED) || el.getName() + .equals(KEYWORD_MODIFIED))) + throw new InvalidFormatException( + "OPC Compliance error [M4.3]: Producers shall not create a document element that contains refinements to the Dublin Core elements, except for the two specified in the schema: and Consumers shall consider a document element that violates this constraint to be an error."); + + // Rule M4.4 + if (el.attribute(new QName("lang", namespaceXML)) != null) + throw new InvalidFormatException( + "OPC Compliance error [M4.4]: Producers shall not create a document element that contains the xml:lang attribute. Consumers shall consider a document element that violates this constraint to be an error."); + + // Rule M4.5 + if (el.getNamespace().getURI().equals( + PackageProperties.NAMESPACE_DCTERMS)) { + // DCTerms namespace only use with 'created' and 'modified' elements + String elName = el.getName(); + if (!(elName.equals(KEYWORD_CREATED) || elName + .equals(KEYWORD_MODIFIED))) + throw new InvalidFormatException("Namespace error : " + elName + + " shouldn't have the following naemspace -> " + + PackageProperties.NAMESPACE_DCTERMS); + + // Check for the 'xsi:type' attribute + Attribute typeAtt = el.attribute(new QName("type", namespaceXSI)); + if (typeAtt == null) + throw new InvalidFormatException("The element '" + elName + + "' must have the '" + namespaceXSI.getPrefix() + + ":type' attribute present !"); + + // Check for the attribute value => 'dcterms:W3CDTF' + if (!typeAtt.getValue().equals("dcterms:W3CDTF")) + throw new InvalidFormatException("The element '" + elName + + "' must have the '" + namespaceXSI.getPrefix() + + ":type' attribute with the value 'dcterms:W3CDTF' !"); + } + + // Check its children + @SuppressWarnings("unchecked") + Iterator itChildren = el.elementIterator(); + while (itChildren.hasNext()) + checkElementForOPCCompliance(itChildren.next()); + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/signature/PackageDigitalSignature.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/signature/PackageDigitalSignature.java index 8922641ce6..c7a9b8f7ea 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/signature/PackageDigitalSignature.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/signature/PackageDigitalSignature.java @@ -1,70 +1,70 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc.signature; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.exceptions.OpenXML4JException; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.internal.ContentType; - -public class PackageDigitalSignature extends PackagePart { - - public PackageDigitalSignature() throws InvalidFormatException { - super(null, null, new ContentType("")); - } - - @Override - public void close() { - // TODO Auto-generated method stub - - } - - @Override - public void flush() { - // TODO Auto-generated method stub - - } - - @Override - protected InputStream getInputStreamImpl() throws IOException { - // TODO Auto-generated method stub - return null; - } - - @Override - protected OutputStream getOutputStreamImpl() { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean load(InputStream ios) throws InvalidFormatException { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean save(OutputStream zos) throws OpenXML4JException { - // TODO Auto-generated method stub - return false; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc.signature; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.openxml4j.opc.internal.ContentType; + +public final class PackageDigitalSignature extends PackagePart { + + public PackageDigitalSignature() throws InvalidFormatException { + super(null, null, new ContentType("")); + } + + @Override + public void close() { + // TODO Auto-generated method stub + + } + + @Override + public void flush() { + // TODO Auto-generated method stub + + } + + @Override + protected InputStream getInputStreamImpl() throws IOException { + // TODO Auto-generated method stub + return null; + } + + @Override + protected OutputStream getOutputStreamImpl() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean load(InputStream ios) throws InvalidFormatException { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean save(OutputStream zos) throws OpenXML4JException { + // TODO Auto-generated method stub + return false; + } +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/signature/PackageDigitalSignatureManager.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/signature/PackageDigitalSignatureManager.java index 0e5136d3ac..64007f6f00 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/signature/PackageDigitalSignatureManager.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/signature/PackageDigitalSignatureManager.java @@ -1,22 +1,22 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.openxml4j.opc.signature; - -public class PackageDigitalSignatureManager { - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.opc.signature; + +public final class PackageDigitalSignatureManager { + +} diff --git a/src/ooxml/java/org/apache/poi/openxml4j/util/Nullable.java b/src/ooxml/java/org/apache/poi/openxml4j/util/Nullable.java index 9bcea2e3ce..8c1a24c863 100755 --- a/src/ooxml/java/org/apache/poi/openxml4j/util/Nullable.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/util/Nullable.java @@ -1,71 +1,72 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.openxml4j.util; - -/** - * An immutable object that could be defined as null. - * - * @author Julien Chable - * @version 0.9 - */ -public final class Nullable { - - private E value; - - /** - * Constructor. - */ - public Nullable() { - // Do nothing - } - - /** - * Constructor. - * - * @param value - * The value to set to this nullable. - */ - public Nullable(E value) { - this.value = value; - } - - /** - * Get the store value if any. - * - * @return the store value - */ - public E getValue() { - return value; - } - - /** - * Get the status of this nullable. - * - * @return true if the nullable store a value (empty string is - * considered to be a value) else false. - */ - public boolean hasValue() { - return value != null; - } - - /** - * Set the stored value to null. - */ - public void nullify() { - value = null; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.util; + +/** + * An immutable object that could be defined as null. + * + * @author Julien Chable + * @version 0.9 + */ +public final class Nullable { + + private E value; + + /** + * Constructor. + */ + public Nullable() { + // Do nothing + } + + /** + * Constructor. + * + * @param value + * The value to set to this nullable. + */ + public Nullable(E value) { + this.value = value; + } + + /** + * Get the store value if any. + * + * @return the store value + */ + public E getValue() { + return value; + } + + /** + * Get the status of this nullable. + * + * @return true if the nullable store a value (empty string is + * considered to be a value) else false. + */ + public boolean hasValue() { + return value != null; + } + + /** + * Set the stored value to null. + */ + public void nullify() { + value = null; + } +} diff --git a/src/ooxml/java/org/apache/poi/xssf/dev/XSSFDump.java b/src/ooxml/java/org/apache/poi/xssf/dev/XSSFDump.java index 30a800e531..af1d55a960 100755 --- a/src/ooxml/java/org/apache/poi/xssf/dev/XSSFDump.java +++ b/src/ooxml/java/org/apache/poi/xssf/dev/XSSFDump.java @@ -1,90 +1,91 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xssf.dev; - -import org.apache.xmlbeans.XmlObject; -import org.apache.xmlbeans.XmlOptions; - -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.DocumentBuilder; -import java.io.*; -import java.util.zip.ZipFile; -import java.util.zip.ZipEntry; -import java.util.Enumeration; - -/** - * Utility class which dumps the contents of a *.xlsx file into file system. - * - * @author Yegor Kozlov - */ -public class XSSFDump { - - public static void main(String[] args) throws Exception { - for (int i = 0; i < args.length; i++) { - System.out.println("Dumping " + args[i]); - ZipFile zip = new ZipFile(args[i]); - dump(zip); - } - } - - public static void dump(ZipFile zip) throws Exception { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - - String zipname = zip.getName(); - int sep = zipname.lastIndexOf('.'); - File root = new File(zipname.substring(0, sep)); - root.mkdir(); - - Enumeration en = zip.entries(); - while(en.hasMoreElements()){ - ZipEntry entry = (ZipEntry)en.nextElement(); - String name = entry.getName(); - int idx = name.lastIndexOf('/'); - if(idx != -1){ - File bs = new File(root, name.substring(0, idx)); - bs.mkdirs(); - } - - File f = new File(root, entry.getName()); - FileOutputStream out = new FileOutputStream(f); - - if(entry.getName().endsWith(".xml") || entry.getName().endsWith(".vml") || entry.getName().endsWith(".rels")){ - try { - XmlObject xml = XmlObject.Factory.parse(zip.getInputStream(entry)); - XmlOptions options = new XmlOptions(); - options.setSavePrettyPrint(); - xml.save(out, options); - } catch (Exception e){ - System.err.println("Failed to parse " + entry.getName() + ", dumping raw content"); - dump(zip.getInputStream(entry), out); - } - } else { - dump(zip.getInputStream(entry), out); - } - out.close(); - - } - } - - protected static void dump(InputStream is, OutputStream out) throws IOException{ - int pos; - byte[] chunk = new byte[2048]; - while((pos = is.read(chunk)) > 0) out.write(chunk, 0, pos); - - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xssf.dev; + +import org.apache.xmlbeans.XmlObject; +import org.apache.xmlbeans.XmlOptions; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.DocumentBuilder; +import java.io.*; +import java.util.zip.ZipFile; +import java.util.zip.ZipEntry; +import java.util.Enumeration; + +/** + * Utility class which dumps the contents of a *.xlsx file into file system. + * + * @author Yegor Kozlov + */ +public final class XSSFDump { + + public static void main(String[] args) throws Exception { + for (int i = 0; i < args.length; i++) { + System.out.println("Dumping " + args[i]); + ZipFile zip = new ZipFile(args[i]); + dump(zip); + } + } + + public static void dump(ZipFile zip) throws Exception { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + + String zipname = zip.getName(); + int sep = zipname.lastIndexOf('.'); + File root = new File(zipname.substring(0, sep)); + root.mkdir(); + + Enumeration en = zip.entries(); + while(en.hasMoreElements()){ + ZipEntry entry = (ZipEntry)en.nextElement(); + String name = entry.getName(); + int idx = name.lastIndexOf('/'); + if(idx != -1){ + File bs = new File(root, name.substring(0, idx)); + bs.mkdirs(); + } + + File f = new File(root, entry.getName()); + FileOutputStream out = new FileOutputStream(f); + + if(entry.getName().endsWith(".xml") || entry.getName().endsWith(".vml") || entry.getName().endsWith(".rels")){ + try { + XmlObject xml = XmlObject.Factory.parse(zip.getInputStream(entry)); + XmlOptions options = new XmlOptions(); + options.setSavePrettyPrint(); + xml.save(out, options); + } catch (Exception e){ + System.err.println("Failed to parse " + entry.getName() + ", dumping raw content"); + dump(zip.getInputStream(entry), out); + } + } else { + dump(zip.getInputStream(entry), out); + } + out.close(); + + } + } + + protected static void dump(InputStream is, OutputStream out) throws IOException{ + int pos; + byte[] chunk = new byte[2048]; + while((pos = is.read(chunk)) > 0) out.write(chunk, 0, pos); + + } +} diff --git a/src/ooxml/java/org/apache/poi/xssf/dev/XSSFSave.java b/src/ooxml/java/org/apache/poi/xssf/dev/XSSFSave.java index 10a4b4755e..4b2fc3ca53 100755 --- a/src/ooxml/java/org/apache/poi/xssf/dev/XSSFSave.java +++ b/src/ooxml/java/org/apache/poi/xssf/dev/XSSFSave.java @@ -1,42 +1,43 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xssf.dev; - -import org.apache.poi.xssf.usermodel.XSSFWorkbook; - -import java.io.FileOutputStream; - -/** - * Utility which loads a SpreadsheetML file and saves it back. - * This is a handy tool to investigate read-write round trip safety. - * - * @author Yegor Kozlov - */ -public class XSSFSave { - public static void main(String[] args) throws Exception { - for (int i = 0; i < args.length; i++) { - XSSFWorkbook wb = new XSSFWorkbook(args[i]); - - int sep = args[i].lastIndexOf('.'); - String outfile = args[i].substring(0, sep) + "-save.xls" + (wb.isMacroEnabled() ? "m" : "x"); - FileOutputStream out = new FileOutputStream(outfile); - wb.write(out); - out.close(); - } - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xssf.dev; + +import org.apache.poi.xssf.usermodel.XSSFWorkbook; + +import java.io.FileOutputStream; + +/** + * Utility which loads a SpreadsheetML file and saves it back. + * This is a handy tool to investigate read-write round trip safety. + * + * @author Yegor Kozlov + */ +public final class XSSFSave { + public static void main(String[] args) throws Exception { + for (int i = 0; i < args.length; i++) { + XSSFWorkbook wb = new XSSFWorkbook(args[i]); + + int sep = args[i].lastIndexOf('.'); + String outfile = args[i].substring(0, sep) + "-save.xls" + (wb.isMacroEnabled() ? "m" : "x"); + FileOutputStream out = new FileOutputStream(outfile); + wb.write(out); + out.close(); + } + } + +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFAnchor.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFAnchor.java index f640f408df..a804176fcd 100755 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFAnchor.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFAnchor.java @@ -1,36 +1,37 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xssf.usermodel; - -/** - * An anchor is what specifics the position of a shape within a client object - * or within another containing shape. - * - * @author Yegor Kozlov - */ -public abstract class XSSFAnchor { - - public abstract int getDx1(); - public abstract void setDx1( int dx1 ); - public abstract int getDy1(); - public abstract void setDy1( int dy1 ); - public abstract int getDy2(); - public abstract void setDy2( int dy2 ); - public abstract int getDx2(); - public abstract void setDx2( int dx2 ); - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xssf.usermodel; + +/** + * An anchor is what specifics the position of a shape within a client object + * or within another containing shape. + * + * @author Yegor Kozlov + */ +public abstract class XSSFAnchor { + + public abstract int getDx1(); + public abstract void setDx1( int dx1 ); + public abstract int getDy1(); + public abstract void setDy1( int dy1 ); + public abstract int getDy2(); + public abstract void setDy2( int dy2 ); + public abstract int getDx2(); + public abstract void setDx2( int dx2 ); + +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFChildAnchor.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFChildAnchor.java index d02ee82d02..5032395394 100755 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFChildAnchor.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFChildAnchor.java @@ -1,81 +1,82 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xssf.usermodel; - -import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; - -/** - * @author Yegor Kozlov - */ -public class XSSFChildAnchor extends XSSFAnchor { - private CTTransform2D t2d; - - public XSSFChildAnchor(int x, int y, int cx, int cy) { - t2d = CTTransform2D.Factory.newInstance(); - CTPoint2D off = t2d.addNewOff(); - CTPositiveSize2D ext = t2d.addNewExt(); - - off.setX(x); - off.setY(y); - ext.setCx(Math.abs(cx - x)); - ext.setCy(Math.abs(cy - y)); - if(x > cx) t2d.setFlipH(true); - if(y > cy) t2d.setFlipV(true); - } - - public XSSFChildAnchor(CTTransform2D t2d) { - this.t2d = t2d; - } - - public CTTransform2D getCTTransform2D() { - return t2d; - } - - public int getDx1() { - return (int)t2d.getOff().getX(); - } - - public void setDx1(int dx1) { - t2d.getOff().setX(dx1); - } - - public int getDy1() { - return (int)t2d.getOff().getY(); - } - - public void setDy1(int dy1) { - t2d.getOff().setY(dy1); - } - - public int getDy2() { - return (int)(getDy1() + t2d.getExt().getCy()); - } - - public void setDy2(int dy2) { - t2d.getExt().setCy(dy2 - getDy1()); - } - - public int getDx2() { - return (int)(getDx1() + t2d.getExt().getCx()); - } - - public void setDx2(int dx2) { - t2d.getExt().setCx(dx2 - getDx1()); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xssf.usermodel; + +import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; + +/** + * @author Yegor Kozlov + */ +public final class XSSFChildAnchor extends XSSFAnchor { + private CTTransform2D t2d; + + public XSSFChildAnchor(int x, int y, int cx, int cy) { + t2d = CTTransform2D.Factory.newInstance(); + CTPoint2D off = t2d.addNewOff(); + CTPositiveSize2D ext = t2d.addNewExt(); + + off.setX(x); + off.setY(y); + ext.setCx(Math.abs(cx - x)); + ext.setCy(Math.abs(cy - y)); + if(x > cx) t2d.setFlipH(true); + if(y > cy) t2d.setFlipV(true); + } + + public XSSFChildAnchor(CTTransform2D t2d) { + this.t2d = t2d; + } + + public CTTransform2D getCTTransform2D() { + return t2d; + } + + public int getDx1() { + return (int)t2d.getOff().getX(); + } + + public void setDx1(int dx1) { + t2d.getOff().setX(dx1); + } + + public int getDy1() { + return (int)t2d.getOff().getY(); + } + + public void setDy1(int dy1) { + t2d.getOff().setY(dy1); + } + + public int getDy2() { + return (int)(getDy1() + t2d.getExt().getCy()); + } + + public void setDy2(int dy2) { + t2d.getExt().setCy(dy2 - getDy1()); + } + + public int getDx2() { + return (int)(getDx1() + t2d.getExt().getCx()); + } + + public void setDx2(int dx2) { + t2d.getExt().setCx(dx2 - getDx1()); + } +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFClientAnchor.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFClientAnchor.java index b23429fa01..b6a17fe53e 100755 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFClientAnchor.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFClientAnchor.java @@ -1,219 +1,220 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xssf.usermodel; - -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker; -import org.apache.poi.ss.usermodel.ClientAnchor; - -/** - * A client anchor is attached to an excel worksheet. It anchors against - * top-left and bottom-right cells. - * - * @author Yegor Kozlov - */ -public class XSSFClientAnchor extends XSSFAnchor implements ClientAnchor { - private int anchorType; - - /** - * Starting anchor point - */ - private CTMarker cell1; - - /** - * Ending anchor point - */ - private CTMarker cell2; - - /** - * Creates a new client anchor and defaults all the anchor positions to 0. - */ - public XSSFClientAnchor() { - cell1 = CTMarker.Factory.newInstance(); - cell1.setCol(0); - cell1.setColOff(0); - cell1.setRow(0); - cell1.setRowOff(0); - cell2 = CTMarker.Factory.newInstance(); - cell2.setCol(0); - cell2.setColOff(0); - cell2.setRow(0); - cell2.setRowOff(0); - } - - /** - * Creates a new client anchor and sets the top-left and bottom-right - * coordinates of the anchor. - * - * @param dx1 the x coordinate within the first cell. - * @param dy1 the y coordinate within the first cell. - * @param dx2 the x coordinate within the second cell. - * @param dy2 the y coordinate within the second cell. - * @param col1 the column (0 based) of the first cell. - * @param row1 the row (0 based) of the first cell. - * @param col2 the column (0 based) of the second cell. - * @param row2 the row (0 based) of the second cell. - */ - public XSSFClientAnchor(int dx1, int dy1, int dx2, int dy2, int col1, int row1, int col2, int row2) { - this(); - cell1.setCol(col1); - cell1.setColOff(dx1); - cell1.setRow(row1); - cell1.setRowOff(dy1); - cell2.setCol(col2); - cell2.setColOff(dx2); - cell2.setRow(row2); - cell2.setRowOff(dy2); - } - - /** - * Create XSSFClientAnchor from existing xml beans - * - * @param cell1 starting anchor point - * @param cell2 ending anchor point - */ - protected XSSFClientAnchor(CTMarker cell1, CTMarker cell2) { - this.cell1 = cell1; - this.cell2 = cell2; - } - - public short getCol1() { - return (short)cell1.getCol(); - } - - public void setCol1(int col1) { - cell1.setCol(col1); - } - - public short getCol2() { - return (short)cell2.getCol(); - } - - public void setCol2(int col2) { - cell2.setCol(col2); - } - - public int getRow1() { - return cell1.getRow(); - } - - public void setRow1(int row1) { - cell1.setRow(row1); - } - - public int getRow2() { - return cell2.getRow(); - } - - public void setRow2(int row2) { - cell2.setRow(row2); - } - - public int getDx1() { - return (int)cell1.getColOff(); - } - - public void setDx1(int dx1) { - cell1.setColOff(dx1); - } - - public int getDy1() { - return (int)cell1.getRowOff(); - } - - public void setDy1(int dy1) { - cell1.setRowOff(dy1); - } - - public int getDy2() { - return (int)cell2.getRowOff(); - } - - public void setDy2(int dy2) { - cell2.setRowOff(dy2); - } - - public int getDx2() { - return (int)cell2.getColOff(); - } - - public void setDx2(int dx2) { - cell2.setColOff(dx2); - } - - @Override - public boolean equals(Object o) { - if (o == null || !(o instanceof XSSFClientAnchor)) return false; - - XSSFClientAnchor anchor = (XSSFClientAnchor) o; - return cell1.toString().equals(anchor.getFrom().toString()) && - cell2.toString().equals(anchor.getTo().toString()) ; - - } - - @Override - public String toString(){ - return "from : " + cell1.toString() + "; to: " + cell2.toString(); - } - - /** - * Return starting anchor point - * - * @return starting anchor point - */ - public CTMarker getFrom(){ - return cell1; - } - - protected void setFrom(CTMarker from){ - cell1 = from; - } - - /** - * Return ending anchor point - * - * @return ending anchor point - */ - public CTMarker getTo(){ - return cell2; - } - - protected void setTo(CTMarker to){ - cell2 = to; - } - - - /** - * Sets the anchor type - *

- * 0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells. - */ - public void setAnchorType( int anchorType ) - { - this.anchorType = anchorType; - } - - /** - * Gets the anchor type - *

- * 0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells. - */ - public int getAnchorType() - { - return anchorType; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xssf.usermodel; + +import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker; +import org.apache.poi.ss.usermodel.ClientAnchor; + +/** + * A client anchor is attached to an excel worksheet. It anchors against + * top-left and bottom-right cells. + * + * @author Yegor Kozlov + */ +public final class XSSFClientAnchor extends XSSFAnchor implements ClientAnchor { + private int anchorType; + + /** + * Starting anchor point + */ + private CTMarker cell1; + + /** + * Ending anchor point + */ + private CTMarker cell2; + + /** + * Creates a new client anchor and defaults all the anchor positions to 0. + */ + public XSSFClientAnchor() { + cell1 = CTMarker.Factory.newInstance(); + cell1.setCol(0); + cell1.setColOff(0); + cell1.setRow(0); + cell1.setRowOff(0); + cell2 = CTMarker.Factory.newInstance(); + cell2.setCol(0); + cell2.setColOff(0); + cell2.setRow(0); + cell2.setRowOff(0); + } + + /** + * Creates a new client anchor and sets the top-left and bottom-right + * coordinates of the anchor. + * + * @param dx1 the x coordinate within the first cell. + * @param dy1 the y coordinate within the first cell. + * @param dx2 the x coordinate within the second cell. + * @param dy2 the y coordinate within the second cell. + * @param col1 the column (0 based) of the first cell. + * @param row1 the row (0 based) of the first cell. + * @param col2 the column (0 based) of the second cell. + * @param row2 the row (0 based) of the second cell. + */ + public XSSFClientAnchor(int dx1, int dy1, int dx2, int dy2, int col1, int row1, int col2, int row2) { + this(); + cell1.setCol(col1); + cell1.setColOff(dx1); + cell1.setRow(row1); + cell1.setRowOff(dy1); + cell2.setCol(col2); + cell2.setColOff(dx2); + cell2.setRow(row2); + cell2.setRowOff(dy2); + } + + /** + * Create XSSFClientAnchor from existing xml beans + * + * @param cell1 starting anchor point + * @param cell2 ending anchor point + */ + protected XSSFClientAnchor(CTMarker cell1, CTMarker cell2) { + this.cell1 = cell1; + this.cell2 = cell2; + } + + public short getCol1() { + return (short)cell1.getCol(); + } + + public void setCol1(int col1) { + cell1.setCol(col1); + } + + public short getCol2() { + return (short)cell2.getCol(); + } + + public void setCol2(int col2) { + cell2.setCol(col2); + } + + public int getRow1() { + return cell1.getRow(); + } + + public void setRow1(int row1) { + cell1.setRow(row1); + } + + public int getRow2() { + return cell2.getRow(); + } + + public void setRow2(int row2) { + cell2.setRow(row2); + } + + public int getDx1() { + return (int)cell1.getColOff(); + } + + public void setDx1(int dx1) { + cell1.setColOff(dx1); + } + + public int getDy1() { + return (int)cell1.getRowOff(); + } + + public void setDy1(int dy1) { + cell1.setRowOff(dy1); + } + + public int getDy2() { + return (int)cell2.getRowOff(); + } + + public void setDy2(int dy2) { + cell2.setRowOff(dy2); + } + + public int getDx2() { + return (int)cell2.getColOff(); + } + + public void setDx2(int dx2) { + cell2.setColOff(dx2); + } + + @Override + public boolean equals(Object o) { + if (o == null || !(o instanceof XSSFClientAnchor)) return false; + + XSSFClientAnchor anchor = (XSSFClientAnchor) o; + return cell1.toString().equals(anchor.getFrom().toString()) && + cell2.toString().equals(anchor.getTo().toString()) ; + + } + + @Override + public String toString(){ + return "from : " + cell1.toString() + "; to: " + cell2.toString(); + } + + /** + * Return starting anchor point + * + * @return starting anchor point + */ + public CTMarker getFrom(){ + return cell1; + } + + protected void setFrom(CTMarker from){ + cell1 = from; + } + + /** + * Return ending anchor point + * + * @return ending anchor point + */ + public CTMarker getTo(){ + return cell2; + } + + protected void setTo(CTMarker to){ + cell2 = to; + } + + + /** + * Sets the anchor type + *

+ * 0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells. + */ + public void setAnchorType( int anchorType ) + { + this.anchorType = anchorType; + } + + /** + * Gets the anchor type + *

+ * 0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells. + */ + public int getAnchorType() + { + return anchorType; + } + +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConnector.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConnector.java index 92f0d1d73c..f7cf9d5a75 100755 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConnector.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConnector.java @@ -1,121 +1,122 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xssf.usermodel; - -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.*; -import org.openxmlformats.schemas.drawingml.x2006.main.*; - -/** - * A connection shape drawing element. A connection shape is a line, etc. - * that connects two other shapes in this drawing. - * - * @author Yegor Kozlov - */ -public class XSSFConnector extends XSSFShape { - - private static CTConnector prototype = null; - - private CTConnector ctShape; - - /** - * Construct a new XSSFConnector object. - * - * @param drawing the XSSFDrawing that owns this shape - * @param ctShape the shape bean that holds all the shape properties - */ - protected XSSFConnector(XSSFDrawing drawing, CTConnector ctShape) { - this.drawing = drawing; - this.ctShape = ctShape; - } - - /** - * Initialize default structure of a new auto-shape - * - */ - protected static CTConnector prototype() { - if(prototype == null) { - CTConnector shape = CTConnector.Factory.newInstance(); - CTConnectorNonVisual nv = shape.addNewNvCxnSpPr(); - CTNonVisualDrawingProps nvp = nv.addNewCNvPr(); - nvp.setId(1); - nvp.setName("Shape 1"); - nv.addNewCNvCxnSpPr(); - - CTShapeProperties sp = shape.addNewSpPr(); - CTTransform2D t2d = sp.addNewXfrm(); - CTPositiveSize2D p1 = t2d.addNewExt(); - p1.setCx(0); - p1.setCy(0); - CTPoint2D p2 = t2d.addNewOff(); - p2.setX(0); - p2.setY(0); - - CTPresetGeometry2D geom = sp.addNewPrstGeom(); - geom.setPrst(STShapeType.LINE); - geom.addNewAvLst(); - - CTShapeStyle style = shape.addNewStyle(); - CTSchemeColor scheme = style.addNewLnRef().addNewSchemeClr(); - scheme.setVal(STSchemeColorVal.ACCENT_1); - style.getLnRef().setIdx(1); - - CTStyleMatrixReference fillref = style.addNewFillRef(); - fillref.setIdx(0); - fillref.addNewSchemeClr().setVal(STSchemeColorVal.ACCENT_1); - - CTStyleMatrixReference effectRef = style.addNewEffectRef(); - effectRef.setIdx(0); - effectRef.addNewSchemeClr().setVal(STSchemeColorVal.ACCENT_1); - - CTFontReference fontRef = style.addNewFontRef(); - fontRef.setIdx(STFontCollectionIndex.MINOR); - fontRef.addNewSchemeClr().setVal(STSchemeColorVal.TX_1); - - prototype = shape; - } - return prototype; - } - - public CTConnector getCTConnector(){ - return ctShape; - } - - /** - * Gets the shape type, one of the constants defined in {@link org.apache.poi.ss.usermodel.ShapeTypes}. - * - * @return the shape type - * @see org.apache.poi.ss.usermodel.ShapeTypes - */ - public int getShapeType() { - return ctShape.getSpPr().getPrstGeom().getPrst().intValue(); - } - - /** - * Sets the shape types. - * - * @param type the shape type, one of the constants defined in {@link org.apache.poi.ss.usermodel.ShapeTypes}. - * @see org.apache.poi.ss.usermodel.ShapeTypes - */ - public void setShapeType(int type) { - ctShape.getSpPr().getPrstGeom().setPrst(STShapeType.Enum.forInt(type)); - } - - protected CTShapeProperties getShapeProperties(){ - return ctShape.getSpPr(); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xssf.usermodel; + +import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.*; +import org.openxmlformats.schemas.drawingml.x2006.main.*; + +/** + * A connection shape drawing element. A connection shape is a line, etc. + * that connects two other shapes in this drawing. + * + * @author Yegor Kozlov + */ +public final class XSSFConnector extends XSSFShape { + + private static CTConnector prototype = null; + + private CTConnector ctShape; + + /** + * Construct a new XSSFConnector object. + * + * @param drawing the XSSFDrawing that owns this shape + * @param ctShape the shape bean that holds all the shape properties + */ + protected XSSFConnector(XSSFDrawing drawing, CTConnector ctShape) { + this.drawing = drawing; + this.ctShape = ctShape; + } + + /** + * Initialize default structure of a new auto-shape + * + */ + protected static CTConnector prototype() { + if(prototype == null) { + CTConnector shape = CTConnector.Factory.newInstance(); + CTConnectorNonVisual nv = shape.addNewNvCxnSpPr(); + CTNonVisualDrawingProps nvp = nv.addNewCNvPr(); + nvp.setId(1); + nvp.setName("Shape 1"); + nv.addNewCNvCxnSpPr(); + + CTShapeProperties sp = shape.addNewSpPr(); + CTTransform2D t2d = sp.addNewXfrm(); + CTPositiveSize2D p1 = t2d.addNewExt(); + p1.setCx(0); + p1.setCy(0); + CTPoint2D p2 = t2d.addNewOff(); + p2.setX(0); + p2.setY(0); + + CTPresetGeometry2D geom = sp.addNewPrstGeom(); + geom.setPrst(STShapeType.LINE); + geom.addNewAvLst(); + + CTShapeStyle style = shape.addNewStyle(); + CTSchemeColor scheme = style.addNewLnRef().addNewSchemeClr(); + scheme.setVal(STSchemeColorVal.ACCENT_1); + style.getLnRef().setIdx(1); + + CTStyleMatrixReference fillref = style.addNewFillRef(); + fillref.setIdx(0); + fillref.addNewSchemeClr().setVal(STSchemeColorVal.ACCENT_1); + + CTStyleMatrixReference effectRef = style.addNewEffectRef(); + effectRef.setIdx(0); + effectRef.addNewSchemeClr().setVal(STSchemeColorVal.ACCENT_1); + + CTFontReference fontRef = style.addNewFontRef(); + fontRef.setIdx(STFontCollectionIndex.MINOR); + fontRef.addNewSchemeClr().setVal(STSchemeColorVal.TX_1); + + prototype = shape; + } + return prototype; + } + + public CTConnector getCTConnector(){ + return ctShape; + } + + /** + * Gets the shape type, one of the constants defined in {@link org.apache.poi.ss.usermodel.ShapeTypes}. + * + * @return the shape type + * @see org.apache.poi.ss.usermodel.ShapeTypes + */ + public int getShapeType() { + return ctShape.getSpPr().getPrstGeom().getPrst().intValue(); + } + + /** + * Sets the shape types. + * + * @param type the shape type, one of the constants defined in {@link org.apache.poi.ss.usermodel.ShapeTypes}. + * @see org.apache.poi.ss.usermodel.ShapeTypes + */ + public void setShapeType(int type) { + ctShape.getSpPr().getPrstGeom().setPrst(STShapeType.Enum.forInt(type)); + } + + protected CTShapeProperties getShapeProperties(){ + return ctShape.getSpPr(); + } + +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java index 24943ba834..ffdc684f5b 100755 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDrawing.java @@ -1,247 +1,248 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xssf.usermodel; - -import org.apache.poi.POIXMLDocumentPart; -import org.apache.poi.ss.usermodel.Drawing; -import org.apache.poi.ss.usermodel.ClientAnchor; -import org.apache.xmlbeans.XmlException; -import org.apache.xmlbeans.XmlOptions; -import org.apache.poi.openxml4j.opc.*; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.*; -import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId; - -import javax.xml.namespace.QName; -import java.io.IOException; -import java.io.OutputStream; -import java.util.Map; -import java.util.HashMap; - -/** - * Represents a SpreadsheetML drawing - * - * @author Yegor Kozlov - */ -public class XSSFDrawing extends POIXMLDocumentPart implements Drawing { - /** - * Root element of the SpreadsheetML Drawing part - */ - private CTDrawing drawing; - private boolean isNew; - - /** - * Create a new SpreadsheetML drawing - * - * @see org.apache.poi.xssf.usermodel.XSSFSheet#createDrawingPatriarch() - */ - protected XSSFDrawing() { - super(); - drawing = newDrawing(); - isNew = true; - } - - /** - * Construct a SpreadsheetML drawing from a package part - * - * @param part the package part holding the drawing data, - * the content type must be application/vnd.openxmlformats-officedocument.drawing+xml - * @param rel the package relationship holding this drawing, - * the relationship type must be http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing - */ - protected XSSFDrawing(PackagePart part, PackageRelationship rel) throws IOException, XmlException { - super(part, rel); - drawing = CTDrawing.Factory.parse(part.getInputStream()); - } - - /** - * Construct a new CTDrawing bean. By default, it's just an empty placeholder for drawing objects - * - * @return a new CTDrawing bean - */ - private static CTDrawing newDrawing(){ - return CTDrawing.Factory.newInstance(); - } - - /** - * Return the underlying CTDrawing bean, the root element of the SpreadsheetML Drawing part. - * - * @return the underlying CTDrawing bean - */ - public CTDrawing getCTDrawing(){ - return drawing; - } - - @Override - protected void commit() throws IOException { - XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); - - /* - Saved drawings must have the following namespaces set: - - */ - if(isNew) xmlOptions.setSaveSyntheticDocumentElement(new QName(CTDrawing.type.getName().getNamespaceURI(), "wsDr", "xdr")); - Map map = new HashMap(); - map.put("http://schemas.openxmlformats.org/drawingml/2006/main", "a"); - map.put(STRelationshipId.type.getName().getNamespaceURI(), "r"); - xmlOptions.setSaveSuggestedPrefixes(map); - - PackagePart part = getPackagePart(); - OutputStream out = part.getOutputStream(); - drawing.save(out, xmlOptions); - out.close(); - } - - /** - * Constructs a textbox under the drawing. - * - * @param anchor the client anchor describes how this group is attached - * to the sheet. - * @return the newly created textbox. - */ - public XSSFTextBox createTextbox(XSSFClientAnchor anchor){ - CTTwoCellAnchor ctAnchor = createTwoCellAnchor(anchor); - CTShape ctShape = ctAnchor.addNewSp(); - ctShape.set(XSSFSimpleShape.prototype()); - XSSFTextBox shape = new XSSFTextBox(this, ctShape); - shape.anchor = anchor; - return shape; - - } - - /** - * Creates a picture. - * - * @param anchor the client anchor describes how this picture is attached to the sheet. - * @param pictureIndex the index of the picture in the workbook collection of pictures, - * {@link org.apache.poi.xssf.usermodel.XSSFWorkbook#getAllPictures()} . - * - * @return the newly created picture shape. - */ - public XSSFPicture createPicture(XSSFClientAnchor anchor, int pictureIndex) - { - PackageRelationship rel = addPictureReference(pictureIndex); - - CTTwoCellAnchor ctAnchor = createTwoCellAnchor(anchor); - CTPicture ctShape = ctAnchor.addNewPic(); - ctShape.set(XSSFPicture.prototype()); - - XSSFPicture shape = new XSSFPicture(this, ctShape); - shape.anchor = anchor; - shape.setPictureReference(rel); - return shape; - } - - public XSSFPicture createPicture(ClientAnchor anchor, int pictureIndex){ - return createPicture((XSSFClientAnchor)anchor, pictureIndex); - } - - /** - * Add the indexed picture to this drawing relations - * - * @param pictureIndex the index of the picture in the workbook collection of pictures, - * {@link org.apache.poi.xssf.usermodel.XSSFWorkbook#getAllPictures()} . - */ - protected PackageRelationship addPictureReference(int pictureIndex){ - XSSFWorkbook wb = (XSSFWorkbook)getParent().getParent(); - XSSFPictureData data = wb.getAllPictures().get(pictureIndex); - PackagePartName ppName = data.getPackagePart().getPartName(); - PackageRelationship rel = getPackagePart().addRelationship(ppName, TargetMode.INTERNAL, XSSFRelation.IMAGES.getRelation()); - addRelation(new XSSFPictureData(data.getPackagePart(), rel)); - return rel; - } - - /** - * Creates a simple shape. This includes such shapes as lines, rectangles, - * and ovals. - * - * @param anchor the client anchor describes how this group is attached - * to the sheet. - * @return the newly created shape. - */ - public XSSFSimpleShape createSimpleShape(XSSFClientAnchor anchor) - { - CTTwoCellAnchor ctAnchor = createTwoCellAnchor(anchor); - CTShape ctShape = ctAnchor.addNewSp(); - ctShape.set(XSSFSimpleShape.prototype()); - XSSFSimpleShape shape = new XSSFSimpleShape(this, ctShape); - shape.anchor = anchor; - return shape; - } - - /** - * Creates a simple shape. This includes such shapes as lines, rectangles, - * and ovals. - * - * @param anchor the client anchor describes how this group is attached - * to the sheet. - * @return the newly created shape. - */ - public XSSFConnector createConnector(XSSFClientAnchor anchor) - { - CTTwoCellAnchor ctAnchor = createTwoCellAnchor(anchor); - CTConnector ctShape = ctAnchor.addNewCxnSp(); - ctShape.set(XSSFConnector.prototype()); - - XSSFConnector shape = new XSSFConnector(this, ctShape); - shape.anchor = anchor; - return shape; - } - - /** - * Creates a simple shape. This includes such shapes as lines, rectangles, - * and ovals. - * - * @param anchor the client anchor describes how this group is attached - * to the sheet. - * @return the newly created shape. - */ - public XSSFShapeGroup createGroup(XSSFClientAnchor anchor) - { - CTTwoCellAnchor ctAnchor = createTwoCellAnchor(anchor); - CTGroupShape ctGroup = ctAnchor.addNewGrpSp(); - ctGroup.set(XSSFShapeGroup.prototype()); - - XSSFShapeGroup shape = new XSSFShapeGroup(this, ctGroup); - shape.anchor = anchor; - return shape; - } - - /** - * Create and initialize a CTTwoCellAnchor that anchors a shape against top-left and bottom-right cells. - * - * @return a new CTTwoCellAnchor - */ - private CTTwoCellAnchor createTwoCellAnchor(XSSFClientAnchor anchor) { - CTTwoCellAnchor ctAnchor = drawing.addNewTwoCellAnchor(); - ctAnchor.setFrom(anchor.getFrom()); - ctAnchor.setTo(anchor.getTo()); - ctAnchor.addNewClientData(); - anchor.setTo(ctAnchor.getTo()); - anchor.setFrom(ctAnchor.getFrom()); - STEditAs.Enum aditAs; - switch(anchor.getAnchorType()) { - case ClientAnchor.DONT_MOVE_AND_RESIZE: aditAs = STEditAs.ABSOLUTE; break; - case ClientAnchor.MOVE_AND_RESIZE: aditAs = STEditAs.TWO_CELL; break; - case ClientAnchor.MOVE_DONT_RESIZE: aditAs = STEditAs.ONE_CELL; break; - default: aditAs = STEditAs.ONE_CELL; - } - ctAnchor.setEditAs(aditAs); - return ctAnchor; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xssf.usermodel; + +import org.apache.poi.POIXMLDocumentPart; +import org.apache.poi.ss.usermodel.Drawing; +import org.apache.poi.ss.usermodel.ClientAnchor; +import org.apache.xmlbeans.XmlException; +import org.apache.xmlbeans.XmlOptions; +import org.apache.poi.openxml4j.opc.*; +import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.*; +import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId; + +import javax.xml.namespace.QName; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Map; +import java.util.HashMap; + +/** + * Represents a SpreadsheetML drawing + * + * @author Yegor Kozlov + */ +public final class XSSFDrawing extends POIXMLDocumentPart implements Drawing { + /** + * Root element of the SpreadsheetML Drawing part + */ + private CTDrawing drawing; + private boolean isNew; + + /** + * Create a new SpreadsheetML drawing + * + * @see org.apache.poi.xssf.usermodel.XSSFSheet#createDrawingPatriarch() + */ + protected XSSFDrawing() { + super(); + drawing = newDrawing(); + isNew = true; + } + + /** + * Construct a SpreadsheetML drawing from a package part + * + * @param part the package part holding the drawing data, + * the content type must be application/vnd.openxmlformats-officedocument.drawing+xml + * @param rel the package relationship holding this drawing, + * the relationship type must be http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing + */ + protected XSSFDrawing(PackagePart part, PackageRelationship rel) throws IOException, XmlException { + super(part, rel); + drawing = CTDrawing.Factory.parse(part.getInputStream()); + } + + /** + * Construct a new CTDrawing bean. By default, it's just an empty placeholder for drawing objects + * + * @return a new CTDrawing bean + */ + private static CTDrawing newDrawing(){ + return CTDrawing.Factory.newInstance(); + } + + /** + * Return the underlying CTDrawing bean, the root element of the SpreadsheetML Drawing part. + * + * @return the underlying CTDrawing bean + */ + public CTDrawing getCTDrawing(){ + return drawing; + } + + @Override + protected void commit() throws IOException { + XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); + + /* + Saved drawings must have the following namespaces set: + + */ + if(isNew) xmlOptions.setSaveSyntheticDocumentElement(new QName(CTDrawing.type.getName().getNamespaceURI(), "wsDr", "xdr")); + Map map = new HashMap(); + map.put("http://schemas.openxmlformats.org/drawingml/2006/main", "a"); + map.put(STRelationshipId.type.getName().getNamespaceURI(), "r"); + xmlOptions.setSaveSuggestedPrefixes(map); + + PackagePart part = getPackagePart(); + OutputStream out = part.getOutputStream(); + drawing.save(out, xmlOptions); + out.close(); + } + + /** + * Constructs a textbox under the drawing. + * + * @param anchor the client anchor describes how this group is attached + * to the sheet. + * @return the newly created textbox. + */ + public XSSFTextBox createTextbox(XSSFClientAnchor anchor){ + CTTwoCellAnchor ctAnchor = createTwoCellAnchor(anchor); + CTShape ctShape = ctAnchor.addNewSp(); + ctShape.set(XSSFSimpleShape.prototype()); + XSSFTextBox shape = new XSSFTextBox(this, ctShape); + shape.anchor = anchor; + return shape; + + } + + /** + * Creates a picture. + * + * @param anchor the client anchor describes how this picture is attached to the sheet. + * @param pictureIndex the index of the picture in the workbook collection of pictures, + * {@link org.apache.poi.xssf.usermodel.XSSFWorkbook#getAllPictures()} . + * + * @return the newly created picture shape. + */ + public XSSFPicture createPicture(XSSFClientAnchor anchor, int pictureIndex) + { + PackageRelationship rel = addPictureReference(pictureIndex); + + CTTwoCellAnchor ctAnchor = createTwoCellAnchor(anchor); + CTPicture ctShape = ctAnchor.addNewPic(); + ctShape.set(XSSFPicture.prototype()); + + XSSFPicture shape = new XSSFPicture(this, ctShape); + shape.anchor = anchor; + shape.setPictureReference(rel); + return shape; + } + + public XSSFPicture createPicture(ClientAnchor anchor, int pictureIndex){ + return createPicture((XSSFClientAnchor)anchor, pictureIndex); + } + + /** + * Add the indexed picture to this drawing relations + * + * @param pictureIndex the index of the picture in the workbook collection of pictures, + * {@link org.apache.poi.xssf.usermodel.XSSFWorkbook#getAllPictures()} . + */ + protected PackageRelationship addPictureReference(int pictureIndex){ + XSSFWorkbook wb = (XSSFWorkbook)getParent().getParent(); + XSSFPictureData data = wb.getAllPictures().get(pictureIndex); + PackagePartName ppName = data.getPackagePart().getPartName(); + PackageRelationship rel = getPackagePart().addRelationship(ppName, TargetMode.INTERNAL, XSSFRelation.IMAGES.getRelation()); + addRelation(new XSSFPictureData(data.getPackagePart(), rel)); + return rel; + } + + /** + * Creates a simple shape. This includes such shapes as lines, rectangles, + * and ovals. + * + * @param anchor the client anchor describes how this group is attached + * to the sheet. + * @return the newly created shape. + */ + public XSSFSimpleShape createSimpleShape(XSSFClientAnchor anchor) + { + CTTwoCellAnchor ctAnchor = createTwoCellAnchor(anchor); + CTShape ctShape = ctAnchor.addNewSp(); + ctShape.set(XSSFSimpleShape.prototype()); + XSSFSimpleShape shape = new XSSFSimpleShape(this, ctShape); + shape.anchor = anchor; + return shape; + } + + /** + * Creates a simple shape. This includes such shapes as lines, rectangles, + * and ovals. + * + * @param anchor the client anchor describes how this group is attached + * to the sheet. + * @return the newly created shape. + */ + public XSSFConnector createConnector(XSSFClientAnchor anchor) + { + CTTwoCellAnchor ctAnchor = createTwoCellAnchor(anchor); + CTConnector ctShape = ctAnchor.addNewCxnSp(); + ctShape.set(XSSFConnector.prototype()); + + XSSFConnector shape = new XSSFConnector(this, ctShape); + shape.anchor = anchor; + return shape; + } + + /** + * Creates a simple shape. This includes such shapes as lines, rectangles, + * and ovals. + * + * @param anchor the client anchor describes how this group is attached + * to the sheet. + * @return the newly created shape. + */ + public XSSFShapeGroup createGroup(XSSFClientAnchor anchor) + { + CTTwoCellAnchor ctAnchor = createTwoCellAnchor(anchor); + CTGroupShape ctGroup = ctAnchor.addNewGrpSp(); + ctGroup.set(XSSFShapeGroup.prototype()); + + XSSFShapeGroup shape = new XSSFShapeGroup(this, ctGroup); + shape.anchor = anchor; + return shape; + } + + /** + * Create and initialize a CTTwoCellAnchor that anchors a shape against top-left and bottom-right cells. + * + * @return a new CTTwoCellAnchor + */ + private CTTwoCellAnchor createTwoCellAnchor(XSSFClientAnchor anchor) { + CTTwoCellAnchor ctAnchor = drawing.addNewTwoCellAnchor(); + ctAnchor.setFrom(anchor.getFrom()); + ctAnchor.setTo(anchor.getTo()); + ctAnchor.addNewClientData(); + anchor.setTo(ctAnchor.getTo()); + anchor.setFrom(ctAnchor.getFrom()); + STEditAs.Enum aditAs; + switch(anchor.getAnchorType()) { + case ClientAnchor.DONT_MOVE_AND_RESIZE: aditAs = STEditAs.ABSOLUTE; break; + case ClientAnchor.MOVE_AND_RESIZE: aditAs = STEditAs.TWO_CELL; break; + case ClientAnchor.MOVE_DONT_RESIZE: aditAs = STEditAs.ONE_CELL; break; + default: aditAs = STEditAs.ONE_CELL; + } + ctAnchor.setEditAs(aditAs); + return ctAnchor; + } +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java index ef2bdf89b3..5264281f00 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java @@ -1,180 +1,180 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.xssf.usermodel; - -import org.apache.poi.hssf.record.formula.NamePtg; -import org.apache.poi.hssf.record.formula.NameXPtg; -import org.apache.poi.hssf.record.formula.Ptg; -import org.apache.poi.ss.formula.*; -import org.apache.poi.ss.SpreadsheetVersion; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDefinedName; - -/** - * Internal POI use only - * - * @author Josh Micich - */ -public final class XSSFEvaluationWorkbook implements FormulaRenderingWorkbook, EvaluationWorkbook, FormulaParsingWorkbook { - - private final XSSFWorkbook _uBook; - - public static XSSFEvaluationWorkbook create(XSSFWorkbook book) { - if (book == null) { - return null; - } - return new XSSFEvaluationWorkbook(book); - } - - private XSSFEvaluationWorkbook(XSSFWorkbook book) { - _uBook = book; - } - - private int convertFromExternalSheetIndex(int externSheetIndex) { - return externSheetIndex; - } - /** - * @return the sheet index of the sheet with the given external index. - */ - public int convertFromExternSheetIndex(int externSheetIndex) { - return externSheetIndex; - } - /** - * @return the external sheet index of the sheet with the given internal - * index. Used by some of the more obscure formula and named range things. - * Fairly easy on XSSF (we think...) since the internal and external - * indicies are the same - */ - private int convertToExternalSheetIndex(int sheetIndex) { - return sheetIndex; - } - - public int getExternalSheetIndex(String sheetName) { - int sheetIndex = _uBook.getSheetIndex(sheetName); - return convertToExternalSheetIndex(sheetIndex); - } - - public EvaluationName getName(String name, int sheetIndex) { - for(int i=0; i < _uBook.getNumberOfNames(); i++) { - XSSFName nm = _uBook.getNameAt(i); - String nameText = nm.getNameName(); - if (name.equalsIgnoreCase(nameText) && nm.getSheetIndex() == sheetIndex) { - return new Name(_uBook.getNameAt(i), i, this); - } - } - return sheetIndex == -1 ? null : getName(name, -1); - } - - public int getSheetIndex(EvaluationSheet evalSheet) { - XSSFSheet sheet = ((XSSFEvaluationSheet)evalSheet).getXSSFSheet(); - return _uBook.getSheetIndex(sheet); - } - - public String getSheetName(int sheetIndex) { - return _uBook.getSheetName(sheetIndex); - } - - public NameXPtg getNameXPtg(String name) { - // may require to return null to make tests pass - throw new RuntimeException("Not implemented yet"); - } - - public EvaluationSheet getSheet(int sheetIndex) { - return new XSSFEvaluationSheet(_uBook.getSheetAt(sheetIndex)); - } - - public ExternalSheet getExternalSheet(int externSheetIndex) { - // TODO Auto-generated method stub - return null; - } - public int getExternalSheetIndex(String workbookName, String sheetName) { - throw new RuntimeException("not implemented yet"); - } - public int getSheetIndex(String sheetName) { - return _uBook.getSheetIndex(sheetName); - } - - /** - * TODO - figure out what the hell this methods does in - * HSSF... - */ - public String resolveNameXText(NameXPtg n) { - throw new RuntimeException("method not implemented yet"); - } - - public String getSheetNameByExternSheet(int externSheetIndex) { - int sheetIndex = convertFromExternalSheetIndex(externSheetIndex); - return _uBook.getSheetName(sheetIndex); - } - - public String getNameText(NamePtg namePtg) { - return _uBook.getNameAt(namePtg.getIndex()).getNameName(); - } - public EvaluationName getName(NamePtg namePtg) { - int ix = namePtg.getIndex(); - return new Name(_uBook.getNameAt(ix), ix, this); - } - public Ptg[] getFormulaTokens(EvaluationCell evalCell) { - XSSFCell cell = ((XSSFEvaluationCell)evalCell).getXSSFCell(); - XSSFEvaluationWorkbook frBook = XSSFEvaluationWorkbook.create(_uBook); - return FormulaParser.parse(cell.getCellFormula(), frBook, FormulaType.CELL, _uBook.getSheetIndex(cell.getSheet())); - } - - private static final class Name implements EvaluationName { - - private final XSSFName _nameRecord; - private final int _index; - private final FormulaParsingWorkbook _fpBook; - - public Name(XSSFName name, int index, FormulaParsingWorkbook fpBook) { - _nameRecord = name; - _index = index; - _fpBook = fpBook; - } - - public Ptg[] getNameDefinition() { - - return FormulaParser.parse(_nameRecord.getRefersToFormula(), _fpBook, FormulaType.NAMEDRANGE, _nameRecord.getSheetIndex()); - } - - public String getNameText() { - return _nameRecord.getNameName(); - } - - public boolean hasFormula() { - // TODO - no idea if this is right - CTDefinedName ctn = _nameRecord.getCTName(); - String strVal = ctn.getStringValue(); - return !ctn.getFunction() && strVal != null && strVal.length() > 0; - } - - public boolean isFunctionName() { - return _nameRecord.isFunctionName(); - } - - public boolean isRange() { - return hasFormula(); // TODO - is this right? - } - public NamePtg createPtg() { - return new NamePtg(_index); - } - } - - public SpreadsheetVersion getSpreadsheetVersion(){ - return SpreadsheetVersion.EXCEL2007; - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xssf.usermodel; + +import org.apache.poi.hssf.record.formula.NamePtg; +import org.apache.poi.hssf.record.formula.NameXPtg; +import org.apache.poi.hssf.record.formula.Ptg; +import org.apache.poi.ss.formula.*; +import org.apache.poi.ss.SpreadsheetVersion; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDefinedName; + +/** + * Internal POI use only + * + * @author Josh Micich + */ +public final class XSSFEvaluationWorkbook implements FormulaRenderingWorkbook, EvaluationWorkbook, FormulaParsingWorkbook { + + private final XSSFWorkbook _uBook; + + public static XSSFEvaluationWorkbook create(XSSFWorkbook book) { + if (book == null) { + return null; + } + return new XSSFEvaluationWorkbook(book); + } + + private XSSFEvaluationWorkbook(XSSFWorkbook book) { + _uBook = book; + } + + private int convertFromExternalSheetIndex(int externSheetIndex) { + return externSheetIndex; + } + /** + * @return the sheet index of the sheet with the given external index. + */ + public int convertFromExternSheetIndex(int externSheetIndex) { + return externSheetIndex; + } + /** + * @return the external sheet index of the sheet with the given internal + * index. Used by some of the more obscure formula and named range things. + * Fairly easy on XSSF (we think...) since the internal and external + * indicies are the same + */ + private int convertToExternalSheetIndex(int sheetIndex) { + return sheetIndex; + } + + public int getExternalSheetIndex(String sheetName) { + int sheetIndex = _uBook.getSheetIndex(sheetName); + return convertToExternalSheetIndex(sheetIndex); + } + + public EvaluationName getName(String name, int sheetIndex) { + for (int i = 0; i < _uBook.getNumberOfNames(); i++) { + XSSFName nm = _uBook.getNameAt(i); + String nameText = nm.getNameName(); + if (name.equalsIgnoreCase(nameText) && nm.getSheetIndex() == sheetIndex) { + return new Name(_uBook.getNameAt(i), i, this); + } + } + return sheetIndex == -1 ? null : getName(name, -1); + } + + public int getSheetIndex(EvaluationSheet evalSheet) { + XSSFSheet sheet = ((XSSFEvaluationSheet)evalSheet).getXSSFSheet(); + return _uBook.getSheetIndex(sheet); + } + + public String getSheetName(int sheetIndex) { + return _uBook.getSheetName(sheetIndex); + } + + public NameXPtg getNameXPtg(String name) { + // may require to return null to make tests pass + throw new RuntimeException("Not implemented yet"); + } + + public EvaluationSheet getSheet(int sheetIndex) { + return new XSSFEvaluationSheet(_uBook.getSheetAt(sheetIndex)); + } + + public ExternalSheet getExternalSheet(int externSheetIndex) { + // TODO Auto-generated method stub + return null; + } + public int getExternalSheetIndex(String workbookName, String sheetName) { + throw new RuntimeException("not implemented yet"); + } + public int getSheetIndex(String sheetName) { + return _uBook.getSheetIndex(sheetName); + } + + /** + * TODO - figure out what the hell this methods does in + * HSSF... + */ + public String resolveNameXText(NameXPtg n) { + throw new RuntimeException("method not implemented yet"); + } + + public String getSheetNameByExternSheet(int externSheetIndex) { + int sheetIndex = convertFromExternalSheetIndex(externSheetIndex); + return _uBook.getSheetName(sheetIndex); + } + + public String getNameText(NamePtg namePtg) { + return _uBook.getNameAt(namePtg.getIndex()).getNameName(); + } + public EvaluationName getName(NamePtg namePtg) { + int ix = namePtg.getIndex(); + return new Name(_uBook.getNameAt(ix), ix, this); + } + public Ptg[] getFormulaTokens(EvaluationCell evalCell) { + XSSFCell cell = ((XSSFEvaluationCell)evalCell).getXSSFCell(); + XSSFEvaluationWorkbook frBook = XSSFEvaluationWorkbook.create(_uBook); + return FormulaParser.parse(cell.getCellFormula(), frBook, FormulaType.CELL, _uBook.getSheetIndex(cell.getSheet())); + } + + private static final class Name implements EvaluationName { + + private final XSSFName _nameRecord; + private final int _index; + private final FormulaParsingWorkbook _fpBook; + + public Name(XSSFName name, int index, FormulaParsingWorkbook fpBook) { + _nameRecord = name; + _index = index; + _fpBook = fpBook; + } + + public Ptg[] getNameDefinition() { + + return FormulaParser.parse(_nameRecord.getRefersToFormula(), _fpBook, FormulaType.NAMEDRANGE, _nameRecord.getSheetIndex()); + } + + public String getNameText() { + return _nameRecord.getNameName(); + } + + public boolean hasFormula() { + // TODO - no idea if this is right + CTDefinedName ctn = _nameRecord.getCTName(); + String strVal = ctn.getStringValue(); + return !ctn.getFunction() && strVal != null && strVal.length() > 0; + } + + public boolean isFunctionName() { + return _nameRecord.isFunctionName(); + } + + public boolean isRange() { + return hasFormula(); // TODO - is this right? + } + public NamePtg createPtg() { + return new NamePtg(_index); + } + } + + public SpreadsheetVersion getSpreadsheetVersion(){ + return SpreadsheetVersion.EXCEL2007; + } +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFactory.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFactory.java index 4736ecbc4a..ab0ef2b443 100755 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFactory.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFactory.java @@ -1,74 +1,75 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xssf.usermodel; - -import org.apache.poi.POIXMLDocumentPart; -import org.apache.poi.POIXMLFactory; -import org.apache.poi.POIXMLException; -import org.apache.poi.POIXMLRelation; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.openxml4j.opc.PackageRelationship; -import org.apache.poi.openxml4j.opc.PackagePart; - -import java.lang.reflect.Constructor; - -/** - * Instantiates sub-classes of POIXMLDocumentPart depending on their relationship type - * - * @author Yegor Kozlov - */ -public class XSSFFactory extends POIXMLFactory { - private static POILogger logger = POILogFactory.getLogger(XSSFFactory.class); - - private XSSFFactory(){ - - } - - private static final XSSFFactory inst = new XSSFFactory(); - - public static XSSFFactory getInstance(){ - return inst; - } - - public POIXMLDocumentPart createDocumentPart(PackageRelationship rel, PackagePart part){ - POIXMLRelation descriptor = XSSFRelation.getInstance(rel.getRelationshipType()); - if(descriptor == null || descriptor.getRelationClass() == null){ - logger.log(POILogger.DEBUG, "using default POIXMLDocumentPart for " + rel.getRelationshipType()); - return new POIXMLDocumentPart(part, rel); - } - - try { - Class cls = descriptor.getRelationClass(); - Constructor constructor = cls.getDeclaredConstructor(PackagePart.class, PackageRelationship.class); - return constructor.newInstance(part, rel); - } catch (Exception e){ - throw new POIXMLException(e); - } - } - - public POIXMLDocumentPart newDocumentPart(POIXMLRelation descriptor){ - try { - Class cls = descriptor.getRelationClass(); - Constructor constructor = cls.getDeclaredConstructor(); - return constructor.newInstance(); - } catch (Exception e){ - throw new POIXMLException(e); - } - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xssf.usermodel; + +import org.apache.poi.POIXMLDocumentPart; +import org.apache.poi.POIXMLFactory; +import org.apache.poi.POIXMLException; +import org.apache.poi.POIXMLRelation; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.openxml4j.opc.PackagePart; + +import java.lang.reflect.Constructor; + +/** + * Instantiates sub-classes of POIXMLDocumentPart depending on their relationship type + * + * @author Yegor Kozlov + */ +public final class XSSFFactory extends POIXMLFactory { + private static POILogger logger = POILogFactory.getLogger(XSSFFactory.class); + + private XSSFFactory(){ + + } + + private static final XSSFFactory inst = new XSSFFactory(); + + public static XSSFFactory getInstance(){ + return inst; + } + + public POIXMLDocumentPart createDocumentPart(PackageRelationship rel, PackagePart part){ + POIXMLRelation descriptor = XSSFRelation.getInstance(rel.getRelationshipType()); + if(descriptor == null || descriptor.getRelationClass() == null){ + logger.log(POILogger.DEBUG, "using default POIXMLDocumentPart for " + rel.getRelationshipType()); + return new POIXMLDocumentPart(part, rel); + } + + try { + Class cls = descriptor.getRelationClass(); + Constructor constructor = cls.getDeclaredConstructor(PackagePart.class, PackageRelationship.class); + return constructor.newInstance(part, rel); + } catch (Exception e){ + throw new POIXMLException(e); + } + } + + public POIXMLDocumentPart newDocumentPart(POIXMLRelation descriptor){ + try { + Class cls = descriptor.getRelationClass(); + Constructor constructor = cls.getDeclaredConstructor(); + return constructor.newInstance(); + } catch (Exception e){ + throw new POIXMLException(e); + } + } + +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPicture.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPicture.java index e58b58377b..ef548e7b97 100755 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPicture.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPicture.java @@ -1,349 +1,350 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xssf.usermodel; - -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.*; -import org.openxmlformats.schemas.drawingml.x2006.main.*; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCol; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.ss.usermodel.Picture; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.POIXMLDocumentPart; -import org.apache.poi.openxml4j.opc.PackageRelationship; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.w3c.dom.NodeList; -import org.w3c.dom.Element; -import javax.imageio.ImageIO; -import javax.imageio.ImageReader; -import javax.imageio.stream.ImageInputStream; -import java.awt.*; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.util.Iterator; - -/** - * Represents a picture shape in a SpreadsheetML drawing. - * - * @author Yegor Kozlov - */ -public class XSSFPicture extends XSSFShape implements Picture { - private static final POILogger logger = POILogFactory.getLogger(XSSFPicture.class); - - /** - * Column width measured as the number of characters of the maximum digit width of the - * numbers 0, 1, 2, ..., 9 as rendered in the normal style's font. There are 4 pixels of margin - * padding (two on each side), plus 1 pixel padding for the gridlines. - * - * This value is the same for default font in Office 2007 (Calibry) and Office 2003 and earlier (Arial) - */ - private static float DEFAULT_COLUMN_WIDTH = 9.140625f; - - /** - * A default instance of CTShape used for creating new shapes. - */ - private static CTPicture prototype = null; - - /** - * This object specifies a picture object and all its properties - */ - private CTPicture ctPicture; - - /** - * Construct a new XSSFPicture object. This constructor is called from - * {@link XSSFDrawing#createPicture(XSSFClientAnchor, int)} - * - * @param drawing the XSSFDrawing that owns this picture - */ - protected XSSFPicture(XSSFDrawing drawing, CTPicture ctPicture){ - this.drawing = drawing; - this.ctPicture = ctPicture; - } - - /** - * Returns a prototype that is used to construct new shapes - * - * @return a prototype that is used to construct new shapes - */ - protected static CTPicture prototype(){ - if(prototype == null) { - CTPicture pic = CTPicture.Factory.newInstance(); - CTPictureNonVisual nvpr = pic.addNewNvPicPr(); - CTNonVisualDrawingProps nvProps = nvpr.addNewCNvPr(); - nvProps.setId(1); - nvProps.setName("Picture 1"); - nvProps.setDescr("Picture"); - CTNonVisualPictureProperties nvPicProps = nvpr.addNewCNvPicPr(); - nvPicProps.addNewPicLocks().setNoChangeAspect(true); - - CTBlipFillProperties blip = pic.addNewBlipFill(); - blip.addNewBlip().setEmbed(""); - blip.addNewStretch().addNewFillRect(); - - CTShapeProperties sppr = pic.addNewSpPr(); - CTTransform2D t2d = sppr.addNewXfrm(); - CTPositiveSize2D ext = t2d.addNewExt(); - //should be original picture width and height expressed in EMUs - ext.setCx(0); - ext.setCy(0); - - CTPoint2D off = t2d.addNewOff(); - off.setX(0); - off.setY(0); - - CTPresetGeometry2D prstGeom = sppr.addNewPrstGeom(); - prstGeom.setPrst(STShapeType.RECT); - prstGeom.addNewAvLst(); - - prototype = pic; - } - return prototype; - } - - /** - * Link this shape with the picture data - * - * @param rel relationship referring the picture data - */ - protected void setPictureReference(PackageRelationship rel){ - ctPicture.getBlipFill().getBlip().setEmbed(rel.getId()); - } - - /** - * Return the underlying CTPicture bean that holds all properties for this picture - * - * @return the underlying CTPicture bean - */ - public CTPicture getCTPicture(){ - return ctPicture; - } - - /** - * Reset the image to the original size. - */ - public void resize(){ - resize(1.0); - } - - /** - * Reset the image to the original size. - * - * @param scale the amount by which image dimensions are multiplied relative to the original size. - * resize(1.0) sets the original size, resize(0.5) resize to 50% of the original, - * resize(2.0) resizes to 200% of the original. - */ - public void resize(double scale){ - XSSFClientAnchor anchor = (XSSFClientAnchor)getAnchor(); - - XSSFClientAnchor pref = getPreferredSize(scale); - - int row2 = anchor.getRow1() + (pref.getRow2() - pref.getRow1()); - int col2 = anchor.getCol1() + (pref.getCol2() - pref.getCol1()); - - anchor.setCol2(col2); - anchor.setDx1(0); - anchor.setDx2(pref.getDx2()); - - anchor.setRow2(row2); - anchor.setDy1(0); - anchor.setDy2(pref.getDy2()); - } - - /** - * Calculate the preferred size for this picture. - * - * @return XSSFClientAnchor with the preferred size for this image - */ - public XSSFClientAnchor getPreferredSize(){ - return getPreferredSize(1); - } - - /** - * Calculate the preferred size for this picture. - * - * @param scale the amount by which image dimensions are multiplied relative to the original size. - * @return XSSFClientAnchor with the preferred size for this image - */ - public XSSFClientAnchor getPreferredSize(double scale){ - XSSFClientAnchor anchor = (XSSFClientAnchor)getAnchor(); - - XSSFPictureData data = getPictureData(); - Dimension size = getImageDimension(data.getPackagePart(), data.getPictureType()); - double scaledWidth = size.getWidth() * scale; - double scaledHeight = size.getHeight() * scale; - - float w = 0; - int col2 = anchor.getCol1(); - int dx2 = 0; - if(anchor.getDx1() > 0){ - w += getColumnWidthInPixels(col2) - anchor.getDx1(); - col2++; - } - - for (;;) { - w += getColumnWidthInPixels(col2); - if(w > scaledWidth) break; - col2++; - } - - if(w > scaledWidth) { - double cw = getColumnWidthInPixels(col2 + 1); - double delta = w - scaledWidth; - dx2 = (int)(EMU_PER_PIXEL*(cw-delta)); - } - anchor.setCol2(col2); - anchor.setDx2(dx2); - - double h = 0; - int row2 = anchor.getRow1(); - int dy2 = 0; - - if(anchor.getDy1() > 0){ - h += getRowHeightInPixels(row2) - anchor.getDy1(); - row2++; - } - - for (;;) { - h += getRowHeightInPixels(row2); - if(h > scaledHeight) break; - row2++; - } - - if(h > scaledHeight) { - double ch = getRowHeightInPixels(row2 + 1); - double delta = h - scaledHeight; - dy2 = (int)(EMU_PER_PIXEL*(ch-delta)); - } - anchor.setRow2(row2); - anchor.setDy2(dy2); - - CTPositiveSize2D size2d = ctPicture.getSpPr().getXfrm().getExt(); - size2d.setCx((long)(scaledWidth*EMU_PER_PIXEL)); - size2d.setCy((long)(scaledHeight*EMU_PER_PIXEL)); - - return anchor; - } - - private float getColumnWidthInPixels(int columnIndex){ - XSSFSheet sheet = (XSSFSheet)getDrawing().getParent(); - - CTCol col = sheet.getColumnHelper().getColumn(columnIndex, false); - double numChars = col == null || !col.isSetWidth() ? DEFAULT_COLUMN_WIDTH : col.getWidth(); - - return (float)numChars*XSSFWorkbook.DEFAULT_CHARACTER_WIDTH; - } - - private float getRowHeightInPixels(int rowIndex){ - XSSFSheet sheet = (XSSFSheet)getDrawing().getParent(); - - XSSFRow row = sheet.getRow(rowIndex); - float height = row != null ? row.getHeightInPoints() : sheet.getDefaultRowHeightInPoints(); - return height*PIXEL_DPI/POINT_DPI; - } - - /** - * Return the dimension of this image - * - * @param part the package part holding raw picture data - * @param type type of the picture: {@link Workbook#PICTURE_TYPE_JPEG}, - * {@link Workbook#PICTURE_TYPE_PNG} or {@link Workbook#PICTURE_TYPE_DIB} - * - * @return image dimension in pixels - */ - protected static Dimension getImageDimension(PackagePart part, int type){ - Dimension size = new Dimension(); - - switch (type){ - //we can calculate the preferred size only for JPEG, PNG and BMP - //other formats like WMF, EMF and PICT are not supported in Java - case Workbook.PICTURE_TYPE_JPEG: - case Workbook.PICTURE_TYPE_PNG: - case Workbook.PICTURE_TYPE_DIB: - try { - //read the image using javax.imageio.* - ImageInputStream iis = ImageIO.createImageInputStream( part.getInputStream() ); - Iterator i = ImageIO.getImageReaders( iis ); - ImageReader r = (ImageReader) i.next(); - r.setInput( iis ); - BufferedImage img = r.read(0); - - int[] dpi = getResolution(r); - - //if DPI is zero then assume standard 96 DPI - //since cannot divide by zero - if (dpi[0] == 0) dpi[0] = PIXEL_DPI; - if (dpi[1] == 0) dpi[1] = PIXEL_DPI; - - size.width = img.getWidth()*PIXEL_DPI/dpi[0]; - size.height = img.getHeight()*PIXEL_DPI/dpi[1]; - - } catch (IOException e){ - //silently return if ImageIO failed to read the image - logger.log(POILogger.WARN, e); - } - - break; - default: - logger.log(POILogger.WARN, "Only JPEG, PNG and DIB pictures can be automatically sized"); - } - return size; - } - - /** - * The metadata of PNG and JPEG can contain the width of a pixel in millimeters. - * Return the the "effective" dpi calculated as 25.4/HorizontalPixelSize - * and 25.4/VerticalPixelSize. Where 25.4 is the number of mm in inch. - * - * @return array of two elements: {horisontalPdi, verticalDpi}. - * {96, 96} is the default. - */ - protected static int[] getResolution(ImageReader r) throws IOException { - int hdpi = PIXEL_DPI, vdpi = PIXEL_DPI; - double mm2inch = 25.4; - - NodeList lst; - Element node = (Element)r.getImageMetadata(0).getAsTree("javax_imageio_1.0"); - lst = node.getElementsByTagName("HorizontalPixelSize"); - if(lst != null && lst.getLength() == 1) hdpi = (int)(mm2inch/Float.parseFloat(((Element)lst.item(0)).getAttribute("value"))); - - lst = node.getElementsByTagName("VerticalPixelSize"); - if(lst != null && lst.getLength() == 1) vdpi = (int)(mm2inch/Float.parseFloat(((Element)lst.item(0)).getAttribute("value"))); - - return new int[]{hdpi, vdpi}; - } - - /** - * Return picture data for this shape - * - * @return picture data for this shape - */ - public XSSFPictureData getPictureData() { - String blipId = ctPicture.getBlipFill().getBlip().getEmbed(); - for (POIXMLDocumentPart part : getDrawing().getRelations()) { - if(part.getPackageRelationship().getId().equals(blipId)){ - return (XSSFPictureData)part; - } - } - logger.log(POILogger.WARN, "Picture data was not found for blipId=" + blipId); - return null; - } - - protected CTShapeProperties getShapeProperties(){ - return ctPicture.getSpPr(); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xssf.usermodel; + +import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.*; +import org.openxmlformats.schemas.drawingml.x2006.main.*; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCol; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.Picture; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.POIXMLDocumentPart; +import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.w3c.dom.NodeList; +import org.w3c.dom.Element; +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.stream.ImageInputStream; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.Iterator; + +/** + * Represents a picture shape in a SpreadsheetML drawing. + * + * @author Yegor Kozlov + */ +public final class XSSFPicture extends XSSFShape implements Picture { + private static final POILogger logger = POILogFactory.getLogger(XSSFPicture.class); + + /** + * Column width measured as the number of characters of the maximum digit width of the + * numbers 0, 1, 2, ..., 9 as rendered in the normal style's font. There are 4 pixels of margin + * padding (two on each side), plus 1 pixel padding for the gridlines. + * + * This value is the same for default font in Office 2007 (Calibry) and Office 2003 and earlier (Arial) + */ + private static float DEFAULT_COLUMN_WIDTH = 9.140625f; + + /** + * A default instance of CTShape used for creating new shapes. + */ + private static CTPicture prototype = null; + + /** + * This object specifies a picture object and all its properties + */ + private CTPicture ctPicture; + + /** + * Construct a new XSSFPicture object. This constructor is called from + * {@link XSSFDrawing#createPicture(XSSFClientAnchor, int)} + * + * @param drawing the XSSFDrawing that owns this picture + */ + protected XSSFPicture(XSSFDrawing drawing, CTPicture ctPicture){ + this.drawing = drawing; + this.ctPicture = ctPicture; + } + + /** + * Returns a prototype that is used to construct new shapes + * + * @return a prototype that is used to construct new shapes + */ + protected static CTPicture prototype(){ + if(prototype == null) { + CTPicture pic = CTPicture.Factory.newInstance(); + CTPictureNonVisual nvpr = pic.addNewNvPicPr(); + CTNonVisualDrawingProps nvProps = nvpr.addNewCNvPr(); + nvProps.setId(1); + nvProps.setName("Picture 1"); + nvProps.setDescr("Picture"); + CTNonVisualPictureProperties nvPicProps = nvpr.addNewCNvPicPr(); + nvPicProps.addNewPicLocks().setNoChangeAspect(true); + + CTBlipFillProperties blip = pic.addNewBlipFill(); + blip.addNewBlip().setEmbed(""); + blip.addNewStretch().addNewFillRect(); + + CTShapeProperties sppr = pic.addNewSpPr(); + CTTransform2D t2d = sppr.addNewXfrm(); + CTPositiveSize2D ext = t2d.addNewExt(); + //should be original picture width and height expressed in EMUs + ext.setCx(0); + ext.setCy(0); + + CTPoint2D off = t2d.addNewOff(); + off.setX(0); + off.setY(0); + + CTPresetGeometry2D prstGeom = sppr.addNewPrstGeom(); + prstGeom.setPrst(STShapeType.RECT); + prstGeom.addNewAvLst(); + + prototype = pic; + } + return prototype; + } + + /** + * Link this shape with the picture data + * + * @param rel relationship referring the picture data + */ + protected void setPictureReference(PackageRelationship rel){ + ctPicture.getBlipFill().getBlip().setEmbed(rel.getId()); + } + + /** + * Return the underlying CTPicture bean that holds all properties for this picture + * + * @return the underlying CTPicture bean + */ + public CTPicture getCTPicture(){ + return ctPicture; + } + + /** + * Reset the image to the original size. + */ + public void resize(){ + resize(1.0); + } + + /** + * Reset the image to the original size. + * + * @param scale the amount by which image dimensions are multiplied relative to the original size. + * resize(1.0) sets the original size, resize(0.5) resize to 50% of the original, + * resize(2.0) resizes to 200% of the original. + */ + public void resize(double scale){ + XSSFClientAnchor anchor = (XSSFClientAnchor)getAnchor(); + + XSSFClientAnchor pref = getPreferredSize(scale); + + int row2 = anchor.getRow1() + (pref.getRow2() - pref.getRow1()); + int col2 = anchor.getCol1() + (pref.getCol2() - pref.getCol1()); + + anchor.setCol2(col2); + anchor.setDx1(0); + anchor.setDx2(pref.getDx2()); + + anchor.setRow2(row2); + anchor.setDy1(0); + anchor.setDy2(pref.getDy2()); + } + + /** + * Calculate the preferred size for this picture. + * + * @return XSSFClientAnchor with the preferred size for this image + */ + public XSSFClientAnchor getPreferredSize(){ + return getPreferredSize(1); + } + + /** + * Calculate the preferred size for this picture. + * + * @param scale the amount by which image dimensions are multiplied relative to the original size. + * @return XSSFClientAnchor with the preferred size for this image + */ + public XSSFClientAnchor getPreferredSize(double scale){ + XSSFClientAnchor anchor = (XSSFClientAnchor)getAnchor(); + + XSSFPictureData data = getPictureData(); + Dimension size = getImageDimension(data.getPackagePart(), data.getPictureType()); + double scaledWidth = size.getWidth() * scale; + double scaledHeight = size.getHeight() * scale; + + float w = 0; + int col2 = anchor.getCol1(); + int dx2 = 0; + if(anchor.getDx1() > 0){ + w += getColumnWidthInPixels(col2) - anchor.getDx1(); + col2++; + } + + for (;;) { + w += getColumnWidthInPixels(col2); + if(w > scaledWidth) break; + col2++; + } + + if(w > scaledWidth) { + double cw = getColumnWidthInPixels(col2 + 1); + double delta = w - scaledWidth; + dx2 = (int)(EMU_PER_PIXEL*(cw-delta)); + } + anchor.setCol2(col2); + anchor.setDx2(dx2); + + double h = 0; + int row2 = anchor.getRow1(); + int dy2 = 0; + + if(anchor.getDy1() > 0){ + h += getRowHeightInPixels(row2) - anchor.getDy1(); + row2++; + } + + for (;;) { + h += getRowHeightInPixels(row2); + if(h > scaledHeight) break; + row2++; + } + + if(h > scaledHeight) { + double ch = getRowHeightInPixels(row2 + 1); + double delta = h - scaledHeight; + dy2 = (int)(EMU_PER_PIXEL*(ch-delta)); + } + anchor.setRow2(row2); + anchor.setDy2(dy2); + + CTPositiveSize2D size2d = ctPicture.getSpPr().getXfrm().getExt(); + size2d.setCx((long)(scaledWidth*EMU_PER_PIXEL)); + size2d.setCy((long)(scaledHeight*EMU_PER_PIXEL)); + + return anchor; + } + + private float getColumnWidthInPixels(int columnIndex){ + XSSFSheet sheet = (XSSFSheet)getDrawing().getParent(); + + CTCol col = sheet.getColumnHelper().getColumn(columnIndex, false); + double numChars = col == null || !col.isSetWidth() ? DEFAULT_COLUMN_WIDTH : col.getWidth(); + + return (float)numChars*XSSFWorkbook.DEFAULT_CHARACTER_WIDTH; + } + + private float getRowHeightInPixels(int rowIndex){ + XSSFSheet sheet = (XSSFSheet)getDrawing().getParent(); + + XSSFRow row = sheet.getRow(rowIndex); + float height = row != null ? row.getHeightInPoints() : sheet.getDefaultRowHeightInPoints(); + return height*PIXEL_DPI/POINT_DPI; + } + + /** + * Return the dimension of this image + * + * @param part the package part holding raw picture data + * @param type type of the picture: {@link Workbook#PICTURE_TYPE_JPEG}, + * {@link Workbook#PICTURE_TYPE_PNG} or {@link Workbook#PICTURE_TYPE_DIB} + * + * @return image dimension in pixels + */ + protected static Dimension getImageDimension(PackagePart part, int type){ + Dimension size = new Dimension(); + + switch (type){ + //we can calculate the preferred size only for JPEG, PNG and BMP + //other formats like WMF, EMF and PICT are not supported in Java + case Workbook.PICTURE_TYPE_JPEG: + case Workbook.PICTURE_TYPE_PNG: + case Workbook.PICTURE_TYPE_DIB: + try { + //read the image using javax.imageio.* + ImageInputStream iis = ImageIO.createImageInputStream( part.getInputStream() ); + Iterator i = ImageIO.getImageReaders( iis ); + ImageReader r = (ImageReader) i.next(); + r.setInput( iis ); + BufferedImage img = r.read(0); + + int[] dpi = getResolution(r); + + //if DPI is zero then assume standard 96 DPI + //since cannot divide by zero + if (dpi[0] == 0) dpi[0] = PIXEL_DPI; + if (dpi[1] == 0) dpi[1] = PIXEL_DPI; + + size.width = img.getWidth()*PIXEL_DPI/dpi[0]; + size.height = img.getHeight()*PIXEL_DPI/dpi[1]; + + } catch (IOException e){ + //silently return if ImageIO failed to read the image + logger.log(POILogger.WARN, e); + } + + break; + default: + logger.log(POILogger.WARN, "Only JPEG, PNG and DIB pictures can be automatically sized"); + } + return size; + } + + /** + * The metadata of PNG and JPEG can contain the width of a pixel in millimeters. + * Return the the "effective" dpi calculated as 25.4/HorizontalPixelSize + * and 25.4/VerticalPixelSize. Where 25.4 is the number of mm in inch. + * + * @return array of two elements: {horisontalPdi, verticalDpi}. + * {96, 96} is the default. + */ + protected static int[] getResolution(ImageReader r) throws IOException { + int hdpi = PIXEL_DPI, vdpi = PIXEL_DPI; + double mm2inch = 25.4; + + NodeList lst; + Element node = (Element)r.getImageMetadata(0).getAsTree("javax_imageio_1.0"); + lst = node.getElementsByTagName("HorizontalPixelSize"); + if(lst != null && lst.getLength() == 1) hdpi = (int)(mm2inch/Float.parseFloat(((Element)lst.item(0)).getAttribute("value"))); + + lst = node.getElementsByTagName("VerticalPixelSize"); + if(lst != null && lst.getLength() == 1) vdpi = (int)(mm2inch/Float.parseFloat(((Element)lst.item(0)).getAttribute("value"))); + + return new int[]{hdpi, vdpi}; + } + + /** + * Return picture data for this shape + * + * @return picture data for this shape + */ + public XSSFPictureData getPictureData() { + String blipId = ctPicture.getBlipFill().getBlip().getEmbed(); + for (POIXMLDocumentPart part : getDrawing().getRelations()) { + if(part.getPackageRelationship().getId().equals(blipId)){ + return (XSSFPictureData)part; + } + } + logger.log(POILogger.WARN, "Picture data was not found for blipId=" + blipId); + return null; + } + + protected CTShapeProperties getShapeProperties(){ + return ctPicture.getSpPr(); + } + +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShape.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShape.java index cd6c2208df..4734a26fa5 100755 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShape.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShape.java @@ -1,150 +1,151 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xssf.usermodel; - -import org.openxmlformats.schemas.drawingml.x2006.main.*; - -/** - * Represents a shape in a SpreadsheetML drawing. - * - * @author Yegor Kozlov - */ -public abstract class XSSFShape { - public static final int EMU_PER_PIXEL = 9525; - public static final int EMU_PER_POINT = 12700; - - public static final int POINT_DPI = 72; - public static final int PIXEL_DPI = 96; - - /** - * Parent drawing - */ - protected XSSFDrawing drawing; - - /** - * The parent shape, always not-null for shapes in groups - */ - protected XSSFShapeGroup parent; - - /** - * anchor that is used by this shape - */ - protected XSSFAnchor anchor; - - /** - * Return the drawing that owns this shape - * - * @return the parent drawing that owns this shape - */ - public XSSFDrawing getDrawing(){ - return drawing; - } - - /** - * Gets the parent shape. - */ - public XSSFShapeGroup getParent() - { - return parent; - } - - /** - * @return the anchor that is used by this shape. - */ - public XSSFAnchor getAnchor() - { - return anchor; - } - - /** - * Returns xml bean with shape properties. - * - * @return xml bean with shape properties. - */ - protected abstract CTShapeProperties getShapeProperties(); - - /** - * Whether this shape is not filled with a color - * - * @return true if this shape is not filled with a color. - */ - public boolean isNoFill() { - return getShapeProperties().isSetNoFill(); - } - - /** - * Sets whether this shape is filled or transparent. - * - * @param noFill if true then no fill will be applied to the shape element. - */ - public void setNoFill(boolean noFill) { - CTShapeProperties props = getShapeProperties(); - //unset solid and pattern fills if they are set - if (props.isSetPattFill()) props.unsetPattFill(); - if (props.isSetSolidFill()) props.unsetSolidFill(); - - props.setNoFill(CTNoFillProperties.Factory.newInstance()); - } - - /** - * Sets the color used to fill this shape using the solid fill pattern. - */ - public void setFillColor(int red, int green, int blue) { - CTShapeProperties props = getShapeProperties(); - CTSolidColorFillProperties fill = props.isSetSolidFill() ? props.getSolidFill() : props.addNewSolidFill(); - CTSRgbColor rgb = CTSRgbColor.Factory.newInstance(); - rgb.setVal(new byte[]{(byte)red, (byte)green, (byte)blue}); - fill.setSrgbClr(rgb); - } - - /** - * The color applied to the lines of this shape. - */ - public void setLineStyleColor( int red, int green, int blue ) { - CTShapeProperties props = getShapeProperties(); - CTLineProperties ln = props.isSetLn() ? props.getLn() : props.addNewLn(); - CTSolidColorFillProperties fill = ln.isSetSolidFill() ? ln.getSolidFill() : ln.addNewSolidFill(); - CTSRgbColor rgb = CTSRgbColor.Factory.newInstance(); - rgb.setVal(new byte[]{(byte)red, (byte)green, (byte)blue}); - fill.setSrgbClr(rgb); - } - - /** - * Specifies the width to be used for the underline stroke. - * - * @param lineWidth width in points - */ - public void setLineWidth( double lineWidth ) { - CTShapeProperties props = getShapeProperties(); - CTLineProperties ln = props.isSetLn() ? props.getLn() : props.addNewLn(); - ln.setW((int)(lineWidth*EMU_PER_POINT)); - } - - /** - * Sets the line style. - * - * @param lineStyle - */ - public void setLineStyle( int lineStyle ) { - CTShapeProperties props = getShapeProperties(); - CTLineProperties ln = props.isSetLn() ? props.getLn() : props.addNewLn(); - CTPresetLineDashProperties dashStyle = CTPresetLineDashProperties.Factory.newInstance(); - dashStyle.setVal(STPresetLineDashVal.Enum.forInt(lineStyle+1)); - ln.setPrstDash(dashStyle); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xssf.usermodel; + +import org.openxmlformats.schemas.drawingml.x2006.main.*; + +/** + * Represents a shape in a SpreadsheetML drawing. + * + * @author Yegor Kozlov + */ +public abstract class XSSFShape { + public static final int EMU_PER_PIXEL = 9525; + public static final int EMU_PER_POINT = 12700; + + public static final int POINT_DPI = 72; + public static final int PIXEL_DPI = 96; + + /** + * Parent drawing + */ + protected XSSFDrawing drawing; + + /** + * The parent shape, always not-null for shapes in groups + */ + protected XSSFShapeGroup parent; + + /** + * anchor that is used by this shape + */ + protected XSSFAnchor anchor; + + /** + * Return the drawing that owns this shape + * + * @return the parent drawing that owns this shape + */ + public XSSFDrawing getDrawing(){ + return drawing; + } + + /** + * Gets the parent shape. + */ + public XSSFShapeGroup getParent() + { + return parent; + } + + /** + * @return the anchor that is used by this shape. + */ + public XSSFAnchor getAnchor() + { + return anchor; + } + + /** + * Returns xml bean with shape properties. + * + * @return xml bean with shape properties. + */ + protected abstract CTShapeProperties getShapeProperties(); + + /** + * Whether this shape is not filled with a color + * + * @return true if this shape is not filled with a color. + */ + public boolean isNoFill() { + return getShapeProperties().isSetNoFill(); + } + + /** + * Sets whether this shape is filled or transparent. + * + * @param noFill if true then no fill will be applied to the shape element. + */ + public void setNoFill(boolean noFill) { + CTShapeProperties props = getShapeProperties(); + //unset solid and pattern fills if they are set + if (props.isSetPattFill()) props.unsetPattFill(); + if (props.isSetSolidFill()) props.unsetSolidFill(); + + props.setNoFill(CTNoFillProperties.Factory.newInstance()); + } + + /** + * Sets the color used to fill this shape using the solid fill pattern. + */ + public void setFillColor(int red, int green, int blue) { + CTShapeProperties props = getShapeProperties(); + CTSolidColorFillProperties fill = props.isSetSolidFill() ? props.getSolidFill() : props.addNewSolidFill(); + CTSRgbColor rgb = CTSRgbColor.Factory.newInstance(); + rgb.setVal(new byte[]{(byte)red, (byte)green, (byte)blue}); + fill.setSrgbClr(rgb); + } + + /** + * The color applied to the lines of this shape. + */ + public void setLineStyleColor( int red, int green, int blue ) { + CTShapeProperties props = getShapeProperties(); + CTLineProperties ln = props.isSetLn() ? props.getLn() : props.addNewLn(); + CTSolidColorFillProperties fill = ln.isSetSolidFill() ? ln.getSolidFill() : ln.addNewSolidFill(); + CTSRgbColor rgb = CTSRgbColor.Factory.newInstance(); + rgb.setVal(new byte[]{(byte)red, (byte)green, (byte)blue}); + fill.setSrgbClr(rgb); + } + + /** + * Specifies the width to be used for the underline stroke. + * + * @param lineWidth width in points + */ + public void setLineWidth( double lineWidth ) { + CTShapeProperties props = getShapeProperties(); + CTLineProperties ln = props.isSetLn() ? props.getLn() : props.addNewLn(); + ln.setW((int)(lineWidth*EMU_PER_POINT)); + } + + /** + * Sets the line style. + * + * @param lineStyle + */ + public void setLineStyle( int lineStyle ) { + CTShapeProperties props = getShapeProperties(); + CTLineProperties ln = props.isSetLn() ? props.getLn() : props.addNewLn(); + CTPresetLineDashProperties dashStyle = CTPresetLineDashProperties.Factory.newInstance(); + dashStyle.setVal(STPresetLineDashVal.Enum.forInt(lineStyle+1)); + ln.setPrstDash(dashStyle); + } + +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShapeGroup.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShapeGroup.java index ac6b1268ba..de2c22cdc2 100755 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShapeGroup.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFShapeGroup.java @@ -1,185 +1,186 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xssf.usermodel; - -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.*; -import org.openxmlformats.schemas.drawingml.x2006.main.*; -import org.apache.poi.openxml4j.opc.PackageRelationship; - -/** - * This object specifies a group shape that represents many shapes grouped together. This shape is to be treated - * just as if it were a regular shape but instead of being described by a single geometry it is made up of all the - * shape geometries encompassed within it. Within a group shape each of the shapes that make up the group are - * specified just as they normally would. - * - * @author Yegor Kozlov - */ -public class XSSFShapeGroup extends XSSFShape { - private static CTGroupShape prototype = null; - - private CTGroupShape ctGroup; - - /** - * Construct a new XSSFSimpleShape object. - * - * @param drawing the XSSFDrawing that owns this shape - * @param ctGroup the XML bean that stores this group content - */ - protected XSSFShapeGroup(XSSFDrawing drawing, CTGroupShape ctGroup) { - this.drawing = drawing; - this.ctGroup = ctGroup; - } - - /** - * Initialize default structure of a new shape group - */ - protected static CTGroupShape prototype() { - if (prototype == null) { - CTGroupShape shape = CTGroupShape.Factory.newInstance(); - - CTGroupShapeNonVisual nv = shape.addNewNvGrpSpPr(); - CTNonVisualDrawingProps nvpr = nv.addNewCNvPr(); - nvpr.setId(0); - nvpr.setName("Group 0"); - nv.addNewCNvGrpSpPr(); - CTGroupShapeProperties sp = shape.addNewGrpSpPr(); - CTGroupTransform2D t2d = sp.addNewXfrm(); - CTPositiveSize2D p1 = t2d.addNewExt(); - p1.setCx(0); - p1.setCy(0); - CTPoint2D p2 = t2d.addNewOff(); - p2.setX(0); - p2.setY(0); - CTPositiveSize2D p3 = t2d.addNewChExt(); - p3.setCx(0); - p3.setCy(0); - CTPoint2D p4 = t2d.addNewChOff(); - p4.setX(0); - p4.setY(0); - - prototype = shape; - } - return prototype; - } - - /** - * Constructs a textbox. - * - * @param anchor the child anchor describes how this shape is attached - * to the group. - * @return the newly created textbox. - */ - public XSSFTextBox createTextbox(XSSFChildAnchor anchor){ - CTShape ctShape = ctGroup.addNewSp(); - ctShape.set(XSSFSimpleShape.prototype()); - - XSSFTextBox shape = new XSSFTextBox(getDrawing(), ctShape); - shape.parent = this; - shape.anchor = anchor; - shape.getCTShape().getSpPr().setXfrm(anchor.getCTTransform2D()); - return shape; - - } - /** - * Creates a simple shape. This includes such shapes as lines, rectangles, - * and ovals. - * - * @param anchor the child anchor describes how this shape is attached - * to the group. - * @return the newly created shape. - */ - public XSSFSimpleShape createSimpleShape(XSSFChildAnchor anchor) { - CTShape ctShape = ctGroup.addNewSp(); - ctShape.set(XSSFSimpleShape.prototype()); - - XSSFSimpleShape shape = new XSSFSimpleShape(getDrawing(), ctShape); - shape.parent = this; - shape.anchor = anchor; - shape.getCTShape().getSpPr().setXfrm(anchor.getCTTransform2D()); - return shape; - } - - /** - * Creates a simple shape. This includes such shapes as lines, rectangles, - * and ovals. - * - * @param anchor the child anchor describes how this shape is attached - * to the group. - * @return the newly created shape. - */ - public XSSFConnector createConnector(XSSFChildAnchor anchor) { - CTConnector ctShape = ctGroup.addNewCxnSp(); - ctShape.set(XSSFConnector.prototype()); - - XSSFConnector shape = new XSSFConnector(getDrawing(), ctShape); - shape.parent = this; - shape.anchor = anchor; - shape.getCTConnector().getSpPr().setXfrm(anchor.getCTTransform2D()); - return shape; - } - - /** - * Creates a picture. - * - * @param anchor the client anchor describes how this picture is attached to the sheet. - * @param pictureIndex the index of the picture in the workbook collection of pictures, - * {@link XSSFWorkbook#getAllPictures()} . - * @return the newly created picture shape. - */ - public XSSFPicture createPicture(XSSFClientAnchor anchor, int pictureIndex) { - PackageRelationship rel = getDrawing().addPictureReference(pictureIndex); - - CTPicture ctShape = ctGroup.addNewPic(); - ctShape.set(XSSFPicture.prototype()); - - XSSFPicture shape = new XSSFPicture(getDrawing(), ctShape); - shape.parent = this; - shape.anchor = anchor; - shape.setPictureReference(rel); - return shape; - } - - public CTGroupShape getCTGroupShape() { - return ctGroup; - } - - /** - * Sets the coordinate space of this group. All children are constrained - * to these coordinates. - */ - public void setCoordinates(int x1, int y1, int x2, int y2) { - CTGroupTransform2D t2d = ctGroup.getGrpSpPr().getXfrm(); - CTPoint2D off = t2d.getOff(); - off.setX(x1); - off.setY(y1); - CTPositiveSize2D ext = t2d.getExt(); - ext.setCx(x2); - ext.setCy(y2); - - CTPoint2D chOff = t2d.getChOff(); - chOff.setX(x1); - chOff.setY(y1); - CTPositiveSize2D chExt = t2d.getChExt(); - chExt.setCx(x2); - chExt.setCy(y2); - } - - protected CTShapeProperties getShapeProperties() { - throw new IllegalStateException("Not supported for shape group"); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xssf.usermodel; + +import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.*; +import org.openxmlformats.schemas.drawingml.x2006.main.*; +import org.apache.poi.openxml4j.opc.PackageRelationship; + +/** + * This object specifies a group shape that represents many shapes grouped together. This shape is to be treated + * just as if it were a regular shape but instead of being described by a single geometry it is made up of all the + * shape geometries encompassed within it. Within a group shape each of the shapes that make up the group are + * specified just as they normally would. + * + * @author Yegor Kozlov + */ +public final class XSSFShapeGroup extends XSSFShape { + private static CTGroupShape prototype = null; + + private CTGroupShape ctGroup; + + /** + * Construct a new XSSFSimpleShape object. + * + * @param drawing the XSSFDrawing that owns this shape + * @param ctGroup the XML bean that stores this group content + */ + protected XSSFShapeGroup(XSSFDrawing drawing, CTGroupShape ctGroup) { + this.drawing = drawing; + this.ctGroup = ctGroup; + } + + /** + * Initialize default structure of a new shape group + */ + protected static CTGroupShape prototype() { + if (prototype == null) { + CTGroupShape shape = CTGroupShape.Factory.newInstance(); + + CTGroupShapeNonVisual nv = shape.addNewNvGrpSpPr(); + CTNonVisualDrawingProps nvpr = nv.addNewCNvPr(); + nvpr.setId(0); + nvpr.setName("Group 0"); + nv.addNewCNvGrpSpPr(); + CTGroupShapeProperties sp = shape.addNewGrpSpPr(); + CTGroupTransform2D t2d = sp.addNewXfrm(); + CTPositiveSize2D p1 = t2d.addNewExt(); + p1.setCx(0); + p1.setCy(0); + CTPoint2D p2 = t2d.addNewOff(); + p2.setX(0); + p2.setY(0); + CTPositiveSize2D p3 = t2d.addNewChExt(); + p3.setCx(0); + p3.setCy(0); + CTPoint2D p4 = t2d.addNewChOff(); + p4.setX(0); + p4.setY(0); + + prototype = shape; + } + return prototype; + } + + /** + * Constructs a textbox. + * + * @param anchor the child anchor describes how this shape is attached + * to the group. + * @return the newly created textbox. + */ + public XSSFTextBox createTextbox(XSSFChildAnchor anchor){ + CTShape ctShape = ctGroup.addNewSp(); + ctShape.set(XSSFSimpleShape.prototype()); + + XSSFTextBox shape = new XSSFTextBox(getDrawing(), ctShape); + shape.parent = this; + shape.anchor = anchor; + shape.getCTShape().getSpPr().setXfrm(anchor.getCTTransform2D()); + return shape; + + } + /** + * Creates a simple shape. This includes such shapes as lines, rectangles, + * and ovals. + * + * @param anchor the child anchor describes how this shape is attached + * to the group. + * @return the newly created shape. + */ + public XSSFSimpleShape createSimpleShape(XSSFChildAnchor anchor) { + CTShape ctShape = ctGroup.addNewSp(); + ctShape.set(XSSFSimpleShape.prototype()); + + XSSFSimpleShape shape = new XSSFSimpleShape(getDrawing(), ctShape); + shape.parent = this; + shape.anchor = anchor; + shape.getCTShape().getSpPr().setXfrm(anchor.getCTTransform2D()); + return shape; + } + + /** + * Creates a simple shape. This includes such shapes as lines, rectangles, + * and ovals. + * + * @param anchor the child anchor describes how this shape is attached + * to the group. + * @return the newly created shape. + */ + public XSSFConnector createConnector(XSSFChildAnchor anchor) { + CTConnector ctShape = ctGroup.addNewCxnSp(); + ctShape.set(XSSFConnector.prototype()); + + XSSFConnector shape = new XSSFConnector(getDrawing(), ctShape); + shape.parent = this; + shape.anchor = anchor; + shape.getCTConnector().getSpPr().setXfrm(anchor.getCTTransform2D()); + return shape; + } + + /** + * Creates a picture. + * + * @param anchor the client anchor describes how this picture is attached to the sheet. + * @param pictureIndex the index of the picture in the workbook collection of pictures, + * {@link XSSFWorkbook#getAllPictures()} . + * @return the newly created picture shape. + */ + public XSSFPicture createPicture(XSSFClientAnchor anchor, int pictureIndex) { + PackageRelationship rel = getDrawing().addPictureReference(pictureIndex); + + CTPicture ctShape = ctGroup.addNewPic(); + ctShape.set(XSSFPicture.prototype()); + + XSSFPicture shape = new XSSFPicture(getDrawing(), ctShape); + shape.parent = this; + shape.anchor = anchor; + shape.setPictureReference(rel); + return shape; + } + + public CTGroupShape getCTGroupShape() { + return ctGroup; + } + + /** + * Sets the coordinate space of this group. All children are constrained + * to these coordinates. + */ + public void setCoordinates(int x1, int y1, int x2, int y2) { + CTGroupTransform2D t2d = ctGroup.getGrpSpPr().getXfrm(); + CTPoint2D off = t2d.getOff(); + off.setX(x1); + off.setY(y1); + CTPositiveSize2D ext = t2d.getExt(); + ext.setCx(x2); + ext.setCy(y2); + + CTPoint2D chOff = t2d.getChOff(); + chOff.setX(x1); + chOff.setY(y1); + CTPositiveSize2D chExt = t2d.getChExt(); + chExt.setCx(x2); + chExt.setCy(y2); + } + + protected CTShapeProperties getShapeProperties() { + throw new IllegalStateException("Not supported for shape group"); + } + +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java index d5dd19c1ba..3667c8cbb7 100755 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSimpleShape.java @@ -1,179 +1,180 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xssf.usermodel; - -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTShape; -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTShapeNonVisual; -import org.openxmlformats.schemas.drawingml.x2006.main.*; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.*; - -/** - * Represents a shape with a predefined geometry in a SpreadsheetML drawing. - * Possible shape types are defined in {@link org.apache.poi.ss.usermodel.ShapeTypes} - * - * @author Yegor Kozlov - */ -public class XSSFSimpleShape extends XSSFShape { - /** - * A default instance of CTShape used for creating new shapes. - */ - private static CTShape prototype = null; - - /** - * Xml bean that stores properties of this shape - */ - private CTShape ctShape; - - protected XSSFSimpleShape(XSSFDrawing drawing, CTShape ctShape) { - this.drawing = drawing; - this.ctShape = ctShape; - } - - /** - * Prototype with the default structure of a new auto-shape. - */ - protected static CTShape prototype() { - if(prototype == null) { - CTShape shape = CTShape.Factory.newInstance(); - - CTShapeNonVisual nv = shape.addNewNvSpPr(); - CTNonVisualDrawingProps nvp = nv.addNewCNvPr(); - nvp.setId(1); - nvp.setName("Shape 1"); - nv.addNewCNvSpPr(); - - CTShapeProperties sp = shape.addNewSpPr(); - CTTransform2D t2d = sp.addNewXfrm(); - CTPositiveSize2D p1 = t2d.addNewExt(); - p1.setCx(0); - p1.setCy(0); - CTPoint2D p2 = t2d.addNewOff(); - p2.setX(0); - p2.setY(0); - - CTPresetGeometry2D geom = sp.addNewPrstGeom(); - geom.setPrst(STShapeType.RECT); - geom.addNewAvLst(); - - CTShapeStyle style = shape.addNewStyle(); - CTSchemeColor scheme = style.addNewLnRef().addNewSchemeClr(); - scheme.setVal(STSchemeColorVal.ACCENT_1); - scheme.addNewShade().setVal(50000); - style.getLnRef().setIdx(2); - - CTStyleMatrixReference fillref = style.addNewFillRef(); - fillref.setIdx(1); - fillref.addNewSchemeClr().setVal(STSchemeColorVal.ACCENT_1); - - CTStyleMatrixReference effectRef = style.addNewEffectRef(); - effectRef.setIdx(0); - effectRef.addNewSchemeClr().setVal(STSchemeColorVal.ACCENT_1); - - CTFontReference fontRef = style.addNewFontRef(); - fontRef.setIdx(STFontCollectionIndex.MINOR); - fontRef.addNewSchemeClr().setVal(STSchemeColorVal.LT_1); - - CTTextBody body = shape.addNewTxBody(); - CTTextBodyProperties bodypr = body.addNewBodyPr(); - bodypr.setAnchor(STTextAnchoringType.CTR); - bodypr.setRtlCol(false); - CTTextParagraph p = body.addNewP(); - p.addNewPPr().setAlgn(STTextAlignType.CTR); - CTTextCharacterProperties endPr = p.addNewEndParaRPr(); - endPr.setLang("en-US"); - endPr.setSz(1100); - - body.addNewLstStyle(); - - prototype = shape; - } - return prototype; - } - - public CTShape getCTShape(){ - return ctShape; - } - - /** - * Gets the shape type, one of the constants defined in {@link org.apache.poi.ss.usermodel.ShapeTypes}. - * - * @return the shape type - * @see org.apache.poi.ss.usermodel.ShapeTypes - */ - public int getShapeType() { - return ctShape.getSpPr().getPrstGeom().getPrst().intValue(); - } - - /** - * Sets the shape types. - * - * @param type the shape type, one of the constants defined in {@link org.apache.poi.ss.usermodel.ShapeTypes}. - * @see org.apache.poi.ss.usermodel.ShapeTypes - */ - public void setShapeType(int type) { - ctShape.getSpPr().getPrstGeom().setPrst(STShapeType.Enum.forInt(type)); - } - - protected CTShapeProperties getShapeProperties(){ - return ctShape.getSpPr(); - } - - public void setText(XSSFRichTextString str){ - - XSSFWorkbook wb = (XSSFWorkbook)getDrawing().getParent().getParent(); - str.setStylesTableReference(wb.getStylesSource()); - - CTTextParagraph p = CTTextParagraph.Factory.newInstance(); - if(str.numFormattingRuns() == 0){ - CTRegularTextRun r = p.addNewR(); - CTTextCharacterProperties rPr = r.addNewRPr(); - rPr.setLang("en-US"); - rPr.setSz(1100); - r.setT(str.getString()); - - } else { - for (int i = 0; i < str.getCTRst().sizeOfRArray(); i++) { - CTRElt lt = str.getCTRst().getRArray(i); - CTRPrElt ltPr = lt.getRPr(); - - CTRegularTextRun r = p.addNewR(); - CTTextCharacterProperties rPr = r.addNewRPr(); - rPr.setLang("en-US"); - - applyAttributes(ltPr, rPr); - - r.setT(lt.getT()); - } - } - ctShape.getTxBody().setPArray(new CTTextParagraph[]{p}); - - } - - /** - * - * CTRPrElt --> CTFont adapter - */ - private static void applyAttributes(CTRPrElt pr, CTTextCharacterProperties rPr){ - - if(pr.sizeOfBArray() > 0) rPr.setB(pr.getBArray(0).getVal()); - //if(pr.sizeOfUArray() > 0) rPr.setU(pr.getUArray(0).getVal()); - if(pr.sizeOfIArray() > 0) rPr.setI(pr.getIArray(0).getVal()); - - CTTextFont rFont = rPr.addNewLatin(); - rFont.setTypeface(pr.sizeOfRFontArray() > 0 ? pr.getRFontArray(0).getVal() : "Arial"); - } -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xssf.usermodel; + +import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTShape; +import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTShapeNonVisual; +import org.openxmlformats.schemas.drawingml.x2006.main.*; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.*; + +/** + * Represents a shape with a predefined geometry in a SpreadsheetML drawing. + * Possible shape types are defined in {@link org.apache.poi.ss.usermodel.ShapeTypes} + * + * @author Yegor Kozlov + */ +public class XSSFSimpleShape extends XSSFShape { // TODO - instantiable superclass + /** + * A default instance of CTShape used for creating new shapes. + */ + private static CTShape prototype = null; + + /** + * Xml bean that stores properties of this shape + */ + private CTShape ctShape; + + protected XSSFSimpleShape(XSSFDrawing drawing, CTShape ctShape) { + this.drawing = drawing; + this.ctShape = ctShape; + } + + /** + * Prototype with the default structure of a new auto-shape. + */ + protected static CTShape prototype() { + if(prototype == null) { + CTShape shape = CTShape.Factory.newInstance(); + + CTShapeNonVisual nv = shape.addNewNvSpPr(); + CTNonVisualDrawingProps nvp = nv.addNewCNvPr(); + nvp.setId(1); + nvp.setName("Shape 1"); + nv.addNewCNvSpPr(); + + CTShapeProperties sp = shape.addNewSpPr(); + CTTransform2D t2d = sp.addNewXfrm(); + CTPositiveSize2D p1 = t2d.addNewExt(); + p1.setCx(0); + p1.setCy(0); + CTPoint2D p2 = t2d.addNewOff(); + p2.setX(0); + p2.setY(0); + + CTPresetGeometry2D geom = sp.addNewPrstGeom(); + geom.setPrst(STShapeType.RECT); + geom.addNewAvLst(); + + CTShapeStyle style = shape.addNewStyle(); + CTSchemeColor scheme = style.addNewLnRef().addNewSchemeClr(); + scheme.setVal(STSchemeColorVal.ACCENT_1); + scheme.addNewShade().setVal(50000); + style.getLnRef().setIdx(2); + + CTStyleMatrixReference fillref = style.addNewFillRef(); + fillref.setIdx(1); + fillref.addNewSchemeClr().setVal(STSchemeColorVal.ACCENT_1); + + CTStyleMatrixReference effectRef = style.addNewEffectRef(); + effectRef.setIdx(0); + effectRef.addNewSchemeClr().setVal(STSchemeColorVal.ACCENT_1); + + CTFontReference fontRef = style.addNewFontRef(); + fontRef.setIdx(STFontCollectionIndex.MINOR); + fontRef.addNewSchemeClr().setVal(STSchemeColorVal.LT_1); + + CTTextBody body = shape.addNewTxBody(); + CTTextBodyProperties bodypr = body.addNewBodyPr(); + bodypr.setAnchor(STTextAnchoringType.CTR); + bodypr.setRtlCol(false); + CTTextParagraph p = body.addNewP(); + p.addNewPPr().setAlgn(STTextAlignType.CTR); + CTTextCharacterProperties endPr = p.addNewEndParaRPr(); + endPr.setLang("en-US"); + endPr.setSz(1100); + + body.addNewLstStyle(); + + prototype = shape; + } + return prototype; + } + + public CTShape getCTShape(){ + return ctShape; + } + + /** + * Gets the shape type, one of the constants defined in {@link org.apache.poi.ss.usermodel.ShapeTypes}. + * + * @return the shape type + * @see org.apache.poi.ss.usermodel.ShapeTypes + */ + public int getShapeType() { + return ctShape.getSpPr().getPrstGeom().getPrst().intValue(); + } + + /** + * Sets the shape types. + * + * @param type the shape type, one of the constants defined in {@link org.apache.poi.ss.usermodel.ShapeTypes}. + * @see org.apache.poi.ss.usermodel.ShapeTypes + */ + public void setShapeType(int type) { + ctShape.getSpPr().getPrstGeom().setPrst(STShapeType.Enum.forInt(type)); + } + + protected CTShapeProperties getShapeProperties(){ + return ctShape.getSpPr(); + } + + public void setText(XSSFRichTextString str){ + + XSSFWorkbook wb = (XSSFWorkbook)getDrawing().getParent().getParent(); + str.setStylesTableReference(wb.getStylesSource()); + + CTTextParagraph p = CTTextParagraph.Factory.newInstance(); + if(str.numFormattingRuns() == 0){ + CTRegularTextRun r = p.addNewR(); + CTTextCharacterProperties rPr = r.addNewRPr(); + rPr.setLang("en-US"); + rPr.setSz(1100); + r.setT(str.getString()); + + } else { + for (int i = 0; i < str.getCTRst().sizeOfRArray(); i++) { + CTRElt lt = str.getCTRst().getRArray(i); + CTRPrElt ltPr = lt.getRPr(); + + CTRegularTextRun r = p.addNewR(); + CTTextCharacterProperties rPr = r.addNewRPr(); + rPr.setLang("en-US"); + + applyAttributes(ltPr, rPr); + + r.setT(lt.getT()); + } + } + ctShape.getTxBody().setPArray(new CTTextParagraph[]{p}); + + } + + /** + * + * CTRPrElt --> CTFont adapter + */ + private static void applyAttributes(CTRPrElt pr, CTTextCharacterProperties rPr){ + + if(pr.sizeOfBArray() > 0) rPr.setB(pr.getBArray(0).getVal()); + //if(pr.sizeOfUArray() > 0) rPr.setU(pr.getUArray(0).getVal()); + if(pr.sizeOfIArray() > 0) rPr.setI(pr.getIArray(0).getVal()); + + CTTextFont rFont = rPr.addNewLatin(); + rFont.setTypeface(pr.sizeOfRFontArray() > 0 ? pr.getRFontArray(0).getVal() : "Arial"); + } +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextBox.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextBox.java index a708a759fd..027f83bf2e 100755 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextBox.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextBox.java @@ -1,32 +1,32 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xssf.usermodel; - -import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.*; - -/** - * Represents a text box in a SpreadsheetML drawing. - * - * @author Yegor Kozlov - */ -public class XSSFTextBox extends XSSFSimpleShape { - - protected XSSFTextBox(XSSFDrawing drawing, CTShape ctShape) { - super(drawing, ctShape); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xssf.usermodel; + +import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.*; + +/** + * Represents a text box in a SpreadsheetML drawing. + * + * @author Yegor Kozlov + */ +public final class XSSFTextBox extends XSSFSimpleShape { + + protected XSSFTextBox(XSSFDrawing drawing, CTShape ctShape) { + super(drawing, ctShape); + } +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java index 26fdad839c..9facfe8f28 100755 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java @@ -1,189 +1,190 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.xssf.usermodel.helpers; - -import org.apache.poi.xssf.usermodel.*; -import org.apache.poi.ss.util.CellRangeAddress; -import org.apache.poi.ss.formula.FormulaParser; -import org.apache.poi.ss.formula.FormulaType; -import org.apache.poi.ss.formula.FormulaRenderer; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.hssf.record.formula.FormulaShifter; -import org.apache.poi.hssf.record.formula.Ptg; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellFormula; - -import java.util.List; -import java.util.ArrayList; - -/** - * @author Yegor Kozlov - */ -public class XSSFRowShifter { - private final XSSFSheet sheet; - - public XSSFRowShifter(XSSFSheet sh) { - sheet = sh; - } - - /** - * Shift merged regions - * - * @param startRow the row to start shifting - * @param endRow the row to end shifting - * @param n the number of rows to shift - * @return an array of affected cell regions - */ - public List shiftMerged(int startRow, int endRow, int n) { - List shiftedRegions = new ArrayList(); - //move merged regions completely if they fall within the new region boundaries when they are shifted - for (int i = 0; i < sheet.getNumMergedRegions(); i++) { - CellRangeAddress merged = sheet.getMergedRegion(i); - - boolean inStart = (merged.getFirstRow() >= startRow || merged.getLastRow() >= startRow); - boolean inEnd = (merged.getFirstRow() <= endRow || merged.getLastRow() <= endRow); - - //don't check if it's not within the shifted area - if (!inStart || !inEnd) { - continue; - } - - //only shift if the region outside the shifted rows is not merged too - if (!containsCell(merged, startRow - 1, 0) && !containsCell(merged, endRow + 1, 0)) { - merged.setFirstRow(merged.getFirstRow() + n); - merged.setLastRow(merged.getLastRow() + n); - //have to remove/add it back - shiftedRegions.add(merged); - sheet.removeMergedRegion(i); - i = i - 1; // we have to back up now since we removed one - } - } - - //read so it doesn't get shifted again - for (CellRangeAddress region : shiftedRegions) { - sheet.addMergedRegion(region); - } - return shiftedRegions; - } - - /** - * Check if the row and column are in the specified cell range - * - * @param cr the cell range to check in - * @param rowIx the row to check - * @param colIx the column to check - * @return true if the range contains the cell [rowIx,colIx] - */ - private static boolean containsCell(CellRangeAddress cr, int rowIx, int colIx) { - if (cr.getFirstRow() <= rowIx && cr.getLastRow() >= rowIx - && cr.getFirstColumn() <= colIx && cr.getLastColumn() >= colIx) { - return true; - } - return false; - } - - /** - * Updated named ranges - */ - public void updateNamedRanges(FormulaShifter shifter) { - XSSFWorkbook wb = sheet.getWorkbook(); - XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb); - for (int i = 0; i < wb.getNumberOfNames(); i++) { - XSSFName name = wb.getNameAt(i); - String formula = name.getRefersToFormula(); - int sheetIndex = name.getSheetIndex(); - - Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.NAMEDRANGE, sheetIndex); - if (shifter.adjustFormula(ptgs, sheetIndex)) { - String shiftedFmla = FormulaRenderer.toFormulaString(fpb, ptgs); - name.setRefersToFormula(shiftedFmla); - } - - } - } - - /** - * Update formulas. - */ - public void updateFormulas(FormulaShifter shifter) { - //update formulas on the parent sheet - updateSheetFormulas(sheet, shifter); - - //update formulas on other sheets - XSSFWorkbook wb = sheet.getWorkbook(); - for (XSSFSheet sh : wb) { - if (sheet == sh) continue; - updateSheetFormulas(sh, shifter); - } - } - - private void updateSheetFormulas(XSSFSheet sh, FormulaShifter shifter) { - for (Row r : sh) { - XSSFRow row = (XSSFRow) r; - updateRowFormulas(row, shifter); - } - } - - private void updateRowFormulas(XSSFRow row, FormulaShifter shifter) { - for (Cell c : row) { - XSSFCell cell = (XSSFCell) c; - - CTCell ctCell = cell.getCTCell(); - if (ctCell.isSetF()) { - CTCellFormula f = ctCell.getF(); - String formula = f.getStringValue(); - if (formula.length() > 0) { - String shiftedFormula = shiftFormula(row, formula, shifter); - if (shiftedFormula != null) { - f.setStringValue(shiftedFormula); - } - } - - if (f.isSetRef()) { //Range of cells which the formula applies to. - String ref = f.getRef(); - String shiftedRef = shiftFormula(row, ref, shifter); - if (shiftedRef != null) f.setRef(shiftedRef); - } - } - - } - } - - /** - * Shift a formula using the supplied FormulaShifter - * - * @param row the row of the cell this formula belongs to. Used to get a reference to the parent workbook. - * @param formula the formula to shift - * @param shifter the FormulaShifter object that operates on the parsed formula tokens - * @return the shifted formula if the formula was changed, - * null if the formula wasn't modified - */ - private static String shiftFormula(XSSFRow row, String formula, FormulaShifter shifter) { - XSSFSheet sheet = row.getSheet(); - XSSFWorkbook wb = sheet.getWorkbook(); - int sheetIndex = wb.getSheetIndex(sheet); - XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb); - Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.CELL, sheetIndex); - String shiftedFmla = null; - if (shifter.adjustFormula(ptgs, sheetIndex)) { - shiftedFmla = FormulaRenderer.toFormulaString(fpb, ptgs); - } - return shiftedFmla; - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xssf.usermodel.helpers; + +import org.apache.poi.xssf.usermodel.*; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.ss.formula.FormulaParser; +import org.apache.poi.ss.formula.FormulaType; +import org.apache.poi.ss.formula.FormulaRenderer; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.hssf.record.formula.FormulaShifter; +import org.apache.poi.hssf.record.formula.Ptg; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellFormula; + +import java.util.List; +import java.util.ArrayList; + +/** + * @author Yegor Kozlov + */ +public final class XSSFRowShifter { + private final XSSFSheet sheet; + + public XSSFRowShifter(XSSFSheet sh) { + sheet = sh; + } + + /** + * Shift merged regions + * + * @param startRow the row to start shifting + * @param endRow the row to end shifting + * @param n the number of rows to shift + * @return an array of affected cell regions + */ + public List shiftMerged(int startRow, int endRow, int n) { + List shiftedRegions = new ArrayList(); + //move merged regions completely if they fall within the new region boundaries when they are shifted + for (int i = 0; i < sheet.getNumMergedRegions(); i++) { + CellRangeAddress merged = sheet.getMergedRegion(i); + + boolean inStart = (merged.getFirstRow() >= startRow || merged.getLastRow() >= startRow); + boolean inEnd = (merged.getFirstRow() <= endRow || merged.getLastRow() <= endRow); + + //don't check if it's not within the shifted area + if (!inStart || !inEnd) { + continue; + } + + //only shift if the region outside the shifted rows is not merged too + if (!containsCell(merged, startRow - 1, 0) && !containsCell(merged, endRow + 1, 0)) { + merged.setFirstRow(merged.getFirstRow() + n); + merged.setLastRow(merged.getLastRow() + n); + //have to remove/add it back + shiftedRegions.add(merged); + sheet.removeMergedRegion(i); + i = i - 1; // we have to back up now since we removed one + } + } + + //read so it doesn't get shifted again + for (CellRangeAddress region : shiftedRegions) { + sheet.addMergedRegion(region); + } + return shiftedRegions; + } + + /** + * Check if the row and column are in the specified cell range + * + * @param cr the cell range to check in + * @param rowIx the row to check + * @param colIx the column to check + * @return true if the range contains the cell [rowIx,colIx] + */ + private static boolean containsCell(CellRangeAddress cr, int rowIx, int colIx) { + if (cr.getFirstRow() <= rowIx && cr.getLastRow() >= rowIx + && cr.getFirstColumn() <= colIx && cr.getLastColumn() >= colIx) { + return true; + } + return false; + } + + /** + * Updated named ranges + */ + public void updateNamedRanges(FormulaShifter shifter) { + XSSFWorkbook wb = sheet.getWorkbook(); + XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb); + for (int i = 0; i < wb.getNumberOfNames(); i++) { + XSSFName name = wb.getNameAt(i); + String formula = name.getRefersToFormula(); + int sheetIndex = name.getSheetIndex(); + + Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.NAMEDRANGE, sheetIndex); + if (shifter.adjustFormula(ptgs, sheetIndex)) { + String shiftedFmla = FormulaRenderer.toFormulaString(fpb, ptgs); + name.setRefersToFormula(shiftedFmla); + } + + } + } + + /** + * Update formulas. + */ + public void updateFormulas(FormulaShifter shifter) { + //update formulas on the parent sheet + updateSheetFormulas(sheet, shifter); + + //update formulas on other sheets + XSSFWorkbook wb = sheet.getWorkbook(); + for (XSSFSheet sh : wb) { + if (sheet == sh) continue; + updateSheetFormulas(sh, shifter); + } + } + + private void updateSheetFormulas(XSSFSheet sh, FormulaShifter shifter) { + for (Row r : sh) { + XSSFRow row = (XSSFRow) r; + updateRowFormulas(row, shifter); + } + } + + private void updateRowFormulas(XSSFRow row, FormulaShifter shifter) { + for (Cell c : row) { + XSSFCell cell = (XSSFCell) c; + + CTCell ctCell = cell.getCTCell(); + if (ctCell.isSetF()) { + CTCellFormula f = ctCell.getF(); + String formula = f.getStringValue(); + if (formula.length() > 0) { + String shiftedFormula = shiftFormula(row, formula, shifter); + if (shiftedFormula != null) { + f.setStringValue(shiftedFormula); + } + } + + if (f.isSetRef()) { //Range of cells which the formula applies to. + String ref = f.getRef(); + String shiftedRef = shiftFormula(row, ref, shifter); + if (shiftedRef != null) f.setRef(shiftedRef); + } + } + + } + } + + /** + * Shift a formula using the supplied FormulaShifter + * + * @param row the row of the cell this formula belongs to. Used to get a reference to the parent workbook. + * @param formula the formula to shift + * @param shifter the FormulaShifter object that operates on the parsed formula tokens + * @return the shifted formula if the formula was changed, + * null if the formula wasn't modified + */ + private static String shiftFormula(XSSFRow row, String formula, FormulaShifter shifter) { + XSSFSheet sheet = row.getSheet(); + XSSFWorkbook wb = sheet.getWorkbook(); + int sheetIndex = wb.getSheetIndex(sheet); + XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb); + Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.CELL, sheetIndex); + String shiftedFmla = null; + if (shifter.adjustFormula(ptgs, sheetIndex)) { + shiftedFmla = FormulaRenderer.toFormulaString(fpb, ptgs); + } + return shiftedFmla; + } + +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/Borders.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/Borders.java index fd0b635654..3b2a90baec 100755 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/Borders.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/Borders.java @@ -1,626 +1,626 @@ -/* ==================================================================== - 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.xwpf.usermodel; - -import java.util.HashMap; -import java.util.Map; - -/** - * Specifies all types of borders which can be specified for WordprocessingML - * objects which have a border. Borders can be separated into two types: - *

    - *
  • Line borders: which specify a pattern to be used when drawing a line around the - * specified object. - *
  • - *
  • Art borders: which specify a repeated image to be used - * when drawing a border around the specified object. Line borders may be - * specified on any object which allows a border, however, art borders may only - * be used as a border at the page level - the borders under the pgBorders - * element - *
  • - *
- * @author Gisella Bronzetti - */ -public enum Borders { - - NIL(1), - - NONE(2), - - /** - * Specifies a line border consisting of a single line around the parent - * object. - */ - SINGLE(3), - - THICK(4), - - DOUBLE(5), - - DOTTED(6), - - DASHED(7), - - DOT_DASH(8), - - DOT_DOT_DASH(9), - - TRIPLE(10), - - THIN_THICK_SMALL_GAP(11), - - THICK_THIN_SMALL_GAP(12), - - THIN_THICK_THIN_SMALL_GAP(13), - - THIN_THICK_MEDIUM_GAP(14), - - THICK_THIN_MEDIUM_GAP(15), - - THIN_THICK_THIN_MEDIUM_GAP(16), - - THIN_THICK_LARGE_GAP(17), - - THICK_THIN_LARGE_GAP(18), - - THIN_THICK_THIN_LARGE_GAP(19), - - WAVE(20), - - DOUBLE_WAVE(21), - - DASH_SMALL_GAP(22), - - DASH_DOT_STROKED(23), - - THREE_D_EMBOSS(24), - - THREE_D_ENGRAVE(25), - - OUTSET(26), - - INSET(27), - - /** - * Specifies an art border consisting of a repeated image of an apple - */ - APPLES(28), - - /** - * Specifies an art border consisting of a repeated image of a shell pattern - */ - ARCHED_SCALLOPS(29), - - /** - * Specifies an art border consisting of a repeated image of a baby pacifier - */ - BABY_PACIFIER(30), - - /** - * Specifies an art border consisting of a repeated image of a baby rattle - */ - BABY_RATTLE(31), - - /** - * Specifies an art border consisting of a repeated image of a set of - * balloons - */ - BALLOONS_3_COLORS(32), - - /** - * Specifies an art border consisting of a repeated image of a hot air - * balloon - */ - BALLOONS_HOT_AIR(33), - - /** - * Specifies an art border consisting of a repeating image of a black and - * white background. - */ - BASIC_BLACK_DASHES(34), - - /** - * Specifies an art border consisting of a repeating image of a black dot on - * a white background. - */ - BASIC_BLACK_DOTS(35), - - /** - * Specifies an art border consisting of a repeating image of a black and - * white background - */ - BASIC_BLACK_SQUARES(36), - - /** - * Specifies an art border consisting of a repeating image of a black and - * white background. - */ - BASIC_THIN_LINES(37), - - /** - * Specifies an art border consisting of a repeating image of a black and - * white background. - */ - BASIC_WHITE_DASHES(38), - - /** - * Specifies an art border consisting of a repeating image of a white dot on - * a black background. - */ - BASIC_WHITE_DOTS(39), - - /** - * Specifies an art border consisting of a repeating image of a black and - * white background. - */ - BASIC_WHITE_SQUARES(40), - - /** - * Specifies an art border consisting of a repeating image of a black and - * white background. - */ - BASIC_WIDE_INLINE(41), - - /** - * Specifies an art border consisting of a repeating image of a black and - * white background - */ - BASIC_WIDE_MIDLINE(42), - - /** - * Specifies an art border consisting of a repeating image of a black and - * white background - */ - BASIC_WIDE_OUTLINE(43), - - /** - * Specifies an art border consisting of a repeated image of bats - */ - BATS(44), - - /** - * Specifies an art border consisting of repeating images of birds - */ - BIRDS(45), - - /** - * Specifies an art border consisting of a repeated image of birds flying - */ - BIRDS_FLIGHT(46), - - /** - * Specifies an art border consisting of a repeated image of a cabin - */ - CABINS(47), - - /** - * Specifies an art border consisting of a repeated image of a piece of cake - */ - CAKE_SLICE(48), - - /** - * Specifies an art border consisting of a repeated image of candy corn - */ - CANDY_CORN(49), - - /** - * Specifies an art border consisting of a repeated image of a knot work - * pattern - */ - CELTIC_KNOTWORK(50), - - /** - * Specifies an art border consisting of a banner. - *

- * If the border is on the left or right, no border is displayed. - *

- */ - CERTIFICATE_BANNER(51), - - /** - * Specifies an art border consisting of a repeating image of a chain link - * pattern. - */ - CHAIN_LINK(52), - - /** - * Specifies an art border consisting of a repeated image of a champagne - * bottle - */ - CHAMPAGNE_BOTTLE(53), - - /** - * Specifies an art border consisting of repeating images of a compass - */ - CHECKED_BAR_BLACK(54), - - /** - * Specifies an art border consisting of a repeating image of a colored - * pattern. - */ - CHECKED_BAR_COLOR(55), - - /** - * Specifies an art border consisting of a repeated image of a checkerboard - */ - CHECKERED(56), - - /** - * Specifies an art border consisting of a repeated image of a Christmas - * tree - */ - CHRISTMAS_TREE(57), - - /** - * Specifies an art border consisting of repeating images of lines and - * circles - */ - CIRCLES_LINES(58), - - /** - * Specifies an art border consisting of a repeated image of a rectangular - * pattern - */ - CIRCLES_RECTANGLES(59), - - /** - * Specifies an art border consisting of a repeated image of a wave - */ - CLASSICAL_WAVE(60), - - /** - * Specifies an art border consisting of a repeated image of a clock - */ - CLOCKS(61), - - /** - * Specifies an art border consisting of repeating images of a compass - */ - COMPASS(62), - - /** - * Specifies an art border consisting of a repeated image of confetti - */ - CONFETTI(63), - - /** - * Specifies an art border consisting of a repeated image of confetti - */ - CONFETTI_GRAYS(64), - - /** - * Specifies an art border consisting of a repeated image of confetti - */ - CONFETTI_OUTLINE(65), - - /** - * Specifies an art border consisting of a repeated image of confetti - * streamers - */ - CONFETTI_STREAMERS(66), - - /** - * Specifies an art border consisting of a repeated image of confetti - */ - CONFETTI_WHITE(67), - - /** - * Specifies an art border consisting of a repeated image - */ - CORNER_TRIANGLES(68), - - /** - * Specifies an art border consisting of a dashed line - */ - COUPON_CUTOUT_DASHES(69), - - /** - * Specifies an art border consisting of a dotted line - */ - COUPON_CUTOUT_DOTS(70), - - /** - * Specifies an art border consisting of a repeated image of a maze-like - * pattern - */ - CRAZY_MAZE(71), - - /** - * Specifies an art border consisting of a repeated image of a butterfly - */ - CREATURES_BUTTERFLY(72), - - /** - * Specifies an art border consisting of a repeated image of a fish - */ - CREATURES_FISH(73), - - /** - * Specifies an art border consisting of repeating images of insects. - */ - CREATURES_INSECTS(74), - - /** - * Specifies an art border consisting of a repeated image of a ladybug - */ - CREATURES_LADY_BUG(75), - - /** - * Specifies an art border consisting of repeating images of a cross-stitch - * pattern - */ - CROSS_STITCH(76), - - /** - * Specifies an art border consisting of a repeated image of Cupid - */ - CUP(77), - - DECO_ARCH(78), - - DECO_ARCH_COLOR(79), - - DECO_BLOCKS(80), - - DIAMONDS_GRAY(81), - - DOUBLE_D(82), - - DOUBLE_DIAMONDS(83), - - EARTH_1(84), - - EARTH_2(85), - - ECLIPSING_SQUARES_1(86), - - ECLIPSING_SQUARES_2(87), - - EGGS_BLACK(88), - - FANS(89), - - FILM(90), - - FIRECRACKERS(91), - - FLOWERS_BLOCK_PRINT(92), - - FLOWERS_DAISIES(93), - - FLOWERS_MODERN_1(94), - - FLOWERS_MODERN_2(95), - - FLOWERS_PANSY(96), - - FLOWERS_RED_ROSE(97), - - FLOWERS_ROSES(98), - - FLOWERS_TEACUP(99), - - FLOWERS_TINY(100), - - GEMS(101), - - GINGERBREAD_MAN(102), - - GRADIENT(103), - - HANDMADE_1(104), - - HANDMADE_2(105), - - HEART_BALLOON(106), - - HEART_GRAY(107), - - HEARTS(108), - - HEEBIE_JEEBIES(109), - - HOLLY(110), - - HOUSE_FUNKY(111), - - HYPNOTIC(112), - - ICE_CREAM_CONES(113), - - LIGHT_BULB(114), - - LIGHTNING_1(115), - - LIGHTNING_2(116), - - MAP_PINS(117), - - MAPLE_LEAF(118), - - MAPLE_MUFFINS(119), - - MARQUEE(120), - - MARQUEE_TOOTHED(121), - - MOONS(122), - - MOSAIC(123), - - MUSIC_NOTES(124), - - NORTHWEST(125), - - OVALS(126), - - PACKAGES(127), - - PALMS_BLACK(128), - - PALMS_COLOR(129), - - PAPER_CLIPS(130), - - PAPYRUS(131), - - PARTY_FAVOR(132), - - PARTY_GLASS(133), - - PENCILS(134), - - PEOPLE(135), - - PEOPLE_WAVING(136), - - PEOPLE_HATS(137), - - POINSETTIAS(138), - - POSTAGE_STAMP(139), - - PUMPKIN_1(140), - - PUSH_PIN_NOTE_2(141), - - PUSH_PIN_NOTE_1(142), - - PYRAMIDS(143), - - PYRAMIDS_ABOVE(144), - - QUADRANTS(145), - - RINGS(146), - - SAFARI(147), - - SAWTOOTH(148), - - SAWTOOTH_GRAY(149), - - SCARED_CAT(150), - - SEATTLE(151), - - SHADOWED_SQUARES(152), - - SHARKS_TEETH(153), - - SHOREBIRD_TRACKS(154), - - SKYROCKET(155), - - SNOWFLAKE_FANCY(156), - - SNOWFLAKES(157), - - SOMBRERO(158), - - SOUTHWEST(159), - - STARS(160), - - STARS_TOP(161), - - STARS_3_D(162), - - STARS_BLACK(163), - - STARS_SHADOWED(164), - - SUN(165), - - SWIRLIGIG(166), - - TORN_PAPER(167), - - TORN_PAPER_BLACK(168), - - TREES(169), - - TRIANGLE_PARTY(170), - - TRIANGLES(171), - - TRIBAL_1(172), - - TRIBAL_2(173), - - TRIBAL_3(174), - - TRIBAL_4(175), - - TRIBAL_5(176), - - TRIBAL_6(177), - - TWISTED_LINES_1(178), - - TWISTED_LINES_2(179), - - VINE(180), - - WAVELINE(181), - - WEAVING_ANGLES(182), - - WEAVING_BRAID(183), - - WEAVING_RIBBON(184), - - WEAVING_STRIPS(185), - - WHITE_FLOWERS(186), - - WOODWORK(187), - - X_ILLUSIONS(188), - - ZANY_TRIANGLES(189), - - ZIG_ZAG(190), - - ZIG_ZAG_STITCH(191); - - private final int value; - - private Borders(int val) { - value = val; - } - - public int getValue() { - return value; - } - - private static Map imap = new HashMap(); - static { - for (Borders p : values()) { - imap.put(p.getValue(), p); - } - } - - public static Borders valueOf(int type) { - Borders pBorder = imap.get(type); - if (pBorder == null) - throw new IllegalArgumentException("Unknown paragraph border: " - + type); - return pBorder; - } - -} +/* ==================================================================== + 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.xwpf.usermodel; + +import java.util.HashMap; +import java.util.Map; + +/** + * Specifies all types of borders which can be specified for WordprocessingML + * objects which have a border. Borders can be separated into two types: + *
    + *
  • Line borders: which specify a pattern to be used when drawing a line around the + * specified object. + *
  • + *
  • Art borders: which specify a repeated image to be used + * when drawing a border around the specified object. Line borders may be + * specified on any object which allows a border, however, art borders may only + * be used as a border at the page level - the borders under the pgBorders + * element + *
  • + *
+ * @author Gisella Bronzetti + */ +public enum Borders { + + NIL(1), + + NONE(2), + + /** + * Specifies a line border consisting of a single line around the parent + * object. + */ + SINGLE(3), + + THICK(4), + + DOUBLE(5), + + DOTTED(6), + + DASHED(7), + + DOT_DASH(8), + + DOT_DOT_DASH(9), + + TRIPLE(10), + + THIN_THICK_SMALL_GAP(11), + + THICK_THIN_SMALL_GAP(12), + + THIN_THICK_THIN_SMALL_GAP(13), + + THIN_THICK_MEDIUM_GAP(14), + + THICK_THIN_MEDIUM_GAP(15), + + THIN_THICK_THIN_MEDIUM_GAP(16), + + THIN_THICK_LARGE_GAP(17), + + THICK_THIN_LARGE_GAP(18), + + THIN_THICK_THIN_LARGE_GAP(19), + + WAVE(20), + + DOUBLE_WAVE(21), + + DASH_SMALL_GAP(22), + + DASH_DOT_STROKED(23), + + THREE_D_EMBOSS(24), + + THREE_D_ENGRAVE(25), + + OUTSET(26), + + INSET(27), + + /** + * Specifies an art border consisting of a repeated image of an apple + */ + APPLES(28), + + /** + * Specifies an art border consisting of a repeated image of a shell pattern + */ + ARCHED_SCALLOPS(29), + + /** + * Specifies an art border consisting of a repeated image of a baby pacifier + */ + BABY_PACIFIER(30), + + /** + * Specifies an art border consisting of a repeated image of a baby rattle + */ + BABY_RATTLE(31), + + /** + * Specifies an art border consisting of a repeated image of a set of + * balloons + */ + BALLOONS_3_COLORS(32), + + /** + * Specifies an art border consisting of a repeated image of a hot air + * balloon + */ + BALLOONS_HOT_AIR(33), + + /** + * Specifies an art border consisting of a repeating image of a black and + * white background. + */ + BASIC_BLACK_DASHES(34), + + /** + * Specifies an art border consisting of a repeating image of a black dot on + * a white background. + */ + BASIC_BLACK_DOTS(35), + + /** + * Specifies an art border consisting of a repeating image of a black and + * white background + */ + BASIC_BLACK_SQUARES(36), + + /** + * Specifies an art border consisting of a repeating image of a black and + * white background. + */ + BASIC_THIN_LINES(37), + + /** + * Specifies an art border consisting of a repeating image of a black and + * white background. + */ + BASIC_WHITE_DASHES(38), + + /** + * Specifies an art border consisting of a repeating image of a white dot on + * a black background. + */ + BASIC_WHITE_DOTS(39), + + /** + * Specifies an art border consisting of a repeating image of a black and + * white background. + */ + BASIC_WHITE_SQUARES(40), + + /** + * Specifies an art border consisting of a repeating image of a black and + * white background. + */ + BASIC_WIDE_INLINE(41), + + /** + * Specifies an art border consisting of a repeating image of a black and + * white background + */ + BASIC_WIDE_MIDLINE(42), + + /** + * Specifies an art border consisting of a repeating image of a black and + * white background + */ + BASIC_WIDE_OUTLINE(43), + + /** + * Specifies an art border consisting of a repeated image of bats + */ + BATS(44), + + /** + * Specifies an art border consisting of repeating images of birds + */ + BIRDS(45), + + /** + * Specifies an art border consisting of a repeated image of birds flying + */ + BIRDS_FLIGHT(46), + + /** + * Specifies an art border consisting of a repeated image of a cabin + */ + CABINS(47), + + /** + * Specifies an art border consisting of a repeated image of a piece of cake + */ + CAKE_SLICE(48), + + /** + * Specifies an art border consisting of a repeated image of candy corn + */ + CANDY_CORN(49), + + /** + * Specifies an art border consisting of a repeated image of a knot work + * pattern + */ + CELTIC_KNOTWORK(50), + + /** + * Specifies an art border consisting of a banner. + *

+ * If the border is on the left or right, no border is displayed. + *

+ */ + CERTIFICATE_BANNER(51), + + /** + * Specifies an art border consisting of a repeating image of a chain link + * pattern. + */ + CHAIN_LINK(52), + + /** + * Specifies an art border consisting of a repeated image of a champagne + * bottle + */ + CHAMPAGNE_BOTTLE(53), + + /** + * Specifies an art border consisting of repeating images of a compass + */ + CHECKED_BAR_BLACK(54), + + /** + * Specifies an art border consisting of a repeating image of a colored + * pattern. + */ + CHECKED_BAR_COLOR(55), + + /** + * Specifies an art border consisting of a repeated image of a checkerboard + */ + CHECKERED(56), + + /** + * Specifies an art border consisting of a repeated image of a Christmas + * tree + */ + CHRISTMAS_TREE(57), + + /** + * Specifies an art border consisting of repeating images of lines and + * circles + */ + CIRCLES_LINES(58), + + /** + * Specifies an art border consisting of a repeated image of a rectangular + * pattern + */ + CIRCLES_RECTANGLES(59), + + /** + * Specifies an art border consisting of a repeated image of a wave + */ + CLASSICAL_WAVE(60), + + /** + * Specifies an art border consisting of a repeated image of a clock + */ + CLOCKS(61), + + /** + * Specifies an art border consisting of repeating images of a compass + */ + COMPASS(62), + + /** + * Specifies an art border consisting of a repeated image of confetti + */ + CONFETTI(63), + + /** + * Specifies an art border consisting of a repeated image of confetti + */ + CONFETTI_GRAYS(64), + + /** + * Specifies an art border consisting of a repeated image of confetti + */ + CONFETTI_OUTLINE(65), + + /** + * Specifies an art border consisting of a repeated image of confetti + * streamers + */ + CONFETTI_STREAMERS(66), + + /** + * Specifies an art border consisting of a repeated image of confetti + */ + CONFETTI_WHITE(67), + + /** + * Specifies an art border consisting of a repeated image + */ + CORNER_TRIANGLES(68), + + /** + * Specifies an art border consisting of a dashed line + */ + COUPON_CUTOUT_DASHES(69), + + /** + * Specifies an art border consisting of a dotted line + */ + COUPON_CUTOUT_DOTS(70), + + /** + * Specifies an art border consisting of a repeated image of a maze-like + * pattern + */ + CRAZY_MAZE(71), + + /** + * Specifies an art border consisting of a repeated image of a butterfly + */ + CREATURES_BUTTERFLY(72), + + /** + * Specifies an art border consisting of a repeated image of a fish + */ + CREATURES_FISH(73), + + /** + * Specifies an art border consisting of repeating images of insects. + */ + CREATURES_INSECTS(74), + + /** + * Specifies an art border consisting of a repeated image of a ladybug + */ + CREATURES_LADY_BUG(75), + + /** + * Specifies an art border consisting of repeating images of a cross-stitch + * pattern + */ + CROSS_STITCH(76), + + /** + * Specifies an art border consisting of a repeated image of Cupid + */ + CUP(77), + + DECO_ARCH(78), + + DECO_ARCH_COLOR(79), + + DECO_BLOCKS(80), + + DIAMONDS_GRAY(81), + + DOUBLE_D(82), + + DOUBLE_DIAMONDS(83), + + EARTH_1(84), + + EARTH_2(85), + + ECLIPSING_SQUARES_1(86), + + ECLIPSING_SQUARES_2(87), + + EGGS_BLACK(88), + + FANS(89), + + FILM(90), + + FIRECRACKERS(91), + + FLOWERS_BLOCK_PRINT(92), + + FLOWERS_DAISIES(93), + + FLOWERS_MODERN_1(94), + + FLOWERS_MODERN_2(95), + + FLOWERS_PANSY(96), + + FLOWERS_RED_ROSE(97), + + FLOWERS_ROSES(98), + + FLOWERS_TEACUP(99), + + FLOWERS_TINY(100), + + GEMS(101), + + GINGERBREAD_MAN(102), + + GRADIENT(103), + + HANDMADE_1(104), + + HANDMADE_2(105), + + HEART_BALLOON(106), + + HEART_GRAY(107), + + HEARTS(108), + + HEEBIE_JEEBIES(109), + + HOLLY(110), + + HOUSE_FUNKY(111), + + HYPNOTIC(112), + + ICE_CREAM_CONES(113), + + LIGHT_BULB(114), + + LIGHTNING_1(115), + + LIGHTNING_2(116), + + MAP_PINS(117), + + MAPLE_LEAF(118), + + MAPLE_MUFFINS(119), + + MARQUEE(120), + + MARQUEE_TOOTHED(121), + + MOONS(122), + + MOSAIC(123), + + MUSIC_NOTES(124), + + NORTHWEST(125), + + OVALS(126), + + PACKAGES(127), + + PALMS_BLACK(128), + + PALMS_COLOR(129), + + PAPER_CLIPS(130), + + PAPYRUS(131), + + PARTY_FAVOR(132), + + PARTY_GLASS(133), + + PENCILS(134), + + PEOPLE(135), + + PEOPLE_WAVING(136), + + PEOPLE_HATS(137), + + POINSETTIAS(138), + + POSTAGE_STAMP(139), + + PUMPKIN_1(140), + + PUSH_PIN_NOTE_2(141), + + PUSH_PIN_NOTE_1(142), + + PYRAMIDS(143), + + PYRAMIDS_ABOVE(144), + + QUADRANTS(145), + + RINGS(146), + + SAFARI(147), + + SAWTOOTH(148), + + SAWTOOTH_GRAY(149), + + SCARED_CAT(150), + + SEATTLE(151), + + SHADOWED_SQUARES(152), + + SHARKS_TEETH(153), + + SHOREBIRD_TRACKS(154), + + SKYROCKET(155), + + SNOWFLAKE_FANCY(156), + + SNOWFLAKES(157), + + SOMBRERO(158), + + SOUTHWEST(159), + + STARS(160), + + STARS_TOP(161), + + STARS_3_D(162), + + STARS_BLACK(163), + + STARS_SHADOWED(164), + + SUN(165), + + SWIRLIGIG(166), + + TORN_PAPER(167), + + TORN_PAPER_BLACK(168), + + TREES(169), + + TRIANGLE_PARTY(170), + + TRIANGLES(171), + + TRIBAL_1(172), + + TRIBAL_2(173), + + TRIBAL_3(174), + + TRIBAL_4(175), + + TRIBAL_5(176), + + TRIBAL_6(177), + + TWISTED_LINES_1(178), + + TWISTED_LINES_2(179), + + VINE(180), + + WAVELINE(181), + + WEAVING_ANGLES(182), + + WEAVING_BRAID(183), + + WEAVING_RIBBON(184), + + WEAVING_STRIPS(185), + + WHITE_FLOWERS(186), + + WOODWORK(187), + + X_ILLUSIONS(188), + + ZANY_TRIANGLES(189), + + ZIG_ZAG(190), + + ZIG_ZAG_STITCH(191); + + private final int value; + + private Borders(int val) { + value = val; + } + + public int getValue() { + return value; + } + + private static Map imap = new HashMap(); + static { + for (Borders p : values()) { + imap.put(new Integer(p.getValue()), p); + } + } + + public static Borders valueOf(int type) { + Borders pBorder = imap.get(new Integer(type)); + if (pBorder == null) { + throw new IllegalArgumentException("Unknown paragraph border: " + type); + } + return pBorder; + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/ParagraphAlignment.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/ParagraphAlignment.java index 6c8aad1c7f..503aeca8e3 100755 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/ParagraphAlignment.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/ParagraphAlignment.java @@ -1,65 +1,66 @@ -/* ==================================================================== - 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.xwpf.usermodel; - -import java.util.Map; -import java.util.HashMap; - -/** - * Specifies all types of alignment which are available to be applied to objects in a - * WordprocessingML document - * - * @author Yegor Kozlov - */ -public enum ParagraphAlignment { - //YK: TODO document each alignment option - - LEFT(1), - CENTER(2), - RIGHT(3), - BOTH(4), - MEDIUM_KASHIDA(5), - DISTRIBUTE(6), - NUM_TAB(7), - HIGH_KASHIDA(8), - LOW_KASHIDA(9), - THAI_DISTRIBUTE(10); - - private final int value; - - private ParagraphAlignment(int val){ - value = val; - } - - public int getValue(){ - return value; - } - - private static Map imap = new HashMap(); - static{ - for (ParagraphAlignment p : values()) { - imap.put(p.getValue(), p); - } - } - - public static ParagraphAlignment valueOf(int type){ - ParagraphAlignment err = imap.get(type); - if(err == null) throw new IllegalArgumentException("Unknown paragraph alignment: " + type); - return err; - } - -} +/* ==================================================================== + 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.xwpf.usermodel; + +import java.util.Map; +import java.util.HashMap; + +/** + * Specifies all types of alignment which are available to be applied to objects in a + * WordprocessingML document + * + * @author Yegor Kozlov + */ +public enum ParagraphAlignment { + //YK: TODO document each alignment option + + LEFT(1), + CENTER(2), + RIGHT(3), + BOTH(4), + MEDIUM_KASHIDA(5), + DISTRIBUTE(6), + NUM_TAB(7), + HIGH_KASHIDA(8), + LOW_KASHIDA(9), + THAI_DISTRIBUTE(10); + + private final int value; + + private ParagraphAlignment(int val){ + value = val; + } + + public int getValue(){ + return value; + } + + private static Map imap = new HashMap(); + static{ + for (ParagraphAlignment p : values()) { + imap.put(p.getValue(), p); + } + } + + public static ParagraphAlignment valueOf(int type){ + ParagraphAlignment err = imap.get(type); + if(err == null) throw new IllegalArgumentException("Unknown paragraph alignment: " + type); + return err; + } + +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFactory.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFactory.java index 04bf13d113..02b18d9a2e 100755 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFactory.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFactory.java @@ -1,73 +1,74 @@ -/* ==================================================================== - 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.xwpf.usermodel; - -import org.apache.poi.POIXMLFactory; -import org.apache.poi.POIXMLDocumentPart; -import org.apache.poi.POIXMLException; -import org.apache.poi.POIXMLRelation; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.openxml4j.opc.PackageRelationship; -import org.apache.poi.openxml4j.opc.PackagePart; - -import java.lang.reflect.Constructor; - -/** - * @author Yegor Kozlov - */ -public class XWPFFactory extends POIXMLFactory { - - private static POILogger logger = POILogFactory.getLogger(XWPFFactory.class); - - private XWPFFactory(){ - - } - - private static final XWPFFactory inst = new XWPFFactory(); - - public static XWPFFactory getInstance(){ - return inst; - } - - public POIXMLDocumentPart createDocumentPart(PackageRelationship rel, PackagePart part){ - POIXMLRelation descriptor = XWPFRelation.getInstance(rel.getRelationshipType()); - if(descriptor == null || descriptor.getRelationClass() == null){ - logger.log(POILogger.DEBUG, "using default POIXMLDocumentPart for " + rel.getRelationshipType()); - return new POIXMLDocumentPart(part, rel); - } - - try { - Class cls = descriptor.getRelationClass(); - Constructor constructor = cls.getDeclaredConstructor(PackagePart.class, PackageRelationship.class); - return constructor.newInstance(part, rel); - } catch (Exception e){ - throw new POIXMLException(e); - } - } - - public POIXMLDocumentPart newDocumentPart(POIXMLRelation descriptor){ - try { - Class cls = descriptor.getRelationClass(); - Constructor constructor = cls.getDeclaredConstructor(); - return constructor.newInstance(); - } catch (Exception e){ - throw new POIXMLException(e); - } - } - -} +/* ==================================================================== + 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.xwpf.usermodel; + +import org.apache.poi.POIXMLFactory; +import org.apache.poi.POIXMLDocumentPart; +import org.apache.poi.POIXMLException; +import org.apache.poi.POIXMLRelation; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.openxml4j.opc.PackagePart; + +import java.lang.reflect.Constructor; + +/** + * @author Yegor Kozlov + */ +public final class XWPFFactory extends POIXMLFactory { + + private static POILogger logger = POILogFactory.getLogger(XWPFFactory.class); + + private XWPFFactory(){ + + } + + private static final XWPFFactory inst = new XWPFFactory(); + + public static XWPFFactory getInstance(){ + return inst; + } + + public POIXMLDocumentPart createDocumentPart(PackageRelationship rel, PackagePart part){ + POIXMLRelation descriptor = XWPFRelation.getInstance(rel.getRelationshipType()); + if(descriptor == null || descriptor.getRelationClass() == null){ + logger.log(POILogger.DEBUG, "using default POIXMLDocumentPart for " + rel.getRelationshipType()); + return new POIXMLDocumentPart(part, rel); + } + + try { + Class cls = descriptor.getRelationClass(); + Constructor constructor = cls.getDeclaredConstructor(PackagePart.class, PackageRelationship.class); + return constructor.newInstance(part, rel); + } catch (Exception e){ + throw new POIXMLException(e); + } + } + + public POIXMLDocumentPart newDocumentPart(POIXMLRelation descriptor){ + try { + Class cls = descriptor.getRelationClass(); + Constructor constructor = cls.getDeclaredConstructor(); + return constructor.newInstance(); + } catch (Exception e){ + throw new POIXMLException(e); + } + } + +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFRelation.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFRelation.java index b58db4a75f..5532ee299f 100755 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFRelation.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFRelation.java @@ -1,109 +1,110 @@ -/* ==================================================================== - 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.xwpf.usermodel; - -import org.apache.poi.POIXMLRelation; -import org.apache.poi.POIXMLDocumentPart; - -import java.util.Map; -import java.util.HashMap; - -/** - * @author Yegor Kozlov - */ -public class XWPFRelation extends POIXMLRelation { - - /** - * A map to lookup POIXMLRelation by its relation type - */ - protected static Map _table = new HashMap(); - - - public static final XWPFRelation DOCUMENT = new XWPFRelation( - "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument", - "/word/document.xml", - null - ); - public static final XWPFRelation FONT_TABLE = new XWPFRelation( - "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable", - "/word/fontTable.xml", - null - ); - public static final XWPFRelation SETTINGS = new XWPFRelation( - "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings", - "/word/settings.xml", - null - ); - public static final XWPFRelation STYLES = new XWPFRelation( - "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles", - "/word/styles.xml", - null - ); - public static final XWPFRelation WEB_SETTINGS = new XWPFRelation( - "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings", - "/word/webSettings.xml", - null - ); - public static final XWPFRelation HEADER = new XWPFRelation( - "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header", - "/word/header#.xml", - null - ); - public static final XWPFRelation FOOTER = new XWPFRelation( - "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer", - "/word/footer#.xml", - null - ); - public static final XWPFRelation HYPERLINK = new XWPFRelation( - null, - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", - null, - null - ); - public static final XWPFRelation COMMENT = new XWPFRelation( - null, - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments", - null, - null - ); - - - private XWPFRelation(String type, String rel, String defaultName, Class cls) { - super(type, rel, defaultName, cls); - - if (cls != null && !_table.containsKey(rel)) _table.put(rel, this); - } - - /** - * Get POIXMLRelation by relation type - * - * @param rel relation type, for example, - * http://schemas.openxmlformats.org/officeDocument/2006/relationships/image - * @return registered POIXMLRelation or null if not found - */ - public static XWPFRelation getInstance(String rel) { - return _table.get(rel); - } - -} +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xwpf.usermodel; + +import org.apache.poi.POIXMLRelation; +import org.apache.poi.POIXMLDocumentPart; + +import java.util.Map; +import java.util.HashMap; + +/** + * @author Yegor Kozlov + */ +public final class XWPFRelation extends POIXMLRelation { + + /** + * A map to lookup POIXMLRelation by its relation type + */ + protected static Map _table = new HashMap(); + + + public static final XWPFRelation DOCUMENT = new XWPFRelation( + "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument", + "/word/document.xml", + null + ); + public static final XWPFRelation FONT_TABLE = new XWPFRelation( + "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable", + "/word/fontTable.xml", + null + ); + public static final XWPFRelation SETTINGS = new XWPFRelation( + "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings", + "/word/settings.xml", + null + ); + public static final XWPFRelation STYLES = new XWPFRelation( + "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles", + "/word/styles.xml", + null + ); + public static final XWPFRelation WEB_SETTINGS = new XWPFRelation( + "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings", + "/word/webSettings.xml", + null + ); + public static final XWPFRelation HEADER = new XWPFRelation( + "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header", + "/word/header#.xml", + null + ); + public static final XWPFRelation FOOTER = new XWPFRelation( + "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer", + "/word/footer#.xml", + null + ); + public static final XWPFRelation HYPERLINK = new XWPFRelation( + null, + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", + null, + null + ); + public static final XWPFRelation COMMENT = new XWPFRelation( + null, + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments", + null, + null + ); + + + private XWPFRelation(String type, String rel, String defaultName, Class cls) { + super(type, rel, defaultName, cls); + + if (cls != null && !_table.containsKey(rel)) _table.put(rel, this); + } + + /** + * Get POIXMLRelation by relation type + * + * @param rel relation type, for example, + * http://schemas.openxmlformats.org/officeDocument/2006/relationships/image + * @return registered POIXMLRelation or null if not found + */ + public static XWPFRelation getInstance(String rel) { + return _table.get(rel); + } + +} -- 2.39.5