Author: kiwiwings
Date: Tue May 2 23:24:50 2017
New Revision: 1793594
URL: http://svn.apache.org/viewvc?rev=1793594&view=rev
Log:
HPSF: Use LittleEndianStream instead of offset calculation
Modified:
poi/trunk/src/java/org/apache/poi/hpsf/Array.java
poi/trunk/src/java/org/apache/poi/hpsf/Blob.java
poi/trunk/src/java/org/apache/poi/hpsf/ClassID.java
poi/trunk/src/java/org/apache/poi/hpsf/ClipboardData.java
poi/trunk/src/java/org/apache/poi/hpsf/CodePageString.java
poi/trunk/src/java/org/apache/poi/hpsf/Currency.java
poi/trunk/src/java/org/apache/poi/hpsf/CustomProperties.java
poi/trunk/src/java/org/apache/poi/hpsf/Date.java
poi/trunk/src/java/org/apache/poi/hpsf/Decimal.java
poi/trunk/src/java/org/apache/poi/hpsf/DocumentSummaryInformation.java
poi/trunk/src/java/org/apache/poi/hpsf/Filetime.java
poi/trunk/src/java/org/apache/poi/hpsf/GUID.java
poi/trunk/src/java/org/apache/poi/hpsf/IndirectPropertyName.java
poi/trunk/src/java/org/apache/poi/hpsf/MutableProperty.java
poi/trunk/src/java/org/apache/poi/hpsf/PropertySet.java
poi/trunk/src/java/org/apache/poi/hpsf/TypeWriter.java
poi/trunk/src/java/org/apache/poi/hpsf/TypedPropertyValue.java
poi/trunk/src/java/org/apache/poi/hpsf/UnicodeString.java
poi/trunk/src/java/org/apache/poi/hpsf/Util.java
poi/trunk/src/java/org/apache/poi/hpsf/Variant.java
poi/trunk/src/java/org/apache/poi/hpsf/VariantBool.java
poi/trunk/src/java/org/apache/poi/hpsf/Vector.java
poi/trunk/src/java/org/apache/poi/hpsf/VersionedStream.java
Modified: poi/trunk/src/java/org/apache/poi/hpsf/Array.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hpsf/Array.java?rev=1793594&r1=1793593&r2=1793594&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hpsf/Array.java (original)
+++ poi/trunk/src/java/org/apache/poi/hpsf/Array.java Tue May 2 23:24:50 2017
@@ -17,23 +17,19 @@
package org.apache.poi.hpsf;
import org.apache.poi.util.Internal;
-import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianByteArrayInputStream;
@Internal
class Array
{
- static class ArrayDimension
- {
- static final int SIZE = 8;
-
- private int _indexOffset;
+ static class ArrayDimension {
private long _size;
+ @SuppressWarnings("unused")
+ private int _indexOffset;
- ArrayDimension( byte[] data, int offset )
- {
- _size = LittleEndian.getUInt( data, offset );
- _indexOffset = LittleEndian.getInt( data, offset
- + LittleEndian.INT_SIZE );
+ void read( LittleEndianByteArrayInputStream lei ) {
+ _size = lei.readUInt();
+ _indexOffset = lei.readInt();
}
}
@@ -42,96 +38,69 @@ class Array
private ArrayDimension[] _dimensions;
private int _type;
- ArrayHeader( byte[] data, int startOffset )
- {
- int offset = startOffset;
-
- _type = LittleEndian.getInt( data, offset );
- offset += LittleEndian.INT_SIZE;
-
- long numDimensionsUnsigned = LittleEndian.getUInt( data, offset );
- offset += LittleEndian.INT_SIZE;
-
- if ( !( 1 <= numDimensionsUnsigned && numDimensionsUnsigned <= 31
) )
- throw new IllegalPropertySetDataException(
- "Array dimension number " + numDimensionsUnsigned
- + " is not in [1; 31] range" );
+ void read( LittleEndianByteArrayInputStream lei ) {
+ _type = lei.readInt();
+
+ long numDimensionsUnsigned = lei.readUInt();
+
+ if ( !( 1 <= numDimensionsUnsigned && numDimensionsUnsigned <= 31
) ) {
+ String msg = "Array dimension number "+numDimensionsUnsigned+"
is not in [1; 31] range";
+ throw new IllegalPropertySetDataException(msg);
+ }
+
int numDimensions = (int) numDimensionsUnsigned;
_dimensions = new ArrayDimension[numDimensions];
- for ( int i = 0; i < numDimensions; i++ )
- {
- _dimensions[i] = new ArrayDimension( data, offset );
- offset += ArrayDimension.SIZE;
+ for ( int i = 0; i < numDimensions; i++ ) {
+ ArrayDimension ad = new ArrayDimension();
+ ad.read(lei);
+ _dimensions[i] = ad;
}
}
- long getNumberOfScalarValues()
- {
+ long getNumberOfScalarValues() {
long result = 1;
- for ( ArrayDimension dimension : _dimensions )
+ for ( ArrayDimension dimension : _dimensions ) {
result *= dimension._size;
+ }
return result;
}
- int getSize()
- {
- return LittleEndian.INT_SIZE * 2 + _dimensions.length
- * ArrayDimension.SIZE;
- }
-
- int getType()
- {
+ int getType() {
return _type;
}
}
- private ArrayHeader _header;
+ private final ArrayHeader _header = new ArrayHeader();
private TypedPropertyValue[] _values;
- Array()
- {
- }
-
- Array( final byte[] data, final int offset )
- {
- read( data, offset );
- }
-
- int read( final byte[] data, final int startOffset )
- {
- int offset = startOffset;
+ Array() {}
- _header = new ArrayHeader( data, offset );
- offset += _header.getSize();
+ void read( LittleEndianByteArrayInputStream lei ) {
+ _header.read(lei);
long numberOfScalarsLong = _header.getNumberOfScalarValues();
- if ( numberOfScalarsLong > Integer.MAX_VALUE )
- throw new UnsupportedOperationException(
- "Sorry, but POI can't store array of properties with size
of "
- + numberOfScalarsLong + " in memory" );
+ if ( numberOfScalarsLong > Integer.MAX_VALUE ) {
+ String msg =
+ "Sorry, but POI can't store array of properties with size of "
+
+ numberOfScalarsLong + " in memory";
+ throw new UnsupportedOperationException(msg);
+ }
int numberOfScalars = (int) numberOfScalarsLong;
_values = new TypedPropertyValue[numberOfScalars];
- final int type = _header._type;
- if ( type == Variant.VT_VARIANT )
- {
- for ( int i = 0; i < numberOfScalars; i++ )
- {
- TypedPropertyValue typedPropertyValue = new
TypedPropertyValue();
- offset += typedPropertyValue.read( data, offset );
- }
- }
- else
- {
- for ( int i = 0; i < numberOfScalars; i++ )
- {
- TypedPropertyValue typedPropertyValue = new TypedPropertyValue(
- type, null );
- offset += typedPropertyValue.readValuePadded( data, offset );
+ int paddedType = (_header._type == Variant.VT_VARIANT) ? 0 :
_header._type;
+ for ( int i = 0; i < numberOfScalars; i++ ) {
+ TypedPropertyValue typedPropertyValue = new
TypedPropertyValue(paddedType, null);
+ typedPropertyValue.read(lei);
+ _values[i] = typedPropertyValue;
+ if (paddedType != 0) {
+ TypedPropertyValue.skipPadding(lei);
}
}
-
- return offset - startOffset;
+ }
+
+ TypedPropertyValue[] getValues(){
+ return _values;
}
}
Modified: poi/trunk/src/java/org/apache/poi/hpsf/Blob.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hpsf/Blob.java?rev=1793594&r1=1793593&r2=1793594&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hpsf/Blob.java (original)
+++ poi/trunk/src/java/org/apache/poi/hpsf/Blob.java Tue May 2 23:24:50 2017
@@ -17,29 +17,19 @@
package org.apache.poi.hpsf;
import org.apache.poi.util.Internal;
-import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianInput;
@Internal
-class Blob
-{
+class Blob {
private byte[] _value;
- Blob( byte[] data, int offset )
- {
- int size = LittleEndian.getInt( data, offset );
-
- if ( size == 0 )
- {
- _value = new byte[0];
- return;
+ Blob() {}
+
+ void read( LittleEndianInput lei ) {
+ int size = lei.readInt();
+ _value = new byte[size];
+ if ( size > 0 ) {
+ lei.readFully(_value);
}
-
- _value = LittleEndian.getByteArray( data, offset
- + LittleEndian.INT_SIZE, size );
- }
-
- int getSize()
- {
- return LittleEndian.INT_SIZE + _value.length;
}
}
Modified: poi/trunk/src/java/org/apache/poi/hpsf/ClassID.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hpsf/ClassID.java?rev=1793594&r1=1793593&r2=1793594&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hpsf/ClassID.java (original)
+++ poi/trunk/src/java/org/apache/poi/hpsf/ClassID.java Tue May 2 23:24:50 2017
@@ -20,16 +20,16 @@ package org.apache.poi.hpsf;
import java.util.Arrays;
import org.apache.poi.util.HexDump;
-import org.apache.poi.util.StringUtil;
/**
- * <p>Represents a class ID (16 bytes). Unlike other little-endian
- * type the {@link ClassID} is not just 16 bytes stored in the wrong
- * order. Instead, it is a double word (4 bytes) followed by two
- * words (2 bytes each) followed by 8 bytes.</p>
+ * Represents a class ID (16 bytes). Unlike other little-endian
+ * type the {@link ClassID} is not just 16 bytes stored in the wrong
+ * order. Instead, it is a double word (4 bytes) followed by two
+ * words (2 bytes each) followed by 8 bytes.<p>
+ *
+ * The ClassID (or CLSID) is a UUID - see RFC 4122
*/
-public class ClassID
-{
+public class ClassID {
public static final ClassID OLE10_PACKAGE = new
ClassID("{0003000C-0000-0000-C000-000000000046}");
public static final ClassID PPT_SHOW = new
ClassID("{64818D10-4F9B-11CF-86EA-00AA00B929E8}");
public static final ClassID XLS_WORKBOOK = new
ClassID("{00020841-0000-0000-C000-000000000046}");
@@ -68,21 +68,16 @@ public class ClassID
public static final ClassID EQUATION30 = new
ClassID("{0002CE02-0000-0000-C000-000000000046}");
- /** <p>The number of bytes occupied by this object in the byte
- * stream.</p> */
+ /** The number of bytes occupied by this object in the byte stream. */
public static final int LENGTH = 16;
/**
- * <p>The bytes making out the class ID in correct order,
- * i.e. big-endian.</p>
+ * The bytes making out the class ID in correct order, i.e. big-endian.
*/
private final byte[] bytes = new byte[LENGTH];
-
-
/**
- * <p>Creates a {@link ClassID} and reads its value from a byte
- * array.</p>
+ * Creates a {@link ClassID} and reads its value from a byte array.
*
* @param src The byte array to read from.
* @param offset The offset of the first byte to read.
@@ -93,8 +88,7 @@ public class ClassID
/**
- * <p>Creates a {@link ClassID} and initializes its value with
- * 0x00 bytes.</p>
+ * Creates a {@link ClassID} and initializes its value with 0x00 bytes.
*/
public ClassID() {
Arrays.fill(bytes, (byte)0);
@@ -102,8 +96,8 @@ public class ClassID
/**
- * <p>Creates a {@link ClassID} from a human-readable representation of
the Class ID in standard
- * format <code>"{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"</code>.</p>
+ * Creates a {@link ClassID} from a human-readable representation of the
Class ID in standard
+ * format {@code "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"}.
*
* @param externalForm representation of the Class ID represented by this
object.
*/
@@ -116,8 +110,7 @@ public class ClassID
/**
- * @return The number of bytes occupied by this object in the byte
- * stream.
+ * @return The number of bytes occupied by this object in the byte stream.
*/
public int length() {
return LENGTH;
@@ -126,8 +119,7 @@ public class ClassID
/**
- * <p>Gets the bytes making out the class ID. They are returned in
- * correct order, i.e. big-endian.</p>
+ * Gets the bytes making out the class ID. They are returned in correct
order, i.e. big-endian.
*
* @return the bytes making out the class ID.
*/
@@ -138,7 +130,7 @@ public class ClassID
/**
- * <p>Sets the bytes making out the class ID.</p>
+ * Sets the bytes making out the class ID.
*
* @param bytes The bytes making out the class ID in big-endian format.
They
* are copied without their order being changed.
@@ -150,13 +142,10 @@ public class ClassID
/**
- * <p>Reads the class ID's value from a byte array by turning
- * little-endian into big-endian.</p>
+ * Reads the class ID's value from a byte array by turning little-endian
into big-endian.
*
* @param src The byte array to read from
- *
- * @param offset The offset within the <var>src</var> byte array
- *
+ * @param offset The offset within the {@code src} byte array
* @return A byte array containing the class ID.
*/
public byte[] read(final byte[] src, final int offset) {
@@ -180,18 +169,15 @@ public class ClassID
return bytes;
}
-
-
/**
- * <p>Writes the class ID to a byte array in the
- * little-endian format.</p>
+ * Writes the class ID to a byte array in the little-endian format.
*
* @param dst The byte array to write to.
*
- * @param offset The offset within the <var>dst</var> byte array.
+ * @param offset The offset within the {@code dst} byte array.
*
* @exception ArrayStoreException if there is not enough room for the class
- * ID 16 bytes in the byte array after the <var>offset</var> position.
+ * ID 16 bytes in the byte array after the {@code offset} position.
*/
public void write(final byte[] dst, final int offset)
throws ArrayStoreException {
@@ -223,30 +209,44 @@ public class ClassID
/**
- * <p>Checks whether this <code>ClassID</code> is equal to another
- * object.</p>
+ * Checks whether this {@code ClassID} is equal to another object.
*
- * @param o the object to compare this <code>PropertySet</code> with
- * @return <code>true</code> if the objects are equal, else
- * <code>false</code>.
+ * @param o the object to compare this {@code ClassID} with
+ * @return {@code true} if the objects are equal, else {@code false}.
*/
@Override
public boolean equals(final Object o) {
- if (o == null || !(o instanceof ClassID)) {
- return false;
- }
- final ClassID cid = (ClassID) o;
- if (bytes.length != cid.bytes.length) {
- return false;
- }
- for (int i = 0; i < bytes.length; i++) {
- if (bytes[i] != cid.bytes[i]) {
- return false;
- }
- }
- return true;
+ return (o instanceof ClassID) && Arrays.equals(bytes,
((ClassID)o).bytes);
}
+ /**
+ * Checks whether this {@code ClassID} is equal to another ClassID with
inverted endianess,
+ * because there are apparently not only version 1 GUIDs (aka "network"
with big-endian encoding),
+ * but also version 2 GUIDs (aka "native" with little-endian encoding) out
there.
+ *
+ * @param o the object to compare this {@code ClassID} with
+ * @return {@code true} if the objects are equal, else {@code false}.
+ */
+ public boolean equalsInverted(ClassID o) {
+ return
+ o.bytes[0] == bytes[3] &&
+ o.bytes[1] == bytes[2] &&
+ o.bytes[2] == bytes[1] &&
+ o.bytes[3] == bytes[0] &&
+ o.bytes[4] == bytes[5] &&
+ o.bytes[5] == bytes[4] &&
+ o.bytes[6] == bytes[7] &&
+ o.bytes[7] == bytes[6] &&
+ o.bytes[8] == bytes[8] &&
+ o.bytes[9] == bytes[9] &&
+ o.bytes[10] == bytes[10] &&
+ o.bytes[11] == bytes[11] &&
+ o.bytes[12] == bytes[12] &&
+ o.bytes[13] == bytes[13] &&
+ o.bytes[14] == bytes[14] &&
+ o.bytes[15] == bytes[15]
+ ;
+ }
/**
@@ -254,12 +254,12 @@ public class ClassID
*/
@Override
public int hashCode() {
- return new String(bytes, StringUtil.UTF8).hashCode();
+ return toString().hashCode();
}
/**
- * <p>Returns a human-readable representation of the Class ID in standard
- * format <code>"{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"</code>.</p>
+ * Returns a human-readable representation of the Class ID in standard
+ * format {@code "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"}.
*
* @return String representation of the Class ID represented by this
object.
*/
Modified: poi/trunk/src/java/org/apache/poi/hpsf/ClipboardData.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hpsf/ClipboardData.java?rev=1793594&r1=1793593&r2=1793594&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hpsf/ClipboardData.java (original)
+++ poi/trunk/src/java/org/apache/poi/hpsf/ClipboardData.java Tue May 2
23:24:50 2017
@@ -16,69 +16,60 @@
==================================================================== */
package org.apache.poi.hpsf;
-import java.io.IOException;
-import java.io.OutputStream;
-
+import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal;
-import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianByteArrayInputStream;
+import org.apache.poi.util.LittleEndianByteArrayOutputStream;
+import org.apache.poi.util.LittleEndianConsts;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
@Internal
-class ClipboardData
-{
- private static final POILogger logger = POILogFactory
- .getLogger( ClipboardData.class );
+class ClipboardData {
+ private static final POILogger LOG = POILogFactory.getLogger(
ClipboardData.class );
- private int _format;
+ private int _format = 0;
private byte[] _value;
+
+ ClipboardData() {}
- ClipboardData( byte[] data, int offset )
- {
- int size = LittleEndian.getInt( data, offset );
-
- if ( size < 4 )
- {
- logger.log( POILogger.WARN, "ClipboardData at offset ",
- Integer.valueOf( offset ), " size less than 4 bytes "
- + "(doesn't even have format field!). "
- + "Setting to format == 0 and hope for the best" );
+ void read( LittleEndianByteArrayInputStream lei ) {
+ int offset = lei.getReadIndex();
+ int size = lei.readInt();
+
+ if ( size < 4 ) {
+ String msg =
+ "ClipboardData at offset "+offset+" size less than 4 bytes "+
+ "(doesn't even have format field!). Setting to format == 0 and
hope for the best";
+ LOG.log( POILogger.WARN, msg);
_format = 0;
_value = new byte[0];
return;
}
- _format = LittleEndian.getInt( data, offset + LittleEndian.INT_SIZE );
- _value = LittleEndian.getByteArray( data, offset
- + LittleEndian.INT_SIZE * 2, size - LittleEndian.INT_SIZE );
- }
-
- int getSize()
- {
- return LittleEndian.INT_SIZE * 2 + _value.length;
+ _format = lei.readInt();
+ _value = new byte[size - LittleEndianConsts.INT_SIZE];
+ lei.readFully(_value);
}
- byte[] getValue()
- {
+ byte[] getValue() {
return _value;
}
- byte[] toByteArray()
- {
- byte[] result = new byte[getSize()];
- LittleEndian.putInt( result, 0 * LittleEndian.INT_SIZE,
- LittleEndian.INT_SIZE + _value.length );
- LittleEndian.putInt( result, 1 * LittleEndian.INT_SIZE, _format );
- System.arraycopy( _value, 0, result, LittleEndian.INT_SIZE
- + LittleEndian.INT_SIZE, _value.length );
- return result;
+ byte[] toByteArray() {
+ byte[] result = new byte[LittleEndianConsts.INT_SIZE*2+_value.length];
+ LittleEndianByteArrayOutputStream bos = new
LittleEndianByteArrayOutputStream(result,0);
+ try {
+ bos.writeInt(LittleEndianConsts.INT_SIZE + _value.length);
+ bos.writeInt(_format);
+ bos.write(_value);
+ return result;
+ } finally {
+ IOUtils.closeQuietly(bos);
+ }
}
-
- int write( OutputStream out ) throws IOException
- {
- LittleEndian.putInt( LittleEndian.INT_SIZE + _value.length, out );
- LittleEndian.putInt( _format, out );
- out.write( _value );
- return 2 * LittleEndian.INT_SIZE + _value.length;
+
+ void setValue( byte[] value ) {
+ _value = value.clone();
}
}
Modified: poi/trunk/src/java/org/apache/poi/hpsf/CodePageString.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hpsf/CodePageString.java?rev=1793594&r1=1793593&r2=1793594&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hpsf/CodePageString.java (original)
+++ poi/trunk/src/java/org/apache/poi/hpsf/CodePageString.java Tue May 2
23:24:50 2017
@@ -23,89 +23,83 @@ import java.io.UnsupportedEncodingExcept
import org.apache.poi.util.CodePageUtil;
import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianByteArrayInputStream;
+import org.apache.poi.util.LittleEndianConsts;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
-import org.apache.poi.util.StringUtil;
@Internal
-class CodePageString
-{
- private final static POILogger logger = POILogFactory
- .getLogger( CodePageString.class );
+class CodePageString {
+ private final static POILogger LOG = POILogFactory.getLogger(
CodePageString.class );
private byte[] _value;
+
+
+ CodePageString() {}
+
+ void read( LittleEndianByteArrayInputStream lei ) {
+ int offset = lei.getReadIndex();
+ int size = lei.readInt();
+ _value = new byte[size];
+ if (size == 0) {
+ return;
+ }
- CodePageString( final byte[] data, final int startOffset )
- {
- int offset = startOffset;
-
- int size = LittleEndian.getInt( data, offset );
- offset += LittleEndian.INT_SIZE;
-
- _value = LittleEndian.getByteArray( data, offset, size );
- if ( size != 0 && _value[size - 1] != 0 ) {
+ // If Size is zero, this field MUST be zero bytes in length. If Size is
+ // nonzero and the CodePage property set's CodePage property has the
value CP_WINUNICODE
+ // (0x04B0), then the value MUST be a null-terminated array of 16-bit
Unicode characters,
+ // followed by zero padding to a multiple of 4 bytes. If Size is
nonzero and the property set's
+ // CodePage property has any other value, it MUST be a null-terminated
array of 8-bit characters
+ // from the code page identified by the CodePage property, followed by
zero padding to a
+ // multiple of 4 bytes. The string represented by this field MAY
contain embedded or additional
+ // trailing null characters and an OLEPS implementation MUST be able
to handle such strings.
+
+ lei.readFully(_value);
+ if (_value[size - 1] != 0 ) {
// TODO Some files, such as TestVisioWithCodepage.vsd, are
currently
- // triggering this for values that don't look like codepages
+ // triggering this for values that don't look like codepages
// See Bug #52258 for details
- logger.log(POILogger.WARN, "CodePageString started at offset #" +
offset
- + " is not NULL-terminated" );
-// throw new IllegalPropertySetDataException(
-// "CodePageString started at offset #" + offset
-// + " is not NULL-terminated" );
+ String msg = "CodePageString started at offset #" + offset + " is
not NULL-terminated";
+ LOG.log(POILogger.WARN, msg);
}
- }
- CodePageString( String string, int codepage )
- throws UnsupportedEncodingException
- {
- setJavaValue( string, codepage );
+ TypedPropertyValue.skipPadding(lei);
}
- String getJavaValue( int codepage ) throws UnsupportedEncodingException
- {
- String result;
- if ( codepage == -1 )
- result = new String( _value, StringUtil.UTF8 );
- else
- result = CodePageUtil.getStringFromCodePage(_value, codepage);
+ String getJavaValue( int codepage ) throws UnsupportedEncodingException {
+ int cp = ( codepage == -1 ) ? Property.DEFAULT_CODEPAGE : codepage;
+ String result = CodePageUtil.getStringFromCodePage(_value, cp);
+
+
final int terminator = result.indexOf( '\0' );
- if ( terminator == -1 )
- {
- logger.log(
- POILogger.WARN,
- "String terminator (\\0) for CodePageString property value
not found."
- + "Continue without trimming and hope for the
best." );
+ if ( terminator == -1 ) {
+ String msg =
+ "String terminator (\\0) for CodePageString property value not
found." +
+ "Continue without trimming and hope for the best.";
+ LOG.log(POILogger.WARN, msg);
return result;
}
- if ( terminator != result.length() - 1 )
- {
- logger.log(
- POILogger.WARN,
- "String terminator (\\0) for CodePageString property value
occured before the end of string. "
- + "Trimming and hope for the best." );
+ if ( terminator != result.length() - 1 ) {
+ String msg =
+ "String terminator (\\0) for CodePageString property value
occured before the end of string. "+
+ "Trimming and hope for the best.";
+ LOG.log(POILogger.WARN, msg );
}
return result.substring( 0, terminator );
}
- int getSize()
- {
- return LittleEndian.INT_SIZE + _value.length;
+ int getSize() {
+ return LittleEndianConsts.INT_SIZE + _value.length;
}
- void setJavaValue( String string, int codepage )
- throws UnsupportedEncodingException
- {
- String stringNT = string + "\0";
- if ( codepage == -1 )
- _value = stringNT.getBytes(StringUtil.UTF8);
- else
- _value = CodePageUtil.getBytesInCodePage(stringNT, codepage);
+ void setJavaValue( String string, int codepage ) throws
UnsupportedEncodingException {
+ int cp = ( codepage == -1 ) ? Property.DEFAULT_CODEPAGE : codepage;
+ _value = CodePageUtil.getBytesInCodePage(string + "\0", cp);
}
- int write( OutputStream out ) throws IOException
- {
- LittleEndian.putInt( _value.length, out );
+ int write( OutputStream out ) throws IOException {
+ LittleEndian.putUInt( _value.length, out );
out.write( _value );
- return LittleEndian.INT_SIZE + _value.length;
+ return LittleEndianConsts.INT_SIZE + _value.length;
}
}
Modified: poi/trunk/src/java/org/apache/poi/hpsf/Currency.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hpsf/Currency.java?rev=1793594&r1=1793593&r2=1793594&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hpsf/Currency.java (original)
+++ poi/trunk/src/java/org/apache/poi/hpsf/Currency.java Tue May 2 23:24:50
2017
@@ -17,17 +17,17 @@
package org.apache.poi.hpsf;
import org.apache.poi.util.Internal;
-import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianByteArrayInputStream;
@Internal
-class Currency
-{
- static final int SIZE = 8;
+class Currency {
+ private static final int SIZE = 8;
- private byte[] _value;
+ private final byte[] _value = new byte[SIZE];
+
+ Currency() {}
- Currency( byte[] data, int offset )
- {
- _value = LittleEndian.getByteArray( data, offset, SIZE );
+ void read( LittleEndianByteArrayInputStream lei ) {
+ lei.readFully(_value);
}
}
Modified: poi/trunk/src/java/org/apache/poi/hpsf/CustomProperties.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hpsf/CustomProperties.java?rev=1793594&r1=1793593&r2=1793594&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hpsf/CustomProperties.java (original)
+++ poi/trunk/src/java/org/apache/poi/hpsf/CustomProperties.java Tue May 2
23:24:50 2017
@@ -17,6 +17,8 @@
package org.apache.poi.hpsf;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@@ -24,6 +26,9 @@ import java.util.Set;
import org.apache.commons.collections4.bidimap.TreeBidiMap;
import org.apache.poi.hpsf.wellknown.PropertyIDMap;
+import org.apache.poi.util.CodePageUtil;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
/**
* Maintains the instances of {@link CustomProperty} that belong to a
@@ -55,6 +60,7 @@ import org.apache.poi.hpsf.wellknown.Pro
*/
@SuppressWarnings("serial")
public class CustomProperties extends HashMap<Long,CustomProperty> {
+ private static final POILogger LOG =
POILogFactory.getLogger(CustomProperties.class);
/**
* Maps property IDs to property names and vice versa.
@@ -66,6 +72,7 @@ public class CustomProperties extends Ha
*/
private boolean isPure = true;
+ private int codepage = -1;
/**
* Puts a {@link CustomProperty} into this map. It is assumed that the
@@ -90,6 +97,8 @@ public class CustomProperties extends Ha
") do not match.");
}
+ checkCodePage(name);
+
/* Register name and ID in the dictionary. Mapping in both directions
is possible. If there is already a */
super.remove(dictionary.getKey(name));
dictionary.put(cp.getID(), name);
@@ -124,7 +133,8 @@ public class CustomProperties extends Ha
customProperty.setID(oldId);
} else {
long lastKey = (dictionary.isEmpty()) ? 0 : dictionary.lastKey();
- customProperty.setID(Math.max(lastKey,PropertyIDMap.PID_MAX) + 1);
+ long nextKey = Math.max(lastKey,PropertyIDMap.PID_MAX)+1;
+ customProperty.setID(nextKey);
}
return this.put(name, customProperty);
}
@@ -152,7 +162,7 @@ public class CustomProperties extends Ha
* {@code null} if there was no such property before.
*/
public Object put(final String name, final String value) {
- final Property p = new Property(-1, Variant.VT_LPWSTR, value);
+ final Property p = new MutableProperty(-1, Variant.VT_LPSTR, value);
return put(new CustomProperty(p, name));
}
@@ -165,7 +175,7 @@ public class CustomProperties extends Ha
* {@code null} if there was no such property before.
*/
public Object put(final String name, final Long value) {
- final Property p = new Property(-1, Variant.VT_I8, value);
+ final Property p = new MutableProperty(-1, Variant.VT_I8, value);
return put(new CustomProperty(p, name));
}
@@ -178,7 +188,7 @@ public class CustomProperties extends Ha
* {@code null} if there was no such property before.
*/
public Object put(final String name, final Double value) {
- final Property p = new Property(-1, Variant.VT_R8, value);
+ final Property p = new MutableProperty(-1, Variant.VT_R8, value);
return put(new CustomProperty(p, name));
}
@@ -191,7 +201,7 @@ public class CustomProperties extends Ha
* {@code null} if there was no such property before.
*/
public Object put(final String name, final Integer value) {
- final Property p = new Property(-1, Variant.VT_I4, value);
+ final Property p = new MutableProperty(-1, Variant.VT_I4, value);
return put(new CustomProperty(p, name));
}
@@ -204,7 +214,7 @@ public class CustomProperties extends Ha
* {@code null} if there was no such property before.
*/
public Object put(final String name, final Boolean value) {
- final Property p = new Property(-1, Variant.VT_BOOL, value);
+ final Property p = new MutableProperty(-1, Variant.VT_BOOL, value);
return put(new CustomProperty(p, name));
}
@@ -233,7 +243,7 @@ public class CustomProperties extends Ha
* {@code null} if there was no such property before.
*/
public Object put(final String name, final Date value) {
- final Property p = new Property(-1, Variant.VT_FILETIME, value);
+ final Property p = new MutableProperty(-1, Variant.VT_FILETIME, value);
return put(new CustomProperty(p, name));
}
@@ -274,11 +284,17 @@ public class CustomProperties extends Ha
* @param codepage the codepage
*/
public void setCodepage(final int codepage) {
- Property p = new Property(PropertyIDMap.PID_CODEPAGE, Variant.VT_I2,
codepage);
- put(new CustomProperty(p));
+ this.codepage = codepage;
}
-
+ /**
+ * Gets the codepage.
+ *
+ * @return the codepage or -1 if the codepage is undefined.
+ */
+ public int getCodepage() {
+ return codepage;
+ }
/**
* <p>Gets the dictionary which contains IDs and names of the named custom
@@ -318,16 +334,6 @@ public class CustomProperties extends Ha
}
/**
- * Gets the codepage.
- *
- * @return the codepage or -1 if the codepage is undefined.
- */
- public int getCodepage() {
- CustomProperty cp = get(PropertyIDMap.PID_CODEPAGE);
- return (cp == null) ? -1 : (Integer)cp.getValue();
- }
-
- /**
* Tells whether this {@link CustomProperties} instance is pure or one or
* more properties of the underlying low-level property set has been
* dropped.
@@ -347,4 +353,25 @@ public class CustomProperties extends Ha
public void setPure(final boolean isPure) {
this.isPure = isPure;
}
+
+ private void checkCodePage(String value) {
+ int cp = getCodepage();
+ if (cp == -1) {
+ cp = Property.DEFAULT_CODEPAGE;
+ }
+ if (cp == CodePageUtil.CP_UNICODE) {
+ return;
+ }
+ String cps = "";
+ try {
+ cps = CodePageUtil.codepageToEncoding(cp, false);
+ } catch (UnsupportedEncodingException e) {
+ LOG.log(POILogger.ERROR, "Codepage '"+cp+"' can't be found.");
+ }
+ if (!cps.isEmpty() &&
Charset.forName(cps).newEncoder().canEncode(value)) {
+ return;
+ }
+ LOG.log(POILogger.DEBUG, "Charset '"+cps+"' can't encode '"+value+"' -
switching to unicode.");
+ setCodepage(CodePageUtil.CP_UNICODE);
+ }
}
Modified: poi/trunk/src/java/org/apache/poi/hpsf/Date.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hpsf/Date.java?rev=1793594&r1=1793593&r2=1793594&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hpsf/Date.java (original)
+++ poi/trunk/src/java/org/apache/poi/hpsf/Date.java Tue May 2 23:24:50 2017
@@ -17,17 +17,17 @@
package org.apache.poi.hpsf;
import org.apache.poi.util.Internal;
-import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianByteArrayInputStream;
@Internal
-class Date
-{
- static final int SIZE = 8;
+class Date {
+ private static final int SIZE = 8;
- private byte[] _value;
+ private final byte[] _value = new byte[SIZE];
+
+ Date() {}
- Date( byte[] data, int offset )
- {
- _value = LittleEndian.getByteArray( data, offset, SIZE );
+ void read( LittleEndianByteArrayInputStream lei ) {
+ lei.readFully(_value);
}
}
Modified: poi/trunk/src/java/org/apache/poi/hpsf/Decimal.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hpsf/Decimal.java?rev=1793594&r1=1793593&r2=1793594&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hpsf/Decimal.java (original)
+++ poi/trunk/src/java/org/apache/poi/hpsf/Decimal.java Tue May 2 23:24:50 2017
@@ -17,13 +17,10 @@
package org.apache.poi.hpsf;
import org.apache.poi.util.Internal;
-import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianByteArrayInputStream;
@Internal
-class Decimal
-{
- static final int SIZE = 16;
-
+class Decimal {
/**
* Findbugs: UNR_UNREAD_FIELD
*/
@@ -33,23 +30,13 @@ class Decimal
private int field_4_hi32;
private long field_5_lo64;
- Decimal( final byte[] data, final int startOffset )
- {
- int offset = startOffset;
-
- field_1_wReserved = LittleEndian.getShort( data, offset );
- offset += LittleEndian.SHORT_SIZE;
-
- field_2_scale = data[offset];
- offset += LittleEndian.BYTE_SIZE;
-
- field_3_sign = data[offset];
- offset += LittleEndian.BYTE_SIZE;
-
- field_4_hi32 = LittleEndian.getInt( data, offset );
- offset += LittleEndian.INT_SIZE;
-
- field_5_lo64 = LittleEndian.getLong( data, offset );
- offset += LittleEndian.LONG_SIZE;
+ Decimal() {}
+
+ void read( LittleEndianByteArrayInputStream lei ) {
+ field_1_wReserved = lei.readShort();
+ field_2_scale = lei.readByte();
+ field_3_sign = lei.readByte();
+ field_4_hi32 = lei.readInt();
+ field_5_lo64 = lei.readLong();
}
}
Modified: poi/trunk/src/java/org/apache/poi/hpsf/DocumentSummaryInformation.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hpsf/DocumentSummaryInformation.java?rev=1793594&r1=1793593&r2=1793594&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hpsf/DocumentSummaryInformation.java
(original)
+++ poi/trunk/src/java/org/apache/poi/hpsf/DocumentSummaryInformation.java Tue
May 2 23:24:50 2017
@@ -17,13 +17,15 @@
package org.apache.poi.hpsf;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.poi.hpsf.wellknown.PropertyIDMap;
import org.apache.poi.hpsf.wellknown.SectionIDMap;
-import org.apache.poi.util.CodePageUtil;
/**
* Convenience class representing a DocumentSummary Information stream in a
@@ -70,6 +72,32 @@ public class DocumentSummaryInformation
}
}
+ /**
+ * Creates a {@link DocumentSummaryInformation} 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 DocumentSummaryInformation(final InputStream stream)
+ throws NoPropertySetStreamException, MarkUnsupportedException,
IOException, UnsupportedEncodingException {
+ super(stream);
+ }
/**
* Returns the category (or {@code null}).
@@ -732,13 +760,13 @@ public class DocumentSummaryInformation
final Map<Long,String> dictionary = section.getDictionary();
final Property[] properties = section.getProperties();
int propertyCount = 0;
- for (int i = 0; i < properties.length; i++) {
- final Property p = properties[i];
+ for (Property p : properties) {
final long id = p.getID();
- if (id != 0 && id != 1) {
+ if (id == PropertyIDMap.PID_CODEPAGE) {
+ cps.setCodepage((Integer)p.getValue());
+ } else if (id > PropertyIDMap.PID_CODEPAGE) {
propertyCount++;
- final CustomProperty cp = new CustomProperty(p,
- dictionary.get(Long.valueOf(id)));
+ final CustomProperty cp = new CustomProperty(p,
dictionary.get(id));
cps.put(cp.getName(), cp);
}
}
@@ -758,17 +786,17 @@ public class DocumentSummaryInformation
ensureSection2();
final Section section = getSections().get(1);
final Map<Long,String> dictionary = customProperties.getDictionary();
- section.clear();
+ // section.clear();
/* Set the codepage. If both custom properties and section have a
* codepage, the codepage from the custom properties wins, else take
the
- * one that is defined. If none is defined, take Unicode. */
+ * one that is defined. If none is defined, take ISO-8859-1. */
int cpCodepage = customProperties.getCodepage();
if (cpCodepage < 0) {
cpCodepage = section.getCodepage();
}
if (cpCodepage < 0) {
- cpCodepage = CodePageUtil.CP_UNICODE;
+ cpCodepage = Property.DEFAULT_CODEPAGE;
}
customProperties.setCodepage(cpCodepage);
section.setCodepage(cpCodepage);
Modified: poi/trunk/src/java/org/apache/poi/hpsf/Filetime.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hpsf/Filetime.java?rev=1793594&r1=1793593&r2=1793594&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hpsf/Filetime.java (original)
+++ poi/trunk/src/java/org/apache/poi/hpsf/Filetime.java Tue May 2 23:24:50
2017
@@ -20,49 +20,45 @@ import java.io.IOException;
import java.io.OutputStream;
import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianByteArrayInputStream;
+import org.apache.poi.util.LittleEndianConsts;
-class Filetime
-{
- static final int SIZE = LittleEndian.INT_SIZE * 2;
+class Filetime {
+ private static final int SIZE = LittleEndian.INT_SIZE * 2;
private int _dwHighDateTime;
private int _dwLowDateTime;
+
+ Filetime() {}
- Filetime( byte[] data, int offset )
- {
- _dwLowDateTime = LittleEndian.getInt( data, offset + 0
- * LittleEndian.INT_SIZE );
- _dwHighDateTime = LittleEndian.getInt( data, offset + 1
- * LittleEndian.INT_SIZE );
- }
-
- Filetime( int low, int high )
- {
+ Filetime( int low, int high ) {
_dwLowDateTime = low;
_dwHighDateTime = high;
}
- long getHigh()
- {
+
+ void read( LittleEndianByteArrayInputStream lei ) {
+ _dwLowDateTime = lei.readInt();
+ _dwHighDateTime = lei.readInt();
+ }
+
+ long getHigh() {
return _dwHighDateTime;
}
- long getLow()
- {
+ long getLow() {
return _dwLowDateTime;
}
- byte[] toByteArray()
- {
+ byte[] toByteArray() {
byte[] result = new byte[SIZE];
- LittleEndian.putInt( result, 0 * LittleEndian.INT_SIZE, _dwLowDateTime
);
+ LittleEndian.putInt( result, 0 * LittleEndianConsts.INT_SIZE,
_dwLowDateTime );
LittleEndian
- .putInt( result, 1 * LittleEndian.INT_SIZE, _dwHighDateTime );
+ .putInt( result, 1 * LittleEndianConsts.INT_SIZE,
_dwHighDateTime );
return result;
}
- int write( OutputStream out ) throws IOException
- {
+ int write( OutputStream out ) throws IOException {
LittleEndian.putInt( _dwLowDateTime, out );
LittleEndian.putInt( _dwHighDateTime, out );
return SIZE;
Modified: poi/trunk/src/java/org/apache/poi/hpsf/GUID.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hpsf/GUID.java?rev=1793594&r1=1793593&r2=1793594&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hpsf/GUID.java (original)
+++ poi/trunk/src/java/org/apache/poi/hpsf/GUID.java Tue May 2 23:24:50 2017
@@ -17,23 +17,21 @@
package org.apache.poi.hpsf;
import org.apache.poi.util.Internal;
-import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianByteArrayInputStream;
@Internal
-class GUID
-{
- static final int SIZE = 16;
-
+class GUID {
private int _data1;
private short _data2;
private short _data3;
private long _data4;
- GUID( byte[] data, int offset )
- {
- _data1 = LittleEndian.getInt( data, offset + 0 );
- _data2 = LittleEndian.getShort( data, offset + 4 );
- _data3 = LittleEndian.getShort( data, offset + 6 );
- _data4 = LittleEndian.getLong( data, offset + 8 );
+ GUID() {}
+
+ void read( LittleEndianByteArrayInputStream lei ) {
+ _data1 = lei.readInt();
+ _data2 = lei.readShort();
+ _data3 = lei.readShort();
+ _data4 = lei.readLong();
}
}
Modified: poi/trunk/src/java/org/apache/poi/hpsf/IndirectPropertyName.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hpsf/IndirectPropertyName.java?rev=1793594&r1=1793593&r2=1793594&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hpsf/IndirectPropertyName.java (original)
+++ poi/trunk/src/java/org/apache/poi/hpsf/IndirectPropertyName.java Tue May 2
23:24:50 2017
@@ -19,17 +19,6 @@ package org.apache.poi.hpsf;
import org.apache.poi.util.Internal;
@Internal
-class IndirectPropertyName
-{
- private CodePageString _value;
-
- IndirectPropertyName( byte[] data, int offset ) //NOSONAR
- {
- _value = new CodePageString( data, offset );
- }
-
- int getSize()
- {
- return _value.getSize();
- }
+class IndirectPropertyName extends CodePageString {
+ IndirectPropertyName() {}
}
Modified: poi/trunk/src/java/org/apache/poi/hpsf/MutableProperty.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hpsf/MutableProperty.java?rev=1793594&r1=1793593&r2=1793594&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hpsf/MutableProperty.java (original)
+++ poi/trunk/src/java/org/apache/poi/hpsf/MutableProperty.java Tue May 2
23:24:50 2017
@@ -17,6 +17,9 @@
package org.apache.poi.hpsf;
+import java.io.UnsupportedEncodingException;
+
+import org.apache.poi.util.LittleEndianByteArrayInputStream;
import org.apache.poi.util.Removal;
/**
@@ -27,6 +30,7 @@ import org.apache.poi.util.Removal;
*
* @deprecated POI 3.16 - use Property as base class instead
*/
+@Deprecated
@Removal(version="3.18")
public class MutableProperty extends Property {
public MutableProperty() {}
@@ -35,4 +39,17 @@ public class MutableProperty extends Pro
super(p);
}
+ public MutableProperty(final long id, final long type, final Object value)
{
+ super(id, type, value);
+ }
+
+ public MutableProperty(final long id, final byte[] src, final long offset,
final int length, final int codepage)
+ throws UnsupportedEncodingException {
+ super(id, src, offset, length, codepage);
+ }
+
+ public MutableProperty(final long id, LittleEndianByteArrayInputStream
leis, final int length, final int codepage)
+ throws UnsupportedEncodingException {
+ super(id, leis, length, codepage);
+ }
}
Modified: poi/trunk/src/java/org/apache/poi/hpsf/PropertySet.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hpsf/PropertySet.java?rev=1793594&r1=1793593&r2=1793594&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hpsf/PropertySet.java (original)
+++ poi/trunk/src/java/org/apache/poi/hpsf/PropertySet.java Tue May 2 23:24:50
2017
@@ -23,10 +23,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
-import java.nio.charset.Charset;
-import java.util.Arrays;
+import java.util.ArrayList;
import java.util.Collections;
-import java.util.LinkedList;
import java.util.List;
import org.apache.poi.EmptyFileException;
@@ -34,6 +32,7 @@ import org.apache.poi.hpsf.wellknown.Pro
import org.apache.poi.hpsf.wellknown.SectionIDMap;
import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.Entry;
+import org.apache.poi.util.CodePageUtil;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianConsts;
@@ -90,17 +89,17 @@ public class PropertySet {
/**
* The "byteOrder" field must equal this value.
*/
- private static final int BYTE_ORDER_ASSERTION = 0xFFFE;
+ /* package */ static final int BYTE_ORDER_ASSERTION = 0xFFFE;
/**
* The "format" field must equal this value.
*/
- private static final int FORMAT_ASSERTION = 0x0000;
+ /* package */ static final int FORMAT_ASSERTION = 0x0000;
/**
* The length of the property set stream header.
*/
- private static final int OFFSET_HEADER =
+ /* package */ static final int OFFSET_HEADER =
LittleEndianConsts.SHORT_SIZE + /* Byte order */
LittleEndianConsts.SHORT_SIZE + /* Format */
LittleEndianConsts.INT_SIZE + /* OS version */
@@ -135,7 +134,7 @@ public class PropertySet {
/**
* The sections in this {@link PropertySet}.
*/
- private final List<Section> sections = new LinkedList<Section>();
+ private final List<Section> sections = new ArrayList<Section>();
/**
@@ -513,11 +512,11 @@ public class PropertySet {
final int nrSections = getSectionCount();
/* Write the property set's header. */
- TypeWriter.writeToStream(out, (short) getByteOrder());
- TypeWriter.writeToStream(out, (short) getFormat());
- TypeWriter.writeToStream(out, getOSVersion());
- TypeWriter.writeToStream(out, getClassID());
- TypeWriter.writeToStream(out, nrSections);
+ LittleEndian.putShort(out, (short) getByteOrder());
+ LittleEndian.putShort(out, (short) getFormat());
+ LittleEndian.putInt(getOSVersion(), out);
+ putClassId(out, getClassID());
+ LittleEndian.putInt(nrSections, out);
int offset = OFFSET_HEADER;
/* Write the section list, i.e. the references to the sections. Each
@@ -530,8 +529,8 @@ public class PropertySet {
if (formatID == null) {
throw new NoFormatIDException();
}
- TypeWriter.writeToStream(out, section.getFormatID());
- TypeWriter.writeUIntToStream(out, offset);
+ putClassId(out, formatID);
+ LittleEndian.putUInt(offset, out);
try {
offset += section.getSize();
} catch (HPSFRuntimeException ex) {
@@ -643,7 +642,12 @@ public class PropertySet {
return Long.toString( LittleEndian.getUInt(b) );
default:
// Maybe it's a string? who knows!
- return new String(b, Charset.forName("ASCII"));
+ try {
+ return CodePageUtil.getStringFromCodePage(b,
Property.DEFAULT_CODEPAGE);
+ } catch (UnsupportedEncodingException e) {
+ // doesn't happen ...
+ return "";
+ }
}
}
return propertyValue.toString();
@@ -656,7 +660,7 @@ public class PropertySet {
* represents a Summary Information, else {@code false}.
*/
public boolean isSummaryInformation() {
- return matchesSummary(SectionIDMap.SUMMARY_INFORMATION_ID);
+ return !sections.isEmpty() &&
matchesSummary(getFirstSection().getFormatID(),
SectionIDMap.SUMMARY_INFORMATION_ID);
}
/**
@@ -666,15 +670,17 @@ public class PropertySet {
* represents a Document Summary Information, else {@code false}.
*/
public boolean isDocumentSummaryInformation() {
- return
matchesSummary(SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID[0]);
- }
-
- private boolean matchesSummary(byte[] summaryBytes) {
- return !sections.isEmpty() &&
- Arrays.equals(getFirstSection().getFormatID().getBytes(),
summaryBytes);
+ return !sections.isEmpty() &&
matchesSummary(getFirstSection().getFormatID(),
SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID);
}
-
+ /* package */ static boolean matchesSummary(ClassID actual, ClassID...
expected) {
+ for (ClassID sum : expected) {
+ if (sum.equals(actual) || sum.equalsInverted(actual)) {
+ return true;
+ }
+ }
+ return false;
+ }
/**
* Convenience method returning the {@link Property} array contained in
this
@@ -892,4 +898,10 @@ public class PropertySet {
protected void set1stProperty(long id, byte[] value) {
getFirstSection().setProperty((int)id, value);
}
+
+ private static void putClassId(final OutputStream out, final ClassID n)
throws IOException {
+ byte[] b = new byte[16];
+ n.write(b, 0);
+ out.write(b, 0, b.length);
+ }
}
Modified: poi/trunk/src/java/org/apache/poi/hpsf/TypeWriter.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hpsf/TypeWriter.java?rev=1793594&r1=1793593&r2=1793594&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hpsf/TypeWriter.java (original)
+++ poi/trunk/src/java/org/apache/poi/hpsf/TypeWriter.java Tue May 2 23:24:50
2017
@@ -21,10 +21,15 @@ import java.io.IOException;
import java.io.OutputStream;
import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianConsts;
+import org.apache.poi.util.Removal;
/**
- * <p>Class for writing little-endian data and more.</p>
+ * Class for writing little-endian data and more.
+ * @deprecated POI 3.16 beta 2 - use LittleEndian instead
*/
+@Deprecated
+@Removal(version="3.18")
public class TypeWriter
{
@@ -40,7 +45,7 @@ public class TypeWriter
throws IOException
{
LittleEndian.putShort( out, n ); // FIXME: unsigned
- return LittleEndian.SHORT_SIZE;
+ return LittleEndianConsts.SHORT_SIZE;
}
/**
@@ -55,7 +60,7 @@ public class TypeWriter
throws IOException
{
LittleEndian.putInt( n, out );
- return LittleEndian.INT_SIZE;
+ return LittleEndianConsts.INT_SIZE;
}
/**
@@ -70,7 +75,7 @@ public class TypeWriter
throws IOException
{
LittleEndian.putLong( n, out );
- return LittleEndian.LONG_SIZE;
+ return LittleEndianConsts.LONG_SIZE;
}
/**
@@ -84,9 +89,10 @@ public class TypeWriter
throws IOException
{
int high = n & 0xFFFF0000;
- if ( high != 0 )
+ if ( high != 0 ) {
throw new IllegalPropertySetDataException( "Value " + n
+ " cannot be represented by 2 bytes." );
+ }
LittleEndian.putUShort( n, out );
}
@@ -102,11 +108,12 @@ public class TypeWriter
throws IOException
{
long high = n & 0xFFFFFFFF00000000L;
- if ( high != 0 && high != 0xFFFFFFFF00000000L )
+ if ( high != 0 && high != 0xFFFFFFFF00000000L ) {
throw new IllegalPropertySetDataException( "Value " + n
+ " cannot be represented by 4 bytes." );
+ }
LittleEndian.putUInt( n, out );
- return LittleEndian.INT_SIZE;
+ return LittleEndianConsts.INT_SIZE;
}
/**
@@ -145,8 +152,9 @@ public class TypeWriter
throws IOException, UnsupportedVariantTypeException
{
/* If there are no properties don't write anything. */
- if (properties == null)
+ if (properties == null) {
return;
+ }
/* Write the property list. This is a list containing pairs of property
* ID and offset into the stream. */
@@ -154,7 +162,7 @@ public class TypeWriter
{
final Property p = properties[i];
writeUIntToStream(out, p.getID());
- writeUIntToStream(out, p.getSize());
+ writeUIntToStream(out, p.getSize(codepage));
}
/* Write the properties themselves. */
@@ -181,7 +189,7 @@ public class TypeWriter
throws IOException
{
LittleEndian.putDouble( n, out );
- return LittleEndian.DOUBLE_SIZE;
+ return LittleEndianConsts.DOUBLE_SIZE;
}
}
Modified: poi/trunk/src/java/org/apache/poi/hpsf/TypedPropertyValue.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hpsf/TypedPropertyValue.java?rev=1793594&r1=1793593&r2=1793594&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hpsf/TypedPropertyValue.java (original)
+++ poi/trunk/src/java/org/apache/poi/hpsf/TypedPropertyValue.java Tue May 2
23:24:50 2017
@@ -18,168 +18,181 @@
*/
package org.apache.poi.hpsf;
+import java.math.BigInteger;
+
import org.apache.poi.util.Internal;
-import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianByteArrayInputStream;
+import org.apache.poi.util.LittleEndianConsts;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
@Internal
-class TypedPropertyValue
-{
- private static final POILogger logger = POILogFactory
- .getLogger( TypedPropertyValue.class );
+class TypedPropertyValue {
+ private static final POILogger LOG = POILogFactory.getLogger(
TypedPropertyValue.class );
private int _type;
-
private Object _value;
- TypedPropertyValue()
- {
- }
-
- TypedPropertyValue( byte[] data, int startOffset )
- {
- read( data, startOffset );
- }
-
- TypedPropertyValue( int type, Object value )
- {
+ TypedPropertyValue( int type, Object value ) {
_type = type;
_value = value;
}
- Object getValue()
- {
+ Object getValue() {
return _value;
}
- int read( byte[] data, int startOffset )
- {
- int offset = startOffset;
-
- _type = LittleEndian.getShort( data, offset );
- offset += LittleEndian.SHORT_SIZE;
-
- short padding = LittleEndian.getShort( data, offset );
- offset += LittleEndian.SHORT_SIZE;
- if ( padding != 0 )
- {
- logger.log( POILogger.WARN, "TypedPropertyValue padding at offset "
- + offset + " MUST be 0, but it's value is " + padding );
+ void read( LittleEndianByteArrayInputStream lei ) {
+ _type = lei.readShort();
+ short padding = lei.readShort();
+ if ( padding != 0 ) {
+ LOG.log( POILogger.WARN, "TypedPropertyValue padding at offset "
+ + lei.getReadIndex() + " MUST be 0, but it's value is " +
padding );
}
-
- offset += readValue( data, offset );
-
- return offset - startOffset;
+ readValue( lei );
}
- int readValue( byte[] data, int offset ) // NOSONAR
- {
- switch ( _type )
- {
+ void readValue( LittleEndianByteArrayInputStream lei ) {
+ switch ( _type ) {
case Variant.VT_EMPTY:
case Variant.VT_NULL:
_value = null;
- return 0;
+ break;
+
+ case Variant.VT_I1:
+ _value = lei.readByte();
+ break;
+
+ case Variant.VT_UI1:
+ _value = lei.readUByte();
+ break;
- case Variant.VT_R4:
case Variant.VT_I2:
- _value = Short.valueOf( LittleEndian.getShort( data, offset ) );
- return 4;
+ _value = lei.readShort();
+ break;
+ case Variant.VT_UI2:
+ _value = lei.readUShort();
+ break;
+
case Variant.VT_INT:
case Variant.VT_I4:
- _value = Integer.valueOf( LittleEndian.getInt( data, offset ) );
- return 4;
+ _value = lei.readInt();
+ break;
+
+ case Variant.VT_UINT:
+ case Variant.VT_UI4:
+ case Variant.VT_ERROR:
+ _value = lei.readUInt();
+ break;
+
+ case Variant.VT_I8:
+ _value = lei.readLong();
+ break;
+
+ case Variant.VT_UI8: {
+ byte[] biBytesLE = new byte[LittleEndianConsts.LONG_SIZE];
+ lei.readFully(biBytesLE);
+
+ // first byte needs to be 0 for unsigned BigInteger
+ byte[] biBytesBE = new byte[9];
+ int i=biBytesLE.length;
+ for (byte b : biBytesLE) {
+ if (i<=8) {
+ biBytesBE[i] = b;
+ }
+ i--;
+ }
+ _value = new BigInteger(biBytesBE);
+ break;
+ }
+
+ case Variant.VT_R4:
+ _value = Float.intBitsToFloat(lei.readInt());
+ break;
+
case Variant.VT_R8:
- _value = Double.valueOf( LittleEndian.getDouble( data, offset ) );
- return 8;
+ _value = lei.readDouble();
+ break;
case Variant.VT_CY:
- _value = new Currency( data, offset );
- return Currency.SIZE;
+ Currency cur = new Currency();
+ cur.read(lei);
+ _value = cur;
+ break;
+
case Variant.VT_DATE:
- _value = new Date( data, offset );
- return Date.SIZE;
+ Date date = new Date();
+ date.read(lei);
+ _value = date;
+ break;
case Variant.VT_BSTR:
- _value = new CodePageString( data, offset );
- return ( (CodePageString) _value ).getSize();
+ case Variant.VT_LPSTR:
+ CodePageString cps = new CodePageString();
+ cps.read(lei);
+ _value = cps;
+ break;
case Variant.VT_BOOL:
- _value = new VariantBool( data, offset );
- return VariantBool.SIZE;
+ VariantBool vb = new VariantBool();
+ vb.read(lei);
+ _value = vb;
+ break;
case Variant.VT_DECIMAL:
- _value = new Decimal( data, offset );
- return Decimal.SIZE;
-
- case Variant.VT_I1:
- _value = Byte.valueOf( data[offset] );
- return 1;
-
- case Variant.VT_UI1:
- _value = Short.valueOf( LittleEndian.getUByte( data, offset ) );
- return 2;
-
- case Variant.VT_UI2:
- _value = Integer.valueOf( LittleEndian.getUShort( data, offset ) );
- return 4;
-
- case Variant.VT_UINT:
- case Variant.VT_UI4:
- case Variant.VT_ERROR:
- _value = Long.valueOf( LittleEndian.getUInt( data, offset ) );
- return 4;
-
- case Variant.VT_I8:
- _value = Long.valueOf( LittleEndian.getLong( data, offset ) );
- return 8;
-
- case Variant.VT_UI8:
- _value = LittleEndian.getByteArray( data, offset, 8 );
- return 8;
-
- case Variant.VT_LPSTR:
- _value = new CodePageString( data, offset );
- return ( (CodePageString) _value ).getSize();
+ Decimal dec = new Decimal();
+ dec.read(lei);
+ _value = dec;
+ break;
case Variant.VT_LPWSTR:
- _value = new UnicodeString( data, offset );
- return ( (UnicodeString) _value ).getSize();
+ UnicodeString us = new UnicodeString();
+ us.read(lei);
+ _value = us;
+ break;
case Variant.VT_FILETIME:
- _value = new Filetime( data, offset );
- return Filetime.SIZE;
+ Filetime ft = new Filetime();
+ ft.read(lei);
+ _value = ft;
+ break;
case Variant.VT_BLOB:
- _value = new Blob( data, offset );
- return ( (Blob) _value ).getSize();
+ case Variant.VT_BLOB_OBJECT:
+ Blob blob = new Blob();
+ blob.read(lei);
+ _value = blob;
+ break;
case Variant.VT_STREAM:
case Variant.VT_STORAGE:
case Variant.VT_STREAMED_OBJECT:
case Variant.VT_STORED_OBJECT:
- _value = new IndirectPropertyName( data, offset );
- return ( (IndirectPropertyName) _value ).getSize();
-
- case Variant.VT_BLOB_OBJECT:
- _value = new Blob( data, offset );
- return ( (Blob) _value ).getSize();
+ IndirectPropertyName ipn = new IndirectPropertyName();
+ ipn.read(lei);
+ _value = ipn;
+ break;
case Variant.VT_CF:
- _value = new ClipboardData( data, offset );
- return ( (ClipboardData) _value ).getSize();
+ ClipboardData cd = new ClipboardData();
+ cd.read(lei);
+ _value = cd;
+ break;
case Variant.VT_CLSID:
- _value = new GUID( data, offset );
- return GUID.SIZE;
+ GUID guid = new GUID();
+ guid.read(lei);
+ _value = lei;
+ break;
case Variant.VT_VERSIONED_STREAM:
- _value = new VersionedStream( data, offset );
- return ( (VersionedStream) _value ).getSize();
+ VersionedStream vs = new VersionedStream();
+ vs.read(lei);
+ _value = vs;
+ break;
case Variant.VT_VECTOR | Variant.VT_I2:
case Variant.VT_VECTOR | Variant.VT_I4:
@@ -202,8 +215,10 @@ class TypedPropertyValue
case Variant.VT_VECTOR | Variant.VT_FILETIME:
case Variant.VT_VECTOR | Variant.VT_CF:
case Variant.VT_VECTOR | Variant.VT_CLSID:
- _value = new Vector( (short) ( _type & 0x0FFF ) );
- return ( (Vector) _value ).read( data, offset );
+ Vector vec = new Vector( (short) ( _type & 0x0FFF ) );
+ vec.read(lei);
+ _value = vec;
+ break;
case Variant.VT_ARRAY | Variant.VT_I2:
case Variant.VT_ARRAY | Variant.VT_I4:
@@ -222,20 +237,27 @@ class TypedPropertyValue
case Variant.VT_ARRAY | Variant.VT_UI4:
case Variant.VT_ARRAY | Variant.VT_INT:
case Variant.VT_ARRAY | Variant.VT_UINT:
- _value = new Array();
- return ( (Array) _value ).read( data, offset );
+ Array arr = new Array();
+ arr.read(lei);
+ _value = arr;
+ break;
default:
- throw new UnsupportedOperationException(
- "Unknown (possibly, incorrect) TypedPropertyValue type: "
- + _type );
+ String msg = "Unknown (possibly, incorrect) TypedPropertyValue
type: " + _type;
+ throw new UnsupportedOperationException(msg);
}
}
- int readValuePadded( byte[] data, int offset )
- {
- int nonPadded = readValue( data, offset );
- return ( nonPadded & 0x03 ) == 0 ? nonPadded : nonPadded
- + ( 4 - ( nonPadded & 0x03 ) );
+ static void skipPadding( LittleEndianByteArrayInputStream lei ) {
+ final int offset = lei.getReadIndex();
+ int skipBytes = (4 - (offset & 3)) & 3;
+ for (int i=0; i<skipBytes; i++) {
+ lei.mark(1);
+ int b = lei.read();
+ if (b == -1 || b != 0) {
+ lei.reset();
+ break;
+ }
+ }
}
}
Modified: poi/trunk/src/java/org/apache/poi/hpsf/UnicodeString.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hpsf/UnicodeString.java?rev=1793594&r1=1793593&r2=1793594&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hpsf/UnicodeString.java (original)
+++ poi/trunk/src/java/org/apache/poi/hpsf/UnicodeString.java Tue May 2
23:24:50 2017
@@ -16,110 +16,89 @@
==================================================================== */
package org.apache.poi.hpsf;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+
+import org.apache.poi.util.CodePageUtil;
import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianByteArrayInputStream;
+import org.apache.poi.util.LittleEndianConsts;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.StringUtil;
@Internal
class UnicodeString {
- private final static POILogger logger =
- POILogFactory.getLogger( UnicodeString.class );
+ private static final POILogger LOG = POILogFactory.getLogger(
UnicodeString.class );
private byte[] _value;
+
+ UnicodeString() {}
- UnicodeString(byte[] data, int offset) {
- int length = LittleEndian.getInt( data, offset );
- int dataOffset = offset + LittleEndian.INT_SIZE;
+ void read(LittleEndianByteArrayInputStream lei) {
+ final int length = lei.readInt();
+ final int unicodeBytes = length*2;
+ _value = new byte[unicodeBytes];
- if (! validLength(length, data, dataOffset)) {
- // If the length looks wrong, this might be because the offset is
sometimes expected
- // to be on a 4 byte boundary. Try checking with that if so,
rather than blowing up with
- // and ArrayIndexOutOfBoundsException below
- boolean valid = false;
- int past4byte = offset % 4;
- if (past4byte != 0) {
- offset = offset + past4byte;
- length = LittleEndian.getInt( data, offset );
- dataOffset = offset + LittleEndian.INT_SIZE;
-
- valid = validLength(length, data, dataOffset);
- }
-
- if (!valid) {
- throw new IllegalPropertySetDataException(
- "UnicodeString started at offset #" + offset +
- " is not NULL-terminated" );
- }
- }
-
- if ( length == 0 )
- {
- _value = new byte[0];
+ // If Length is zero, this field MUST be zero bytes in length. If
Length is
+ // nonzero, this field MUST be a null-terminated array of 16-bit
Unicode characters, followed by
+ // zero padding to a multiple of 4 bytes. The string represented by
this field SHOULD NOT
+ // contain embedded or additional trailing null characters.
+
+ if (length == 0) {
return;
}
- _value = LittleEndian.getByteArray( data, dataOffset, length * 2 );
- }
-
- /**
- * Checks to see if the specified length seems valid,
- * given the amount of data available still to read,
- * and the requirement that the string be NULL-terminated
- */
- boolean validLength(int length, byte[] data, int offset) {
- if (length == 0) {
- return true;
- }
+ final int offset = lei.getReadIndex();
+
+ lei.readFully(_value);
- int endOffset = offset + (length * 2);
- if (endOffset <= data.length) {
- // Data Length is OK, ensure it's null terminated too
- if (data[endOffset-1] == 0 && data[endOffset-2] == 0) {
- // Length looks plausible
- return true;
- }
+ if (_value[unicodeBytes-2] != 0 || _value[unicodeBytes-1] != 0) {
+ String msg = "UnicodeString started at offset #" + offset + " is
not NULL-terminated";
+ throw new IllegalPropertySetDataException(msg);
}
-
- // Something's up/invalid with that length for the given data+offset
- return false;
- }
-
- int getSize()
- {
- return LittleEndian.INT_SIZE + _value.length;
+
+ TypedPropertyValue.skipPadding(lei);
}
-
- byte[] getValue()
- {
+
+ byte[] getValue() {
return _value;
}
- String toJavaString()
- {
- if ( _value.length == 0 )
+ String toJavaString() {
+ if ( _value.length == 0 ) {
return null;
+ }
- String result = StringUtil.getFromUnicodeLE( _value, 0,
- _value.length >> 1 );
+ String result = StringUtil.getFromUnicodeLE( _value, 0, _value.length
>> 1 );
final int terminator = result.indexOf( '\0' );
- if ( terminator == -1 )
- {
- logger.log(
- POILogger.WARN,
- "String terminator (\\0) for UnicodeString property value
not found."
- + "Continue without trimming and hope for the
best." );
+ if ( terminator == -1 ) {
+ String msg =
+ "String terminator (\\0) for UnicodeString property value not
found."+
+ "Continue without trimming and hope for the best.";
+ LOG.log(POILogger.WARN, msg);
return result;
}
- if ( terminator != result.length() - 1 )
- {
- logger.log(
- POILogger.WARN,
- "String terminator (\\0) for UnicodeString property value
occured before the end of string. "
- + "Trimming and hope for the best." );
+
+ if ( terminator != result.length() - 1 ) {
+ String msg =
+ "String terminator (\\0) for UnicodeString property value
occured before the end of string. "+
+ "Trimming and hope for the best.";
+ LOG.log(POILogger.WARN, msg);
}
return result.substring( 0, terminator );
}
+
+ void setJavaValue( String string ) throws UnsupportedEncodingException {
+ _value = CodePageUtil.getBytesInCodePage(string + "\0",
CodePageUtil.CP_UNICODE);
+ }
+
+ int write( OutputStream out ) throws IOException {
+ LittleEndian.putUInt( _value.length / 2, out );
+ out.write( _value );
+ return LittleEndianConsts.INT_SIZE + _value.length;
+ }
}
Modified: poi/trunk/src/java/org/apache/poi/hpsf/Util.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hpsf/Util.java?rev=1793594&r1=1793593&r2=1793594&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hpsf/Util.java (original)
+++ poi/trunk/src/java/org/apache/poi/hpsf/Util.java Tue May 2 23:24:50 2017
@@ -95,38 +95,6 @@ public class Util
return ms_since_16010101 * (1000 * 10);
}
-
-
- /**
- * <p>Compares to object arrays with regarding the objects' order. For
- * example, [1, 2, 3] and [2, 1, 3] are equal.</p>
- *
- * @param c1 The first object array.
- * @param c2 The second object array.
- * @return <code>true</code> if the object arrays are equal,
- * <code>false</code> if they are not.
- */
- public static boolean equals(Object[] c1, Object[] c2)
- {
- for (int i1 = 0; i1 < c1.length; i1++)
- {
- final Object obj1 = c1[i1];
- boolean matchFound = false;
- for (int i2 = 0; !matchFound && i2 < c1.length; i2++)
- {
- final Object obj2 = c2[i2];
- if (obj1.equals(obj2))
- {
- matchFound = true;
- c2[i2] = null;
- }
- }
- if (!matchFound)
- return false;
- }
- return true;
- }
-
/**
* <p>Pads a byte array with 0x00 bytes so that its length is a multiple of
* 4.</p>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]