mirror of
https://github.com/apache/poi.git
synced 2025-02-09 11:34:46 +00:00
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
This commit is contained in:
parent
774387396f
commit
8f08b03cf0
@ -72,7 +72,6 @@ import org.apache.poi.hpsf.MutableSection;
|
|||||||
import org.apache.poi.hpsf.NoPropertySetStreamException;
|
import org.apache.poi.hpsf.NoPropertySetStreamException;
|
||||||
import org.apache.poi.hpsf.PropertySet;
|
import org.apache.poi.hpsf.PropertySet;
|
||||||
import org.apache.poi.hpsf.PropertySetFactory;
|
import org.apache.poi.hpsf.PropertySetFactory;
|
||||||
import org.apache.poi.hpsf.UnexpectedPropertySetTypeException;
|
|
||||||
import org.apache.poi.hpsf.Util;
|
import org.apache.poi.hpsf.Util;
|
||||||
import org.apache.poi.hpsf.Variant;
|
import org.apache.poi.hpsf.Variant;
|
||||||
import org.apache.poi.hpsf.WritingNotSupportedException;
|
import org.apache.poi.hpsf.WritingNotSupportedException;
|
||||||
|
@ -54,11 +54,19 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.poi.hpsf.examples;
|
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.MutableProperty;
|
||||||
import org.apache.poi.hpsf.wellknown.*;
|
import org.apache.poi.hpsf.MutablePropertySet;
|
||||||
import org.apache.poi.poifs.filesystem.*;
|
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
|
* <p>This class is a simple sample application showing how to create a property
|
||||||
|
@ -66,7 +66,7 @@ package org.apache.poi.hpsf;
|
|||||||
* @version $Id$
|
* @version $Id$
|
||||||
* @since 2002-05-26
|
* @since 2002-05-26
|
||||||
*/
|
*/
|
||||||
public class IllegalPropertySetDataException extends HPSFRuntimeException
|
public class IllegalPropertySetDataException extends HPSFRuntimeException
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -106,6 +106,7 @@ public class MutablePropertySet extends PropertySet
|
|||||||
* one section it is added right here. */
|
* one section it is added right here. */
|
||||||
sections = new LinkedList();
|
sections = new LinkedList();
|
||||||
sections.add(new MutableSection());
|
sections.add(new MutableSection());
|
||||||
|
sectionCount = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -123,7 +124,7 @@ public class MutablePropertySet extends PropertySet
|
|||||||
byteOrder = ps.getByteOrder();
|
byteOrder = ps.getByteOrder();
|
||||||
format = ps.getFormat();
|
format = ps.getFormat();
|
||||||
osVersion = ps.getOSVersion();
|
osVersion = ps.getOSVersion();
|
||||||
classID = new ClassID(ps.getClassID().getBytes(), 0);
|
setClassID(ps.getClassID());
|
||||||
clearSections();
|
clearSections();
|
||||||
for (final Iterator i = ps.getSections().iterator(); i.hasNext();)
|
for (final Iterator i = ps.getSections().iterator(); i.hasNext();)
|
||||||
{
|
{
|
||||||
|
@ -60,7 +60,9 @@ import java.io.OutputStream;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.poi.hpsf.wellknown.PropertyIDMap;
|
||||||
import org.apache.poi.util.LittleEndian;
|
import org.apache.poi.util.LittleEndian;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -129,7 +131,7 @@ public class MutableSection extends Section
|
|||||||
for (int i = 0; i < pa.length; i++)
|
for (int i = 0; i < pa.length; i++)
|
||||||
mpa[i] = new MutableProperty(pa[i]);
|
mpa[i] = new MutableProperty(pa[i]);
|
||||||
setProperties(mpa);
|
setProperties(mpa);
|
||||||
dictionary = s.dictionary;
|
setDictionary(s.getDictionary());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -247,13 +249,27 @@ public class MutableSection extends Section
|
|||||||
public void setProperty(final Property p)
|
public void setProperty(final Property p)
|
||||||
{
|
{
|
||||||
final long id = p.getID();
|
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();)
|
for (final Iterator i = preprops.iterator(); i.hasNext();)
|
||||||
if (((Property) i.next()).getID() == id)
|
if (((Property) i.next()).getID() == id)
|
||||||
{
|
{
|
||||||
i.remove();
|
i.remove();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
preprops.add(p);
|
|
||||||
dirty = true;
|
dirty = true;
|
||||||
propertyCount = preprops.size();
|
propertyCount = preprops.size();
|
||||||
}
|
}
|
||||||
@ -292,6 +308,10 @@ public class MutableSection extends Section
|
|||||||
size = calcSize();
|
size = calcSize();
|
||||||
dirty = false;
|
dirty = false;
|
||||||
}
|
}
|
||||||
|
catch (HPSFRuntimeException ex)
|
||||||
|
{
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
throw new HPSFRuntimeException(ex);
|
throw new HPSFRuntimeException(ex);
|
||||||
@ -365,19 +385,55 @@ public class MutableSection extends Section
|
|||||||
position += 2 * LittleEndian.INT_SIZE +
|
position += 2 * LittleEndian.INT_SIZE +
|
||||||
getPropertyCount() * 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
|
/* Write the properties and the property list into their respective
|
||||||
* streams: */
|
* streams: */
|
||||||
for (final Iterator i = preprops.iterator(); i.hasNext();)
|
for (final Iterator i = preprops.iterator(); i.hasNext();)
|
||||||
{
|
{
|
||||||
final MutableProperty p = (MutableProperty) i.next();
|
final MutableProperty p = (MutableProperty) i.next();
|
||||||
|
final long id = p.getID();
|
||||||
|
|
||||||
/* Write the property list entry. */
|
/* Write the property list entry. */
|
||||||
TypeWriter.writeUIntToStream(propertyListStream, p.getID());
|
TypeWriter.writeUIntToStream(propertyListStream, p.getID());
|
||||||
TypeWriter.writeUIntToStream(propertyListStream, position);
|
TypeWriter.writeUIntToStream(propertyListStream, position);
|
||||||
|
|
||||||
/* Write the property and update the position to the next
|
/* If the property ID is not equal 0 we write the property and all
|
||||||
* property. */
|
* is fine. However, if it equals 0 we have to write the section's
|
||||||
position += p.write(propertyStream);
|
* 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();
|
propertyStream.close();
|
||||||
propertyListStream.close();
|
propertyListStream.close();
|
||||||
@ -405,6 +461,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:
|
* <p>Overwrites the super class' method to cope with a redundancy:
|
||||||
* the property count is maintained in a separate member variable, but
|
* the property count is maintained in a separate member variable, but
|
||||||
@ -426,7 +528,77 @@ public class MutableSection extends Section
|
|||||||
*/
|
*/
|
||||||
public Property[] getProperties()
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ public class Property
|
|||||||
{
|
{
|
||||||
|
|
||||||
/** <p>Codepage 1200 denotes Unicode.</p> */
|
/** <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> */
|
/** <p>The property's ID.</p> */
|
||||||
protected long id;
|
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)
|
* @see Object#equals(java.lang.Object)
|
||||||
*/
|
*/
|
||||||
public boolean equals(final Object o)
|
public boolean equals(final Object o)
|
||||||
@ -326,13 +330,14 @@ public class Property
|
|||||||
return false;
|
return false;
|
||||||
final Property p = (Property) o;
|
final Property p = (Property) o;
|
||||||
final Object pValue = p.getValue();
|
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;
|
return false;
|
||||||
if (value == null && pValue == null)
|
if (value == null && pValue == null)
|
||||||
return true;
|
return true;
|
||||||
if (value == null || pValue == null)
|
if (value == null || pValue == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* It's clear now that both values are non-null. */
|
/* It's clear now that both values are non-null. */
|
||||||
final Class valueClass = value.getClass();
|
final Class valueClass = value.getClass();
|
||||||
final Class pValueClass = pValue.getClass();
|
final Class pValueClass = pValue.getClass();
|
||||||
|
@ -84,8 +84,6 @@ public class PropertySetFactory
|
|||||||
* contain a property set.
|
* contain a property set.
|
||||||
* @throws MarkUnsupportedException if the stream does not support
|
* @throws MarkUnsupportedException if the stream does not support
|
||||||
* the <code>mark</code> operation.
|
* the <code>mark</code> operation.
|
||||||
* @throws UnexpectedPropertySetTypeException if the property
|
|
||||||
* set's type is unexpected.
|
|
||||||
* @throws IOException if some I/O problem occurs.
|
* @throws IOException if some I/O problem occurs.
|
||||||
*/
|
*/
|
||||||
public static PropertySet create(final InputStream stream)
|
public static PropertySet create(final InputStream stream)
|
||||||
|
@ -93,8 +93,7 @@ public class Section
|
|||||||
* section. For example, if the format ID of the first {@link
|
* section. For example, if the format ID of the first {@link
|
||||||
* Section} contains the bytes specified by
|
* Section} contains the bytes specified by
|
||||||
* <code>org.apache.poi.hpsf.wellknown.SectionIDMap.SUMMARY_INFORMATION_ID</code>
|
* <code>org.apache.poi.hpsf.wellknown.SectionIDMap.SUMMARY_INFORMATION_ID</code>
|
||||||
* the section (and thus the property set) is a
|
* the section (and thus the property set) is a SummaryInformation.</p>
|
||||||
* SummaryInformation.</p>
|
|
||||||
*
|
*
|
||||||
* @return The format ID
|
* @return The format ID
|
||||||
*/
|
*/
|
||||||
@ -554,4 +553,21 @@ public class Section
|
|||||||
return b.toString();
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -252,7 +252,7 @@ public class VariantSupport extends Variant
|
|||||||
final int i1 = o1 + (i * 2);
|
final int i1 = o1 + (i * 2);
|
||||||
final int i2 = i1 + 1;
|
final int i2 = i1 + 1;
|
||||||
final int high = src[i2] << 8;
|
final int high = src[i2] << 8;
|
||||||
final int low = src[i1] & 0xff;
|
final int low = src[i1] & 0x00ff;
|
||||||
final char c = (char) (high | low);
|
final char c = (char) (high | low);
|
||||||
b.append(c);
|
b.append(c);
|
||||||
}
|
}
|
||||||
@ -352,8 +352,8 @@ public class VariantSupport extends Variant
|
|||||||
char[] s = Util.pad4((String) value);
|
char[] s = Util.pad4((String) value);
|
||||||
for (int i = 0; i < s.length; i++)
|
for (int i = 0; i < s.length; i++)
|
||||||
{
|
{
|
||||||
final int high = (int) ((s[i] & 0xff00) >> 8);
|
final int high = (int) ((s[i] & 0x0000ff00) >> 8);
|
||||||
final int low = (int) (s[i] & 0x00ff);
|
final int low = (int) (s[i] & 0x000000ff);
|
||||||
final byte highb = (byte) high;
|
final byte highb = (byte) high;
|
||||||
final byte lowb = (byte) low;
|
final byte lowb = (byte) low;
|
||||||
out.write(lowb);
|
out.write(lowb);
|
||||||
@ -386,13 +386,14 @@ public class VariantSupport extends Variant
|
|||||||
}
|
}
|
||||||
case Variant.VT_I4:
|
case Variant.VT_I4:
|
||||||
{
|
{
|
||||||
length += TypeWriter.writeToStream(out, ((Long) value).intValue());
|
length += TypeWriter.writeToStream(out,
|
||||||
|
((Long) value).intValue());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Variant.VT_FILETIME:
|
case Variant.VT_FILETIME:
|
||||||
{
|
{
|
||||||
long filetime = Util.dateToFileTime((Date) value);
|
long filetime = Util.dateToFileTime((Date) value);
|
||||||
int high = (int) ((filetime >> 32) & 0xFFFFFFFFL);
|
int high = (int) ((filetime >> 32) & 0x00000000FFFFFFFFL);
|
||||||
int low = (int) (filetime & 0x00000000FFFFFFFFL);
|
int low = (int) (filetime & 0x00000000FFFFFFFFL);
|
||||||
length += TypeWriter.writeUIntToStream
|
length += TypeWriter.writeUIntToStream
|
||||||
(out, 0x0000000FFFFFFFFL & low);
|
(out, 0x0000000FFFFFFFFL & low);
|
||||||
|
@ -141,7 +141,7 @@ public class PropertyIDMap extends HashMap
|
|||||||
* document</p> */
|
* document</p> */
|
||||||
public static final int PID_APPNAME = 18;
|
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;
|
public static final int PID_SECURITY = 19;
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,7 +65,6 @@ import java.util.List;
|
|||||||
import junit.framework.Assert;
|
import junit.framework.Assert;
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import org.apache.poi.hpsf.ClassID;
|
|
||||||
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
||||||
import org.apache.poi.hpsf.HPSFException;
|
import org.apache.poi.hpsf.HPSFException;
|
||||||
import org.apache.poi.hpsf.MarkUnsupportedException;
|
import org.apache.poi.hpsf.MarkUnsupportedException;
|
||||||
@ -288,7 +287,7 @@ public class TestBasic extends TestCase
|
|||||||
{
|
{
|
||||||
final InputStream in =
|
final InputStream in =
|
||||||
new ByteArrayInputStream(psf1[j].getBytes());
|
new ByteArrayInputStream(psf1[j].getBytes());
|
||||||
final PropertySet psIn = PropertySetFactory.create(in);
|
PropertySetFactory.create(in);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,6 @@ import org.apache.poi.hpsf.NoPropertySetStreamException;
|
|||||||
import org.apache.poi.hpsf.PropertySet;
|
import org.apache.poi.hpsf.PropertySet;
|
||||||
import org.apache.poi.hpsf.PropertySetFactory;
|
import org.apache.poi.hpsf.PropertySetFactory;
|
||||||
import org.apache.poi.hpsf.SummaryInformation;
|
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
|
* <p>Test case for OLE2 files with empty properties. An empty property's type
|
||||||
|
@ -66,12 +66,14 @@ import java.io.OutputStream;
|
|||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Iterator;
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import junit.framework.Assert;
|
import junit.framework.Assert;
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import org.apache.poi.hpsf.HPSFRuntimeException;
|
import org.apache.poi.hpsf.HPSFRuntimeException;
|
||||||
|
import org.apache.poi.hpsf.IllegalPropertySetDataException;
|
||||||
import org.apache.poi.hpsf.MutableProperty;
|
import org.apache.poi.hpsf.MutableProperty;
|
||||||
import org.apache.poi.hpsf.MutablePropertySet;
|
import org.apache.poi.hpsf.MutablePropertySet;
|
||||||
import org.apache.poi.hpsf.MutableSection;
|
import org.apache.poi.hpsf.MutableSection;
|
||||||
@ -570,7 +572,7 @@ public class TestWrite extends TestCase
|
|||||||
final InputStream in =
|
final InputStream in =
|
||||||
new ByteArrayInputStream(psf1[i].getBytes());
|
new ByteArrayInputStream(psf1[i].getBytes());
|
||||||
final PropertySet psIn = PropertySetFactory.create(in);
|
final PropertySet psIn = PropertySetFactory.create(in);
|
||||||
final MutablePropertySet psOut = copy(psIn);
|
final MutablePropertySet psOut = new MutablePropertySet(psIn);
|
||||||
final ByteArrayOutputStream psStream =
|
final ByteArrayOutputStream psStream =
|
||||||
new ByteArrayOutputStream();
|
new ByteArrayOutputStream();
|
||||||
psOut.write(psStream);
|
psOut.write(psStream);
|
||||||
@ -602,75 +604,134 @@ public class TestWrite extends TestCase
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
StringWriter sw = new StringWriter();
|
handle(ex);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Creates a copy of a {@link PropertySet}.</p>
|
* <p>Tests writing and reading back a proper dictionary.</p>
|
||||||
*
|
|
||||||
* @param ps the property set to copy
|
|
||||||
* @return the copy
|
|
||||||
*/
|
*/
|
||||||
private MutablePropertySet copy(final PropertySet ps)
|
public void testDictionary()
|
||||||
{
|
{
|
||||||
MutablePropertySet copy = new MutablePropertySet();
|
try
|
||||||
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();)
|
|
||||||
{
|
{
|
||||||
final Section s1 = (Section) i1.next();
|
final File copy = File.createTempFile("Test-HPSF", "ole2");
|
||||||
final MutableSection s2 = new MutableSection();
|
copy.deleteOnExit();
|
||||||
s2.setFormatID(s1.getFormatID());
|
|
||||||
|
|
||||||
/* Copy the properties. */
|
/* Write: */
|
||||||
final Property[] pa = s1.getProperties();
|
final OutputStream out = new FileOutputStream(copy);
|
||||||
for (int i2 = 0; i2 < pa.length; i2++)
|
final POIFSFileSystem poiFs = new POIFSFileSystem();
|
||||||
{
|
final MutablePropertySet ps1 = new MutablePropertySet();
|
||||||
final Property p1 = pa[i2];
|
final MutableSection s = (MutableSection) ps1.getSections().get(0);
|
||||||
final MutableProperty p2 = new MutableProperty();
|
final Map m = new HashMap(3, 1.0f);
|
||||||
p2.setID(p1.getID());
|
m.put(new Long(1), "String 1");
|
||||||
p2.setType(p1.getType());
|
m.put(new Long(2), "String 2");
|
||||||
p2.setValue(p1.getValue());
|
m.put(new Long(3), "String 3");
|
||||||
s2.setProperty(p2);
|
s.setDictionary(m);
|
||||||
}
|
s.setFormatID(SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID);
|
||||||
copy.addSection(s2);
|
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);
|
||||||
}
|
}
|
||||||
return copy;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <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>
|
* <p>Runs the test cases stand-alone.</p>
|
||||||
*/
|
*/
|
||||||
|
BIN
src/testcases/org/apache/poi/hpsf/data/TestSectionDictionary.doc
Normal file
BIN
src/testcases/org/apache/poi/hpsf/data/TestSectionDictionary.doc
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user