diff --git a/src/documentation/xdocs/hpsf/how-to.xml b/src/documentation/xdocs/hpsf/how-to.xml index 826e60cb8..ec88ddcfe 100644 --- a/src/documentation/xdocs/hpsf/how-to.xml +++ b/src/documentation/xdocs/hpsf/how-to.xml @@ -95,9 +95,6 @@ examples section of the POI source tree as ReadTitle.java.

- I just found out that ReadTitle.java is no longer there! I - shall look it up in the CVS and try to restore it. - import java.io.*; import org.apache.poi.hpsf.*; @@ -317,18 +314,139 @@ else value.

Okay, that was still rather easy. However, to make things more - complicated Microsoft in its infinite wisdom decided that a property set + complicated, Microsoft in its infinite wisdom decided that a property set shalt be broken into sections. Each section holds a bunch - of properties. But since that's still not complicated enough: a section + of properties. But since that's still not complicated enough: A section can optionally have a dictionary that maps property IDs to property names - we'll explain later what that means.

- [To be continued.] +

So the procedure to get to the properties is as follows:

- Let's consider a Java application that wants to read a stream - containing a general property set. It is modelled by the class - PropertySet in the org.apache.poi.hpsf - package. +
    +
  1. Use the PropertySetFactory to create a + PropertySet from an input stream. You can try this with any + input stream: You'll either PropertySet instance or an + exception is thrown.
  2. + +
  3. Call the PropertySet's method getSections() + to get a list of sections contained in the property set. Each section is + an instance of the Section class.
  4. + +
  5. Each section has a format ID. The format ID of the first section in a + property set determines the property set's type. For example, the first + (and only) section of the SummaryInformation property set has a format ID + of F29F85E0-4FF9-1068-AB-91-08-00-2B-27-B3-D9. You can + get the format ID with Section.getFormatID().
  6. + +
  7. The properties contained in a Section can be retrieved + with Section.getProperties(). The result is an array of + Property instances.
  8. + +
  9. A property has a name, a type, and a value. The Property + class has methods to retrieve them.
  10. +
+ +

Let's have a look at a sample Java application that dumps all property + set streams contained in a POI file system. The full source code of this + program can be found as ReadCustomPropertySets.java in the + examples area of the POI source code tree. Here are the key + sections:

+ + import java.io.*; +import java.util.*; +import org.apache.poi.hpsf.*; +import org.apache.poi.poifs.eventfilesystem.*; +import org.apache.poi.util.HexDump; + +

The most important package the application needs is + org.apache.poi.hpsf.*. This package contains the HPSF + classes. Most classes named below are from the HPSF package. Of course we + also need the POIFS event file system's classes and java.io.* + since we are dealing with POI I/O. From the java.util package + we use the List and Iterator class. The class + org.apache.poi.util.HexDump provides a methods to dump byte + arrays as nicely formatted strings.

+ + public static void main(String[] args) + throws IOException +{ + final String filename = args[0]; + POIFSReader r = new POIFSReader(); + + /* Register a listener for *all* documents. */ + r.registerListener(new MyPOIFSReaderListener()); + r.read(new FileInputStream(filename)); +} + +

The POIFSReader is set up in a way that the listener + MyPOIFSReaderListener is called on every file in the POI file + system.

+ +

The listener class tries to create a PropertySet from each + stream using the PropertySetFactory.create() method:

+ + static class MyPOIFSReaderListener implements POIFSReaderListener +{ + public void processPOIFSReaderEvent(POIFSReaderEvent event) + { + PropertySet ps = null; + try + { + ps = PropertySetFactory.create(event.getStream()); + } + catch (NoPropertySetStreamException ex) + { + out("No property set stream: \"" + event.getPath() + + event.getName() + "\""); + return; + } + catch (Exception ex) + { + throw new RuntimeException + ("Property set stream \"" + + event.getPath() + event.getName() + "\": " + ex); + } + + /* Print the name of the property set stream: */ + out("Property set stream \"" + event.getPath() + + event.getName() + "\":"); + +

Creating the PropertySet is done in a try + block, because not each stream in the POI file system contains a property + set. If it is some other file, the + PropertySetFactory.create() throws a + NoPropertySetStreamException, which is caught and + logged. Then the program continues with the next stream. However, all + other types of exceptions cause the program to terminate by throwing a + runtime exception. If all went well, we can print the name of the property + set stream.

+ +

The next step is to print the number of sections followed by the + sections themselves:

+ + /* Print the number of sections: */ +final long sectionCount = ps.getSectionCount(); +out(" No. of sections: " + sectionCount); + +/* Print the list of sections: */ +List sections = ps.getSections(); +int nr = 0; +for (Iterator i = sections.iterator(); i.hasNext();) +{ + /* Print a single section: */ + Section sec = (Section) i.next(); + + // ... +} + +

The PropertySet's method getSectionCount() + returns the number of sections.

+ +

To retrieve the sections, use the getSections() + method. This method returns a java.util.List containing + instances of the Section class in their proper order.

+ + [To be continued.]