Fix hpsf javadocs and code issues
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1793596 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
5600fa6f58
commit
456b33a837
@ -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 PropertySet {
|
||||
public MutablePropertySet(final PropertySet ps) {
|
||||
super(ps);
|
||||
}
|
||||
|
||||
/* package */ MutablePropertySet(final InputStream stream)
|
||||
throws NoPropertySetStreamException, MarkUnsupportedException, IOException, UnsupportedEncodingException {
|
||||
super(stream);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@ -196,100 +238,6 @@ 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,22 +262,19 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
@ -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,11 +514,19 @@ 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) {
|
||||
// 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;
|
||||
}
|
||||
|
@ -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;
|
||||
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();
|
||||
}
|
||||
} catch (UnexpectedPropertySetTypeException ex) {
|
||||
/* This exception will never be throws because we already checked
|
||||
* explicitly for this case above. */
|
||||
throw new IllegalStateException(ex);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 MutablePropertySet {
|
||||
public SpecialPropertySet(final PropertySet ps) throws UnexpectedPropertySetTypeException {
|
||||
super(ps);
|
||||
}
|
||||
|
||||
/* package */ SpecialPropertySet(final InputStream stream)
|
||||
throws NoPropertySetStreamException, MarkUnsupportedException, IOException, UnsupportedEncodingException {
|
||||
super(stream);
|
||||
}
|
||||
}
|
||||
|
@ -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,6 +65,32 @@ public final class SummaryInformation extends SpecialPropertySet {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
@ -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 HashMap<Long,String> {
|
||||
* (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 HashMap<Long,String> {
|
||||
*/
|
||||
|
||||
/**
|
||||
* <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 HashMap<Long,String> {
|
||||
// 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 HashMap<Long,String> {
|
||||
// 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 HashMap<Long,String> {
|
||||
|
||||
|
||||
/**
|
||||
* <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 HashMap<Long,String> {
|
||||
|
||||
|
||||
/**
|
||||
* <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 HashMap<Long,String> {
|
||||
|
||||
|
||||
/**
|
||||
* <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 HashMap<Long,String> {
|
||||
/**
|
||||
* @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 HashMap<Long,String> {
|
||||
|
||||
|
||||
/**
|
||||
* <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 HashMap<Long,String> {
|
||||
|
||||
|
||||
/**
|
||||
* <p>For the most basic testing.</p>
|
||||
* For the most basic testing.
|
||||
*
|
||||
* @param args The command-line arguments
|
||||
*/
|
||||
|
@ -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 HashMap {
|
||||
* /<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 HashMap {
|
||||
* @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 HashMap {
|
||||
* @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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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 LittleEndianByteArrayInputStream extends ByteArrayInputStream
|
||||
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,22 +81,26 @@ public final class LittleEndianByteArrayInputStream extends ByteArrayInputStream
|
||||
|
||||
@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
|
||||
|
@ -32,7 +32,7 @@ public class LittleEndianCP950Reader extends Reader {
|
||||
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 extends Reader {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
|
||||
public void close() {
|
||||
}
|
||||
|
||||
private int handleRange1(int leading, int trailing) {
|
||||
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
|
@ -17,135 +17,62 @@
|
||||
|
||||
package org.apache.poi.hpsf.basic;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Date;
|
||||
import java.util.Random;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.hpsf.*;
|
||||
import org.apache.poi.hpsf.CustomProperties;
|
||||
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
||||
import org.apache.poi.hpsf.HPSFException;
|
||||
import org.apache.poi.hpsf.PropertySetFactory;
|
||||
import org.apache.poi.hpsf.SummaryInformation;
|
||||
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.poifs.filesystem.POIFSFileSystem;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
/**
|
||||
* Basing on: src/examples/src/org/apache/poi/hpsf/examples/ModifyDocumentSummaryInformation.java
|
||||
* This class tests reading and writing of meta data. No actual document is created. All information
|
||||
* is stored in a virtual document in a ByteArrayOutputStream
|
||||
* @author Matthias G\u00fcnter
|
||||
*/
|
||||
public final class TestMetaDataIPI extends TestCase{
|
||||
public final class TestMetaDataIPI {
|
||||
|
||||
private ByteArrayOutputStream bout; //our store
|
||||
private POIFSFileSystem poifs;
|
||||
private DirectoryEntry dir;
|
||||
private POIFSFileSystem poifs ;
|
||||
private DocumentSummaryInformation dsi;
|
||||
private SummaryInformation si;
|
||||
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
poifs.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup is used to get the document ready. Gets the DocumentSummaryInformation and the
|
||||
* SummaryInformation to reasonable values
|
||||
*/
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
bout = new ByteArrayOutputStream();
|
||||
poifs = new POIFSFileSystem();
|
||||
dir = poifs.getRoot();
|
||||
dsi = null;
|
||||
try {
|
||||
DocumentEntry dsiEntry = (DocumentEntry) dir
|
||||
.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
||||
DocumentInputStream dis = new DocumentInputStream(dsiEntry);
|
||||
PropertySet ps = new PropertySet(dis);
|
||||
dis.close();
|
||||
dsi = new DocumentSummaryInformation(ps);
|
||||
|
||||
} catch (FileNotFoundException ex) {
|
||||
/*
|
||||
* There is no document summary information yet. We have to create a
|
||||
* new one.
|
||||
*/
|
||||
dsi = PropertySetFactory.newDocumentSummaryInformation();
|
||||
assertNotNull(dsi);
|
||||
}
|
||||
assertNotNull(dsi);
|
||||
try {
|
||||
DocumentEntry dsiEntry = (DocumentEntry) dir
|
||||
.getEntry(SummaryInformation.DEFAULT_STREAM_NAME);
|
||||
DocumentInputStream dis = new DocumentInputStream(dsiEntry);
|
||||
PropertySet ps = new PropertySet(dis);
|
||||
dis.close();
|
||||
si = new SummaryInformation(ps);
|
||||
|
||||
} catch (FileNotFoundException ex) {
|
||||
/*
|
||||
* There is no document summary information yet. We have to create a
|
||||
* new one.
|
||||
*/
|
||||
si = PropertySetFactory.newSummaryInformation();
|
||||
assertNotNull(si);
|
||||
}
|
||||
assertNotNull(dsi);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the ByteArrayOutputStream and reads it into a ByteArrayInputStream.
|
||||
* When finished writing information this method is used in the tests to
|
||||
* start reading from the created document and then the see if the results match.
|
||||
*/
|
||||
public void closeAndReOpen() throws IOException, HPSFException {
|
||||
|
||||
dsi.write(dir, DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
||||
si.write(dir, SummaryInformation.DEFAULT_STREAM_NAME);
|
||||
|
||||
si = null;
|
||||
dsi = null;
|
||||
poifs.writeFilesystem(bout);
|
||||
bout.flush();
|
||||
|
||||
InputStream is = new ByteArrayInputStream(bout.toByteArray());
|
||||
assertNotNull(is);
|
||||
POIFSFileSystem poifs = new POIFSFileSystem(is);
|
||||
is.close();
|
||||
|
||||
assertNotNull(poifs);
|
||||
/* Read the document summary information. */
|
||||
DirectoryEntry dir = poifs.getRoot();
|
||||
|
||||
DocumentEntry dsiEntry = (DocumentEntry) dir
|
||||
.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
||||
DocumentInputStream dis = new DocumentInputStream(dsiEntry);
|
||||
PropertySet ps = new PropertySet(dis);
|
||||
dis.close();
|
||||
dsi = new DocumentSummaryInformation(ps);
|
||||
|
||||
try {
|
||||
dsiEntry = (DocumentEntry) dir
|
||||
.getEntry(SummaryInformation.DEFAULT_STREAM_NAME);
|
||||
dis = new DocumentInputStream(dsiEntry);
|
||||
ps = new PropertySet(dis);
|
||||
dis.close();
|
||||
si = new SummaryInformation(ps);
|
||||
|
||||
} catch (FileNotFoundException ex) {
|
||||
/*
|
||||
* There is no document summary information yet. We have to create a
|
||||
* new one.
|
||||
*/
|
||||
si = PropertySetFactory.newSummaryInformation();
|
||||
assertNotNull(si);
|
||||
}
|
||||
dsi.write(poifs.getRoot(), DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
||||
si.write(poifs.getRoot(), SummaryInformation.DEFAULT_STREAM_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the most important information in DocumentSummaryInformation and Summary Information and rereads it
|
||||
*/
|
||||
@Test
|
||||
public void testOne() throws Exception {
|
||||
|
||||
// DocumentSummaryInformation
|
||||
@ -201,9 +128,7 @@ public final class TestMetaDataIPI extends TestCase{
|
||||
* serve as a container for custom properties.
|
||||
*/
|
||||
customProperties = dsi.getCustomProperties();
|
||||
if (customProperties == null) {
|
||||
fail();
|
||||
}
|
||||
assertNotNull(customProperties);
|
||||
|
||||
/* Insert some custom properties into the container. */
|
||||
String a1 = (String) customProperties.get("Key1");
|
||||
@ -224,23 +149,10 @@ public final class TestMetaDataIPI extends TestCase{
|
||||
assertEquals("Neg", new Integer(-100000), a7);
|
||||
}
|
||||
|
||||
/**
|
||||
* multiplies a string
|
||||
* @param s Input String
|
||||
* @return the multiplied String
|
||||
*/
|
||||
private static String elongate(String s) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
sb.append(s);
|
||||
sb.append(" ");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test very long input in each of the fields (approx 30-60KB each)
|
||||
*/
|
||||
@Test
|
||||
public void testTwo() throws Exception {
|
||||
|
||||
String company = elongate("company");
|
||||
@ -323,21 +235,10 @@ public final class TestMetaDataIPI extends TestCase{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* adds strange characters to the string
|
||||
* @param s Input String
|
||||
* @return the multiplied String
|
||||
*/
|
||||
private static String strangize(String s) {
|
||||
StringBuilder sb = strangizeInit(s);
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests with strange characters in keys and data (Umlaute etc.)
|
||||
*/
|
||||
@Test
|
||||
public void testThree() throws Exception {
|
||||
|
||||
String company = strangize("company");
|
||||
@ -423,50 +324,18 @@ public final class TestMetaDataIPI extends TestCase{
|
||||
/**
|
||||
* Iterative testing: writing, reading etc.
|
||||
*/
|
||||
@Test
|
||||
public void testFour() throws Exception {
|
||||
for (int i = 1; i < 100; i++) {
|
||||
setUp();
|
||||
testThree();
|
||||
closeAndReOpen();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* adds strange characters to the string with the adding of unicode characters
|
||||
* @param s Input String
|
||||
* @return the multiplied String
|
||||
*/
|
||||
private static String strangizeU(String s) {
|
||||
|
||||
StringBuilder sb = strangizeInit(s);
|
||||
sb.append("\u00e4\u00f6\u00fc\uD840\uDC00");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static StringBuilder strangizeInit(String s) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String[] umlaute = { "\u00e4", "\u00fc", "\u00f6", "\u00dc", "$", "\u00d6", "\u00dc",
|
||||
"\u00c9", "\u00d6", "@", "\u00e7", "&" };
|
||||
Random rand = new Random(0); // TODO - no Random - tests should be completely deterministic
|
||||
for (int i = 0; i < 5; i++) {
|
||||
sb.append(s);
|
||||
sb.append(" ");
|
||||
char j = (char) rand.nextInt(220);
|
||||
j += 33;
|
||||
// System.out.println(j);
|
||||
sb.append(">");
|
||||
sb.append(Character.valueOf(j));
|
||||
sb.append("=");
|
||||
sb.append(umlaute[rand.nextInt(umlaute.length)]);
|
||||
sb.append("<");
|
||||
}
|
||||
return sb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unicode test
|
||||
*/
|
||||
@Test
|
||||
public void testUnicode() throws Exception {
|
||||
String company = strangizeU("company");
|
||||
String manager = strangizeU("manager");
|
||||
@ -490,11 +359,8 @@ public final class TestMetaDataIPI extends TestCase{
|
||||
si.setComments(comments);
|
||||
si.setKeywords(keywords);
|
||||
si.setSubject(subject);
|
||||
CustomProperties customProperties = dsi.getCustomProperties();
|
||||
if (customProperties == null) {
|
||||
customProperties = new CustomProperties();
|
||||
}
|
||||
|
||||
CustomProperties customProperties = new CustomProperties();
|
||||
/* Insert some custom properties into the container. */
|
||||
customProperties.put(k1, p1);
|
||||
customProperties.put(k2, p2);
|
||||
@ -529,9 +395,7 @@ public final class TestMetaDataIPI extends TestCase{
|
||||
* serve as a container for custom properties.
|
||||
*/
|
||||
customProperties = dsi.getCustomProperties();
|
||||
if (customProperties == null) {
|
||||
fail();
|
||||
}
|
||||
assertNotNull(customProperties);
|
||||
|
||||
/* Insert some custom properties into the container. */
|
||||
// System.out.println(k1);
|
||||
@ -552,10 +416,11 @@ public final class TestMetaDataIPI extends TestCase{
|
||||
* Iterative testing of the unicode test
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testSix() throws Exception {
|
||||
for (int i = 1; i < 100; i++) {
|
||||
setUp();
|
||||
testUnicode();
|
||||
closeAndReOpen();
|
||||
}
|
||||
}
|
||||
|
||||
@ -563,6 +428,7 @@ public final class TestMetaDataIPI extends TestCase{
|
||||
/**
|
||||
* Tests conversion in custom fields and errors
|
||||
*/
|
||||
@Test
|
||||
public void testConvAndExistence() throws Exception {
|
||||
|
||||
CustomProperties customProperties = dsi.getCustomProperties();
|
||||
@ -656,4 +522,86 @@ public final class TestMetaDataIPI extends TestCase{
|
||||
assertTrue(customProperties.get("negdouble") instanceof Double);
|
||||
assertTrue(customProperties.get("date") instanceof Date);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Closes the ByteArrayOutputStream and reads it into a ByteArrayInputStream.
|
||||
* When finished writing information this method is used in the tests to
|
||||
* start reading from the created document and then the see if the results match.
|
||||
*/
|
||||
private void closeAndReOpen() throws IOException, HPSFException {
|
||||
dsi.write(poifs.getRoot(), DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
||||
si.write(poifs.getRoot(), SummaryInformation.DEFAULT_STREAM_NAME);
|
||||
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||
poifs.writeFilesystem(bout);
|
||||
poifs.close();
|
||||
|
||||
InputStream is = new ByteArrayInputStream(bout.toByteArray());
|
||||
poifs = new POIFSFileSystem(is);
|
||||
is.close();
|
||||
|
||||
/* Read the document summary information. */
|
||||
DirectoryEntry dir = poifs.getRoot();
|
||||
|
||||
dsi = (DocumentSummaryInformation)PropertySetFactory.create(dir, DocumentSummaryInformation.DEFAULT_STREAM_NAME);;
|
||||
si = (SummaryInformation)PropertySetFactory.create(dir, SummaryInformation.DEFAULT_STREAM_NAME);;
|
||||
}
|
||||
|
||||
/**
|
||||
* multiplies a string
|
||||
* @param s Input String
|
||||
* @return the multiplied String
|
||||
*/
|
||||
private static String elongate(String s) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
sb.append(s);
|
||||
sb.append(" ");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* adds strange characters to the string
|
||||
* @param s Input String
|
||||
* @return the multiplied String
|
||||
*/
|
||||
private static String strangize(String s) {
|
||||
StringBuilder sb = strangizeInit(s);
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* adds strange characters to the string with the adding of unicode characters
|
||||
* @param s Input String
|
||||
* @return the multiplied String
|
||||
*/
|
||||
private static String strangizeU(String s) {
|
||||
|
||||
StringBuilder sb = strangizeInit(s);
|
||||
sb.append("\u00e4\u00f6\u00fc\uD840\uDC00");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static StringBuilder strangizeInit(String s) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String[] umlaute = { "\u00e4", "\u00fc", "\u00f6", "\u00dc", "$", "\u00d6", "\u00dc",
|
||||
"\u00c9", "\u00d6", "@", "\u00e7", "&" };
|
||||
Random rand = new Random(0); // TODO - no Random - tests should be completely deterministic
|
||||
for (int i = 0; i < 5; i++) {
|
||||
sb.append(s);
|
||||
sb.append(" ");
|
||||
char j = (char) rand.nextInt(220);
|
||||
j += 33;
|
||||
// System.out.println(j);
|
||||
sb.append(">");
|
||||
sb.append(Character.valueOf(j));
|
||||
sb.append("=");
|
||||
sb.append(umlaute[rand.nextInt(umlaute.length)]);
|
||||
sb.append("<");
|
||||
}
|
||||
return sb;
|
||||
}
|
||||
}
|
||||
|
@ -17,77 +17,214 @@
|
||||
|
||||
package org.apache.poi.hpsf.basic;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.poi.POIDataSamples;
|
||||
import org.apache.poi.hpsf.CustomProperties;
|
||||
import org.apache.poi.hpsf.CustomProperty;
|
||||
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
||||
import org.apache.poi.hpsf.HPSFException;
|
||||
import org.apache.poi.hpsf.MarkUnsupportedException;
|
||||
import org.apache.poi.hpsf.NoPropertySetStreamException;
|
||||
import org.apache.poi.hpsf.PropertySet;
|
||||
import org.apache.poi.hpsf.PropertySetFactory;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryEntry;
|
||||
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameter;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
/**
|
||||
* <p>Tests some HPSF functionality by reading all property sets from all files
|
||||
* Tests some HPSF functionality by reading all property sets from all files
|
||||
* in the "data" directory. If you want to ensure HPSF can deal with a certain
|
||||
* OLE2 file, just add it to the "data" directory and run this test case.</p>
|
||||
* OLE2 file, just add it to the "data" directory and run this test case.
|
||||
*/
|
||||
public class TestReadAllFiles extends TestCase {
|
||||
private static String[] excludes = new String[] {};
|
||||
@RunWith(Parameterized.class)
|
||||
public class TestReadAllFiles {
|
||||
private static final POIDataSamples _samples = POIDataSamples.getHPSFInstance();
|
||||
|
||||
/**
|
||||
* <p>This test methods reads all property set streams from all POI
|
||||
* filesystems in the "data" directory.</p>
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws HPSFException
|
||||
*/
|
||||
public void testReadAllFiles() throws IOException, HPSFException
|
||||
{
|
||||
POIDataSamples _samples = POIDataSamples.getHPSFInstance();
|
||||
final File dataDir = _samples.getFile("");
|
||||
final File[] fileList = dataDir.listFiles(new FileFilter()
|
||||
{
|
||||
@Parameters(name="{index}: {0} using {1}")
|
||||
public static Iterable<Object[]> files() {
|
||||
final List<Object[]> files = new ArrayList<Object[]>();
|
||||
|
||||
_samples.getFile("").listFiles(new FileFilter() {
|
||||
@Override
|
||||
public boolean accept(final File f)
|
||||
{
|
||||
// exclude files that we know will fail
|
||||
return f.isFile() && checkExclude(f);
|
||||
public boolean accept(final File f) {
|
||||
if (f.getName().startsWith("Test")) { // && f.getName().equals("TestCorel.shw")
|
||||
files.add(new Object[]{ f });
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
for (final File f : fileList) {
|
||||
/* Read the POI filesystem's property set streams: */
|
||||
final POIFile[] psf1 = Util.readPropertySets(f);
|
||||
return files;
|
||||
}
|
||||
|
||||
for (int j = 0; j < psf1.length; j++)
|
||||
{
|
||||
final InputStream in =
|
||||
new ByteArrayInputStream(psf1[j].getBytes());
|
||||
@Parameter(value=0)
|
||||
public File file;
|
||||
|
||||
/**
|
||||
* This test methods reads all property set streams from all POI
|
||||
* filesystems in the "data" directory.
|
||||
*/
|
||||
@Test
|
||||
public void read() throws IOException, NoPropertySetStreamException, MarkUnsupportedException {
|
||||
/* Read the POI filesystem's property set streams: */
|
||||
for (POIFile pf : Util.readPropertySets(file)) {
|
||||
final InputStream in = new ByteArrayInputStream(pf.getBytes());
|
||||
try {
|
||||
PropertySetFactory.create(in);
|
||||
} catch (Exception e) {
|
||||
throw new IOException("While handling file: " + f + " at " + j, e);
|
||||
} finally {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This test method does a write and read back test with all POI
|
||||
* filesystems in the "data" directory by performing the following
|
||||
* actions for each file:<p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>Read its property set streams.
|
||||
* <li>Create a new POI filesystem containing the origin file's property set streams.
|
||||
* <li>Read the property set streams from the POI filesystem just created.
|
||||
* <li>Compare each property set stream with the corresponding one from
|
||||
* the origin file and check whether they are equal.
|
||||
* </ul>
|
||||
*/
|
||||
@Test
|
||||
public void recreate() throws IOException, HPSFException {
|
||||
/* Read the POI filesystem's property set streams: */
|
||||
Map<String,PropertySet> psMap = new HashMap<String,PropertySet>();
|
||||
|
||||
/* Create a new POI filesystem containing the origin file's
|
||||
* property set streams: */
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
final POIFSFileSystem poiFs = new POIFSFileSystem();
|
||||
for (POIFile poifile : Util.readPropertySets(file)) {
|
||||
final InputStream in = new ByteArrayInputStream(poifile.getBytes());
|
||||
final PropertySet psIn = PropertySetFactory.create(in);
|
||||
psMap.put(poifile.getName(), psIn);
|
||||
bos.reset();
|
||||
psIn.write(bos);
|
||||
poiFs.createDocument(new ByteArrayInputStream(bos.toByteArray()), poifile.getName());
|
||||
}
|
||||
|
||||
/* Read the property set streams from the POI filesystem just
|
||||
* created. */
|
||||
for (Map.Entry<String,PropertySet> me : psMap.entrySet()) {
|
||||
final PropertySet ps1 = me.getValue();
|
||||
final PropertySet ps2 = PropertySetFactory.create(poiFs.getRoot(), me.getKey());
|
||||
assertNotNull(ps2);
|
||||
|
||||
/* Compare the property set stream with the corresponding one
|
||||
* from the origin file and check whether they are equal. */
|
||||
|
||||
// Because of missing 0-paddings in the original input files, the bytes might differ.
|
||||
// This fixes the comparison
|
||||
String ps1str = ps1.toString().replace(" 00", " ").replace(".", " ").replaceAll("(?m)( +$|(size|offset): [0-9]+)","");
|
||||
String ps2str = ps2.toString().replace(" 00", " ").replace(".", " ").replaceAll("(?m)( +$|(size|offset): [0-9]+)","");
|
||||
|
||||
assertEquals("Equality for file " + file.getName(), ps1str, ps2str);
|
||||
}
|
||||
poiFs.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>This test method checks whether DocumentSummary information streams
|
||||
* can be read. This is done by opening all "Test*" files in the 'poifs' directrory
|
||||
* pointed to by the "POI.testdata.path" system property, trying to extract
|
||||
* the document summary information stream in the root directory and calling
|
||||
* its get... methods.</p>
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void readDocumentSummaryInformation() throws Exception {
|
||||
/* Read a test document <em>doc</em> into a POI filesystem. */
|
||||
NPOIFSFileSystem poifs = new NPOIFSFileSystem(file, true);
|
||||
try {
|
||||
final DirectoryEntry dir = poifs.getRoot();
|
||||
/*
|
||||
* If there is a document summry information stream, read it from
|
||||
* the POI filesystem.
|
||||
*/
|
||||
if (dir.hasEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME)) {
|
||||
final DocumentSummaryInformation dsi = TestWriteWellKnown.getDocumentSummaryInformation(poifs);
|
||||
|
||||
/* Execute the get... methods. */
|
||||
dsi.getByteCount();
|
||||
dsi.getByteOrder();
|
||||
dsi.getCategory();
|
||||
dsi.getCompany();
|
||||
dsi.getCustomProperties();
|
||||
// FIXME dsi.getDocparts();
|
||||
// FIXME dsi.getHeadingPair();
|
||||
dsi.getHiddenCount();
|
||||
dsi.getLineCount();
|
||||
dsi.getLinksDirty();
|
||||
dsi.getManager();
|
||||
dsi.getMMClipCount();
|
||||
dsi.getNoteCount();
|
||||
dsi.getParCount();
|
||||
dsi.getPresentationFormat();
|
||||
dsi.getScale();
|
||||
dsi.getSlideCount();
|
||||
}
|
||||
} finally {
|
||||
poifs.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the file should be checked, false if it should be excluded.
|
||||
* <p>Tests the simplified custom properties by reading them from the
|
||||
* available test files.</p>
|
||||
*
|
||||
* @param f
|
||||
* @return
|
||||
* @throws Throwable if anything goes wrong.
|
||||
*/
|
||||
public static boolean checkExclude(File f) {
|
||||
for(String exclude : excludes) {
|
||||
if(f.getAbsolutePath().endsWith(exclude)) {
|
||||
return false;
|
||||
@Test
|
||||
public void readCustomPropertiesFromFiles() throws Exception {
|
||||
/* Read a test document <em>doc</em> into a POI filesystem. */
|
||||
NPOIFSFileSystem poifs = new NPOIFSFileSystem(file);
|
||||
try {
|
||||
/*
|
||||
* If there is a document summry information stream, read it from
|
||||
* the POI filesystem, else create a new one.
|
||||
*/
|
||||
DocumentSummaryInformation dsi = TestWriteWellKnown.getDocumentSummaryInformation(poifs);
|
||||
if (dsi == null) {
|
||||
dsi = PropertySetFactory.newDocumentSummaryInformation();
|
||||
}
|
||||
final CustomProperties cps = dsi.getCustomProperties();
|
||||
|
||||
if (cps == null) {
|
||||
/* The document does not have custom properties. */
|
||||
return;
|
||||
}
|
||||
|
||||
for (CustomProperty cp : cps.values()) {
|
||||
cp.getName();
|
||||
cp.getValue();
|
||||
}
|
||||
} finally {
|
||||
poifs.close();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
package org.apache.poi.hpsf.basic;
|
||||
|
||||
import static org.hamcrest.core.IsEqual.equalTo;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
@ -27,7 +28,6 @@ import static org.junit.Assert.fail;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
@ -37,6 +37,7 @@ import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
@ -73,28 +74,29 @@ import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.apache.poi.util.CodePageUtil;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.TempFile;
|
||||
import org.junit.Before;
|
||||
import org.junit.Assume;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* <p>Tests HPSF's writing functionality.</p>
|
||||
* Tests HPSF's writing functionality
|
||||
*/
|
||||
public class TestWrite
|
||||
{
|
||||
public class TestWrite {
|
||||
private static final POIDataSamples _samples = POIDataSamples.getHPSFInstance();
|
||||
private static final int CODEPAGE_DEFAULT = -1;
|
||||
|
||||
static final String POI_FS = "TestHPSFWritingFunctionality.doc";
|
||||
private static final String POI_FS = "TestHPSFWritingFunctionality.doc";
|
||||
|
||||
static final int BYTE_ORDER = 0xfffe;
|
||||
static final int FORMAT = 0x0000;
|
||||
static final int OS_VERSION = 0x00020A04;
|
||||
static final int[] SECTION_COUNT = {1, 2};
|
||||
static final boolean[] IS_SUMMARY_INFORMATION = {true, false};
|
||||
static final boolean[] IS_DOCUMENT_SUMMARY_INFORMATION = {false, true};
|
||||
private static final int BYTE_ORDER = 0xfffe;
|
||||
private static final int FORMAT = 0x0000;
|
||||
private static final int OS_VERSION = 0x00020A04;
|
||||
private static final int[] SECTION_COUNT = {1, 2};
|
||||
private static final boolean[] IS_SUMMARY_INFORMATION = {true, false};
|
||||
private static final boolean[] IS_DOCUMENT_SUMMARY_INFORMATION = {false, true};
|
||||
|
||||
final String IMPROPER_DEFAULT_CHARSET_MESSAGE =
|
||||
private static final String IMPROPER_DEFAULT_CHARSET_MESSAGE =
|
||||
"Your default character set is " + getDefaultCharsetName() +
|
||||
". However, this testcase must be run in an environment " +
|
||||
"with a default character set supporting at least " +
|
||||
@ -104,9 +106,8 @@ public class TestWrite
|
||||
|
||||
POIFile[] poiFiles;
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
@BeforeClass
|
||||
public static void setUp() {
|
||||
VariantSupport.setLogUnsupportedTypes(false);
|
||||
}
|
||||
|
||||
@ -117,8 +118,7 @@ public class TestWrite
|
||||
* @exception IOException if an I/O exception occurs
|
||||
*/
|
||||
@Test(expected=NoFormatIDException.class)
|
||||
public void withoutAFormatID() throws Exception
|
||||
{
|
||||
public void withoutAFormatID() throws Exception {
|
||||
final File filename = TempFile.createTempFile(POI_FS, ".doc");
|
||||
|
||||
/* Create a mutable property set with a section that does not have the
|
||||
@ -144,8 +144,6 @@ public class TestWrite
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Writes an empty property set to a POIFS and reads it back
|
||||
* in.</p>
|
||||
@ -156,8 +154,7 @@ public class TestWrite
|
||||
*/
|
||||
@Test
|
||||
public void writeEmptyPropertySet()
|
||||
throws IOException, UnsupportedVariantTypeException
|
||||
{
|
||||
throws IOException, UnsupportedVariantTypeException {
|
||||
final File dataDir = _samples.getFile("");
|
||||
final File filename = new File(dataDir, POI_FS);
|
||||
filename.deleteOnExit();
|
||||
@ -203,8 +200,7 @@ public class TestWrite
|
||||
*/
|
||||
@Test
|
||||
public void writeSimplePropertySet()
|
||||
throws IOException, UnsupportedVariantTypeException
|
||||
{
|
||||
throws IOException, UnsupportedVariantTypeException {
|
||||
final String AUTHOR = "Rainer Klute";
|
||||
final String TITLE = "Test Document";
|
||||
final File dataDir = _samples.getFile("");
|
||||
@ -235,24 +231,17 @@ public class TestWrite
|
||||
/* Read the POIFS: */
|
||||
final PropertySet[] psa = new PropertySet[1];
|
||||
final POIFSReader r = new POIFSReader();
|
||||
r.registerListener(new POIFSReaderListener()
|
||||
{
|
||||
r.registerListener(new POIFSReaderListener() {
|
||||
@Override
|
||||
public void processPOIFSReaderEvent
|
||||
(final POIFSReaderEvent event)
|
||||
{
|
||||
try
|
||||
{
|
||||
public void processPOIFSReaderEvent(final POIFSReaderEvent event) {
|
||||
try {
|
||||
psa[0] = PropertySetFactory.create(event.getStream());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
} catch (Exception ex) {
|
||||
fail(org.apache.poi.hpsf.Util.toString(ex));
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
SummaryInformation.DEFAULT_STREAM_NAME);
|
||||
}},
|
||||
SummaryInformation.DEFAULT_STREAM_NAME
|
||||
);
|
||||
|
||||
InputStream stream = new FileInputStream(filename);
|
||||
try {
|
||||
@ -281,9 +270,7 @@ public class TestWrite
|
||||
* a variant type to be written
|
||||
*/
|
||||
@Test
|
||||
public void writeTwoSections()
|
||||
throws WritingNotSupportedException, IOException
|
||||
{
|
||||
public void writeTwoSections() throws WritingNotSupportedException, IOException {
|
||||
final String STREAM_NAME = "PropertySetStream";
|
||||
final String SECTION1 = "Section 1";
|
||||
final String SECTION2 = "Section 2";
|
||||
@ -318,18 +305,12 @@ public class TestWrite
|
||||
/* Read the POIFS: */
|
||||
final PropertySet[] psa = new PropertySet[1];
|
||||
final POIFSReader r = new POIFSReader();
|
||||
r.registerListener(new POIFSReaderListener()
|
||||
{
|
||||
r.registerListener(new POIFSReaderListener() {
|
||||
@Override
|
||||
public void processPOIFSReaderEvent
|
||||
(final POIFSReaderEvent event)
|
||||
{
|
||||
try
|
||||
{
|
||||
public void processPOIFSReaderEvent(final POIFSReaderEvent event) {
|
||||
try {
|
||||
psa[0] = PropertySetFactory.create(event.getStream());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
@ -353,17 +334,12 @@ public class TestWrite
|
||||
|
||||
|
||||
|
||||
static class MyPOIFSReaderListener implements POIFSReaderListener
|
||||
{
|
||||
static class MyPOIFSReaderListener implements POIFSReaderListener {
|
||||
@Override
|
||||
public void processPOIFSReaderEvent(final POIFSReaderEvent event)
|
||||
{
|
||||
try
|
||||
{
|
||||
public void processPOIFSReaderEvent(final POIFSReaderEvent event) {
|
||||
try {
|
||||
PropertySetFactory.create(event.getStream());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
} catch (Exception ex) {
|
||||
fail(org.apache.poi.hpsf.Util.toString(ex));
|
||||
}
|
||||
}
|
||||
@ -371,109 +347,52 @@ public class TestWrite
|
||||
|
||||
|
||||
|
||||
private static final int CODEPAGE_DEFAULT = -1;
|
||||
private static final int CODEPAGE_1252 = 1252;
|
||||
private static final int CODEPAGE_UTF8 = CodePageUtil.CP_UTF8;
|
||||
private static final int CODEPAGE_UTF16 = CodePageUtil.CP_UTF16;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Writes and reads back various variant types and checks whether the
|
||||
* stuff that has been read back equals the stuff that was written.</p>
|
||||
* @throws IOException
|
||||
* @throws UnsupportedEncodingException
|
||||
* @throws UnsupportedVariantTypeException
|
||||
* @throws ReadingNotSupportedException
|
||||
*/
|
||||
@Test
|
||||
public void variantTypes()
|
||||
{
|
||||
Throwable t = null;
|
||||
public void variantTypes() throws Exception {
|
||||
final int codepage = CODEPAGE_DEFAULT;
|
||||
if (!hasProperDefaultCharset())
|
||||
{
|
||||
System.err.println(IMPROPER_DEFAULT_CHARSET_MESSAGE +
|
||||
" This testcase is skipped.");
|
||||
return;
|
||||
}
|
||||
Assume.assumeTrue(IMPROPER_DEFAULT_CHARSET_MESSAGE, hasProperDefaultCharset());
|
||||
|
||||
try
|
||||
{
|
||||
check(Variant.VT_EMPTY, null, codepage);
|
||||
check(Variant.VT_BOOL, Boolean.TRUE, codepage);
|
||||
check(Variant.VT_BOOL, Boolean.FALSE, codepage);
|
||||
check( Variant.VT_CF, new byte[] { 8, 0, 0, 0, 1, 0, 0, 0, 1, 2, 3,
|
||||
4 }, codepage );
|
||||
check(Variant.VT_I4, Integer.valueOf(27), codepage);
|
||||
check(Variant.VT_I8, Long.valueOf(28), codepage);
|
||||
check(Variant.VT_R8, new Double(29.0), codepage);
|
||||
check(Variant.VT_I4, Integer.valueOf(-27), codepage);
|
||||
check(Variant.VT_I8, Long.valueOf(-28), codepage);
|
||||
check(Variant.VT_R8, new Double(-29.0), codepage);
|
||||
check( Variant.VT_CF, new byte[] { 8, 0, 0, 0, 1, 0, 0, 0, 1, 2, 3, 4 }, codepage );
|
||||
check(Variant.VT_I4, 27, codepage);
|
||||
check(Variant.VT_I8, 28L, codepage);
|
||||
check(Variant.VT_R8, 29.0d, codepage);
|
||||
check(Variant.VT_I4, -27, codepage);
|
||||
check(Variant.VT_I8, -28L, codepage);
|
||||
check(Variant.VT_R8, -29.0d, codepage);
|
||||
check(Variant.VT_FILETIME, new Date(), codepage);
|
||||
check(Variant.VT_I4, new Integer(Integer.MAX_VALUE), codepage);
|
||||
check(Variant.VT_I4, new Integer(Integer.MIN_VALUE), codepage);
|
||||
check(Variant.VT_I8, new Long(Long.MAX_VALUE), codepage);
|
||||
check(Variant.VT_I8, new Long(Long.MIN_VALUE), codepage);
|
||||
check(Variant.VT_R8, new Double(Double.MAX_VALUE), codepage);
|
||||
check(Variant.VT_R8, new Double(Double.MIN_VALUE), codepage);
|
||||
|
||||
check(Variant.VT_LPSTR,
|
||||
"", codepage);
|
||||
check(Variant.VT_LPSTR,
|
||||
"\u00e4", codepage);
|
||||
check(Variant.VT_LPSTR,
|
||||
"\u00e4\u00f6", codepage);
|
||||
check(Variant.VT_LPSTR,
|
||||
"\u00e4\u00f6\u00fc", codepage);
|
||||
check(Variant.VT_LPSTR,
|
||||
"\u00e4\u00f6\u00fc\u00df", codepage);
|
||||
check(Variant.VT_LPSTR,
|
||||
"\u00e4\u00f6\u00fc\u00df\u00c4", codepage);
|
||||
check(Variant.VT_LPSTR,
|
||||
"\u00e4\u00f6\u00fc\u00df\u00c4\u00d6", codepage);
|
||||
check(Variant.VT_LPSTR,
|
||||
"\u00e4\u00f6\u00fc\u00df\u00c4\u00d6\u00dc", codepage);
|
||||
|
||||
check(Variant.VT_LPWSTR,
|
||||
"", codepage);
|
||||
check(Variant.VT_LPWSTR,
|
||||
"\u00e4", codepage);
|
||||
check(Variant.VT_LPWSTR,
|
||||
"\u00e4\u00f6", codepage);
|
||||
check(Variant.VT_LPWSTR,
|
||||
"\u00e4\u00f6\u00fc", codepage);
|
||||
check(Variant.VT_LPWSTR,
|
||||
"\u00e4\u00f6\u00fc\u00df", codepage);
|
||||
check(Variant.VT_LPWSTR,
|
||||
"\u00e4\u00f6\u00fc\u00df\u00c4", codepage);
|
||||
check(Variant.VT_LPWSTR,
|
||||
"\u00e4\u00f6\u00fc\u00df\u00c4\u00d6", codepage);
|
||||
check(Variant.VT_LPWSTR,
|
||||
"\u00e4\u00f6\u00fc\u00df\u00c4\u00d6\u00dc", codepage);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
t = ex;
|
||||
}
|
||||
catch (Error ex)
|
||||
{
|
||||
t = ex;
|
||||
}
|
||||
if (t != null)
|
||||
fail(org.apache.poi.hpsf.Util.toString(t));
|
||||
check(Variant.VT_I4, Integer.MAX_VALUE, codepage);
|
||||
check(Variant.VT_I4, Integer.MIN_VALUE, codepage);
|
||||
check(Variant.VT_I8, Long.MAX_VALUE, codepage);
|
||||
check(Variant.VT_I8, Long.MIN_VALUE, codepage);
|
||||
check(Variant.VT_R8, Double.MAX_VALUE, codepage);
|
||||
check(Variant.VT_R8, Double.MIN_VALUE, codepage);
|
||||
checkString(Variant.VT_LPSTR, "\u00e4\u00f6\u00fc\u00df\u00c4\u00d6\u00dc", codepage);
|
||||
checkString(Variant.VT_LPWSTR, "\u00e4\u00f6\u00fc\u00df\u00c4\u00d6\u00dc", codepage);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Writes and reads back strings using several different codepages and
|
||||
* Writes and reads back strings using several different codepages and
|
||||
* checks whether the stuff that has been read back equals the stuff that
|
||||
* was written.</p>
|
||||
* was written.
|
||||
*/
|
||||
@Test
|
||||
public void codepages()
|
||||
public void codepages() throws ReadingNotSupportedException, UnsupportedVariantTypeException, IOException
|
||||
{
|
||||
Throwable thr = null;
|
||||
final int[] validCodepages = new int[]
|
||||
{CODEPAGE_DEFAULT, CODEPAGE_UTF8, CODEPAGE_UTF16, CODEPAGE_1252};
|
||||
final int[] validCodepages = {CODEPAGE_DEFAULT, CodePageUtil.CP_UTF8, CodePageUtil.CP_UNICODE, CodePageUtil.CP_WINDOWS_1252};
|
||||
for (final int cp : validCodepages) {
|
||||
if (cp == -1 && !hasProperDefaultCharset())
|
||||
{
|
||||
@ -482,65 +401,22 @@ public class TestWrite
|
||||
continue;
|
||||
}
|
||||
|
||||
final long t = cp == CODEPAGE_UTF16 ? Variant.VT_LPWSTR
|
||||
: Variant.VT_LPSTR;
|
||||
try
|
||||
{
|
||||
check(t, "", cp);
|
||||
check(t, "\u00e4", cp);
|
||||
check(t, "\u00e4\u00f6", cp);
|
||||
check(t, "\u00e4\u00f6\u00fc", cp);
|
||||
check(t, "\u00e4\u00f6\u00fc\u00c4", cp);
|
||||
check(t, "\u00e4\u00f6\u00fc\u00c4\u00d6", cp);
|
||||
check(t, "\u00e4\u00f6\u00fc\u00c4\u00d6\u00dc", cp);
|
||||
check(t, "\u00e4\u00f6\u00fc\u00c4\u00d6\u00dc\u00df", cp);
|
||||
if (cp == CodePageUtil.CP_UTF16 || cp == CodePageUtil.CP_UTF8)
|
||||
final long t = (cp == CodePageUtil.CP_UNICODE) ? Variant.VT_LPWSTR : Variant.VT_LPSTR;
|
||||
checkString(t, "\u00e4\u00f6\u00fc\u00c4\u00d6\u00dc\u00df", cp);
|
||||
if (cp == CodePageUtil.CP_UTF16 || cp == CodePageUtil.CP_UTF8) {
|
||||
check(t, "\u79D1\u5B78", cp);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
thr = ex;
|
||||
}
|
||||
catch (Error ex)
|
||||
{
|
||||
thr = ex;
|
||||
}
|
||||
if (thr != null)
|
||||
fail(org.apache.poi.hpsf.Util.toString(thr) +
|
||||
" with codepage " + cp);
|
||||
}
|
||||
|
||||
final int[] invalidCodepages = new int[] {0, 1, 2, 4711, 815};
|
||||
for (int cp : invalidCodepages) {
|
||||
final long type = cp == CODEPAGE_UTF16 ? Variant.VT_LPWSTR
|
||||
: Variant.VT_LPSTR;
|
||||
try
|
||||
{
|
||||
check(type, "", cp);
|
||||
check(type, "\u00e4", cp);
|
||||
check(type, "\u00e4\u00f6", cp);
|
||||
check(type, "\u00e4\u00f6\u00fc", cp);
|
||||
check(type, "\u00e4\u00f6\u00fc\u00c4", cp);
|
||||
check(type, "\u00e4\u00f6\u00fc\u00c4\u00d6", cp);
|
||||
check(type, "\u00e4\u00f6\u00fc\u00c4\u00d6\u00dc", cp);
|
||||
check(type, "\u00e4\u00f6\u00fc\u00c4\u00d6\u00dc\u00df", cp);
|
||||
fail("UnsupportedEncodingException for codepage " + cp +
|
||||
" expected.");
|
||||
}
|
||||
catch (UnsupportedEncodingException ex)
|
||||
{
|
||||
final long type = (cp == CodePageUtil.CP_UNICODE) ? Variant.VT_LPWSTR : Variant.VT_LPSTR;
|
||||
try {
|
||||
checkString(type, "\u00e4\u00f6\u00fc\u00c4\u00d6\u00dc\u00df", cp);
|
||||
fail("UnsupportedEncodingException for codepage " + cp + " expected.");
|
||||
} catch (UnsupportedEncodingException ex) {
|
||||
/* This is the expected behaviour. */
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
thr = ex;
|
||||
}
|
||||
catch (Error ex)
|
||||
{
|
||||
thr = ex;
|
||||
}
|
||||
if (thr != null)
|
||||
fail(org.apache.poi.hpsf.Util.toString(thr));
|
||||
}
|
||||
|
||||
}
|
||||
@ -548,12 +424,10 @@ public class TestWrite
|
||||
|
||||
|
||||
/**
|
||||
* <p>Tests whether writing 8-bit characters to a Unicode property
|
||||
* succeeds.</p>
|
||||
* Tests whether writing 8-bit characters to a Unicode property succeeds.
|
||||
*/
|
||||
@Test
|
||||
public void unicodeWrite8Bit()
|
||||
{
|
||||
public void unicodeWrite8Bit() throws WritingNotSupportedException, IOException, NoPropertySetStreamException {
|
||||
final String TITLE = "This is a sample title";
|
||||
final MutablePropertySet mps = new MutablePropertySet();
|
||||
final MutableSection ms = (MutableSection) mps.getSections().get(0);
|
||||
@ -564,9 +438,6 @@ public class TestWrite
|
||||
p.setValue(TITLE);
|
||||
ms.setProperty(p);
|
||||
|
||||
Throwable t = null;
|
||||
try
|
||||
{
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
mps.write(out);
|
||||
out.close();
|
||||
@ -578,204 +449,46 @@ public class TestWrite
|
||||
String title = (String) sr.getProperty(PropertyIDMap.PID_TITLE);
|
||||
assertEquals(TITLE, title);
|
||||
}
|
||||
catch (WritingNotSupportedException e)
|
||||
{
|
||||
t = e;
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
t = e;
|
||||
}
|
||||
catch (NoPropertySetStreamException e)
|
||||
{
|
||||
t = e;
|
||||
}
|
||||
if (t != null)
|
||||
fail(t.getMessage());
|
||||
}
|
||||
|
||||
|
||||
private void checkString(final long variantType, final String value, final int codepage)
|
||||
throws UnsupportedVariantTypeException, IOException, ReadingNotSupportedException, UnsupportedEncodingException {
|
||||
for (int i=0; i<value.length(); i++) {
|
||||
check(variantType, value.substring(0, i), codepage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Writes a property and reads it back in.</p>
|
||||
* Writes a property and reads it back in.
|
||||
*
|
||||
* @param variantType The property's variant type.
|
||||
* @param value The property's value.
|
||||
* @param codepage The codepage to use for writing and reading.
|
||||
* @throws UnsupportedVariantTypeException if the variant is not supported.
|
||||
* @throws IOException if an I/O exception occurs.
|
||||
* @throws ReadingNotSupportedException
|
||||
* @throws UnsupportedEncodingException
|
||||
*/
|
||||
private void check(final long variantType, final Object value,
|
||||
final int codepage)
|
||||
throws UnsupportedVariantTypeException, IOException,
|
||||
ReadingNotSupportedException, UnsupportedEncodingException
|
||||
private void check(final long variantType, final Object value, final int codepage)
|
||||
throws UnsupportedVariantTypeException, IOException, ReadingNotSupportedException, UnsupportedEncodingException
|
||||
{
|
||||
final ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
VariantSupport.write(out, variantType, value, codepage);
|
||||
out.close();
|
||||
final byte[] b = out.toByteArray();
|
||||
final Object objRead =
|
||||
VariantSupport.read(b, 0, b.length + LittleEndian.INT_SIZE,
|
||||
variantType, codepage);
|
||||
if (objRead instanceof byte[])
|
||||
{
|
||||
byte[] valueB = (byte[])value;
|
||||
byte[] readB = (byte[])objRead;
|
||||
if (valueB.length != readB.length)
|
||||
fail("Byte arrays are different length - expected " + valueB.length +
|
||||
" but found " + readB.length);
|
||||
|
||||
final int diff = diff(valueB, readB);
|
||||
if (diff >= 0)
|
||||
fail("Byte arrays are different. First different byte is at " +
|
||||
"index " + diff + ".");
|
||||
}
|
||||
else
|
||||
if (value != null && !value.equals(objRead))
|
||||
{
|
||||
fail("Expected: \"" + value + "\" but was: \"" + objRead +
|
||||
"\". Codepage: " + codepage +
|
||||
(codepage == -1 ?
|
||||
" (" + System.getProperty("file.encoding") + ")." : "."));
|
||||
}
|
||||
else
|
||||
VariantSupport.read(b, 0, b.length + LittleEndianConsts.INT_SIZE, variantType, codepage);
|
||||
if (objRead instanceof byte[]) {
|
||||
assertArrayEquals((byte[])value, (byte[])objRead);
|
||||
} else if (value != null && !value.equals(objRead)) {
|
||||
assertEquals(value, objRead);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Compares two byte arrays.</p>
|
||||
*
|
||||
* @param a The first byte array
|
||||
* @param b The second byte array
|
||||
* @return The index of the first byte that is different. If the byte arrays
|
||||
* are equal, -1 is returned.
|
||||
*/
|
||||
private int diff(final byte[] a, final byte[] b)
|
||||
{
|
||||
final int min = Math.min(a.length, b.length);
|
||||
for (int i = 0; i < min; i++)
|
||||
if (a[i] != b[i])
|
||||
return i;
|
||||
if (a.length != b.length)
|
||||
return min;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>This test method does a write and read back test with all POI
|
||||
* filesystems in the "data" directory by performing the following
|
||||
* actions for each file:</p>
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li><p>Read its property set streams.</p></li>
|
||||
*
|
||||
* <li><p>Create a new POI filesystem containing the origin file's
|
||||
* property set streams.</p></li>
|
||||
*
|
||||
* <li><p>Read the property set streams from the POI filesystem just
|
||||
* created.</p></li>
|
||||
*
|
||||
* <li><p>Compare each property set stream with the corresponding one from
|
||||
* the origin file and check whether they are equal.</p></li>
|
||||
*
|
||||
* </ul>
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void recreate() throws IOException
|
||||
{
|
||||
final File dataDir = _samples.getFile("");
|
||||
final File[] fileList = dataDir.listFiles(new FileFilter()
|
||||
{
|
||||
@Override
|
||||
public boolean accept(final File f)
|
||||
{
|
||||
return f.getName().startsWith("Test") && TestReadAllFiles.checkExclude(f);
|
||||
}
|
||||
});
|
||||
for (final File file : fileList) {
|
||||
try {
|
||||
testRecreate(file);
|
||||
} catch (Exception e) {
|
||||
throw new IOException("While handling file " + file, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Performs the check described in {@link #recreate()} for a single
|
||||
* POI filesystem.</p>
|
||||
*
|
||||
* @param f the POI filesystem to check
|
||||
* @throws IOException
|
||||
* @throws HPSFException
|
||||
*/
|
||||
private void testRecreate(final File f) throws IOException, HPSFException
|
||||
{
|
||||
/* Read the POI filesystem's property set streams: */
|
||||
final POIFile[] psf1 = Util.readPropertySets(f);
|
||||
|
||||
/* Create a new POI filesystem containing the origin file's
|
||||
* property set streams: */
|
||||
final File copy = TempFile.createTempFile(f.getName(), "");
|
||||
copy.deleteOnExit();
|
||||
final OutputStream out = new FileOutputStream(copy);
|
||||
final POIFSFileSystem poiFs = new POIFSFileSystem();
|
||||
for (POIFile file : psf1) {
|
||||
final InputStream in =
|
||||
new ByteArrayInputStream(file.getBytes());
|
||||
final PropertySet psIn = PropertySetFactory.create(in);
|
||||
final MutablePropertySet psOut = new MutablePropertySet(psIn);
|
||||
final ByteArrayOutputStream psStream =
|
||||
new ByteArrayOutputStream();
|
||||
psOut.write(psStream);
|
||||
psStream.close();
|
||||
final byte[] streamData = psStream.toByteArray();
|
||||
poiFs.createDocument(new ByteArrayInputStream(streamData),
|
||||
file.getName());
|
||||
poiFs.writeFilesystem(out);
|
||||
}
|
||||
poiFs.close();
|
||||
out.close();
|
||||
|
||||
|
||||
/* Read the property set streams from the POI filesystem just
|
||||
* created. */
|
||||
final POIFile[] psf2 = Util.readPropertySets(copy);
|
||||
for (int i = 0; i < psf2.length; i++)
|
||||
{
|
||||
final byte[] bytes1 = psf1[i].getBytes();
|
||||
final byte[] bytes2 = psf2[i].getBytes();
|
||||
final InputStream in1 = new ByteArrayInputStream(bytes1);
|
||||
final InputStream in2 = new ByteArrayInputStream(bytes2);
|
||||
final PropertySet ps1 = PropertySetFactory.create(in1);
|
||||
final PropertySet ps2 = PropertySetFactory.create(in2);
|
||||
|
||||
/* Compare the property set stream with the corresponding one
|
||||
* from the origin file and check whether they are equal. */
|
||||
assertEquals("Equality for file " + f.getName(), ps1, ps2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Tests writing and reading back a proper dictionary.</p>
|
||||
* @throws IOException
|
||||
* @throws HPSFException
|
||||
*/
|
||||
@Test
|
||||
public void dictionary() throws IOException, HPSFException
|
||||
{
|
||||
public void dictionary() throws IOException, HPSFException {
|
||||
final File copy = TempFile.createTempFile("Test-HPSF", "ole2");
|
||||
copy.deleteOnExit();
|
||||
|
||||
@ -791,17 +504,16 @@ public class TestWrite
|
||||
s.setDictionary(m);
|
||||
s.setFormatID(SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID[0]);
|
||||
int codepage = CodePageUtil.CP_UNICODE;
|
||||
s.setProperty(PropertyIDMap.PID_CODEPAGE, Variant.VT_I2,
|
||||
Integer.valueOf(codepage));
|
||||
s.setProperty(PropertyIDMap.PID_CODEPAGE, Variant.VT_I2, codepage);
|
||||
poiFs.createDocument(ps1.toInputStream(), "Test");
|
||||
poiFs.writeFilesystem(out);
|
||||
poiFs.close();
|
||||
out.close();
|
||||
|
||||
/* Read back: */
|
||||
final POIFile[] psf = Util.readPropertySets(copy);
|
||||
assertEquals(1, psf.length);
|
||||
final byte[] bytes = psf[0].getBytes();
|
||||
final List<POIFile> psf = Util.readPropertySets(copy);
|
||||
assertEquals(1, psf.size());
|
||||
final byte[] bytes = psf.get(0).getBytes();
|
||||
final InputStream in = new ByteArrayInputStream(bytes);
|
||||
final PropertySet ps2 = PropertySetFactory.create(in);
|
||||
|
||||
@ -1039,8 +751,7 @@ public class TestWrite
|
||||
* @throws HPSFException
|
||||
*/
|
||||
@Test(expected=IllegalPropertySetDataException.class)
|
||||
public void dictionaryWithInvalidCodepage() throws IOException, HPSFException
|
||||
{
|
||||
public void dictionaryWithInvalidCodepage() throws IOException, HPSFException {
|
||||
final File copy = TempFile.createTempFile("Test-HPSF", "ole2");
|
||||
copy.deleteOnExit();
|
||||
|
||||
@ -1069,22 +780,17 @@ public class TestWrite
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the display name of the default character set.</p>
|
||||
*
|
||||
* @return the display name of the default character set.
|
||||
*/
|
||||
private String getDefaultCharsetName()
|
||||
{
|
||||
private static String getDefaultCharsetName() {
|
||||
final String charSetName = System.getProperty("file.encoding");
|
||||
final Charset charSet = Charset.forName(charSetName);
|
||||
return charSet.displayName(Locale.ROOT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>In order to execute tests with characters beyond US-ASCII, this
|
||||
* method checks whether the application is runing in an environment
|
||||
@ -1093,8 +799,7 @@ public class TestWrite
|
||||
* @return <code>true</code> if the default character set is 16-bit-capable,
|
||||
* else <code>false</code>.
|
||||
*/
|
||||
private boolean hasProperDefaultCharset()
|
||||
{
|
||||
private boolean hasProperDefaultCharset() {
|
||||
final String charSetName = System.getProperty("file.encoding");
|
||||
final Charset charSet = Charset.forName(charSetName);
|
||||
return charSet.newEncoder().canEncode('\u00e4');
|
||||
|
@ -24,9 +24,7 @@ import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
@ -51,7 +49,6 @@ import org.apache.poi.hpsf.Variant;
|
||||
import org.apache.poi.hpsf.VariantSupport;
|
||||
import org.apache.poi.hpsf.WritingNotSupportedException;
|
||||
import org.apache.poi.hpsf.wellknown.SectionIDMap;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryEntry;
|
||||
import org.apache.poi.poifs.filesystem.DocumentInputStream;
|
||||
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
@ -73,70 +70,6 @@ public class TestWriteWellKnown {
|
||||
VariantSupport.setLogUnsupportedTypes(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>This test method checks whether DocumentSummary information streams
|
||||
* can be read. This is done by opening all "Test*" files in the 'poifs' directrory
|
||||
* pointed to by the "POI.testdata.path" system property, trying to extract
|
||||
* the document summary information stream in the root directory and calling
|
||||
* its get... methods.</p>
|
||||
*/
|
||||
@Test
|
||||
public void testReadDocumentSummaryInformation()
|
||||
throws FileNotFoundException, IOException,
|
||||
NoPropertySetStreamException, MarkUnsupportedException,
|
||||
UnexpectedPropertySetTypeException
|
||||
{
|
||||
POIDataSamples _samples = POIDataSamples.getHPSFInstance();
|
||||
final File dataDir = _samples.getFile("");
|
||||
final File[] docs = dataDir.listFiles(new FileFilter()
|
||||
{
|
||||
@Override
|
||||
public boolean accept(final File file)
|
||||
{
|
||||
return file.isFile() && file.getName().startsWith("Test") && TestReadAllFiles.checkExclude(file);
|
||||
}
|
||||
});
|
||||
|
||||
for (final File doc : docs) {
|
||||
NPOIFSFileSystem poifs = null;
|
||||
try {
|
||||
/* Read a test document <em>doc</em> into a POI filesystem. */
|
||||
poifs = new NPOIFSFileSystem(doc, true);
|
||||
final DirectoryEntry dir = poifs.getRoot();
|
||||
/*
|
||||
* If there is a document summry information stream, read it from
|
||||
* the POI filesystem.
|
||||
*/
|
||||
if (dir.hasEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME)) {
|
||||
final DocumentSummaryInformation dsi = getDocumentSummaryInformation(poifs);
|
||||
|
||||
/* Execute the get... methods. */
|
||||
dsi.getByteCount();
|
||||
dsi.getByteOrder();
|
||||
dsi.getCategory();
|
||||
dsi.getCompany();
|
||||
dsi.getCustomProperties();
|
||||
// FIXME dsi.getDocparts();
|
||||
// FIXME dsi.getHeadingPair();
|
||||
dsi.getHiddenCount();
|
||||
dsi.getLineCount();
|
||||
dsi.getLinksDirty();
|
||||
dsi.getManager();
|
||||
dsi.getMMClipCount();
|
||||
dsi.getNoteCount();
|
||||
dsi.getParCount();
|
||||
dsi.getPresentationFormat();
|
||||
dsi.getScale();
|
||||
dsi.getSlideCount();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new IOException("While handling file " + doc, e);
|
||||
} finally {
|
||||
if (poifs != null) poifs.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static final String P_APPLICATION_NAME = "ApplicationName";
|
||||
static final String P_AUTHOR = "Author";
|
||||
static final int P_CHAR_COUNT = 4712;
|
||||
@ -483,15 +416,12 @@ public class TestWriteWellKnown {
|
||||
dsi.removeScale();
|
||||
dsi.removeSlideCount();
|
||||
|
||||
/*
|
||||
* <li><p>Write the summary information stream and the document summary
|
||||
* information stream to the POI filesystem. */
|
||||
// Write the summary information stream and the document summary
|
||||
// information stream to the POI filesystem.
|
||||
si.write(poifs.getRoot(), SummaryInformation.DEFAULT_STREAM_NAME);
|
||||
dsi.write(poifs.getRoot(), DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
||||
|
||||
/*
|
||||
* <li><p>Write the POI filesystem to a (temporary) file <em>doc3</em>
|
||||
* and close the latter. */
|
||||
// Write the POI filesystem to a (temporary) file doc3 and close the latter.
|
||||
FileOutputStream out = new FileOutputStream(fileOut);
|
||||
poifs.writeFilesystem(out);
|
||||
out.close();
|
||||
@ -501,9 +431,9 @@ public class TestWriteWellKnown {
|
||||
}
|
||||
|
||||
/*
|
||||
* Open <em>doc3</em> for reading and check summary information
|
||||
* Open {@code doc3} for reading and check summary information
|
||||
* and document summary information. All properties removed before must not
|
||||
* be found in the property streams of <em>doc3</em>.
|
||||
* be found in the property streams of {@code doc3}.
|
||||
*/
|
||||
private static CustomProperties write3rdFile(File fileIn, File fileOut) throws Exception {
|
||||
NPOIFSFileSystem poifs = new NPOIFSFileSystem(fileIn, false);
|
||||
@ -571,7 +501,12 @@ public class TestWriteWellKnown {
|
||||
return si;
|
||||
}
|
||||
|
||||
private static DocumentSummaryInformation getDocumentSummaryInformation(NPOIFSFileSystem poifs) throws Exception {
|
||||
static DocumentSummaryInformation getDocumentSummaryInformation(NPOIFSFileSystem poifs)
|
||||
throws IOException, NoPropertySetStreamException, UnexpectedPropertySetTypeException, MarkUnsupportedException {
|
||||
if (!poifs.getRoot().hasEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
DocumentInputStream dis = poifs.createDocumentInputStream(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
||||
PropertySet ps = new PropertySet(dis);
|
||||
DocumentSummaryInformation dsi = new DocumentSummaryInformation(ps);
|
||||
@ -579,83 +514,8 @@ public class TestWriteWellKnown {
|
||||
return dsi;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Tests the simplified custom properties by reading them from the
|
||||
* available test files.</p>
|
||||
*
|
||||
* @throws Throwable if anything goes wrong.
|
||||
*/
|
||||
@Test
|
||||
public void testReadCustomPropertiesFromFiles() throws Throwable
|
||||
{
|
||||
final AllDataFilesTester.TestTask task = new AllDataFilesTester.TestTask()
|
||||
{
|
||||
@Override
|
||||
public void runTest(final File file) throws FileNotFoundException,
|
||||
IOException, NoPropertySetStreamException,
|
||||
MarkUnsupportedException,
|
||||
UnexpectedPropertySetTypeException
|
||||
{
|
||||
/* Read a test document <em>doc</em> into a POI filesystem. */
|
||||
NPOIFSFileSystem poifs = null;
|
||||
try {
|
||||
poifs = new NPOIFSFileSystem(file);
|
||||
final DirectoryEntry dir = poifs.getRoot();
|
||||
/*
|
||||
* If there is a document summry information stream, read it from
|
||||
* the POI filesystem, else create a new one.
|
||||
*/
|
||||
DocumentSummaryInformation dsi;
|
||||
if (dir.hasEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME)) {
|
||||
final DocumentInputStream dis = poifs.createDocumentInputStream(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
||||
final PropertySet ps = new PropertySet(dis);
|
||||
dsi = new DocumentSummaryInformation(ps);
|
||||
dis.close();
|
||||
} else {
|
||||
dsi = PropertySetFactory.newDocumentSummaryInformation();
|
||||
}
|
||||
final CustomProperties cps = dsi.getCustomProperties();
|
||||
|
||||
if (cps == null)
|
||||
/* The document does not have custom properties. */
|
||||
return;
|
||||
|
||||
for (CustomProperty cp : cps.values()) {
|
||||
cp.getName();
|
||||
cp.getValue();
|
||||
}
|
||||
} finally {
|
||||
if (poifs != null) poifs.close();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
POIDataSamples _samples = POIDataSamples.getHPSFInstance();
|
||||
final File dataDir = _samples.getFile("");
|
||||
final File[] docs = dataDir.listFiles(new FileFilter()
|
||||
{
|
||||
@Override
|
||||
public boolean accept(final File file)
|
||||
{
|
||||
return file.isFile() && file.getName().startsWith("Test") && TestReadAllFiles.checkExclude(file);
|
||||
}
|
||||
});
|
||||
|
||||
for (File doc : docs) {
|
||||
try {
|
||||
task.runTest(doc);
|
||||
} catch (Exception e) {
|
||||
throw new IOException("While handling file " + doc, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Tests basic custom property features.</p>
|
||||
* Tests basic custom property features.
|
||||
*/
|
||||
@Test
|
||||
public void testCustomerProperties()
|
||||
@ -693,8 +553,8 @@ public class TestWriteWellKnown {
|
||||
|
||||
|
||||
/**
|
||||
* <p>Tests reading custom properties from a section including reading
|
||||
* custom properties which are not pure.</p>
|
||||
* Tests reading custom properties from a section including reading
|
||||
* custom properties which are not pure.
|
||||
*/
|
||||
@Test
|
||||
public void testGetCustomerProperties()
|
||||
|
@ -19,13 +19,11 @@
|
||||
package org.apache.poi.hpsf.basic;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
@ -36,6 +34,7 @@ import org.apache.poi.hpsf.PropertySet;
|
||||
import org.apache.poi.poifs.eventfilesystem.POIFSReader;
|
||||
import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
|
||||
import org.apache.poi.poifs.eventfilesystem.POIFSReaderListener;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
|
||||
|
||||
|
||||
@ -44,42 +43,6 @@ import org.apache.poi.poifs.eventfilesystem.POIFSReaderListener;
|
||||
*/
|
||||
final class Util {
|
||||
|
||||
/**
|
||||
* <p>Reads bytes from an input stream and writes them to an
|
||||
* output stream until end of file is encountered.</p>
|
||||
*
|
||||
* @param in the input stream to read from
|
||||
*
|
||||
* @param out the output stream to write to
|
||||
*
|
||||
* @exception IOException if an I/O exception occurs
|
||||
*/
|
||||
public static void copy(final InputStream in, final OutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
final int BUF_SIZE = 1000;
|
||||
byte[] b = new byte[BUF_SIZE];
|
||||
int read;
|
||||
boolean eof = false;
|
||||
while (!eof)
|
||||
{
|
||||
try
|
||||
{
|
||||
read = in.read(b, 0, BUF_SIZE);
|
||||
if (read > 0)
|
||||
out.write(b, 0, read);
|
||||
else
|
||||
eof = true;
|
||||
}
|
||||
catch (EOFException ex)
|
||||
{
|
||||
eof = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>Reads all files from a POI filesystem and returns them as an
|
||||
* array of {@link POIFile} instances. This method loads all files
|
||||
@ -143,7 +106,7 @@ final class Util {
|
||||
final InputStream in = event.getStream();
|
||||
final ByteArrayOutputStream out =
|
||||
new ByteArrayOutputStream();
|
||||
Util.copy(in, out);
|
||||
IOUtils.copy(in, out);
|
||||
out.close();
|
||||
f.setBytes(out.toByteArray());
|
||||
files.add(f);
|
||||
@ -192,34 +155,33 @@ final class Util {
|
||||
*
|
||||
* @exception IOException if an I/O exception occurs
|
||||
*/
|
||||
public static POIFile[] readPropertySets(final File poiFs)
|
||||
throws FileNotFoundException, IOException
|
||||
{
|
||||
public static List<POIFile> readPropertySets(final File poiFs)
|
||||
throws FileNotFoundException, IOException {
|
||||
FileInputStream stream = new FileInputStream(poiFs);
|
||||
try {
|
||||
return readPropertySets(stream);
|
||||
} finally {
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static List<POIFile> readPropertySets(final InputStream poiFs)
|
||||
throws FileNotFoundException, IOException {
|
||||
final List<POIFile> files = new ArrayList<POIFile>(7);
|
||||
final POIFSReader r = new POIFSReader();
|
||||
POIFSReaderListener pfl = new POIFSReaderListener()
|
||||
{
|
||||
POIFSReaderListener pfl = new POIFSReaderListener() {
|
||||
@Override
|
||||
public void processPOIFSReaderEvent(final POIFSReaderEvent event)
|
||||
{
|
||||
try
|
||||
{
|
||||
public void processPOIFSReaderEvent(final POIFSReaderEvent event) {
|
||||
try {
|
||||
final POIFile f = new POIFile();
|
||||
f.setName(event.getName());
|
||||
f.setPath(event.getPath());
|
||||
final InputStream in = event.getStream();
|
||||
if (PropertySet.isPropertySetStream(in))
|
||||
{
|
||||
final ByteArrayOutputStream out =
|
||||
new ByteArrayOutputStream();
|
||||
Util.copy(in, out);
|
||||
out.close();
|
||||
f.setBytes(out.toByteArray());
|
||||
if (PropertySet.isPropertySetStream(in)) {
|
||||
f.setBytes(IOUtils.toByteArray(in));
|
||||
files.add(f);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
@ -229,17 +191,9 @@ final class Util {
|
||||
r.registerListener(pfl);
|
||||
|
||||
/* Read the POI filesystem. */
|
||||
FileInputStream stream = new FileInputStream(poiFs);
|
||||
try {
|
||||
r.read(stream);
|
||||
} finally {
|
||||
stream.close();
|
||||
}
|
||||
r.read(poiFs);
|
||||
|
||||
POIFile[] result = new POIFile[files.size()];
|
||||
for (int i = 0; i < result.length; i++)
|
||||
result[i] = files.get(i);
|
||||
return result;
|
||||
return files;
|
||||
}
|
||||
|
||||
|
||||
|
BIN
test-data/hpsf/TestInvertedClassID.doc
Normal file
BIN
test-data/hpsf/TestInvertedClassID.doc
Normal file
Binary file not shown.
BIN
test-data/hpsf/TestVisio43688.vsd
Normal file
BIN
test-data/hpsf/TestVisio43688.vsd
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user