From 3073474f487f99f580c9693b3b193e08c6f4f430 Mon Sep 17 00:00:00 2001 From: Rainer Klute Date: Tue, 22 Jun 2004 16:11:39 +0000 Subject: [PATCH] - 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 --- src/java/org/apache/poi/hpsf/Constants.java | 26 +++++++ .../poi/hpsf/IllegalVariantTypeException.java | 60 +++++++++++++++ .../org/apache/poi/hpsf/MutableProperty.java | 9 +-- .../org/apache/poi/hpsf/MutableSection.java | 7 +- src/java/org/apache/poi/hpsf/Property.java | 10 +-- src/java/org/apache/poi/hpsf/PropertySet.java | 10 ++- .../apache/poi/hpsf/PropertySetFactory.java | 5 +- src/java/org/apache/poi/hpsf/Section.java | 13 +--- .../hpsf/UnsupportedVariantTypeException.java | 37 +-------- .../org/apache/poi/hpsf/VariantSupport.java | 41 +++++++--- .../apache/poi/hpsf/VariantTypeException.java | 76 +++++++++++++++++++ .../hpsf/WritingNotSupportedException.java | 2 +- 12 files changed, 217 insertions(+), 79 deletions(-) create mode 100644 src/java/org/apache/poi/hpsf/Constants.java create mode 100644 src/java/org/apache/poi/hpsf/IllegalVariantTypeException.java create mode 100644 src/java/org/apache/poi/hpsf/VariantTypeException.java diff --git a/src/java/org/apache/poi/hpsf/Constants.java b/src/java/org/apache/poi/hpsf/Constants.java new file mode 100644 index 000000000..ac1422474 --- /dev/null +++ b/src/java/org/apache/poi/hpsf/Constants.java @@ -0,0 +1,26 @@ +package org.apache.poi.hpsf; + +/** + *

Defines constants of general use.

+ * + * @author Rainer Klute <klute@rainer-klute.de> + * @since 2004-06-20 + * @version $Id$ + */ +public class Constants +{ + + /**

Codepage for SJIS

*/ + public static final int CP_SJIS = 932; + + /**

Codepage for UTF-16

*/ + public static final int CP_UTF16 = 1200; + + /**

Codepage for UTF-8

*/ + public static final int CP_UTF8 = 65001; + + /**

Codepage for Unicode

*/ + public static final int CP_UNICODE = CP_UTF16; + +} diff --git a/src/java/org/apache/poi/hpsf/IllegalVariantTypeException.java b/src/java/org/apache/poi/hpsf/IllegalVariantTypeException.java new file mode 100644 index 000000000..61009ea32 --- /dev/null +++ b/src/java/org/apache/poi/hpsf/IllegalVariantTypeException.java @@ -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; + +/** + *

This exception is thrown if HPSF encounters a variant type that is illegal + * in the current context.

+ * + * @author Rainer Klute <klute@rainer-klute.de> + * @since 2004-06-21 + * @version $Id$ + */ +public class IllegalVariantTypeException extends VariantTypeException +{ + + /** + *

Constructor

+ * + * @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); + } + + /** + *

Constructor

+ * + * @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."); + } + +} diff --git a/src/java/org/apache/poi/hpsf/MutableProperty.java b/src/java/org/apache/poi/hpsf/MutableProperty.java index d6769a5b2..1aa603a4a 100644 --- a/src/java/org/apache/poi/hpsf/MutableProperty.java +++ b/src/java/org/apache/poi/hpsf/MutableProperty.java @@ -1,4 +1,3 @@ - /* ==================================================================== Copyright 2002-2004 Apache Software Foundation @@ -22,7 +21,7 @@ import java.io.OutputStream; /** *

Adds writing capability to the {@link Property} class.

- * + * *

Please be aware that this class' functionality will be merged into the * {@link Property} class at a later time, so the API will change.

* @@ -46,7 +45,7 @@ public class MutableProperty extends Property /** *

Creates a MutableProperty as a copy of an existing * Property.

- * + * * @param p The property to copy. */ public MutableProperty(final Property p) @@ -95,11 +94,11 @@ public class MutableProperty extends Property /** *

Writes the property to an output stream.

- * + * * @param out The output stream to write to. * @param codepage The codepage to use for writing non-wide strings * @return the number of bytes written to the stream - * + * * @exception IOException if an I/O error occurs * @exception WritingNotSupportedException if a variant type is to be * written that is not yet supported diff --git a/src/java/org/apache/poi/hpsf/MutableSection.java b/src/java/org/apache/poi/hpsf/MutableSection.java index 4559fbe80..9c47c71cb 100644 --- a/src/java/org/apache/poi/hpsf/MutableSection.java +++ b/src/java/org/apache/poi/hpsf/MutableSection.java @@ -144,7 +144,6 @@ public class MutableSection extends Section for (int i = 0; i < properties.length; i++) preprops.add(properties[i]); dirty = true; - propertyCount = properties.length; } @@ -217,7 +216,6 @@ public class MutableSection extends Section removeProperty(id); preprops.add(p); dirty = true; - propertyCount = preprops.size(); } @@ -236,7 +234,6 @@ public class MutableSection extends Section break; } dirty = true; - propertyCount = preprops.size(); } @@ -362,7 +359,7 @@ public class MutableSection extends Section throw new IllegalPropertySetDataException ("The codepage property (ID = 1) must be an " + "Integer object."); - else if (((Integer) p1).intValue() != Property.CP_UNICODE) + else if (((Integer) p1).intValue() != Constants.CP_UNICODE) throw new IllegalPropertySetDataException ("The codepage property (ID = 1) must be " + "1200 (Unicode)."); @@ -574,7 +571,7 @@ public class MutableSection extends Section * dictionary. HPSF always writes Unicode strings to the * dictionary. */ setProperty(PropertyIDMap.PID_CODEPAGE, Variant.VT_I2, - new Integer(Property.CP_UNICODE)); + new Integer(Constants.CP_UNICODE)); } else /* Setting the dictionary to null means to remove property 0. diff --git a/src/java/org/apache/poi/hpsf/Property.java b/src/java/org/apache/poi/hpsf/Property.java index 167ceabec..a517758db 100644 --- a/src/java/org/apache/poi/hpsf/Property.java +++ b/src/java/org/apache/poi/hpsf/Property.java @@ -56,9 +56,6 @@ import org.apache.poi.util.LittleEndian; public class Property { - /**

Codepage 1200 denotes Unicode.

*/ - public static final int CP_UNICODE = 1200; - /**

The property's ID.

*/ protected long id; @@ -118,9 +115,8 @@ public class Property * @param length The property's type/value pair's length in bytes. * @param codepage The section's and thus the property's * codepage. It is needed only when reading string values. - * * @exception UnsupportedEncodingException if the specified codepage is not - * supported + * supported. */ public Property(final long id, final byte[] src, final long offset, final int length, final int codepage) @@ -210,7 +206,7 @@ public class Property * character set is Unicode or not. */ StringBuffer b = new StringBuffer((int) sLength); for (int j = 0; j < sLength; j++) - if (codepage == CP_UNICODE) + if (codepage == Constants.CP_UNICODE) { final int i1 = o + (j * 2); final int i2 = i1 + 1; @@ -222,7 +218,7 @@ public class Property /* Strip 0x00 characters from the end of the string: */ while (b.length() > 0 && b.charAt(b.length() - 1) == 0x00) b.setLength(b.length() - 1); - if (codepage == CP_UNICODE) + if (codepage == Constants.CP_UNICODE) { if (sLength % 2 == 1) sLength++; diff --git a/src/java/org/apache/poi/hpsf/PropertySet.java b/src/java/org/apache/poi/hpsf/PropertySet.java index d105d767f..30b682392 100644 --- a/src/java/org/apache/poi/hpsf/PropertySet.java +++ b/src/java/org/apache/poi/hpsf/PropertySet.java @@ -233,11 +233,13 @@ public class PropertySet * @throws IOException if the {@link InputStream} cannot not be * accessed as needed. * @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) throws NoPropertySetStreamException, MarkUnsupportedException, - IOException + IOException, UnsupportedEncodingException { if (isPropertySetStream(stream)) { @@ -265,7 +267,7 @@ public class PropertySet * @throws NoPropertySetStreamException if the byte array is not a * 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) throws NoPropertySetStreamException, UnsupportedEncodingException @@ -288,7 +290,7 @@ public class PropertySet * @throws NoPropertySetStreamException if the byte array is not a * property set stream. * - * @exception UnsupportedEncodingException if the codepage is not supported + * @exception UnsupportedEncodingException if the codepage is not supported. */ public PropertySet(final byte[] stream) throws NoPropertySetStreamException, UnsupportedEncodingException diff --git a/src/java/org/apache/poi/hpsf/PropertySetFactory.java b/src/java/org/apache/poi/hpsf/PropertySetFactory.java index 53c18b5a1..e7b957679 100644 --- a/src/java/org/apache/poi/hpsf/PropertySetFactory.java +++ b/src/java/org/apache/poi/hpsf/PropertySetFactory.java @@ -19,6 +19,7 @@ package org.apache.poi.hpsf; import java.io.InputStream; import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.rmi.UnexpectedException; /** @@ -48,10 +49,12 @@ public class PropertySetFactory * @throws MarkUnsupportedException if the stream does not support * the mark operation. * @throws IOException if some I/O problem occurs. + * @exception UnsupportedEncodingException if the specified codepage is not + * supported. */ public static PropertySet create(final InputStream stream) throws NoPropertySetStreamException, MarkUnsupportedException, - IOException + UnsupportedEncodingException, IOException { final PropertySet ps = new PropertySet(stream); try diff --git a/src/java/org/apache/poi/hpsf/Section.java b/src/java/org/apache/poi/hpsf/Section.java index cc1b112b2..fd9e020c4 100644 --- a/src/java/org/apache/poi/hpsf/Section.java +++ b/src/java/org/apache/poi/hpsf/Section.java @@ -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; - - /** *

Returns the number of properties in this section.

* @@ -120,7 +111,7 @@ public class Section */ public int getPropertyCount() { - return propertyCount; + return properties.length; } @@ -188,7 +179,7 @@ public class Section /* * Read the number of properties. */ - propertyCount = (int) LittleEndian.getUInt(src, o1); + final int propertyCount = (int) LittleEndian.getUInt(src, o1); o1 += LittleEndian.INT_SIZE; /* diff --git a/src/java/org/apache/poi/hpsf/UnsupportedVariantTypeException.java b/src/java/org/apache/poi/hpsf/UnsupportedVariantTypeException.java index 8dba3efb2..af46b3947 100644 --- a/src/java/org/apache/poi/hpsf/UnsupportedVariantTypeException.java +++ b/src/java/org/apache/poi/hpsf/UnsupportedVariantTypeException.java @@ -1,4 +1,3 @@ - /* ==================================================================== Copyright 2002-2004 Apache Software Foundation @@ -31,15 +30,10 @@ import org.apache.poi.util.HexDump; * @since 2003-08-05 * @version $Id$ */ -public abstract class UnsupportedVariantTypeException extends HPSFException +public abstract class UnsupportedVariantTypeException +extends VariantTypeException { - private Object value; - - private long variantType; - - - /** *

Constructor.

* @@ -49,38 +43,15 @@ public abstract class UnsupportedVariantTypeException extends HPSFException public UnsupportedVariantTypeException(final long variantType, 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) + ", " + HexDump.toHex(variantType) + "). If you want support for " + "this variant type in one of the next POI releases please " + "submit a request for enhancement (RFE) to " + "! Thank you!"); - this.variantType = variantType; - this.value = value; } - /** - *

Returns the offending variant type.

- * - * @return the offending variant type. - */ - public long getVariantType() - { - return variantType; - } - - - - /** - *

Return the value who's variant type is not yet supported.

- * - * @return the value who's variant type is not yet supported - */ - public Object getValue() - { - return value; - } - } diff --git a/src/java/org/apache/poi/hpsf/VariantSupport.java b/src/java/org/apache/poi/hpsf/VariantSupport.java index cb4c86715..95ff2e469 100644 --- a/src/java/org/apache/poi/hpsf/VariantSupport.java +++ b/src/java/org/apache/poi/hpsf/VariantSupport.java @@ -1,4 +1,3 @@ - /* ==================================================================== Copyright 2002-2004 Apache Software Foundation @@ -14,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - + package org.apache.poi.hpsf; import java.io.IOException; @@ -41,7 +40,7 @@ import org.apache.poi.util.LittleEndianConsts; *
  • Reading reads from a byte array while writing writes to an byte array * output stream.

  • * - * * * @author Rainer Klute <klute@rainer-klute.de> @@ -126,19 +125,26 @@ public class VariantSupport extends Variant * @exception ReadingNotSupportedException if a property is to be written * who's variant type HPSF does not yet support * @exception UnsupportedEncodingException if the specified codepage is not - * supported + * supported. * * @see Variant */ public static Object read(final byte[] src, final int offset, final int length, final long type, final int codepage) - throws ReadingNotSupportedException, UnsupportedEncodingException + throws ReadingNotSupportedException, UnsupportedEncodingException { Object value; int o1 = offset; 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: { @@ -279,11 +285,11 @@ public class VariantSupport extends Variant ("Codepage number may not be " + codepage); switch (codepage) { - case 932: + case Constants.CP_SJIS: return "SJIS"; - case 1200: + case Constants.CP_UTF16: return "UTF-16"; - case 65001: + case Constants.CP_UTF8: return "UTF-8"; default: return "cp" + codepage; @@ -295,6 +301,11 @@ public class VariantSupport extends Variant *

    Writes a variant value to an output stream. This method ensures that * always a multiple of 4 bytes is written.

    * + *

    If the codepage is UTF-16, which is encouraged, strings + * must 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.

    + * * @param out The stream to write the value to. * @param type The variant's type. * @param value The variant's value. @@ -309,8 +320,14 @@ public class VariantSupport extends Variant final Object value, final int codepage) 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; - switch ((int) type) + switch ((int) lType) { case Variant.VT_BOOL: { @@ -402,10 +419,10 @@ public class VariantSupport extends Variant out.write(b); length = b.length; writeUnsupportedTypeMessage - (new WritingNotSupportedException(type, value)); + (new WritingNotSupportedException(lType, value)); } else - throw new WritingNotSupportedException(type, value); + throw new WritingNotSupportedException(lType, value); break; } } diff --git a/src/java/org/apache/poi/hpsf/VariantTypeException.java b/src/java/org/apache/poi/hpsf/VariantTypeException.java new file mode 100644 index 000000000..a775ee876 --- /dev/null +++ b/src/java/org/apache/poi/hpsf/VariantTypeException.java @@ -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; + +/** + *

    This exception is thrown if HPSF encounters a problem with a variant type. + * Concrete subclasses specifiy the problem further.

    + * + * @author Rainer Klute <klute@rainer-klute.de> + * @since 2004-06-21 + * @version $Id$ + */ +public abstract class VariantTypeException extends HPSFException +{ + + private Object value; + + private long variantType; + + + + /** + *

    Constructor.

    + * + * @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; + } + + + + /** + *

    Returns the offending variant type.

    + * + * @return the offending variant type. + */ + public long getVariantType() + { + return variantType; + } + + + + /** + *

    Returns the value who's variant type caused the problem.

    + * + * @return the value who's variant type caused the problem + */ + public Object getValue() + { + return value; + } + +} diff --git a/src/java/org/apache/poi/hpsf/WritingNotSupportedException.java b/src/java/org/apache/poi/hpsf/WritingNotSupportedException.java index 3eb2c68d0..64e955a70 100644 --- a/src/java/org/apache/poi/hpsf/WritingNotSupportedException.java +++ b/src/java/org/apache/poi/hpsf/WritingNotSupportedException.java @@ -36,7 +36,7 @@ public class WritingNotSupportedException /** *

    Constructor

    * - * @param variantType The unsupported varian type. + * @param variantType The unsupported variant type. * @param value The value. */ public WritingNotSupportedException(final long variantType,