diff options
author | Andreas Beeker <kiwiwings@apache.org> | 2014-08-12 23:33:07 +0000 |
---|---|---|
committer | Andreas Beeker <kiwiwings@apache.org> | 2014-08-12 23:33:07 +0000 |
commit | 4f4b1bedd7ea2386281a84a2dbbc16e4da764606 (patch) | |
tree | 233fc4bd5f9b88ea3e55270eaadf4583f4b02197 /src/ooxml | |
parent | 9bf516734409aa54781c39f1b5e152f2652a3cf8 (diff) | |
parent | effe9463eecb25de2a55f205d03926e1ccd8d773 (diff) | |
download | poi-4f4b1bedd7ea2386281a84a2dbbc16e4da764606.tar.gz poi-4f4b1bedd7ea2386281a84a2dbbc16e4da764606.zip |
sync merge to trunk
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/xml_signature@1617624 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/ooxml')
18 files changed, 585 insertions, 632 deletions
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 40141befc8..9109f28f30 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/Configuration.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/Configuration.java @@ -21,7 +21,7 @@ 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 ? + * TODO xml syntax checking is not done with JAXP by default -> remove the schema or do it ? * * @author CDubettier, Julen Chable * @version 1.0 diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageRelationshipCollection.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageRelationshipCollection.java index bef53f4a6e..2732c825ea 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageRelationshipCollection.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageRelationshipCollection.java @@ -27,9 +27,10 @@ import org.apache.poi.openxml4j.exceptions.InvalidOperationException; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.apache.poi.util.SAXHelper; -import org.dom4j.Attribute; -import org.dom4j.Document; -import org.dom4j.Element; +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; /** * Represents a collection of PackageRelationship elements that are owned by a @@ -313,22 +314,19 @@ public final class PackageRelationshipCollection implements Document xmlRelationshipsDoc = SAXHelper.readSAXDocument(relPart.getInputStream()); // Browse default types - Element root = xmlRelationshipsDoc.getRootElement(); + Element root = xmlRelationshipsDoc.getDocumentElement(); // Check OPC compliance M4.1 rule boolean fCorePropertiesRelationship = false; - @SuppressWarnings("unchecked") - Iterator<Element> iter = (Iterator<Element>) - root.elementIterator(PackageRelationship.RELATIONSHIP_TAG_NAME); - while (iter.hasNext()) { - Element element = iter.next(); + NodeList nodeList = root.getElementsByTagName(PackageRelationship.RELATIONSHIP_TAG_NAME); + int nodeCount = nodeList.getLength(); + for (int i = 0; i < nodeCount; i++) { + Element element = (Element)nodeList.item(i); // Relationship ID - String id = element.attribute( - PackageRelationship.ID_ATTRIBUTE_NAME).getValue(); + String id = element.getAttribute(PackageRelationship.ID_ATTRIBUTE_NAME); // Relationship type - String type = element.attribute( - PackageRelationship.TYPE_ATTRIBUTE_NAME).getValue(); + String type = element.getAttribute(PackageRelationship.TYPE_ATTRIBUTE_NAME); /* Check OPC Compliance */ // Check Rule M4.1 @@ -342,8 +340,7 @@ public final class PackageRelationshipCollection implements /* End OPC Compliance */ // TargetMode (default value "Internal") - Attribute targetModeAttr = element - .attribute(PackageRelationship.TARGET_MODE_ATTRIBUTE_NAME); + Attr targetModeAttr = element.getAttributeNode(PackageRelationship.TARGET_MODE_ATTRIBUTE_NAME); TargetMode targetMode = TargetMode.INTERNAL; if (targetModeAttr != null) { targetMode = targetModeAttr.getValue().toLowerCase() @@ -353,9 +350,7 @@ public final class PackageRelationshipCollection implements // Target converted in URI URI target = PackagingURIHelper.toURI("http://invalid.uri"); // dummy url - String value = element.attribute( - PackageRelationship.TARGET_ATTRIBUTE_NAME) - .getValue(); + String value = element.getAttribute(PackageRelationship.TARGET_ATTRIBUTE_NAME); try { // when parsing of the given uri fails, we can either // ignore this relationship, which leads to IllegalStateException 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 a02264ea68..860d711590 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/StreamHelper.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/StreamHelper.java @@ -17,21 +17,36 @@ package org.apache.poi.openxml4j.opc; +import java.io.FilterOutputStream; +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import org.dom4j.Document; -import org.dom4j.io.OutputFormat; -import org.dom4j.io.XMLWriter; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.w3c.dom.Document; public final class StreamHelper { private StreamHelper() { // Do nothing } + + private static final TransformerFactory transformerFactory = TransformerFactory.newInstance(); + + private static synchronized Transformer getIdentityTransformer() throws TransformerException { + return transformerFactory.newTransformer(); + } /** - * Turning the DOM4j object in the specified output stream. + * Save the document object in the specified output stream. * * @param xmlContent * The XML document. @@ -40,18 +55,34 @@ public final class StreamHelper { * @return <b>true</b> if the xml is successfully written in the stream, * else <b>false</b>. */ - public static boolean saveXmlInStream(Document xmlContent, - OutputStream outStream) { - try { - OutputFormat outformat = OutputFormat.createPrettyPrint(); - outformat.setEncoding("UTF-8"); - XMLWriter writer = new XMLWriter(outStream, outformat); - writer.write(xmlContent); - } catch (Exception e) { - return false; - } - return true; - } + public static boolean saveXmlInStream(Document xmlContent, + OutputStream outStream) { + try { + Transformer trans = getIdentityTransformer(); + Source xmlSource = new DOMSource(xmlContent); + // prevent close of stream by transformer: + Result outputTarget = new StreamResult(new FilterOutputStream( + outStream) { + @Override + public void write(byte b[], int off, int len) + throws IOException { + out.write(b, off, len); + } + + @Override + public void close() throws IOException { + out.flush(); // only flush, don't close! + } + }); + trans.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + trans.setOutputProperty(OutputKeys.INDENT, "yes"); + trans.setOutputProperty(OutputKeys.STANDALONE, "yes"); + trans.transform(xmlSource, outputTarget); + } catch (TransformerException e) { + return false; + } + return true; + } /** * Copy the input stream into the output stream. diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ContentTypeManager.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ContentTypeManager.java index 381d26b9c8..8aa4b7d1dd 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ContentTypeManager.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ContentTypeManager.java @@ -17,12 +17,11 @@ package org.apache.poi.openxml4j.opc.internal; +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URI; import java.net.URISyntaxException; -import java.util.Iterator; -import java.util.List; import java.util.Map.Entry; import java.util.TreeMap; @@ -33,13 +32,12 @@ import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackagePartName; import org.apache.poi.openxml4j.opc.PackagingURIHelper; +import org.apache.poi.util.DocumentHelper; import org.apache.poi.util.SAXHelper; -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.DocumentHelper; -import org.dom4j.Element; -import org.dom4j.Namespace; -import org.dom4j.QName; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; /** * Manage package content types ([Content_Types].xml part). @@ -375,38 +373,33 @@ public abstract class ContentTypeManager { Document xmlContentTypetDoc = SAXHelper.readSAXDocument(in); // Default content types - List defaultTypes = xmlContentTypetDoc.getRootElement().elements( - DEFAULT_TAG_NAME); - Iterator elementIteratorDefault = defaultTypes.iterator(); - while (elementIteratorDefault.hasNext()) { - Element element = (Element) elementIteratorDefault.next(); - String extension = element.attribute(EXTENSION_ATTRIBUTE_NAME) - .getValue(); - String contentType = element.attribute( - CONTENT_TYPE_ATTRIBUTE_NAME).getValue(); + NodeList defaultTypes = xmlContentTypetDoc.getDocumentElement().getElementsByTagName(DEFAULT_TAG_NAME); + int defaultTypeCount = defaultTypes.getLength(); + for (int i = 0; i < defaultTypeCount; i++) { + Element element = (Element) defaultTypes.item(i); + String extension = element.getAttribute(EXTENSION_ATTRIBUTE_NAME); + String contentType = element.getAttribute(CONTENT_TYPE_ATTRIBUTE_NAME); addDefaultContentType(extension, contentType); } // Overriden content types - List overrideTypes = xmlContentTypetDoc.getRootElement().elements( - OVERRIDE_TAG_NAME); - Iterator elementIteratorOverride = overrideTypes.iterator(); - while (elementIteratorOverride.hasNext()) { - Element element = (Element) elementIteratorOverride.next(); - URI uri = new URI(element.attribute(PART_NAME_ATTRIBUTE_NAME) - .getValue()); - PackagePartName partName = PackagingURIHelper - .createPartName(uri); - String contentType = element.attribute( - CONTENT_TYPE_ATTRIBUTE_NAME).getValue(); + NodeList overrideTypes = xmlContentTypetDoc.getDocumentElement().getElementsByTagName(OVERRIDE_TAG_NAME); + int overrideTypeCount = overrideTypes.getLength(); + for (int i = 0; i < overrideTypeCount; i++) { + Element element = (Element) overrideTypes.item(i); + URI uri = new URI(element.getAttribute(PART_NAME_ATTRIBUTE_NAME)); + PackagePartName partName = PackagingURIHelper.createPartName(uri); + String contentType = element.getAttribute(CONTENT_TYPE_ATTRIBUTE_NAME); addOverrideContentType(partName, contentType); } } catch (URISyntaxException urie) { throw new InvalidFormatException(urie.getMessage()); - } catch (DocumentException e) { - throw new InvalidFormatException(e.getMessage()); - } - } + } catch (SAXException e) { + throw new InvalidFormatException(e.getMessage()); + } catch (IOException e) { + throw new InvalidFormatException(e.getMessage()); + } + } /** * Save the contents type part. @@ -420,9 +413,8 @@ public abstract class ContentTypeManager { Document xmlOutDoc = DocumentHelper.createDocument(); // Building namespace - Namespace dfNs = Namespace.get("", TYPES_NAMESPACE_URI); - Element typesElem = xmlOutDoc - .addElement(new QName(TYPES_TAG_NAME, dfNs)); + Element typesElem = xmlOutDoc.createElementNS(TYPES_NAMESPACE_URI, TYPES_TAG_NAME); + xmlOutDoc.appendChild(typesElem); // Adding default types for (Entry<String, String> entry : defaultContentType.entrySet()) { @@ -453,10 +445,10 @@ public abstract class ContentTypeManager { */ private void appendSpecificTypes(Element root, Entry<PackagePartName, String> entry) { - root.addElement(OVERRIDE_TAG_NAME).addAttribute( - PART_NAME_ATTRIBUTE_NAME, - entry.getKey().getName()).addAttribute( - CONTENT_TYPE_ATTRIBUTE_NAME, entry.getValue()); + Element specificType = root.getOwnerDocument().createElement(OVERRIDE_TAG_NAME); + specificType.setAttribute(PART_NAME_ATTRIBUTE_NAME, entry.getKey().getName()); + specificType.setAttribute(CONTENT_TYPE_ATTRIBUTE_NAME, entry.getValue()); + root.appendChild(specificType); } /** @@ -469,11 +461,10 @@ public abstract class ContentTypeManager { * @see #save(java.io.OutputStream) */ private void appendDefaultType(Element root, Entry<String, String> entry) { - root.addElement(DEFAULT_TAG_NAME).addAttribute( - EXTENSION_ATTRIBUTE_NAME, entry.getKey()) - .addAttribute(CONTENT_TYPE_ATTRIBUTE_NAME, - entry.getValue()); - + Element defaultType = root.getOwnerDocument().createElement(DEFAULT_TAG_NAME); + defaultType.setAttribute(EXTENSION_ATTRIBUTE_NAME, entry.getKey()); + defaultType.setAttribute(CONTENT_TYPE_ATTRIBUTE_NAME, entry.getValue()); + root.appendChild(defaultType); } /** diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/PackagePropertiesPart.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/PackagePropertiesPart.java index 44191e1443..523cdeca6f 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/PackagePropertiesPart.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/PackagePropertiesPart.java @@ -48,8 +48,6 @@ public final class PackagePropertiesPart extends PackagePart implements public final static String NAMESPACE_DCTERMS_URI = "http://purl.org/dc/terms/"; - public final static String NAMESPACE_XSI_URI = "http://www.w3.org/2001/XMLSchema-instance"; - /** * Constructor. * diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipContentTypeManager.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipContentTypeManager.java index 3491dc6424..1b9e7fe2ca 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipContentTypeManager.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipContentTypeManager.java @@ -17,8 +17,6 @@ package org.apache.poi.openxml4j.opc.internal; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -30,7 +28,7 @@ import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.StreamHelper; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; -import org.dom4j.Document; +import org.w3c.dom.Document; /** * Zip implementation of the ContentTypeManager. @@ -69,17 +67,8 @@ public class ZipContentTypeManager extends ContentTypeManager { // Referenced in ZIP zos.putNextEntry(partEntry); // Saving data in the ZIP file - ByteArrayOutputStream outTemp = new ByteArrayOutputStream(); - StreamHelper.saveXmlInStream(content, out); - InputStream ins = new ByteArrayInputStream(outTemp.toByteArray()); - byte[] buff = new byte[ZipHelper.READ_WRITE_FILE_BUFFER_SIZE]; - while (ins.available() > 0) { - int resultRead = ins.read(buff); - if (resultRead == -1) { - // end of file reached - break; - } - zos.write(buff, 0, resultRead); + if (!StreamHelper.saveXmlInStream(content, zos)) { + return false; } zos.closeEntry(); } catch (IOException ioe) { 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 1ad4d26b71..ca549f91f6 100644 --- 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 @@ -19,15 +19,18 @@ 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 javax.xml.XMLConstants; +import javax.xml.stream.XMLEventFactory; +import javax.xml.stream.events.Namespace; + 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; +import org.apache.poi.openxml4j.util.Nullable; +import org.apache.poi.util.DocumentHelper; +import org.w3c.dom.Document; +import org.w3c.dom.Element; /** * Package properties marshaller. @@ -36,17 +39,15 @@ import org.apache.poi.openxml4j.opc.internal.PartMarshaller; */ 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); + + private final static Namespace namespaceDC, namespaceCoreProperties, namespaceDcTerms, namespaceXSI; + static { + final XMLEventFactory f = XMLEventFactory.newFactory(); + namespaceDC = f.createNamespace("dc", PackagePropertiesPart.NAMESPACE_DC_URI); + namespaceCoreProperties = f.createNamespace("cp", PackagePropertiesPart.NAMESPACE_CP_URI); + namespaceDcTerms = f.createNamespace("dcterms", PackagePropertiesPart.NAMESPACE_DCTERMS_URI); + namespaceXSI = f.createNamespace("xsi", XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI); + } protected static final String KEYWORD_CATEGORY = "category"; @@ -98,13 +99,13 @@ public class PackagePropertiesMarshaller implements PartMarshaller { // 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); + Element rootElem = xmlDoc.createElementNS(namespaceCoreProperties.getNamespaceURI(), + getQName("coreProperties", namespaceCoreProperties)); + DocumentHelper.addNamespaceDeclaration(rootElem, namespaceCoreProperties); + DocumentHelper.addNamespaceDeclaration(rootElem, namespaceDC); + DocumentHelper.addNamespaceDeclaration(rootElem, namespaceDcTerms); + DocumentHelper.addNamespaceDeclaration(rootElem, namespaceXSI); + xmlDoc.appendChild(rootElem); addCategory(); addContentStatus(); @@ -125,197 +126,110 @@ public class PackagePropertiesMarshaller implements PartMarshaller { return true; } - /** + /** + * Sets the given element's text content, creating it if necessary. + */ + private Element setElementTextContent(String localName, Namespace namespace, Nullable<String> property) { + return setElementTextContent(localName, namespace, property, property.getValue()); + } + + private String getQName(String localName, Namespace namespace) { + return namespace.getPrefix().isEmpty() ? localName : namespace.getPrefix() + ':' + localName; + } + + private Element setElementTextContent(String localName, Namespace namespace, Nullable<?> property, String propertyValue) { + if (!property.hasValue()) + return null; + + Element root = xmlDoc.getDocumentElement(); + Element elem = (Element) root.getElementsByTagNameNS(namespace.getNamespaceURI(), localName).item(0); + if (elem == null) { + // missing, we add it + elem = xmlDoc.createElementNS(namespace.getNamespaceURI(), getQName(localName, namespace)); + root.appendChild(elem); + } + elem.setTextContent(propertyValue); + return elem; + } + + private Element setElementTextContent(String localName, Namespace namespace, Nullable<?> property, String propertyValue, String xsiType) { + Element element = setElementTextContent(localName, namespace, property, propertyValue); + if (element != null) { + element.setAttributeNS(namespaceXSI.getNamespaceURI(), getQName("type", namespaceXSI), xsiType); + } + return element; + } + + + /** * 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()); + setElementTextContent(KEYWORD_CATEGORY, namespaceCoreProperties, propsPart.getCategoryProperty()); } /** * 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()); + setElementTextContent(KEYWORD_CONTENT_STATUS, namespaceCoreProperties, propsPart.getContentStatusProperty()); } /** * 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()); + setElementTextContent(KEYWORD_CONTENT_TYPE, namespaceCoreProperties, propsPart.getContentTypeProperty()); } /** * 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()); + setElementTextContent(KEYWORD_CREATED, namespaceDcTerms, propsPart.getCreatedProperty(), + propsPart.getCreatedPropertyString(), "dcterms:W3CDTF"); } /** * 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()); + setElementTextContent(KEYWORD_CREATOR, namespaceDC, propsPart.getCreatorProperty()); } /** * 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()); + setElementTextContent(KEYWORD_DESCRIPTION, namespaceDC, propsPart.getDescriptionProperty()); } /** * 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()); + setElementTextContent(KEYWORD_IDENTIFIER, namespaceDC, propsPart.getIdentifierProperty()); } - /** + /** * 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()); + setElementTextContent(KEYWORD_KEYWORDS, namespaceCoreProperties, propsPart.getKeywordsProperty()); } /** * 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()); + setElementTextContent(KEYWORD_LANGUAGE, namespaceDC, propsPart.getLanguageProperty()); } /** * 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()); + setElementTextContent(KEYWORD_LAST_MODIFIED_BY, namespaceCoreProperties, propsPart.getLastModifiedByProperty()); } /** @@ -323,111 +237,39 @@ public class PackagePropertiesMarshaller implements PartMarshaller { * */ 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()); + setElementTextContent(KEYWORD_LAST_PRINTED, namespaceCoreProperties, propsPart.getLastPrintedProperty(), 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()); - } + setElementTextContent(KEYWORD_MODIFIED, namespaceDcTerms, propsPart.getModifiedProperty(), + propsPart.getModifiedPropertyString(), "dcterms:W3CDTF"); + } /** * 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()); + setElementTextContent(KEYWORD_REVISION, namespaceCoreProperties, propsPart.getRevisionProperty()); } /** * 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()); + setElementTextContent(KEYWORD_SUBJECT, namespaceDC, propsPart.getSubjectProperty()); } /** * 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()); + setElementTextContent(KEYWORD_TITLE, namespaceDC, propsPart.getTitleProperty()); } 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()); + setElementTextContent(KEYWORD_VERSION, namespaceCoreProperties, propsPart.getVersionProperty()); } } 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 4a9fec855e..37a538dc26 100644 --- 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 @@ -24,11 +24,6 @@ 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; @@ -40,8 +35,11 @@ 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.DocumentHelper; import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; /** * Zip part marshaller. This marshaller is use to save any part in a zip stream. @@ -122,9 +120,8 @@ public final class ZipPartMarshaller implements PartMarshaller { Document xmlOutDoc = DocumentHelper.createDocument(); // make something like <Relationships // xmlns="http://schemas.openxmlformats.org/package/2006/relationships"> - Namespace dfNs = Namespace.get("", PackageNamespaces.RELATIONSHIPS); - Element root = xmlOutDoc.addElement(new QName( - PackageRelationship.RELATIONSHIPS_TAG_NAME, dfNs)); + Element root = xmlOutDoc.createElementNS(PackageNamespaces.RELATIONSHIPS, PackageRelationship.RELATIONSHIPS_TAG_NAME); + xmlOutDoc.appendChild(root); // <Relationship // TargetMode="External" @@ -137,16 +134,14 @@ public final class ZipPartMarshaller implements PartMarshaller { for (PackageRelationship rel : rels) { // the relationship element - Element relElem = root - .addElement(PackageRelationship.RELATIONSHIP_TAG_NAME); + Element relElem = xmlOutDoc.createElement(PackageRelationship.RELATIONSHIP_TAG_NAME); + root.appendChild(relElem); // the relationship ID - relElem.addAttribute(PackageRelationship.ID_ATTRIBUTE_NAME, rel - .getId()); + relElem.setAttribute(PackageRelationship.ID_ATTRIBUTE_NAME, rel.getId()); // the relationship Type - relElem.addAttribute(PackageRelationship.TYPE_ATTRIBUTE_NAME, rel - .getRelationshipType()); + relElem.setAttribute(PackageRelationship.TYPE_ATTRIBUTE_NAME, rel.getRelationshipType()); // the relationship Target String targetValue; @@ -157,16 +152,13 @@ public final class ZipPartMarshaller implements PartMarshaller { targetValue = uri.toString(); // add TargetMode attribute (as it is external link external) - relElem.addAttribute( - PackageRelationship.TARGET_MODE_ATTRIBUTE_NAME, - "External"); + relElem.setAttribute(PackageRelationship.TARGET_MODE_ATTRIBUTE_NAME, "External"); } else { URI targetURI = rel.getTargetURI(); targetValue = PackagingURIHelper.relativizeURI( sourcePartURI, targetURI, true).toString(); } - relElem.addAttribute(PackageRelationship.TARGET_ATTRIBUTE_NAME, - targetValue); + relElem.setAttribute(PackageRelationship.TARGET_ATTRIBUTE_NAME, targetValue); } xmlOutDoc.normalize(); 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 6f1d62b8a0..b4e3e83723 100644 --- 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 @@ -19,10 +19,10 @@ 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 javax.xml.XMLConstants; + import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.opc.PackageNamespaces; import org.apache.poi.openxml4j.opc.PackagePart; @@ -32,12 +32,12 @@ import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart; import org.apache.poi.openxml4j.opc.internal.PartUnmarshaller; import org.apache.poi.openxml4j.opc.internal.ZipHelper; import org.apache.poi.util.SAXHelper; -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.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; /** * Package properties unmarshaller. @@ -46,21 +46,6 @@ import org.dom4j.QName; */ 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"; @@ -125,15 +110,15 @@ public final class PackagePropertiesUnmarshaller implements PartUnmarshaller { /* Check OPC compliance */ // Rule M4.2, M4.3, M4.4 and M4.5/ - checkElementForOPCCompliance(xmlDoc.getRootElement()); + checkElementForOPCCompliance(xmlDoc.getDocumentElement()); /* End OPC compliance */ - } catch (DocumentException e) { - throw new IOException(e.getMessage()); - } + } catch (SAXException e) { + throw new IOException(e.getMessage()); + } - coreProps.setCategoryProperty(loadCategory(xmlDoc)); + coreProps.setCategoryProperty(loadCategory(xmlDoc)); coreProps.setContentStatusProperty(loadContentStatus(xmlDoc)); coreProps.setContentTypeProperty(loadContentType(xmlDoc)); coreProps.setCreatedProperty(loadCreated(xmlDoc)); @@ -153,148 +138,76 @@ public final class PackagePropertiesUnmarshaller implements PartUnmarshaller { return coreProps; } + private String readElement(Document xmlDoc, String localName, String namespaceURI) { + Element el = (Element)xmlDoc.getDocumentElement().getElementsByTagNameNS(namespaceURI, localName).item(0); + if (el == null) { + return null; + } + return el.getTextContent(); + } + private String loadCategory(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_CATEGORY, namespaceCP)); - if (el == null) { - return null; - } - return el.getStringValue(); + return readElement(xmlDoc, KEYWORD_CATEGORY, PackageNamespaces.CORE_PROPERTIES); } - 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 loadContentStatus(Document xmlDoc) { + return readElement(xmlDoc, KEYWORD_CONTENT_STATUS, PackageNamespaces.CORE_PROPERTIES); } private String loadContentType(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_CONTENT_TYPE, namespaceCP)); - if (el == null) { - return null; - } - return el.getStringValue(); + return readElement(xmlDoc, KEYWORD_CONTENT_TYPE, PackageNamespaces.CORE_PROPERTIES); } private String loadCreated(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_CREATED, namespaceDcTerms)); - if (el == null) { - return null; - } - return el.getStringValue(); + return readElement(xmlDoc, KEYWORD_CREATED, PackageProperties.NAMESPACE_DCTERMS); } private String loadCreator(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_CREATOR, namespaceDC)); - if (el == null) { - return null; - } - return el.getStringValue(); + return readElement(xmlDoc, KEYWORD_CREATOR, PackageProperties.NAMESPACE_DC); } private String loadDescription(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_DESCRIPTION, namespaceDC)); - if (el == null) { - return null; - } - return el.getStringValue(); + return readElement(xmlDoc, KEYWORD_DESCRIPTION, PackageProperties.NAMESPACE_DC); } private String loadIdentifier(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_IDENTIFIER, namespaceDC)); - if (el == null) { - return null; - } - return el.getStringValue(); + return readElement(xmlDoc, KEYWORD_IDENTIFIER, PackageProperties.NAMESPACE_DC); } private String loadKeywords(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_KEYWORDS, namespaceCP)); - if (el == null) { - return null; - } - return el.getStringValue(); + return readElement(xmlDoc, KEYWORD_KEYWORDS, PackageNamespaces.CORE_PROPERTIES); } private String loadLanguage(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_LANGUAGE, namespaceDC)); - if (el == null) { - return null; - } - return el.getStringValue(); + return readElement(xmlDoc, KEYWORD_LANGUAGE, PackageProperties.NAMESPACE_DC); } 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(); + return readElement(xmlDoc, KEYWORD_LAST_MODIFIED_BY, PackageNamespaces.CORE_PROPERTIES); } private String loadLastPrinted(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_LAST_PRINTED, namespaceCP)); - if (el == null) { - return null; - } - return el.getStringValue(); + return readElement(xmlDoc, KEYWORD_LAST_PRINTED, PackageNamespaces.CORE_PROPERTIES); } private String loadModified(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_MODIFIED, namespaceDcTerms)); - if (el == null) { - return null; - } - return el.getStringValue(); + return readElement(xmlDoc, KEYWORD_MODIFIED, PackageProperties.NAMESPACE_DCTERMS); } private String loadRevision(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_REVISION, namespaceCP)); - if (el == null) { - return null; - } - return el.getStringValue(); + return readElement(xmlDoc, KEYWORD_REVISION, PackageNamespaces.CORE_PROPERTIES); } private String loadSubject(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_SUBJECT, namespaceDC)); - if (el == null) { - return null; - } - return el.getStringValue(); + return readElement(xmlDoc, KEYWORD_SUBJECT, PackageProperties.NAMESPACE_DC); } private String loadTitle(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_TITLE, namespaceDC)); - if (el == null) { - return null; - } - return el.getStringValue(); + return readElement(xmlDoc, KEYWORD_TITLE, PackageProperties.NAMESPACE_DC); } private String loadVersion(Document xmlDoc) { - Element el = xmlDoc.getRootElement().element( - new QName(KEYWORD_VERSION, namespaceCP)); - if (el == null) { - return null; - } - return el.getStringValue(); + return readElement(xmlDoc, KEYWORD_VERSION, PackageNamespaces.CORE_PROPERTIES); } /* OPC Compliance methods */ @@ -325,60 +238,56 @@ public final class PackagePropertiesUnmarshaller implements PartUnmarshaller { public void checkElementForOPCCompliance(Element el) throws InvalidFormatException { // Check the current element - @SuppressWarnings("unchecked") - List<Namespace> declaredNamespaces = el.declaredNamespaces(); - Iterator<Namespace> 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."); - } + NamedNodeMap namedNodeMap = el.getAttributes(); + int namedNodeCount = namedNodeMap.getLength(); + for (int i = 0; i < namedNodeCount; i++) { + Attr attr = (Attr)namedNodeMap.item(0); + + if (attr.getNamespaceURI().equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) { + // Rule M4.2 + if (attr.getValue().equals(PackageNamespaces.MARKUP_COMPATIBILITY)) + throw new InvalidFormatException( + "OPC Compliance error [M4.2]: A format consumer shall consider the use of the Markup Compatibility namespace to be an error."); + + } + } // Rule M4.3 - if (el.getNamespace().getURI().equals( - PackageProperties.NAMESPACE_DCTERMS) - && !(el.getName().equals(KEYWORD_CREATED) || el.getName() - .equals(KEYWORD_MODIFIED))) - throw new InvalidFormatException( - "OPC Compliance error [M4.3]: Producers shall not create a document element that contains refinements to the Dublin Core elements, except for the two specified in the schema: <dcterms:created> and <dcterms:modified> Consumers shall consider a document element that violates this constraint to be an error."); + String elName = el.getLocalName(); + if (el.getNamespaceURI().equals(PackageProperties.NAMESPACE_DCTERMS)) + if (!(elName.equals(KEYWORD_CREATED) || elName.equals(KEYWORD_MODIFIED))) + throw new InvalidFormatException( + "OPC Compliance error [M4.3]: Producers shall not create a document element that contains refinements to the Dublin Core elements, except for the two specified in the schema: <dcterms:created> and <dcterms:modified> Consumers shall consider a document element that violates this constraint to be an error."); // Rule M4.4 - if (el.attribute(new QName("lang", namespaceXML)) != null) + if (el.getAttributeNodeNS(XMLConstants.XML_NS_URI, "lang") != 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)) { + if (el.getNamespaceURI().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))) + 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)); + Attr typeAtt = el.getAttributeNodeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type"); if (typeAtt == null) throw new InvalidFormatException("The element '" + elName - + "' must have the '" + namespaceXSI.getPrefix() - + ":type' attribute present !"); + + "' must have the 'xsi: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' !"); + + "' must have the 'xsi:type' attribute with the value 'dcterms:W3CDTF' !"); } // Check its children - @SuppressWarnings("unchecked") - Iterator<Element> itChildren = el.elementIterator(); - while (itChildren.hasNext()) - checkElementForOPCCompliance(itChildren.next()); + NodeList childElements = el.getElementsByTagName("*"); + int childElementCount = childElements.getLength(); + for (int i = 0; i < childElementCount; i++) + checkElementForOPCCompliance((Element)childElements.item(i)); } } diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/HorribleProxies.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/HorribleProxies.java index 54a5aad325..96395b3d08 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/HorribleProxies.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/HorribleProxies.java @@ -176,6 +176,7 @@ public interface HorribleProxies { public interface OCSPRespIf extends ProxyIf {
String delegateClass = "org.bouncycastle.cert.ocsp.OCSPResp";
BasicOCSPRespIf getResponseObject();
+ byte[] getEncoded() throws IOException;
}
public interface PKIFailureInfoIf extends ProxyIf {
diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureInfo.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureInfo.java index 4dbfa5474a..142d56bc0a 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureInfo.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureInfo.java @@ -171,7 +171,7 @@ public class SignatureInfo { KeyInfoKeySelector keySelector = new KeyInfoKeySelector();
try {
- Document doc = SAXHelper.readSAXDocumentW3C(signaturePart.getInputStream());
+ Document doc = SAXHelper.readSAXDocument(signaturePart.getInputStream());
// dummy call to createSignatureService to tweak document afterwards
createSignatureService(HashAlgorithm.sha1, pkg).registerIds(doc);
diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/EnvelopedSignatureFacet.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/EnvelopedSignatureFacet.java new file mode 100644 index 0000000000..4f4f9af7ad --- /dev/null +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/EnvelopedSignatureFacet.java @@ -0,0 +1,84 @@ +package org.apache.poi.poifs.crypt.dsig.facets;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.crypto.dsig.CanonicalizationMethod;
+import javax.xml.crypto.dsig.DigestMethod;
+import javax.xml.crypto.dsig.Reference;
+import javax.xml.crypto.dsig.Transform;
+import javax.xml.crypto.dsig.XMLObject;
+import javax.xml.crypto.dsig.XMLSignatureFactory;
+import javax.xml.crypto.dsig.spec.TransformParameterSpec;
+
+import org.apache.poi.poifs.crypt.HashAlgorithm;
+import org.w3.x2000.x09.xmldsig.SignatureType;
+
+/**
+ * Signature Facet implementation to create enveloped signatures.
+ *
+ * @author Frank Cornelis
+ *
+ */
+public class EnvelopedSignatureFacet implements SignatureFacet {
+
+ private final HashAlgorithm hashAlgo;
+
+ /**
+ * Default constructor. Digest algorithm will be SHA-1.
+ */
+ public EnvelopedSignatureFacet() {
+ this(HashAlgorithm.sha1);
+ }
+
+ /**
+ * Main constructor.
+ *
+ * @param hashAlgo
+ * the digest algorithm to be used within the ds:Reference
+ * element. Possible values: "SHA-1", "SHA-256, or "SHA-512".
+ */
+ public EnvelopedSignatureFacet(HashAlgorithm hashAlgo) {
+ this.hashAlgo = hashAlgo;
+ }
+
+ @Override
+ public void postSign(SignatureType signatureElement
+ , List<X509Certificate> signingCertificateChain) {
+ // empty
+ }
+
+ @Override
+ public void preSign(XMLSignatureFactory signatureFactory,
+ String signatureId,
+ List<X509Certificate> signingCertificateChain,
+ List<Reference> references, List<XMLObject> objects)
+ throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
+ DigestMethod digestMethod = signatureFactory.newDigestMethod(
+ this.hashAlgo.xmlSignUri, null);
+
+ List<Transform> transforms = new LinkedList<Transform>();
+ Transform envelopedTransform = signatureFactory
+ .newTransform(CanonicalizationMethod.ENVELOPED,
+ (TransformParameterSpec) null);
+ transforms.add(envelopedTransform);
+ Transform exclusiveTransform = signatureFactory
+ .newTransform(CanonicalizationMethod.EXCLUSIVE,
+ (TransformParameterSpec) null);
+ transforms.add(exclusiveTransform);
+
+ Reference reference = signatureFactory.newReference("", digestMethod,
+ transforms, null, null);
+
+ references.add(reference);
+ }
+
+ @Override
+ public Map<String,String> getNamespacePrefixMapping() {
+ return null;
+ }
+}
diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/XmlSignatureService.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/XmlSignatureService.java index c09501a4a1..bea7653430 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/XmlSignatureService.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/XmlSignatureService.java @@ -174,8 +174,10 @@ public class XmlSignatureService implements SignatureService { *
* @param signatureFacet
*/
- protected void addSignatureFacet(SignatureFacet signatureFacet) {
- this.signatureFacets.add(signatureFacet);
+ public void addSignatureFacet(SignatureFacet... signatureFacets) {
+ for (SignatureFacet sf : signatureFacets) {
+ this.signatureFacets.add(sf);
+ }
}
/**
diff --git a/src/ooxml/java/org/apache/poi/util/DocumentHelper.java b/src/ooxml/java/org/apache/poi/util/DocumentHelper.java new file mode 100644 index 0000000000..22bdd4e0fd --- /dev/null +++ b/src/ooxml/java/org/apache/poi/util/DocumentHelper.java @@ -0,0 +1,60 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.util; + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.stream.events.Namespace; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +public class DocumentHelper { + + private static final DocumentBuilder newDocumentBuilder; + static { + try { + newDocumentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("cannot create a DocumentBuilder", e); + } + } + + public static synchronized Document createDocument() { + return newDocumentBuilder.newDocument(); + } + + /** + * Adds a namespace declaration attribute to the given element. + */ + public static void addNamespaceDeclaration(Element element, String namespacePrefix, String namespaceURI) { + element.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, + XMLConstants.XMLNS_ATTRIBUTE + ':' + namespacePrefix, + namespaceURI); + } + + /** + * Adds a namespace declaration attribute to the given element. + */ + public static void addNamespaceDeclaration(Element element, Namespace namespace) { + addNamespaceDeclaration(element, namespace.getPrefix(), namespace.getNamespaceURI()); + } + +} diff --git a/src/ooxml/java/org/apache/poi/util/SAXHelper.java b/src/ooxml/java/org/apache/poi/util/SAXHelper.java index 9ee00fb69a..81049a9a2e 100644 --- a/src/ooxml/java/org/apache/poi/util/SAXHelper.java +++ b/src/ooxml/java/org/apache/poi/util/SAXHelper.java @@ -27,9 +27,7 @@ import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.io.SAXReader; +import org.w3c.dom.Document; import org.xml.sax.EntityResolver; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -40,59 +38,7 @@ import org.xml.sax.SAXException; */ public final class SAXHelper { private static POILogger logger = POILogFactory.getLogger(SAXHelper.class); - - /** - * Creates a new SAX Reader, with sensible defaults - */ - public static SAXReader getSAXReader() { - SAXReader xmlReader = new SAXReader(); - xmlReader.setValidation(false); - xmlReader.setEntityResolver(new EntityResolver() { - public InputSource resolveEntity(String publicId, String systemId) - throws SAXException, IOException { - return new InputSource(new StringReader("")); - } - }); - trySetSAXFeature(xmlReader, XMLConstants.FEATURE_SECURE_PROCESSING, true); - trySetXercesSecurityManager(xmlReader); - return xmlReader; - } - private static void trySetSAXFeature(SAXReader xmlReader, String feature, boolean enabled) { - try { - xmlReader.setFeature(feature, enabled); - } catch (Exception e) { - logger.log(POILogger.INFO, "SAX Feature unsupported", feature, e); - } - } - private static void trySetXercesSecurityManager(SAXReader xmlReader) { - // Try built-in JVM one first, standalone if not - for (String securityManagerClassName : new String[] { - "com.sun.org.apache.xerces.internal.util.SecurityManager", - "org.apache.xerces.util.SecurityManager" - }) { - try { - Object mgr = Class.forName(securityManagerClassName).newInstance(); - Method setLimit = mgr.getClass().getMethod("setEntityExpansionLimit", Integer.TYPE); - setLimit.invoke(mgr, 4096); - xmlReader.setProperty("http://apache.org/xml/properties/security-manager", mgr); - // Stop once one can be setup without error - return; - } catch (Exception e) { - logger.log(POILogger.INFO, "SAX Security Manager could not be setup", e); - } - } - } - /** - * Parses the given stream via the default (sensible) - * SAX Reader - * @param inp Stream to read the XML data from - * @return the SAX processed Document - */ - public static Document readSAXDocument(InputStream inp) throws DocumentException { - return getSAXReader().read(inp); - } - private static final EntityResolver IGNORING_ENTITY_RESOLVER = new EntityResolver() { @Override public InputSource resolveEntity(String publicId, String systemId) @@ -101,6 +47,27 @@ public final class SAXHelper { } }; + private static final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + static { + documentBuilderFactory.setNamespaceAware(true); + documentBuilderFactory.setValidating(false); + trySetSAXFeature(documentBuilderFactory, XMLConstants.FEATURE_SECURE_PROCESSING, true); + trySetXercesSecurityManager(documentBuilderFactory); + } + + /** + * Creates a new document builder, with sensible defaults + */ + public static synchronized DocumentBuilder getDocumentBuilder() { + try { + DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); + documentBuilder.setEntityResolver(IGNORING_ENTITY_RESOLVER); + return documentBuilder; + } catch (ParserConfigurationException e) { + throw new IllegalStateException("cannot create a DocumentBuilder", e); + } + } + private static void trySetSAXFeature(DocumentBuilderFactory documentBuilderFactory, String feature, boolean enabled) { try { documentBuilderFactory.setFeature(feature, enabled); @@ -126,38 +93,14 @@ public final class SAXHelper { } } } - - private static final ThreadLocal<DocumentBuilder> documentBuilder = new ThreadLocal<DocumentBuilder>() { - @Override - protected DocumentBuilder initialValue() { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - factory.setValidating(false); - trySetSAXFeature(factory, XMLConstants.FEATURE_SECURE_PROCESSING, true); - trySetXercesSecurityManager(factory); - try { - return factory.newDocumentBuilder(); - } catch (ParserConfigurationException e) { - throw new IllegalStateException("cannot create a DocumentBuilder", e); - } - } - @Override - public DocumentBuilder get() { - DocumentBuilder documentBuilder = super.get(); - documentBuilder.reset(); - documentBuilder.setEntityResolver(IGNORING_ENTITY_RESOLVER); - return documentBuilder; - } - }; - /** * Parses the given stream via the default (sensible) * SAX Reader * @param inp Stream to read the XML data from * @return the SAX processed Document */ - public static org.w3c.dom.Document readSAXDocumentW3C(InputStream inp) throws IOException, SAXException { - return documentBuilder.get().parse(inp); + public static Document readSAXDocument(InputStream inp) throws IOException, SAXException { + return getDocumentBuilder().parse(inp); } } diff --git a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackage.java b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackage.java index fe5bb21d46..1c64fd8629 100644 --- a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackage.java +++ b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackage.java @@ -27,7 +27,6 @@ import java.io.OutputStream; import java.lang.reflect.Field; import java.net.URI; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.TreeMap; import java.util.regex.Pattern; @@ -40,15 +39,14 @@ import org.apache.poi.openxml4j.exceptions.InvalidOperationException; import org.apache.poi.openxml4j.opc.internal.ContentTypeManager; import org.apache.poi.openxml4j.opc.internal.FileHelper; import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart; +import org.apache.poi.util.DocumentHelper; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.apache.poi.util.SAXHelper; import org.apache.poi.util.TempFile; -import org.dom4j.Document; -import org.dom4j.DocumentHelper; -import org.dom4j.Element; -import org.dom4j.Namespace; -import org.dom4j.QName; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; public final class TestPackage extends TestCase { private static final POILogger logger = POILogFactory.getLogger(TestPackage.class); @@ -127,18 +125,17 @@ public final class TestPackage extends TestCase { "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"); Document doc = DocumentHelper.createDocument(); - Namespace nsWordprocessinML = new Namespace("w", - "http://schemas.openxmlformats.org/wordprocessingml/2006/main"); - Element elDocument = doc.addElement(new QName("document", - nsWordprocessinML)); - Element elBody = elDocument.addElement(new QName("body", - nsWordprocessinML)); - Element elParagraph = elBody.addElement(new QName("p", - nsWordprocessinML)); - Element elRun = elParagraph - .addElement(new QName("r", nsWordprocessinML)); - Element elText = elRun.addElement(new QName("t", nsWordprocessinML)); - elText.setText("Hello Open XML !"); + Element elDocument = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:document"); + doc.appendChild(elDocument); + Element elBody = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:body"); + elDocument.appendChild(elBody); + Element elParagraph = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:p"); + elBody.appendChild(elParagraph); + Element elRun = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:r"); + elParagraph.appendChild(elRun); + Element elText = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:t"); + elRun.appendChild(elText); + elText.setTextContent("Hello Open XML !"); StreamHelper.saveXmlInStream(doc, corePart.getOutputStream()); pkg.close(); @@ -223,15 +220,13 @@ public final class TestPackage extends TestCase { Document xmlRelationshipsDoc = SAXHelper.readSAXDocument(relPart.getInputStream()); - Element root = xmlRelationshipsDoc.getRootElement(); - for (Iterator i = root - .elementIterator(PackageRelationship.RELATIONSHIP_TAG_NAME); i - .hasNext();) { - Element element = (Element) i.next(); - String value = element.attribute( - PackageRelationship.TARGET_ATTRIBUTE_NAME) - .getValue(); - assertTrue("Root target must not start with a leadng slash ('/'): " + value, value.charAt(0) != '/'); + Element root = xmlRelationshipsDoc.getDocumentElement(); + NodeList nodeList = root.getElementsByTagName(PackageRelationship.RELATIONSHIP_TAG_NAME); + int nodeCount = nodeList.getLength(); + for (int i = 0; i < nodeCount; i++) { + Element element = (Element) nodeList.item(i); + String value = element.getAttribute(PackageRelationship.TARGET_ATTRIBUTE_NAME); + assertTrue("Root target must not start with a leading slash ('/'): " + value, value.charAt(0) != '/'); } } @@ -268,18 +263,17 @@ public final class TestPackage extends TestCase { // Create a content Document doc = DocumentHelper.createDocument(); - Namespace nsWordprocessinML = new Namespace("w", - "http://schemas.openxmlformats.org/wordprocessingml/2006/main"); - Element elDocument = doc.addElement(new QName("document", - nsWordprocessinML)); - Element elBody = elDocument.addElement(new QName("body", - nsWordprocessinML)); - Element elParagraph = elBody.addElement(new QName("p", - nsWordprocessinML)); - Element elRun = elParagraph - .addElement(new QName("r", nsWordprocessinML)); - Element elText = elRun.addElement(new QName("t", nsWordprocessinML)); - elText.setText("Hello Open XML !"); + Element elDocument = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:document"); + doc.appendChild(elDocument); + Element elBody = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:body"); + elDocument.appendChild(elBody); + Element elParagraph = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:p"); + elBody.appendChild(elParagraph); + Element elRun = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:r"); + elParagraph.appendChild(elRun); + Element elText = doc.createElementNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w:t"); + elRun.appendChild(elText); + elText.setTextContent("Hello Open XML !"); StreamHelper.saveXmlInStream(doc, corePart.getOutputStream()); diff --git a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java index 4243f6b1f5..b3f08b3c8b 100644 --- a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java +++ b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java @@ -26,6 +26,10 @@ package org.apache.poi.poifs.crypt; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -40,7 +44,9 @@ import java.security.KeyPair; import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
+import java.security.cert.X509CRL;
import java.security.cert.X509Certificate;
+import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
@@ -53,8 +59,17 @@ import org.apache.poi.POIDataSamples; import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.poifs.crypt.dsig.HorribleProxies.KeyUsageIf;
+import org.apache.poi.poifs.crypt.dsig.HorribleProxies.OCSPRespIf;
import org.apache.poi.poifs.crypt.dsig.HorribleProxy;
import org.apache.poi.poifs.crypt.dsig.SignatureInfo;
+import org.apache.poi.poifs.crypt.dsig.facets.EnvelopedSignatureFacet;
+import org.apache.poi.poifs.crypt.dsig.facets.KeyInfoSignatureFacet;
+import org.apache.poi.poifs.crypt.dsig.facets.SignaturePolicyService;
+import org.apache.poi.poifs.crypt.dsig.facets.XAdESSignatureFacet;
+import org.apache.poi.poifs.crypt.dsig.facets.XAdESXLSignatureFacet;
+import org.apache.poi.poifs.crypt.dsig.services.RevocationData;
+import org.apache.poi.poifs.crypt.dsig.services.RevocationDataService;
+import org.apache.poi.poifs.crypt.dsig.services.TimeStampService;
import org.apache.poi.poifs.crypt.dsig.services.XmlSignatureService;
import org.apache.poi.poifs.crypt.dsig.spi.DigestInfo;
import org.apache.poi.util.IOUtils;
@@ -62,6 +77,8 @@ import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
public class TestSignatureInfo {
private static final POILogger LOG = POILogFactory.getLogger(TestSignatureInfo.class);
@@ -171,6 +188,64 @@ public class TestSignatureInfo { pkg.close();
}
+ @Test
+ public void testSignEnvelopingDocument() throws Exception {
+ String testFile = "hello-world-unsigned.xlsx";
+ OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE);
+
+ // setup
+ EnvelopedSignatureFacet envelopedSignatureFacet = new EnvelopedSignatureFacet();
+ KeyInfoSignatureFacet keyInfoSignatureFacet = new KeyInfoSignatureFacet(true, false, false);
+ SignaturePolicyService signaturePolicyService = null;
+ XAdESSignatureFacet xadesSignatureFacet = new XAdESSignatureFacet(null, null, signaturePolicyService);
+
+
+ TimeStampService mockTimeStampService = mock(TimeStampService.class);
+ RevocationDataService mockRevocationDataService = mock(RevocationDataService.class);
+
+ XAdESXLSignatureFacet xadesXLSignatureFacet = new XAdESXLSignatureFacet(
+ mockTimeStampService, mockRevocationDataService);
+ XmlSignatureService testedInstance = new XmlSignatureService(HashAlgorithm.sha1, pkg);
+ testedInstance.addSignatureFacet(envelopedSignatureFacet, keyInfoSignatureFacet,
+ xadesSignatureFacet, xadesXLSignatureFacet);
+
+ initKeyPair("Test", "CN=Test");
+ List<X509Certificate> certificateChain = new ArrayList<X509Certificate>();
+ /*
+ * We need at least 2 certificates for the XAdES-C complete certificate
+ * refs construction.
+ */
+ certificateChain.add(x509);
+ certificateChain.add(x509);
+
+ RevocationData revocationData = new RevocationData();
+ final X509CRL crl = PkiTestUtils.generateCrl(x509, keyPair.getPrivate());
+ revocationData.addCRL(crl);
+ OCSPRespIf ocspResp = PkiTestUtils.createOcspResp(x509, false,
+ x509, x509, keyPair.getPrivate(), "SHA1withRSA");
+ revocationData.addOCSP(ocspResp.getEncoded());
+
+ when(mockTimeStampService.timeStamp(any(byte[].class), any(RevocationData.class)))
+ .thenAnswer(new Answer<byte[]>(){
+ public byte[] answer(InvocationOnMock invocation) throws Throwable {
+ Object[] arguments = invocation.getArguments();
+ RevocationData revocationData = (RevocationData) arguments[1];
+ revocationData.addCRL(crl);
+ return "time-stamp-token".getBytes();
+ }
+ });
+
+ when(mockRevocationDataService.getRevocationData(eq(certificateChain)))
+ .thenReturn(revocationData);
+
+ // operate
+ DigestInfo digestInfo = testedInstance.preSign(null, certificateChain, null, null, null);
+
+ // verify
+ assertNotNull(digestInfo);
+ assertEquals("SHA-1", digestInfo.hashAlgo);
+ assertNotNull(digestInfo.digestValue);
+ }
private OPCPackage sign(OPCPackage pkgCopy, String alias, String signerDn, int signerCount) throws Exception {
/*** TODO : set cal to now ... only set to fixed date for debugging ... */
diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/extractor/TestExternalEntities.java b/src/ooxml/testcases/org/apache/poi/xwpf/extractor/TestExternalEntities.java new file mode 100644 index 0000000000..05d6b2f844 --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/xwpf/extractor/TestExternalEntities.java @@ -0,0 +1,47 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xwpf.extractor; + +import java.io.IOException; + +import junit.framework.TestCase; + +import org.apache.poi.xwpf.XWPFTestDataSamples; +import org.apache.poi.xwpf.usermodel.XWPFDocument; + +public class TestExternalEntities extends TestCase { + + /** + * Get text out of the simple file + * @throws IOException + */ + public void testFile() throws IOException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("ExternalEntityInText.docx"); + XWPFWordExtractor extractor = new XWPFWordExtractor(doc); + + String text = extractor.getText(); + + assertTrue(text.length() > 0); + + // Check contents, they should not contain the text from POI web site after colon! + assertEquals("Here should not be the POI web site: \"\"", text.trim()); + + extractor.close(); + } + +} |