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.

WriteAuthorAndTitle.java 7.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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.examples.hpsf;
  16. import java.io.File;
  17. import java.io.FileOutputStream;
  18. import java.io.IOException;
  19. import java.io.InputStream;
  20. import java.io.OutputStream;
  21. import org.apache.poi.hpsf.HPSFRuntimeException;
  22. import org.apache.poi.hpsf.MarkUnsupportedException;
  23. import org.apache.poi.hpsf.NoPropertySetStreamException;
  24. import org.apache.poi.hpsf.PropertySet;
  25. import org.apache.poi.hpsf.PropertySetFactory;
  26. import org.apache.poi.hpsf.Section;
  27. import org.apache.poi.hpsf.SummaryInformation;
  28. import org.apache.poi.hpsf.Variant;
  29. import org.apache.poi.hpsf.WritingNotSupportedException;
  30. import org.apache.poi.hpsf.wellknown.PropertyIDMap;
  31. import org.apache.poi.poifs.eventfilesystem.POIFSReader;
  32. import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
  33. import org.apache.poi.poifs.filesystem.DirectoryEntry;
  34. import org.apache.poi.poifs.filesystem.DocumentInputStream;
  35. import org.apache.poi.poifs.filesystem.POIFSDocumentPath;
  36. import org.apache.poi.poifs.filesystem.POIFSFileSystem;
  37. /**
  38. * <p>This class is a sample application which shows how to write or modify the
  39. * author and title property of an OLE 2 document. This could be done in two
  40. * different ways:</p>
  41. *
  42. * <ul>
  43. *
  44. * <li><p>The first approach is to open the OLE 2 file as a POI filesystem
  45. * (see class {@link POIFSFileSystem}), read the summary information property
  46. * set (see classes {@link SummaryInformation} and {@link PropertySet}), write
  47. * the author and title properties into it and write the property set back into
  48. * the POI filesystem.</p></li>
  49. *
  50. * <li><p>The second approach does not modify the original POI filesystem, but
  51. * instead creates a new one. All documents from the original POIFS are copied
  52. * to the destination POIFS, except for the summary information stream. The
  53. * latter is modified by setting the author and title property before writing
  54. * it to the destination POIFS. It there are several summary information streams
  55. * in the original POIFS - e.g. in subordinate directories - they are modified
  56. * just the same.</p></li>
  57. *
  58. * </ul>
  59. *
  60. * <p>This sample application takes the second approach. It expects the name of
  61. * the existing POI filesystem's name as its first command-line parameter and
  62. * the name of the output POIFS as the second command-line argument. The
  63. * program then works as described above: It copies nearly all documents
  64. * unmodified from the input POI filesystem to the output POI filesystem. If it
  65. * encounters a summary information stream it reads its properties. Then it sets
  66. * the "author" and "title" properties to new values and writes the modified
  67. * summary information stream into the output file.</p>
  68. *
  69. * <p>Further explanations can be found in the HPSF HOW-TO.</p>
  70. */
  71. @SuppressWarnings({"java:S106","java:S4823"})
  72. public final class WriteAuthorAndTitle {
  73. private WriteAuthorAndTitle() {}
  74. /**
  75. * <p>Runs the example program.</p>
  76. *
  77. * @param args Command-line arguments. The first command-line argument must
  78. * be the name of a POI filesystem to read.
  79. * @throws IOException if any I/O exception occurs.
  80. */
  81. public static void main(final String[] args) throws IOException {
  82. /* Check whether we have exactly two command-line arguments. */
  83. if (args.length != 2) {
  84. System.err.println("Usage: WriteAuthorAndTitle originPOIFS destinationPOIFS");
  85. System.exit(1);
  86. }
  87. /* Read the names of the origin and destination POI filesystems. */
  88. final String srcName = args[0];
  89. final String dstName = args[1];
  90. /* Read the origin POIFS using the eventing API. The real work is done
  91. * in the class ModifySICopyTheRest which is registered here as a
  92. * POIFSReader. */
  93. try (POIFSFileSystem poifs = new POIFSFileSystem();
  94. OutputStream out = new FileOutputStream(dstName)) {
  95. final POIFSReader r = new POIFSReader();
  96. r.registerListener(e -> handleEvent(poifs, e));
  97. r.read(new File(srcName));
  98. /* Write the new POIFS to disk. */
  99. poifs.writeFilesystem(out);
  100. }
  101. }
  102. private interface InputStreamSupplier {
  103. InputStream get() throws IOException, WritingNotSupportedException;
  104. }
  105. /**
  106. * The method is called by POI's eventing API for each file in the origin POIFS.
  107. */
  108. private static void handleEvent(final POIFSFileSystem poiFs, final POIFSReaderEvent event) {
  109. // The following declarations are shortcuts for accessing the "event" object.
  110. final DocumentInputStream stream = event.getStream();
  111. try {
  112. final InputStreamSupplier isSup;
  113. // Find out whether the current document is a property set stream or not.
  114. if (PropertySet.isPropertySetStream(stream)) {
  115. // Yes, the current document is a property set stream. Let's create a PropertySet instance from it.
  116. PropertySet ps = PropertySetFactory.create(stream);
  117. // Now we know that we really have a property set.
  118. // The next step is to find out whether it is a summary information or not.
  119. if (ps.isSummaryInformation()) {
  120. // Create a mutable property set as a copy of the original read-only property set.
  121. ps = new PropertySet(ps);
  122. // Retrieve the section containing the properties to modify.
  123. // A summary information property set contains exactly one section.
  124. final Section s = ps.getSections().get(0);
  125. // Set the properties.
  126. s.setProperty(PropertyIDMap.PID_AUTHOR, Variant.VT_LPSTR, "Rainer Klute");
  127. s.setProperty(PropertyIDMap.PID_TITLE, Variant.VT_LPWSTR, "Test");
  128. }
  129. isSup = ps::toInputStream;
  130. } else {
  131. // No, the current document is not a property set stream. We copy it unmodified to the destination POIFS.
  132. isSup = event::getStream;
  133. }
  134. try (InputStream is = isSup.get()) {
  135. final POIFSDocumentPath path = event.getPath();
  136. // Ensures that the directory hierarchy for a document in a POI fileystem is in place.
  137. // Get the root directory. It does not have to be created since it always exists in a POIFS.
  138. DirectoryEntry de = poiFs.getRoot();
  139. for (int i=0; i<path.length(); i++) {
  140. String subDir = path.getComponent(i);
  141. de = (de.hasEntry(subDir)) ? (DirectoryEntry)de.getEntry(subDir) : de.createDirectory(subDir);
  142. }
  143. de.createDocument(event.getName(), is);
  144. }
  145. } catch (MarkUnsupportedException | WritingNotSupportedException | IOException | NoPropertySetStreamException ex) {
  146. // According to the definition of the processPOIFSReaderEvent method we cannot pass checked
  147. // exceptions to the caller.
  148. throw new HPSFRuntimeException("Could not read file " + event.getPath() + "/" + event.getName(), ex);
  149. }
  150. }
  151. }