Author: kiwiwings
Date: Tue May  2 23:27:27 2017
New Revision: 1793596

URL: http://svn.apache.org/viewvc?rev=1793596&view=rev
Log:
Fix hpsf javadocs and code issues

Added:
    poi/trunk/test-data/hpsf/TestInvertedClassID.doc   (with props)
    poi/trunk/test-data/hpsf/TestVisio43688.vsd   (with props)
Modified:
    poi/site/src/documentation/content/xdocs/status.xml
    poi/trunk/src/java/org/apache/poi/hpsf/MutablePropertySet.java
    poi/trunk/src/java/org/apache/poi/hpsf/Property.java
    poi/trunk/src/java/org/apache/poi/hpsf/PropertySetFactory.java
    poi/trunk/src/java/org/apache/poi/hpsf/SpecialPropertySet.java
    poi/trunk/src/java/org/apache/poi/hpsf/SummaryInformation.java
    poi/trunk/src/java/org/apache/poi/hpsf/wellknown/PropertyIDMap.java
    poi/trunk/src/java/org/apache/poi/hpsf/wellknown/SectionIDMap.java
    poi/trunk/src/java/org/apache/poi/hssf/record/OldStringRecord.java
    poi/trunk/src/java/org/apache/poi/util/CodePageUtil.java
    poi/trunk/src/java/org/apache/poi/util/LittleEndianByteArrayInputStream.java
    poi/trunk/src/java/org/apache/poi/util/LittleEndianCP950Reader.java
    poi/trunk/src/java/org/apache/poi/util/LocaleUtil.java
    poi/trunk/src/testcases/org/apache/poi/hpsf/basic/TestBasic.java
    poi/trunk/src/testcases/org/apache/poi/hpsf/basic/TestMetaDataIPI.java
    poi/trunk/src/testcases/org/apache/poi/hpsf/basic/TestReadAllFiles.java
    poi/trunk/src/testcases/org/apache/poi/hpsf/basic/TestWrite.java
    poi/trunk/src/testcases/org/apache/poi/hpsf/basic/TestWriteWellKnown.java
    poi/trunk/src/testcases/org/apache/poi/hpsf/basic/Util.java

Modified: poi/site/src/documentation/content/xdocs/status.xml
URL: 
http://svn.apache.org/viewvc/poi/site/src/documentation/content/xdocs/status.xml?rev=1793596&r1=1793595&r2=1793596&view=diff
==============================================================================
--- poi/site/src/documentation/content/xdocs/status.xml (original)
+++ poi/site/src/documentation/content/xdocs/status.xml Tue May  2 23:27:27 2017
@@ -58,6 +58,7 @@
 
     <release version="3.17-beta1" date="2017-07-??">
       <actions>
+        <action dev="PD" type="fix" fixes-bug="61062" module="HPSF">Various 
HPSF related fixes</action>
         <action dev="PD" type="fix" fixes-bug="61034" module="XSSF-SAX">Call 
to XSSFReader.getSheetsData() returns duplicate sheets</action>
         <action dev="PD" type="fix" fixes-bug="61049" module="SS">Fix order of 
two built-in formats</action>
         <action dev="PD" type="add" fixes-bug="61021" module="XSSF">Extract 
Excel 2013 absPath info from xlsb</action>

