You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ZipPartMarshaller.java 6.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.openxml4j.opc.internal.marshallers;
  16. import java.io.IOException;
  17. import java.io.InputStream;
  18. import java.io.OutputStream;
  19. import java.net.URI;
  20. import java.util.zip.ZipEntry;
  21. import java.util.zip.ZipOutputStream;
  22. import org.dom4j.Document;
  23. import org.dom4j.DocumentHelper;
  24. import org.dom4j.Element;
  25. import org.dom4j.Namespace;
  26. import org.dom4j.QName;
  27. import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
  28. import org.apache.poi.openxml4j.opc.PackageNamespaces;
  29. import org.apache.poi.openxml4j.opc.PackagePart;
  30. import org.apache.poi.openxml4j.opc.PackagePartName;
  31. import org.apache.poi.openxml4j.opc.PackageRelationship;
  32. import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
  33. import org.apache.poi.openxml4j.opc.PackagingURIHelper;
  34. import org.apache.poi.openxml4j.opc.StreamHelper;
  35. import org.apache.poi.openxml4j.opc.TargetMode;
  36. import org.apache.poi.openxml4j.opc.internal.PartMarshaller;
  37. import org.apache.poi.openxml4j.opc.internal.ZipHelper;
  38. import org.apache.poi.util.POILogger;
  39. import org.apache.poi.util.POILogFactory;
  40. /**
  41. * Zip part marshaller. This marshaller is use to save any part in a zip stream.
  42. *
  43. * @author Julien Chable
  44. */
  45. public final class ZipPartMarshaller implements PartMarshaller {
  46. private static POILogger logger = POILogFactory.getLogger(ZipPartMarshaller.class);
  47. /**
  48. * Save the specified part.
  49. *
  50. * @throws OpenXML4JException
  51. * Throws if an internal exception is thrown.
  52. */
  53. public boolean marshall(PackagePart part, OutputStream os)
  54. throws OpenXML4JException {
  55. if (!(os instanceof ZipOutputStream)) {
  56. logger.log(POILogger.ERROR,"Unexpected class " + os.getClass().getName());
  57. throw new OpenXML4JException("ZipOutputStream expected !");
  58. // Normally should happen only in developement phase, so just throw
  59. // exception
  60. }
  61. ZipOutputStream zos = (ZipOutputStream) os;
  62. ZipEntry partEntry = new ZipEntry(ZipHelper
  63. .getZipItemNameFromOPCName(part.getPartName().getURI()
  64. .getPath()));
  65. try {
  66. // Create next zip entry
  67. zos.putNextEntry(partEntry);
  68. // Saving data in the ZIP file
  69. InputStream ins = part.getInputStream();
  70. byte[] buff = new byte[ZipHelper.READ_WRITE_FILE_BUFFER_SIZE];
  71. while (ins.available() > 0) {
  72. int resultRead = ins.read(buff);
  73. if (resultRead == -1) {
  74. // End of file reached
  75. break;
  76. }
  77. zos.write(buff, 0, resultRead);
  78. }
  79. zos.closeEntry();
  80. } catch (IOException ioe) {
  81. logger.log(POILogger.ERROR,"Cannot write: " + part.getPartName() + ": in ZIP",
  82. ioe);
  83. return false;
  84. }
  85. // Saving relationship part
  86. if (part.hasRelationships()) {
  87. PackagePartName relationshipPartName = PackagingURIHelper
  88. .getRelationshipPartName(part.getPartName());
  89. marshallRelationshipPart(part.getRelationships(),
  90. relationshipPartName, zos);
  91. }
  92. return true;
  93. }
  94. /**
  95. * Save relationships into the part.
  96. *
  97. * @param rels
  98. * The relationships collection to marshall.
  99. * @param relPartName
  100. * Part name of the relationship part to marshall.
  101. * @param zos
  102. * Zip output stream in which to save the XML content of the
  103. * relationships serialization.
  104. */
  105. public static boolean marshallRelationshipPart(
  106. PackageRelationshipCollection rels, PackagePartName relPartName,
  107. ZipOutputStream zos) {
  108. // Building xml
  109. Document xmlOutDoc = DocumentHelper.createDocument();
  110. // make something like <Relationships
  111. // xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
  112. Namespace dfNs = Namespace.get("", PackageNamespaces.RELATIONSHIPS);
  113. Element root = xmlOutDoc.addElement(new QName(
  114. PackageRelationship.RELATIONSHIPS_TAG_NAME, dfNs));
  115. // <Relationship
  116. // TargetMode="External"
  117. // Id="rIdx"
  118. // Target="http://www.custom.com/images/pic1.jpg"
  119. // Type="http://www.custom.com/external-resource"/>
  120. URI sourcePartURI = PackagingURIHelper
  121. .getSourcePartUriFromRelationshipPartUri(relPartName.getURI());
  122. for (PackageRelationship rel : rels) {
  123. // the relationship element
  124. Element relElem = root
  125. .addElement(PackageRelationship.RELATIONSHIP_TAG_NAME);
  126. // the relationship ID
  127. relElem.addAttribute(PackageRelationship.ID_ATTRIBUTE_NAME, rel
  128. .getId());
  129. // the relationship Type
  130. relElem.addAttribute(PackageRelationship.TYPE_ATTRIBUTE_NAME, rel
  131. .getRelationshipType());
  132. // the relationship Target
  133. String targetValue;
  134. URI uri = rel.getTargetURI();
  135. if (rel.getTargetMode() == TargetMode.EXTERNAL) {
  136. // Save the target as-is - we don't need to validate it,
  137. // alter it etc
  138. targetValue = uri.toString();
  139. // add TargetMode attribute (as it is external link external)
  140. relElem.addAttribute(
  141. PackageRelationship.TARGET_MODE_ATTRIBUTE_NAME,
  142. "External");
  143. } else {
  144. URI targetURI = rel.getTargetURI();
  145. targetValue = PackagingURIHelper.relativizeURI(
  146. sourcePartURI, targetURI, true).toString();
  147. }
  148. relElem.addAttribute(PackageRelationship.TARGET_ATTRIBUTE_NAME,
  149. targetValue);
  150. }
  151. xmlOutDoc.normalize();
  152. // String schemaFilename = Configuration.getPathForXmlSchema()+
  153. // File.separator + "opc-relationships.xsd";
  154. // Save part in zip
  155. ZipEntry ctEntry = new ZipEntry(ZipHelper.getZipURIFromOPCName(
  156. relPartName.getURI().toASCIIString()).getPath());
  157. try {
  158. zos.putNextEntry(ctEntry);
  159. if (!StreamHelper.saveXmlInStream(xmlOutDoc, zos)) {
  160. return false;
  161. }
  162. zos.closeEntry();
  163. } catch (IOException e) {
  164. logger.log(POILogger.ERROR,"Cannot create zip entry " + relPartName, e);
  165. return false;
  166. }
  167. return true; // success
  168. }
  169. }