/* ==================================================================== 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.apache.log4j.Logger; 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; /** * 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 Logger logger = Logger.getLogger("org.openxml4j"); /** * 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.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.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 relPartURI * 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) { // L'�l�ment de la relation Element relElem = root .addElement(PackageRelationship.RELATIONSHIP_TAG_NAME); // L'attribut ID relElem.addAttribute(PackageRelationship.ID_ATTRIBUTE_NAME, rel .getId()); // L'attribut Type relElem.addAttribute(PackageRelationship.TYPE_ATTRIBUTE_NAME, rel .getRelationshipType()); // L'attribut 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 attribut (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 { // Cr�ation de l'entr�e dans le fichier ZIP zos.putNextEntry(ctEntry); if (!StreamHelper.saveXmlInStream(xmlOutDoc, zos)) { return false; } zos.closeEntry(); } catch (IOException e) { logger.error("Cannot create zip entry " + relPartName, e); return false; } return true; // success } }