Modified: poi/trunk/src/java/org/apache/poi/hpsf/MutablePropertySet.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hpsf/MutablePropertySet.java?rev=1793596&r1=1793595&r2=1793596&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hpsf/MutablePropertySet.java (original)
+++ poi/trunk/src/java/org/apache/poi/hpsf/MutablePropertySet.java Tue May  2 
23:27:27 2017
@@ -17,6 +17,10 @@
 
 package org.apache.poi.hpsf;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+
 import org.apache.poi.util.Removal;
 
 /**
@@ -34,4 +38,9 @@ public class MutablePropertySet extends
        public MutablePropertySet(final PropertySet ps) {
         super(ps);
     }
+
+    /* package */ MutablePropertySet(final InputStream stream)
+    throws NoPropertySetStreamException, MarkUnsupportedException, 
IOException, UnsupportedEncodingException {
+        super(stream);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/hpsf/Property.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hpsf/Property.java?rev=1793596&r1=1793595&r2=1793596&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hpsf/Property.java (original)
+++ poi/trunk/src/java/org/apache/poi/hpsf/Property.java Tue May  2 23:27:27 
2017
@@ -17,17 +17,20 @@
 
 package org.apache.poi.hpsf;
 
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
 import java.nio.charset.Charset;
 import java.util.Arrays;
-import java.util.LinkedHashMap;
-import java.util.Map;
 
+import org.apache.poi.hpsf.wellknown.PropertyIDMap;
 import org.apache.poi.util.CodePageUtil;
 import org.apache.poi.util.HexDump;
 import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianByteArrayInputStream;
+import org.apache.poi.util.LittleEndianConsts;
+import org.apache.poi.util.LocaleUtil;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
 
@@ -58,6 +61,13 @@ import org.apache.poi.util.POILogger;
  */
 public class Property {
 
+    /**
+     * Default codepage for {@link CodePageString CodePageStrings}
+     */
+    public static final int DEFAULT_CODEPAGE = CodePageUtil.CP_WINDOWS_1252; 
+    
+    private static final POILogger LOG = 
POILogFactory.getLogger(Property.class);
+    
     /** The property's ID. */
     private long id;
 
@@ -82,7 +92,7 @@ public class Property {
     public Property(Property p) {
         this(p.id, p.type, p.value);
     }
-    
+
     /**
      * Creates a property.
      *
@@ -120,13 +130,12 @@ public class Property {
          * property IDs and property names.
          */
         if (id == 0) {
-            value = readDictionary(src, offset, length, codepage);
-            return;
+            throw new UnsupportedEncodingException("Dictionary not allowed 
here");
         }
 
         int o = (int) offset;
         type = LittleEndian.getUInt(src, o);
-        o += LittleEndian.INT_SIZE;
+        o += LittleEndianConsts.INT_SIZE;
 
         try {
             value = VariantSupport.read(src, o, length, (int) type, codepage);
@@ -136,6 +145,39 @@ public class Property {
         }
     }
 
+    /**
+     * Creates a {@link Property} instance by reading its bytes
+     * from the property set stream.
+     *
+     * @param id The property's ID.
+     * @param leis The bytes the property set stream consists of.
+     * @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.
+     */
+    public Property(final long id, LittleEndianByteArrayInputStream leis, 
final int length, final int codepage)
+    throws UnsupportedEncodingException {
+        this.id = id;
+
+        /*
+         * ID 0 is a special case since it specifies a dictionary of
+         * property IDs and property names.
+         */
+        if (id == 0) {
+            throw new UnsupportedEncodingException("Dictionary not allowed 
here");
+        }
+
+        type = leis.readUInt();
+
+        try {
+            value = VariantSupport.read(leis, length, (int) type, codepage);
+        } catch (UnsupportedVariantTypeException ex) {
+            VariantSupport.writeUnsupportedTypeMessage(ex);
+            value = ex.getValue();
+        }
+    }
 
 
     /**
@@ -182,7 +224,7 @@ public class Property {
     public Object getValue() {
         return value;
     }
-    
+
     /**
      * Sets the property's value.
      *
@@ -194,102 +236,8 @@ public class Property {
 
 
 
-    
 
-    /**
-     * Reads a dictionary.
-     *
-     * @param src The byte array containing the bytes making out the 
dictionary.
-     * @param offset At this offset within {@code src} the dictionary
-     *        starts.
-     * @param length The dictionary contains at most this many bytes.
-     * @param codepage The codepage of the string values.
-     * @return The dictonary
-     * @throws UnsupportedEncodingException if the dictionary's codepage is not
-     *         (yet) supported.
-     */
-    protected Map<?, ?> readDictionary(final byte[] src, final long offset, 
final int length, final int codepage)
-    throws UnsupportedEncodingException {
-        /* Check whether "offset" points into the "src" array". */
-        if (offset < 0 || offset > src.length) {
-            throw new HPSFRuntimeException
-                ("Illegal offset " + offset + " while HPSF stream contains " +
-                 length + " bytes.");
-        }
-        int o = (int) offset;
 
-        /*
-         * Read the number of dictionary entries.
-         */
-        final long nrEntries = LittleEndian.getUInt(src, o);
-        o += LittleEndian.INT_SIZE;
-
-        final Map<Object, Object> m = new LinkedHashMap<Object, Object>((int) 
nrEntries, (float) 1.0 );
-
-        try {
-            for (int i = 0; i < nrEntries; i++) {
-                /* The key. */
-                final Long id = Long.valueOf(LittleEndian.getUInt(src, o));
-                o += LittleEndian.INT_SIZE;
-
-                /* The value (a string). The length is the either the
-                 * number of (two-byte) characters if the character set is 
Unicode
-                 * or the number of bytes if the character set is not Unicode.
-                 * The length includes terminating 0x00 bytes which we have to 
strip
-                 * off to create a Java string. */
-                long sLength = LittleEndian.getUInt(src, o);
-                o += LittleEndian.INT_SIZE;
-
-                /* Read the string. */
-                final StringBuffer b = new StringBuffer();
-                switch (codepage) {
-                    case -1:
-                        /* Without a codepage the length is equal to the 
number of
-                         * bytes. */
-                        b.append(new String(src, o, (int) sLength, 
Charset.forName("ASCII")));
-                        break;
-                    case CodePageUtil.CP_UNICODE:
-                        /* The length is the number of characters, i.e. the 
number
-                         * of bytes is twice the number of the characters. */
-                        final int nrBytes = (int) (sLength * 2);
-                        final byte[] h = new byte[nrBytes];
-                        for (int i2 = 0; i2 < nrBytes; i2 += 2)
-                        {
-                            h[i2] = src[o + i2 + 1];
-                            h[i2 + 1] = src[o + i2];
-                        }
-                        b.append(new String(h, 0, nrBytes, 
CodePageUtil.codepageToEncoding(codepage)));
-                        break;
-                    default:
-                        /* For encodings other than Unicode the length is the 
number
-                         * of bytes. */
-                        b.append(new String(src, o, (int) sLength, 
CodePageUtil.codepageToEncoding(codepage)));
-                        break;
-                }
-
-                /* 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 == CodePageUtil.CP_UNICODE) {
-                    if (sLength % 2 == 1) {
-                        sLength++;
-                    }
-                    o += (sLength + sLength);
-                } else {
-                    o += sLength;
-                }
-                m.put(id, b.toString());
-            }
-        } catch (RuntimeException ex) {
-            final POILogger l = POILogFactory.getLogger(getClass());
-            l.log(POILogger.WARN,
-                    "The property set's dictionary contains bogus data. "
-                    + "All dictionary entries starting with the one with ID "
-                    + id + " will be ignored.", ex);
-        }
-        return m;
-    }
 
 
 
@@ -301,11 +249,12 @@ public class Property {
      * @exception WritingNotSupportedException if HPSF does not yet support the
      * property's variant type.
      */
-    protected int getSize() throws WritingNotSupportedException
+    protected int getSize(int codepage) throws WritingNotSupportedException
     {
-        int length = VariantSupport.getVariantLength(type);
-        if (length >= 0) {
-            return length; /* Fixed length */
+        int length = Variant.getVariantLength(type);
+        if (length >= 0  || type == Variant.VT_EMPTY) {
+            /* Fixed length */
+            return length;
         }
         if (length == -2) {
             /* Unknown length */
@@ -313,29 +262,26 @@ public class Property {
         }
 
         /* Variable length: */
-        final int PADDING = 4; /* Pad to multiples of 4. */
-        switch ((int) type) {
-            case Variant.VT_LPSTR: {
-                int l = ((String) value).length() + 1;
-                int r = l % PADDING;
-                if (r > 0)
-                    l += PADDING - r;
-                length += l;
-                break;
-            }
-            case Variant.VT_EMPTY:
-                break;
-            default:
+        if (type == Variant.VT_LPSTR || type == Variant.VT_LPWSTR) {
+            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            try {
+                length = write(bos, codepage) - 2*LittleEndianConsts.INT_SIZE;
+                /* Pad to multiples of 4. */
+                length += (4 - (length & 0x3)) & 0x3;
+                return length;
+            } catch (IOException e) {
                 throw new WritingNotSupportedException(type, value);
+            }
         }
-        return length;
+
+        throw new WritingNotSupportedException(type, value);
     }
 
 
 
     /**
      * Compares two properties.<p>
-     * 
+     *
      * 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. Another special case are strings: Two properties
@@ -343,6 +289,7 @@ public class Property {
      *
      * @see Object#equals(java.lang.Object)
      */
+    @Override
     public boolean equals(final Object o) {
         if (!(o instanceof Property)) {
             return false;
@@ -369,12 +316,35 @@ public class Property {
         }
 
         if (value instanceof byte[]) {
-            return Arrays.equals((byte[]) value, (byte[]) pValue);
+            // compare without padding bytes
+            byte[] thisVal = (byte[]) value, otherVal = (byte[]) pValue;
+            int len = unpaddedLength(thisVal);
+            if (len != unpaddedLength(otherVal)) {
+                return false;
+            }
+            for (int i=0; i<len; i++) {
+                if (thisVal[i] != otherVal[i]) {
+                    return false;
+                }
+            }
+            return true;
         }
 
         return value.equals(pValue);
     }
 
+    /**
+     * Byte arrays can be 0-padded up to 3 bytes to form a full quad array.
+     * This returns the truncated length without the potentially 0-padded bytes
+     *
+     * @param buf the bytes
+     * @return the truncated size with a maximum of 4 bytes shorter (3 bytes + 
trailing 0 of strings)
+     */
+    private static int unpaddedLength(byte[] buf) {
+        int len;
+        for (len = buf.length; len > 0 && len > buf.length-4 && buf[len-1] == 
0; len--);
+        return len;
+    }
 
 
     private boolean typesAreEqual(final long t1, final long t2) {
@@ -388,6 +358,7 @@ public class Property {
     /**
      * @see Object#hashCode()
      */
+    @Override
     public int hashCode() {
         long hashCode = 0;
         hashCode += id;
@@ -404,47 +375,128 @@ public class Property {
     /**
      * @see Object#toString()
      */
+    @Override
     public String toString() {
+        return toString(Property.DEFAULT_CODEPAGE);
+    }
+    
+    public String toString(int codepage) {
         final StringBuffer b = new StringBuffer();
-        b.append(getClass().getName());
-        b.append('[');
+        b.append("Property[");
         b.append("id: ");
         b.append(getID());
+        String idName = getNameFromID();
+        if (idName != null) {
+            b.append(" (");
+            b.append(idName);
+            b.append(")");
+        }
         b.append(", type: ");
         b.append(getType());
+        b.append(" (");
+        b.append(getVariantName());
+        b.append(") ");
         final Object value = getValue();
         b.append(", value: ");
         if (value instanceof String) {
-            b.append(value);
-            final String s = (String) value;
-            final int l = s.length();
-            final byte[] bytes = new byte[l * 2];
-            for (int i = 0; i < l; i++) {
-                final char c = s.charAt(i);
-                final byte high = (byte) ((c & 0x00ff00) >> 8);
-                final byte low  = (byte) ((c & 0x0000ff) >> 0);
-                bytes[i * 2]     = high;
-                bytes[i * 2 + 1] = low;
+            b.append("\n");
+            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            try {
+                write(bos, codepage);
+            } catch (Exception e) {
+                LOG.log(POILogger.WARN, "can't serialize string", e);
             }
+            
             b.append(" [");
-            if(bytes.length > 0) {
-                final String hex = HexDump.dump(bytes, 0L, 0);
+            // skip length field
+            if(bos.size() > 2*LittleEndianConsts.INT_SIZE) {
+                final String hex = HexDump.dump(bos.toByteArray(), 
-2*LittleEndianConsts.INT_SIZE, 2*LittleEndianConsts.INT_SIZE);
                 b.append(hex);
             }
             b.append("]");
         } else if (value instanceof byte[]) {
+            b.append("\n");
             byte[] bytes = (byte[])value;
             if(bytes.length > 0) {
                 String hex = HexDump.dump(bytes, 0L, 0);
                 b.append(hex);
             }
+        } else if (type == Variant.VT_EMPTY || type == Variant.VT_NULL) {
+            b.append("null");
         } else {
-            b.append(value);
+            b.append(value.toString());
+            
+            String decoded = decodeValueFromID();
+            if (decoded != null) {
+                b.append(" (");
+                b.append(decoded);
+                b.append(")");
+            }
         }
         b.append(']');
         return b.toString();
     }
 
+    private String getVariantName() {
+        if (getID() == 0) {
+            return "dictionary";
+        }
+        return Variant.getVariantName(getType());
+    }
+    
+    private String decodeValueFromID() {
+        try {
+            switch((int)getID()) {
+                case PropertyIDMap.PID_CODEPAGE:
+                    return 
CodePageUtil.codepageToEncoding(((Number)value).intValue());
+                case PropertyIDMap.PID_LOCALE:
+                    return 
LocaleUtil.getLocaleFromLCID(((Number)value).intValue());
+            }
+        } catch (Exception e) {
+            LOG.log(POILogger.WARN, "Can't decode id "+getID());
+        }
+        return null;
+    }
+    
+    private String getNameFromID() {
+        switch ((int)getID()) {
+        case PropertyIDMap.PID_DICTIONARY: return "PID_DICTIONARY";
+        case PropertyIDMap.PID_CODEPAGE: return "PID_CODEPAGE";
+        case PropertyIDMap.PID_CATEGORY: return "PID_CATEGORY";
+        case PropertyIDMap.PID_PRESFORMAT: return "PID_PRESFORMAT";
+        case PropertyIDMap.PID_BYTECOUNT: return "PID_BYTECOUNT";
+        case PropertyIDMap.PID_LINECOUNT: return "PID_LINECOUNT";
+        case PropertyIDMap.PID_PARCOUNT: return "PID_PARCOUNT";
+        case PropertyIDMap.PID_SLIDECOUNT: return "PID_SLIDECOUNT";
+        case PropertyIDMap.PID_NOTECOUNT: return "PID_NOTECOUNT";
+        case PropertyIDMap.PID_HIDDENCOUNT: return "PID_HIDDENCOUNT";
+        case PropertyIDMap.PID_MMCLIPCOUNT: return "PID_MMCLIPCOUNT";
+        case PropertyIDMap.PID_SCALE: return "PID_SCALE";
+        case PropertyIDMap.PID_HEADINGPAIR: return "PID_HEADINGPAIR";
+        case PropertyIDMap.PID_DOCPARTS: return "PID_DOCPARTS";
+        case PropertyIDMap.PID_MANAGER: return "PID_MANAGER";
+        case PropertyIDMap.PID_COMPANY: return "PID_COMPANY";
+        case PropertyIDMap.PID_LINKSDIRTY: return "PID_LINKSDIRTY";
+        case PropertyIDMap.PID_CCHWITHSPACES: return "PID_CCHWITHSPACES";
+        // 0x12 Unused
+        // 0x13 GKPIDDSI_SHAREDDOC - Must be False
+        // 0x14 GKPIDDSI_LINKBASE - Must not be written
+        // 0x15 GKPIDDSI_HLINKS - Must not be written
+        case PropertyIDMap.PID_HYPERLINKSCHANGED: return 
"PID_HYPERLINKSCHANGED";
+        case PropertyIDMap.PID_VERSION: return "PID_VERSION";
+        case PropertyIDMap.PID_DIGSIG: return "PID_DIGSIG";
+        // 0x19 Unused
+        case PropertyIDMap.PID_CONTENTTYPE: return "PID_CONTENTTYPE";
+        case PropertyIDMap.PID_CONTENTSTATUS: return "PID_CONTENTSTATUS";
+        case PropertyIDMap.PID_LANGUAGE: return "PID_LANGUAGE";
+        case PropertyIDMap.PID_DOCVERSION: return "PID_DOCVERSION";
+        case PropertyIDMap.PID_MAX: return "PID_MAX";
+        case PropertyIDMap.PID_LOCALE: return "PID_LOCALE";
+        case PropertyIDMap.PID_BEHAVIOUR: return "PID_BEHAVIOUR";
+        default: return null;
+        }
+    }
+
     /**
      * Writes the property to an output stream.
      *
@@ -462,13 +514,21 @@ public class Property {
         long variantType = getType();
 
         /* Ensure that wide strings are written if the codepage is Unicode. */
-        if (codepage == CodePageUtil.CP_UNICODE && variantType == 
Variant.VT_LPSTR) {
-            variantType = Variant.VT_LPWSTR;
+//        if (codepage == CodePageUtil.CP_UNICODE && variantType == 
Variant.VT_LPSTR) {
+//            variantType = Variant.VT_LPWSTR;
+//        }
+
+        if (variantType == Variant.VT_LPSTR && codepage != 
CodePageUtil.CP_UTF16) {
+            String csStr = CodePageUtil.codepageToEncoding(codepage > 0 ? 
codepage : Property.DEFAULT_CODEPAGE);
+            if (!Charset.forName(csStr).newEncoder().canEncode((String)value)) 
{
+                variantType = Variant.VT_LPWSTR;
+            }
         }
 
-        length += TypeWriter.writeUIntToStream(out, variantType);
+        LittleEndian.putUInt(variantType, out);
+        length += LittleEndianConsts.INT_SIZE;
         length += VariantSupport.write(out, variantType, getValue(), codepage);
         return length;
     }
-    
+
 }

Modified: poi/trunk/src/java/org/apache/poi/hpsf/PropertySetFactory.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hpsf/PropertySetFactory.java?rev=1793596&r1=1793595&r2=1793596&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hpsf/PropertySetFactory.java (original)
+++ poi/trunk/src/java/org/apache/poi/hpsf/PropertySetFactory.java Tue May  2 
23:27:27 2017
@@ -22,9 +22,11 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
 
+import org.apache.poi.hpsf.wellknown.SectionIDMap;
 import org.apache.poi.poifs.filesystem.DirectoryEntry;
 import org.apache.poi.poifs.filesystem.DocumentEntry;
 import org.apache.poi.poifs.filesystem.DocumentInputStream;
+import org.apache.poi.util.LittleEndianInputStream;
 
 /**
  * Factory class to create instances of {@link SummaryInformation},
@@ -87,19 +89,33 @@ public class PropertySetFactory {
      */
     public static PropertySet create(final InputStream stream)
     throws NoPropertySetStreamException, MarkUnsupportedException, 
UnsupportedEncodingException, IOException {
-        final PropertySet ps = new PropertySet(stream);
-        try {
-            if (ps.isSummaryInformation()) {
-                return new SummaryInformation(ps);
-            } else if (ps.isDocumentSummaryInformation()) {
-                return new DocumentSummaryInformation(ps);
-            } else {
-                return ps;
-            }
-        } catch (UnexpectedPropertySetTypeException ex) {
-            /* This exception will never be throws because we already checked
-             * explicitly for this case above. */
-            throw new IllegalStateException(ex);
+        stream.mark(PropertySet.OFFSET_HEADER+ClassID.LENGTH+1);
+        LittleEndianInputStream leis = new LittleEndianInputStream(stream);
+        int byteOrder =  leis.readUShort();
+        int format = leis.readUShort();
+        int osVersion = (int)leis.readUInt();
+        byte[] clsIdBuf = new byte[ClassID.LENGTH];
+        leis.readFully(clsIdBuf);
+        int sectionCount = (int)leis.readUInt();
+        
+        if (byteOrder != PropertySet.BYTE_ORDER_ASSERTION ||
+            format != PropertySet.FORMAT_ASSERTION ||
+            sectionCount < 0) {
+            throw new NoPropertySetStreamException();
+        }
+        
+        if (sectionCount > 0) {
+            leis.readFully(clsIdBuf);
+        }
+        stream.reset();
+        
+        ClassID clsId = new ClassID(clsIdBuf, 0);
+        if (sectionCount > 0 && PropertySet.matchesSummary(clsId, 
SectionIDMap.SUMMARY_INFORMATION_ID)) {
+            return new SummaryInformation(stream);
+        } else if (sectionCount > 0 && PropertySet.matchesSummary(clsId, 
SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID)) {
+            return new DocumentSummaryInformation(stream);
+        } else {
+            return new PropertySet(stream);
         }
     }
 

Modified: poi/trunk/src/java/org/apache/poi/hpsf/SpecialPropertySet.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hpsf/SpecialPropertySet.java?rev=1793596&r1=1793595&r2=1793596&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hpsf/SpecialPropertySet.java (original)
+++ poi/trunk/src/java/org/apache/poi/hpsf/SpecialPropertySet.java Tue May  2 
23:27:27 2017
@@ -17,6 +17,10 @@
 
 package org.apache.poi.hpsf;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+
 import org.apache.poi.util.Removal;
 
 /**
@@ -37,4 +41,9 @@ public class SpecialPropertySet extends
     public SpecialPropertySet(final PropertySet ps) throws 
UnexpectedPropertySetTypeException {
         super(ps);
     }
+
+    /* package */ SpecialPropertySet(final InputStream stream)
+    throws NoPropertySetStreamException, MarkUnsupportedException, 
IOException, UnsupportedEncodingException {
+        super(stream);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/hpsf/SummaryInformation.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hpsf/SummaryInformation.java?rev=1793596&r1=1793595&r2=1793596&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hpsf/SummaryInformation.java (original)
+++ poi/trunk/src/java/org/apache/poi/hpsf/SummaryInformation.java Tue May  2 
23:27:27 2017
@@ -17,6 +17,9 @@
 
 package org.apache.poi.hpsf;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
 import java.util.Date;
 
 import org.apache.poi.hpsf.wellknown.PropertyIDMap;
@@ -62,8 +65,34 @@ public final class SummaryInformation ex
         }
     }
 
+    /**
+     * Creates a {@link SummaryInformation} instance from an {@link
+     * InputStream} in the Horrible Property Set Format.<p>
+     *
+     * The constructor reads the first few bytes from the stream
+     * and determines whether it is really a property set stream. If
+     * it is, it parses the rest of the stream. If it is not, it
+     * resets the stream to its beginning in order to let other
+     * components mess around with the data and throws an
+     * exception.
+     *
+     * @param stream Holds the data making out the property set
+     * stream.
+     * @throws MarkUnsupportedException
+     *    if the stream does not support the {@link InputStream#markSupported} 
method.
+     * @throws IOException
+     *    if the {@link InputStream} cannot be accessed as needed.
+     * @exception NoPropertySetStreamException
+     *    if the input stream does not contain a property set.
+     * @exception UnsupportedEncodingException
+     *    if a character encoding is not supported.
+     */
+    public SummaryInformation(final InputStream stream)
+    throws NoPropertySetStreamException, MarkUnsupportedException, 
IOException, UnsupportedEncodingException {
+        super(stream);
+    }
 
-
+    
     /**
      * @return The title or {@code null}
      */

Modified: poi/trunk/src/java/org/apache/poi/hpsf/wellknown/PropertyIDMap.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hpsf/wellknown/PropertyIDMap.java?rev=1793596&r1=1793595&r2=1793596&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hpsf/wellknown/PropertyIDMap.java 
(original)
+++ poi/trunk/src/java/org/apache/poi/hpsf/wellknown/PropertyIDMap.java Tue May 
 2 23:27:27 2017
@@ -22,14 +22,14 @@ import java.util.HashMap;
 import java.util.Map;
 
 /**
- * <p>This is a dictionary which maps property ID values to property
- * ID strings.</p>
+ * This is a dictionary which maps property ID values to property
+ * ID strings.
  *
- * <p>The methods {@link #getSummaryInformationProperties} and {@link
+ * The methods {@link #getSummaryInformationProperties} and {@link
  * #getDocumentSummaryInformationProperties} return singleton {@link
  * PropertyIDMap}s. An application that wants to extend these maps
  * should treat them as unmodifiable, copy them and modifiy the
- * copies.</p>
+ * copies.
  */
 public class PropertyIDMap extends HashMap<Long,String> {
 
@@ -38,85 +38,85 @@ public class PropertyIDMap extends HashM
      * (and only) section of the Summary Information property set.
      */
 
-    /** <p>ID of the property that denotes the document's title</p> */
+    /** ID of the property that denotes the document's title */
     public static final int PID_TITLE = 2;
 
-    /** <p>ID of the property that denotes the document's subject</p> */
+    /** ID of the property that denotes the document's subject */
     public static final int PID_SUBJECT = 3;
 
-    /** <p>ID of the property that denotes the document's author</p> */
+    /** ID of the property that denotes the document's author */
     public static final int PID_AUTHOR = 4;
 
-    /** <p>ID of the property that denotes the document's keywords</p> */
+    /** ID of the property that denotes the document's keywords */
     public static final int PID_KEYWORDS = 5;
 
-    /** <p>ID of the property that denotes the document's comments</p> */
+    /** ID of the property that denotes the document's comments */
     public static final int PID_COMMENTS = 6;
 
-    /** <p>ID of the property that denotes the document's template</p> */
+    /** ID of the property that denotes the document's template */
     public static final int PID_TEMPLATE = 7;
 
-    /** <p>ID of the property that denotes the document's last author</p> */
+    /** ID of the property that denotes the document's last author */
     public static final int PID_LASTAUTHOR = 8;
 
-    /** <p>ID of the property that denotes the document's revision number</p> 
*/
+    /** ID of the property that denotes the document's revision number */
     public static final int PID_REVNUMBER = 9;
 
-    /** <p>ID of the property that denotes the document's edit time</p> */
+    /** ID of the property that denotes the document's edit time */
     public static final int PID_EDITTIME = 10;
 
-    /** <p>ID of the property that denotes the date and time the document was
-     * last printed</p> */
+    /** ID of the property that denotes the date and time the document was
+     * last printed */
     public static final int PID_LASTPRINTED = 11;
 
-    /** <p>ID of the property that denotes the date and time the document was
-     * created.</p> */
+    /** ID of the property that denotes the date and time the document was
+     * created. */
     public static final int PID_CREATE_DTM = 12;
 
-    /** <p>ID of the property that denotes the date and time the document was
-     * saved</p> */
+    /** ID of the property that denotes the date and time the document was
+     * saved */
     public static final int PID_LASTSAVE_DTM = 13;
 
-    /** <p>ID of the property that denotes the number of pages in the
-     * document</p> */
+    /** ID of the property that denotes the number of pages in the
+     * document */
     public static final int PID_PAGECOUNT = 14;
 
-    /** <p>ID of the property that denotes the number of words in the
-     * document</p> */
+    /** ID of the property that denotes the number of words in the
+     * document */
     public static final int PID_WORDCOUNT = 15;
 
-    /** <p>ID of the property that denotes the number of characters in the
-     * document</p> */
+    /** ID of the property that denotes the number of characters in the
+     * document */
     public static final int PID_CHARCOUNT = 16;
 
-    /** <p>ID of the property that denotes the document's thumbnail</p> */
+    /** ID of the property that denotes the document's thumbnail */
     public static final int PID_THUMBNAIL = 17;
 
-    /** <p>ID of the property that denotes the application that created the
-     * document</p> */
+    /** ID of the property that denotes the application that created the
+     * document */
     public static final int PID_APPNAME = 18;
 
-    /** <p>ID of the property that denotes whether read/write access to the
+    /** ID of the property that denotes whether read/write access to the
      * document is allowed or whether is should be opened as read-only. It can
-     * have the following values:</p>
+     * have the following values:
      *
      * <table summary="">
      *  <tbody>
      *   <tr>
-     *    <th><p>Value</p></th>
-     *    <th><p>Description</p></th>
+     *    <th>Value</th>
+     *    <th>Description</th>
      *   </tr>
      *   <tr>
-     *    <th><p>0</p></th>
-     *    <th><p>No restriction</p></th>
+     *    <th>0</th>
+     *    <th>No restriction</th>
      *   </tr>
      *   <tr>
-     *    <th><p>2</p></th>
-     *    <th><p>Read-only recommended</p></th>
+     *    <th>2</th>
+     *    <th>Read-only recommended</th>
      *   </tr>
      *   <tr>
-     *    <th><p>4</p></th>
-     *    <th><p>Read-only enforced</p></th>
+     *    <th>4</th>
+     *    <th>Read-only enforced</th>
      *   </tr>
      *  </tbody>
      * </table>
@@ -131,103 +131,103 @@ public class PropertyIDMap extends HashM
      */
 
     /**
-     * <p>The entry is a dictionary.</p>
+     * The entry is a dictionary.
      */
     public static final int PID_DICTIONARY = 0;
 
     /**
-     * <p>The entry denotes a code page.</p>
+     * The entry denotes a code page.
      */
     public static final int PID_CODEPAGE = 1;
 
     /**
-     * <p>The entry is a string denoting the category the file belongs
+     * The entry is a string denoting the category the file belongs
      * to, e.g. review, memo, etc. This is useful to find documents of
-     * same type.</p>
+     * same type.
      */
     public static final int PID_CATEGORY = 2;
 
     /**
-     * <p>Target format for power point presentation, e.g. 35mm,
-     * printer, video etc.</p>
+     * Target format for power point presentation, e.g. 35mm,
+     * printer, video etc.
      */
     public static final int PID_PRESFORMAT = 3;
 
     /**
-     * <p>Number of bytes.</p>
+     * Number of bytes.
      */
     public static final int PID_BYTECOUNT = 4;
 
     /**
-     * <p>Number of lines.</p>
+     * Number of lines.
      */
     public static final int PID_LINECOUNT = 5;
 
     /**
-     * <p>Number of paragraphs.</p>
+     * Number of paragraphs.
      */
     public static final int PID_PARCOUNT = 6;
 
     /**
-     * <p>Number of slides in a power point presentation.</p>
+     * Number of slides in a power point presentation.
      */
     public static final int PID_SLIDECOUNT = 7;
 
     /**
-     * <p>Number of slides with notes.</p>
+     * Number of slides with notes.
      */
     public static final int PID_NOTECOUNT = 8;
 
     /**
-     * <p>Number of hidden slides.</p>
+     * Number of hidden slides.
      */
     public static final int PID_HIDDENCOUNT = 9;
 
     /**
-     * <p>Number of multimedia clips, e.g. sound or video.</p>
+     * Number of multimedia clips, e.g. sound or video.
      */
     public static final int PID_MMCLIPCOUNT = 10;
 
     /**
-     * <p>This entry is set to -1 when scaling of the thumbnail is
-     * desired. Otherwise the thumbnail should be cropped.</p>
+     * This entry is set to -1 when scaling of the thumbnail is
+     * desired. Otherwise the thumbnail should be cropped.
      */
     public static final int PID_SCALE = 11;
 
     /**
-     * <p>This entry denotes an internally used property. It is a
+     * This entry denotes an internally used property. It is a
      * vector of variants consisting of pairs of a string (VT_LPSTR)
      * and a number (VT_I4). The string is a heading name, and the
      * number tells how many document parts are under that
-     * heading.</p>
+     * heading.
      */
     public static final int PID_HEADINGPAIR = 12;
 
     /**
-     * <p>This entry contains the names of document parts (word: names
+     * This entry contains the names of document parts (word: names
      * of the documents in the master document, excel: sheet names,
-     * power point: slide titles, binder: document names).</p>
+     * power point: slide titles, binder: document names).
      */
     public static final int PID_DOCPARTS = 13;
 
     /**
-     * <p>This entry contains the name of the project manager.</p>
+     * This entry contains the name of the project manager.
      */
     public static final int PID_MANAGER = 14;
 
     /**
-     * <p>This entry contains the company name.</p>
+     * This entry contains the company name.
      */
     public static final int PID_COMPANY = 15;
 
     /**
-     * <p>If this entry is -1 the links are dirty and should be
-     * re-evaluated.</p>
+     * If this entry is -1 the links are dirty and should be
+     * re-evaluated.
      */
     public static final int PID_LINKSDIRTY = 0x10;
     
     /**
-     * <p>The entry specifies an estimate of the number of characters 
+     * The entry specifies an estimate of the number of characters 
      *  in the document, including whitespace, as an integer
      */
     public static final int PID_CCHWITHSPACES = 0x11;
@@ -238,21 +238,21 @@ public class PropertyIDMap extends HashM
     // 0x15 GKPIDDSI_HLINKS - Must not be written
 
     /**
-     * <p>This entry contains a boolean which marks if the User Defined
+     * This entry contains a boolean which marks if the User Defined
      *  Property Set has been updated outside of the Application, if so the
      *  hyperlinks should be updated on document load.
      */
     public static final int PID_HYPERLINKSCHANGED = 0x16;
     
     /**
-     * <p>This entry contains the version of the Application which wrote the
+     * This entry contains the version of the Application which wrote the
      *  Property set, stored with the two high order bytes having the major
      *  version number, and the two low order bytes the minor version number.
      */
     public static final int PID_VERSION = 0x17;
     
     /**
-     * <p>This entry contains the VBA digital signature for the VBA project 
+     * This entry contains the VBA digital signature for the VBA project 
      *  embedded in the document.
      */
     public static final int PID_DIGSIG = 0x18;
@@ -260,54 +260,75 @@ public class PropertyIDMap extends HashM
     // 0x19 Unused
     
     /**
-     * <p>This entry contains a string of the content type of the file.
+     * This entry contains a string of the content type of the file.
      */
     public static final int PID_CONTENTTYPE = 0x1A;
     
     /**
-     * <p>This entry contains a string of the document status.
+     * This entry contains a string of the document status.
      */
     public static final int PID_CONTENTSTATUS = 0x1B;
     
     /**
-     * <p>This entry contains a string of the document language, but
+     * This entry contains a string of the document language, but
      *  normally should be empty.
      */
     public static final int PID_LANGUAGE = 0x1C;
     
     /**
-     * <p>This entry contains a string of the document version, but
+     * This entry contains a string of the document version, but
      *  normally should be empty
      */
     public static final int PID_DOCVERSION = 0x1D;
     
     /**
-     * <p>The highest well-known property ID. Applications are free to use 
+     * The highest well-known property ID. Applications are free to use 
      *  higher values for custom purposes. (This value is based on Office 12,
-     *  earlier versions of Office had lower values)</p>
+     *  earlier versions of Office had lower values)
      */
     public static final int PID_MAX = 0x1F;
 
+    /**
+     * The Locale property, if present, MUST have the property identifier 
0x80000000,
+     * MUST NOT have a property name, and MUST have type VT_UI4 (0x0013).
+     * If present, its value MUST be a valid language code identifier as 
specified in [MS-LCID].
+     * Its value is selected in an implementation-specific manner.
+     */
+    public static final int PID_LOCALE = 0x80000000;
 
 
     /**
-     * <p>Contains the summary information property ID values and
+     * The Behavior property, if present, MUST have the property identifier 
0x80000003,
+     * MUST NOT have a property name, and MUST have type VT_UI4 (0x0013).
+     * A version 0 property set, indicated by the value 0x0000 for the Version 
field of
+     * the PropertySetStream packet, MUST NOT have a Behavior property.
+     * If the Behavior property is present, it MUST have one of the following 
values.
+     * 
+     * <ul>
+     * <li>0x00000000 = Property names are case-insensitive (default)
+     * <li>0x00000001 = Property names are case-sensitive.
+     * </ul>
+     */
+    public static final int PID_BEHAVIOUR = 0x80000003;
+    
+    /**
+     * Contains the summary information property ID values and
      * associated strings. See the overall HPSF documentation for
-     * details!</p>
+     * details!
      */
     private static PropertyIDMap summaryInformationProperties;
 
     /**
-     * <p>Contains the summary information property ID values and
+     * Contains the summary information property ID values and
      * associated strings. See the overall HPSF documentation for
-     * details!</p>
+     * details!
      */
     private static PropertyIDMap documentSummaryInformationProperties;
 
 
 
     /**
-     * <p>Creates a {@link PropertyIDMap}.</p>
+     * Creates a {@link PropertyIDMap}.
      *
      * @param initialCapacity The initial capacity as defined for
      * {@link HashMap}
@@ -321,7 +342,7 @@ public class PropertyIDMap extends HashM
 
 
     /**
-     * <p>Creates a {@link PropertyIDMap} backed by another map.</p>
+     * Creates a {@link PropertyIDMap} backed by another map.
      *
      * @param map The instance to be created is backed by this map.
      */
@@ -333,8 +354,8 @@ public class PropertyIDMap extends HashM
 
 
     /**
-     * <p>Puts a ID string for an ID into the {@link
-     * PropertyIDMap}.</p>
+     * Puts a ID string for an ID into the {@link
+     * PropertyIDMap}.
      *
      * @param id The ID.
      * @param idString The ID string.
@@ -351,8 +372,8 @@ public class PropertyIDMap extends HashM
 
 
     /**
-     * <p>Gets the ID string for an ID from the {@link
-     * PropertyIDMap}.</p>
+     * Gets the ID string for an ID from the {@link
+     * PropertyIDMap}.
      *
      * @param id The ID.
      * @return The ID string associated with <var>id</var>.
@@ -367,7 +388,7 @@ public class PropertyIDMap extends HashM
     /**
      * @return the Summary Information properties singleton
      */
-    public static PropertyIDMap getSummaryInformationProperties()
+    public static synchronized PropertyIDMap getSummaryInformationProperties()
     {
         if (summaryInformationProperties == null)
         {
@@ -399,12 +420,12 @@ public class PropertyIDMap extends HashM
 
 
     /**
-     * <p>Returns the Document Summary Information properties
-     * singleton.</p>
+     * Returns the Document Summary Information properties
+     * singleton.
      *
      * @return The Document Summary Information properties singleton.
      */
-    public static PropertyIDMap getDocumentSummaryInformationProperties()
+    public static synchronized PropertyIDMap 
getDocumentSummaryInformationProperties()
     {
         if (documentSummaryInformationProperties == null)
         {
@@ -435,7 +456,7 @@ public class PropertyIDMap extends HashM
 
 
     /**
-     * <p>For the most basic testing.</p>
+     * For the most basic testing.
      *
      * @param args The command-line arguments
      */

Modified: poi/trunk/src/java/org/apache/poi/hpsf/wellknown/SectionIDMap.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hpsf/wellknown/SectionIDMap.java?rev=1793596&r1=1793595&r2=1793596&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hpsf/wellknown/SectionIDMap.java 
(original)
+++ poi/trunk/src/java/org/apache/poi/hpsf/wellknown/SectionIDMap.java Tue May  
2 23:27:27 2017
@@ -18,8 +18,10 @@
 package org.apache.poi.hpsf.wellknown;
 
 import java.util.HashMap;
+import java.util.Map;
 
-import org.apache.poi.util.StringUtil;
+import org.apache.poi.hpsf.ClassID;
+import org.apache.poi.util.Internal;
 
 /**
  * <p>Maps section format IDs to {@link PropertyIDMap}s. It is
@@ -36,70 +38,53 @@ import org.apache.poi.util.StringUtil;
  * as keys. A key maps to a {@link PropertyIDMap} describing the
  * property IDs in sections with the specified section format ID.</p>
  */
-@SuppressWarnings({"rawtypes","unchecked"}) // Java Generics have issues on 
this style of class...
-public class SectionIDMap extends HashMap {
+@Internal
+public class SectionIDMap {
+
+    /**
+     * The default section ID map. It maps section format IDs to {@link 
PropertyIDMap PropertyIDMaps}
+     */
+    private static ThreadLocal<Map<ClassID,PropertyIDMap>> defaultMap =
+        new ThreadLocal<Map<ClassID,PropertyIDMap>>();
+    
     /**
      * <p>The SummaryInformation's section's format ID.</p>
      */
-    public static final byte[] SUMMARY_INFORMATION_ID = new byte[]
-    {
-        (byte) 0xF2, (byte) 0x9F, (byte) 0x85, (byte) 0xE0,
-        (byte) 0x4F, (byte) 0xF9, (byte) 0x10, (byte) 0x68,
-        (byte) 0xAB, (byte) 0x91, (byte) 0x08, (byte) 0x00,
-        (byte) 0x2B, (byte) 0x27, (byte) 0xB3, (byte) 0xD9
-    };
+    public static final ClassID SUMMARY_INFORMATION_ID =
+        new ClassID("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}");
 
     /**
-     * <p>The DocumentSummaryInformation's first and second sections' format
-     * ID.</p>
+     * The DocumentSummaryInformation's first and second sections' format ID.
      */
-    public static final byte[][] DOCUMENT_SUMMARY_INFORMATION_ID = new byte[][]
-    {
-        {
-            (byte) 0xD5, (byte) 0xCD, (byte) 0xD5, (byte) 0x02,
-            (byte) 0x2E, (byte) 0x9C, (byte) 0x10, (byte) 0x1B,
-            (byte) 0x93, (byte) 0x97, (byte) 0x08, (byte) 0x00,
-            (byte) 0x2B, (byte) 0x2C, (byte) 0xF9, (byte) 0xAE
-        },
-        {
-            (byte) 0xD5, (byte) 0xCD, (byte) 0xD5, (byte) 0x05,
-            (byte) 0x2E, (byte) 0x9C, (byte) 0x10, (byte) 0x1B,
-            (byte) 0x93, (byte) 0x97, (byte) 0x08, (byte) 0x00,
-            (byte) 0x2B, (byte) 0x2C, (byte) 0xF9, (byte) 0xAE
-        }
+    private static final ClassID DOC_SUMMARY_INFORMATION =
+        new ClassID("{D5CDD502-2E9C-101B-9397-08002B2CF9AE}");    
+    private static final ClassID USER_DEFINED_PROPERTIES =
+        new ClassID("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}");
+    
+    public static final ClassID[] DOCUMENT_SUMMARY_INFORMATION_ID = {
+        DOC_SUMMARY_INFORMATION, USER_DEFINED_PROPERTIES
     };
 
     /**
-     * <p>A property without a known name is described by this string.</p>
+     * A property without a known name is described by this string.
      */
     public static final String UNDEFINED = "[undefined]";
 
     /**
-     * <p>The default section ID map. It maps section format IDs to
-     * {@link PropertyIDMap}s.</p>
-     */
-    private static SectionIDMap defaultMap;
-
-
-
-    /**
      * <p>Returns the singleton instance of the default {@link
      * SectionIDMap}.</p>
      *
      * @return The instance value
      */
-    public static SectionIDMap getInstance()
-    {
-        if (defaultMap == null)
-        {
-            final SectionIDMap m = new SectionIDMap();
-            m.put(SUMMARY_INFORMATION_ID,
-                  PropertyIDMap.getSummaryInformationProperties());
-            m.put(DOCUMENT_SUMMARY_INFORMATION_ID[0],
-                  PropertyIDMap.getDocumentSummaryInformationProperties());
-            defaultMap = m;
+    public static SectionIDMap getInstance() {
+        Map<ClassID,PropertyIDMap> m = defaultMap.get();
+        if (m == null) {
+            m = new HashMap<ClassID,PropertyIDMap>();
+            m.put(SUMMARY_INFORMATION_ID, 
PropertyIDMap.getSummaryInformationProperties());
+            m.put(DOCUMENT_SUMMARY_INFORMATION_ID[0], 
PropertyIDMap.getDocumentSummaryInformationProperties());
+            defaultMap.set(m);
         }
-        return defaultMap;
+        return new SectionIDMap();
     }
 
 
@@ -117,16 +102,15 @@ public class SectionIDMap extends HashMa
      * /<var>sectionFormatID </var> combination is not well-known, the
      * string "[undefined]" is returned.
      */
-    public static String getPIDString(final byte[] sectionFormatID,
-                                      final long pid)
-    {
+    public static String getPIDString(ClassID sectionFormatID, long pid) {
         final PropertyIDMap m = getInstance().get(sectionFormatID);
         if (m == null) {
             return UNDEFINED;
         }
         final String s = (String) m.get(pid);
-        if (s == null)
+        if (s == null) {
             return UNDEFINED;
+        }
         return s;
     }
 
@@ -139,28 +123,23 @@ public class SectionIDMap extends HashMa
      * @param sectionFormatID the section format ID
      * @return the property ID map
      */
-    public PropertyIDMap get(final byte[] sectionFormatID)
-    {
-        return (PropertyIDMap)super.get(new String(sectionFormatID, 
StringUtil.UTF8));
+    public PropertyIDMap get(final ClassID sectionFormatID) {
+        return getInstance().get(sectionFormatID);
     }
 
     /**
-     * <p>Associates a section format ID with a {@link
-     * PropertyIDMap}.</p>
+     * Associates a section format ID with a {@link PropertyIDMap}.
      *
      * @param sectionFormatID the section format ID
      * @param propertyIDMap the property ID map
      * @return as defined by {@link java.util.Map#put}
      */
-    public PropertyIDMap put(final byte[] sectionFormatID,
-                             final PropertyIDMap propertyIDMap)
-    {
-        return (PropertyIDMap)super.put(new String(sectionFormatID, 
StringUtil.UTF8), propertyIDMap);
+    public PropertyIDMap put(ClassID sectionFormatID, PropertyIDMap 
propertyIDMap) {
+        return getInstance().put(sectionFormatID, propertyIDMap);
     }
 
     /**
-     * Associates the string representation of a section
-     *  format ID with a {@link PropertyIDMap}
+     * Associates the string representation of a section format ID with a 
{@link PropertyIDMap}
      * 
      * @param key the key of the PropertyIDMap
      * @param value the PropertyIDMap itself
@@ -168,6 +147,6 @@ public class SectionIDMap extends HashMa
      * @return the previous PropertyIDMap stored under this key, or {@code 
null} if there wasn't one
      */
     protected PropertyIDMap put(String key, PropertyIDMap value) {
-        return (PropertyIDMap)super.put(key, value);
+        return put(new ClassID(key), value);
     }
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/OldStringRecord.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/OldStringRecord.java?rev=1793596&r1=1793595&r2=1793596&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/OldStringRecord.java 
(original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/OldStringRecord.java Tue May  
2 23:27:27 2017
@@ -19,6 +19,7 @@ package org.apache.poi.hssf.record;
 
 import java.io.UnsupportedEncodingException;
 
+import org.apache.poi.hpsf.Property;
 import org.apache.poi.util.CodePageUtil;
 
 
@@ -73,7 +74,7 @@ public final class OldStringRecord {
     }
     
     protected static String getString(byte[] data, CodepageRecord codepage) {
-        int cp = CodePageUtil.CP_ISO_8859_1;
+        int cp = Property.DEFAULT_CODEPAGE;
         if (codepage != null) {
             cp = codepage.getCodepage() & 0xffff;
         }

Modified: poi/trunk/src/java/org/apache/poi/util/CodePageUtil.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/util/CodePageUtil.java?rev=1793596&r1=1793595&r2=1793596&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/util/CodePageUtil.java (original)
+++ poi/trunk/src/java/org/apache/poi/util/CodePageUtil.java Tue May  2 
23:27:27 2017
@@ -284,7 +284,7 @@ public class CodePageUtil
         
         switch (codepage) {
             case CP_UTF16:
-                return "UTF-16";
+                return "UTF-16LE";
             case CP_UTF16_BE:
                 return "UTF-16BE";
             case CP_UTF8:
@@ -466,6 +466,7 @@ public class CodePageUtil
             sb.append((char)c);
             c = reader.read();
         }
+        reader.close();
         return sb.toString();
     }
 }

Modified: 
poi/trunk/src/java/org/apache/poi/util/LittleEndianByteArrayInputStream.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/util/LittleEndianByteArrayInputStream.java?rev=1793596&r1=1793595&r2=1793596&view=diff
==============================================================================
--- 
poi/trunk/src/java/org/apache/poi/util/LittleEndianByteArrayInputStream.java 
(original)
+++ 
poi/trunk/src/java/org/apache/poi/util/LittleEndianByteArrayInputStream.java 
Tue May  2 23:27:27 2017
@@ -22,20 +22,20 @@ import java.io.ByteArrayInputStream;
 /**
  * Adapts a plain byte array to {@link LittleEndianInput}
  */
-public final class LittleEndianByteArrayInputStream extends 
ByteArrayInputStream implements LittleEndianInput {
+public class LittleEndianByteArrayInputStream extends ByteArrayInputStream 
implements LittleEndianInput {
        public LittleEndianByteArrayInputStream(byte[] buf, int startOffset, 
int maxReadLen) { // NOSONAR
            super(buf, startOffset, maxReadLen);
        }
        
        public LittleEndianByteArrayInputStream(byte[] buf, int startOffset) {
-           super(buf, startOffset, buf.length - startOffset);
+           this(buf, startOffset, buf.length - startOffset);
        }
        
        public LittleEndianByteArrayInputStream(byte[] buf) {
-           super(buf);
+           this(buf, 0);
        }
 
-       private void checkPosition(int i) {
+       protected void checkPosition(int i) {
                if (i > count - pos) {
                        throw new RuntimeException("Buffer overrun");
                }
@@ -45,6 +45,14 @@ public final class LittleEndianByteArray
                return pos;
        }
 
+       public void setReadIndex(int pos) {
+          if (pos < 0 || pos >= count) {
+               throw new IndexOutOfBoundsException();
+          }
+          this.pos = pos;
+       }
+       
+       
        @Override
     public byte readByte() {
                checkPosition(1);
@@ -73,24 +81,28 @@ public final class LittleEndianByteArray
 
        @Override
     public short readShort() {
-               return (short)readUShort();
+        final int size = LittleEndianConsts.SHORT_SIZE;
+        checkPosition(size);
+        short le = LittleEndian.getShort(buf, pos);
+        long skipped = super.skip(size);
+        assert skipped == size : "Buffer overrun";
+        return le;
        }
 
        @Override
     public int readUByte() {
-           return readByte() & 0xFF;
+           return readByte() & 0x00FF;
        }
 
        @Override
     public int readUShort() {
-        final int size = LittleEndianConsts.SHORT_SIZE;
-        checkPosition(size);
-        int le = LittleEndian.getUShort(buf, pos);
-        long skipped = super.skip(size);
-        assert skipped == size : "Buffer overrun";
-        return le;
+        return readShort() & 0x00FFFF;
        }
 
+       public long readUInt() {
+           return readInt() & 0x00FFFFFFFFL; 
+    }
+
     @Override
     public double readDouble() {
         return Double.longBitsToDouble(readLong());

Modified: poi/trunk/src/java/org/apache/poi/util/LittleEndianCP950Reader.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/util/LittleEndianCP950Reader.java?rev=1793596&r1=1793595&r2=1793596&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/util/LittleEndianCP950Reader.java 
(original)
+++ poi/trunk/src/java/org/apache/poi/util/LittleEndianCP950Reader.java Tue May 
 2 23:27:27 2017
@@ -32,7 +32,7 @@ public class LittleEndianCP950Reader ext
     private static final POILogger LOGGER = 
POILogFactory.getLogger(LittleEndianCP950Reader.class);
 
 
-    private static final char UNMAPPABLE = (char) '?';
+    private static final char UNMAPPABLE = '?';
     private final ByteBuffer doubleByteBuffer = ByteBuffer.allocate(2);
     private final CharBuffer charBuffer = CharBuffer.allocate(2);
     private final CharsetDecoder decoder = StringUtil.BIG5.newDecoder();
@@ -131,8 +131,7 @@ public class LittleEndianCP950Reader ext
     }
 
     @Override
-    public void close() throws IOException {
-
+    public void close() {
     }
 
     private int handleRange1(int leading, int trailing) {

Modified: poi/trunk/src/java/org/apache/poi/util/LocaleUtil.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/util/LocaleUtil.java?rev=1793596&r1=1793595&r2=1793596&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/util/LocaleUtil.java (original)
+++ poi/trunk/src/java/org/apache/poi/util/LocaleUtil.java Tue May  2 23:27:27 
2017
@@ -146,5 +146,475 @@ public final class LocaleUtil {
     public static Calendar getLocaleCalendar(TimeZone timeZone) {
         return Calendar.getInstance(timeZone, getUserLocale());
     }
+    
+    /**
+     * Decode the language ID from LCID value
+     *
+     * @param lcid
+     * @return
+     */
+    public static String getLocaleFromLCID(int lcid) {
+        int languageId = lcid & 0xFFFF;
+        switch (languageId) {
+        case 0x0001: return "ar";
+        case 0x0002: return "bg";
+        case 0x0003: return "ca";
+        case 0x0004: return "zh-Hans";
+        case 0x0005: return "cs";
+        case 0x0006: return "da";
+        case 0x0007: return "de";
+        case 0x0008: return "el";
+        case 0x0009: return "en";
+        case 0x000a: return "es";
+        case 0x000b: return "fi";
+        case 0x000c: return "fr";
+        case 0x000d: return "he";
+        case 0x000e: return "hu";
+        case 0x000f: return "is";
+        case 0x0010: return "it";
+        case 0x0011: return "ja";
+        case 0x0012: return "ko";
+        case 0x0013: return "nl";
+        case 0x0014: return "no";
+        case 0x0015: return "pl";
+        case 0x0016: return "pt";
+        case 0x0017: return "rm";
+        case 0x0018: return "ro";
+        case 0x0019: return "ru";
+        case 0x001a: return "bs, hr, or sr";
+        case 0x001b: return "sk";
+        case 0x001c: return "sq";
+        case 0x001d: return "sv";
+        case 0x001e: return "th";
+        case 0x001f: return "tr";
+        case 0x0020: return "ur";
+        case 0x0021: return "id";
+        case 0x0022: return "uk";
+        case 0x0023: return "be";
+        case 0x0024: return "sl";
+        case 0x0025: return "et";
+        case 0x0026: return "lv";
+        case 0x0027: return "lt";
+        case 0x0028: return "tg";
+        case 0x0029: return "fa";
+        case 0x002a: return "vi";
+        case 0x002b: return "hy";
+        case 0x002c: return "az";
+        case 0x002d: return "eu";
+        case 0x002e: return "dsb or hsb";
+        case 0x002f: return "mk";
+        case 0x0030: return "st"; // reserved
+        case 0x0031: return "ts"; // reserved
+        case 0x0032: return "tn";
+        case 0x0033: return "ve"; // reserved
+        case 0x0034: return "xh";
+        case 0x0035: return "zu";
+        case 0x0036: return "af";
+        case 0x0037: return "ka";
+        case 0x0038: return "fo";
+        case 0x0039: return "hi";
+        case 0x003a: return "mt";
+        case 0x003b: return "se";
+        case 0x003c: return "ga";
+        case 0x003d: return "yi"; // reserved
+        case 0x003e: return "ms";
+        case 0x003f: return "kk";
+        case 0x0040: return "ky";
+        case 0x0041: return "sw";
+        case 0x0042: return "tk";
+        case 0x0043: return "uz";
+        case 0x0044: return "tt";
+        case 0x0045: return "bn";
+        case 0x0046: return "pa";
+        case 0x0047: return "gu";
+        case 0x0048: return "or";
+        case 0x0049: return "ta";
+        case 0x004a: return "te";
+        case 0x004b: return "kn";
+        case 0x004c: return "ml";
+        case 0x004d: return "as";
+        case 0x004e: return "mr";
+        case 0x004f: return "sa";
+        case 0x0050: return "mn";
+        case 0x0051: return "bo";
+        case 0x0052: return "cy";
+        case 0x0053: return "km";
+        case 0x0054: return "lo";
+        case 0x0055: return "my"; // reserved
+        case 0x0056: return "gl";
+        case 0x0057: return "kok";
+        case 0x0058: return "mni"; // reserved
+        case 0x0059: return "sd";
+        case 0x005a: return "syr";
+        case 0x005b: return "si";
+        case 0x005c: return "chr";
+        case 0x005d: return "iu";
+        case 0x005e: return "am";
+        case 0x005f: return "tzm";
+        case 0x0060: return "ks"; // reserved
+        case 0x0061: return "ne";
+        case 0x0062: return "fy";
+        case 0x0063: return "ps";
+        case 0x0064: return "fil";
+        case 0x0065: return "dv";
+        case 0x0066: return "bin"; // reserved
+        case 0x0067: return "ff";
+        case 0x0068: return "ha";
+        case 0x0069: return "ibb"; // reserved
+        case 0x006a: return "yo";
+        case 0x006b: return "quz";
+        case 0x006c: return "nso";
+        case 0x006d: return "ba";
+        case 0x006e: return "lb";
+        case 0x006f: return "kl";
+        case 0x0070: return "ig";
+        case 0x0071: return "kr"; // reserved
+        case 0x0072: return "om"; // reserved
+        case 0x0073: return "ti";
+        case 0x0074: return "gn"; // reserved
+        case 0x0075: return "haw";
+        case 0x0076: return "la"; // reserved
+        case 0x0077: return "so"; // reserved
+        case 0x0078: return "ii";
+        case 0x0079: return "pap"; // reserved
+        case 0x007a: return "arn";
+        case 0x007b: return "invalid"; // Neither defined nor reserved
+        case 0x007c: return "moh";
+        case 0x007d: return "invalid"; // Neither defined nor reserved
+        case 0x007e: return "br";
+        case 0x007f: return "invalid"; // Reserved or invariant locale behavior
+        case 0x0080: return "ug";
+        case 0x0081: return "mi";
+        case 0x0082: return "oc";
+        case 0x0083: return "co";
+        case 0x0084: return "gsw";
+        case 0x0085: return "sah";
+        case 0x0086: return "qut";
+        case 0x0087: return "rw";
+        case 0x0088: return "wo";
+        case 0x0089: return "invalid"; // Neither defined nor reserved
+        case 0x008a: return "invalid"; // Neither defined nor reserved
+        case 0x008b: return "invalid"; // Neither defined nor reserved
+        case 0x008c: return "prs";
+        case 0x008d: return "invalid"; // Neither defined nor reserved
+        case 0x008e: return "invalid"; // Neither defined nor reserved
+        case 0x008f: return "invalid"; // Neither defined nor reserved
+        case 0x0090: return "invalid"; // Neither defined nor reserved
+        case 0x0091: return "gd";
+        case 0x0092: return "ku";
+        case 0x0093: return "quc"; // reserved
+        case 0x0401: return "ar-SA";
+        case 0x0402: return "bg-BG";
+        case 0x0403: return "ca-ES";
+        case 0x0404: return "zh-TW";
+        case 0x0405: return "cs-CZ";
+        case 0x0406: return "da-DK";
+        case 0x0407: return "de-DE";
+        case 0x0408: return "el-GR";
+        case 0x0409: return "en-US";
+        case 0x040a: return "es-ES_tradnl";
+        case 0x040b: return "fi-FI";
+        case 0x040c: return "fr-FR";
+        case 0x040d: return "he-IL";
+        case 0x040e: return "hu-HU";
+        case 0x040f: return "is-IS";
+        case 0x0410: return "it-IT";
+        case 0x0411: return "ja-JP";
+        case 0x0412: return "ko-KR";
+        case 0x0413: return "nl-NL";
+        case 0x0414: return "nb-NO";
+        case 0x0415: return "pl-PL";
+        case 0x0416: return "pt-BR";
+        case 0x0417: return "rm-CH";
+        case 0x0418: return "ro-RO";
+        case 0x0419: return "ru-RU";
+        case 0x041a: return "hr-HR";
+        case 0x041b: return "sk-SK";
+        case 0x041c: return "sq-AL";
+        case 0x041d: return "sv-SE";
+        case 0x041e: return "th-TH";
+        case 0x041f: return "tr-TR";
+        case 0x0420: return "ur-PK";
+        case 0x0421: return "id-ID";
+        case 0x0422: return "uk-UA";
+        case 0x0423: return "be-BY";
+        case 0x0424: return "sl-SI";
+        case 0x0425: return "et-EE";
+        case 0x0426: return "lv-LV";
+        case 0x0427: return "lt-LT";
+        case 0x0428: return "tg-Cyrl-TJ";
+        case 0x0429: return "fa-IR";
+        case 0x042a: return "vi-VN";
+        case 0x042b: return "hy-AM";
+        case 0x042c: return "az-Latn-AZ";
+        case 0x042d: return "eu-ES";
+        case 0x042e: return "hsb-DE";
+        case 0x042f: return "mk-MK";
+        case 0x0430: return "st-ZA"; // reserved
+        case 0x0431: return "ts-ZA"; // reserved
+        case 0x0432: return "tn-ZA";
+        case 0x0433: return "ve-ZA"; // reserved
+        case 0x0434: return "xh-ZA";
+        case 0x0435: return "zu-ZA";
+        case 0x0436: return "af-ZA";
+        case 0x0437: return "ka-GE";
+        case 0x0438: return "fo-FO";
+        case 0x0439: return "hi-IN";
+        case 0x043a: return "mt-MT";
+        case 0x043b: return "se-NO";
+        case 0x043d: return "yi-Hebr"; // reserved
+        case 0x043e: return "ms-MY";
+        case 0x043f: return "kk-KZ";
+        case 0x0440: return "ky-KG";
+        case 0x0441: return "sw-KE";
+        case 0x0442: return "tk-TM";
+        case 0x0443: return "uz-Latn-UZ";
+        case 0x0444: return "tt-RU";
+        case 0x0445: return "bn-IN";
+        case 0x0446: return "pa-IN";
+        case 0x0447: return "gu-IN";
+        case 0x0448: return "or-IN";
+        case 0x0449: return "ta-IN";
+        case 0x044a: return "te-IN";
+        case 0x044b: return "kn-IN";
+        case 0x044c: return "ml-IN";
+        case 0x044d: return "as-IN";
+        case 0x044e: return "mr-IN";
+        case 0x044f: return "sa-IN";
+        case 0x0450: return "mn-MN";
+        case 0x0451: return "bo-CN";
+        case 0x0452: return "cy-GB";
+        case 0x0453: return "km-KH";
+        case 0x0454: return "lo-LA";
+        case 0x0455: return "my-MM"; // reserved
+        case 0x0456: return "gl-ES";
+        case 0x0457: return "kok-IN";
+        case 0x0458: return "mni-IN"; // reserved
+        case 0x0459: return "sd-Deva-IN"; // reserved
+        case 0x045a: return "syr-SY";
+        case 0x045b: return "si-LK";
+        case 0x045c: return "chr-Cher-US";
+        case 0x045d: return "iu-Cans-CA";
+        case 0x045e: return "am-ET";
+        case 0x045f: return "tzm-Arab-MA"; // reserved
+        case 0x0460: return "ks-Arab"; // reserved
+        case 0x0461: return "ne-NP";
+        case 0x0462: return "fy-NL";
+        case 0x0463: return "ps-AF";
+        case 0x0464: return "fil-PH";
+        case 0x0465: return "dv-MV";
+        case 0x0466: return "bin-NG"; // reserved
+        case 0x0467: return "fuv-NG"; // reserved
+        case 0x0468: return "ha-Latn-NG";
+        case 0x0469: return "ibb-NG"; // reserved
+        case 0x046a: return "yo-NG";
+        case 0x046b: return "quz-BO";
+        case 0x046c: return "nso-ZA";
+        case 0x046d: return "ba-RU";
+        case 0x046e: return "lb-LU";
+        case 0x046f: return "kl-GL";
+        case 0x0470: return "ig-NG";
+        case 0x0471: return "kr-NG"; // reserved
+        case 0x0472: return "om-Ethi-ET"; // reserved
+        case 0x0473: return "ti-ET";
+        case 0x0474: return "gn-PY"; // reserved
+        case 0x0475: return "haw-US";
+        case 0x0476: return "la-Latn"; // reserved
+        case 0x0477: return "so-SO"; // reserved
+        case 0x0478: return "ii-CN";
+        case 0x0479: return "pap-x029"; // reserved
+        case 0x047a: return "arn-CL";
+        case 0x047c: return "moh-CA";
+        case 0x047e: return "br-FR";
+        case 0x0480: return "ug-CN";
+        case 0x0481: return "mi-NZ";
+        case 0x0482: return "oc-FR";
+        case 0x0483: return "co-FR";
+        case 0x0484: return "gsw-FR";
+        case 0x0485: return "sah-RU";
+        case 0x0486: return "qut-GT";
+        case 0x0487: return "rw-RW";
+        case 0x0488: return "wo-SN";
+        case 0x048c: return "prs-AF";
+        case 0x048d: return "plt-MG"; // reserved
+        case 0x048e: return "zh-yue-HK"; // reserved
+        case 0x048f: return "tdd-Tale-CN"; // reserved
+        case 0x0490: return "khb-Talu-CN"; // reserved
+        case 0x0491: return "gd-GB";
+        case 0x0492: return "ku-Arab-IQ";
+        case 0x0493: return "quc-CO"; // reserved
+        case 0x0501: return "qps-ploc";
+        case 0x05fe: return "qps-ploca";
+        case 0x0801: return "ar-IQ";
+        case 0x0803: return "ca-ES-valencia";
+        case 0x0804: return "zh-CN";
+        case 0x0807: return "de-CH";
+        case 0x0809: return "en-GB";
+        case 0x080a: return "es-MX";
+        case 0x080c: return "fr-BE";
+        case 0x0810: return "it-CH";
+        case 0x0811: return "ja-Ploc-JP"; // reserved
+        case 0x0813: return "nl-BE";
+        case 0x0814: return "nn-NO";
+        case 0x0816: return "pt-PT";
+        case 0x0818: return "ro-MO"; // reserved
+        case 0x0819: return "ru-MO"; // reserved
+        case 0x081a: return "sr-Latn-CS";
+        case 0x081d: return "sv-FI";
+        case 0x0820: return "ur-IN"; // reserved
+        case 0x0827: return "invalid"; // Neither defined nor reserved
+        case 0x082c: return "az-Cyrl-AZ";
+        case 0x082e: return "dsb-DE";
+        case 0x0832: return "tn-BW";
+        case 0x083b: return "se-SE";
+        case 0x083c: return "ga-IE";
+        case 0x083e: return "ms-BN";
+        case 0x0843: return "uz-Cyrl-UZ";
+        case 0x0845: return "bn-BD";
+        case 0x0846: return "pa-Arab-PK";
+        case 0x0849: return "ta-LK";
+        case 0x0850: return "mn-Mong-CN";
+        case 0x0851: return "bo-BT"; // reserved
+        case 0x0859: return "sd-Arab-PK";
+        case 0x085d: return "iu-Latn-CA";
+        case 0x085f: return "tzm-Latn-DZ";
+        case 0x0860: return "ks-Deva"; // reserved
+        case 0x0861: return "ne-IN"; // reserved
+        case 0x0867: return "ff-Latn-SN";
+        case 0x086b: return "quz-EC";
+        case 0x0873: return "ti-ER";
+        case 0x09ff: return "qps-plocm";
+        case 0x0c01: return "ar-EG";
+        case 0x0c04: return "zh-HK";
+        case 0x0c07: return "de-AT";
+        case 0x0c09: return "en-AU";
+        case 0x0c0a: return "es-ES";
+        case 0x0c0c: return "fr-CA";
+        case 0x0c1a: return "sr-Cyrl-CS";
+        case 0x0c3b: return "se-FI";
+        case 0x0c5f: return "tmz-MA"; // reserved
+        case 0x0c6b: return "quz-PE";
+        case 0x1001: return "ar-LY";
+        case 0x1004: return "zh-SG";
+        case 0x1007: return "de-LU";
+        case 0x1009: return "en-CA";
+        case 0x100a: return "es-GT";
+        case 0x100c: return "fr-CH";
+        case 0x101a: return "hr-BA";
+        case 0x103b: return "smj-NO";
+        case 0x1401: return "ar-DZ";
+        case 0x1404: return "zh-MO";
+        case 0x1407: return "de-LI";
+        case 0x1409: return "en-NZ";
+        case 0x140a: return "es-CR";
+        case 0x140c: return "fr-LU";
+        case 0x141a: return "bs-Latn-BA";
+        case 0x143b: return "smj-SE";
+        case 0x1801: return "ar-MA";
+        case 0x1809: return "en-IE";
+        case 0x180a: return "es-PA";
+        case 0x180c: return "fr-MC";
+        case 0x181a: return "sr-Latn-BA";
+        case 0x183b: return "sma-NO";
+        case 0x1c01: return "ar-TN";
+        case 0x1c09: return "en-ZA";
+        case 0x1c0a: return "es-DO";
+        case 0x1c0c: return "invalid"; // Neither defined nor reserved
+        case 0x1c1a: return "sr-Cyrl-BA";
+        case 0x1c3b: return "sma-SE";
+        case 0x2001: return "ar-OM";
+        case 0x2008: return "invalid"; // Neither defined nor reserved
+        case 0x2009: return "en-JM";
+        case 0x200a: return "es-VE";
+        case 0x200c: return "fr-RE"; // reserved
+        case 0x201a: return "bs-Cyrl-BA";
+        case 0x203b: return "sms-FI";
+        case 0x2401: return "ar-YE";
+        case 0x2409: return "en-029";
+        case 0x240a: return "es-CO";
+        case 0x240c: return "fr-CG"; // reserved
+        case 0x241a: return "sr-Latn-RS";
+        case 0x243b: return "smn-FI";
+        case 0x2801: return "ar-SY";
+        case 0x2809: return "en-BZ";
+        case 0x280a: return "es-PE";
+        case 0x280c: return "fr-SN"; // reserved
+        case 0x281a: return "sr-Cyrl-RS";
+        case 0x2c01: return "ar-JO";
+        case 0x2c09: return "en-TT";
+        case 0x2c0a: return "es-AR";
+        case 0x2c0c: return "fr-CM"; // reserved
+        case 0x2c1a: return "sr-Latn-ME";
+        case 0x3001: return "ar-LB";
+        case 0x3009: return "en-ZW";
+        case 0x300a: return "es-EC";
+        case 0x300c: return "fr-CI"; // reserved
+        case 0x301a: return "sr-Cyrl-ME";
+        case 0x3401: return "ar-KW";
+        case 0x3409: return "en-PH";
+        case 0x340a: return "es-CL";
+        case 0x340c: return "fr-ML"; // reserved
+        case 0x3801: return "ar-AE";
+        case 0x3809: return "en-ID"; // reserved
+        case 0x380a: return "es-UY";
+        case 0x380c: return "fr-MA"; // reserved
+        case 0x3c01: return "ar-BH";
+        case 0x3c09: return "en-HK"; // reserved
+        case 0x3c0a: return "es-PY";
+        case 0x3c0c: return "fr-HT"; // reserved
+        case 0x4001: return "ar-QA";
+        case 0x4009: return "en-IN";
+        case 0x400a: return "es-BO";
+        case 0x4401: return "ar-Ploc-SA"; // reseærved
+        case 0x4409: return "en-MY";
+        case 0x440a: return "es-SV";
+        case 0x4801: return "ar-145"; // reserved
+        case 0x4809: return "en-SG";
+        case 0x480a: return "es-HN";
+        case 0x4c09: return "en-AE"; // reserved
+        case 0x4c0a: return "es-NI";
+        case 0x5009: return "en-BH"; // reserved
+        case 0x500a: return "es-PR";
+        case 0x5409: return "en-EG"; // reserved
+        case 0x540a: return "es-US";
+        case 0x5809: return "en-JO"; // reserved
+        case 0x5c09: return "en-KW"; // reserved
+        case 0x6009: return "en-TR"; // reserved
+        case 0x6409: return "en-YE"; // reserved
+        case 0x641a: return "bs-Cyrl";
+        case 0x681a: return "bs-Latn";
+        case 0x6c1a: return "sr-Cyrl";
+        case 0x701a: return "sr-Latn";
+        case 0x703b: return "smn";
+        case 0x742c: return "az-Cyrl";
+        case 0x743b: return "sms";
+        case 0x7804: return "zh";
+        case 0x7814: return "nn";
+        case 0x781a: return "bs";
+        case 0x782c: return "az-Latn";
+        case 0x783b: return "sma";
+        case 0x7843: return "uz-Cyrl";
+        case 0x7850: return "mn-Cyrl";
+        case 0x785d: return "iu-Cans";
+        case 0x7c04: return "zh-Hant";
+        case 0x7c14: return "nb";
+        case 0x7c1a: return "sr";
+        case 0x7c28: return "tg-Cyrl";
+        case 0x7c2e: return "dsb";
+        case 0x7c3b: return "smj";
+        case 0x7c43: return "uz-Latn";
+        case 0x7c46: return "pa-Arab";
+        case 0x7c50: return "mn-Mong";
+        case 0x7c59: return "sd-Arab";
+        case 0x7c5c: return "chr-Cher";
+        case 0x7c5d: return "iu-Latn";
+        case 0x7c5f: return "tzm-Latn";
+        case 0x7c67: return "ff-Latn";
+        case 0x7c68: return "ha-Latn";
+        case 0x7c92: return "ku-Arab";
+        default: return "invalid";
+        }
+    }
+    
 }
 

Modified: poi/trunk/src/testcases/org/apache/poi/hpsf/basic/TestBasic.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hpsf/basic/TestBasic.java?rev=1793596&r1=1793595&r2=1793596&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hpsf/basic/TestBasic.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hpsf/basic/TestBasic.java Tue May  2 
23:27:27 2017
@@ -192,7 +192,7 @@ public final class TestBasic {
                 (poiFiles[0].getBytes()));
         final List<Section> sections = si.getSections();
         final Section s = sections.get(0);
-        assertArrayEquals(s.getFormatID().getBytes(), 
SectionIDMap.SUMMARY_INFORMATION_ID);
+        assertEquals(s.getFormatID(), SectionIDMap.SUMMARY_INFORMATION_ID);
         assertNotNull(s.getProperties());
         assertEquals(17, s.getPropertyCount());
         assertEquals("Titel", s.getProperty(2));



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to