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 org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
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.ooxml.util.DocumentHelper;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.xssf.usermodel.XSSFRelation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public final class ZipPartMarshaller implements PartMarshaller {
private final static POILogger logger = POILogFactory.getLogger(ZipPartMarshaller.class);
@Override
public boolean marshall(PackagePart part, OutputStream os)
throws OpenXML4JException {
if (!(os instanceof ZipArchiveOutputStream)) {
logger.log(POILogger.ERROR,"Unexpected class " + os.getClass().getName());
throw new OpenXML4JException("ZipOutputStream expected !");
}
if(part.getSize() == 0 && part.getPartName().getName().equals(XSSFRelation.SHARED_STRINGS.getDefaultFileName())) {
return true;
}
ZipArchiveOutputStream zos = (ZipArchiveOutputStream) os;
ZipArchiveEntry partEntry = new ZipArchiveEntry(ZipHelper
.getZipItemNameFromOPCName(part.getPartName().getURI()
.getPath()));
try {
zos.putArchiveEntry(partEntry);
try (final InputStream ins = part.getInputStream()) {
IOUtils.copy(ins, zos);
} finally {
zos.closeArchiveEntry();
}
} catch (IOException ioe) {
logger.log(POILogger.ERROR,"Cannot write: " + part.getPartName() + ": in ZIP",
ioe);
return false;
}
if (part.hasRelationships()) {
PackagePartName relationshipPartName = PackagingURIHelper
.getRelationshipPartName(part.getPartName());
marshallRelationshipPart(part.getRelationships(),
relationshipPartName, zos);
}
return true;
}
public static boolean marshallRelationshipPart(
PackageRelationshipCollection rels, PackagePartName relPartName,
ZipArchiveOutputStream zos) {
Document xmlOutDoc = DocumentHelper.createDocument();
Element root = xmlOutDoc.createElementNS(PackageNamespaces.RELATIONSHIPS, PackageRelationship.RELATIONSHIPS_TAG_NAME);
xmlOutDoc.appendChild(root);
URI sourcePartURI = PackagingURIHelper
.getSourcePartUriFromRelationshipPartUri(relPartName.getURI());
for (PackageRelationship rel : rels) {
Element relElem = xmlOutDoc.createElementNS(PackageNamespaces.RELATIONSHIPS, PackageRelationship.RELATIONSHIP_TAG_NAME);
root.appendChild(relElem);
relElem.setAttribute(PackageRelationship.ID_ATTRIBUTE_NAME, rel.getId());
relElem.setAttribute(PackageRelationship.TYPE_ATTRIBUTE_NAME, rel.getRelationshipType());
String targetValue;
URI uri = rel.getTargetURI();
if (rel.getTargetMode() == TargetMode.EXTERNAL) {
targetValue = uri.toString();
relElem.setAttribute(PackageRelationship.TARGET_MODE_ATTRIBUTE_NAME, "External");
} else {
URI targetURI = rel.getTargetURI();
targetValue = PackagingURIHelper.relativizeURI(
sourcePartURI, targetURI, true).toString();
}
relElem.setAttribute(PackageRelationship.TARGET_ATTRIBUTE_NAME, targetValue);
}
xmlOutDoc.normalize();
ZipArchiveEntry ctEntry = new ZipArchiveEntry(ZipHelper.getZipURIFromOPCName(
relPartName.getURI().toASCIIString()).getPath());
try {
zos.putArchiveEntry(ctEntry);
try {
return StreamHelper.saveXmlInStream(xmlOutDoc, zos);
} finally {
zos.closeArchiveEntry();
}
} catch (IOException e) {
logger.log(POILogger.ERROR,"Cannot create zip entry " + relPartName, e);
return false;
}
}
}