aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Klute <klute@apache.org>2003-09-18 18:56:35 +0000
committerRainer Klute <klute@apache.org>2003-09-18 18:56:35 +0000
commit8f08b03cf0437945156cd3a2f23b39d22513dfa6 (patch)
treec3885b6611dde2dcd7a504c2b979384229edc17e
parent774387396fd3aa45e884246957842fe7b7541a71 (diff)
downloadpoi-8f08b03cf0437945156cd3a2f23b39d22513dfa6.tar.gz
poi-8f08b03cf0437945156cd3a2f23b39d22513dfa6.zip
These changes introduce the following HPSF enhancements and fixes:
- Section dictionaries (aka custom properties) can be written now. - Constructor MutableProperty(PropertySet) sets the class ID correctly now. - Possible invalid section count fixed - More testcases - Cosmetics git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@353360 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--src/examples/src/org/apache/poi/hpsf/examples/WriteAuthorAndTitle.java1
-rw-r--r--src/examples/src/org/apache/poi/hpsf/examples/WriteTitle.java16
-rw-r--r--src/java/org/apache/poi/hpsf/IllegalPropertySetDataException.java2
-rw-r--r--src/java/org/apache/poi/hpsf/MutablePropertySet.java3
-rw-r--r--src/java/org/apache/poi/hpsf/MutableSection.java186
-rw-r--r--src/java/org/apache/poi/hpsf/Property.java11
-rw-r--r--src/java/org/apache/poi/hpsf/PropertySetFactory.java2
-rw-r--r--src/java/org/apache/poi/hpsf/Section.java20
-rw-r--r--src/java/org/apache/poi/hpsf/VariantSupport.java11
-rw-r--r--src/java/org/apache/poi/hpsf/wellknown/PropertyIDMap.java2
-rw-r--r--src/testcases/org/apache/poi/hpsf/basic/TestBasic.java3
-rw-r--r--src/testcases/org/apache/poi/hpsf/basic/TestEmptyProperties.java1
-rw-r--r--src/testcases/org/apache/poi/hpsf/basic/TestWrite.java173
-rw-r--r--src/testcases/org/apache/poi/hpsf/data/TestSectionDictionary.docbin0 -> 83456 bytes
14 files changed, 345 insertions, 86 deletions
diff --git a/src/examples/src/org/apache/poi/hpsf/examples/WriteAuthorAndTitle.java b/src/examples/src/org/apache/poi/hpsf/examples/WriteAuthorAndTitle.java
index 64ea6c5427..d0b203dfdd 100644
--- a/src/examples/src/org/apache/poi/hpsf/examples/WriteAuthorAndTitle.java
+++ b/src/examples/src/org/apache/poi/hpsf/examples/WriteAuthorAndTitle.java
@@ -72,7 +72,6 @@ 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.UnexpectedPropertySetTypeException;
import org.apache.poi.hpsf.Util;
import org.apache.poi.hpsf.Variant;
import org.apache.poi.hpsf.WritingNotSupportedException;
diff --git a/src/examples/src/org/apache/poi/hpsf/examples/WriteTitle.java b/src/examples/src/org/apache/poi/hpsf/examples/WriteTitle.java
index c98274829b..df85917e68 100644
--- a/src/examples/src/org/apache/poi/hpsf/examples/WriteTitle.java
+++ b/src/examples/src/org/apache/poi/hpsf/examples/WriteTitle.java
@@ -54,11 +54,19 @@
*/
package org.apache.poi.hpsf.examples;
-import java.io.*;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
-import org.apache.poi.hpsf.*;
-import org.apache.poi.hpsf.wellknown.*;
-import org.apache.poi.poifs.filesystem.*;
+import org.apache.poi.hpsf.MutableProperty;
+import org.apache.poi.hpsf.MutablePropertySet;
+import org.apache.poi.hpsf.MutableSection;
+import org.apache.poi.hpsf.SummaryInformation;
+import org.apache.poi.hpsf.Variant;
+import org.apache.poi.hpsf.WritingNotSupportedException;
+import org.apache.poi.hpsf.wellknown.PropertyIDMap;
+import org.apache.poi.hpsf.wellknown.SectionIDMap;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
/**
* <p>This class is a simple sample application showing how to create a property
diff --git a/src/java/org/apache/poi/hpsf/IllegalPropertySetDataException.java b/src/java/org/apache/poi/hpsf/IllegalPropertySetDataException.java
index 378b1874d1..3ad7de6e0b 100644
--- a/src/java/org/apache/poi/hpsf/IllegalPropertySetDataException.java
+++ b/src/java/org/apache/poi/hpsf/IllegalPropertySetDataException.java
@@ -66,7 +66,7 @@ package org.apache.poi.hpsf;
* @version $Id$
* @since 2002-05-26
*/
-public class IllegalPropertySetDataException extends HPSFRuntimeException
+public class IllegalPropertySetDataException extends HPSFRuntimeException
{
/**
diff --git a/src/java/org/apache/poi/hpsf/MutablePropertySet.java b/src/java/org/apache/poi/hpsf/MutablePropertySet.java
index 8a236643d7..f9f1333eec 100644
--- a/src/java/org/apache/poi/hpsf/MutablePropertySet.java
+++ b/src/java/org/apache/poi/hpsf/MutablePropertySet.java
@@ -106,6 +106,7 @@ public class MutablePropertySet extends PropertySet
* one section it is added right here. */
sections = new LinkedList();
sections.add(new MutableSection());
+ sectionCount = 1;
}
@@ -123,7 +124,7 @@ public class MutablePropertySet extends PropertySet
byteOrder = ps.getByteOrder();
format = ps.getFormat();
osVersion = ps.getOSVersion();
- classID = new ClassID(ps.getClassID().getBytes(), 0);
+ setClassID(ps.getClassID());
clearSections();
for (final Iterator i = ps.getSections().iterator(); i.hasNext();)
{
diff --git a/src/java/org/apache/poi/hpsf/MutableSection.java b/src/java/org/apache/poi/hpsf/MutableSection.java
index fce86980e4..e60edf5bd4 100644
--- a/src/java/org/apache/poi/hpsf/MutableSection.java
+++ b/src/java/org/apache/poi/hpsf/MutableSection.java
@@ -60,7 +60,9 @@ import java.io.OutputStream;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
+import org.apache.poi.hpsf.wellknown.PropertyIDMap;
import org.apache.poi.util.LittleEndian;
/**
@@ -129,7 +131,7 @@ public class MutableSection extends Section
for (int i = 0; i < pa.length; i++)
mpa[i] = new MutableProperty(pa[i]);
setProperties(mpa);
- dictionary = s.dictionary;
+ setDictionary(s.getDictionary());
}
@@ -247,13 +249,27 @@ public class MutableSection extends Section
public void setProperty(final Property p)
{
final long id = p.getID();
+ removeProperty(id);
+ preprops.add(p);
+ dirty = true;
+ propertyCount = preprops.size();
+ }
+
+
+
+ /**
+ * <p>Removes a property.</p>
+ *
+ * @param id The ID of the property to be removed
+ */
+ public void removeProperty(final long id)
+ {
for (final Iterator i = preprops.iterator(); i.hasNext();)
if (((Property) i.next()).getID() == id)
{
i.remove();
break;
}
- preprops.add(p);
dirty = true;
propertyCount = preprops.size();
}
@@ -292,6 +308,10 @@ public class MutableSection extends Section
size = calcSize();
dirty = false;
}
+ catch (HPSFRuntimeException ex)
+ {
+ throw ex;
+ }
catch (Exception ex)
{
throw new HPSFRuntimeException(ex);
@@ -365,19 +385,55 @@ public class MutableSection extends Section
position += 2 * LittleEndian.INT_SIZE +
getPropertyCount() * 2 * LittleEndian.INT_SIZE;
+ /* Writing the section's dictionary it tricky. If there is a dictionary
+ * (property 0) the codepage property (property 1) has to be set, too.
+ * Since HPSF supports Unicode only, the codepage must be 1200. */
+ if (getProperty(PropertyIDMap.PID_DICTIONARY) != null)
+ {
+ final Object p1 = getProperty(PropertyIDMap.PID_CODEPAGE);
+ if (p1 != null)
+ {
+ if (!(p1 instanceof Integer))
+ throw new IllegalPropertySetDataException
+ ("The codepage property (ID = 1) must be an " +
+ "Integer object.");
+ else if (((Integer) p1).intValue() != Property.CP_UNICODE)
+ throw new IllegalPropertySetDataException
+ ("The codepage property (ID = 1) must be " +
+ "1200 (Unicode).");
+ }
+ else
+ throw new IllegalPropertySetDataException
+ ("The codepage property (ID = 1) must be set.");
+ }
+
/* Write the properties and the property list into their respective
* streams: */
for (final Iterator i = preprops.iterator(); i.hasNext();)
{
final MutableProperty p = (MutableProperty) i.next();
+ final long id = p.getID();
/* Write the property list entry. */
TypeWriter.writeUIntToStream(propertyListStream, p.getID());
TypeWriter.writeUIntToStream(propertyListStream, position);
-
- /* Write the property and update the position to the next
- * property. */
- position += p.write(propertyStream);
+
+ /* If the property ID is not equal 0 we write the property and all
+ * is fine. However, if it equals 0 we have to write the section's
+ * dictionary which does not have a type but just a value. */
+ if (id != 0)
+ /* Write the property and update the position to the next
+ * property. */
+ position += p.write(propertyStream);
+ else
+ {
+ final Integer codepage =
+ (Integer) getProperty(PropertyIDMap.PID_CODEPAGE);
+ if (codepage == null)
+ throw new IllegalPropertySetDataException
+ ("Codepage (property 1) is undefined.");
+ position += writeDictionary(propertyStream, dictionary);
+ }
}
propertyStream.close();
propertyListStream.close();
@@ -406,6 +462,52 @@ public class MutableSection extends Section
/**
+ * <p>Writes the section's dictionary.</p>
+ *
+ * @param out The output stream to write to.
+ * @param dictionary The dictionary.
+ * @return The number of bytes written
+ * @exception IOException if an I/O exception occurs.
+ */
+ private static int writeDictionary(final OutputStream out,
+ final Map dictionary)
+ throws IOException
+ {
+ int length = 0;
+ length += TypeWriter.writeUIntToStream(out, dictionary.size());
+ for (final Iterator i = dictionary.keySet().iterator(); i.hasNext();)
+ {
+ final Long key = (Long) i.next();
+ final String value = (String) dictionary.get(key);
+ int sLength = value.length() + 1;
+ if (sLength % 2 == 1)
+ 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++)
+ {
+ int high = (ca[j] & 0x0ff00) >> 8;
+ int low = (ca[j] & 0x000ff);
+ out.write(low);
+ out.write(high);
+ length += 2;
+ sLength--;
+ }
+ while (sLength > 0)
+ {
+ out.write(0x00);
+ out.write(0x00);
+ length += 2;
+ sLength--;
+ }
+ }
+ return length;
+ }
+
+
+
+ /**
* <p>Overwrites the super class' method to cope with a redundancy:
* the property count is maintained in a separate member variable, but
* shouldn't.</p>
@@ -426,7 +528,77 @@ public class MutableSection extends Section
*/
public Property[] getProperties()
{
- return (Property[]) preprops.toArray(new Property[0]);
+ properties = (Property[]) preprops.toArray(new Property[0]);
+ return properties;
+ }
+
+
+
+ /**
+ * <p>Gets a property.</p>
+ *
+ * <p><strong>FIXME (2):</strong> This method ensures that properties and
+ * preprops are in sync. Cleanup this awful stuff!</p>
+ *
+ * @param id The ID of the property to get
+ * @return The property or <code>null</code> if there is no such property
+ */
+ public Object getProperty(final long id)
+ {
+ getProperties();
+ return super.getProperty(id);
+ }
+
+
+
+ /**
+ * <p>Sets the section's dictionary. All keys in the dictionary must be
+ * {@see java.lang.Long} instances, all values must be
+ * {@see java.lang.String}s. This method overwrites the properties with IDs
+ * 0 and 1 since they are reserved for the dictionary and the dictionary's
+ * codepage. Setting these properties explicitly might have surprising
+ * effects. An application should never do this but always use this
+ * method.</p>
+ *
+ * @param dictionary The dictionary
+ *
+ * @exception IllegalPropertySetDataException if the dictionary's key and
+ * value types are not correct.
+ *
+ * @see Section#getDictionary()
+ */
+ public void setDictionary(final Map dictionary)
+ throws IllegalPropertySetDataException
+ {
+ if (dictionary != null)
+ {
+ for (final Iterator i = dictionary.keySet().iterator();
+ i.hasNext();)
+ if (!(i.next() instanceof Long))
+ throw new IllegalPropertySetDataException
+ ("Dictionary keys must be of type Long.");
+ for (final Iterator i = dictionary.values().iterator();
+ i.hasNext();)
+ if (!(i.next() instanceof String))
+ throw new IllegalPropertySetDataException
+ ("Dictionary values must be of type String.");
+ this.dictionary = dictionary;
+
+ /* Set the dictionary property (ID 0). Please note that the second
+ * parameter in the method call below is unused because dictionaries
+ * don't have a type. */
+ setProperty(PropertyIDMap.PID_DICTIONARY, -1, dictionary);
+
+ /* Set the codepage property (ID 1) for the strings used in the
+ * dictionary. HPSF always writes Unicode strings to the
+ * dictionary. */
+ setProperty(PropertyIDMap.PID_CODEPAGE, Variant.VT_I2,
+ new Integer(Property.CP_UNICODE));
+ }
+ else
+ /* Setting the dictionary to null means to remove property 0.
+ * However, it does not mean to remove property 1 (codepage). */
+ removeProperty(PropertyIDMap.PID_DICTIONARY);
}
}
diff --git a/src/java/org/apache/poi/hpsf/Property.java b/src/java/org/apache/poi/hpsf/Property.java
index 0a3bc97fa4..e4d70bd1c3 100644
--- a/src/java/org/apache/poi/hpsf/Property.java
+++ b/src/java/org/apache/poi/hpsf/Property.java
@@ -100,7 +100,7 @@ public class Property
{
/** <p>Codepage 1200 denotes Unicode.</p> */
- private static final int CP_UNICODE = 1200;
+ public static final int CP_UNICODE = 1200;
/** <p>The property's ID.</p> */
protected long id;
@@ -318,6 +318,10 @@ public class Property
/**
+ * <p>Compares two properties. Please beware that a property with ID == 0 is
+ * a special case: It does not have a type, and its value is the section's
+ * dictionary.</p>
+ *
* @see Object#equals(java.lang.Object)
*/
public boolean equals(final Object o)
@@ -326,13 +330,14 @@ public class Property
return false;
final Property p = (Property) o;
final Object pValue = p.getValue();
- if (id != p.getID() || type != p.getType())
+ final long pId = p.getID();
+ if (id != pId || (id != 0 && type != p.getType()))
return false;
if (value == null && pValue == null)
return true;
if (value == null || pValue == null)
return false;
-
+
/* It's clear now that both values are non-null. */
final Class valueClass = value.getClass();
final Class pValueClass = pValue.getClass();
diff --git a/src/java/org/apache/poi/hpsf/PropertySetFactory.java b/src/java/org/apache/poi/hpsf/PropertySetFactory.java
index 6f6d8e6ed2..e399bceee8 100644
--- a/src/java/org/apache/poi/hpsf/PropertySetFactory.java
+++ b/src/java/org/apache/poi/hpsf/PropertySetFactory.java
@@ -84,8 +84,6 @@ public class PropertySetFactory
* contain a property set.
* @throws MarkUnsupportedException if the stream does not support
* the <code>mark</code> operation.
- * @throws UnexpectedPropertySetTypeException if the property
- * set's type is unexpected.
* @throws IOException if some I/O problem occurs.
*/
public static PropertySet create(final InputStream stream)
diff --git a/src/java/org/apache/poi/hpsf/Section.java b/src/java/org/apache/poi/hpsf/Section.java
index 9a27a3dedc..efe74015c3 100644
--- a/src/java/org/apache/poi/hpsf/Section.java
+++ b/src/java/org/apache/poi/hpsf/Section.java
@@ -93,8 +93,7 @@ public class Section
* section. For example, if the format ID of the first {@link
* Section} contains the bytes specified by
* <code>org.apache.poi.hpsf.wellknown.SectionIDMap.SUMMARY_INFORMATION_ID</code>
- * the section (and thus the property set) is a
- * SummaryInformation.</p>
+ * the section (and thus the property set) is a SummaryInformation.</p>
*
* @return The format ID
*/
@@ -554,4 +553,21 @@ public class Section
return b.toString();
}
+
+
+ /**
+ * <p>Gets the section's dictionary. A dictionary allows an application to
+ * use human-readable property names instead of numeric property IDs. It
+ * contains mappings from property IDs to their associated string
+ * values. The dictionary is stored as the property with ID 0. The codepage
+ * for the strings in the dictionary is defined by property with ID 1.</p>
+ *
+ * @return the dictionary or <code>null</code> if the section does not have
+ * a dictionary.
+ */
+ public Map getDictionary()
+ {
+ return dictionary;
+ }
+
}
diff --git a/src/java/org/apache/poi/hpsf/VariantSupport.java b/src/java/org/apache/poi/hpsf/VariantSupport.java
index 6e9d96c60a..3bc0c39c38 100644
--- a/src/java/org/apache/poi/hpsf/VariantSupport.java
+++ b/src/java/org/apache/poi/hpsf/VariantSupport.java
@@ -252,7 +252,7 @@ public class VariantSupport extends Variant
final int i1 = o1 + (i * 2);
final int i2 = i1 + 1;
final int high = src[i2] << 8;
- final int low = src[i1] & 0xff;
+ final int low = src[i1] & 0x00ff;
final char c = (char) (high | low);
b.append(c);
}
@@ -352,8 +352,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] & 0xff00) >> 8);
- final int low = (int) (s[i] & 0x00ff);
+ final int high = (int) ((s[i] & 0x0000ff00) >> 8);
+ final int low = (int) (s[i] & 0x000000ff);
final byte highb = (byte) high;
final byte lowb = (byte) low;
out.write(lowb);
@@ -386,13 +386,14 @@ public class VariantSupport extends Variant
}
case Variant.VT_I4:
{
- length += TypeWriter.writeToStream(out, ((Long) value).intValue());
+ length += TypeWriter.writeToStream(out,
+ ((Long) value).intValue());
break;
}
case Variant.VT_FILETIME:
{
long filetime = Util.dateToFileTime((Date) value);
- int high = (int) ((filetime >> 32) & 0xFFFFFFFFL);
+ int high = (int) ((filetime >> 32) & 0x00000000FFFFFFFFL);
int low = (int) (filetime & 0x00000000FFFFFFFFL);
length += TypeWriter.writeUIntToStream
(out, 0x0000000FFFFFFFFL & low);
diff --git a/src/java/org/apache/poi/hpsf/wellknown/PropertyIDMap.java b/src/java/org/apache/poi/hpsf/wellknown/PropertyIDMap.java
index 30cb43e825..855e0c94eb 100644
--- a/src/java/org/apache/poi/hpsf/wellknown/PropertyIDMap.java
+++ b/src/java/org/apache/poi/hpsf/wellknown/PropertyIDMap.java
@@ -141,7 +141,7 @@ public class PropertyIDMap extends HashMap
* document</p> */
public static final int PID_APPNAME = 18;
- /** <p>ID of the property that denotes... FIXME (2)</p> */
+ /** <p>FIXME (2): ID of the property that denotes...</p> */
public static final int PID_SECURITY = 19;
diff --git a/src/testcases/org/apache/poi/hpsf/basic/TestBasic.java b/src/testcases/org/apache/poi/hpsf/basic/TestBasic.java
index 5d7ff30e76..4e6d2a2129 100644
--- a/src/testcases/org/apache/poi/hpsf/basic/TestBasic.java
+++ b/src/testcases/org/apache/poi/hpsf/basic/TestBasic.java
@@ -65,7 +65,6 @@ import java.util.List;
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.HPSFException;
import org.apache.poi.hpsf.MarkUnsupportedException;
@@ -288,7 +287,7 @@ public class TestBasic extends TestCase
{
final InputStream in =
new ByteArrayInputStream(psf1[j].getBytes());
- final PropertySet psIn = PropertySetFactory.create(in);
+ PropertySetFactory.create(in);
}
}
}
diff --git a/src/testcases/org/apache/poi/hpsf/basic/TestEmptyProperties.java b/src/testcases/org/apache/poi/hpsf/basic/TestEmptyProperties.java
index 9d8df67d87..7ca404f2db 100644
--- a/src/testcases/org/apache/poi/hpsf/basic/TestEmptyProperties.java
+++ b/src/testcases/org/apache/poi/hpsf/basic/TestEmptyProperties.java
@@ -15,7 +15,6 @@ 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;
/**
* <p>Test case for OLE2 files with empty properties. An empty property's type
diff --git a/src/testcases/org/apache/poi/hpsf/basic/TestWrite.java b/src/testcases/org/apache/poi/hpsf/basic/TestWrite.java
index 75f941d80d..d62378dffd 100644
--- a/src/testcases/org/apache/poi/hpsf/basic/TestWrite.java
+++ b/src/testcases/org/apache/poi/hpsf/basic/TestWrite.java
@@ -66,12 +66,14 @@ import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;
-import java.util.Iterator;
+import java.util.HashMap;
+import java.util.Map;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.apache.poi.hpsf.HPSFRuntimeException;
+import org.apache.poi.hpsf.IllegalPropertySetDataException;
import org.apache.poi.hpsf.MutableProperty;
import org.apache.poi.hpsf.MutablePropertySet;
import org.apache.poi.hpsf.MutableSection;
@@ -570,7 +572,7 @@ public class TestWrite extends TestCase
final InputStream in =
new ByteArrayInputStream(psf1[i].getBytes());
final PropertySet psIn = PropertySetFactory.create(in);
- final MutablePropertySet psOut = copy(psIn);
+ final MutablePropertySet psOut = new MutablePropertySet(psIn);
final ByteArrayOutputStream psStream =
new ByteArrayOutputStream();
psOut.write(psStream);
@@ -602,76 +604,135 @@ public class TestWrite extends TestCase
}
catch (Exception ex)
{
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- Throwable t = ex;
- while (t != null)
- {
- t.printStackTrace(pw);
- if (t instanceof HPSFRuntimeException)
- t = ((HPSFRuntimeException) t).getReason();
- else
- t = null;
- if (t != null)
- pw.println("Caused by:");
- }
- pw.close();
- try
- {
- sw.close();
- }
- catch (IOException ex2)
- {
- ex.printStackTrace();
- }
- String msg = sw.toString();
- fail(msg);
+ handle(ex);
}
}
/**
- * <p>Creates a copy of a {@link PropertySet}.</p>
- *
- * @param ps the property set to copy
- * @return the copy
+ * <p>Tests writing and reading back a proper dictionary.</p>
*/
- private MutablePropertySet copy(final PropertySet ps)
+ public void testDictionary()
{
- MutablePropertySet copy = new MutablePropertySet();
- copy.setByteOrder(ps.getByteOrder());
- copy.setClassID(ps.getClassID());
- copy.setFormat(ps.getFormat());
- copy.setOSVersion(ps.getOSVersion());
- copy.clearSections();
-
- /* Copy the sections. */
- for (final Iterator i1 = ps.getSections().iterator(); i1.hasNext();)
+ try
{
- final Section s1 = (Section) i1.next();
- final MutableSection s2 = new MutableSection();
- s2.setFormatID(s1.getFormatID());
+ final File copy = File.createTempFile("Test-HPSF", "ole2");
+ copy.deleteOnExit();
- /* Copy the properties. */
- final Property[] pa = s1.getProperties();
- for (int i2 = 0; i2 < pa.length; i2++)
- {
- final Property p1 = pa[i2];
- final MutableProperty p2 = new MutableProperty();
- p2.setID(p1.getID());
- p2.setType(p1.getType());
- p2.setValue(p1.getValue());
- s2.setProperty(p2);
- }
- copy.addSection(s2);
+ /* Write: */
+ final OutputStream out = new FileOutputStream(copy);
+ final POIFSFileSystem poiFs = new POIFSFileSystem();
+ final MutablePropertySet ps1 = new MutablePropertySet();
+ final MutableSection s = (MutableSection) ps1.getSections().get(0);
+ final Map m = new HashMap(3, 1.0f);
+ m.put(new Long(1), "String 1");
+ m.put(new Long(2), "String 2");
+ m.put(new Long(3), "String 3");
+ s.setDictionary(m);
+ s.setFormatID(SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID);
+ int codepage = Property.CP_UNICODE;
+ s.setProperty(PropertyIDMap.PID_CODEPAGE, Variant.VT_I2,
+ new Integer(codepage));
+ poiFs.createDocument(ps1.toInputStream(), "Test");
+ poiFs.writeFilesystem(out);
+ out.close();
+
+ /* Read back: */
+ final POIFile[] psf = Util.readPropertySets(copy);
+ Assert.assertEquals(1, psf.length);
+ final byte[] bytes = psf[0].getBytes();
+ final InputStream in = new ByteArrayInputStream(bytes);
+ final PropertySet ps2 = PropertySetFactory.create(in);
+
+ /* Compare the property set stream with the corresponding one
+ * from the origin file and check whether they are equal. */
+ assertEquals(ps1, ps2);
+ }
+ catch (Exception ex)
+ {
+ handle(ex);
+ }
+ }
+
+
+
+ /**
+ * <p>Tests writing and reading back a proper dictionary with an invalid
+ * codepage. (HPSF writes Unicode dictionaries only.)</p>
+ */
+ public void testDictionaryWithInvalidCodepage()
+ {
+ try
+ {
+ final File copy = File.createTempFile("Test-HPSF", "ole2");
+ copy.deleteOnExit();
+
+ /* Write: */
+ final OutputStream out = new FileOutputStream(copy);
+ final POIFSFileSystem poiFs = new POIFSFileSystem();
+ final MutablePropertySet ps1 = new MutablePropertySet();
+ final MutableSection s = (MutableSection) ps1.getSections().get(0);
+ final Map m = new HashMap(3, 1.0f);
+ m.put(new Long(1), "String 1");
+ m.put(new Long(2), "String 2");
+ m.put(new Long(3), "String 3");
+ s.setDictionary(m);
+ s.setFormatID(SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID);
+ int codepage = 12345;
+ s.setProperty(PropertyIDMap.PID_CODEPAGE, Variant.VT_I2,
+ new Integer(codepage));
+ poiFs.createDocument(ps1.toInputStream(), "Test");
+ poiFs.writeFilesystem(out);
+ out.close();
+ fail("This testcase did not detect the invalid codepage value.");
+ }
+ catch (IllegalPropertySetDataException ex)
+ {
+ assertTrue(true);
+ }
+ catch (Exception ex)
+ {
+ handle(ex);
}
- return copy;
}
/**
+ * <p>Handles unexpected exceptions in testcases.</p>
+ *
+ * @param ex The exception that has been thrown.
+ */
+ private void handle(final Exception ex)
+ {
+ final StringWriter sw = new StringWriter();
+ final PrintWriter pw = new PrintWriter(sw);
+ Throwable t = ex;
+ while (t != null)
+ {
+ t.printStackTrace(pw);
+ if (t instanceof HPSFRuntimeException)
+ t = ((HPSFRuntimeException) t).getReason();
+ else
+ t = null;
+ if (t != null)
+ pw.println("Caused by:");
+ }
+ pw.close();
+ try
+ {
+ sw.close();
+ }
+ catch (IOException ex2)
+ {
+ ex.printStackTrace();
+ }
+ fail(sw.toString());
+ }
+
+
+ /**
* <p>Runs the test cases stand-alone.</p>
*/
public static void main(final String[] args) throws Throwable
diff --git a/src/testcases/org/apache/poi/hpsf/data/TestSectionDictionary.doc b/src/testcases/org/apache/poi/hpsf/data/TestSectionDictionary.doc
new file mode 100644
index 0000000000..6114a76572
--- /dev/null
+++ b/src/testcases/org/apache/poi/hpsf/data/TestSectionDictionary.doc
Binary files differ