- Fix: HPSF now ensures that string properties are always written with the type Variant.VT_LPWSTR instead of Variant.VT_LPSTR if the codepage is 1200 (Unicode).

- Code cleanup (propertyCount in MutableSection removed).
- Codepage numbers aggregated in the new class org.apache.poi.hpsf.Constants.


git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@353561 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Rainer Klute 2004-06-22 16:11:39 +00:00
parent efa4e1efb2
commit 3073474f48
12 changed files with 217 additions and 79 deletions

View File

@ -0,0 +1,26 @@
package org.apache.poi.hpsf;
/**
* <p>Defines constants of general use.</p>
*
* @author Rainer Klute <a
* href="mailto:klute@rainer-klute.de">&lt;klute@rainer-klute.de&gt;</a>
* @since 2004-06-20
* @version $Id$
*/
public class Constants
{
/** <p>Codepage for SJIS</p> */
public static final int CP_SJIS = 932;
/** <p>Codepage for UTF-16</p> */
public static final int CP_UTF16 = 1200;
/** <p>Codepage for UTF-8</p> */
public static final int CP_UTF8 = 65001;
/** <p>Codepage for Unicode</p> */
public static final int CP_UNICODE = CP_UTF16;
}

View File

@ -0,0 +1,60 @@
/* ====================================================================
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.
==================================================================== */
package org.apache.poi.hpsf;
import org.apache.poi.util.HexDump;
/**
* <p>This exception is thrown if HPSF encounters a variant type that is illegal
* in the current context.</p>
*
* @author Rainer Klute <a
* href="mailto:klute@rainer-klute.de">&lt;klute@rainer-klute.de&gt;</a>
* @since 2004-06-21
* @version $Id$
*/
public class IllegalVariantTypeException extends VariantTypeException
{
/**
* <p>Constructor</p>
*
* @param variantType The unsupported variant type
* @param value The value
* @param msg A message string
*/
public IllegalVariantTypeException(final long variantType,
final Object value, final String msg)
{
super(variantType, value, msg);
}
/**
* <p>Constructor</p>
*
* @param variantType The unsupported variant type
* @param value The value
*/
public IllegalVariantTypeException(final long variantType,
final Object value)
{
this(variantType, value, "The variant type " + variantType + " (" +
Variant.getVariantName(variantType) + ", " +
HexDump.toHex(variantType) + ") is illegal in this context.");
}
}

View File

@ -1,4 +1,3 @@
/* ==================================================================== /* ====================================================================
Copyright 2002-2004 Apache Software Foundation Copyright 2002-2004 Apache Software Foundation
@ -22,7 +21,7 @@ import java.io.OutputStream;
/** /**
* <p>Adds writing capability to the {@link Property} class.</p> * <p>Adds writing capability to the {@link Property} class.</p>
* *
* <p>Please be aware that this class' functionality will be merged into the * <p>Please be aware that this class' functionality will be merged into the
* {@link Property} class at a later time, so the API will change.</p> * {@link Property} class at a later time, so the API will change.</p>
* *
@ -46,7 +45,7 @@ public class MutableProperty extends Property
/** /**
* <p>Creates a <code>MutableProperty</code> as a copy of an existing * <p>Creates a <code>MutableProperty</code> as a copy of an existing
* <code>Property</code>.</p> * <code>Property</code>.</p>
* *
* @param p The property to copy. * @param p The property to copy.
*/ */
public MutableProperty(final Property p) public MutableProperty(final Property p)
@ -95,11 +94,11 @@ public class MutableProperty extends Property
/** /**
* <p>Writes the property to an output stream.</p> * <p>Writes the property to an output stream.</p>
* *
* @param out The output stream to write to. * @param out The output stream to write to.
* @param codepage The codepage to use for writing non-wide strings * @param codepage The codepage to use for writing non-wide strings
* @return the number of bytes written to the stream * @return the number of bytes written to the stream
* *
* @exception IOException if an I/O error occurs * @exception IOException if an I/O error occurs
* @exception WritingNotSupportedException if a variant type is to be * @exception WritingNotSupportedException if a variant type is to be
* written that is not yet supported * written that is not yet supported

View File

@ -144,7 +144,6 @@ public class MutableSection extends Section
for (int i = 0; i < properties.length; i++) for (int i = 0; i < properties.length; i++)
preprops.add(properties[i]); preprops.add(properties[i]);
dirty = true; dirty = true;
propertyCount = properties.length;
} }
@ -217,7 +216,6 @@ public class MutableSection extends Section
removeProperty(id); removeProperty(id);
preprops.add(p); preprops.add(p);
dirty = true; dirty = true;
propertyCount = preprops.size();
} }
@ -236,7 +234,6 @@ public class MutableSection extends Section
break; break;
} }
dirty = true; dirty = true;
propertyCount = preprops.size();
} }
@ -362,7 +359,7 @@ public class MutableSection extends Section
throw new IllegalPropertySetDataException throw new IllegalPropertySetDataException
("The codepage property (ID = 1) must be an " + ("The codepage property (ID = 1) must be an " +
"Integer object."); "Integer object.");
else if (((Integer) p1).intValue() != Property.CP_UNICODE) else if (((Integer) p1).intValue() != Constants.CP_UNICODE)
throw new IllegalPropertySetDataException throw new IllegalPropertySetDataException
("The codepage property (ID = 1) must be " + ("The codepage property (ID = 1) must be " +
"1200 (Unicode)."); "1200 (Unicode).");
@ -574,7 +571,7 @@ public class MutableSection extends Section
* dictionary. HPSF always writes Unicode strings to the * dictionary. HPSF always writes Unicode strings to the
* dictionary. */ * dictionary. */
setProperty(PropertyIDMap.PID_CODEPAGE, Variant.VT_I2, setProperty(PropertyIDMap.PID_CODEPAGE, Variant.VT_I2,
new Integer(Property.CP_UNICODE)); new Integer(Constants.CP_UNICODE));
} }
else else
/* Setting the dictionary to null means to remove property 0. /* Setting the dictionary to null means to remove property 0.

View File

@ -56,9 +56,6 @@ import org.apache.poi.util.LittleEndian;
public class Property public class Property
{ {
/** <p>Codepage 1200 denotes Unicode.</p> */
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;
@ -118,9 +115,8 @@ public class Property
* @param length The property's type/value pair's length in bytes. * @param length The property's type/value pair's length in bytes.
* @param codepage The section's and thus the property's * @param codepage The section's and thus the property's
* codepage. It is needed only when reading string values. * codepage. It is needed only when reading string values.
*
* @exception UnsupportedEncodingException if the specified codepage is not * @exception UnsupportedEncodingException if the specified codepage is not
* supported * supported.
*/ */
public Property(final long id, final byte[] src, final long offset, public Property(final long id, final byte[] src, final long offset,
final int length, final int codepage) final int length, final int codepage)
@ -210,7 +206,7 @@ public class Property
* character set is Unicode or not. */ * character set is Unicode or not. */
StringBuffer b = new StringBuffer((int) sLength); StringBuffer b = new StringBuffer((int) sLength);
for (int j = 0; j < sLength; j++) for (int j = 0; j < sLength; j++)
if (codepage == CP_UNICODE) if (codepage == Constants.CP_UNICODE)
{ {
final int i1 = o + (j * 2); final int i1 = o + (j * 2);
final int i2 = i1 + 1; final int i2 = i1 + 1;
@ -222,7 +218,7 @@ public class Property
/* Strip 0x00 characters from the end of the string: */ /* Strip 0x00 characters from the end of the string: */
while (b.length() > 0 && b.charAt(b.length() - 1) == 0x00) while (b.length() > 0 && b.charAt(b.length() - 1) == 0x00)
b.setLength(b.length() - 1); b.setLength(b.length() - 1);
if (codepage == CP_UNICODE) if (codepage == Constants.CP_UNICODE)
{ {
if (sLength % 2 == 1) if (sLength % 2 == 1)
sLength++; sLength++;

View File

@ -233,11 +233,13 @@ public class PropertySet
* @throws IOException if the {@link InputStream} cannot not be * @throws IOException if the {@link InputStream} cannot not be
* accessed as needed. * accessed as needed.
* @exception NoPropertySetStreamException if the input stream does not * @exception NoPropertySetStreamException if the input stream does not
* contain a property set * contain a property set.
* @exception UnsupportedEncodingException if a character encoding is not
* supported.
*/ */
public PropertySet(final InputStream stream) public PropertySet(final InputStream stream)
throws NoPropertySetStreamException, MarkUnsupportedException, throws NoPropertySetStreamException, MarkUnsupportedException,
IOException IOException, UnsupportedEncodingException
{ {
if (isPropertySetStream(stream)) if (isPropertySetStream(stream))
{ {
@ -265,7 +267,7 @@ public class PropertySet
* @throws NoPropertySetStreamException if the byte array is not a * @throws NoPropertySetStreamException if the byte array is not a
* property set stream. * property set stream.
* *
* @exception UnsupportedEncodingException if the codepage is not supported * @exception UnsupportedEncodingException if the codepage is not supported.
*/ */
public PropertySet(final byte[] stream, final int offset, final int length) public PropertySet(final byte[] stream, final int offset, final int length)
throws NoPropertySetStreamException, UnsupportedEncodingException throws NoPropertySetStreamException, UnsupportedEncodingException
@ -288,7 +290,7 @@ public class PropertySet
* @throws NoPropertySetStreamException if the byte array is not a * @throws NoPropertySetStreamException if the byte array is not a
* property set stream. * property set stream.
* *
* @exception UnsupportedEncodingException if the codepage is not supported * @exception UnsupportedEncodingException if the codepage is not supported.
*/ */
public PropertySet(final byte[] stream) public PropertySet(final byte[] stream)
throws NoPropertySetStreamException, UnsupportedEncodingException throws NoPropertySetStreamException, UnsupportedEncodingException

View File

@ -19,6 +19,7 @@ package org.apache.poi.hpsf;
import java.io.InputStream; import java.io.InputStream;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.rmi.UnexpectedException; import java.rmi.UnexpectedException;
/** /**
@ -48,10 +49,12 @@ public class PropertySetFactory
* @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 IOException if some I/O problem occurs. * @throws IOException if some I/O problem occurs.
* @exception UnsupportedEncodingException if the specified codepage is not
* supported.
*/ */
public static PropertySet create(final InputStream stream) public static PropertySet create(final InputStream stream)
throws NoPropertySetStreamException, MarkUnsupportedException, throws NoPropertySetStreamException, MarkUnsupportedException,
IOException UnsupportedEncodingException, IOException
{ {
final PropertySet ps = new PropertySet(stream); final PropertySet ps = new PropertySet(stream);
try try

View File

@ -104,15 +104,6 @@ public class Section
/**
* FIXME (2): Get rid of this! The property count is implicitly available as
* the length of the "properties" array.
*
* @see #getPropertyCount
*/
protected int propertyCount;
/** /**
* <p>Returns the number of properties in this section.</p> * <p>Returns the number of properties in this section.</p>
* *
@ -120,7 +111,7 @@ public class Section
*/ */
public int getPropertyCount() public int getPropertyCount()
{ {
return propertyCount; return properties.length;
} }
@ -188,7 +179,7 @@ public class Section
/* /*
* Read the number of properties. * Read the number of properties.
*/ */
propertyCount = (int) LittleEndian.getUInt(src, o1); final int propertyCount = (int) LittleEndian.getUInt(src, o1);
o1 += LittleEndian.INT_SIZE; o1 += LittleEndian.INT_SIZE;
/* /*

View File

@ -1,4 +1,3 @@
/* ==================================================================== /* ====================================================================
Copyright 2002-2004 Apache Software Foundation Copyright 2002-2004 Apache Software Foundation
@ -31,15 +30,10 @@ import org.apache.poi.util.HexDump;
* @since 2003-08-05 * @since 2003-08-05
* @version $Id$ * @version $Id$
*/ */
public abstract class UnsupportedVariantTypeException extends HPSFException public abstract class UnsupportedVariantTypeException
extends VariantTypeException
{ {
private Object value;
private long variantType;
/** /**
* <p>Constructor.</p> * <p>Constructor.</p>
* *
@ -49,38 +43,15 @@ public abstract class UnsupportedVariantTypeException extends HPSFException
public UnsupportedVariantTypeException(final long variantType, public UnsupportedVariantTypeException(final long variantType,
final Object value) final Object value)
{ {
super("HPSF does not yet support the variant type " + variantType + super(variantType, value,
"HPSF does not yet support the variant type " + variantType +
" (" + Variant.getVariantName(variantType) + ", " + " (" + Variant.getVariantName(variantType) + ", " +
HexDump.toHex(variantType) + "). If you want support for " + HexDump.toHex(variantType) + "). If you want support for " +
"this variant type in one of the next POI releases please " + "this variant type in one of the next POI releases please " +
"submit a request for enhancement (RFE) to " + "submit a request for enhancement (RFE) to " +
"<http://nagoya.apache.org/bugzilla/>! Thank you!"); "<http://nagoya.apache.org/bugzilla/>! Thank you!");
this.variantType = variantType;
this.value = value;
} }
/**
* <p>Returns the offending variant type.</p>
*
* @return the offending variant type.
*/
public long getVariantType()
{
return variantType;
}
/**
* <p>Return the value who's variant type is not yet supported.</p>
*
* @return the value who's variant type is not yet supported
*/
public Object getValue()
{
return value;
}
} }

View File

@ -1,4 +1,3 @@
/* ==================================================================== /* ====================================================================
Copyright 2002-2004 Apache Software Foundation Copyright 2002-2004 Apache Software Foundation
@ -14,7 +13,7 @@
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
package org.apache.poi.hpsf; package org.apache.poi.hpsf;
import java.io.IOException; import java.io.IOException;
@ -41,7 +40,7 @@ import org.apache.poi.util.LittleEndianConsts;
* <li><p>Reading reads from a byte array while writing writes to an byte array * <li><p>Reading reads from a byte array while writing writes to an byte array
* output stream.</p></li> * output stream.</p></li>
* *
* <ul> * </ul>
* *
* @author Rainer Klute <a * @author Rainer Klute <a
* href="mailto:klute@rainer-klute.de">&lt;klute@rainer-klute.de&gt;</a> * href="mailto:klute@rainer-klute.de">&lt;klute@rainer-klute.de&gt;</a>
@ -126,19 +125,26 @@ public class VariantSupport extends Variant
* @exception ReadingNotSupportedException if a property is to be written * @exception ReadingNotSupportedException if a property is to be written
* who's variant type HPSF does not yet support * who's variant type HPSF does not yet support
* @exception UnsupportedEncodingException if the specified codepage is not * @exception UnsupportedEncodingException if the specified codepage is not
* supported * supported.
* *
* @see Variant * @see Variant
*/ */
public static Object read(final byte[] src, final int offset, public static Object read(final byte[] src, final int offset,
final int length, final long type, final int length, final long type,
final int codepage) final int codepage)
throws ReadingNotSupportedException, UnsupportedEncodingException throws ReadingNotSupportedException, UnsupportedEncodingException
{ {
Object value; Object value;
int o1 = offset; int o1 = offset;
int l1 = length - LittleEndian.INT_SIZE; int l1 = length - LittleEndian.INT_SIZE;
switch ((int) type) long lType = type;
/* Instead of trying to read 8-bit characters from a Unicode string,
* read 16-bit characters. */
if (codepage == Constants.CP_UNICODE && type == Variant.VT_LPSTR)
lType = Variant.VT_LPWSTR;
switch ((int) lType)
{ {
case Variant.VT_EMPTY: case Variant.VT_EMPTY:
{ {
@ -279,11 +285,11 @@ public class VariantSupport extends Variant
("Codepage number may not be " + codepage); ("Codepage number may not be " + codepage);
switch (codepage) switch (codepage)
{ {
case 932: case Constants.CP_SJIS:
return "SJIS"; return "SJIS";
case 1200: case Constants.CP_UTF16:
return "UTF-16"; return "UTF-16";
case 65001: case Constants.CP_UTF8:
return "UTF-8"; return "UTF-8";
default: default:
return "cp" + codepage; return "cp" + codepage;
@ -295,6 +301,11 @@ public class VariantSupport extends Variant
* <p>Writes a variant value to an output stream. This method ensures that * <p>Writes a variant value to an output stream. This method ensures that
* always a multiple of 4 bytes is written.</p> * always a multiple of 4 bytes is written.</p>
* *
* <p>If the codepage is UTF-16, which is encouraged, strings
* <strong>must</strong> always be written as {@link Variant#VT_LPWSTR}
* strings, not as {@link Variant#VT_LPSTR} strings. This method ensure this
* by converting strings appropriately, if needed.</p>
*
* @param out The stream to write the value to. * @param out The stream to write the value to.
* @param type The variant's type. * @param type The variant's type.
* @param value The variant's value. * @param value The variant's value.
@ -309,8 +320,14 @@ public class VariantSupport extends Variant
final Object value, final int codepage) final Object value, final int codepage)
throws IOException, WritingNotSupportedException throws IOException, WritingNotSupportedException
{ {
long lType = type;
/* Ensure that wide strings are written if the codepage is Unicode. */
if (codepage == Constants.CP_UNICODE && type == Variant.VT_LPSTR)
lType = Variant.VT_LPWSTR;
int length = 0; int length = 0;
switch ((int) type) switch ((int) lType)
{ {
case Variant.VT_BOOL: case Variant.VT_BOOL:
{ {
@ -402,10 +419,10 @@ public class VariantSupport extends Variant
out.write(b); out.write(b);
length = b.length; length = b.length;
writeUnsupportedTypeMessage writeUnsupportedTypeMessage
(new WritingNotSupportedException(type, value)); (new WritingNotSupportedException(lType, value));
} }
else else
throw new WritingNotSupportedException(type, value); throw new WritingNotSupportedException(lType, value);
break; break;
} }
} }

View File

@ -0,0 +1,76 @@
/* ====================================================================
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.
==================================================================== */
package org.apache.poi.hpsf;
/**
* <p>This exception is thrown if HPSF encounters a problem with a variant type.
* Concrete subclasses specifiy the problem further.</p>
*
* @author Rainer Klute <a
* href="mailto:klute@rainer-klute.de">&lt;klute@rainer-klute.de&gt;</a>
* @since 2004-06-21
* @version $Id$
*/
public abstract class VariantTypeException extends HPSFException
{
private Object value;
private long variantType;
/**
* <p>Constructor.</p>
*
* @param variantType The variant type causing the problem
* @param value The value who's variant type causes the problem
* @param msg A message text describing the problem
*/
public VariantTypeException(final long variantType, final Object value,
final String msg)
{
super(msg);
this.variantType = variantType;
this.value = value;
}
/**
* <p>Returns the offending variant type.</p>
*
* @return the offending variant type.
*/
public long getVariantType()
{
return variantType;
}
/**
* <p>Returns the value who's variant type caused the problem.</p>
*
* @return the value who's variant type caused the problem
*/
public Object getValue()
{
return value;
}
}

View File

@ -36,7 +36,7 @@ public class WritingNotSupportedException
/** /**
* <p>Constructor</p> * <p>Constructor</p>
* *
* @param variantType The unsupported varian type. * @param variantType The unsupported variant type.
* @param value The value. * @param value The value.
*/ */
public WritingNotSupportedException(final long variantType, public WritingNotSupportedException(final long variantType,