mirror of https://github.com/apache/poi.git
HPSF: Enable new number types in VariantSupport
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1793598 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
c22e972b3d
commit
57460325b4
|
@ -20,11 +20,15 @@ package org.apache.poi.hpsf;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.math.BigInteger;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.poi.util.CodePageUtil;
|
import org.apache.poi.util.CodePageUtil;
|
||||||
|
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.POILogFactory;
|
||||||
import org.apache.poi.util.POILogger;
|
import org.apache.poi.util.POILogger;
|
||||||
import org.apache.poi.util.Removal;
|
import org.apache.poi.util.Removal;
|
||||||
|
@ -64,6 +68,8 @@ public class VariantSupport extends Variant {
|
||||||
*/
|
*/
|
||||||
private static List<Long> unsupportedMessage;
|
private static List<Long> unsupportedMessage;
|
||||||
|
|
||||||
|
private static final byte[] paddingBytes = new byte[3];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether warnings about unsupported variant types are to be
|
* Specifies whether warnings about unsupported variant types are to be
|
||||||
|
@ -100,8 +106,9 @@ public class VariantSupport extends Variant {
|
||||||
(final UnsupportedVariantTypeException ex) {
|
(final UnsupportedVariantTypeException ex) {
|
||||||
if (isLogUnsupportedTypes())
|
if (isLogUnsupportedTypes())
|
||||||
{
|
{
|
||||||
if (unsupportedMessage == null)
|
if (unsupportedMessage == null) {
|
||||||
unsupportedMessage = new LinkedList<Long>();
|
unsupportedMessage = new LinkedList<Long>();
|
||||||
|
}
|
||||||
Long vt = Long.valueOf(ex.getVariantType());
|
Long vt = Long.valueOf(ex.getVariantType());
|
||||||
if (!unsupportedMessage.contains(vt))
|
if (!unsupportedMessage.contains(vt))
|
||||||
{
|
{
|
||||||
|
@ -124,9 +131,11 @@ public class VariantSupport extends Variant {
|
||||||
* {@code false}
|
* {@code false}
|
||||||
*/
|
*/
|
||||||
public boolean isSupportedType(final int variantType) {
|
public boolean isSupportedType(final int variantType) {
|
||||||
for (int i = 0; i < SUPPORTED_TYPES.length; i++)
|
for (int st : SUPPORTED_TYPES) {
|
||||||
if (variantType == SUPPORTED_TYPES[i])
|
if (variantType == st) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,14 +161,21 @@ public class VariantSupport extends Variant {
|
||||||
public static Object read( final byte[] src, final int offset,
|
public static Object read( final byte[] src, final int offset,
|
||||||
final int length, final long type, final int codepage )
|
final int length, final long type, final int codepage )
|
||||||
throws ReadingNotSupportedException, UnsupportedEncodingException {
|
throws ReadingNotSupportedException, UnsupportedEncodingException {
|
||||||
|
LittleEndianByteArrayInputStream lei = new LittleEndianByteArrayInputStream(src, offset);
|
||||||
|
return read( lei, length, type, codepage );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object read( LittleEndianByteArrayInputStream lei,
|
||||||
|
final int length, final long type, final int codepage )
|
||||||
|
throws ReadingNotSupportedException, UnsupportedEncodingException {
|
||||||
|
final int offset = lei.getReadIndex();
|
||||||
TypedPropertyValue typedPropertyValue = new TypedPropertyValue( (int) type, null );
|
TypedPropertyValue typedPropertyValue = new TypedPropertyValue( (int) type, null );
|
||||||
int unpadded;
|
|
||||||
try {
|
try {
|
||||||
unpadded = typedPropertyValue.readValue( src, offset );
|
typedPropertyValue.readValue(lei);
|
||||||
} catch ( UnsupportedOperationException exc ) {
|
} catch ( UnsupportedOperationException exc ) {
|
||||||
int propLength = Math.min( length, src.length - offset );
|
int propLength = Math.min( length, lei.available() );
|
||||||
final byte[] v = new byte[propLength];
|
final byte[] v = new byte[propLength];
|
||||||
System.arraycopy( src, offset, v, 0, propLength );
|
lei.readFully(v, 0, propLength);
|
||||||
throw new ReadingNotSupportedException( type, v );
|
throw new ReadingNotSupportedException( type, v );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,8 +187,14 @@ public class VariantSupport extends Variant {
|
||||||
* changed -- sergey
|
* changed -- sergey
|
||||||
*/
|
*/
|
||||||
case Variant.VT_EMPTY:
|
case Variant.VT_EMPTY:
|
||||||
|
case Variant.VT_I1:
|
||||||
|
case Variant.VT_UI1:
|
||||||
|
case Variant.VT_UI2:
|
||||||
case Variant.VT_I4:
|
case Variant.VT_I4:
|
||||||
|
case Variant.VT_UI4:
|
||||||
case Variant.VT_I8:
|
case Variant.VT_I8:
|
||||||
|
case Variant.VT_UI8:
|
||||||
|
case Variant.VT_R4:
|
||||||
case Variant.VT_R8:
|
case Variant.VT_R8:
|
||||||
return typedPropertyValue.getValue();
|
return typedPropertyValue.getValue();
|
||||||
|
|
||||||
|
@ -226,8 +248,10 @@ public class VariantSupport extends Variant {
|
||||||
* API? --sergey
|
* API? --sergey
|
||||||
*/
|
*/
|
||||||
default:
|
default:
|
||||||
|
final int unpadded = lei.getReadIndex()-offset;
|
||||||
|
lei.setReadIndex(offset);
|
||||||
final byte[] v = new byte[unpadded];
|
final byte[] v = new byte[unpadded];
|
||||||
System.arraycopy( src, offset, v, 0, unpadded );
|
lei.readFully( v, 0, unpadded );
|
||||||
throw new ReadingNotSupportedException( type, v );
|
throw new ReadingNotSupportedException( type, v );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,6 +272,7 @@ public class VariantSupport extends Variant {
|
||||||
*
|
*
|
||||||
* @deprecated POI 3.16 - use {@link CodePageUtil#codepageToEncoding(int)}
|
* @deprecated POI 3.16 - use {@link CodePageUtil#codepageToEncoding(int)}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
@Removal(version="3.18")
|
@Removal(version="3.18")
|
||||||
public static String codepageToEncoding(final int codepage)
|
public static String codepageToEncoding(final int codepage)
|
||||||
throws UnsupportedEncodingException
|
throws UnsupportedEncodingException
|
||||||
|
@ -260,11 +285,6 @@ public class VariantSupport extends Variant {
|
||||||
* Writes a variant value to an output stream. This method ensures that
|
* Writes a variant value to an output stream. This method ensures that
|
||||||
* always a multiple of 4 bytes is written.<p>
|
* always a multiple of 4 bytes is written.<p>
|
||||||
*
|
*
|
||||||
* If the codepage is UTF-16, which is encouraged, strings
|
|
||||||
* <strong>must</strong> always be written as {@link Variant#VT_LPWSTR}
|
|
||||||
* strings, not as {@link Variant#VT_LPSTR} strings. This method ensure this
|
|
||||||
* by converting strings appropriately, if needed.
|
|
||||||
*
|
|
||||||
* @param out The stream to write the value to.
|
* @param out The stream to write the value to.
|
||||||
* @param type The variant's type.
|
* @param type The variant's type.
|
||||||
* @param value The variant's value.
|
* @param value The variant's value.
|
||||||
|
@ -278,102 +298,151 @@ public class VariantSupport extends Variant {
|
||||||
public static int write(final OutputStream out, final long type,
|
public static int write(final OutputStream out, final long type,
|
||||||
final Object value, final int codepage)
|
final Object value, final int codepage)
|
||||||
throws IOException, WritingNotSupportedException {
|
throws IOException, WritingNotSupportedException {
|
||||||
int length = 0;
|
int length = -1;
|
||||||
switch ((int) type) {
|
switch ((int) type) {
|
||||||
case Variant.VT_BOOL:
|
case Variant.VT_BOOL: {
|
||||||
if ( ( (Boolean) value ).booleanValue() ) {
|
if (value instanceof Boolean) {
|
||||||
out.write( 0xff );
|
int bb = ((Boolean)value) ? 0xff : 0x00;
|
||||||
out.write( 0xff );
|
out.write(bb);
|
||||||
} else {
|
out.write(bb);
|
||||||
out.write( 0x00 );
|
length = 2;
|
||||||
out.write( 0x00 );
|
|
||||||
}
|
}
|
||||||
length += 2;
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case Variant.VT_LPSTR:
|
case Variant.VT_LPSTR:
|
||||||
CodePageString codePageString = new CodePageString( (String) value, codepage );
|
if (value instanceof String) {
|
||||||
length += codePageString.write( out );
|
CodePageString codePageString = new CodePageString();
|
||||||
|
codePageString.setJavaValue( (String)value, codepage );
|
||||||
|
length = codePageString.write( out );
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Variant.VT_LPWSTR:
|
case Variant.VT_LPWSTR:
|
||||||
final int nrOfChars = ( (String) value ).length() + 1;
|
if (value instanceof String) {
|
||||||
length += TypeWriter.writeUIntToStream( out, nrOfChars );
|
UnicodeString uniString = new UnicodeString();
|
||||||
for ( char s : ( (String) value ).toCharArray() ) {
|
uniString.setJavaValue((String)value);
|
||||||
final int high = ( ( s & 0x0000ff00 ) >> 8 );
|
length = uniString.write(out);
|
||||||
final int low = ( s & 0x000000ff );
|
|
||||||
final byte highb = (byte) high;
|
|
||||||
final byte lowb = (byte) low;
|
|
||||||
out.write( lowb );
|
|
||||||
out.write( highb );
|
|
||||||
length += 2;
|
|
||||||
}
|
}
|
||||||
// NullTerminator
|
|
||||||
out.write( 0x00 );
|
|
||||||
out.write( 0x00 );
|
|
||||||
length += 2;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Variant.VT_CF:
|
case Variant.VT_CF:
|
||||||
final byte[] cf = (byte[]) value;
|
if (value instanceof byte[]) {
|
||||||
out.write(cf);
|
final byte[] cf = (byte[]) value;
|
||||||
length = cf.length;
|
out.write(cf);
|
||||||
|
length = cf.length;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Variant.VT_EMPTY:
|
case Variant.VT_EMPTY:
|
||||||
length += TypeWriter.writeUIntToStream( out, Variant.VT_EMPTY );
|
LittleEndian.putUInt(Variant.VT_EMPTY, out);
|
||||||
|
length = LittleEndianConsts.INT_SIZE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Variant.VT_I2:
|
case Variant.VT_I2:
|
||||||
length += TypeWriter.writeToStream( out, ( (Integer) value ).shortValue() );
|
if (value instanceof Number) {
|
||||||
|
LittleEndian.putShort( out, ((Number)value).shortValue() );
|
||||||
|
length = LittleEndianConsts.SHORT_SIZE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Variant.VT_UI2:
|
||||||
|
if (value instanceof Number) {
|
||||||
|
LittleEndian.putUShort( ((Number)value).intValue(), out );
|
||||||
|
length = LittleEndianConsts.SHORT_SIZE;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Variant.VT_I4:
|
case Variant.VT_I4:
|
||||||
if (!(value instanceof Integer)) {
|
if (value instanceof Number) {
|
||||||
throw new ClassCastException("Could not cast an object to "
|
LittleEndian.putInt( ((Number)value).intValue(), out);
|
||||||
+ Integer.class + ": "
|
length = LittleEndianConsts.INT_SIZE;
|
||||||
+ value.getClass() + ", "
|
}
|
||||||
+ value);
|
break;
|
||||||
|
|
||||||
|
case Variant.VT_UI4:
|
||||||
|
if (value instanceof Number) {
|
||||||
|
LittleEndian.putUInt( ((Number)value).longValue(), out);
|
||||||
|
length = LittleEndianConsts.INT_SIZE;
|
||||||
}
|
}
|
||||||
length += TypeWriter.writeToStream(out, ((Integer) value).intValue());
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Variant.VT_I8:
|
case Variant.VT_I8:
|
||||||
length += TypeWriter.writeToStream(out, ((Long) value).longValue());
|
if (value instanceof Number) {
|
||||||
|
LittleEndian.putLong( ((Number)value).longValue(), out);
|
||||||
|
length = LittleEndianConsts.LONG_SIZE;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Variant.VT_UI8: {
|
||||||
|
if (value instanceof Number) {
|
||||||
|
BigInteger bi = (value instanceof BigInteger) ? (BigInteger)value : BigInteger.valueOf(((Number)value).longValue());
|
||||||
|
if (bi.bitLength() > 64) {
|
||||||
|
throw new WritingNotSupportedException(type, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] biBytesBE = bi.toByteArray(), biBytesLE = new byte[LittleEndianConsts.LONG_SIZE];
|
||||||
|
int i=biBytesBE.length;
|
||||||
|
for (byte b : biBytesBE) {
|
||||||
|
if (i<=LittleEndianConsts.LONG_SIZE) {
|
||||||
|
biBytesLE[i-1] = b;
|
||||||
|
}
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.write(biBytesLE);
|
||||||
|
length = LittleEndianConsts.LONG_SIZE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Variant.VT_R4: {
|
||||||
|
if (value instanceof Number) {
|
||||||
|
int floatBits = Float.floatToIntBits(((Number)value).floatValue());
|
||||||
|
LittleEndian.putInt(floatBits, out);
|
||||||
|
length = LittleEndianConsts.INT_SIZE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case Variant.VT_R8:
|
case Variant.VT_R8:
|
||||||
length += TypeWriter.writeToStream(out, ((Double) value).doubleValue());
|
if (value instanceof Number) {
|
||||||
|
LittleEndian.putDouble( ((Number)value).doubleValue(), out);
|
||||||
|
length = LittleEndianConsts.DOUBLE_SIZE;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Variant.VT_FILETIME:
|
case Variant.VT_FILETIME:
|
||||||
long filetime = Util.dateToFileTime((Date) value);
|
if (value instanceof Date) {
|
||||||
int high = (int) ((filetime >> 32) & 0x00000000FFFFFFFFL);
|
long filetime = Util.dateToFileTime((Date) value);
|
||||||
int low = (int) (filetime & 0x00000000FFFFFFFFL);
|
int high = (int) ((filetime >> 32) & 0x00000000FFFFFFFFL);
|
||||||
Filetime filetimeValue = new Filetime( low, high);
|
int low = (int) (filetime & 0x00000000FFFFFFFFL);
|
||||||
length += filetimeValue.write( out );
|
Filetime filetimeValue = new Filetime( low, high);
|
||||||
|
length = filetimeValue.write( out );
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* The variant type is not supported yet. However, if the value
|
|
||||||
* is a byte array we can write it nevertheless. */
|
|
||||||
if (value instanceof byte[]) {
|
|
||||||
final byte[] b = (byte[]) value;
|
|
||||||
out.write(b);
|
|
||||||
length = b.length;
|
|
||||||
writeUnsupportedTypeMessage(new WritingNotSupportedException(type, value));
|
|
||||||
} else {
|
|
||||||
throw new WritingNotSupportedException(type, value);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pad values to 4-bytes */
|
/* The variant type is not supported yet. However, if the value
|
||||||
while ( ( length & 0x3 ) != 0 ) {
|
* is a byte array we can write it nevertheless. */
|
||||||
out.write( 0x00 );
|
if (length == -1) {
|
||||||
length++;
|
if (value instanceof byte[]) {
|
||||||
|
final byte[] b = (byte[]) value;
|
||||||
|
out.write(b);
|
||||||
|
length = b.length;
|
||||||
|
writeUnsupportedTypeMessage(new WritingNotSupportedException(type, value));
|
||||||
|
} else {
|
||||||
|
throw new WritingNotSupportedException(type, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return length;
|
/* pad values to 4-bytes */
|
||||||
|
int padding = (4-(length & 0x3)) & 0x3;
|
||||||
|
out.write(paddingBytes, 0, padding);
|
||||||
|
|
||||||
|
return length + padding;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,71 +18,107 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.poi.hpsf;
|
package org.apache.poi.hpsf;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import static org.junit.Assert.*;
|
||||||
import org.apache.poi.hpsf.wellknown.PropertyIDMap;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import org.apache.poi.util.HexRead;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
/**
|
import org.apache.poi.hpsf.wellknown.PropertyIDMap;
|
||||||
* @author Yegor Kozlov
|
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||||
*/
|
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||||
public class TestVariantSupport extends TestCase {
|
import org.apache.poi.poifs.storage.RawDataUtil;
|
||||||
|
import org.apache.poi.util.LittleEndianByteArrayInputStream;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class TestVariantSupport {
|
||||||
|
@Test
|
||||||
public void test52337() throws Exception {
|
public void test52337() throws Exception {
|
||||||
// document summary stream from test1-excel.doc attached to Bugzilla 52337
|
// document summary stream from test1-excel.doc attached to Bugzilla 52337
|
||||||
String hex =
|
String documentSummaryEnc =
|
||||||
"FE FF 00 00 05 01 02 00 00 00 00 00 00 00 00 00 00 00 00 00" +
|
"H4sIAAAAAAAAAG2RsUvDQBjFXxsraiuNKDoI8ZwclIJOjhYCGpQitINbzXChgTQtyQ3+Hw52cHB0E"+
|
||||||
"00 00 00 00 02 00 00 00 02 D5 CD D5 9C 2E 1B 10 93 97 08 00" +
|
"kdHRxfBpeAf4H/g5KK+M59Firn8eNx3d+++x31+AZVSGdOfrZTHz+Prxrp7eTWH7Z2PO5+1ylTtrA"+
|
||||||
"2B 2C F9 AE 44 00 00 00 05 D5 CD D5 9C 2E 1B 10 93 97 08 00" +
|
"SskBrXKOiROhnavWREZskNWSK3ZI3ckyp5IC55JMvkiaySF7JIXlF4v0tPbzOAR1XE18MwM32dGjW"+
|
||||||
"2B 2C F9 AE 58 01 00 00 14 01 00 00 0C 00 00 00 01 00 00 00" +
|
"IVJAanaVhoppRFMZZDjjSgyO9WT10Cq1vVX/uh/Txn3pucc7m6fTiXPEPldG5Qc0t2vEkXic2iZ5c"+
|
||||||
"68 00 00 00 0F 00 00 00 70 00 00 00 05 00 00 00 98 00 00 00" +
|
"JDkd8VFS3pcMBzIvS7buaeB3j06C1nF7krFJPRdz62M4rM7/8f3NtyE+LQyQoY8QCfbQwAU1l/UF0"+
|
||||||
"06 00 00 00 A0 00 00 00 11 00 00 00 A8 00 00 00 17 00 00 00" +
|
"ubraA6DXWzC5x7gG6xzLtsAAgAA";
|
||||||
"B0 00 00 00 0B 00 00 00 B8 00 00 00 10 00 00 00 C0 00 00 00" +
|
byte[] bytes = RawDataUtil.decompress(documentSummaryEnc);
|
||||||
"13 00 00 00 C8 00 00 00 16 00 00 00 D0 00 00 00 0D 00 00 00" +
|
|
||||||
"D8 00 00 00 0C 00 00 00 F3 00 00 00 02 00 00 00 E4 04 00 00" +
|
|
||||||
"1E 00 00 00 20 00 00 00 44 65 70 61 72 74 6D 65 6E 74 20 6F" +
|
|
||||||
"66 20 49 6E 74 65 72 6E 61 6C 20 41 66 66 61 69 72 73 00 00" +
|
|
||||||
"03 00 00 00 05 00 00 00 03 00 00 00 01 00 00 00 03 00 00 00" +
|
|
||||||
"47 03 00 00 03 00 00 00 0F 27 0B 00 0B 00 00 00 00 00 00 00" +
|
|
||||||
"0B 00 00 00 00 00 00 00 0B 00 00 00 00 00 00 00 0B 00 00 00" +
|
|
||||||
"00 00 00 00 1E 10 00 00 01 00 00 00 0F 00 00 00 54 68 69 73" +
|
|
||||||
"20 69 73 20 61 20 74 65 73 74 00 0C 10 00 00 02 00 00 00 1E" +
|
|
||||||
"00 00 00 06 00 00 00 54 69 74 6C 65 00 03 00 00 00 01 00 00" +
|
|
||||||
"00 00 00 00 A8 00 00 00 03 00 00 00 00 00 00 00 20 00 00 00" +
|
|
||||||
"01 00 00 00 38 00 00 00 02 00 00 00 40 00 00 00 01 00 00 00" +
|
|
||||||
"02 00 00 00 0C 00 00 00 5F 50 49 44 5F 48 4C 49 4E 4B 53 00" +
|
|
||||||
"02 00 00 00 E4 04 00 00 41 00 00 00 60 00 00 00 06 00 00 00" +
|
|
||||||
"03 00 00 00 74 00 74 00 03 00 00 00 09 00 00 00 03 00 00 00" +
|
|
||||||
"00 00 00 00 03 00 00 00 05 00 00 00 1F 00 00 00 0C 00 00 00" +
|
|
||||||
"4E 00 6F 00 72 00 6D 00 61 00 6C 00 32 00 2E 00 78 00 6C 00" +
|
|
||||||
"73 00 00 00 1F 00 00 00 0A 00 00 00 53 00 68 00 65 00 65 00" +
|
|
||||||
"74 00 31 00 21 00 44 00 32 00 00 00 ";
|
|
||||||
byte[] bytes = HexRead.readFromString(hex);
|
|
||||||
|
|
||||||
PropertySet ps = PropertySetFactory.create(new ByteArrayInputStream(bytes));
|
PropertySet ps = PropertySetFactory.create(new ByteArrayInputStream(bytes));
|
||||||
DocumentSummaryInformation dsi = (DocumentSummaryInformation) ps;
|
DocumentSummaryInformation dsi = (DocumentSummaryInformation) ps;
|
||||||
Section s = dsi.getSections().get(0);
|
Section s = dsi.getSections().get(0);
|
||||||
|
|
||||||
Object hdrs = s.getProperty(PropertyIDMap.PID_HEADINGPAIR);
|
Object hdrs = s.getProperty(PropertyIDMap.PID_HEADINGPAIR);
|
||||||
|
assertNotNull(hdrs);
|
||||||
|
assertEquals(byte[].class, hdrs.getClass());
|
||||||
|
|
||||||
assertNotNull("PID_HEADINGPAIR was not found", hdrs);
|
|
||||||
|
|
||||||
assertTrue("PID_HEADINGPAIR: expected byte[] but was "+ hdrs.getClass(), hdrs instanceof byte[]);
|
|
||||||
// parse the value
|
// parse the value
|
||||||
Vector v = new Vector((short)Variant.VT_VARIANT);
|
Vector v = new Vector((short)Variant.VT_VARIANT);
|
||||||
v.read((byte[])hdrs, 0);
|
LittleEndianByteArrayInputStream lei = new LittleEndianByteArrayInputStream((byte[])hdrs, 0);
|
||||||
|
v.read(lei);
|
||||||
|
|
||||||
TypedPropertyValue[] items = v.getValues();
|
TypedPropertyValue[] items = v.getValues();
|
||||||
assertEquals(2, items.length);
|
assertEquals(2, items.length);
|
||||||
|
|
||||||
assertNotNull(items[0].getValue());
|
Object cp = items[0].getValue();
|
||||||
assertTrue("first item must be CodePageString but was "+ items[0].getValue().getClass(),
|
assertNotNull(cp);
|
||||||
items[0].getValue() instanceof CodePageString);
|
assertEquals(CodePageString.class, cp.getClass());
|
||||||
assertNotNull(items[1].getValue());
|
Object i = items[1].getValue();
|
||||||
assertTrue("second item must be Integer but was "+ items[1].getValue().getClass(),
|
assertNotNull(i);
|
||||||
items[1].getValue() instanceof Integer);
|
assertEquals(Integer.class, i.getClass());
|
||||||
assertEquals(1, (int)(Integer)items[1].getValue());
|
assertEquals(1, i);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void newNumberTypes() throws Exception {
|
||||||
|
ClipboardData cd = new ClipboardData();
|
||||||
|
cd.setValue(new byte[10]);
|
||||||
|
|
||||||
|
Object exp[][] = {
|
||||||
|
{ Variant.VT_CF, cd.toByteArray() },
|
||||||
|
{ Variant.VT_BOOL, true },
|
||||||
|
{ Variant.VT_LPSTR, "codepagestring" },
|
||||||
|
{ Variant.VT_LPWSTR, "widestring" },
|
||||||
|
{ Variant.VT_I2, -1 }, // int, not short ... :(
|
||||||
|
{ Variant.VT_UI2, 0xFFFF },
|
||||||
|
{ Variant.VT_I4, -1 },
|
||||||
|
{ Variant.VT_UI4, 0xFFFFFFFFL },
|
||||||
|
{ Variant.VT_I8, -1L },
|
||||||
|
{ Variant.VT_UI8, BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.TEN) },
|
||||||
|
{ Variant.VT_R4, -999.99f },
|
||||||
|
{ Variant.VT_R8, -999.99d },
|
||||||
|
};
|
||||||
|
|
||||||
|
HSSFWorkbook wb = new HSSFWorkbook();
|
||||||
|
POIFSFileSystem poifs = new POIFSFileSystem();
|
||||||
|
DocumentSummaryInformation dsi = PropertySetFactory.newDocumentSummaryInformation();
|
||||||
|
CustomProperties cpList = new CustomProperties();
|
||||||
|
for (Object o[] : exp) {
|
||||||
|
int type = (Integer)o[0];
|
||||||
|
Property p = new Property(PropertyIDMap.PID_MAX+type, type, o[1]);
|
||||||
|
cpList.put("testprop"+type, new CustomProperty(p, "testprop"+type));
|
||||||
|
|
||||||
|
}
|
||||||
|
dsi.setCustomProperties(cpList);
|
||||||
|
dsi.write(poifs.getRoot(), DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
||||||
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
|
poifs.writeFilesystem(bos);
|
||||||
|
poifs.close();
|
||||||
|
poifs = new POIFSFileSystem(new ByteArrayInputStream(bos.toByteArray()));
|
||||||
|
dsi = (DocumentSummaryInformation)PropertySetFactory.create(poifs.getRoot(), DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
||||||
|
cpList = dsi.getCustomProperties();
|
||||||
|
int i=0;
|
||||||
|
for (Object o[] : exp) {
|
||||||
|
Object obj = cpList.get("testprop"+o[0]);
|
||||||
|
if (o[1] instanceof byte[]) {
|
||||||
|
assertArrayEquals("property "+i, (byte[])o[1], (byte[])obj);
|
||||||
|
} else {
|
||||||
|
assertEquals("property "+i, o[1], obj);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
poifs.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue