* Writing support added to the SummaryInformation and DocumentSummaryInformation classes. These classes now have methods for setting and removing properties. Coherent extensions are:
** Documentation section about writing standard properties added to the HPSF HOW-TO. ** Example application added showing how to modify the document summary information. ** Testcases added for testing modifying summary information and document summary information. ** PropertySetFactory extended to create SummaryInformation and DocumentSummaryInformation instances. * Added MutablePropertySet.write(DirectoryEntry, String) to ease writing a property set to a POI filesystem document. * Improved codepage handling. * Bug fixed: Integral values were read and written as unsigned instead of signed. * Reworked the mapping between variant types and Java types: Variant.VT_I4 is mapped to Integer now and Variant.VT_I8 to Long. This might cause incompatibilities if you are doing low-level HPSF programming. * Changed SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID from a byte[] to a byte[][] in order to contain the format ID of the first and the second section. This is an incompatible change! * Added PropertySet.getFirstSection(). This method is similar to getSingleSection() won't choke if the property set has more than one section. * Support for low-level reading and writing of Variant.VT_I8 type properties added. * Unnecessary casts removed. * Poibrowser's display format changed slightly. git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@382887 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
a7f8720bad
commit
bb7ebd3492
@ -128,7 +128,7 @@ public class POIBrowser extends JFrame
|
||||
new PropertySetDescriptorRenderer());
|
||||
treeUI.setCellRenderer(etcr);
|
||||
setSize(600, 450);
|
||||
setTitle("POI Browser 0.08");
|
||||
setTitle("POI Browser 0.09");
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,6 @@ import org.apache.poi.hpsf.MarkUnsupportedException;
|
||||
import org.apache.poi.hpsf.NoPropertySetStreamException;
|
||||
import org.apache.poi.hpsf.PropertySet;
|
||||
import org.apache.poi.hpsf.PropertySetFactory;
|
||||
import org.apache.poi.hpsf.UnexpectedPropertySetTypeException;
|
||||
import org.apache.poi.poifs.filesystem.DocumentInputStream;
|
||||
import org.apache.poi.poifs.filesystem.POIFSDocumentPath;
|
||||
|
||||
@ -70,7 +69,7 @@ public class PropertySetDescriptor extends DocumentDescriptor
|
||||
final POIFSDocumentPath path,
|
||||
final DocumentInputStream stream,
|
||||
final int nrOfBytesToDump)
|
||||
throws UnexpectedPropertySetTypeException, NoPropertySetStreamException,
|
||||
throws NoPropertySetStreamException,
|
||||
MarkUnsupportedException, UnsupportedEncodingException,
|
||||
IOException
|
||||
{
|
||||
|
@ -127,6 +127,9 @@ public class PropertySetDescriptorRenderer extends DocumentDescriptorRenderer
|
||||
|
||||
/**
|
||||
* <p>Returns a string representation of a {@link Section}.</p>
|
||||
* @param s the section
|
||||
* @param name the section's name
|
||||
* @return a string representation of the {@link Section}
|
||||
*/
|
||||
protected String toString(final Section s, final String name)
|
||||
{
|
||||
@ -141,12 +144,18 @@ public class PropertySetDescriptorRenderer extends DocumentDescriptorRenderer
|
||||
for (int i = 0; i < properties.length; i++)
|
||||
{
|
||||
final Property p = properties[i];
|
||||
final long id = p.getID();
|
||||
final long type = p.getType();
|
||||
final Object value = p.getValue();
|
||||
b.append("\n" + name + " ");
|
||||
b.append("PID_");
|
||||
b.append(p.getID());
|
||||
b.append(' ');
|
||||
b.append(s.getPIDString(p.getID()) + ": ");
|
||||
b.append('\n');
|
||||
b.append(name);
|
||||
b.append(", Name: ");
|
||||
b.append(id);
|
||||
b.append(" (");
|
||||
b.append(s.getPIDString(id));
|
||||
b.append("), Type: ");
|
||||
b.append(type);
|
||||
b.append(", Value: ");
|
||||
if (value instanceof byte[])
|
||||
{
|
||||
byte[] b2 = (byte[]) value;
|
||||
|
@ -19,8 +19,8 @@
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
The <link href="#sec1">first section</link> explains how to read
|
||||
the most important standard properties of a Microsoft Office
|
||||
The <link href="#sec1">first section</link> explains how to <strong>read
|
||||
the most important standard properties</strong> of a Microsoft Office
|
||||
document. Standard properties are things like title, author, creation
|
||||
date etc. It is quite likely that you will find here what you need and
|
||||
don't have to read the other sections.
|
||||
@ -28,58 +28,78 @@
|
||||
|
||||
<li>
|
||||
The <link href="#sec2">second section</link> goes a small step
|
||||
further and focusses on reading additional standard properties. It also
|
||||
talks about exceptions that may be thrown when dealing with HPSF and
|
||||
shows how you can read properties of embedded objects.
|
||||
further and focusses on <strong>reading additional standard
|
||||
properties</strong>. It also talks about <strong>exceptions</strong> that
|
||||
may be thrown when dealing with HPSF and shows how you can <strong>read
|
||||
properties of embedded objects</strong>.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
The <link href="#sec3">third section</link> tells how to read
|
||||
non-standard properties. Non-standard properties are application-specific
|
||||
triples consisting of an ID, a type, and a value.
|
||||
The <link href="#sec3">third section</link> explains how to <strong>write
|
||||
standard properties</strong>. HPSF provides some high-level classes and
|
||||
methods which make writing of standard properties easy. They are based on
|
||||
the low-level writing functions explained in the <link href="#sec3">fifth
|
||||
section</link>.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
The <link href="#sec4">fourth section</link> tells you how to write
|
||||
property set streams. At this time HPSF provides low-level methods only
|
||||
for writing properties. Therefore you have to understand the <link
|
||||
href="#sec3">third section</link> before you should think about writing
|
||||
properties. Check the Javadoc API documentation to find out about the
|
||||
details! <strong>Please note:</strong> HPSF's writing functionality is
|
||||
<strong>not</strong> present in POI releases up to and including 2.5. In
|
||||
order to write properties you have to download a later POI release (when
|
||||
available) or retrieve the POI development version from the Subversion
|
||||
repository.
|
||||
The <link href="#sec4">fourth section</link> tells how to <strong>read
|
||||
non-standard properties</strong>. Non-standard properties are
|
||||
application-specific triples consisting of an ID, a type, and a value.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
The <link href="#sec5">fifth section</link> tells you how to <strong>write
|
||||
property set streams</strong> using HPSF's low-level methods. You have to
|
||||
understand the <link href="#sec3">fourth section</link> before you should
|
||||
think about low-level writing properties. Check the Javadoc API
|
||||
documentation to find out about the details!
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<note><strong>Please note:</strong> HPSF's writing functionality is
|
||||
<strong>not</strong> present in POI releases up to and including 2.5. In
|
||||
order to write properties you have to download a later POI release (when
|
||||
available) or retrieve the POI development version from the <link
|
||||
href="http://jakarta.apache.org/site/cvsindex.html">Subversion
|
||||
repository</link>.</note>
|
||||
|
||||
|
||||
|
||||
<anchor id="sec1"/>
|
||||
<section><title>Reading Standard Properties</title>
|
||||
|
||||
<note>This section explains how to read
|
||||
the most important standard properties of a Microsoft Office
|
||||
document. Standard properties are things like title, author, creation
|
||||
date etc. Chances are that you will find here what you need and
|
||||
don't have to read the other sections.</note>
|
||||
<note>This section explains how to read the most important standard
|
||||
properties of a Microsoft Office document. Standard properties are things
|
||||
like title, author, creation date etc. This section introduces the
|
||||
<strong>summary information stream</strong> which is used to keep these
|
||||
properties. Chances are that you will find here what you need and don't
|
||||
have to read the other sections.</note>
|
||||
|
||||
<p>The first thing you should understand is that properties are stored in
|
||||
separate documents inside the POI filesystem. (If you don't know what a
|
||||
POI filesystem is, read the <link href="../poifs/index.html">POIFS
|
||||
documentation</link>.) A document in a POI filesystem is also called a
|
||||
<strong>stream</strong>.</p>
|
||||
<p>The first thing you should understand is that a Microsoft Office file is
|
||||
not one large bunch of bytes but has an internal filesystem structure with
|
||||
files and directories. You can access these files and directories using
|
||||
the <link href="../poifs/index.html">POI filesystem (POIFS)</link>
|
||||
provides. A file or document in a POI filesystem is also called a
|
||||
<strong>stream</strong> - The properties of, say, an Excel document are
|
||||
stored apart of the actual spreadsheet data in separate streams. The good
|
||||
new is that this separation makes the properties independent of the
|
||||
concrete Microsoft Office file. In the following text we will always say
|
||||
"POI filesystem" instead of "Microsoft Office file" because a POI
|
||||
filesystem is not necessarily created by or for a Microsoft Office
|
||||
application, because it is shorter, and because we want to avoid the name
|
||||
of That Redmond Company.</p>
|
||||
|
||||
<p>The following example shows how to read a POI filesystem's
|
||||
"title" property. Reading other properties is similar. Consider the API
|
||||
documentation of <code>org.apache.poi.hpsf.SummaryInformation</code> to
|
||||
learn which methods are available!</p>
|
||||
<p>The following example shows how to read the "title" property. Reading
|
||||
other properties is similar. Consider the API documentation of the class
|
||||
<code>org.apache.poi.hpsf.SummaryInformation</code> to learn which methods
|
||||
are available.</p>
|
||||
|
||||
<p>The standard properties this section focusses on can be found in a
|
||||
document called <em>\005SummaryInformation</em> located in the root of the
|
||||
POI filesystem. The notation <em>\005</em> in the document's name means
|
||||
the character with the decimal value of 5. In order to read the title, an
|
||||
application has to perform the following steps:</p>
|
||||
the character with a decimal value of 5. In order to read the "title"
|
||||
property, an application has to perform the following steps:</p>
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
@ -103,7 +123,7 @@
|
||||
POI filesystem</title>
|
||||
|
||||
<p>An application that wants to open a document in a POI filesystem
|
||||
(POIFS) proceeds as shown by the following code fragment. (The full
|
||||
(POIFS) proceeds as shown by the following code fragment. The full
|
||||
source code of the sample application is available in the
|
||||
<em>examples</em> section of the POI source tree as
|
||||
<em>ReadTitle.java</em>.</p>
|
||||
@ -144,14 +164,15 @@ r.registerListener(new MyPOIFSReaderListener(),
|
||||
<p>This method call registers a
|
||||
<code>org.apache.poi.poifs.eventfilesystem.POIFSReaderListener</code>
|
||||
with the <code>POIFSReader</code>. The <code>POIFSReaderListener</code>
|
||||
interface specifies the method <code>processPOIFSReaderEvent</code>
|
||||
interface specifies the method <code>processPOIFSReaderEvent()</code>
|
||||
which processes a document. The class
|
||||
<code>MyPOIFSReaderListener</code> implements the
|
||||
<code>POIFSReaderListener</code> and thus the
|
||||
<code>processPOIFSReaderEvent</code> method. The eventing POI filesystem
|
||||
calls this method when it finds the <em>\005SummaryInformation</em>
|
||||
document. In the sample application <code>MyPOIFSReaderListener</code> is
|
||||
a static class in the <em>ReadTitle.java</em> source file.</p>
|
||||
<code>processPOIFSReaderEvent()</code> method. The eventing POI
|
||||
filesystem calls this method when it finds the
|
||||
<em>\005SummaryInformation</em> document. In the sample application
|
||||
<code>MyPOIFSReaderListener</code> is a static class in the
|
||||
<em>ReadTitle.java</em> source file.</p>
|
||||
|
||||
<p>Now everything is prepared and reading the POI filesystem can
|
||||
start:</p>
|
||||
@ -209,7 +230,7 @@ static class MyPOIFSReaderListener implements POIFSReaderListener
|
||||
convenience class with methods like <code>getTitle()</code>,
|
||||
<code>getAuthor()</code> etc.</p>
|
||||
|
||||
<p>The <code>PropertySetFactory.create</code> method may throw all sorts
|
||||
<p>The <code>PropertySetFactory.create()</code> method may throw all sorts
|
||||
of exceptions. We'll deal with them in the next sections. For now we just
|
||||
catch all exceptions and throw a <code>RuntimeException</code>
|
||||
containing the message text of the origin exception.</p>
|
||||
@ -224,10 +245,10 @@ if (title != null)
|
||||
else
|
||||
System.out.println("Document has no title.");</source>
|
||||
|
||||
<p>Please note that a Microsoft Office document does not necessarily
|
||||
contain the <em>\005SummaryInformation</em> stream. The documents created
|
||||
by the Microsoft Office suite have one, as far as I know. However, an
|
||||
Excel spreadsheet exported from StarOffice 5.2 won't have a
|
||||
<p>Please note that a POI filesystem does not necessarily contain the
|
||||
<em>\005SummaryInformation</em> stream. The documents created by the
|
||||
Microsoft Office suite have one, as far as I know. However, an Excel
|
||||
spreadsheet exported from StarOffice 5.2 won't have a
|
||||
<em>\005SummaryInformation</em> stream. In this case the applications
|
||||
won't throw an exception but simply does not call the
|
||||
<code>processPOIFSReaderEvent</code> method. You have been warned!</p>
|
||||
@ -238,14 +259,16 @@ else
|
||||
<section><title>Additional Standard Properties, Exceptions And Embedded
|
||||
Objects</title>
|
||||
|
||||
<note>This section focusses on reading additional standard properties. It
|
||||
<note>This section focusses on reading additional standard properties which
|
||||
are kept in the <strong>document summary information</strong> stream. It
|
||||
also talks about exceptions that may be thrown when dealing with HPSF and
|
||||
shows how you can read properties of embedded objects.</note>
|
||||
|
||||
<p>A couple of <strong>additional standard properties</strong> are not
|
||||
contained in the <em>\005SummaryInformation</em> stream explained above,
|
||||
for example a document's category or the number of multimedia clips in a
|
||||
PowerPoint presentation. Microsoft has invented an additional stream named
|
||||
contained in the <em>\005SummaryInformation</em> stream explained
|
||||
above. Examples for such properties are a document's category or the
|
||||
number of multimedia clips in a PowerPoint presentation. Microsoft has
|
||||
invented an additional stream named
|
||||
<em>\005DocumentSummaryInformation</em> to hold these properties. With two
|
||||
minor exceptions you can proceed exactly as described above to read the
|
||||
properties stored in <em>\005DocumentSummaryInformation</em>:</p>
|
||||
@ -259,13 +282,14 @@ else
|
||||
</ul>
|
||||
|
||||
<p>And of course you cannot call <code>getTitle()</code> because
|
||||
<code>DocumentSummaryInformation</code> has different query methods. See
|
||||
the Javadoc API documentation for the details!</p>
|
||||
<code>DocumentSummaryInformation</code> has different query methods,
|
||||
e.g. <code>getCategory</code>. See the Javadoc API documentation for the
|
||||
details.</p>
|
||||
|
||||
<p>In the previous section the application simply caught all
|
||||
<strong>exceptions</strong> and was in no way interested in any
|
||||
details. However, a real application will likely want to know what went
|
||||
wrong and act appropriately. Besides any IO exceptions there are three
|
||||
wrong and act appropriately. Besides any I/O exceptions there are three
|
||||
HPSF resp. POI specific exceptions you should know about:</p>
|
||||
|
||||
<dl>
|
||||
@ -279,9 +303,9 @@ else
|
||||
being a property set stream at all. An application should be prepared to
|
||||
deal with this case even if it opens streams named
|
||||
<em>\005SummaryInformation</em> or
|
||||
<em>\005DocumentSummaryInformation</em> only. These are just names. A
|
||||
stream's name by itself does not ensure that the stream contains the
|
||||
expected contents and that this contents is correct.
|
||||
<em>\005DocumentSummaryInformation</em>. These are just names. A
|
||||
stream's name by itself does not ensure that the stream contains the
|
||||
expected contents and that this contents is correct.
|
||||
</dd>
|
||||
|
||||
<dt><code>UnexpectedPropertySetTypeException</code></dt>
|
||||
@ -301,7 +325,7 @@ else
|
||||
</dl>
|
||||
|
||||
<p>Many Microsoft Office documents contain <strong>embedded
|
||||
objects</strong>, for example an Excel sheet on a page in a Word
|
||||
objects</strong>, for example an Excel sheet within a Word
|
||||
document. Embedded objects may have property sets of their own. An
|
||||
application can open these property set streams as described above. The
|
||||
only difference is that they are not located in the POI filesystem's root
|
||||
@ -313,7 +337,252 @@ else
|
||||
properties.</p>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
<anchor id="sec3"/>
|
||||
<section><title>Writing Standard Properties</title>
|
||||
|
||||
<note>This section explains how to <strong>write standard
|
||||
properties</strong>. HPSF provides some high-level classes and methods
|
||||
which make writing of standard properties easy. They are based on the
|
||||
low-level writing functions explained in <link href="#sec4">another
|
||||
section</link>.</note>
|
||||
|
||||
<p>As explained above, standard properties are located in the summary
|
||||
information and document summary information streams of typical POI
|
||||
filesystems. You have already learned about the classes
|
||||
<code>SummaryInformation</code> and
|
||||
<code>DocumentSummaryInformation</code> and their <code>get...()</code>
|
||||
methods for reading standard properties. These classes also provide
|
||||
<code>set...()</code> methods for writing properties.</p>
|
||||
|
||||
<p>After setting properties in <code>SummaryInformation</code> or
|
||||
<code>DocumentSummaryInformation</code> you have to write them to a disk
|
||||
file. The following sample program shows how you can</p>
|
||||
|
||||
<ol>
|
||||
<li>read a disk file into a POI filesystem,</li>
|
||||
<li>read the document summary information from the POI filesystem,</li>
|
||||
<li>set a property to a new value,</li>
|
||||
<li>write the modified document summary information back to the POI
|
||||
filesystem, and</li>
|
||||
<li>write the POI filesystem to a disk file.</li>
|
||||
</ol>
|
||||
|
||||
<p>The complete source code of this program is available as
|
||||
<em>ModifyDocumentSummaryInformation.java</em> in the <em>examples</em>
|
||||
section of the POI source tree.</p>
|
||||
|
||||
<note>Dealing with the summary information stream is analogous to handling
|
||||
the document summary information and therefore does not need to be
|
||||
explained here in detailed. See the HPSF API documentation to learn about
|
||||
the <code>set...()</code> methods of the class
|
||||
<code>SummaryInformation</code>.</note>
|
||||
|
||||
<p>The first step is to read the POI filesystem into memory:</p>
|
||||
|
||||
<source>InputStream is = new FileInputStream(poiFilesystem);
|
||||
POIFSFileSystem poifs = new POIFSFileSystem(is);
|
||||
is.close();</source>
|
||||
|
||||
<p>The code snippet above assumes that the variable
|
||||
<code>poiFilesystem</code> holds the name of a disk file. It reads the
|
||||
file from an input stream and creates a <code>POIFSFileSystem</code>
|
||||
object in memory. After having read the file, the input stream should be
|
||||
closed as shown.</p>
|
||||
|
||||
<p>In order to read the document summary information stream the application
|
||||
must open the element <em>\005DocumentSummaryInformation</em> in the POI
|
||||
filesystem's root directory. However, the POI filesystem does not
|
||||
necessarily contain a document summary information stream, and the
|
||||
application should be able to deal with that situation. The following
|
||||
code does so by creating a new <code>DocumentSummaryInformation</code> if
|
||||
there is none in the POI filesystem:</p>
|
||||
|
||||
<source>DirectoryEntry dir = poifs.getRoot();
|
||||
DocumentSummaryInformation dsi;
|
||||
try
|
||||
{
|
||||
DocumentEntry dsiEntry = (DocumentEntry)
|
||||
dir.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
||||
DocumentInputStream dis = new DocumentInputStream(dsiEntry);
|
||||
PropertySet ps = new PropertySet(dis);
|
||||
dis.close();
|
||||
dsi = new DocumentSummaryInformation(ps);
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
/* There is no document summary information. We have to create a
|
||||
* new one. */
|
||||
dsi = PropertySetFactory.newDocumentSummaryInformation();
|
||||
}
|
||||
</source>
|
||||
|
||||
<p>In the source code above the statement</p>
|
||||
|
||||
<source>DirectoryEntry dir = poifs.getRoot();</source>
|
||||
|
||||
<p>gets hold of the POI filesystem's root directory as a
|
||||
<code>DirectoryEntry</code>. The <code>getEntry()</code> method of this
|
||||
class is used to access a file or directory entry in a directory. However,
|
||||
if the file to be opened does not exist, a
|
||||
<code>FileNotFoundException</code> will be thrown. Therefore opening the
|
||||
document summary information entry should be done in a <code>try</code>
|
||||
block:</p>
|
||||
|
||||
<source> DocumentEntry dsiEntry = (DocumentEntry)
|
||||
dir.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);</source>
|
||||
|
||||
<p><code>DocumentSummaryInformation.DEFAULT_STREAM_NAME</code> represents
|
||||
the string "\005DocumentSummaryInformation", i.e. the standard name of a
|
||||
document summary information stream. If this stream exists, the
|
||||
<code>getEntry()</code> method returns a <code>DocumentEntry</code>. To
|
||||
read the <code>DocumentEntry</code>'s contents, create a
|
||||
<code>DocumentInputStream</code>:</p>
|
||||
|
||||
<source> DocumentInputStream dis = new DocumentInputStream(dsiEntry);</source>
|
||||
|
||||
<p>Up to this point we have used POI's <link
|
||||
href="../poifs/index.html">POIFS component</link>. Now HPSF enters the
|
||||
stage. A property set is created from the input stream's data:</p>
|
||||
|
||||
<source> PropertySet ps = new PropertySet(dis);
|
||||
dis.close();
|
||||
dsi = new DocumentSummaryInformation(ps); </source>
|
||||
|
||||
<p>If the data really constitutes a property set, a
|
||||
<code>PropertySet</code> object is created. Otherwise a
|
||||
<code>NoPropertySetStreamException</code> is thrown. After having read the
|
||||
data from the input stream the latter should be closed.</p>
|
||||
|
||||
<p>Since we know - or at least hope - that the stream named
|
||||
"\005DocumentSummaryInformation" is not just any property set but really
|
||||
contains the document summary information, we try to create a new
|
||||
<code>DocumentSummaryInformation</code> from the property set. If the
|
||||
stream is not document summary information stream the sample application
|
||||
fails with a <code>UnexpectedPropertySetTypeException</code>.</p>
|
||||
|
||||
<p>If the POI document does not contain a document summary information
|
||||
stream, we can create a new one in the <code>catch</code> clause. The
|
||||
<code>PropertySetFactory</code>'s method
|
||||
<code>newDocumentSummaryInformation()</code> establishes a new and empty
|
||||
<code>DocumentSummaryInformation</code> instance:</p>
|
||||
|
||||
<source> dsi = PropertySetFactory.newDocumentSummaryInformation();</source>
|
||||
|
||||
<p>Whether we read the document summary information from the POI filesystem
|
||||
or created it from scratch, in either case we now have a
|
||||
<code>DocumentSummaryInformation</code> instance we can write to. Writing
|
||||
is quite simple, as the following line of code shows:</p>
|
||||
|
||||
<source>dsi.setCategory("POI example");</source>
|
||||
|
||||
<p>This statement sets the "category" property to "POI example". Any
|
||||
former "category" value will be lost. If there hasn't been a "category"
|
||||
property yet, a new one will be created.</p>
|
||||
|
||||
<p><code>DocumentSummaryInformation</code> of course has methods to set the
|
||||
other standard properties, too - look into the API documentation to see
|
||||
all of them.</p>
|
||||
|
||||
<p>Once all properties are set as needed, they should be stored into the
|
||||
file on disk. The first step is to write the
|
||||
<code>DocumentSummaryInformation</code> into the POI filesystem:</p>
|
||||
|
||||
<source>dsi.write(dir, DocumentSummaryInformation.DEFAULT_STREAM_NAME);</source>
|
||||
|
||||
<p>The <code>DocumentSummaryInformation</code>'s <code>write()</code>
|
||||
method takes two parameters: The first is the <code>DirectoryEntry</code>
|
||||
in the POI filesystem, the second is the name of the stream to create in
|
||||
the directory. If this stream already exists, it will be overwritten.</p>
|
||||
|
||||
<note>If you not only modified the document summary information but also
|
||||
the summary information you have to write both of them to the POI
|
||||
filesystem.</note>
|
||||
|
||||
<p>Still the POI filesystem is a data structure in memory only and must be
|
||||
written to a disk file to make it permanent. The following lines write
|
||||
back the POI filesystem to the file it was read from before. Please note
|
||||
that in production-quality code you should never write directly to the
|
||||
origin file, because in case of an error everything would be lost. Here it
|
||||
is done this way to keep the example short.</p>
|
||||
|
||||
<source>OutputStream out = new FileOutputStream(poiFilesystem);
|
||||
poifs.writeFilesystem(out);
|
||||
out.close();</source>
|
||||
|
||||
<section><title>User-Defined Properties</title>
|
||||
|
||||
<p>If you compare the source code excerpts above with the file containing
|
||||
the full source code, you will notice that I left out some following
|
||||
lines of code. The are dealing with the special topic of custom
|
||||
properties.</p>
|
||||
|
||||
<source>DocumentSummaryInformation dsi = ...
|
||||
...
|
||||
CustomProperties customProperties = dsi.getCustomProperties();
|
||||
if (customProperties == null)
|
||||
customProperties = new CustomProperties();
|
||||
|
||||
/* Insert some custom properties into the container. */
|
||||
customProperties.put("Key 1", "Value 1");
|
||||
customProperties.put("Schlüssel 2", "Wert 2");
|
||||
customProperties.put("Sample Number", new Integer(12345));
|
||||
customProperties.put("Sample Boolean", new Boolean(true));
|
||||
customProperties.put("Sample Date", new Date());
|
||||
|
||||
/* Read a custom property. */
|
||||
Object value = customProperties.get("Sample Number");
|
||||
|
||||
/* Write the custom properties back to the document summary
|
||||
* information. */
|
||||
dsi.setCustomProperties(customProperties);</source>
|
||||
|
||||
<p>Custom properties are properties the user can define himself. Using for
|
||||
example Microsoft Word he can define these extra properties and give
|
||||
each of them a <strong>name</strong>, a <strong>type</strong> and a
|
||||
<strong>value</strong>. The custom properties are stored in the document
|
||||
information summary along with the standard properties.</p>
|
||||
|
||||
<p>The source code example shows how to retrieve the custom properties
|
||||
as a whole from a <code>DocumentSummaryInformation</code> instance using
|
||||
the <code>getCustomProperties()</code> method. The result is a
|
||||
<code>CustomProperties</code> instance or <code>null</code> if no
|
||||
user-defined properties exist.</p>
|
||||
|
||||
<p>Since <code>CustomProperties</code> implements the <code>Map</code>
|
||||
interface you can read and write properties with the usual
|
||||
<code>Map</code> methods. However, <code>CustomProperties</code> poses
|
||||
some restrictions on the types of keys and values.</p>
|
||||
|
||||
<ul>
|
||||
<li>The <strong>key</strong> is a string.</li>
|
||||
<li>The <strong>value</strong> is one of <code>String</code>,
|
||||
<code>Boolean</code>, <code>Long</code>, <code>Integer</code>,
|
||||
<code>Short</code>, or <code>java.util.Date</code>.</li>
|
||||
</ul>
|
||||
|
||||
<p>The <code>CustomProperties</code> class has been designed for easy
|
||||
access using just keys and values. The underlying Microsoft-specific
|
||||
custom properties data structure is more complicated. However, it does
|
||||
not provide noteworthy additional benefits. It is possible to have
|
||||
multiple properties with the same name or properties without a
|
||||
name at all. When reading custom properties from a document summary
|
||||
information stream, the <code>CustomProperties</code> class ignores
|
||||
properties without a name and keeps only the "last" (whatever that means)
|
||||
of those properties having the same name. You can find out whether a
|
||||
<code>CustomProperties</code> instance dropped any properties with the
|
||||
<code>isPure()</code> method.</p>
|
||||
|
||||
<p>You can read and write the full spectrum of custom properties with
|
||||
HPSF's low-level methods. They are explained in the <link
|
||||
href="#sec4">next section</link>.</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
<anchor id="sec4"/>
|
||||
<section><title>Reading Non-Standard Properties</title>
|
||||
|
||||
<note>This section tells how to read non-standard properties. Non-standard
|
||||
@ -863,7 +1132,8 @@ No property set stream: "/1Table"</source>
|
||||
|
||||
<p>There are some exceptions to the rule saying that a character
|
||||
encoding's name is derived from the codepage number by prepending the
|
||||
string "cp" to it:</p>
|
||||
string "cp" to it. In these cases the codepage number is mapped to a
|
||||
well-known character encoding name. Here are a few examples:</p>
|
||||
|
||||
<dl>
|
||||
<dt>Codepage 932</dt>
|
||||
@ -874,26 +1144,32 @@ No property set stream: "/1Table"</source>
|
||||
<dd>is mapped to the character encoding "UTF-8".</dd>
|
||||
</dl>
|
||||
|
||||
<p>Probably there will be a need to add more mappings between codepage
|
||||
numbers and character encoding names. They should be added to the method
|
||||
<code>codepageToEncoding</code> in the class
|
||||
<code>org.apache.poi.hpsf.VariantSupport</code>. The HPSF author will
|
||||
appreciate any advices for mappings to be added.</p>
|
||||
<p>More of these mappings between codepage and character encoding name are
|
||||
hard-coded in the classes <code>org.apache.poi.hpsf.Constants</code> and
|
||||
<code>org.apache.poi.hpsf.VariantSupport</code>. Probably there will be a
|
||||
need to add more mappings. The HPSF author will appreciate any hints.</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<anchor id="sec4"/>
|
||||
<anchor id="sec5"/>
|
||||
<section><title>Writing Properties</title>
|
||||
|
||||
<note>This section describes how to write properties.</note>
|
||||
|
||||
<section><title>Overview of Writing Properties</title>
|
||||
<p>Writing properties is possible at a low level only at the moment. You
|
||||
have to deal with things like property IDs and variant types to write
|
||||
properties. There are no convenience classes or convenience methods for
|
||||
dealing with summary information and document summary information streams
|
||||
yet. Therefore you should have read <link href="#sec3">section 3</link>
|
||||
to understand what follows in this section.</p>
|
||||
<p>Writing properties is possible at a high level and at a low level:</p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li>Most users will want to create or change entries in the summary
|
||||
information or document summary information streams. </li>
|
||||
|
||||
<li>On the low level, there are no convenience classes or methods. You
|
||||
have to deal with things like property IDs and variant types to write
|
||||
properties. Therefore you should have read <link href="#sec3">section
|
||||
3</link> to understand the description of the low-level writing
|
||||
functions.</li>
|
||||
</ul>
|
||||
|
||||
<p>HPSF's writing capabilities come with the classes
|
||||
<code>MutablePropertySet</code>, <code>MutableSection</code>,
|
||||
@ -903,7 +1179,10 @@ No property set stream: "/1Table"</source>
|
||||
"write" methods, following the <link
|
||||
href="http://en.wikipedia.org/wiki/Decorator_pattern">Decorator
|
||||
pattern</link>.</p>
|
||||
</section>
|
||||
|
||||
|
||||
<section><title>Low-Level Writing: An Overview</title>
|
||||
<p>When you are going to write a property set stream your application has
|
||||
to perform the following steps:</p>
|
||||
|
||||
|
@ -1006,41 +1006,40 @@
|
||||
helpful. If you have any amendments or corrections, please let us know!
|
||||
Thank you!</p>
|
||||
|
||||
<ol>
|
||||
<ol>
|
||||
|
||||
<li>In
|
||||
<li>In
|
||||
<link href="http://www.kyler.com/pubs/ddj9894.html"><em>Understanding OLE
|
||||
documents</em></link>, Ken Kyler gives an introduction to OLE2
|
||||
documents
|
||||
and especially to property sets. He names the property names, types, and
|
||||
IDs of the Summary Information and Document Summary Information
|
||||
stream.</li>
|
||||
documents</em></link>, Ken Kyler gives an introduction to OLE2
|
||||
documents and especially to property sets. He names the property names,
|
||||
types, and IDs of the Summary Information and Document Summary
|
||||
Information stream.</li>
|
||||
|
||||
<li>The
|
||||
<link href="http://www.dwam.net/docs/oleref/"><em>ActiveX Programmer's
|
||||
Reference</em></link> at
|
||||
<link href="http://www.dwam.net/docs/oleref/">http://www.dwam.net/docs/oleref/</link>
|
||||
<li>The <link href="http://www.dwam.net/docs/oleref/"><em>ActiveX
|
||||
Programmer's Reference</em></link> at <link
|
||||
href="http://www.dwam.net/docs/oleref/">http://www.dwam.net/docs/oleref/</link>
|
||||
seems a little outdated, but that's what I have found.</li>
|
||||
|
||||
<li>An overview of the <code>VT_</code> types is in
|
||||
<li>An overview of the <code>VT_</code> types is in
|
||||
<link href="http://www.marin.clara.net/COM/variant_type_definitions.htm"><em>Variant
|
||||
Type Definitions</em></link>.</li>
|
||||
|
||||
<li>What is a <code>FILETIME</code>? The answer can be found
|
||||
under <link
|
||||
href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/filetime_str.asp"></link>, <link href="http://www.vbapi.com/ref/f/filetime.html">http://www.vbapi.com/ref/f/filetime.html</link> or
|
||||
<li>What is a <code>FILETIME</code>? The answer can be found
|
||||
under <link
|
||||
href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/filetime_str.asp"></link>, <link href="http://www.vbapi.com/ref/f/filetime.html">http://www.vbapi.com/ref/f/filetime.html</link> or
|
||||
<link href="http://www.cs.rpi.edu/courses/fall01/os/FILETIME.html">http://www.cs.rpi.edu/courses/fall01/os/FILETIME.html</link>.
|
||||
In short: <em>The FILETIME structure holds a date and time associated
|
||||
with a file. The structure identifies a 64-bit integer specifying the
|
||||
number of 100-nanosecond intervals which have passed since January 1,
|
||||
1601. This 64-bit value is split into the two dwords stored in the
|
||||
structure.</em></li>
|
||||
with a file. The structure identifies a 64-bit integer specifying the
|
||||
number of 100-nanosecond intervals which have passed since January 1,
|
||||
1601. This 64-bit value is split into the two dwords stored in the
|
||||
structure.</em></li>
|
||||
|
||||
<li>Information about the code page property in the
|
||||
DocumentSummaryInformation stream is available at <link
|
||||
href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/stg/stg/property_id_1.asp">http://msdn.microsoft.com/library/default.asp?url=/library/en-us/stg/stg/property_id_1.asp</link>.</li>
|
||||
<li>Microsoft provides some public information in the <link
|
||||
href="http://msdn.microsoft.com/library/default.asp">MSDN
|
||||
Library</link>. Use the search function to try to find what you are
|
||||
looking for, e.g. "codepage" or "document summary information" etc.</li>
|
||||
|
||||
<li>This documentation origins from the <link href="http://www.rainer-klute.de/~klute/Software/poibrowser/doc/HPSF-Description.html">HPSF description</link> available at <link href="http://www.rainer-klute.de/~klute/Software/poibrowser/doc/HPSF-Description.html">http://www.rainer-klute.de/~klute/Software/poibrowser/doc/HPSF-Description.html</link>.</li>
|
||||
<li>This documentation origins from the <link href="http://www.rainer-klute.de/~klute/Software/poibrowser/doc/HPSF-Description.html">HPSF description</link> available at <link href="http://www.rainer-klute.de/~klute/Software/poibrowser/doc/HPSF-Description.html">http://www.rainer-klute.de/~klute/Software/poibrowser/doc/HPSF-Description.html</link>.</li>
|
||||
</ol>
|
||||
</section>
|
||||
</section>
|
||||
|
@ -0,0 +1,200 @@
|
||||
/* ====================================================================
|
||||
Copyright 2002-2006 Apache Software Foundation
|
||||
|
||||
Licensed 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.hpsf.examples;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.poi.hpsf.CustomProperties;
|
||||
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
||||
import org.apache.poi.hpsf.MarkUnsupportedException;
|
||||
import org.apache.poi.hpsf.NoPropertySetStreamException;
|
||||
import org.apache.poi.hpsf.PropertySet;
|
||||
import org.apache.poi.hpsf.PropertySetFactory;
|
||||
import org.apache.poi.hpsf.SummaryInformation;
|
||||
import org.apache.poi.hpsf.UnexpectedPropertySetTypeException;
|
||||
import org.apache.poi.hpsf.WritingNotSupportedException;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryEntry;
|
||||
import org.apache.poi.poifs.filesystem.DocumentEntry;
|
||||
import org.apache.poi.poifs.filesystem.DocumentInputStream;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>This is a sample application showing how to easily modify properties in
|
||||
* the summary information and in the document summary information. The
|
||||
* application reads the name of a POI filesystem from the command line and
|
||||
* performs the following actions:</p>
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li><p>Open the POI filesystem.</p></li>
|
||||
*
|
||||
* <li><p>Read the summary information.</p></li>
|
||||
*
|
||||
* <li><p>Read and print the "author" property.</p></li>
|
||||
*
|
||||
* <li><p>Change the author to "Rainer Klute".</p></li>
|
||||
*
|
||||
* <li><p>Read the document summary information.</p></li>
|
||||
*
|
||||
* <li><p>Read and print the "category" property.</p></li>
|
||||
*
|
||||
* <li><p>Change the category to "POI example".</p></li>
|
||||
*
|
||||
* <li><p>Read the custom properties (if available).</p></li>
|
||||
*
|
||||
* <li><p>Insert a new custom property.</p></li>
|
||||
*
|
||||
* <li><p>Write the custom properties back to the document summary
|
||||
* information.</p></li>
|
||||
*
|
||||
* <li><p>Write the summary information to the POI filesystem.</p></li>
|
||||
*
|
||||
* <li><p>Write the document summary information to the POI filesystem.</p></li>
|
||||
*
|
||||
* <li><p>Write the POI filesystem back to the original file.</p></li>
|
||||
*
|
||||
* </ol>
|
||||
*
|
||||
* @author Rainer Klute <a
|
||||
* href="mailto:klute@rainer-klute.de">klute@rainer-klute.de</a>
|
||||
* @since 2006-02-09
|
||||
* @version $Id: TestWrite.java 353637 2005-04-13 16:33:22Z klute $
|
||||
*/
|
||||
public class ModifyDocumentSummaryInformation
|
||||
{
|
||||
|
||||
/**
|
||||
* <p>Main method - see class description.</p>
|
||||
*
|
||||
* @param args The command-line parameters.
|
||||
* @throws IOException
|
||||
* @throws MarkUnsupportedException
|
||||
* @throws NoPropertySetStreamException
|
||||
* @throws UnexpectedPropertySetTypeException
|
||||
* @throws WritingNotSupportedException
|
||||
*/
|
||||
public static void main(final String[] args) throws IOException,
|
||||
NoPropertySetStreamException, MarkUnsupportedException,
|
||||
UnexpectedPropertySetTypeException, WritingNotSupportedException
|
||||
{
|
||||
/* Read the name of the POI filesystem to modify from the command line.
|
||||
* For brevity to boundary check is performed on the command-line
|
||||
* arguments. */
|
||||
File poiFilesystem = new File(args[0]);
|
||||
|
||||
/* Open the POI filesystem. */
|
||||
InputStream is = new FileInputStream(poiFilesystem);
|
||||
POIFSFileSystem poifs = new POIFSFileSystem(is);
|
||||
is.close();
|
||||
|
||||
/* Read the summary information. */
|
||||
DirectoryEntry dir = poifs.getRoot();
|
||||
SummaryInformation si;
|
||||
try
|
||||
{
|
||||
DocumentEntry siEntry = (DocumentEntry)
|
||||
dir.getEntry(SummaryInformation.DEFAULT_STREAM_NAME);
|
||||
DocumentInputStream dis = new DocumentInputStream(siEntry);
|
||||
PropertySet ps = new PropertySet(dis);
|
||||
dis.close();
|
||||
si = new SummaryInformation(ps);
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
/* There is no summary information yet. We have to create a new
|
||||
* one. */
|
||||
si = PropertySetFactory.newSummaryInformation();
|
||||
}
|
||||
|
||||
/* Change the author to "Rainer Klute". Any former author value will
|
||||
* be lost. If there has been no author yet, it will be created. */
|
||||
si.setAuthor("Rainer Klute");
|
||||
System.out.println("Author changed to " + si.getAuthor() + ".");
|
||||
|
||||
|
||||
/* Handling the document summary information is analogous to handling
|
||||
* the summary information. An additional feature, however, are the
|
||||
* custom properties. */
|
||||
|
||||
/* Read the document summary information. */
|
||||
DocumentSummaryInformation dsi;
|
||||
try
|
||||
{
|
||||
DocumentEntry dsiEntry = (DocumentEntry)
|
||||
dir.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
||||
DocumentInputStream dis = new DocumentInputStream(dsiEntry);
|
||||
PropertySet ps = new PropertySet(dis);
|
||||
dis.close();
|
||||
dsi = new DocumentSummaryInformation(ps);
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
/* There is no document summary information yet. We have to create a
|
||||
* new one. */
|
||||
dsi = PropertySetFactory.newDocumentSummaryInformation();
|
||||
}
|
||||
|
||||
/* Change the category to "POI example". Any former category value will
|
||||
* be lost. If there has been no category yet, it will be created. */
|
||||
dsi.setCategory("POI example");
|
||||
System.out.println("Category changed to " + dsi.getCategory() + ".");
|
||||
|
||||
/* Read the custom properties. If there are no custom properties yet,
|
||||
* the application has to create a new CustomProperties object. It will
|
||||
* serve as a container for custom properties. */
|
||||
CustomProperties customProperties = dsi.getCustomProperties();
|
||||
if (customProperties == null)
|
||||
customProperties = new CustomProperties();
|
||||
|
||||
/* Insert some custom properties into the container. */
|
||||
customProperties.put("Key 1", "Value 1");
|
||||
customProperties.put("Schlüssel 2", "Wert 2");
|
||||
customProperties.put("Sample Number", new Integer(12345));
|
||||
customProperties.put("Sample Boolean", new Boolean(true));
|
||||
customProperties.put("Sample Date", new Date());
|
||||
|
||||
/* Read a custom property. */
|
||||
Object value = customProperties.get("Sample Number");
|
||||
|
||||
/* Write the custom properties back to the document summary
|
||||
* information. */
|
||||
dsi.setCustomProperties(customProperties);
|
||||
|
||||
/* Write the summary information and the document summary information
|
||||
* to the POI filesystem. */
|
||||
si.write(dir, SummaryInformation.DEFAULT_STREAM_NAME);
|
||||
dsi.write(dir, DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
||||
|
||||
/* Write the POI filesystem back to the original file. Please note that
|
||||
* in production code you should never write directly to the origin
|
||||
* file! In case of a writing error everything would be lost. */
|
||||
OutputStream out = new FileOutputStream(poiFilesystem);
|
||||
poifs.writeFilesystem(out);
|
||||
out.close();
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
|
@ -1,3 +1,19 @@
|
||||
/* ====================================================================
|
||||
Copyright 2002-2006 Apache Software Foundation
|
||||
|
||||
Licensed 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.hpsf;
|
||||
|
||||
/**
|
||||
|
367
src/java/org/apache/poi/hpsf/CustomProperties.java
Normal file
367
src/java/org/apache/poi/hpsf/CustomProperties.java
Normal file
@ -0,0 +1,367 @@
|
||||
/* ====================================================================
|
||||
Copyright 2002-2006 Apache Software Foundation
|
||||
|
||||
Licensed 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.hpsf;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.poi.hpsf.wellknown.PropertyIDMap;
|
||||
|
||||
/**
|
||||
* <p>Maintains the instances of {@link CustomProperty} that belong to a
|
||||
* {@link DocumentSummaryInformation}. The class maintains the names of the
|
||||
* custom properties in a dictionary. It implements the {@link Map} interface
|
||||
* and by this provides a simplified view on custom properties: A property's
|
||||
* name is the key that maps to a typed value. This implementation hides
|
||||
* property IDs from the developer and regards the property names as keys to
|
||||
* typed values.</p>
|
||||
*
|
||||
* <p>While this class provides a simple API to custom properties, it ignores
|
||||
* the fact that not names, but IDs are the real keys to properties. Under the
|
||||
* hood this class maintains a 1:1 relationship between IDs and names. Therefore
|
||||
* you should not use this class to process property sets with several IDs
|
||||
* mapping to the same name or with properties without a name: the result will
|
||||
* contain only a subset of the original properties. If you really need to deal
|
||||
* such property sets, use HPSF's low-level access methods.</p>
|
||||
*
|
||||
* <p>An application can call the {@link #isPure} method to check whether a
|
||||
* property set parsed by {@link CustomProperties} is still pure (i.e.
|
||||
* unmodified) or whether one or more properties have been dropped.</p>
|
||||
*
|
||||
* <p>This class is not thread-safe; concurrent access to instances of this
|
||||
* class must be syncronized.</p>
|
||||
*
|
||||
* @author Rainer Klute <a
|
||||
* href="mailto:klute@rainer-klute.de"><klute@rainer-klute.de></a>
|
||||
* @since 2006-02-09
|
||||
* @version $Id$
|
||||
*/
|
||||
public class CustomProperties extends HashMap
|
||||
{
|
||||
|
||||
/**
|
||||
* <p>Maps property IDs to property names.</p>
|
||||
*/
|
||||
private Map dictionaryIDToName = new HashMap();
|
||||
|
||||
/**
|
||||
* <p>Maps property names to property IDs.</p>
|
||||
*/
|
||||
private Map dictionaryNameToID = new HashMap();
|
||||
|
||||
/**
|
||||
* <p>Tells whether this object is pure or not.</p>
|
||||
*/
|
||||
private boolean isPure = true;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Puts a {@link CustomProperty} into this map. It is assumed that the
|
||||
* {@link CustomProperty} already has a valid ID. Otherwise use
|
||||
* {@link #put(CustomProperty)}.</p>
|
||||
*/
|
||||
public Object put(final Object name, final Object customProperty) throws ClassCastException
|
||||
{
|
||||
final CustomProperty cp = (CustomProperty) customProperty;
|
||||
if (name == null)
|
||||
{
|
||||
/* Ignoring a property without a name. */
|
||||
isPure = false;
|
||||
return null;
|
||||
}
|
||||
if (!(name instanceof String))
|
||||
throw new ClassCastException("The name of a custom property must " +
|
||||
"be a java.lang.String, but it is a " +
|
||||
name.getClass().getName());
|
||||
if (!(name.equals(cp.getName())))
|
||||
throw new IllegalArgumentException("Parameter \"name\" (" + name +
|
||||
") and custom property's name (" + cp.getName() +
|
||||
") do not match.");
|
||||
|
||||
/* Register name and ID in the dictionary. Mapping in both directions is possible. If there is already a */
|
||||
final Long idKey = new Long(cp.getID());
|
||||
final Object oldID = dictionaryNameToID.get(name);
|
||||
dictionaryIDToName.remove(oldID);
|
||||
dictionaryNameToID.put(name, idKey);
|
||||
dictionaryIDToName.put(idKey, name);
|
||||
|
||||
/* Put the custom property into this map. */
|
||||
final Object oldCp = super.remove(oldID);
|
||||
super.put(idKey, cp);
|
||||
return oldCp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Puts a {@link CustomProperty} that has not yet a valid ID into this
|
||||
* map. The method will allocate a suitable ID for the custom property:</p>
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li><p>If there is already a property with the same name, take the ID
|
||||
* of that property.</p></li>
|
||||
*
|
||||
* <li><p>Otherwise find the highest ID and use its value plus one.</p></li>
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* @param customProperty
|
||||
* @return If the was already a property with the same name, the
|
||||
* @throws ClassCastException
|
||||
*/
|
||||
private Object put(final CustomProperty customProperty) throws ClassCastException
|
||||
{
|
||||
final String name = customProperty.getName();
|
||||
|
||||
/* Check whether a property with this name is in the map already. */
|
||||
final Long oldId = (Long) dictionaryNameToID.get(name);
|
||||
if (oldId != null)
|
||||
customProperty.setID(oldId.longValue());
|
||||
else
|
||||
{
|
||||
long max = 1;
|
||||
for (final Iterator i = dictionaryIDToName.keySet().iterator(); i.hasNext();)
|
||||
{
|
||||
final long id = ((Long) i.next()).longValue();
|
||||
if (id > max)
|
||||
max = id;
|
||||
}
|
||||
customProperty.setID(max + 1);
|
||||
}
|
||||
return this.put(name, customProperty);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Removes a custom property.</p>
|
||||
* @param name The name of the custom property to remove
|
||||
* @return The removed property or <code>null</code> if the specified property was not found.
|
||||
*
|
||||
* @see java.util.HashSet#remove(java.lang.Object)
|
||||
*/
|
||||
public Object remove(final String name)
|
||||
{
|
||||
final Long id = (Long) dictionaryNameToID.get(name);
|
||||
if (id == null)
|
||||
return null;
|
||||
dictionaryIDToName.remove(id);
|
||||
dictionaryNameToID.remove(name);
|
||||
return super.remove(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Adds a named string property.</p>
|
||||
*
|
||||
* @param name The property's name.
|
||||
* @param value The property's value.
|
||||
* @return the property that was stored under the specified name before, or
|
||||
* <code>null</code> if there was no such property before.
|
||||
*/
|
||||
public Object put(final String name, final String value)
|
||||
{
|
||||
final MutableProperty p = new MutableProperty();
|
||||
p.setID(-1);
|
||||
p.setType(Variant.VT_LPWSTR);
|
||||
p.setValue(value);
|
||||
final CustomProperty cp = new CustomProperty(p, name);
|
||||
return put(cp);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Adds a named long property.</p>
|
||||
*
|
||||
* @param name The property's name.
|
||||
* @param value The property's value.
|
||||
* @return the property that was stored under the specified name before, or
|
||||
* <code>null</code> if there was no such property before.
|
||||
*/
|
||||
public Object put(final String name, final Long value)
|
||||
{
|
||||
final MutableProperty p = new MutableProperty();
|
||||
p.setID(-1);
|
||||
p.setType(Variant.VT_I8);
|
||||
p.setValue(value);
|
||||
final CustomProperty cp = new CustomProperty(p, name);
|
||||
return put(cp);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Adds a named double property.</p>
|
||||
*
|
||||
* @param name The property's name.
|
||||
* @param value The property's value.
|
||||
* @return the property that was stored under the specified name before, or
|
||||
* <code>null</code> if there was no such property before.
|
||||
*/
|
||||
public Object put(final String name, final Double value)
|
||||
{
|
||||
final MutableProperty p = new MutableProperty();
|
||||
p.setID(-1);
|
||||
p.setType(Variant.VT_R8);
|
||||
p.setValue(value);
|
||||
final CustomProperty cp = new CustomProperty(p, name);
|
||||
return put(cp);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Adds a named integer property.</p>
|
||||
*
|
||||
* @param name The property's name.
|
||||
* @param value The property's value.
|
||||
* @return the property that was stored under the specified name before, or
|
||||
* <code>null</code> if there was no such property before.
|
||||
*/
|
||||
public Object put(final String name, final Integer value)
|
||||
{
|
||||
final MutableProperty p = new MutableProperty();
|
||||
p.setID(-1);
|
||||
p.setType(Variant.VT_I4);
|
||||
p.setValue(value);
|
||||
final CustomProperty cp = new CustomProperty(p, name);
|
||||
return put(cp);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Adds a named boolean property.</p>
|
||||
*
|
||||
* @param name The property's name.
|
||||
* @param value The property's value.
|
||||
* @return the property that was stored under the specified name before, or
|
||||
* <code>null</code> if there was no such property before.
|
||||
*/
|
||||
public Object put(final String name, final Boolean value)
|
||||
{
|
||||
final MutableProperty p = new MutableProperty();
|
||||
p.setID(-1);
|
||||
p.setType(Variant.VT_BOOL);
|
||||
p.setValue(value);
|
||||
final CustomProperty cp = new CustomProperty(p, name);
|
||||
return put(cp);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Gets a named value from the custom properties.</p>
|
||||
*
|
||||
* @param name the name of the value to get
|
||||
* @return the value or <code>null</code> if a value with the specified
|
||||
* name is not found in the custom properties.
|
||||
*/
|
||||
public Object get(final String name)
|
||||
{
|
||||
final Long id = (Long) dictionaryNameToID.get(name);
|
||||
final CustomProperty cp = (CustomProperty) super.get(id);
|
||||
return cp != null ? cp.getValue() : null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Adds a named date property.</p>
|
||||
*
|
||||
* @param name The property's name.
|
||||
* @param value The property's value.
|
||||
* @return the property that was stored under the specified name before, or
|
||||
* <code>null</code> if there was no such property before.
|
||||
*/
|
||||
public Object put(final String name, final Date value)
|
||||
{
|
||||
final MutableProperty p = new MutableProperty();
|
||||
p.setID(-1);
|
||||
p.setType(Variant.VT_FILETIME);
|
||||
p.setValue(value);
|
||||
final CustomProperty cp = new CustomProperty(p, name);
|
||||
return put(cp);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the codepage.</p>
|
||||
*
|
||||
* @param codepage the codepage
|
||||
*/
|
||||
public void setCodepage(final int codepage)
|
||||
{
|
||||
final MutableProperty p = new MutableProperty();
|
||||
p.setID(PropertyIDMap.PID_CODEPAGE);
|
||||
p.setType(Variant.VT_I2);
|
||||
p.setValue(new Integer(codepage));
|
||||
put(new CustomProperty(p));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Gets the dictionary which contains IDs and names of the named custom
|
||||
* properties.
|
||||
*
|
||||
* @return the dictionary.
|
||||
*/
|
||||
Map getDictionary()
|
||||
{
|
||||
return dictionaryIDToName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Gets the codepage.</p>
|
||||
*
|
||||
* @return the codepage or -1 if the codepage is undefined.
|
||||
*/
|
||||
public int getCodepage()
|
||||
{
|
||||
int codepage = -1;
|
||||
for (final Iterator i = this.values().iterator(); codepage == -1 && i.hasNext();)
|
||||
{
|
||||
final CustomProperty cp = (CustomProperty) i.next();
|
||||
if (cp.getID() == PropertyIDMap.PID_CODEPAGE)
|
||||
codepage = ((Integer) cp.getValue()).intValue();
|
||||
}
|
||||
return codepage;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Tells whether this {@link CustomProperties} instance is pure or one or
|
||||
* more properties of the underlying low-level property set has been
|
||||
* dropped.</p>
|
||||
*
|
||||
* @return <code>true</code> if the {@link CustomProperties} is pure, else
|
||||
* <code>false</code>.
|
||||
*/
|
||||
public boolean isPure()
|
||||
{
|
||||
return isPure;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the purity of the custom property set.</p>
|
||||
*
|
||||
* @param isPure the purity
|
||||
*/
|
||||
public void setPure(final boolean isPure)
|
||||
{
|
||||
this.isPure = isPure;
|
||||
}
|
||||
|
||||
}
|
123
src/java/org/apache/poi/hpsf/CustomProperty.java
Normal file
123
src/java/org/apache/poi/hpsf/CustomProperty.java
Normal file
@ -0,0 +1,123 @@
|
||||
/* ====================================================================
|
||||
Copyright 2002-2006 Apache Software Foundation
|
||||
|
||||
Licensed 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.hpsf;
|
||||
|
||||
/**
|
||||
* <p>This class represents custum properties in the document summary
|
||||
* information stream. The difference to normal properties is that custom
|
||||
* properties have an optional name. If the name is not <code>null</code> it
|
||||
* will be maintained in the section's dictionary.</p>
|
||||
*
|
||||
* @author Rainer Klute <a
|
||||
* href="mailto:klute@rainer-klute.de"><klute@rainer-klute.de></a>
|
||||
* @since 2006-02-09
|
||||
* @version $Id$
|
||||
*/
|
||||
public class CustomProperty extends MutableProperty
|
||||
{
|
||||
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* <p>Creates an empty {@link CustomProperty}. The set methods must be
|
||||
* called to make it usable.</p>
|
||||
*/
|
||||
public CustomProperty()
|
||||
{
|
||||
this.name = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Creates a {@link CustomProperty} without a name by copying the
|
||||
* underlying {@link Property}' attributes.</p>
|
||||
*
|
||||
* @param property the property to copy
|
||||
*/
|
||||
public CustomProperty(final Property property)
|
||||
{
|
||||
this(property, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Creates a {@link CustomProperty} with a name.</p>
|
||||
*
|
||||
* @param property This property's attributes are copied to the new custom
|
||||
* property.
|
||||
* @param name The new custom property's name.
|
||||
*/
|
||||
public CustomProperty(final Property property, final String name)
|
||||
{
|
||||
super(property);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Gets the property's name.</p>
|
||||
*
|
||||
* @return the property's name.
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the property's name.</p>
|
||||
*
|
||||
* @param name The name to set.
|
||||
*/
|
||||
public void setName(final String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Compares two custom properties for equality. The method returns
|
||||
* <code>true</code> if all attributes of the two custom properties are
|
||||
* equal.</p>
|
||||
*
|
||||
* @param o The custom property to compare with.
|
||||
* @return <code>true</code> if both custom properties are equal, else
|
||||
* <code>false</code>.
|
||||
*
|
||||
* @see java.util.AbstractSet#equals(java.lang.Object)
|
||||
*/
|
||||
public boolean equalsContents(final Object o)
|
||||
{
|
||||
final CustomProperty c = (CustomProperty) o;
|
||||
final String name1 = c.getName();
|
||||
final String name2 = this.getName();
|
||||
boolean equalNames = true;
|
||||
if (name1 == null)
|
||||
equalNames = name2 == null;
|
||||
else
|
||||
equalNames = name1.equals(name2);
|
||||
return equalNames && c.getID() == this.getID()
|
||||
&& c.getType() == this.getType()
|
||||
&& c.getValue().equals(this.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.AbstractSet#hashCode()
|
||||
*/
|
||||
public int hashCode()
|
||||
{
|
||||
return (int) this.getID();
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
Copyright 2002-2006 Apache Software Foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -17,11 +16,11 @@
|
||||
|
||||
package org.apache.poi.hpsf;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.poi.hpsf.wellknown.PropertyIDMap;
|
||||
import org.apache.poi.hpsf.wellknown.SectionIDMap;
|
||||
|
||||
/**
|
||||
* <p>Convenience class representing a DocumentSummary Information stream in a
|
||||
@ -68,7 +67,7 @@ public class DocumentSummaryInformation extends SpecialPropertySet
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's category (or <code>null</code>).</p>
|
||||
* <p>Returns the category (or <code>null</code>).</p>
|
||||
*
|
||||
* @return The category value
|
||||
*/
|
||||
@ -77,23 +76,63 @@ public class DocumentSummaryInformation extends SpecialPropertySet
|
||||
return (String) getProperty(PropertyIDMap.PID_CATEGORY);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the category.</p>
|
||||
*
|
||||
* @param category The category to set.
|
||||
*/
|
||||
public void setCategory(final String category)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_CATEGORY, category);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Removes the category.</p>
|
||||
*/
|
||||
public void removeCategory()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_CATEGORY);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's presentation format (or
|
||||
* <p>Returns the presentation format (or
|
||||
* <code>null</code>).</p>
|
||||
*
|
||||
* @return The presentationFormat value
|
||||
* @return The presentation format value
|
||||
*/
|
||||
public String getPresentationFormat()
|
||||
{
|
||||
return (String) getProperty(PropertyIDMap.PID_PRESFORMAT);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the presentation format.</p>
|
||||
*
|
||||
* @param presentationFormat The presentation format to set.
|
||||
*/
|
||||
public void setPresentationFormat(final String presentationFormat)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_PRESFORMAT, presentationFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Removes the presentation format.</p>
|
||||
*/
|
||||
public void removePresentationFormat()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_PRESFORMAT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's byte count or 0 if the {@link
|
||||
* <p>Returns the byte count or 0 if the {@link
|
||||
* DocumentSummaryInformation} does not contain a byte count.</p>
|
||||
*
|
||||
* @return The byteCount value
|
||||
@ -103,86 +142,226 @@ public class DocumentSummaryInformation extends SpecialPropertySet
|
||||
return getPropertyIntValue(PropertyIDMap.PID_BYTECOUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the byte count.</p>
|
||||
*
|
||||
* @param byteCount The byte count to set.
|
||||
*/
|
||||
public void setByteCount(final int byteCount)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_BYTECOUNT, byteCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Removes the byte count.</p>
|
||||
*/
|
||||
public void removeByteCount()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_BYTECOUNT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's line count or 0 if the {@link
|
||||
* <p>Returns the line count or 0 if the {@link
|
||||
* DocumentSummaryInformation} does not contain a line count.</p>
|
||||
*
|
||||
* @return The lineCount value
|
||||
* @return The line count value
|
||||
*/
|
||||
public int getLineCount()
|
||||
{
|
||||
return getPropertyIntValue(PropertyIDMap.PID_LINECOUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the line count.</p>
|
||||
*
|
||||
* @param lineCount The line count to set.
|
||||
*/
|
||||
public void setLineCount(final int lineCount)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_LINECOUNT, lineCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Removes the line count.</p>
|
||||
*/
|
||||
public void removeLineCount()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_LINECOUNT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's par count or 0 if the {@link
|
||||
* <p>Returns the par count or 0 if the {@link
|
||||
* DocumentSummaryInformation} does not contain a par count.</p>
|
||||
*
|
||||
* @return The parCount value
|
||||
* @return The par count value
|
||||
*/
|
||||
public int getParCount()
|
||||
{
|
||||
return getPropertyIntValue(PropertyIDMap.PID_PARCOUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the par count.</p>
|
||||
*
|
||||
* @param parCount The par count to set.
|
||||
*/
|
||||
public void setParCount(final int parCount)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_PARCOUNT, parCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Removes the par count.</p>
|
||||
*/
|
||||
public void removeParCount()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_PARCOUNT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's slide count or 0 if the {@link
|
||||
* <p>Returns the slide count or 0 if the {@link
|
||||
* DocumentSummaryInformation} does not contain a slide count.</p>
|
||||
*
|
||||
* @return The slideCount value
|
||||
* @return The slide count value
|
||||
*/
|
||||
public int getSlideCount()
|
||||
{
|
||||
return getPropertyIntValue(PropertyIDMap.PID_SLIDECOUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the slideCount.</p>
|
||||
*
|
||||
* @param slideCount The slide count to set.
|
||||
*/
|
||||
public void setSlideCount(final int slideCount)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_SLIDECOUNT, slideCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Removes the slide count.</p>
|
||||
*/
|
||||
public void removeSlideCount()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_SLIDECOUNT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's note count or 0 if the {@link
|
||||
* <p>Returns the note count or 0 if the {@link
|
||||
* DocumentSummaryInformation} does not contain a note count.</p>
|
||||
*
|
||||
* @return The noteCount value
|
||||
* @return The note count value
|
||||
*/
|
||||
public int getNoteCount()
|
||||
{
|
||||
return getPropertyIntValue(PropertyIDMap.PID_NOTECOUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the note count.</p>
|
||||
*
|
||||
* @param noteCount The note count to set.
|
||||
*/
|
||||
public void setNoteCount(final int noteCount)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_NOTECOUNT, noteCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Removes the noteCount.</p>
|
||||
*/
|
||||
public void removeNoteCount()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_NOTECOUNT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's hidden count or 0 if the {@link
|
||||
* <p>Returns the hidden count or 0 if the {@link
|
||||
* DocumentSummaryInformation} does not contain a hidden
|
||||
* count.</p>
|
||||
*
|
||||
* @return The hiddenCount value
|
||||
* @return The hidden count value
|
||||
*/
|
||||
public int getHiddenCount()
|
||||
{
|
||||
return getPropertyIntValue(PropertyIDMap.PID_HIDDENCOUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the hidden count.</p>
|
||||
*
|
||||
* @param hiddenCount The hidden count to set.
|
||||
*/
|
||||
public void setHiddenCount(final int hiddenCount)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getSections().get(0);
|
||||
s.setProperty(PropertyIDMap.PID_HIDDENCOUNT, hiddenCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Removes the hidden count.</p>
|
||||
*/
|
||||
public void removeHiddenCount()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_HIDDENCOUNT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's mmclip count or 0 if the {@link
|
||||
* <p>Returns the mmclip count or 0 if the {@link
|
||||
* DocumentSummaryInformation} does not contain a mmclip
|
||||
* count.</p>
|
||||
*
|
||||
* @return The mMClipCount value
|
||||
* @return The mmclip count value
|
||||
*/
|
||||
public int getMMClipCount()
|
||||
{
|
||||
return getPropertyIntValue(PropertyIDMap.PID_MMCLIPCOUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the mmclip count.</p>
|
||||
*
|
||||
* @param mmClipCount The mmclip count to set.
|
||||
*/
|
||||
public void setMMClipCount(final int mmClipCount)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_MMCLIPCOUNT, mmClipCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Removes the mmclip count.</p>
|
||||
*/
|
||||
public void removeMMClipCount()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_MMCLIPCOUNT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@ -196,42 +375,100 @@ public class DocumentSummaryInformation extends SpecialPropertySet
|
||||
return getPropertyBooleanValue(PropertyIDMap.PID_SCALE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Sets the scale.</p>
|
||||
*
|
||||
* @param scale The scale to set.
|
||||
*/
|
||||
public void setScale(final boolean scale)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_SCALE, scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's heading pair (or <code>null</code>)
|
||||
* <strong>when this method is implemented. Please note that the
|
||||
* return type is likely to change!</strong>
|
||||
*
|
||||
* @return The headingPair value
|
||||
* <p>Removes the scale.</p>
|
||||
*/
|
||||
public byte[] getHeadingPair()
|
||||
public void removeScale()
|
||||
{
|
||||
if (true)
|
||||
throw new UnsupportedOperationException("FIXME");
|
||||
return (byte[]) getProperty(PropertyIDMap.PID_HEADINGPAIR);
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_SCALE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's doc parts (or <code>null</code>)
|
||||
* <p>Returns the heading pair (or <code>null</code>)
|
||||
* <strong>when this method is implemented. Please note that the
|
||||
* return type is likely to change!</strong>
|
||||
*
|
||||
* @return The docparts value
|
||||
* @return The heading pair value
|
||||
*/
|
||||
public byte[] getHeadingPair()
|
||||
{
|
||||
notYetImplemented("Reading byte arrays ");
|
||||
return (byte[]) getProperty(PropertyIDMap.PID_HEADINGPAIR);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the heading pair.</p>
|
||||
*
|
||||
* @param headingPair The heading pair to set.
|
||||
*/
|
||||
public void setHeadingPair(final byte[] headingPair)
|
||||
{
|
||||
notYetImplemented("Writing byte arrays ");
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Removes the heading pair.</p>
|
||||
*/
|
||||
public void removeHeadingPair()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_HEADINGPAIR);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the doc parts (or <code>null</code>)
|
||||
* <strong>when this method is implemented. Please note that the
|
||||
* return type is likely to change!</strong>
|
||||
*
|
||||
* @return The doc parts value
|
||||
*/
|
||||
public byte[] getDocparts()
|
||||
{
|
||||
if (true)
|
||||
throw new UnsupportedOperationException("FIXME");
|
||||
notYetImplemented("Reading byte arrays");
|
||||
return (byte[]) getProperty(PropertyIDMap.PID_DOCPARTS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's manager (or <code>null</code>).</p>
|
||||
* <p>Sets the doc parts.</p>
|
||||
*
|
||||
* @param docparts The doc parts to set.
|
||||
*/
|
||||
public void setDocparts(final byte[] docparts)
|
||||
{
|
||||
notYetImplemented("Writing byte arrays");
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Removes the doc parts.</p>
|
||||
*/
|
||||
public void removeDocparts()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_DOCPARTS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the manager (or <code>null</code>).</p>
|
||||
*
|
||||
* @return The manager value
|
||||
*/
|
||||
@ -240,10 +477,30 @@ public class DocumentSummaryInformation extends SpecialPropertySet
|
||||
return (String) getProperty(PropertyIDMap.PID_MANAGER);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the manager.</p>
|
||||
*
|
||||
* @param manager The manager to set.
|
||||
*/
|
||||
public void setManager(final String manager)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_MANAGER, manager);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Removes the manager.</p>
|
||||
*/
|
||||
public void removeManager()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_MANAGER);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's company (or <code>null</code>).</p>
|
||||
* <p>Returns the company (or <code>null</code>).</p>
|
||||
*
|
||||
* @return The company value
|
||||
*/
|
||||
@ -252,47 +509,168 @@ public class DocumentSummaryInformation extends SpecialPropertySet
|
||||
return (String) getProperty(PropertyIDMap.PID_COMPANY);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the company.</p>
|
||||
*
|
||||
* @param company The company to set.
|
||||
*/
|
||||
public void setCompany(final String company)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_COMPANY, company);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Removes the company.</p>
|
||||
*/
|
||||
public void removeCompany()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_COMPANY);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns <code>true</code> if the custom links are dirty.</p> <p>
|
||||
*
|
||||
* @return The linksDirty value
|
||||
* @return The links dirty value
|
||||
*/
|
||||
public boolean getLinksDirty()
|
||||
{
|
||||
return getPropertyBooleanValue(PropertyIDMap.PID_LINKSDIRTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the linksDirty.</p>
|
||||
*
|
||||
* @param linksDirty The links dirty value to set.
|
||||
*/
|
||||
public void setLinksDirty(final boolean linksDirty)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_LINKSDIRTY, linksDirty);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Removes the links dirty.</p>
|
||||
*/
|
||||
public void removeLinksDirty()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_LINKSDIRTY);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Gets the custom properties as a map from the property name to
|
||||
* value.</p>
|
||||
* <p>Gets the custom properties.</p>
|
||||
*
|
||||
* @return The custom properties if any exist, <code>null</code> otherwise.
|
||||
* @since 2003-10-22
|
||||
* @return The custom properties.
|
||||
* @since 2006-02-09
|
||||
*/
|
||||
public Map getCustomProperties()
|
||||
public CustomProperties getCustomProperties()
|
||||
{
|
||||
Map nameToValue = null;
|
||||
CustomProperties cps = null;
|
||||
if (getSectionCount() >= 2)
|
||||
{
|
||||
cps = new CustomProperties();
|
||||
final Section section = (Section) getSections().get(1);
|
||||
final Map pidToName =
|
||||
(Map) section.getProperty(PropertyIDMap.PID_DICTIONARY);
|
||||
if (pidToName != null)
|
||||
final Map dictionary = section.getDictionary();
|
||||
final Property[] properties = section.getProperties();
|
||||
int propertyCount = 0;
|
||||
for (int i = 0; i < properties.length; i++)
|
||||
{
|
||||
nameToValue = new HashMap(pidToName.size());
|
||||
for (Iterator i = pidToName.entrySet().iterator(); i.hasNext();)
|
||||
final Property p = properties[i];
|
||||
final long id = p.getID();
|
||||
if (id != 0 && id != 1)
|
||||
{
|
||||
final Map.Entry e = (Map.Entry) i.next();
|
||||
final long pid = ((Number) e.getKey()).longValue();
|
||||
nameToValue.put(e.getValue(), section.getProperty(pid));
|
||||
propertyCount++;
|
||||
final CustomProperty cp = new CustomProperty(p,
|
||||
(String) dictionary.get(new Long(id)));
|
||||
cps.put(cp.getName(), cp);
|
||||
}
|
||||
}
|
||||
if (cps.size() != propertyCount)
|
||||
cps.setPure(false);
|
||||
}
|
||||
return nameToValue;
|
||||
return cps;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the custom properties.</p>
|
||||
*
|
||||
* @param customProperties The custom properties
|
||||
* @since 2006-02-07
|
||||
*/
|
||||
public void setCustomProperties(final CustomProperties customProperties)
|
||||
{
|
||||
ensureSection2();
|
||||
final MutableSection section = (MutableSection) getSections().get(1);
|
||||
final Map dictionary = customProperties.getDictionary();
|
||||
section.clear();
|
||||
|
||||
/* Set the codepage. If both custom properties and section have a
|
||||
* codepage, the codepage from the custom properties wins, else take the
|
||||
* one that is defined. If none is defined, take Unicode. */
|
||||
int cpCodepage = customProperties.getCodepage();
|
||||
if (cpCodepage < 0)
|
||||
cpCodepage = section.getCodepage();
|
||||
if (cpCodepage < 0)
|
||||
cpCodepage = Constants.CP_UNICODE;
|
||||
customProperties.setCodepage(cpCodepage);
|
||||
section.setCodepage(cpCodepage);
|
||||
section.setDictionary(dictionary);
|
||||
for (final Iterator i = customProperties.values().iterator(); i.hasNext();)
|
||||
{
|
||||
final Property p = (Property) i.next();
|
||||
section.setProperty(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Creates section 2 if it is not already present.</p>
|
||||
*
|
||||
*/
|
||||
private void ensureSection2()
|
||||
{
|
||||
if (getSectionCount() < 2)
|
||||
{
|
||||
MutableSection s2 = new MutableSection();
|
||||
s2.setFormatID(SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID[1]);
|
||||
addSection(s2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Removes the custom properties.</p>
|
||||
*
|
||||
* @since 2006-02-08
|
||||
*/
|
||||
public void removeCustomProperties()
|
||||
{
|
||||
if (getSectionCount() >= 2)
|
||||
getSections().remove(1);
|
||||
else
|
||||
throw new HPSFRuntimeException("Illegal internal format of Document SummaryInformation stream: second section is missing.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Throws an {@link UnsupportedOperationException} with a message text
|
||||
* telling which functionality is not yet implemented.</p>
|
||||
*
|
||||
* @param msg text telling was leaves to be implemented, e.g.
|
||||
* "Reading byte arrays".
|
||||
*/
|
||||
private void notYetImplemented(final String msg)
|
||||
{
|
||||
throw new UnsupportedOperationException(msg + " is not yet implemented.");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
@ -18,12 +17,12 @@
|
||||
package org.apache.poi.hpsf;
|
||||
|
||||
/**
|
||||
* <p>This exception is the superclass of all other checked exceptions
|
||||
* thrown in this package. It supports a nested "reason" throwable,
|
||||
* i.e. an exception that caused this one to be thrown.</p>
|
||||
* <p>This exception is the superclass of all other checked exceptions thrown
|
||||
* in this package. It supports a nested "reason" throwable, i.e. an exception
|
||||
* that caused this one to be thrown.</p>
|
||||
*
|
||||
* @author Rainer Klute <a
|
||||
* href="mailto:klute@rainer-klute.de"><klute@rainer-klute.de></a>
|
||||
* href="mailto:klute@rainer-klute.de"><klute@rainer-klute.de></a>
|
||||
* @version $Id$
|
||||
* @since 2002-02-09
|
||||
*/
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
|
76
src/java/org/apache/poi/hpsf/MissingSectionException.java
Normal file
76
src/java/org/apache/poi/hpsf/MissingSectionException.java
Normal file
@ -0,0 +1,76 @@
|
||||
/* ====================================================================
|
||||
Copyright 2002-2006 Apache Software Foundation
|
||||
|
||||
Licensed 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.hpsf;
|
||||
|
||||
/**
|
||||
* <p>This exception is thrown if one of the {@link PropertySet}'s
|
||||
* convenience methods does not find a required {@link Section}.</p>
|
||||
*
|
||||
* <p>The constructors of this class are analogous to those of its
|
||||
* superclass and documented there.</p>
|
||||
*
|
||||
* @author Rainer Klute <a
|
||||
* href="mailto:klute@rainer-klute.de"><klute@rainer-klute.de></a>
|
||||
* @version $Id: NoSingleSectionException.java 353545 2004-04-09 13:05:39Z glens $
|
||||
* @since 2006-02-08
|
||||
*/
|
||||
public class MissingSectionException extends HPSFRuntimeException
|
||||
{
|
||||
|
||||
/**
|
||||
* <p>Constructor</p>
|
||||
*/
|
||||
public MissingSectionException()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Constructor</p>
|
||||
*
|
||||
* @param msg The exception's message string
|
||||
*/
|
||||
public MissingSectionException(final String msg)
|
||||
{
|
||||
super(msg);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Constructor</p>
|
||||
*
|
||||
* @param reason This exception's underlying reason
|
||||
*/
|
||||
public MissingSectionException(final Throwable reason)
|
||||
{
|
||||
super(reason);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Constructor</p>
|
||||
*
|
||||
* @param msg The exception's message string
|
||||
* @param reason This exception's underlying reason
|
||||
*/
|
||||
public MissingSectionException(final String msg, final Throwable reason)
|
||||
{
|
||||
super(msg, reason);
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
Copyright 2002-2006 Apache Software Foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -18,6 +18,7 @@ package org.apache.poi.hpsf;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
@ -26,6 +27,8 @@ import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.ListIterator;
|
||||
|
||||
import org.apache.poi.poifs.filesystem.DirectoryEntry;
|
||||
import org.apache.poi.poifs.filesystem.Entry;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
|
||||
@ -151,7 +154,7 @@ public class MutablePropertySet extends PropertySet
|
||||
*
|
||||
* @param classID The property set stream's low-level "class ID" field.
|
||||
*
|
||||
* @see #getClassID
|
||||
* @see PropertySet#getClassID()
|
||||
*/
|
||||
public void setClassID(final ClassID classID)
|
||||
{
|
||||
@ -205,9 +208,9 @@ public class MutablePropertySet extends PropertySet
|
||||
/* Write the property set's header. */
|
||||
length += TypeWriter.writeToStream(out, (short) getByteOrder());
|
||||
length += TypeWriter.writeToStream(out, (short) getFormat());
|
||||
length += TypeWriter.writeToStream(out, (int) getOSVersion());
|
||||
length += TypeWriter.writeToStream(out, getOSVersion());
|
||||
length += TypeWriter.writeToStream(out, getClassID());
|
||||
length += TypeWriter.writeToStream(out, (int) nrSections);
|
||||
length += TypeWriter.writeToStream(out, nrSections);
|
||||
int offset = OFFSET_HEADER;
|
||||
|
||||
/* Write the section list, i.e. the references to the sections. Each
|
||||
@ -272,4 +275,31 @@ public class MutablePropertySet extends PropertySet
|
||||
return new ByteArrayInputStream(streamData);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Writes a property set to a document in a POI filesystem directory.</p>
|
||||
*
|
||||
* @param dir The directory in the POI filesystem to write the document to.
|
||||
* @param name The document's name. If there is already a document with the
|
||||
* same name in the directory the latter will be overwritten.
|
||||
*
|
||||
* @throws WritingNotSupportedException
|
||||
* @throws IOException
|
||||
*/
|
||||
public void write(final DirectoryEntry dir, final String name)
|
||||
throws WritingNotSupportedException, IOException
|
||||
{
|
||||
/* If there is already an entry with the same name, remove it. */
|
||||
try
|
||||
{
|
||||
final Entry e = dir.getEntry(name);
|
||||
e.delete();
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
/* Entry not found, no need to remove it. */
|
||||
}
|
||||
/* Create the new entry. */
|
||||
dir.createDocument(name, toInputStream());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
Copyright 2002-2006 Apache Software Foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -21,6 +21,7 @@ import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@ -107,7 +108,7 @@ public class MutableSection extends Section
|
||||
* @param formatID The section's format ID
|
||||
*
|
||||
* @see #setFormatID(byte[])
|
||||
* @see #getFormatID
|
||||
* @see Section#getFormatID
|
||||
*/
|
||||
public void setFormatID(final ClassID formatID)
|
||||
{
|
||||
@ -123,7 +124,7 @@ public class MutableSection extends Section
|
||||
* are in big-endian format.
|
||||
*
|
||||
* @see #setFormatID(ClassID)
|
||||
* @see #getFormatID
|
||||
* @see Section#getFormatID
|
||||
*/
|
||||
public void setFormatID(final byte[] formatID)
|
||||
{
|
||||
@ -155,10 +156,7 @@ public class MutableSection extends Section
|
||||
|
||||
|
||||
/**
|
||||
* <p>Sets the value of the property with the specified ID. If a
|
||||
* property with this ID is not yet present in the section, it
|
||||
* will be added. An already present property with the specified
|
||||
* ID will be overwritten.</p>
|
||||
* <p>Sets the string value of the property with the specified ID.</p>
|
||||
*
|
||||
* @param id The property's ID
|
||||
* @param value The property's value. It will be written as a Unicode
|
||||
@ -175,6 +173,57 @@ public class MutableSection extends Section
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Sets the int value of the property with the specified ID.</p>
|
||||
*
|
||||
* @param id The property's ID
|
||||
* @param value The property's value.
|
||||
*
|
||||
* @see #setProperty(int, long, Object)
|
||||
* @see #getProperty
|
||||
*/
|
||||
public void setProperty(final int id, final int value)
|
||||
{
|
||||
setProperty(id, Variant.VT_I4, new Integer(value));
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Sets the long value of the property with the specified ID.</p>
|
||||
*
|
||||
* @param id The property's ID
|
||||
* @param value The property's value.
|
||||
*
|
||||
* @see #setProperty(int, long, Object)
|
||||
* @see #getProperty
|
||||
*/
|
||||
public void setProperty(final int id, final long value)
|
||||
{
|
||||
setProperty(id, Variant.VT_I8, new Long(value));
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Sets the boolean value of the property with the specified ID.</p>
|
||||
*
|
||||
* @param id The property's ID
|
||||
* @param value The property's value.
|
||||
*
|
||||
* @see #setProperty(int, long, Object)
|
||||
* @see #getProperty
|
||||
*/
|
||||
public void setProperty(final int id, final boolean value)
|
||||
{
|
||||
setProperty(id, Variant.VT_BOOL, new Boolean(value));
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Sets the value and the variant type of the property with the
|
||||
* specified ID. If a property with this ID is not yet present in
|
||||
@ -204,15 +253,11 @@ public class MutableSection extends Section
|
||||
|
||||
|
||||
/**
|
||||
* <p>Sets a property. If a property with the same ID is not yet present in
|
||||
* the section, the property will be added to the section. If there is
|
||||
* already a property with the same ID present in the section, it will be
|
||||
* overwritten.</p>
|
||||
* <p>Sets a property.</p>
|
||||
*
|
||||
* @param p The property to be added to the section
|
||||
* @param p The property to be set.
|
||||
*
|
||||
* @see #setProperty(int, long, Object)
|
||||
* @see #setProperty(int, String)
|
||||
* @see #getProperty
|
||||
* @see Variant
|
||||
*/
|
||||
@ -257,7 +302,7 @@ public class MutableSection extends Section
|
||||
*/
|
||||
protected void setPropertyBooleanValue(final int id, final boolean value)
|
||||
{
|
||||
setProperty(id, (long) Variant.VT_BOOL, new Boolean(value));
|
||||
setProperty(id, Variant.VT_BOOL, new Boolean(value));
|
||||
}
|
||||
|
||||
|
||||
@ -296,6 +341,8 @@ public class MutableSection extends Section
|
||||
* properties) and the properties themselves.</p>
|
||||
*
|
||||
* @return the section's length in bytes.
|
||||
* @throws WritingNotSupportedException
|
||||
* @throws IOException
|
||||
*/
|
||||
private int calcSize() throws WritingNotSupportedException, IOException
|
||||
{
|
||||
@ -372,7 +419,7 @@ public class MutableSection extends Section
|
||||
/* Warning: The codepage property is not set although a
|
||||
* dictionary is present. In order to cope with this problem we
|
||||
* add the codepage property and set it to Unicode. */
|
||||
setProperty(PropertyIDMap.PID_CODEPAGE, (long) Variant.VT_I2,
|
||||
setProperty(PropertyIDMap.PID_CODEPAGE, Variant.VT_I2,
|
||||
new Integer(Constants.CP_UNICODE));
|
||||
codepage = getCodepage();
|
||||
}
|
||||
@ -474,16 +521,15 @@ public class MutableSection extends Section
|
||||
sLength++;
|
||||
length += TypeWriter.writeUIntToStream(out, key.longValue());
|
||||
length += TypeWriter.writeUIntToStream(out, sLength);
|
||||
final char[] ca = value.toCharArray();
|
||||
for (int j = 0; j < ca.length; j++)
|
||||
final byte[] ca =
|
||||
value.getBytes(VariantSupport.codepageToEncoding(codepage));
|
||||
for (int j = 2; j < ca.length; j += 2)
|
||||
{
|
||||
int high = (ca[j] & 0x0ff00) >> 8;
|
||||
int low = (ca[j] & 0x000ff);
|
||||
out.write(low);
|
||||
out.write(high);
|
||||
out.write(ca[j+1]);
|
||||
out.write(ca[j]);
|
||||
length += 2;
|
||||
sLength--;
|
||||
}
|
||||
sLength -= value.length();
|
||||
while (sLength > 0)
|
||||
{
|
||||
out.write(0x00);
|
||||
@ -610,4 +656,60 @@ public class MutableSection extends Section
|
||||
removeProperty(PropertyIDMap.PID_DICTIONARY);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Sets a property.</p>
|
||||
*
|
||||
* @param id The property ID.
|
||||
* @param value The property's value. The value's class must be one of those
|
||||
* supported by HPSF.
|
||||
*/
|
||||
public void setProperty(final int id, final Object value)
|
||||
{
|
||||
if (value instanceof String)
|
||||
setProperty(id, (String) value);
|
||||
else if (value instanceof Long)
|
||||
setProperty(id, ((Long) value).longValue());
|
||||
else if (value instanceof Integer)
|
||||
setProperty(id, ((Integer) value).intValue());
|
||||
else if (value instanceof Short)
|
||||
setProperty(id, ((Short) value).intValue());
|
||||
else if (value instanceof Boolean)
|
||||
setProperty(id, ((Boolean) value).booleanValue());
|
||||
else if (value instanceof Date)
|
||||
setProperty(id, Variant.VT_FILETIME, value);
|
||||
else
|
||||
throw new HPSFRuntimeException(
|
||||
"HPSF does not support properties of type " +
|
||||
value.getClass().getName() + ".");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Removes all properties from the section including 0 (dictionary) and
|
||||
* 1 (codepage).</p>
|
||||
*/
|
||||
public void clear()
|
||||
{
|
||||
final Property[] properties = getProperties();
|
||||
for (int i = 0; i < properties.length; i++)
|
||||
{
|
||||
final Property p = properties[i];
|
||||
removeProperty(p.getID());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the codepage.</p>
|
||||
*
|
||||
* @param codepage the codepage
|
||||
*/
|
||||
public void setCodepage(final int codepage)
|
||||
{
|
||||
setProperty(PropertyIDMap.PID_CODEPAGE, Variant.VT_I2,
|
||||
new Integer(codepage));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
Copyright 2002-2006 Apache Software Foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -107,6 +107,22 @@ public class Property
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Creates a property.</p>
|
||||
*
|
||||
* @param id the property's ID.
|
||||
* @param type the property's type, see {@link Variant}.
|
||||
* @param value the property's value. Only certain types are allowed, see {@link Variant}.
|
||||
*/
|
||||
public Property(final long id, final long type, final Object value)
|
||||
{
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Creates a {@link Property} instance by reading its bytes
|
||||
* from the property set stream.</p>
|
||||
@ -222,12 +238,15 @@ public class Property
|
||||
{
|
||||
/* The length is the number of characters, i.e. the number
|
||||
* of bytes is twice the number of the characters. */
|
||||
for (int j = 0; j < sLength; j++)
|
||||
final int nrBytes = (int) (sLength * 2);
|
||||
final byte[] h = new byte[nrBytes];
|
||||
for (int i2 = 0; i2 < nrBytes; i2 += 2)
|
||||
{
|
||||
final int i1 = o + (j * 2);
|
||||
final int i2 = i1 + 1;
|
||||
b.append((char) ((src[i2] << 8) + src[i1]));
|
||||
h[i2] = src[o + i2 + 1];
|
||||
h[i2 + 1] = src[o + i2];
|
||||
}
|
||||
b.append(new String(h, 0, nrBytes,
|
||||
VariantSupport.codepageToEncoding(codepage)));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -1,6 +1,5 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
Copyright 2002-2006 Apache Software Foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -402,8 +401,10 @@ public class PropertySet
|
||||
*
|
||||
* @param src Byte array containing the property set stream
|
||||
* @param offset The property set stream starts at this offset
|
||||
* from the beginning of <var>src</src>
|
||||
* from the beginning of <var>src</var>
|
||||
* @param length Length of the property set stream.
|
||||
* @throws UnsupportedEncodingException if HPSF does not (yet) support the
|
||||
* property set's character encoding.
|
||||
*/
|
||||
private void init(final byte[] src, final int offset, final int length)
|
||||
throws UnsupportedEncodingException
|
||||
@ -482,7 +483,7 @@ public class PropertySet
|
||||
public boolean isDocumentSummaryInformation()
|
||||
{
|
||||
return Util.equal(((Section) sections.get(0)).getFormatID().getBytes(),
|
||||
SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID);
|
||||
SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID[0]);
|
||||
}
|
||||
|
||||
|
||||
@ -492,9 +493,7 @@ public class PropertySet
|
||||
* contained in this property set. It is a shortcut for getting
|
||||
* the {@link PropertySet}'s {@link Section}s list and then
|
||||
* getting the {@link Property} array from the first {@link
|
||||
* Section}. However, it can only be used if the {@link
|
||||
* PropertySet} contains exactly one {@link Section}, so check
|
||||
* {@link #getSectionCount} first!</p>
|
||||
* Section}.</p>
|
||||
*
|
||||
* @return The properties of the only {@link Section} of this
|
||||
* {@link PropertySet}.
|
||||
@ -504,7 +503,7 @@ public class PropertySet
|
||||
public Property[] getProperties()
|
||||
throws NoSingleSectionException
|
||||
{
|
||||
return getSingleSection().getProperties();
|
||||
return getFirstSection().getProperties();
|
||||
}
|
||||
|
||||
|
||||
@ -522,7 +521,7 @@ public class PropertySet
|
||||
*/
|
||||
protected Object getProperty(final int id) throws NoSingleSectionException
|
||||
{
|
||||
return getSingleSection().getProperty(id);
|
||||
return getFirstSection().getProperty(id);
|
||||
}
|
||||
|
||||
|
||||
@ -543,7 +542,7 @@ public class PropertySet
|
||||
protected boolean getPropertyBooleanValue(final int id)
|
||||
throws NoSingleSectionException
|
||||
{
|
||||
return getSingleSection().getPropertyBooleanValue(id);
|
||||
return getFirstSection().getPropertyBooleanValue(id);
|
||||
}
|
||||
|
||||
|
||||
@ -563,7 +562,7 @@ public class PropertySet
|
||||
protected int getPropertyIntValue(final int id)
|
||||
throws NoSingleSectionException
|
||||
{
|
||||
return getSingleSection().getPropertyIntValue(id);
|
||||
return getFirstSection().getPropertyIntValue(id);
|
||||
}
|
||||
|
||||
|
||||
@ -585,7 +584,21 @@ public class PropertySet
|
||||
*/
|
||||
public boolean wasNull() throws NoSingleSectionException
|
||||
{
|
||||
return getSingleSection().wasNull();
|
||||
return getFirstSection().wasNull();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Gets the {@link PropertySet}'s first section.</p>
|
||||
*
|
||||
* @return The {@link PropertySet}'s first section.
|
||||
*/
|
||||
public Section getFirstSection()
|
||||
{
|
||||
if (getSectionCount() < 1)
|
||||
throw new MissingSectionException("Property set does not contain any sections.");
|
||||
return ((Section) sections.get(0));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
Copyright 2002-2006 Apache Software Foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -22,6 +21,8 @@ import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.rmi.UnexpectedException;
|
||||
|
||||
import org.apache.poi.hpsf.wellknown.SectionIDMap;
|
||||
|
||||
/**
|
||||
* <p>Factory class to create instances of {@link SummaryInformation},
|
||||
* {@link DocumentSummaryInformation} and {@link PropertySet}.</p>
|
||||
@ -74,4 +75,50 @@ public class PropertySetFactory
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Creates a new summary information.</p>
|
||||
*
|
||||
* @return the new summary information.
|
||||
*/
|
||||
public static SummaryInformation newSummaryInformation()
|
||||
{
|
||||
final MutablePropertySet ps = new MutablePropertySet();
|
||||
final MutableSection s = (MutableSection) ps.getFirstSection();
|
||||
s.setFormatID(SectionIDMap.SUMMARY_INFORMATION_ID);
|
||||
try
|
||||
{
|
||||
return new SummaryInformation(ps);
|
||||
}
|
||||
catch (UnexpectedPropertySetTypeException ex)
|
||||
{
|
||||
/* This should never happen. */
|
||||
throw new HPSFRuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Creates a new document summary information.</p>
|
||||
*
|
||||
* @return the new document summary information.
|
||||
*/
|
||||
public static DocumentSummaryInformation newDocumentSummaryInformation()
|
||||
{
|
||||
final MutablePropertySet ps = new MutablePropertySet();
|
||||
final MutableSection s = (MutableSection) ps.getFirstSection();
|
||||
s.setFormatID(SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID[0]);
|
||||
try
|
||||
{
|
||||
return new DocumentSummaryInformation(ps);
|
||||
}
|
||||
catch (UnexpectedPropertySetTypeException ex)
|
||||
{
|
||||
/* This should never happen. */
|
||||
throw new HPSFRuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
Copyright 2002-2006 Apache Software Foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -278,9 +277,12 @@ public class Section
|
||||
for (final Iterator i = propertyList.iterator(); i.hasNext();)
|
||||
{
|
||||
ple = (PropertyListEntry) i.next();
|
||||
properties[i1++] = new Property(ple.id, src,
|
||||
this.offset + ple.offset,
|
||||
ple.length, codepage);
|
||||
Property p = new Property(ple.id, src,
|
||||
this.offset + ple.offset,
|
||||
ple.length, codepage);
|
||||
if (p.getID() == PropertyIDMap.PID_CODEPAGE)
|
||||
p = new Property(p.getID(), p.getType(), new Integer(codepage));
|
||||
properties[i1++] = p;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -359,15 +361,15 @@ public class Section
|
||||
*/
|
||||
protected int getPropertyIntValue(final long id)
|
||||
{
|
||||
final Long i;
|
||||
final Number i;
|
||||
final Object o = getProperty(id);
|
||||
if (o == null)
|
||||
return 0;
|
||||
if (!(o instanceof Long))
|
||||
if (!(o instanceof Long || o instanceof Integer))
|
||||
throw new HPSFRuntimeException
|
||||
("This property is not an integer type, but " +
|
||||
o.getClass().getName() + ".");
|
||||
i = (Long) o;
|
||||
i = (Number) o;
|
||||
return i.intValue();
|
||||
}
|
||||
|
||||
@ -545,6 +547,10 @@ public class Section
|
||||
/**
|
||||
* <p>Removes a field from a property array. The resulting array is
|
||||
* compactified and returned.</p>
|
||||
*
|
||||
* @param pa The property array.
|
||||
* @param i The index of the field to be removed.
|
||||
* @return the compactified array.
|
||||
*/
|
||||
private Property[] remove(final Property[] pa, final int i)
|
||||
{
|
||||
@ -629,7 +635,10 @@ public class Section
|
||||
{
|
||||
final Integer codepage =
|
||||
(Integer) getProperty(PropertyIDMap.PID_CODEPAGE);
|
||||
return codepage != null ? codepage.intValue() : -1;
|
||||
if (codepage == null)
|
||||
return -1;
|
||||
int cp = codepage.intValue();
|
||||
return cp;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
Copyright 2002-2006 Apache Software Foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -17,8 +16,13 @@
|
||||
|
||||
package org.apache.poi.hpsf;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.poifs.filesystem.DirectoryEntry;
|
||||
|
||||
/**
|
||||
* <p>Abstract superclass for the convenience classes {@link
|
||||
* SummaryInformation} and {@link DocumentSummaryInformation}.</p>
|
||||
@ -50,24 +54,37 @@ import java.util.List;
|
||||
* @version $Id$
|
||||
* @since 2002-02-09
|
||||
*/
|
||||
public abstract class SpecialPropertySet extends PropertySet
|
||||
public abstract class SpecialPropertySet extends MutablePropertySet
|
||||
{
|
||||
|
||||
/**
|
||||
* <p>The "real" property set <code>SpecialPropertySet</code>
|
||||
* delegates to.</p>
|
||||
*/
|
||||
private PropertySet delegate;
|
||||
private MutablePropertySet delegate;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Creates a <code>SpecialPropertySet</code>.
|
||||
*
|
||||
* @param ps The property set encapsulated by the
|
||||
* @param ps The property set to be encapsulated by the
|
||||
* <code>SpecialPropertySet</code>
|
||||
*/
|
||||
public SpecialPropertySet(final PropertySet ps)
|
||||
{
|
||||
delegate = new MutablePropertySet(ps);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Creates a <code>SpecialPropertySet</code>.
|
||||
*
|
||||
* @param ps The mutable property set to be encapsulated by the
|
||||
* <code>SpecialPropertySet</code>
|
||||
*/
|
||||
public SpecialPropertySet(final MutablePropertySet ps)
|
||||
{
|
||||
delegate = ps;
|
||||
}
|
||||
@ -157,9 +174,178 @@ public abstract class SpecialPropertySet extends PropertySet
|
||||
/**
|
||||
* @see PropertySet#getSingleSection
|
||||
*/
|
||||
public Section getSingleSection()
|
||||
public Section getFirstSection()
|
||||
{
|
||||
return delegate.getSingleSection();
|
||||
return delegate.getFirstSection();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.apache.poi.hpsf.MutablePropertySet#addSection(org.apache.poi.hpsf.Section)
|
||||
*/
|
||||
public void addSection(final Section section)
|
||||
{
|
||||
delegate.addSection(section);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.apache.poi.hpsf.MutablePropertySet#clearSections()
|
||||
*/
|
||||
public void clearSections()
|
||||
{
|
||||
delegate.clearSections();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.apache.poi.hpsf.MutablePropertySet#setByteOrder(int)
|
||||
*/
|
||||
public void setByteOrder(final int byteOrder)
|
||||
{
|
||||
delegate.setByteOrder(byteOrder);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.apache.poi.hpsf.MutablePropertySet#setClassID(org.apache.poi.hpsf.ClassID)
|
||||
*/
|
||||
public void setClassID(final ClassID classID)
|
||||
{
|
||||
delegate.setClassID(classID);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.apache.poi.hpsf.MutablePropertySet#setFormat(int)
|
||||
*/
|
||||
public void setFormat(final int format)
|
||||
{
|
||||
delegate.setFormat(format);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.apache.poi.hpsf.MutablePropertySet#setOSVersion(int)
|
||||
*/
|
||||
public void setOSVersion(final int osVersion)
|
||||
{
|
||||
delegate.setOSVersion(osVersion);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.apache.poi.hpsf.MutablePropertySet#toInputStream()
|
||||
*/
|
||||
public InputStream toInputStream() throws IOException, WritingNotSupportedException
|
||||
{
|
||||
return delegate.toInputStream();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.apache.poi.hpsf.MutablePropertySet#write(org.apache.poi.poifs.filesystem.DirectoryEntry, java.lang.String)
|
||||
*/
|
||||
public void write(final DirectoryEntry dir, final String name) throws WritingNotSupportedException, IOException
|
||||
{
|
||||
delegate.write(dir, name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.apache.poi.hpsf.MutablePropertySet#write(java.io.OutputStream)
|
||||
*/
|
||||
public void write(final OutputStream out) throws WritingNotSupportedException, IOException
|
||||
{
|
||||
delegate.write(out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.apache.poi.hpsf.PropertySet#equals(java.lang.Object)
|
||||
*/
|
||||
public boolean equals(final Object o)
|
||||
{
|
||||
return delegate.equals(o);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.apache.poi.hpsf.PropertySet#getProperties()
|
||||
*/
|
||||
public Property[] getProperties() throws NoSingleSectionException
|
||||
{
|
||||
return delegate.getProperties();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.apache.poi.hpsf.PropertySet#getProperty(int)
|
||||
*/
|
||||
protected Object getProperty(final int id) throws NoSingleSectionException
|
||||
{
|
||||
return delegate.getProperty(id);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.apache.poi.hpsf.PropertySet#getPropertyBooleanValue(int)
|
||||
*/
|
||||
protected boolean getPropertyBooleanValue(final int id) throws NoSingleSectionException
|
||||
{
|
||||
return delegate.getPropertyBooleanValue(id);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.apache.poi.hpsf.PropertySet#getPropertyIntValue(int)
|
||||
*/
|
||||
protected int getPropertyIntValue(final int id) throws NoSingleSectionException
|
||||
{
|
||||
return delegate.getPropertyIntValue(id);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.apache.poi.hpsf.PropertySet#hashCode()
|
||||
*/
|
||||
public int hashCode()
|
||||
{
|
||||
return delegate.hashCode();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.apache.poi.hpsf.PropertySet#toString()
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return delegate.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.apache.poi.hpsf.PropertySet#wasNull()
|
||||
*/
|
||||
public boolean wasNull() throws NoSingleSectionException
|
||||
{
|
||||
return delegate.wasNull();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,23 +1,25 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
Licensed 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.
|
||||
==================================================================== */
|
||||
/*
|
||||
* ====================================================================
|
||||
* Copyright 2002-2006 Apache Software Foundation
|
||||
*
|
||||
* Licensed 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.hpsf;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.poi.hpsf.wellknown.PropertyIDMap;
|
||||
|
||||
/**
|
||||
@ -25,7 +27,7 @@ import org.apache.poi.hpsf.wellknown.PropertyIDMap;
|
||||
* Microsoft Office document.</p>
|
||||
*
|
||||
* @author Rainer Klute <a
|
||||
* href="mailto:klute@rainer-klute.de"><klute@rainer-klute.de></a>
|
||||
* href="mailto:klute@rainer-klute.de"><klute@rainer-klute.de></a>
|
||||
* @see DocumentSummaryInformation
|
||||
* @version $Id$
|
||||
* @since 2002-02-09
|
||||
@ -34,8 +36,8 @@ public class SummaryInformation extends SpecialPropertySet
|
||||
{
|
||||
|
||||
/**
|
||||
* <p>The document name a summary information stream usually has
|
||||
* in a POIFS filesystem.</p>
|
||||
* <p>The document name a summary information stream usually has in a POIFS
|
||||
* filesystem.</p>
|
||||
*/
|
||||
public static final String DEFAULT_STREAM_NAME = "\005SummaryInformation";
|
||||
|
||||
@ -46,23 +48,23 @@ public class SummaryInformation extends SpecialPropertySet
|
||||
* PropertySet}.</p>
|
||||
*
|
||||
* @param ps A property set which should be created from a summary
|
||||
* information stream.
|
||||
* @throws UnexpectedPropertySetTypeException if <var>ps</var>
|
||||
* does not contain a summary information stream.
|
||||
* information stream.
|
||||
* @throws UnexpectedPropertySetTypeException if <var>ps</var> does not
|
||||
* contain a summary information stream.
|
||||
*/
|
||||
public SummaryInformation(final PropertySet ps)
|
||||
throws UnexpectedPropertySetTypeException
|
||||
throws UnexpectedPropertySetTypeException
|
||||
{
|
||||
super(ps);
|
||||
if (!isSummaryInformation())
|
||||
throw new UnexpectedPropertySetTypeException
|
||||
("Not a " + getClass().getName());
|
||||
throw new UnexpectedPropertySetTypeException("Not a "
|
||||
+ getClass().getName());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's title (or <code>null</code>).</p>
|
||||
* <p>Returns the title (or <code>null</code>).</p>
|
||||
*
|
||||
* @return The title or <code>null</code>
|
||||
*/
|
||||
@ -74,7 +76,31 @@ public class SummaryInformation extends SpecialPropertySet
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's subject (or <code>null</code>).</p>
|
||||
* <p>Sets the title.</p>
|
||||
*
|
||||
* @param title The title to set.
|
||||
*/
|
||||
public void setTitle(final String title)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_TITLE, title);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Removes the title.</p>
|
||||
*/
|
||||
public void removeTitle()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_TITLE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the subject (or <code>null</code>).</p>
|
||||
*
|
||||
* @return The subject or <code>null</code>
|
||||
*/
|
||||
@ -86,7 +112,31 @@ public class SummaryInformation extends SpecialPropertySet
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's author (or <code>null</code>).</p>
|
||||
* <p>Sets the subject.</p>
|
||||
*
|
||||
* @param subject The subject to set.
|
||||
*/
|
||||
public void setSubject(final String subject)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_SUBJECT, subject);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Removes the subject.</p>
|
||||
*/
|
||||
public void removeSubject()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_SUBJECT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the author (or <code>null</code>).</p>
|
||||
*
|
||||
* @return The author or <code>null</code>
|
||||
*/
|
||||
@ -98,7 +148,31 @@ public class SummaryInformation extends SpecialPropertySet
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's keywords (or <code>null</code>).</p>
|
||||
* <p>Sets the author.</p>
|
||||
*
|
||||
* @param author The author to set.
|
||||
*/
|
||||
public void setAuthor(final String author)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_AUTHOR, author);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Removes the author.</p>
|
||||
*/
|
||||
public void removeAuthor()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_AUTHOR);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the keywords (or <code>null</code>).</p>
|
||||
*
|
||||
* @return The keywords or <code>null</code>
|
||||
*/
|
||||
@ -110,7 +184,31 @@ public class SummaryInformation extends SpecialPropertySet
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's comments (or <code>null</code>).</p>
|
||||
* <p>Sets the keywords.</p>
|
||||
*
|
||||
* @param keywords The keywords to set.
|
||||
*/
|
||||
public void setKeywords(final String keywords)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_KEYWORDS, keywords);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Removes the keywords.</p>
|
||||
*/
|
||||
public void removeKeywords()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_KEYWORDS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the comments (or <code>null</code>).</p>
|
||||
*
|
||||
* @return The comments or <code>null</code>
|
||||
*/
|
||||
@ -122,7 +220,31 @@ public class SummaryInformation extends SpecialPropertySet
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's template (or <code>null</code>).</p>
|
||||
* <p>Sets the comments.</p>
|
||||
*
|
||||
* @param comments The comments to set.
|
||||
*/
|
||||
public void setComments(final String comments)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_COMMENTS, comments);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Removes the comments.</p>
|
||||
*/
|
||||
public void removeComments()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_COMMENTS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the template (or <code>null</code>).</p>
|
||||
*
|
||||
* @return The template or <code>null</code>
|
||||
*/
|
||||
@ -134,7 +256,31 @@ public class SummaryInformation extends SpecialPropertySet
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's last author (or <code>null</code>).</p>
|
||||
* <p>Sets the template.</p>
|
||||
*
|
||||
* @param template The template to set.
|
||||
*/
|
||||
public void setTemplate(final String template)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_TEMPLATE, template);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Removes the template.</p>
|
||||
*/
|
||||
public void removeTemplate()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_TEMPLATE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the last author (or <code>null</code>).</p>
|
||||
*
|
||||
* @return The last author or <code>null</code>
|
||||
*/
|
||||
@ -146,8 +292,31 @@ public class SummaryInformation extends SpecialPropertySet
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's revision number (or
|
||||
* <code>null</code>). </p>
|
||||
* <p>Sets the last author.</p>
|
||||
*
|
||||
* @param lastAuthor The last author to set.
|
||||
*/
|
||||
public void setLastAuthor(final String lastAuthor)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_LASTAUTHOR, lastAuthor);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Removes the last author.</p>
|
||||
*/
|
||||
public void removeLastAuthor()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_LASTAUTHOR);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the revision number (or <code>null</code>). </p>
|
||||
*
|
||||
* @return The revision number or <code>null</code>
|
||||
*/
|
||||
@ -159,11 +328,35 @@ public class SummaryInformation extends SpecialPropertySet
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the total time spent in editing the document
|
||||
* (or <code>0</code>).</p>
|
||||
* <p>Sets the revision number.</p>
|
||||
*
|
||||
* @param revNumber The revision number to set.
|
||||
*/
|
||||
public void setRevNumber(final String revNumber)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_REVNUMBER, revNumber);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Removes the revision number.</p>
|
||||
*/
|
||||
public void removeRevNumber()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_REVNUMBER);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the total time spent in editing the document (or
|
||||
* <code>0</code>).</p>
|
||||
*
|
||||
* @return The total time spent in editing the document or 0 if the {@link
|
||||
* SummaryInformation} does not contain this information.
|
||||
* SummaryInformation} does not contain this information.
|
||||
*/
|
||||
public long getEditTime()
|
||||
{
|
||||
@ -177,8 +370,32 @@ public class SummaryInformation extends SpecialPropertySet
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's last printed time (or
|
||||
* <code>null</code>).</p>
|
||||
* <p>Sets the total time spent in editing the document.</p>
|
||||
*
|
||||
* @param time The time to set.
|
||||
*/
|
||||
public void setEditTime(final long time)
|
||||
{
|
||||
final Date d = Util.filetimeToDate(time);
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_EDITTIME, Variant.VT_FILETIME, d);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Remove the total time spent in editing the document.</p>
|
||||
*/
|
||||
public void removeEditTime()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_EDITTIME);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the last printed time (or <code>null</code>).</p>
|
||||
*
|
||||
* @return The last printed time or <code>null</code>
|
||||
*/
|
||||
@ -190,8 +407,32 @@ public class SummaryInformation extends SpecialPropertySet
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's creation time (or
|
||||
* <code>null</code>).</p>
|
||||
* <p>Sets the lastPrinted.</p>
|
||||
*
|
||||
* @param lastPrinted The lastPrinted to set.
|
||||
*/
|
||||
public void setLastPrinted(final Date lastPrinted)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_LASTPRINTED, Variant.VT_FILETIME,
|
||||
lastPrinted);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Removes the lastPrinted.</p>
|
||||
*/
|
||||
public void removeLastPrinted()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_LASTPRINTED);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the creation time (or <code>null</code>).</p>
|
||||
*
|
||||
* @return The creation time or <code>null</code>
|
||||
*/
|
||||
@ -203,8 +444,32 @@ public class SummaryInformation extends SpecialPropertySet
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's last save time (or
|
||||
* <code>null</code>).</p>
|
||||
* <p>Sets the creation time.</p>
|
||||
*
|
||||
* @param createDateTime The creation time to set.
|
||||
*/
|
||||
public void setCreateDateTime(final Date createDateTime)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_CREATE_DTM, Variant.VT_FILETIME,
|
||||
createDateTime);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Removes the creation time.</p>
|
||||
*/
|
||||
public void removeCreateDateTime()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_CREATE_DTM);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the last save time (or <code>null</code>).</p>
|
||||
*
|
||||
* @return The last save time or <code>null</code>
|
||||
*/
|
||||
@ -216,11 +481,37 @@ public class SummaryInformation extends SpecialPropertySet
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's page count or 0 if the {@link
|
||||
* SummaryInformation} does not contain a page count.</p>
|
||||
* <p>Sets the total time spent in editing the document.</p>
|
||||
*
|
||||
* @param time The time to set.
|
||||
*/
|
||||
public void setLastSaveDateTime(final Date time)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s
|
||||
.setProperty(PropertyIDMap.PID_LASTSAVE_DTM,
|
||||
Variant.VT_FILETIME, time);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Remove the total time spent in editing the document.</p>
|
||||
*/
|
||||
public void removeLastSaveDateTime()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_LASTSAVE_DTM);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the page count or 0 if the {@link SummaryInformation} does
|
||||
* not contain a page count.</p>
|
||||
*
|
||||
* @return The page count or 0 if the {@link SummaryInformation} does not
|
||||
* contain a page count.
|
||||
* contain a page count.
|
||||
*/
|
||||
public int getPageCount()
|
||||
{
|
||||
@ -230,8 +521,32 @@ public class SummaryInformation extends SpecialPropertySet
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's word count or 0 if the {@link
|
||||
* SummaryInformation} does not contain a word count.</p>
|
||||
* <p>Sets the page count.</p>
|
||||
*
|
||||
* @param pageCount The page count to set.
|
||||
*/
|
||||
public void setPageCount(final int pageCount)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_PAGECOUNT, pageCount);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Removes the page count.</p>
|
||||
*/
|
||||
public void removePageCount()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_PAGECOUNT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the word count or 0 if the {@link SummaryInformation} does
|
||||
* not contain a word count.</p>
|
||||
*
|
||||
* @return The word count or <code>null</code>
|
||||
*/
|
||||
@ -243,8 +558,32 @@ public class SummaryInformation extends SpecialPropertySet
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's character count or 0 if the {@link
|
||||
* SummaryInformation} does not contain a char count.</p>
|
||||
* <p>Sets the word count.</p>
|
||||
*
|
||||
* @param wordCount The word count to set.
|
||||
*/
|
||||
public void setWordCount(final int wordCount)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_WORDCOUNT, wordCount);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Removes the word count.</p>
|
||||
*/
|
||||
public void removeWordCount()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_WORDCOUNT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the character count or 0 if the {@link SummaryInformation}
|
||||
* does not contain a char count.</p>
|
||||
*
|
||||
* @return The character count or <code>null</code>
|
||||
*/
|
||||
@ -256,14 +595,38 @@ public class SummaryInformation extends SpecialPropertySet
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's thumbnail (or <code>null</code>)
|
||||
* <strong>when this method is implemented. Please note that the
|
||||
* return type is likely to change!</strong></p>
|
||||
* <p>Sets the character count.</p>
|
||||
*
|
||||
* <p><strong>Hint to developers:</strong> Drew Varner <Drew.Varner -at-
|
||||
* sc.edu> said that this is an image in WMF or Clipboard (BMP?) format.
|
||||
* However, we won't do any conversion into any image type but instead just
|
||||
* return a byte array.</p>
|
||||
* @param charCount The character count to set.
|
||||
*/
|
||||
public void setCharCount(final int charCount)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_CHARCOUNT, charCount);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Removes the character count.</p>
|
||||
*/
|
||||
public void removeCharCount()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_CHARCOUNT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the thumbnail (or <code>null</code>) <strong>when this
|
||||
* method is implemented. Please note that the return type is likely to
|
||||
* change!</strong></p>
|
||||
*
|
||||
* <p><strong>Hint to developers:</strong> Drew Varner <Drew.Varner
|
||||
* -at- sc.edu> said that this is an image in WMF or Clipboard (BMP?)
|
||||
* format. However, we won't do any conversion into any image type but
|
||||
* instead just return a byte array.</p>
|
||||
*
|
||||
* @return The thumbnail or <code>null</code>
|
||||
*/
|
||||
@ -275,8 +638,32 @@ public class SummaryInformation extends SpecialPropertySet
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the stream's application name (or
|
||||
* <code>null</code>).</p>
|
||||
* <p>Sets the thumbnail.</p>
|
||||
*
|
||||
* @param thumbnail The thumbnail to set.
|
||||
*/
|
||||
public void setThumbnail(final byte[] thumbnail)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_THUMBNAIL, /* FIXME: */
|
||||
Variant.VT_LPSTR, thumbnail);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Removes the thumbnail.</p>
|
||||
*/
|
||||
public void removeThumbnail()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_THUMBNAIL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the application name (or <code>null</code>).</p>
|
||||
*
|
||||
* @return The application name or <code>null</code>
|
||||
*/
|
||||
@ -288,32 +675,46 @@ public class SummaryInformation extends SpecialPropertySet
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns a security code which is one of the following
|
||||
* values:</p>
|
||||
* <p>Sets the application name.</p>
|
||||
*
|
||||
* @param applicationName The application name to set.
|
||||
*/
|
||||
public void setApplicationName(final String applicationName)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_APPNAME, applicationName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Removes the application name.</p>
|
||||
*/
|
||||
public void removeApplicationName()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_APPNAME);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns a security code which is one of the following values:</p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>
|
||||
* <p>0 if the {@link SummaryInformation} does not contain a
|
||||
* security field or if there is no security on the
|
||||
* document. Use {@link #wasNull} to distinguish between the
|
||||
* two cases!</p>
|
||||
* </li>
|
||||
*
|
||||
* <li>
|
||||
* <p>1 if the document is password protected</p>
|
||||
* </li>
|
||||
* <li><p>0 if the {@link SummaryInformation} does not contain a
|
||||
* security field or if there is no security on the document. Use
|
||||
* {@link PropertySet#wasNull()} to distinguish between the two
|
||||
* cases!</p></li>
|
||||
*
|
||||
* <li>
|
||||
* <p>2 if the document is read-only recommended</p>
|
||||
* </li>
|
||||
* <li><p>1 if the document is password protected</p></li>
|
||||
*
|
||||
* <li>
|
||||
* <p>4 if the document is read-only enforced</p>
|
||||
* </li>
|
||||
* <li><p>2 if the document is read-only recommended</p></li>
|
||||
*
|
||||
* <li>
|
||||
* <p>8 if the document is locked for annotations</p>
|
||||
* </li>
|
||||
* <li><p>4 if the document is read-only enforced</p></li>
|
||||
*
|
||||
* <li><p>8 if the document is locked for annotations</p></li>
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
@ -324,4 +725,28 @@ public class SummaryInformation extends SpecialPropertySet
|
||||
return getPropertyIntValue(PropertyIDMap.PID_SECURITY);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Sets the security code.</p>
|
||||
*
|
||||
* @param security The security code to set.
|
||||
*/
|
||||
public void setSecurity(final int security)
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.setProperty(PropertyIDMap.PID_SECURITY, security);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Removes the security code.</p>
|
||||
*/
|
||||
public void removeSecurity()
|
||||
{
|
||||
final MutableSection s = (MutableSection) getFirstSection();
|
||||
s.removeProperty(PropertyIDMap.PID_SECURITY);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
Copyright 2002-2006 Apache Software Foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -46,7 +45,7 @@ public class TypeWriter
|
||||
{
|
||||
final int length = LittleEndian.SHORT_SIZE;
|
||||
byte[] buffer = new byte[length];
|
||||
LittleEndian.putUShort(buffer, 0, n);
|
||||
LittleEndian.putShort(buffer, 0, n); // FIXME: unsigned
|
||||
out.write(buffer, 0, length);
|
||||
return length;
|
||||
}
|
||||
@ -74,6 +73,27 @@ public class TypeWriter
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Writes a eight-byte value to an output stream.</p>
|
||||
*
|
||||
* @param out The stream to write to.
|
||||
* @param n The value to write.
|
||||
* @exception IOException if an I/O error occurs
|
||||
* @return The number of bytes written to the output stream.
|
||||
*/
|
||||
public static int writeToStream(final OutputStream out, final long n)
|
||||
throws IOException
|
||||
{
|
||||
final int l = LittleEndian.LONG_SIZE;
|
||||
final byte[] buffer = new byte[l];
|
||||
LittleEndian.putLong(buffer, 0, n);
|
||||
out.write(buffer, 0, l);
|
||||
return l;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Writes an unsigned two-byte value to an output stream.</p>
|
||||
*
|
||||
@ -118,6 +138,7 @@ public class TypeWriter
|
||||
*
|
||||
* @param out The stream to write to
|
||||
* @param n The value to write
|
||||
* @return The number of bytes written
|
||||
* @exception IOException if an I/O error occurs
|
||||
*/
|
||||
public static int writeToStream(final OutputStream out, final ClassID n)
|
||||
@ -137,7 +158,10 @@ public class TypeWriter
|
||||
*
|
||||
* @param out The stream to write to
|
||||
* @param properties The array to write to the stream
|
||||
* @param codepage The codepage number to use for writing strings
|
||||
* @exception IOException if an I/O error occurs
|
||||
* @throws UnsupportedVariantTypeException if HPSF does not support some
|
||||
* variant type.
|
||||
*/
|
||||
public static void writeToStream(final OutputStream out,
|
||||
final Property[] properties,
|
||||
@ -152,7 +176,7 @@ public class TypeWriter
|
||||
* ID and offset into the stream. */
|
||||
for (int i = 0; i < properties.length; i++)
|
||||
{
|
||||
final Property p = (Property) properties[i];
|
||||
final Property p = properties[i];
|
||||
writeUIntToStream(out, p.getID());
|
||||
writeUIntToStream(out, p.getSize());
|
||||
}
|
||||
@ -160,7 +184,7 @@ public class TypeWriter
|
||||
/* Write the properties themselves. */
|
||||
for (int i = 0; i < properties.length; i++)
|
||||
{
|
||||
final Property p = (Property) properties[i];
|
||||
final Property p = properties[i];
|
||||
long type = p.getType();
|
||||
writeUIntToStream(out, type);
|
||||
VariantSupport.write(out, (int) type, p.getValue(), codepage);
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
|
@ -21,7 +21,7 @@ import org.apache.poi.util.HexDump;
|
||||
/**
|
||||
* <p>This exception is thrown if HPSF encounters a variant type that isn't
|
||||
* supported yet. Although a variant type is unsupported the value can still be
|
||||
* retrieved using the {@link #getValue} method.</p>
|
||||
* retrieved using the {@link VariantTypeException#getValue} method.</p>
|
||||
*
|
||||
* <p>Obviously this class should disappear some day.</p>
|
||||
*
|
||||
|
@ -1,6 +1,5 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
Copyright 2002-2006 Apache Software Foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -152,6 +151,21 @@ public class Util
|
||||
public static Date filetimeToDate(final int high, final int low)
|
||||
{
|
||||
final long filetime = ((long) high) << 32 | (low & 0xffffffffL);
|
||||
return filetimeToDate(filetime);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Converts a Windows FILETIME into a {@link Date}. The Windows
|
||||
* FILETIME structure holds a date and time associated with a
|
||||
* file. The structure identifies a 64-bit integer specifying the
|
||||
* number of 100-nanosecond intervals which have passed since
|
||||
* January 1, 1601.</p>
|
||||
*
|
||||
* @param filetime The filetime to convert.
|
||||
* @return The Windows FILETIME as a {@link Date}.
|
||||
*/
|
||||
public static Date filetimeToDate(final long filetime)
|
||||
{
|
||||
final long ms_since_16010101 = filetime / (1000 * 10);
|
||||
final long ms_since_19700101 = ms_since_16010101 - EPOCH_DIFF;
|
||||
return new Date(ms_since_19700101);
|
||||
@ -165,7 +179,8 @@ public class Util
|
||||
* @param date The date to be converted
|
||||
* @return The filetime
|
||||
*
|
||||
* @see #filetimeToDate
|
||||
* @see #filetimeToDate(long)
|
||||
* @see #filetimeToDate(int, int)
|
||||
*/
|
||||
public static long dateToFileTime(final Date date)
|
||||
{
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
Copyright 2002-2006 Apache Software Foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -157,16 +157,25 @@ public class VariantSupport extends Variant
|
||||
* Read a short. In Java it is represented as an
|
||||
* Integer object.
|
||||
*/
|
||||
value = new Integer(LittleEndian.getUShort(src, o1));
|
||||
value = new Integer(LittleEndian.getShort(src, o1));
|
||||
break;
|
||||
}
|
||||
case Variant.VT_I4:
|
||||
{
|
||||
/*
|
||||
* Read a word. In Java it is represented as a
|
||||
* Read a word. In Java it is represented as an
|
||||
* Integer object.
|
||||
*/
|
||||
value = new Integer(LittleEndian.getInt(src, o1));
|
||||
break;
|
||||
}
|
||||
case Variant.VT_I8:
|
||||
{
|
||||
/*
|
||||
* Read a double word. In Java it is represented as a
|
||||
* Long object.
|
||||
*/
|
||||
value = new Long(LittleEndian.getUInt(src, o1));
|
||||
value = new Long(LittleEndian.getLong(src, o1));
|
||||
break;
|
||||
}
|
||||
case Variant.VT_R8:
|
||||
@ -204,9 +213,9 @@ public class VariantSupport extends Variant
|
||||
last--;
|
||||
final int l = (int) (last - first + 1);
|
||||
value = codepage != -1 ?
|
||||
new String(src, (int) first, l,
|
||||
new String(src, first, l,
|
||||
codepageToEncoding(codepage)) :
|
||||
new String(src, (int) first, l);
|
||||
new String(src, first, l);
|
||||
break;
|
||||
}
|
||||
case Variant.VT_LPWSTR:
|
||||
@ -240,7 +249,7 @@ public class VariantSupport extends Variant
|
||||
{
|
||||
final byte[] v = new byte[l1];
|
||||
for (int i = 0; i < l1; i++)
|
||||
v[i] = src[(int) (o1 + i)];
|
||||
v[i] = src[(o1 + i)];
|
||||
value = v;
|
||||
break;
|
||||
}
|
||||
@ -263,7 +272,7 @@ public class VariantSupport extends Variant
|
||||
{
|
||||
final byte[] v = new byte[l1];
|
||||
for (int i = 0; i < l1; i++)
|
||||
v[i] = src[(int) (o1 + i)];
|
||||
v[i] = src[(o1 + i)];
|
||||
throw new ReadingNotSupportedException(type, v);
|
||||
}
|
||||
}
|
||||
@ -397,8 +406,8 @@ public class VariantSupport extends Variant
|
||||
char[] s = Util.pad4((String) value);
|
||||
for (int i = 0; i < s.length; i++)
|
||||
{
|
||||
final int high = (int) ((s[i] & 0x0000ff00) >> 8);
|
||||
final int low = (int) (s[i] & 0x000000ff);
|
||||
final int high = ((s[i] & 0x0000ff00) >> 8);
|
||||
final int low = (s[i] & 0x000000ff);
|
||||
final byte highb = (byte) high;
|
||||
final byte lowb = (byte) low;
|
||||
out.write(lowb);
|
||||
@ -431,8 +440,21 @@ public class VariantSupport extends Variant
|
||||
}
|
||||
case Variant.VT_I4:
|
||||
{
|
||||
if (!(value instanceof Integer))
|
||||
{
|
||||
throw new ClassCastException("Could not cast an object to "
|
||||
+ Integer.class.toString() + ": "
|
||||
+ value.getClass().toString() + ", "
|
||||
+ value.toString());
|
||||
}
|
||||
length += TypeWriter.writeToStream(out,
|
||||
((Long) value).intValue());
|
||||
((Integer) value).intValue());
|
||||
break;
|
||||
}
|
||||
case Variant.VT_I8:
|
||||
{
|
||||
TypeWriter.writeToStream(out, ((Long) value).longValue());
|
||||
length = LittleEndianConsts.LONG_SIZE;
|
||||
break;
|
||||
}
|
||||
case Variant.VT_R8:
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
@ -232,6 +231,11 @@ public class PropertyIDMap extends HashMap
|
||||
*/
|
||||
public static final int PID_LINKSDIRTY = 16;
|
||||
|
||||
/**
|
||||
* <p>The highest well-known property ID. Applications are free to use higher values for custom purposes.</p>
|
||||
*/
|
||||
public static final int PID_MAX = PID_LINKSDIRTY;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,5 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
Copyright 2002-2006 Apache Software Foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -53,16 +52,23 @@ public class SectionIDMap extends HashMap
|
||||
};
|
||||
|
||||
/**
|
||||
* <p>The DocumentSummaryInformation's first section's format
|
||||
* ID. The second section has a different format ID which is not
|
||||
* well-known.</p>
|
||||
* <p>The DocumentSummaryInformation's first and second sections' format
|
||||
* ID.</p>
|
||||
*/
|
||||
public static final byte[] DOCUMENT_SUMMARY_INFORMATION_ID = new byte[]
|
||||
public static final byte[][] DOCUMENT_SUMMARY_INFORMATION_ID = new byte[][]
|
||||
{
|
||||
(byte) 0xD5, (byte) 0xCD, (byte) 0xD5, (byte) 0x02,
|
||||
(byte) 0x2E, (byte) 0x9C, (byte) 0x10, (byte) 0x1B,
|
||||
(byte) 0x93, (byte) 0x97, (byte) 0x08, (byte) 0x00,
|
||||
(byte) 0x2B, (byte) 0x2C, (byte) 0xF9, (byte) 0xAE
|
||||
{
|
||||
(byte) 0xD5, (byte) 0xCD, (byte) 0xD5, (byte) 0x02,
|
||||
(byte) 0x2E, (byte) 0x9C, (byte) 0x10, (byte) 0x1B,
|
||||
(byte) 0x93, (byte) 0x97, (byte) 0x08, (byte) 0x00,
|
||||
(byte) 0x2B, (byte) 0x2C, (byte) 0xF9, (byte) 0xAE
|
||||
},
|
||||
{
|
||||
(byte) 0xD5, (byte) 0xCD, (byte) 0xD5, (byte) 0x05,
|
||||
(byte) 0x2E, (byte) 0x9C, (byte) 0x10, (byte) 0x1B,
|
||||
(byte) 0x93, (byte) 0x97, (byte) 0x08, (byte) 0x00,
|
||||
(byte) 0x2B, (byte) 0x2C, (byte) 0xF9, (byte) 0xAE
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -91,7 +97,7 @@ public class SectionIDMap extends HashMap
|
||||
final SectionIDMap m = new SectionIDMap();
|
||||
m.put(SUMMARY_INFORMATION_ID,
|
||||
PropertyIDMap.getSummaryInformationProperties());
|
||||
m.put(DOCUMENT_SUMMARY_INFORMATION_ID,
|
||||
m.put(DOCUMENT_SUMMARY_INFORMATION_ID[0],
|
||||
PropertyIDMap.getDocumentSummaryInformationProperties());
|
||||
defaultMap = m;
|
||||
}
|
||||
@ -116,8 +122,7 @@ public class SectionIDMap extends HashMap
|
||||
public static String getPIDString(final byte[] sectionFormatID,
|
||||
final long pid)
|
||||
{
|
||||
final PropertyIDMap m =
|
||||
(PropertyIDMap) getInstance().get(sectionFormatID);
|
||||
final PropertyIDMap m = getInstance().get(sectionFormatID);
|
||||
if (m == null)
|
||||
return UNDEFINED;
|
||||
else
|
||||
@ -178,7 +183,8 @@ public class SectionIDMap extends HashMap
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #put(byte[], PropertyIDMap)} instead!
|
||||
* @link #put(byte[], PropertyIDMap)
|
||||
*
|
||||
* @see #put(byte[], PropertyIDMap)
|
||||
*
|
||||
* @param key This parameter remains undocumented since the method is
|
||||
* deprecated.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ====================================================================
|
||||
Copyright 2003-2004 Apache Software Foundation
|
||||
Copyright 2003-2006 Apache Software Foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -64,9 +64,9 @@ public class LittleEndian
|
||||
short num = (short) getNumber(data, offset, SHORT_SIZE);
|
||||
int retNum;
|
||||
if (num < 0) {
|
||||
retNum = ((int) Short.MAX_VALUE + 1) * 2 + (int) num;
|
||||
retNum = (Short.MAX_VALUE + 1) * 2 + num;
|
||||
} else {
|
||||
retNum = (int) num;
|
||||
retNum = num;
|
||||
}
|
||||
return retNum;
|
||||
}
|
||||
@ -163,9 +163,9 @@ public class LittleEndian
|
||||
int num = (int) getNumber(data, offset, INT_SIZE);
|
||||
long retNum;
|
||||
if (num < 0) {
|
||||
retNum = ((long) Integer.MAX_VALUE + 1) * 2 + (long) num;
|
||||
retNum = ((long) Integer.MAX_VALUE + 1) * 2 + num;
|
||||
} else {
|
||||
retNum = (int) num;
|
||||
retNum = num;
|
||||
}
|
||||
return retNum;
|
||||
}
|
||||
@ -522,7 +522,7 @@ public class LittleEndian
|
||||
*@return Description of the Return Value
|
||||
*/
|
||||
public static int ubyteToInt(byte b) {
|
||||
return ((b & 0x80) == 0 ? (int) b : (int) (b & (byte) 0x7f) + 0x80);
|
||||
return ((b & 0x80) == 0 ? (int) b : (b & (byte) 0x7f) + 0x80);
|
||||
}
|
||||
|
||||
|
||||
@ -566,5 +566,22 @@ public class LittleEndian
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Gets an unsigned int value (8 bytes) from a byte array.</p>
|
||||
*
|
||||
* @param data the byte array
|
||||
* @param offset a starting offset into the byte array
|
||||
* @return the unsigned int (32-bit) value in a long
|
||||
*/
|
||||
public static long getULong(final byte[] data, final int offset)
|
||||
{
|
||||
int num = (int) getNumber(data, offset, LONG_SIZE);
|
||||
long retNum;
|
||||
if (num < 0)
|
||||
retNum = ((long) Integer.MAX_VALUE + 1) * 2 + num;
|
||||
else
|
||||
retNum = num;
|
||||
return retNum;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,82 @@
|
||||
/* ====================================================================
|
||||
Copyright 2002-2006 Apache Software Foundation
|
||||
|
||||
Licensed 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.hpsf.basic;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* <p>Processes a test method for all OLE2 files in the HPSF test data
|
||||
* directory. Well, this class does not check whether a file is an OLE2 file but
|
||||
* rather whether its name begins with "Test".</p>
|
||||
*
|
||||
* @author Rainer Klute <a
|
||||
* href="mailto:klute@rainer-klute.de"><klute@rainer-klute.de></a>
|
||||
* @since 2006-02-11
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AllDataFilesTester
|
||||
{
|
||||
|
||||
/**
|
||||
* <p>Interface specifying how to run a test on a single file.</p>
|
||||
*
|
||||
* @author Rainer Klute <a
|
||||
* href="mailto:klute@rainer-klute.de"><klute@rainer-klute.de></a>
|
||||
* @since 2006-02-11
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface TestTask
|
||||
{
|
||||
/**
|
||||
* <p>Executes a test on a single file.</p>
|
||||
*
|
||||
* @param file the file
|
||||
* @throws Throwable if the method throws anything.
|
||||
*/
|
||||
void runTest(File file) throws Throwable;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Tests the simplified custom properties.</p>
|
||||
*
|
||||
* @param task the task to execute
|
||||
* @throws Throwable
|
||||
*/
|
||||
public void runTests(final TestTask task) throws Throwable
|
||||
{
|
||||
final String dataDirName = System.getProperty("HPSF.testdata.path");
|
||||
final File dataDir = new File(dataDirName);
|
||||
final File[] docs = dataDir.listFiles(new FileFilter()
|
||||
{
|
||||
public boolean accept(final File file)
|
||||
{
|
||||
return file.isFile() && file.getName().startsWith("Test");
|
||||
}});
|
||||
for (int i = 0; i < docs.length; i++)
|
||||
{
|
||||
final File doc = docs[i];
|
||||
final Logger logger = Logger.getLogger(getClass().getName());
|
||||
logger.info("Processing file \" " + doc.toString() + "\".");
|
||||
|
||||
/* Execute the test task. */
|
||||
task.runTest(doc);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -112,10 +112,8 @@ public class TestBasic extends TestCase
|
||||
/**
|
||||
* <p>Checks the names of the files in the POI filesystem. They
|
||||
* are expected to be in a certain order.</p>
|
||||
*
|
||||
* @exception IOException if an I/O exception occurs
|
||||
*/
|
||||
public void testReadFiles() throws IOException
|
||||
public void testReadFiles()
|
||||
{
|
||||
String[] expected = POI_FILES;
|
||||
for (int i = 0; i < expected.length; i++)
|
||||
@ -166,7 +164,7 @@ public class TestBasic extends TestCase
|
||||
o = ex;
|
||||
}
|
||||
in.close();
|
||||
Assert.assertEquals(o.getClass(), expected[i]);
|
||||
Assert.assertEquals(expected[i], o.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
@ -223,7 +221,7 @@ public class TestBasic extends TestCase
|
||||
Assert.assertNotNull(s.getProperties());
|
||||
Assert.assertEquals(17, s.getPropertyCount());
|
||||
Assert.assertEquals("Titel", s.getProperty(2));
|
||||
Assert.assertEquals(1764, s.getSize());
|
||||
Assert.assertEquals(1748, s.getSize());
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
@ -22,6 +21,9 @@ import junit.framework.Assert;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hpsf.ClassID;
|
||||
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
||||
import org.apache.poi.hpsf.PropertySet;
|
||||
import org.apache.poi.hpsf.SummaryInformation;
|
||||
|
||||
/**
|
||||
* <p>Tests ClassID structure.</p>
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
@ -27,16 +26,18 @@ import java.io.UnsupportedEncodingException;
|
||||
import junit.framework.Assert;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
||||
import org.apache.poi.hpsf.HPSFException;
|
||||
import org.apache.poi.hpsf.MarkUnsupportedException;
|
||||
import org.apache.poi.hpsf.NoPropertySetStreamException;
|
||||
import org.apache.poi.hpsf.PropertySet;
|
||||
import org.apache.poi.hpsf.PropertySetFactory;
|
||||
import org.apache.poi.hpsf.SummaryInformation;
|
||||
import org.apache.poi.hpsf.Variant;
|
||||
|
||||
/**
|
||||
* <p>Test case for OLE2 files with empty properties. An empty property's type
|
||||
* is {@link Variant.VT_EMPTY}.</p>
|
||||
* is {@link Variant#VT_EMPTY}.</p>
|
||||
*
|
||||
* @author Rainer Klute <a
|
||||
* href="mailto:klute@rainer-klute.de"><klute@rainer-klute.de></a>
|
||||
@ -96,10 +97,8 @@ public class TestEmptyProperties extends TestCase
|
||||
/**
|
||||
* <p>Checks the names of the files in the POI filesystem. They
|
||||
* are expected to be in a certain order.</p>
|
||||
*
|
||||
* @exception IOException if an I/O exception occurs
|
||||
*/
|
||||
public void testReadFiles() throws IOException
|
||||
public void testReadFiles()
|
||||
{
|
||||
String[] expected = POI_FILES;
|
||||
for (int i = 0; i < expected.length; i++)
|
||||
|
827
src/testcases/org/apache/poi/hpsf/basic/TestMetaDataIPI.java
Normal file
827
src/testcases/org/apache/poi/hpsf/basic/TestMetaDataIPI.java
Normal file
@ -0,0 +1,827 @@
|
||||
/* ====================================================================
|
||||
Copyright 2002-2006 Apache Software Foundation
|
||||
|
||||
Licensed 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.hpsf.basic;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Date;
|
||||
import java.util.Random;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hpsf.CustomProperties;
|
||||
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
||||
import org.apache.poi.hpsf.MarkUnsupportedException;
|
||||
import org.apache.poi.hpsf.NoPropertySetStreamException;
|
||||
import org.apache.poi.hpsf.PropertySet;
|
||||
import org.apache.poi.hpsf.PropertySetFactory;
|
||||
import org.apache.poi.hpsf.SummaryInformation;
|
||||
import org.apache.poi.hpsf.UnexpectedPropertySetTypeException;
|
||||
import org.apache.poi.hpsf.WritingNotSupportedException;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryEntry;
|
||||
import org.apache.poi.poifs.filesystem.DocumentEntry;
|
||||
import org.apache.poi.poifs.filesystem.DocumentInputStream;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
/**
|
||||
* Basing on: src/examples/src/org/apache/poi/hpsf/examples/ModifyDocumentSummaryInformation.java
|
||||
* This class tests reading and writing of meta data. No actual document is created. All information
|
||||
* is stored in a virtal document in a ByteArrayOutputStream
|
||||
* @author Matthias Günter
|
||||
* @since 2006-03-03
|
||||
* @version $Id: TestEmptyProperties.java 353563 2004-06-22 16:16:33Z klute $
|
||||
*/
|
||||
public class TestMetaDataIPI extends TestCase{
|
||||
|
||||
private ByteArrayOutputStream bout= null; //our store
|
||||
private POIFSFileSystem poifs=null;
|
||||
DirectoryEntry dir = null;
|
||||
DocumentSummaryInformation dsi=null;
|
||||
SummaryInformation si=null;
|
||||
|
||||
/**
|
||||
* Standard constructor
|
||||
* @param s
|
||||
*/
|
||||
public TestMetaDataIPI(String s ){
|
||||
super(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup is used to get the document ready. Gets the DocumentSummaryInformation and the
|
||||
* SummaryInformation to reasonable values
|
||||
*/
|
||||
public void setUp(){
|
||||
bout=new ByteArrayOutputStream();
|
||||
poifs= new POIFSFileSystem();
|
||||
dir = poifs.getRoot();
|
||||
dsi=null;
|
||||
try
|
||||
{
|
||||
DocumentEntry dsiEntry = (DocumentEntry)
|
||||
dir.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
||||
DocumentInputStream dis = new DocumentInputStream(dsiEntry);
|
||||
PropertySet ps = new PropertySet(dis);
|
||||
dis.close();
|
||||
dsi = new DocumentSummaryInformation(ps);
|
||||
|
||||
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
/* There is no document summary information yet. We have to create a
|
||||
* new one. */
|
||||
dsi = PropertySetFactory.newDocumentSummaryInformation();
|
||||
assertNotNull(dsi);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
} catch (NoPropertySetStreamException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
} catch (MarkUnsupportedException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
} catch (UnexpectedPropertySetTypeException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
}
|
||||
assertNotNull(dsi);
|
||||
try
|
||||
{
|
||||
DocumentEntry dsiEntry = (DocumentEntry)
|
||||
dir.getEntry(SummaryInformation.DEFAULT_STREAM_NAME);
|
||||
DocumentInputStream dis = new DocumentInputStream(dsiEntry);
|
||||
PropertySet ps = new PropertySet(dis);
|
||||
dis.close();
|
||||
si = new SummaryInformation(ps);
|
||||
|
||||
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
/* There is no document summary information yet. We have to create a
|
||||
* new one. */
|
||||
si = PropertySetFactory.newSummaryInformation();
|
||||
assertNotNull(si);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
} catch (NoPropertySetStreamException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
} catch (MarkUnsupportedException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
} catch (UnexpectedPropertySetTypeException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
}
|
||||
assertNotNull(dsi);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Setting a lot of things to null.
|
||||
*/
|
||||
public void tearDown(){
|
||||
bout=null;
|
||||
poifs=null;
|
||||
dir=null;
|
||||
dsi=null;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Closes the ByteArrayOutputStream and reads it into a ByteArrayInputStream.
|
||||
* When finished writing information this method is used in the tests to
|
||||
* start reading from the created document and then the see if the results match.
|
||||
*
|
||||
*/
|
||||
public void closeAndReOpen(){
|
||||
|
||||
try {
|
||||
dsi.write(dir, DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
||||
si.write(dir,SummaryInformation.DEFAULT_STREAM_NAME);
|
||||
} catch (WritingNotSupportedException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
}
|
||||
|
||||
si=null;
|
||||
dsi=null;
|
||||
try {
|
||||
|
||||
poifs.writeFilesystem(bout);
|
||||
bout.flush();
|
||||
|
||||
} catch (IOException e) {
|
||||
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
}
|
||||
|
||||
InputStream is=new ByteArrayInputStream(bout.toByteArray());
|
||||
assertNotNull(is);
|
||||
POIFSFileSystem poifs=null;
|
||||
try {
|
||||
poifs = new POIFSFileSystem(is);
|
||||
} catch (IOException e) {
|
||||
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
}
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
}
|
||||
assertNotNull(poifs);
|
||||
/* Read the document summary information. */
|
||||
DirectoryEntry dir = poifs.getRoot();
|
||||
|
||||
try
|
||||
{
|
||||
DocumentEntry dsiEntry = (DocumentEntry)
|
||||
dir.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
||||
DocumentInputStream dis = new DocumentInputStream(dsiEntry);
|
||||
PropertySet ps = new PropertySet(dis);
|
||||
dis.close();
|
||||
dsi = new DocumentSummaryInformation(ps);
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
fail();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
} catch (NoPropertySetStreamException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
} catch (MarkUnsupportedException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
} catch (UnexpectedPropertySetTypeException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
}
|
||||
try
|
||||
{
|
||||
DocumentEntry dsiEntry = (DocumentEntry)
|
||||
dir.getEntry(SummaryInformation.DEFAULT_STREAM_NAME);
|
||||
DocumentInputStream dis = new DocumentInputStream(dsiEntry);
|
||||
PropertySet ps = new PropertySet(dis);
|
||||
dis.close();
|
||||
si = new SummaryInformation(ps);
|
||||
|
||||
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
/* There is no document summary information yet. We have to create a
|
||||
* new one. */
|
||||
si = PropertySetFactory.newSummaryInformation();
|
||||
assertNotNull(si);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
} catch (NoPropertySetStreamException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
} catch (MarkUnsupportedException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
} catch (UnexpectedPropertySetTypeException e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the most important information in DocumentSummaryInformation and Summary Information and rereads it
|
||||
*
|
||||
*/
|
||||
public void testOne(){
|
||||
|
||||
//DocumentSummaryInformation
|
||||
dsi.setCompany("xxxCompanyxxx");
|
||||
dsi.setManager("xxxManagerxxx");
|
||||
dsi.setCategory("xxxCategoryxxx");
|
||||
|
||||
//SummaryInformation
|
||||
si.setTitle("xxxTitlexxx");
|
||||
si.setAuthor("xxxAuthorxxx");
|
||||
si.setComments("xxxCommentsxxx");
|
||||
si.setKeywords("xxxKeyWordsxxx");
|
||||
si.setSubject("xxxSubjectxxx");
|
||||
|
||||
//Custom Properties (in DocumentSummaryInformation
|
||||
CustomProperties customProperties = dsi.getCustomProperties();
|
||||
if (customProperties == null){
|
||||
customProperties = new CustomProperties();
|
||||
}
|
||||
|
||||
/* Insert some custom properties into the container. */
|
||||
customProperties.put("Key1", "Value1");
|
||||
customProperties.put("Schlüssel2", "Wert2");
|
||||
customProperties.put("Sample Integer", new Integer(12345));
|
||||
customProperties.put("Sample Boolean", new Boolean(true));
|
||||
Date date=new Date();
|
||||
customProperties.put("Sample Date", date);
|
||||
customProperties.put("Sample Double", new Double(-1.0001));
|
||||
customProperties.put("Sample Negative Integer", new Integer(-100000));
|
||||
|
||||
dsi.setCustomProperties(customProperties);
|
||||
|
||||
//start reading
|
||||
closeAndReOpen();
|
||||
|
||||
//testing
|
||||
assertNotNull(dsi);
|
||||
assertNotNull(si);
|
||||
|
||||
assertEquals("Category","xxxCategoryxxx",dsi.getCategory());
|
||||
assertEquals("Company","xxxCompanyxxx",dsi.getCompany());
|
||||
assertEquals("Manager","xxxManagerxxx",dsi.getManager());
|
||||
|
||||
assertEquals("","xxxAuthorxxx",si.getAuthor());
|
||||
assertEquals("","xxxTitlexxx",si.getTitle());
|
||||
assertEquals("","xxxCommentsxxx",si.getComments());
|
||||
assertEquals("","xxxKeyWordsxxx",si.getKeywords());
|
||||
assertEquals("","xxxSubjectxxx",si.getSubject());
|
||||
|
||||
|
||||
/* Read the custom properties. If there are no custom properties yet,
|
||||
* the application has to create a new CustomProperties object. It will
|
||||
* serve as a container for custom properties. */
|
||||
customProperties = dsi.getCustomProperties();
|
||||
if (customProperties == null){
|
||||
fail();
|
||||
}
|
||||
|
||||
/* Insert some custom properties into the container. */
|
||||
String a1=(String) customProperties.get("Key1");
|
||||
assertEquals("Key1","Value1",a1);
|
||||
String a2=(String) customProperties.get("Schlüssel2");
|
||||
assertEquals("Schlüssel2","Wert2",a2);
|
||||
Integer a3=(Integer) customProperties.get("Sample Integer");
|
||||
assertEquals("Sample Number",new Integer(12345),a3);
|
||||
Boolean a4=(Boolean) customProperties.get("Sample Boolean");
|
||||
assertEquals("Sample Boolean",new Boolean(true),a4);
|
||||
Date a5=(Date) customProperties.get("Sample Date");
|
||||
assertEquals("Custom Date:",date,a5);
|
||||
|
||||
Double a6=(Double) customProperties.get("Sample Double");
|
||||
assertEquals("Custom Float",new Double(-1.0001),a6);
|
||||
|
||||
Integer a7=(Integer) customProperties.get("Sample Negative Integer");
|
||||
assertEquals("Neg", new Integer(-100000),a7);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* multiplies a string
|
||||
* @param s Input String
|
||||
* @return the multiplied String
|
||||
*/
|
||||
public String elongate(String s){
|
||||
StringBuffer sb=new StringBuffer();
|
||||
for (int i=0;i<10000;i++){
|
||||
sb.append(s);
|
||||
sb.append(" ");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Test very long input in each of the fields (approx 30-60KB each)
|
||||
*
|
||||
*/
|
||||
public void testTwo(){
|
||||
|
||||
String company=elongate("company");
|
||||
String manager=elongate("manager");
|
||||
String category=elongate("category");
|
||||
String title=elongate("title");
|
||||
String author=elongate("author");
|
||||
String comments=elongate("comments");
|
||||
String keywords=elongate("keywords");
|
||||
String subject=elongate("subject");
|
||||
String p1=elongate("p1");
|
||||
String p2=elongate("p2");
|
||||
String k1=elongate("k1");
|
||||
String k2=elongate("k2");
|
||||
|
||||
dsi.setCompany(company);
|
||||
dsi.setManager(manager);
|
||||
dsi.setCategory(category);
|
||||
|
||||
si.setTitle(title);
|
||||
si.setAuthor(author);
|
||||
si.setComments(comments);
|
||||
si.setKeywords(keywords);
|
||||
si.setSubject(subject);
|
||||
CustomProperties customProperties = dsi.getCustomProperties();
|
||||
if (customProperties == null){
|
||||
customProperties = new CustomProperties();
|
||||
}
|
||||
|
||||
/* Insert some custom properties into the container. */
|
||||
customProperties.put(k1, p1);
|
||||
customProperties.put(k2, p2);
|
||||
customProperties.put("Sample Number", new Integer(12345));
|
||||
customProperties.put("Sample Boolean", new Boolean(true));
|
||||
Date date=new Date();
|
||||
customProperties.put("Sample Date", date);
|
||||
|
||||
dsi.setCustomProperties(customProperties);
|
||||
|
||||
|
||||
closeAndReOpen();
|
||||
|
||||
assertNotNull(dsi);
|
||||
assertNotNull(si);
|
||||
/* Change the category to "POI example". Any former category value will
|
||||
* be lost. If there has been no category yet, it will be created. */
|
||||
assertEquals("Category",category,dsi.getCategory());
|
||||
assertEquals("Company",company,dsi.getCompany());
|
||||
assertEquals("Manager",manager,dsi.getManager());
|
||||
|
||||
assertEquals("",author,si.getAuthor());
|
||||
assertEquals("",title,si.getTitle());
|
||||
assertEquals("",comments,si.getComments());
|
||||
assertEquals("",keywords,si.getKeywords());
|
||||
assertEquals("",subject,si.getSubject());
|
||||
|
||||
|
||||
/* Read the custom properties. If there are no custom properties
|
||||
* yet, the application has to create a new CustomProperties object.
|
||||
* It will serve as a container for custom properties. */
|
||||
customProperties = dsi.getCustomProperties();
|
||||
if (customProperties == null){
|
||||
fail();
|
||||
}
|
||||
|
||||
/* Insert some custom properties into the container. */
|
||||
String a1=(String) customProperties.get(k1);
|
||||
assertEquals("Key1",p1,a1);
|
||||
String a2=(String) customProperties.get(k2);
|
||||
assertEquals("Schlüssel2",p2,a2);
|
||||
Integer a3=(Integer) customProperties.get("Sample Number");
|
||||
assertEquals("Sample Number",new Integer(12345),a3);
|
||||
Boolean a4=(Boolean) customProperties.get("Sample Boolean");
|
||||
assertEquals("Sample Boolean",new Boolean(true),a4);
|
||||
Date a5=(Date) customProperties.get("Sample Date");
|
||||
assertEquals("Custom Date:",date,a5);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* adds strange characters to the string
|
||||
* @param s Input String
|
||||
* @return the multiplied String
|
||||
*/
|
||||
public String strangize(String s){
|
||||
StringBuffer sb=new StringBuffer();
|
||||
String[] umlaute= {"ä","ü","ö","Ü","$","Ö","Ü","É","Ö","@","ç","&"};
|
||||
char j=0;
|
||||
Random rand=new Random();
|
||||
for (int i=0;i<5;i++){
|
||||
sb.append(s);
|
||||
sb.append(" ");
|
||||
j=(char) rand.nextInt(220);
|
||||
j+=33;
|
||||
// System.out.println(j);
|
||||
sb.append(">");
|
||||
sb.append(new Character(j));
|
||||
sb.append("=");
|
||||
sb.append(umlaute[rand.nextInt(umlaute.length)]);
|
||||
sb.append("<");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests with strange characters in keys and data (Umlaute etc.)
|
||||
*
|
||||
*/
|
||||
public void testThree(){
|
||||
|
||||
String company=strangize("company");
|
||||
String manager=strangize("manager");
|
||||
String category=strangize("category");
|
||||
String title=strangize("title");
|
||||
String author=strangize("author");
|
||||
String comments=strangize("comments");
|
||||
String keywords=strangize("keywords");
|
||||
String subject=strangize("subject");
|
||||
String p1=strangize("p1");
|
||||
String p2=strangize("p2");
|
||||
String k1=strangize("k1");
|
||||
String k2=strangize("k2");
|
||||
|
||||
dsi.setCompany(company);
|
||||
dsi.setManager(manager);
|
||||
dsi.setCategory(category);
|
||||
|
||||
si.setTitle(title);
|
||||
si.setAuthor(author);
|
||||
si.setComments(comments);
|
||||
si.setKeywords(keywords);
|
||||
si.setSubject(subject);
|
||||
CustomProperties customProperties = dsi.getCustomProperties();
|
||||
if (customProperties == null){
|
||||
customProperties = new CustomProperties();
|
||||
}
|
||||
|
||||
/* Insert some custom properties into the container. */
|
||||
customProperties.put(k1, p1);
|
||||
customProperties.put(k2, p2);
|
||||
customProperties.put("Sample Number", new Integer(12345));
|
||||
customProperties.put("Sample Boolean", new Boolean(false));
|
||||
Date date=new Date(0);
|
||||
customProperties.put("Sample Date", date);
|
||||
|
||||
dsi.setCustomProperties(customProperties);
|
||||
|
||||
|
||||
closeAndReOpen();
|
||||
|
||||
assertNotNull(dsi);
|
||||
assertNotNull(si);
|
||||
/* Change the category to "POI example". Any former category value will
|
||||
* be lost. If there has been no category yet, it will be created. */
|
||||
assertEquals("Category",category,dsi.getCategory());
|
||||
assertEquals("Company",company,dsi.getCompany());
|
||||
assertEquals("Manager",manager,dsi.getManager());
|
||||
|
||||
assertEquals("",author,si.getAuthor());
|
||||
assertEquals("",title,si.getTitle());
|
||||
assertEquals("",comments,si.getComments());
|
||||
assertEquals("",keywords,si.getKeywords());
|
||||
assertEquals("",subject,si.getSubject());
|
||||
|
||||
|
||||
/* Read the custom properties. If there are no custom properties yet,
|
||||
* the application has to create a new CustomProperties object. It will
|
||||
* serve as a container for custom properties. */
|
||||
customProperties = dsi.getCustomProperties();
|
||||
if (customProperties == null){
|
||||
fail();
|
||||
}
|
||||
|
||||
/* Insert some custom properties into the container. */
|
||||
// System.out.println(k1);
|
||||
String a1=(String) customProperties.get(k1);
|
||||
assertEquals("Key1",p1,a1);
|
||||
String a2=(String) customProperties.get(k2);
|
||||
assertEquals("Schlüssel2",p2,a2);
|
||||
Integer a3=(Integer) customProperties.get("Sample Number");
|
||||
assertEquals("Sample Number",new Integer(12345),a3);
|
||||
Boolean a4=(Boolean) customProperties.get("Sample Boolean");
|
||||
assertEquals("Sample Boolean",new Boolean(false),a4);
|
||||
Date a5=(Date) customProperties.get("Sample Date");
|
||||
assertEquals("Custom Date:",date,a5);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterative testing: writing, reading etc.
|
||||
*
|
||||
*/
|
||||
public void testFour(){
|
||||
for (int i=1;i<100;i++){
|
||||
setUp();
|
||||
testThree();
|
||||
tearDown();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* adds strange characters to the string with the adding of unicode characters
|
||||
* @param s Input String
|
||||
* @return the multiplied String
|
||||
*/
|
||||
public String strangizeU(String s){
|
||||
|
||||
StringBuffer sb=new StringBuffer();
|
||||
String[] umlaute= {"ä","ü","ö","Ü","$","Ö","Ü","É","Ö","@","ç","&"};
|
||||
char j=0;
|
||||
Random rand=new Random();
|
||||
for (int i=0;i<5;i++){
|
||||
sb.append(s);
|
||||
sb.append(" ");
|
||||
j=(char) rand.nextInt(220);
|
||||
j+=33;
|
||||
// System.out.println(j);
|
||||
sb.append(">");
|
||||
sb.append(new Character(j));
|
||||
sb.append("=");
|
||||
sb.append(umlaute[rand.nextInt(umlaute.length)]);
|
||||
sb.append("<");
|
||||
}
|
||||
sb.append("äöü\uD840\uDC00");
|
||||
return sb.toString();
|
||||
}
|
||||
/**
|
||||
* Unicode test
|
||||
*
|
||||
*/
|
||||
public void testUnicode(){
|
||||
String company=strangizeU("company");
|
||||
String manager=strangizeU("manager");
|
||||
String category=strangizeU("category");
|
||||
String title=strangizeU("title");
|
||||
String author=strangizeU("author");
|
||||
String comments=strangizeU("comments");
|
||||
String keywords=strangizeU("keywords");
|
||||
String subject=strangizeU("subject");
|
||||
String p1=strangizeU("p1");
|
||||
String p2=strangizeU("p2");
|
||||
String k1=strangizeU("k1");
|
||||
String k2=strangizeU("k2");
|
||||
|
||||
dsi.setCompany(company);
|
||||
dsi.setManager(manager);
|
||||
dsi.setCategory(category);
|
||||
|
||||
si.setTitle(title);
|
||||
si.setAuthor(author);
|
||||
si.setComments(comments);
|
||||
si.setKeywords(keywords);
|
||||
si.setSubject(subject);
|
||||
CustomProperties customProperties = dsi.getCustomProperties();
|
||||
if (customProperties == null){
|
||||
customProperties = new CustomProperties();
|
||||
}
|
||||
|
||||
/* Insert some custom properties into the container. */
|
||||
customProperties.put(k1, p1);
|
||||
customProperties.put(k2, p2);
|
||||
customProperties.put("Sample Number", new Integer(12345));
|
||||
customProperties.put("Sample Boolean", new Boolean(true));
|
||||
Date date=new Date();
|
||||
customProperties.put("Sample Date", date);
|
||||
|
||||
dsi.setCustomProperties(customProperties);
|
||||
|
||||
|
||||
closeAndReOpen();
|
||||
|
||||
assertNotNull(dsi);
|
||||
assertNotNull(si);
|
||||
/* Change the category to "POI example". Any former category value will
|
||||
* be lost. If there has been no category yet, it will be created. */
|
||||
assertEquals("Category",category,dsi.getCategory());
|
||||
assertEquals("Company",company,dsi.getCompany());
|
||||
assertEquals("Manager",manager,dsi.getManager());
|
||||
|
||||
assertEquals("",author,si.getAuthor());
|
||||
assertEquals("",title,si.getTitle());
|
||||
assertEquals("",comments,si.getComments());
|
||||
assertEquals("",keywords,si.getKeywords());
|
||||
assertEquals("",subject,si.getSubject());
|
||||
|
||||
|
||||
/* Read the custom properties. If there are no custom properties yet,
|
||||
* the application has to create a new CustomProperties object. It will
|
||||
* serve as a container for custom properties. */
|
||||
customProperties = dsi.getCustomProperties();
|
||||
if (customProperties == null){
|
||||
fail();
|
||||
}
|
||||
|
||||
/* Insert some custom properties into the container. */
|
||||
// System.out.println(k1);
|
||||
String a1=(String) customProperties.get(k1);
|
||||
assertEquals("Key1",p1,a1);
|
||||
String a2=(String) customProperties.get(k2);
|
||||
assertEquals("Schlüssel2",p2,a2);
|
||||
Integer a3=(Integer) customProperties.get("Sample Number");
|
||||
assertEquals("Sample Number",new Integer(12345),a3);
|
||||
Boolean a4=(Boolean) customProperties.get("Sample Boolean");
|
||||
assertEquals("Sample Boolean",new Boolean(true),a4);
|
||||
Date a5=(Date) customProperties.get("Sample Date");
|
||||
assertEquals("Custom Date:",date,a5);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Iterative testing of the unicode test
|
||||
*
|
||||
*/
|
||||
public void testSix(){
|
||||
for (int i=1;i<100;i++){
|
||||
setUp();
|
||||
testUnicode();
|
||||
tearDown();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests conversion in custom fields and errors
|
||||
*
|
||||
*/
|
||||
public void testConvAndExistance(){
|
||||
|
||||
|
||||
CustomProperties customProperties = dsi.getCustomProperties();
|
||||
if (customProperties == null){
|
||||
customProperties = new CustomProperties();
|
||||
}
|
||||
|
||||
/* Insert some custom properties into the container. */
|
||||
customProperties.put("int", new Integer(12345));
|
||||
customProperties.put("negint", new Integer(-12345));
|
||||
customProperties.put("long", new Long(12345));
|
||||
customProperties.put("neglong", new Long(-12345));
|
||||
customProperties.put("boolean", new Boolean(true));
|
||||
customProperties.put("string", "a String");
|
||||
//customProperties.put("float", new Float(12345.0)); is not valid
|
||||
//customProperties.put("negfloat", new Float(-12345.1)); is not valid
|
||||
customProperties.put("double", new Double(12345.2));
|
||||
customProperties.put("negdouble", new Double(-12345.3));
|
||||
//customProperties.put("char", new Character('a')); is not valid
|
||||
|
||||
Date date=new Date();
|
||||
customProperties.put("date", date);
|
||||
|
||||
dsi.setCustomProperties(customProperties);
|
||||
|
||||
|
||||
closeAndReOpen();
|
||||
|
||||
assertNotNull(dsi);
|
||||
assertNotNull(si);
|
||||
/* Change the category to "POI example". Any former category value will
|
||||
* be lost. If there has been no category yet, it will be created. */
|
||||
assertNull(dsi.getCategory());
|
||||
assertNull(dsi.getCompany());
|
||||
assertNull(dsi.getManager());
|
||||
|
||||
assertNull(si.getAuthor());
|
||||
assertNull(si.getTitle());
|
||||
assertNull(si.getComments());
|
||||
assertNull(si.getKeywords());
|
||||
assertNull(si.getSubject());
|
||||
|
||||
|
||||
/* Read the custom properties. If there are no custom properties
|
||||
* yet, the application has to create a new CustomProperties object.
|
||||
* It will serve as a container for custom properties. */
|
||||
customProperties = dsi.getCustomProperties();
|
||||
if (customProperties == null){
|
||||
fail();
|
||||
}
|
||||
|
||||
/* Insert some custom properties into the container. */
|
||||
|
||||
Integer a3=(Integer) customProperties.get("int");
|
||||
assertEquals("int",new Integer(12345),a3);
|
||||
|
||||
a3=(Integer) customProperties.get("negint");
|
||||
assertEquals("negint",new Integer(-12345),a3);
|
||||
|
||||
Long al=(Long) customProperties.get("neglong");
|
||||
assertEquals("neglong",new Long(-12345),al);
|
||||
|
||||
al=(Long) customProperties.get("long");
|
||||
assertEquals("long",new Long(12345),al);
|
||||
|
||||
Boolean a4=(Boolean) customProperties.get("boolean");
|
||||
assertEquals("boolean",new Boolean(true),a4);
|
||||
|
||||
Date a5=(Date) customProperties.get("date");
|
||||
assertEquals("Custom Date:",date,a5);
|
||||
|
||||
Double d=(Double) customProperties.get("double");
|
||||
assertEquals("int",new Double(12345.2),d);
|
||||
|
||||
d=(Double) customProperties.get("negdouble");
|
||||
assertEquals("string",new Double(-12345.3),d);
|
||||
|
||||
String s=(String) customProperties.get("string");
|
||||
assertEquals("sring","a String",s);
|
||||
|
||||
Object o=null;
|
||||
|
||||
o=customProperties.get("string");
|
||||
if (!(o instanceof String)){
|
||||
fail();
|
||||
}
|
||||
o=customProperties.get("boolean");
|
||||
if (!(o instanceof Boolean)){
|
||||
fail();
|
||||
}
|
||||
|
||||
o=customProperties.get("int");
|
||||
if (!(o instanceof Integer)){
|
||||
fail();
|
||||
}
|
||||
o=customProperties.get("negint");
|
||||
if (!(o instanceof Integer)){
|
||||
fail();
|
||||
}
|
||||
|
||||
o=customProperties.get("long");
|
||||
if (!(o instanceof Long)){
|
||||
fail();
|
||||
}
|
||||
o=customProperties.get("neglong");
|
||||
if (!(o instanceof Long)){
|
||||
fail();
|
||||
}
|
||||
|
||||
o=customProperties.get("double");
|
||||
if (!(o instanceof Double)){
|
||||
fail();
|
||||
}
|
||||
o=customProperties.get("negdouble");
|
||||
if (!(o instanceof Double)){
|
||||
fail();
|
||||
}
|
||||
|
||||
o=customProperties.get("date");
|
||||
if (!(o instanceof Date)){
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
Copyright 2002-2006 Apache Software Foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -27,10 +26,12 @@ import junit.framework.Assert;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hpsf.Constants;
|
||||
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
||||
import org.apache.poi.hpsf.HPSFException;
|
||||
import org.apache.poi.hpsf.PropertySet;
|
||||
import org.apache.poi.hpsf.PropertySetFactory;
|
||||
import org.apache.poi.hpsf.Section;
|
||||
import org.apache.poi.hpsf.SummaryInformation;
|
||||
|
||||
|
||||
|
||||
@ -102,7 +103,7 @@ public class TestUnicode extends TestCase
|
||||
Assert.assertEquals(s.getProperty(1),
|
||||
new Integer(Constants.CP_UTF16));
|
||||
Assert.assertEquals(s.getProperty(2),
|
||||
new Long(4198897018L));
|
||||
new Integer(-96070278));
|
||||
Assert.assertEquals(s.getProperty(3),
|
||||
"MCon_Info zu Office bei Schreiner");
|
||||
Assert.assertEquals(s.getProperty(4),
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
Copyright 2002-2006 Apache Software Foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -14,7 +14,6 @@
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
package org.apache.poi.hpsf.basic;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
@ -124,11 +123,8 @@ public class TestWrite extends TestCase
|
||||
* in.</p>
|
||||
*
|
||||
* @exception IOException if an I/O exception occurs
|
||||
* @exception UnsupportedVariantTypeException if HPSF does not yet support
|
||||
* a variant type to be written
|
||||
*/
|
||||
public void testNoFormatID()
|
||||
throws IOException, UnsupportedVariantTypeException
|
||||
public void testNoFormatID() throws IOException
|
||||
{
|
||||
final String dataDirName = System.getProperty("HPSF.testdata.path");
|
||||
final File dataDir = new File(dataDirName);
|
||||
@ -409,10 +405,19 @@ public class TestWrite extends TestCase
|
||||
check(Variant.VT_CF, new byte[]{0, 1, 2, 3, 4, 5}, codepage);
|
||||
check(Variant.VT_CF, new byte[]{0, 1, 2, 3, 4, 5, 6}, codepage);
|
||||
check(Variant.VT_CF, new byte[]{0, 1, 2, 3, 4, 5, 6, 7}, codepage);
|
||||
check(Variant.VT_I2, new Integer(27), codepage);
|
||||
check(Variant.VT_I4, new Long(28), codepage);
|
||||
check(Variant.VT_I4, new Integer(27), codepage);
|
||||
check(Variant.VT_I8, new Long(28), codepage);
|
||||
check(Variant.VT_R8, new Double(29.0), codepage);
|
||||
check(Variant.VT_I4, new Integer(-27), codepage);
|
||||
check(Variant.VT_I8, new Long(-28), codepage);
|
||||
check(Variant.VT_R8, new Double(-29.0), codepage);
|
||||
check(Variant.VT_FILETIME, new Date(), codepage);
|
||||
check(Variant.VT_I4, new Integer(Integer.MAX_VALUE), codepage);
|
||||
check(Variant.VT_I4, new Integer(Integer.MIN_VALUE), codepage);
|
||||
check(Variant.VT_I8, new Long(Long.MAX_VALUE), codepage);
|
||||
check(Variant.VT_I8, new Long(Long.MIN_VALUE), codepage);
|
||||
check(Variant.VT_R8, new Double(Double.MAX_VALUE), codepage);
|
||||
check(Variant.VT_R8, new Double(Double.MIN_VALUE), codepage);
|
||||
|
||||
check(Variant.VT_LPSTR,
|
||||
"", codepage);
|
||||
@ -602,8 +607,11 @@ public class TestWrite extends TestCase
|
||||
*
|
||||
* @param variantType The property's variant type.
|
||||
* @param value The property's value.
|
||||
* @param codepage The codepage to use for writing and reading.
|
||||
* @throws UnsupportedVariantTypeException if the variant is not supported.
|
||||
* @throws IOException if an I/O exception occurs.
|
||||
* @throws ReadingNotSupportedException
|
||||
* @throws UnsupportedEncodingException
|
||||
*/
|
||||
private void check(final long variantType, final Object value,
|
||||
final int codepage)
|
||||
@ -779,7 +787,7 @@ public class TestWrite extends TestCase
|
||||
m.put(new Long(2), "String 2");
|
||||
m.put(new Long(3), "String 3");
|
||||
s.setDictionary(m);
|
||||
s.setFormatID(SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID);
|
||||
s.setFormatID(SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID[0]);
|
||||
int codepage = Constants.CP_UNICODE;
|
||||
s.setProperty(PropertyIDMap.PID_CODEPAGE, Variant.VT_I2,
|
||||
new Integer(codepage));
|
||||
@ -831,7 +839,7 @@ public class TestWrite extends TestCase
|
||||
m.put(new Long(2), "String 2");
|
||||
m.put(new Long(3), "String 3");
|
||||
s.setDictionary(m);
|
||||
s.setFormatID(SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID);
|
||||
s.setFormatID(SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID[0]);
|
||||
int codepage = 12345;
|
||||
s.setProperty(PropertyIDMap.PID_CODEPAGE, Variant.VT_I2,
|
||||
new Integer(codepage));
|
||||
@ -902,8 +910,11 @@ public class TestWrite extends TestCase
|
||||
|
||||
/**
|
||||
* <p>In order to execute tests with characters beyond US-ASCII, this
|
||||
* method checks whether the application has is runing in an environment
|
||||
* method checks whether the application is runing in an environment
|
||||
* where the default character set is 16-bit-capable.</p>
|
||||
*
|
||||
* @return <code>true</code> if the default character set is 16-bit-capable,
|
||||
* else <code>false</code>.
|
||||
*/
|
||||
private boolean hasProperDefaultCharset()
|
||||
{
|
||||
@ -916,6 +927,9 @@ public class TestWrite extends TestCase
|
||||
|
||||
/**
|
||||
* <p>Runs the test cases stand-alone.</p>
|
||||
*
|
||||
* @param args The command-line parameters.
|
||||
* @throws Throwable if anything goes wrong.
|
||||
*/
|
||||
public static void main(final String[] args) throws Throwable
|
||||
{
|
||||
|
763
src/testcases/org/apache/poi/hpsf/basic/TestWriteWellKnown.java
Normal file
763
src/testcases/org/apache/poi/hpsf/basic/TestWriteWellKnown.java
Normal file
@ -0,0 +1,763 @@
|
||||
/* ====================================================================
|
||||
Copyright 2002-2006 Apache Software Foundation
|
||||
|
||||
Licensed 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.hpsf.basic;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hpsf.CustomProperties;
|
||||
import org.apache.poi.hpsf.CustomProperty;
|
||||
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
||||
import org.apache.poi.hpsf.MarkUnsupportedException;
|
||||
import org.apache.poi.hpsf.MutableProperty;
|
||||
import org.apache.poi.hpsf.MutableSection;
|
||||
import org.apache.poi.hpsf.NoPropertySetStreamException;
|
||||
import org.apache.poi.hpsf.PropertySet;
|
||||
import org.apache.poi.hpsf.PropertySetFactory;
|
||||
import org.apache.poi.hpsf.SummaryInformation;
|
||||
import org.apache.poi.hpsf.UnexpectedPropertySetTypeException;
|
||||
import org.apache.poi.hpsf.Variant;
|
||||
import org.apache.poi.hpsf.VariantSupport;
|
||||
import org.apache.poi.hpsf.WritingNotSupportedException;
|
||||
import org.apache.poi.hpsf.wellknown.SectionIDMap;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryEntry;
|
||||
import org.apache.poi.poifs.filesystem.DocumentEntry;
|
||||
import org.apache.poi.poifs.filesystem.DocumentInputStream;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Tests HPSF's high-level writing functionality for the well-known property
|
||||
* set "SummaryInformation" and "DocumentSummaryInformation".</p>
|
||||
*
|
||||
* @author Rainer Klute
|
||||
* <a href="mailto:klute@rainer-klute.de">klute@rainer-klute.de</a>
|
||||
* @since 2006-02-01
|
||||
* @version $Id$
|
||||
*/
|
||||
public class TestWriteWellKnown extends TestCase
|
||||
{
|
||||
|
||||
private static final String POI_FS = "TestWriteWellKnown.doc";
|
||||
|
||||
/**
|
||||
* <p>Constructor</p>
|
||||
*
|
||||
* @param name the test case's name
|
||||
*/
|
||||
public TestWriteWellKnown(final String name)
|
||||
{
|
||||
super(name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see TestCase#setUp()
|
||||
*/
|
||||
public void setUp()
|
||||
{
|
||||
VariantSupport.setLogUnsupportedTypes(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>This test method checks whether DocumentSummary information streams
|
||||
* can be read. This is done by opening all "Test*" files in the directrory
|
||||
* pointed to by the "HPSF.testdata.path" system property, trying to extract
|
||||
* the document summary information stream in the root directory and calling
|
||||
* its get... methods.</p>
|
||||
* @throws IOException
|
||||
* @throws FileNotFoundException
|
||||
* @throws MarkUnsupportedException
|
||||
* @throws NoPropertySetStreamException
|
||||
* @throws UnexpectedPropertySetTypeException
|
||||
*/
|
||||
public void testReadDocumentSummaryInformation()
|
||||
throws FileNotFoundException, IOException,
|
||||
NoPropertySetStreamException, MarkUnsupportedException,
|
||||
UnexpectedPropertySetTypeException
|
||||
{
|
||||
final String dataDirName = System.getProperty("HPSF.testdata.path");
|
||||
final File dataDir = new File(dataDirName);
|
||||
final File[] docs = dataDir.listFiles(new FileFilter()
|
||||
{
|
||||
public boolean accept(final File file)
|
||||
{
|
||||
return file.isFile() && file.getName().startsWith("Test");
|
||||
}});
|
||||
for (int i = 0; i < docs.length; i++)
|
||||
{
|
||||
final File doc = docs[i];
|
||||
System.out.println("Reading file " + doc);
|
||||
|
||||
/* Read a test document <em>doc</em> into a POI filesystem. */
|
||||
final POIFSFileSystem poifs = new POIFSFileSystem(new FileInputStream(doc));
|
||||
final DirectoryEntry dir = poifs.getRoot();
|
||||
DocumentEntry dsiEntry = null;
|
||||
try
|
||||
{
|
||||
dsiEntry = (DocumentEntry) dir.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
/*
|
||||
* A missing document summary information stream is not an error
|
||||
* and therefore silently ignored here.
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is a document summry information stream, read it from
|
||||
* the POI filesystem.
|
||||
*/
|
||||
if (dsiEntry != null)
|
||||
{
|
||||
final DocumentInputStream dis = new DocumentInputStream(dsiEntry);
|
||||
final PropertySet ps = new PropertySet(dis);
|
||||
final DocumentSummaryInformation dsi = new DocumentSummaryInformation(ps);
|
||||
|
||||
/* Execute the get... methods. */
|
||||
dsi.getByteCount();
|
||||
dsi.getByteOrder();
|
||||
dsi.getCategory();
|
||||
dsi.getCompany();
|
||||
dsi.getCustomProperties();
|
||||
// FIXME dsi.getDocparts();
|
||||
// FIXME dsi.getHeadingPair();
|
||||
dsi.getHiddenCount();
|
||||
dsi.getLineCount();
|
||||
dsi.getLinksDirty();
|
||||
dsi.getManager();
|
||||
dsi.getMMClipCount();
|
||||
dsi.getNoteCount();
|
||||
dsi.getParCount();
|
||||
dsi.getPresentationFormat();
|
||||
dsi.getScale();
|
||||
dsi.getSlideCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>This test method test the writing of properties in the well-known
|
||||
* property set streams "SummaryInformation" and
|
||||
* "DocumentSummaryInformation" by performing the following steps:</p>
|
||||
*
|
||||
* <ol>
|
||||
*
|
||||
* <li><p>Read a test document <em>doc1</em> into a POI filesystem.</p></li>
|
||||
*
|
||||
* <li><p>Read the summary information stream and the document summary
|
||||
* information stream from the POI filesystem.</p></li>
|
||||
*
|
||||
* <li><p>Write all properties supported by HPSF to the summary
|
||||
* information (e.g. author, edit date, application name) and to the
|
||||
* document summary information (e.g. company, manager).</p></li>
|
||||
*
|
||||
* <li><p>Write the summary information stream and the document summary
|
||||
* information stream to the POI filesystem.</p></li>
|
||||
*
|
||||
* <li><p>Write the POI filesystem to a (temporary) file <em>doc2</em>
|
||||
* and close the latter.</p></li>
|
||||
*
|
||||
* <li><p>Open <em>doc2</em> for reading and check summary information
|
||||
* and document summary information. All properties written before must be
|
||||
* found in the property streams of <em>doc2</em> and have the correct
|
||||
* values.</p></li>
|
||||
*
|
||||
* <li><p>Remove all properties supported by HPSF from the summary
|
||||
* information (e.g. author, edit date, application name) and from the
|
||||
* document summary information (e.g. company, manager).</p></li>
|
||||
*
|
||||
* <li><p>Write the summary information stream and the document summary
|
||||
* information stream to the POI filesystem.</p></li>
|
||||
*
|
||||
* <li><p>Write the POI filesystem to a (temporary) file <em>doc3</em>
|
||||
* and close the latter.</p></li>
|
||||
*
|
||||
* <li><p>Open <em>doc3</em> for reading and check summary information
|
||||
* and document summary information. All properties removed before must not
|
||||
* be found in the property streams of <em>doc3</em>.</p></li> </ol>
|
||||
*
|
||||
* @throws IOException if some I/O error occurred.
|
||||
* @throws MarkUnsupportedException
|
||||
* @throws NoPropertySetStreamException
|
||||
* @throws UnexpectedPropertySetTypeException
|
||||
* @throws WritingNotSupportedException
|
||||
*/
|
||||
public void testWriteWellKnown() throws IOException,
|
||||
NoPropertySetStreamException, MarkUnsupportedException,
|
||||
UnexpectedPropertySetTypeException, WritingNotSupportedException
|
||||
{
|
||||
final String dataDirName = System.getProperty("HPSF.testdata.path");
|
||||
final File dataDir = new File(dataDirName);
|
||||
final File doc1 = new File(dataDir, POI_FS);
|
||||
|
||||
/* Read a test document <em>doc1</em> into a POI filesystem. */
|
||||
POIFSFileSystem poifs = new POIFSFileSystem(new FileInputStream(doc1));
|
||||
DirectoryEntry dir = poifs.getRoot();
|
||||
DocumentEntry siEntry = (DocumentEntry) dir.getEntry(SummaryInformation.DEFAULT_STREAM_NAME);
|
||||
DocumentEntry dsiEntry = (DocumentEntry) dir.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
||||
|
||||
/*
|
||||
* Read the summary information stream and the document summary
|
||||
* information stream from the POI filesystem.
|
||||
*
|
||||
* Please note that the result consists of SummaryInformation and
|
||||
* DocumentSummaryInformation instances which are in memory only. To
|
||||
* make them permanent they have to be written to a POI filesystem
|
||||
* explicitly (overwriting the former contents). Then the POI filesystem
|
||||
* should be saved to a file.
|
||||
*/
|
||||
DocumentInputStream dis = new DocumentInputStream(siEntry);
|
||||
PropertySet ps = new PropertySet(dis);
|
||||
SummaryInformation si = new SummaryInformation(ps);
|
||||
dis = new DocumentInputStream(dsiEntry);
|
||||
ps = new PropertySet(dis);
|
||||
DocumentSummaryInformation dsi = new DocumentSummaryInformation(ps);
|
||||
|
||||
/*
|
||||
* Write all properties supported by HPSF to the summary information
|
||||
* (e.g. author, edit date, application name) and to the document
|
||||
* summary information (e.g. company, manager).
|
||||
*/
|
||||
Calendar cal = new GregorianCalendar();
|
||||
cal.set(2000, 6, 6, 6, 6, 6);
|
||||
final long time1 = cal.getTimeInMillis();
|
||||
cal.set(2001, 7, 7, 7, 7, 7);
|
||||
final long time2 = cal.getTimeInMillis();
|
||||
cal.set(2002, 8, 8, 8, 8, 8);
|
||||
final long time3 = cal.getTimeInMillis();
|
||||
|
||||
int nr = 4711;
|
||||
final String P_APPLICATION_NAME = "ApplicationName";
|
||||
final String P_AUTHOR = "Author";
|
||||
final int P_CHAR_COUNT = ++nr;
|
||||
final String P_COMMENTS = "Comments";
|
||||
final Date P_CREATE_DATE_TIME = new Date(time1);
|
||||
final long P_EDIT_TIME = ++nr * 1000 * 10;
|
||||
final String P_KEYWORDS = "Keywords";
|
||||
final String P_LAST_AUTHOR = "LastAuthor";
|
||||
final Date P_LAST_PRINTED = new Date(time2);
|
||||
final Date P_LAST_SAVE_DATE_TIME = new Date(time3);
|
||||
final int P_PAGE_COUNT = ++nr;
|
||||
final String P_REV_NUMBER = "RevNumber";
|
||||
final int P_SECURITY = 1;
|
||||
final String P_SUBJECT = "Subject";
|
||||
final String P_TEMPLATE = "Template";
|
||||
// FIXME (byte array properties not yet implemented): final byte[] P_THUMBNAIL = new byte[123];
|
||||
final String P_TITLE = "Title";
|
||||
final int P_WORD_COUNT = ++nr;
|
||||
|
||||
final int P_BYTE_COUNT = ++nr;
|
||||
final String P_CATEGORY = "Category";
|
||||
final String P_COMPANY = "Company";
|
||||
// FIXME (byte array properties not yet implemented): final byte[] P_DOCPARTS = new byte[123];
|
||||
// FIXME (byte array properties not yet implemented): final byte[] P_HEADING_PAIR = new byte[123];
|
||||
final int P_HIDDEN_COUNT = ++nr;
|
||||
final int P_LINE_COUNT = ++nr;
|
||||
final boolean P_LINKS_DIRTY = true;
|
||||
final String P_MANAGER = "Manager";
|
||||
final int P_MM_CLIP_COUNT = ++nr;
|
||||
final int P_NOTE_COUNT = ++nr;
|
||||
final int P_PAR_COUNT = ++nr;
|
||||
final String P_PRESENTATION_FORMAT = "PresentationFormat";
|
||||
final boolean P_SCALE = false;
|
||||
final int P_SLIDE_COUNT = ++nr;
|
||||
final Date now = new Date();
|
||||
|
||||
final Integer POSITIVE_INTEGER = new Integer(2222);
|
||||
final Long POSITIVE_LONG = new Long(3333);
|
||||
final Double POSITIVE_DOUBLE = new Double(4444);
|
||||
final Integer NEGATIVE_INTEGER = new Integer(2222);
|
||||
final Long NEGATIVE_LONG = new Long(3333);
|
||||
final Double NEGATIVE_DOUBLE = new Double(4444);
|
||||
|
||||
final Integer MAX_INTEGER = new Integer(Integer.MAX_VALUE);
|
||||
final Integer MIN_INTEGER = new Integer(Integer.MIN_VALUE);
|
||||
final Long MAX_LONG = new Long(Long.MAX_VALUE);
|
||||
final Long MIN_LONG = new Long(Long.MIN_VALUE);
|
||||
final Double MAX_DOUBLE = new Double(Double.MAX_VALUE);
|
||||
final Double MIN_DOUBLE = new Double(Double.MIN_VALUE);
|
||||
|
||||
si.setApplicationName(P_APPLICATION_NAME);
|
||||
si.setAuthor(P_AUTHOR);
|
||||
si.setCharCount(P_CHAR_COUNT);
|
||||
si.setComments(P_COMMENTS);
|
||||
si.setCreateDateTime(P_CREATE_DATE_TIME);
|
||||
si.setEditTime(P_EDIT_TIME);
|
||||
si.setKeywords(P_KEYWORDS);
|
||||
si.setLastAuthor(P_LAST_AUTHOR);
|
||||
si.setLastPrinted(P_LAST_PRINTED);
|
||||
si.setLastSaveDateTime(P_LAST_SAVE_DATE_TIME);
|
||||
si.setPageCount(P_PAGE_COUNT);
|
||||
si.setRevNumber(P_REV_NUMBER);
|
||||
si.setSecurity(P_SECURITY);
|
||||
si.setSubject(P_SUBJECT);
|
||||
si.setTemplate(P_TEMPLATE);
|
||||
// FIXME (byte array properties not yet implemented): si.setThumbnail(P_THUMBNAIL);
|
||||
si.setTitle(P_TITLE);
|
||||
si.setWordCount(P_WORD_COUNT);
|
||||
|
||||
dsi.setByteCount(P_BYTE_COUNT);
|
||||
dsi.setCategory(P_CATEGORY);
|
||||
dsi.setCompany(P_COMPANY);
|
||||
// FIXME (byte array properties not yet implemented): dsi.setDocparts(P_DOCPARTS);
|
||||
// FIXME (byte array properties not yet implemented): dsi.setHeadingPair(P_HEADING_PAIR);
|
||||
dsi.setHiddenCount(P_HIDDEN_COUNT);
|
||||
dsi.setLineCount(P_LINE_COUNT);
|
||||
dsi.setLinksDirty(P_LINKS_DIRTY);
|
||||
dsi.setManager(P_MANAGER);
|
||||
dsi.setMMClipCount(P_MM_CLIP_COUNT);
|
||||
dsi.setNoteCount(P_NOTE_COUNT);
|
||||
dsi.setParCount(P_PAR_COUNT);
|
||||
dsi.setPresentationFormat(P_PRESENTATION_FORMAT);
|
||||
dsi.setScale(P_SCALE);
|
||||
dsi.setSlideCount(P_SLIDE_COUNT);
|
||||
|
||||
CustomProperties customProperties = dsi.getCustomProperties();
|
||||
if (customProperties == null)
|
||||
customProperties = new CustomProperties();
|
||||
customProperties.put("Schlüssel ä", "Wert ä");
|
||||
customProperties.put("Schlüssel äö", "Wert äö");
|
||||
customProperties.put("Schlüssel äöü", "Wert äöü");
|
||||
customProperties.put("Schlüssel äöüß", "Wert äöüß");
|
||||
customProperties.put("positive_Integer", POSITIVE_INTEGER);
|
||||
customProperties.put("positive_Long", POSITIVE_LONG);
|
||||
customProperties.put("positive_Double", POSITIVE_DOUBLE);
|
||||
customProperties.put("negative_Integer", NEGATIVE_INTEGER);
|
||||
customProperties.put("negative_Long", NEGATIVE_LONG);
|
||||
customProperties.put("negative_Double", NEGATIVE_DOUBLE);
|
||||
customProperties.put("Boolean", new Boolean(true));
|
||||
customProperties.put("Date", now);
|
||||
customProperties.put("max_Integer", MAX_INTEGER);
|
||||
customProperties.put("min_Integer", MIN_INTEGER);
|
||||
customProperties.put("max_Long", MAX_LONG);
|
||||
customProperties.put("min_Long", MIN_LONG);
|
||||
customProperties.put("max_Double", MAX_DOUBLE);
|
||||
customProperties.put("min_Double", MIN_DOUBLE);
|
||||
dsi.setCustomProperties(customProperties);
|
||||
|
||||
/* Write the summary information stream and the document summary
|
||||
* information stream to the POI filesystem. */
|
||||
si.write(dir, siEntry.getName());
|
||||
dsi.write(dir, dsiEntry.getName());
|
||||
|
||||
/* Write the POI filesystem to a (temporary) file <em>doc2</em>
|
||||
* and close the latter. */
|
||||
final File doc2 = File.createTempFile("POI_HPSF_Test.", ".tmp");
|
||||
doc2.deleteOnExit();
|
||||
OutputStream out = new FileOutputStream(doc2);
|
||||
poifs.writeFilesystem(out);
|
||||
out.close();
|
||||
|
||||
/*
|
||||
* Open <em>doc2</em> for reading and check summary information and
|
||||
* document summary information. All properties written before must be
|
||||
* found in the property streams of <em>doc2</em> and have the correct
|
||||
* values.
|
||||
*/
|
||||
poifs = new POIFSFileSystem(new FileInputStream(doc2));
|
||||
dir = poifs.getRoot();
|
||||
siEntry = (DocumentEntry) dir.getEntry(SummaryInformation.DEFAULT_STREAM_NAME);
|
||||
dsiEntry = (DocumentEntry) dir.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
||||
|
||||
dis = new DocumentInputStream(siEntry);
|
||||
ps = new PropertySet(dis);
|
||||
si = new SummaryInformation(ps);
|
||||
dis = new DocumentInputStream(dsiEntry);
|
||||
ps = new PropertySet(dis);
|
||||
dsi = new DocumentSummaryInformation(ps);
|
||||
|
||||
assertEquals(P_APPLICATION_NAME, si.getApplicationName());
|
||||
assertEquals(P_AUTHOR, si.getAuthor());
|
||||
assertEquals(P_CHAR_COUNT, si.getCharCount());
|
||||
assertEquals(P_COMMENTS, si.getComments());
|
||||
assertEquals(P_CREATE_DATE_TIME, si.getCreateDateTime());
|
||||
assertEquals(P_EDIT_TIME, si.getEditTime());
|
||||
assertEquals(P_KEYWORDS, si.getKeywords());
|
||||
assertEquals(P_LAST_AUTHOR, si.getLastAuthor());
|
||||
assertEquals(P_LAST_PRINTED, si.getLastPrinted());
|
||||
assertEquals(P_LAST_SAVE_DATE_TIME, si.getLastSaveDateTime());
|
||||
assertEquals(P_PAGE_COUNT, si.getPageCount());
|
||||
assertEquals(P_REV_NUMBER, si.getRevNumber());
|
||||
assertEquals(P_SECURITY, si.getSecurity());
|
||||
assertEquals(P_SUBJECT, si.getSubject());
|
||||
assertEquals(P_TEMPLATE, si.getTemplate());
|
||||
// FIXME (byte array properties not yet implemented): assertEquals(P_THUMBNAIL, si.getThumbnail());
|
||||
assertEquals(P_TITLE, si.getTitle());
|
||||
assertEquals(P_WORD_COUNT, si.getWordCount());
|
||||
|
||||
assertEquals(P_BYTE_COUNT, dsi.getByteCount());
|
||||
assertEquals(P_CATEGORY, dsi.getCategory());
|
||||
assertEquals(P_COMPANY, dsi.getCompany());
|
||||
// FIXME (byte array properties not yet implemented): assertEquals(P_, dsi.getDocparts());
|
||||
// FIXME (byte array properties not yet implemented): assertEquals(P_, dsi.getHeadingPair());
|
||||
assertEquals(P_HIDDEN_COUNT, dsi.getHiddenCount());
|
||||
assertEquals(P_LINE_COUNT, dsi.getLineCount());
|
||||
assertEquals(P_LINKS_DIRTY, dsi.getLinksDirty());
|
||||
assertEquals(P_MANAGER, dsi.getManager());
|
||||
assertEquals(P_MM_CLIP_COUNT, dsi.getMMClipCount());
|
||||
assertEquals(P_NOTE_COUNT, dsi.getNoteCount());
|
||||
assertEquals(P_PAR_COUNT, dsi.getParCount());
|
||||
assertEquals(P_PRESENTATION_FORMAT, dsi.getPresentationFormat());
|
||||
assertEquals(P_SCALE, dsi.getScale());
|
||||
assertEquals(P_SLIDE_COUNT, dsi.getSlideCount());
|
||||
|
||||
final CustomProperties cps = dsi.getCustomProperties();
|
||||
assertEquals(customProperties, cps);
|
||||
assertNull(cps.get("No value available"));
|
||||
assertEquals("Wert ä", cps.get("Schlüssel ä"));
|
||||
assertEquals("Wert äö", cps.get("Schlüssel äö"));
|
||||
assertEquals("Wert äöü", cps.get("Schlüssel äöü"));
|
||||
assertEquals("Wert äöüß", cps.get("Schlüssel äöüß"));
|
||||
assertEquals(POSITIVE_INTEGER, cps.get("positive_Integer"));
|
||||
assertEquals(POSITIVE_LONG, cps.get("positive_Long"));
|
||||
assertEquals(POSITIVE_DOUBLE, cps.get("positive_Double"));
|
||||
assertEquals(NEGATIVE_INTEGER, cps.get("negative_Integer"));
|
||||
assertEquals(NEGATIVE_LONG, cps.get("negative_Long"));
|
||||
assertEquals(NEGATIVE_DOUBLE, cps.get("negative_Double"));
|
||||
assertEquals(new Boolean(true), cps.get("Boolean"));
|
||||
assertEquals(now, cps.get("Date"));
|
||||
assertEquals(MAX_INTEGER, cps.get("max_Integer"));
|
||||
assertEquals(MIN_INTEGER, cps.get("min_Integer"));
|
||||
assertEquals(MAX_LONG, cps.get("max_Long"));
|
||||
assertEquals(MIN_LONG, cps.get("min_Long"));
|
||||
assertEquals(MAX_DOUBLE, cps.get("max_Double"));
|
||||
assertEquals(MIN_DOUBLE, cps.get("min_Double"));
|
||||
|
||||
/* Remove all properties supported by HPSF from the summary
|
||||
* information (e.g. author, edit date, application name) and from the
|
||||
* document summary information (e.g. company, manager). */
|
||||
si.removeApplicationName();
|
||||
si.removeAuthor();
|
||||
si.removeCharCount();
|
||||
si.removeComments();
|
||||
si.removeCreateDateTime();
|
||||
si.removeEditTime();
|
||||
si.removeKeywords();
|
||||
si.removeLastAuthor();
|
||||
si.removeLastPrinted();
|
||||
si.removeLastSaveDateTime();
|
||||
si.removePageCount();
|
||||
si.removeRevNumber();
|
||||
si.removeSecurity();
|
||||
si.removeSubject();
|
||||
si.removeTemplate();
|
||||
si.removeThumbnail();
|
||||
si.removeTitle();
|
||||
si.removeWordCount();
|
||||
|
||||
dsi.removeByteCount();
|
||||
dsi.removeCategory();
|
||||
dsi.removeCompany();
|
||||
dsi.removeCustomProperties();
|
||||
dsi.removeDocparts();
|
||||
dsi.removeHeadingPair();
|
||||
dsi.removeHiddenCount();
|
||||
dsi.removeLineCount();
|
||||
dsi.removeLinksDirty();
|
||||
dsi.removeManager();
|
||||
dsi.removeMMClipCount();
|
||||
dsi.removeNoteCount();
|
||||
dsi.removeParCount();
|
||||
dsi.removePresentationFormat();
|
||||
dsi.removeScale();
|
||||
dsi.removeSlideCount();
|
||||
|
||||
/*
|
||||
* <li><p>Write the summary information stream and the document summary
|
||||
* information stream to the POI filesystem. */
|
||||
si.write(dir, siEntry.getName());
|
||||
dsi.write(dir, dsiEntry.getName());
|
||||
|
||||
/*
|
||||
* <li><p>Write the POI filesystem to a (temporary) file <em>doc3</em>
|
||||
* and close the latter. */
|
||||
final File doc3 = File.createTempFile("POI_HPSF_Test.", ".tmp");
|
||||
doc3.deleteOnExit();
|
||||
out = new FileOutputStream(doc3);
|
||||
poifs.writeFilesystem(out);
|
||||
out.close();
|
||||
|
||||
/*
|
||||
* Open <em>doc3</em> for reading and check summary information
|
||||
* and document summary information. All properties removed before must not
|
||||
* be found in the property streams of <em>doc3</em>.
|
||||
*/
|
||||
poifs = new POIFSFileSystem(new FileInputStream(doc3));
|
||||
dir = poifs.getRoot();
|
||||
siEntry = (DocumentEntry) dir.getEntry(SummaryInformation.DEFAULT_STREAM_NAME);
|
||||
dsiEntry = (DocumentEntry) dir.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
||||
|
||||
dis = new DocumentInputStream(siEntry);
|
||||
ps = new PropertySet(dis);
|
||||
si = new SummaryInformation(ps);
|
||||
dis = new DocumentInputStream(dsiEntry);
|
||||
ps = new PropertySet(dis);
|
||||
dsi = new DocumentSummaryInformation(ps);
|
||||
|
||||
assertEquals(null, si.getApplicationName());
|
||||
assertEquals(null, si.getAuthor());
|
||||
assertEquals(0, si.getCharCount());
|
||||
assertTrue(si.wasNull());
|
||||
assertEquals(null, si.getComments());
|
||||
assertEquals(null, si.getCreateDateTime());
|
||||
assertEquals(0, si.getEditTime());
|
||||
assertTrue(si.wasNull());
|
||||
assertEquals(null, si.getKeywords());
|
||||
assertEquals(null, si.getLastAuthor());
|
||||
assertEquals(null, si.getLastPrinted());
|
||||
assertEquals(null, si.getLastSaveDateTime());
|
||||
assertEquals(0, si.getPageCount());
|
||||
assertTrue(si.wasNull());
|
||||
assertEquals(null, si.getRevNumber());
|
||||
assertEquals(0, si.getSecurity());
|
||||
assertTrue(si.wasNull());
|
||||
assertEquals(null, si.getSubject());
|
||||
assertEquals(null, si.getTemplate());
|
||||
assertEquals(null, si.getThumbnail());
|
||||
assertEquals(null, si.getTitle());
|
||||
assertEquals(0, si.getWordCount());
|
||||
assertTrue(si.wasNull());
|
||||
|
||||
assertEquals(0, dsi.getByteCount());
|
||||
assertTrue(dsi.wasNull());
|
||||
assertEquals(null, dsi.getCategory());
|
||||
assertEquals(null, dsi.getCustomProperties());
|
||||
// FIXME (byte array properties not yet implemented): assertEquals(null, dsi.getDocparts());
|
||||
// FIXME (byte array properties not yet implemented): assertEquals(null, dsi.getHeadingPair());
|
||||
assertEquals(0, dsi.getHiddenCount());
|
||||
assertTrue(dsi.wasNull());
|
||||
assertEquals(0, dsi.getLineCount());
|
||||
assertTrue(dsi.wasNull());
|
||||
assertEquals(false, dsi.getLinksDirty());
|
||||
assertTrue(dsi.wasNull());
|
||||
assertEquals(null, dsi.getManager());
|
||||
assertEquals(0, dsi.getMMClipCount());
|
||||
assertTrue(dsi.wasNull());
|
||||
assertEquals(0, dsi.getNoteCount());
|
||||
assertTrue(dsi.wasNull());
|
||||
assertEquals(0, dsi.getParCount());
|
||||
assertTrue(dsi.wasNull());
|
||||
assertEquals(null, dsi.getPresentationFormat());
|
||||
assertEquals(false, dsi.getScale());
|
||||
assertTrue(dsi.wasNull());
|
||||
assertEquals(0, dsi.getSlideCount());
|
||||
assertTrue(dsi.wasNull());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Tests the simplified custom properties by reading them from the
|
||||
* available test files.</p>
|
||||
*
|
||||
* @throws Throwable if anything goes wrong.
|
||||
*/
|
||||
public void testReadCustomPropertiesFromFiles() throws Throwable
|
||||
{
|
||||
final AllDataFilesTester.TestTask task = new AllDataFilesTester.TestTask()
|
||||
{
|
||||
public void runTest(final File file) throws FileNotFoundException,
|
||||
IOException, NoPropertySetStreamException,
|
||||
MarkUnsupportedException,
|
||||
UnexpectedPropertySetTypeException
|
||||
{
|
||||
/* Read a test document <em>doc</em> into a POI filesystem. */
|
||||
final POIFSFileSystem poifs = new POIFSFileSystem(new FileInputStream(file));
|
||||
final DirectoryEntry dir = poifs.getRoot();
|
||||
DocumentEntry dsiEntry = null;
|
||||
try
|
||||
{
|
||||
dsiEntry = (DocumentEntry) dir.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
/*
|
||||
* A missing document summary information stream is not an error
|
||||
* and therefore silently ignored here.
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is a document summry information stream, read it from
|
||||
* the POI filesystem, else create a new one.
|
||||
*/
|
||||
DocumentSummaryInformation dsi;
|
||||
if (dsiEntry != null)
|
||||
{
|
||||
final DocumentInputStream dis = new DocumentInputStream(dsiEntry);
|
||||
final PropertySet ps = new PropertySet(dis);
|
||||
dsi = new DocumentSummaryInformation(ps);
|
||||
}
|
||||
else
|
||||
dsi = PropertySetFactory.newDocumentSummaryInformation();
|
||||
final CustomProperties cps = dsi.getCustomProperties();
|
||||
|
||||
if (cps == null)
|
||||
/* The document does not have custom properties. */
|
||||
return;
|
||||
|
||||
for (final Iterator i = cps.entrySet().iterator(); i.hasNext();)
|
||||
{
|
||||
final Map.Entry e = (Entry) i.next();
|
||||
final CustomProperty cp = (CustomProperty) e.getValue();
|
||||
cp.getName();
|
||||
cp.getValue();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
final String dataDirName = System.getProperty("HPSF.testdata.path");
|
||||
final File dataDir = new File(dataDirName);
|
||||
final File[] docs = dataDir.listFiles(new FileFilter()
|
||||
{
|
||||
public boolean accept(final File file)
|
||||
{
|
||||
return file.isFile() && file.getName().startsWith("Test");
|
||||
}
|
||||
});
|
||||
|
||||
for (int i = 0; i < docs.length; i++)
|
||||
{
|
||||
task.runTest(docs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Tests basic custom property features.</p>
|
||||
*/
|
||||
public void testCustomerProperties()
|
||||
{
|
||||
final String KEY = "Schlüssel ä";
|
||||
final String VALUE_1 = "Wert 1";
|
||||
final String VALUE_2 = "Wert 2";
|
||||
|
||||
CustomProperty cp;
|
||||
CustomProperties cps = new CustomProperties();
|
||||
assertEquals(0, cps.size());
|
||||
|
||||
/* After adding a custom property the size must be 1 and it must be
|
||||
* possible to extract the custom property from the map. */
|
||||
cps.put(KEY, VALUE_1);
|
||||
assertEquals(1, cps.size());
|
||||
Object v1 = cps.get(KEY);
|
||||
assertEquals(VALUE_1, v1);
|
||||
|
||||
/* After adding a custom property with the same name the size must still
|
||||
* be one. */
|
||||
cps.put(KEY, VALUE_2);
|
||||
assertEquals(1, cps.size());
|
||||
Object v2 = cps.get(KEY);
|
||||
assertEquals(VALUE_2, v2);
|
||||
|
||||
/* Removing the custom property must return the remove property and
|
||||
* reduce the size to 0. */
|
||||
cp = (CustomProperty) cps.remove(KEY);
|
||||
assertEquals(KEY, cp.getName());
|
||||
assertEquals(VALUE_2, cp.getValue());
|
||||
assertEquals(0, cps.size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Tests reading custom properties from a section including reading
|
||||
* custom properties which are not pure.</p>
|
||||
*/
|
||||
public void testGetCustomerProperties()
|
||||
{
|
||||
final int ID_1 = 2;
|
||||
final int ID_2 = 3;
|
||||
final String NAME_1 = "Schlüssel ä";
|
||||
final String VALUE_1 = "Wert 1";
|
||||
final Map dictionary = new HashMap();
|
||||
|
||||
DocumentSummaryInformation dsi = PropertySetFactory.newDocumentSummaryInformation();
|
||||
CustomProperties cps;
|
||||
MutableSection s;
|
||||
|
||||
/* A document summary information set stream by default does have custom properties. */
|
||||
cps = dsi.getCustomProperties();
|
||||
assertEquals(null, cps);
|
||||
|
||||
/* Test an empty custom properties set. */
|
||||
s = new MutableSection();
|
||||
s.setFormatID(SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID[1]);
|
||||
// s.setCodepage(Constants.CP_UNICODE);
|
||||
dsi.addSection(s);
|
||||
cps = dsi.getCustomProperties();
|
||||
assertEquals(0, cps.size());
|
||||
|
||||
/* Add a custom property. */
|
||||
MutableProperty p = new MutableProperty();
|
||||
p.setID(ID_1);
|
||||
p.setType(Variant.VT_LPWSTR);
|
||||
p.setValue(VALUE_1);
|
||||
s.setProperty(p);
|
||||
dictionary.put(new Long(ID_1), NAME_1);
|
||||
s.setDictionary(dictionary);
|
||||
cps = dsi.getCustomProperties();
|
||||
assertEquals(1, cps.size());
|
||||
assertTrue(cps.isPure());
|
||||
|
||||
/* Add another custom property. */
|
||||
s.setProperty(ID_2, Variant.VT_LPWSTR, VALUE_1);
|
||||
dictionary.put(new Long(ID_2), NAME_1);
|
||||
s.setDictionary(dictionary);
|
||||
cps = dsi.getCustomProperties();
|
||||
assertEquals(1, cps.size());
|
||||
assertFalse(cps.isPure());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Runs the test cases stand-alone.</p>
|
||||
*
|
||||
* @param args The command-line parameters.
|
||||
* @throws Throwable if anything goes wrong.
|
||||
*/
|
||||
public static void main(final String[] args) throws Throwable
|
||||
{
|
||||
System.setProperty("HPSF.testdata.path",
|
||||
"./src/testcases/org/apache/poi/hpsf/data");
|
||||
junit.textui.TestRunner.run(TestWriteWellKnown.class);
|
||||
}
|
||||
|
||||
}
|
0
src/testcases/org/apache/poi/hpsf/data/TestCorel.shw
Executable file → Normal file
0
src/testcases/org/apache/poi/hpsf/data/TestCorel.shw
Executable file → Normal file
0
src/testcases/org/apache/poi/hpsf/data/TestGermanWord90.doc
Executable file → Normal file
0
src/testcases/org/apache/poi/hpsf/data/TestGermanWord90.doc
Executable file → Normal file
0
src/testcases/org/apache/poi/hpsf/data/TestRobert_Flaherty.doc
Executable file → Normal file
0
src/testcases/org/apache/poi/hpsf/data/TestRobert_Flaherty.doc
Executable file → Normal file
BIN
src/testcases/org/apache/poi/hpsf/data/TestWriteWellKnown.doc
Normal file
BIN
src/testcases/org/apache/poi/hpsf/data/TestWriteWellKnown.doc
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user