#52117 - Invalid "last printed" summary field value - added helper method to identify undefined dates
HPSF: fixed uid listing in Section.toString() HPSF: moved timestamp based "utility" methods to Filetime class HPSF: preserve original datastream for unchanged property sets git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1795123 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
c45c64ae3a
commit
90dca20bd2
@ -36,7 +36,6 @@ import org.apache.poi.hpsf.MutablePropertySet;
|
|||||||
import org.apache.poi.hpsf.NoPropertySetStreamException;
|
import org.apache.poi.hpsf.NoPropertySetStreamException;
|
||||||
import org.apache.poi.hpsf.PropertySet;
|
import org.apache.poi.hpsf.PropertySet;
|
||||||
import org.apache.poi.hpsf.PropertySetFactory;
|
import org.apache.poi.hpsf.PropertySetFactory;
|
||||||
import org.apache.poi.hpsf.Util;
|
|
||||||
import org.apache.poi.hpsf.WritingNotSupportedException;
|
import org.apache.poi.hpsf.WritingNotSupportedException;
|
||||||
import org.apache.poi.poifs.eventfilesystem.POIFSReader;
|
import org.apache.poi.poifs.eventfilesystem.POIFSReader;
|
||||||
import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
|
import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
|
||||||
@ -352,13 +351,11 @@ public class CopyCompare
|
|||||||
|
|
||||||
/* According to the definition of the processPOIFSReaderEvent method
|
/* According to the definition of the processPOIFSReaderEvent method
|
||||||
* we cannot pass checked exceptions to the caller. The following
|
* we cannot pass checked exceptions to the caller. The following
|
||||||
* lines check whether a checked exception occured and throws an
|
* lines check whether a checked exception occurred and throws an
|
||||||
* unchecked exception. The message of that exception is that of
|
* unchecked exception. The message of that exception is that of
|
||||||
* the underlying checked exception. */
|
* the underlying checked exception. */
|
||||||
if (t != null) {
|
if (t != null) {
|
||||||
throw new HPSFRuntimeException
|
throw new HPSFRuntimeException("Could not read file \"" + path + "/" + name, t);
|
||||||
("Could not read file \"" + path + "/" + name +
|
|
||||||
"\". Reason: " + Util.toString(t));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,6 @@ import org.apache.poi.hpsf.NoPropertySetStreamException;
|
|||||||
import org.apache.poi.hpsf.PropertySet;
|
import org.apache.poi.hpsf.PropertySet;
|
||||||
import org.apache.poi.hpsf.PropertySetFactory;
|
import org.apache.poi.hpsf.PropertySetFactory;
|
||||||
import org.apache.poi.hpsf.SummaryInformation;
|
import org.apache.poi.hpsf.SummaryInformation;
|
||||||
import org.apache.poi.hpsf.Util;
|
|
||||||
import org.apache.poi.hpsf.Variant;
|
import org.apache.poi.hpsf.Variant;
|
||||||
import org.apache.poi.hpsf.WritingNotSupportedException;
|
import org.apache.poi.hpsf.WritingNotSupportedException;
|
||||||
import org.apache.poi.hpsf.wellknown.PropertyIDMap;
|
import org.apache.poi.hpsf.wellknown.PropertyIDMap;
|
||||||
@ -211,9 +210,7 @@ public class WriteAuthorAndTitle
|
|||||||
* unchecked exception. The message of that exception is that of
|
* unchecked exception. The message of that exception is that of
|
||||||
* the underlying checked exception. */
|
* the underlying checked exception. */
|
||||||
if (t != null) {
|
if (t != null) {
|
||||||
throw new HPSFRuntimeException
|
throw new HPSFRuntimeException("Could not read file \"" + path + "/" + name, t);
|
||||||
("Could not read file \"" + path + "/" + name +
|
|
||||||
"\". Reason: " + Util.toString(t));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,24 +18,40 @@ package org.apache.poi.hpsf;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
import org.apache.poi.util.LittleEndian;
|
import org.apache.poi.util.LittleEndian;
|
||||||
import org.apache.poi.util.LittleEndianByteArrayInputStream;
|
import org.apache.poi.util.LittleEndianByteArrayInputStream;
|
||||||
import org.apache.poi.util.LittleEndianConsts;
|
import org.apache.poi.util.LittleEndianConsts;
|
||||||
|
|
||||||
class Filetime {
|
public class Filetime {
|
||||||
private static final int SIZE = LittleEndian.INT_SIZE * 2;
|
/**
|
||||||
|
* The difference between the Windows epoch (1601-01-01
|
||||||
|
* 00:00:00) and the Unix epoch (1970-01-01 00:00:00) in
|
||||||
|
* milliseconds.
|
||||||
|
*/
|
||||||
|
private static final long EPOCH_DIFF = -11644473600000L;
|
||||||
|
|
||||||
|
private static final int SIZE = LittleEndian.INT_SIZE * 2;
|
||||||
|
private static final long UINT_MASK = 0x00000000FFFFFFFFL;
|
||||||
|
private static final long NANO_100 = 1000L * 10L;
|
||||||
|
|
||||||
private int _dwHighDateTime;
|
private int _dwHighDateTime;
|
||||||
private int _dwLowDateTime;
|
private int _dwLowDateTime;
|
||||||
|
|
||||||
Filetime() {}
|
|
||||||
|
|
||||||
|
Filetime() {}
|
||||||
|
|
||||||
Filetime( int low, int high ) {
|
Filetime( int low, int high ) {
|
||||||
_dwLowDateTime = low;
|
_dwLowDateTime = low;
|
||||||
_dwHighDateTime = high;
|
_dwHighDateTime = high;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Filetime( Date date ) {
|
||||||
|
long filetime = Filetime.dateToFileTime(date);
|
||||||
|
_dwHighDateTime = (int) ((filetime >>> 32) & UINT_MASK);
|
||||||
|
_dwLowDateTime = (int) (filetime & UINT_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void read( LittleEndianByteArrayInputStream lei ) {
|
void read( LittleEndianByteArrayInputStream lei ) {
|
||||||
_dwLowDateTime = lei.readInt();
|
_dwLowDateTime = lei.readInt();
|
||||||
@ -53,8 +69,7 @@ class Filetime {
|
|||||||
byte[] toByteArray() {
|
byte[] toByteArray() {
|
||||||
byte[] result = new byte[SIZE];
|
byte[] result = new byte[SIZE];
|
||||||
LittleEndian.putInt( result, 0 * LittleEndianConsts.INT_SIZE, _dwLowDateTime );
|
LittleEndian.putInt( result, 0 * LittleEndianConsts.INT_SIZE, _dwLowDateTime );
|
||||||
LittleEndian
|
LittleEndian.putInt( result, 1 * LittleEndianConsts.INT_SIZE, _dwHighDateTime );
|
||||||
.putInt( result, 1 * LittleEndianConsts.INT_SIZE, _dwHighDateTime );
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,4 +78,49 @@ class Filetime {
|
|||||||
LittleEndian.putInt( _dwHighDateTime, out );
|
LittleEndian.putInt( _dwHighDateTime, out );
|
||||||
return SIZE;
|
return SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Date getJavaValue() {
|
||||||
|
long l = (((long)_dwHighDateTime) << 32) | (_dwLowDateTime & UINT_MASK);
|
||||||
|
return filetimeToDate( l );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a Windows FILETIME into a {@link Date}. The Windows
|
||||||
|
* FILETIME structure holds a date and time associated with a
|
||||||
|
* file. The structure identifies a 64-bit integer specifying the
|
||||||
|
* number of 100-nanosecond intervals which have passed since
|
||||||
|
* January 1, 1601.
|
||||||
|
*
|
||||||
|
* @param filetime The filetime to convert.
|
||||||
|
* @return The Windows FILETIME as a {@link Date}.
|
||||||
|
*/
|
||||||
|
public static Date filetimeToDate(final long filetime) {
|
||||||
|
final long ms_since_16010101 = filetime / NANO_100;
|
||||||
|
final long ms_since_19700101 = ms_since_16010101 + EPOCH_DIFF;
|
||||||
|
return new Date(ms_since_19700101);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a {@link Date} into a filetime.
|
||||||
|
*
|
||||||
|
* @param date The date to be converted
|
||||||
|
* @return The filetime
|
||||||
|
*
|
||||||
|
* @see #filetimeToDate(long)
|
||||||
|
*/
|
||||||
|
public static long dateToFileTime(final Date date) {
|
||||||
|
long ms_since_19700101 = date.getTime();
|
||||||
|
long ms_since_16010101 = ms_since_19700101 - EPOCH_DIFF;
|
||||||
|
return ms_since_16010101 * NANO_100;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return {@code true} if the date is undefined
|
||||||
|
*
|
||||||
|
* @param date the date
|
||||||
|
* @return {@code true} if the date is undefined
|
||||||
|
*/
|
||||||
|
public static boolean isUndefined(Date date) {
|
||||||
|
return (date == null || dateToFileTime(date) == 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,11 @@ import java.io.IOException;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.Arrays;
|
import java.util.Calendar;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import javax.xml.bind.DatatypeConverter;
|
||||||
|
|
||||||
import org.apache.poi.hpsf.wellknown.PropertyIDMap;
|
import org.apache.poi.hpsf.wellknown.PropertyIDMap;
|
||||||
import org.apache.poi.util.CodePageUtil;
|
import org.apache.poi.util.CodePageUtil;
|
||||||
@ -377,15 +381,18 @@ public class Property {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return toString(Property.DEFAULT_CODEPAGE);
|
return toString(Property.DEFAULT_CODEPAGE, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString(int codepage) {
|
public String toString(int codepage, PropertyIDMap idMap) {
|
||||||
final StringBuffer b = new StringBuffer();
|
final StringBuilder b = new StringBuilder();
|
||||||
b.append("Property[");
|
b.append("Property[");
|
||||||
b.append("id: ");
|
b.append("id: ");
|
||||||
b.append(getID());
|
b.append(id);
|
||||||
String idName = getNameFromID();
|
String idName = (idMap == null) ? null : idMap.get(id);
|
||||||
|
if (idName == null) {
|
||||||
|
idName = PropertyIDMap.getFallbackProperties().get(id);
|
||||||
|
}
|
||||||
if (idName != null) {
|
if (idName != null) {
|
||||||
b.append(" (");
|
b.append(" (");
|
||||||
b.append(idName);
|
b.append(idName);
|
||||||
@ -399,6 +406,7 @@ public class Property {
|
|||||||
final Object value = getValue();
|
final Object value = getValue();
|
||||||
b.append(", value: ");
|
b.append(", value: ");
|
||||||
if (value instanceof String) {
|
if (value instanceof String) {
|
||||||
|
b.append((String)value);
|
||||||
b.append("\n");
|
b.append("\n");
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
try {
|
try {
|
||||||
@ -407,13 +415,11 @@ public class Property {
|
|||||||
LOG.log(POILogger.WARN, "can't serialize string", e);
|
LOG.log(POILogger.WARN, "can't serialize string", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
b.append(" [");
|
|
||||||
// skip length field
|
// skip length field
|
||||||
if(bos.size() > 2*LittleEndianConsts.INT_SIZE) {
|
if(bos.size() > 2*LittleEndianConsts.INT_SIZE) {
|
||||||
final String hex = HexDump.dump(bos.toByteArray(), -2*LittleEndianConsts.INT_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(hex);
|
||||||
}
|
}
|
||||||
b.append("]");
|
|
||||||
} else if (value instanceof byte[]) {
|
} else if (value instanceof byte[]) {
|
||||||
b.append("\n");
|
b.append("\n");
|
||||||
byte[] bytes = (byte[])value;
|
byte[] bytes = (byte[])value;
|
||||||
@ -421,7 +427,32 @@ public class Property {
|
|||||||
String hex = HexDump.dump(bytes, 0L, 0);
|
String hex = HexDump.dump(bytes, 0L, 0);
|
||||||
b.append(hex);
|
b.append(hex);
|
||||||
}
|
}
|
||||||
} else if (type == Variant.VT_EMPTY || type == Variant.VT_NULL) {
|
} else if (value instanceof java.util.Date) {
|
||||||
|
java.util.Date d = (java.util.Date)value;
|
||||||
|
long filetime = Filetime.dateToFileTime(d);
|
||||||
|
if (Filetime.isUndefined(d)) {
|
||||||
|
b.append("<undefined>");
|
||||||
|
} else if ((filetime >>> 32) == 0) {
|
||||||
|
// if the upper dword isn't set, we deal with time intervals
|
||||||
|
long l = filetime*100;
|
||||||
|
TimeUnit tu = TimeUnit.NANOSECONDS;
|
||||||
|
final long hr = tu.toHours(l);
|
||||||
|
l -= TimeUnit.HOURS.toNanos(hr);
|
||||||
|
final long min = tu.toMinutes(l);
|
||||||
|
l -= TimeUnit.MINUTES.toNanos(min);
|
||||||
|
final long sec = tu.toSeconds(l);
|
||||||
|
l -= TimeUnit.SECONDS.toNanos(sec);
|
||||||
|
final long ms = tu.toMillis(l);
|
||||||
|
|
||||||
|
String str = String.format(Locale.ROOT, "%02d:%02d:%02d.%03d",hr,min,sec,ms);
|
||||||
|
b.append(str);
|
||||||
|
} else {
|
||||||
|
Calendar cal = Calendar.getInstance(LocaleUtil.TIMEZONE_UTC, Locale.ROOT);
|
||||||
|
cal.setTime(d);
|
||||||
|
// use ISO-8601 timestamp format
|
||||||
|
b.append(DatatypeConverter.printDateTime(cal));
|
||||||
|
}
|
||||||
|
} else if (type == Variant.VT_EMPTY || type == Variant.VT_NULL || value == null) {
|
||||||
b.append("null");
|
b.append("null");
|
||||||
} else {
|
} else {
|
||||||
b.append(value.toString());
|
b.append(value.toString());
|
||||||
@ -458,45 +489,6 @@ public class Property {
|
|||||||
return null;
|
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.
|
* Writes the property to an output stream.
|
||||||
*
|
*
|
||||||
|
@ -871,7 +871,7 @@ public class PropertySet {
|
|||||||
b.append(sectionCount);
|
b.append(sectionCount);
|
||||||
b.append(", sections: [\n");
|
b.append(", sections: [\n");
|
||||||
for (Section section: getSections()) {
|
for (Section section: getSections()) {
|
||||||
b.append(section);
|
b.append(section.toString(getPropertySetIDMap()));
|
||||||
}
|
}
|
||||||
b.append(']');
|
b.append(']');
|
||||||
b.append(']');
|
b.append(']');
|
||||||
|
@ -55,29 +55,19 @@ public class Section {
|
|||||||
* The section's format ID, {@link #getFormatID}.
|
* The section's format ID, {@link #getFormatID}.
|
||||||
*/
|
*/
|
||||||
private ClassID formatID;
|
private ClassID formatID;
|
||||||
/**
|
|
||||||
* If the "dirty" flag is true, the section's size must be
|
|
||||||
* (re-)calculated before the section is written.
|
|
||||||
*/
|
|
||||||
private boolean dirty = true;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains the bytes making out the section. This byte array is
|
* Contains the bytes making out the section. This byte array is
|
||||||
* established when the section's size is calculated and can be reused
|
* established when the section's size is calculated and can be reused
|
||||||
* later. It is valid only if the "dirty" flag is false.
|
* later. If the array is empty, the section was modified and the bytes need to be regenerated.
|
||||||
*/
|
*/
|
||||||
private byte[] sectionBytes;
|
private final ByteArrayOutputStream sectionBytes = new ByteArrayOutputStream();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The offset of the section in the stream.
|
* The offset of the section in the stream.
|
||||||
*/
|
*/
|
||||||
private final long _offset;
|
private final long _offset;
|
||||||
|
|
||||||
/**
|
|
||||||
* The section's size in bytes.
|
|
||||||
*/
|
|
||||||
private int size;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This section's properties.
|
* This section's properties.
|
||||||
*/
|
*/
|
||||||
@ -126,7 +116,6 @@ public class Section {
|
|||||||
* @exception UnsupportedEncodingException if the section's codepage is not
|
* @exception UnsupportedEncodingException if the section's codepage is not
|
||||||
* supported.
|
* supported.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public Section(final byte[] src, final int offset) throws UnsupportedEncodingException {
|
public Section(final byte[] src, final int offset) throws UnsupportedEncodingException {
|
||||||
/*
|
/*
|
||||||
* Read the format ID.
|
* Read the format ID.
|
||||||
@ -154,7 +143,7 @@ public class Section {
|
|||||||
/*
|
/*
|
||||||
* Read the section length.
|
* Read the section length.
|
||||||
*/
|
*/
|
||||||
size = (int)leis.readUInt();
|
int size = (int)Math.min(leis.readUInt(), src.length-_offset);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read the number of properties.
|
* Read the number of properties.
|
||||||
@ -213,6 +202,7 @@ public class Section {
|
|||||||
|
|
||||||
/* Read the codepage number. */
|
/* Read the codepage number. */
|
||||||
codepage = leis.readUShort();
|
codepage = leis.readUShort();
|
||||||
|
setCodepage(codepage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -222,6 +212,10 @@ public class Section {
|
|||||||
long off = me.getKey();
|
long off = me.getKey();
|
||||||
long id = me.getValue();
|
long id = me.getValue();
|
||||||
|
|
||||||
|
if (id == PropertyIDMap.PID_CODEPAGE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
int pLen = propLen(offset2Id, off, size);
|
int pLen = propLen(offset2Id, off, size);
|
||||||
leis.setReadIndex((int)(this._offset + off));
|
leis.setReadIndex((int)(this._offset + off));
|
||||||
|
|
||||||
@ -239,12 +233,13 @@ public class Section {
|
|||||||
LOG.log(POILogger.INFO, "Dictionary fallback failed - ignoring property");
|
LOG.log(POILogger.INFO, "Dictionary fallback failed - ignoring property");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else if (id == PropertyIDMap.PID_CODEPAGE) {
|
|
||||||
setCodepage(codepage);
|
|
||||||
} else {
|
} else {
|
||||||
setProperty(new MutableProperty(id, leis, pLen, codepage));
|
setProperty(new MutableProperty(id, leis, pLen, codepage));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sectionBytes.write(src, (int)_offset, size);
|
||||||
|
padSectionBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -338,9 +333,8 @@ public class Section {
|
|||||||
public void setProperties(final Property[] properties) {
|
public void setProperties(final Property[] properties) {
|
||||||
this.properties.clear();
|
this.properties.clear();
|
||||||
for (Property p : properties) {
|
for (Property p : properties) {
|
||||||
this.properties.put(p.getID(), p);
|
setProperty(p);
|
||||||
}
|
}
|
||||||
dirty = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -448,7 +442,7 @@ public class Section {
|
|||||||
Property old = properties.get(p.getID());
|
Property old = properties.get(p.getID());
|
||||||
if (old == null || !old.equals(p)) {
|
if (old == null || !old.equals(p)) {
|
||||||
properties.put(p.getID(), p);
|
properties.put(p.getID(), p);
|
||||||
dirty = true;
|
sectionBytes.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -543,17 +537,17 @@ public class Section {
|
|||||||
* @return the section's size in bytes.
|
* @return the section's size in bytes.
|
||||||
*/
|
*/
|
||||||
public int getSize() {
|
public int getSize() {
|
||||||
if (dirty) {
|
int size = sectionBytes.size();
|
||||||
try {
|
if (size > 0) {
|
||||||
size = calcSize();
|
return size;
|
||||||
dirty = false;
|
}
|
||||||
} catch (HPSFRuntimeException ex) {
|
try {
|
||||||
throw ex;
|
return calcSize();
|
||||||
} catch (Exception ex) {
|
} catch (HPSFRuntimeException ex) {
|
||||||
throw new HPSFRuntimeException(ex);
|
throw ex;
|
||||||
}
|
} catch (Exception ex) {
|
||||||
|
throw new HPSFRuntimeException(ex);
|
||||||
}
|
}
|
||||||
return size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -566,16 +560,19 @@ public class Section {
|
|||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
private int calcSize() throws WritingNotSupportedException, IOException {
|
private int calcSize() throws WritingNotSupportedException, IOException {
|
||||||
final ByteArrayOutputStream out = new ByteArrayOutputStream();
|
sectionBytes.reset();
|
||||||
write(out);
|
write(sectionBytes);
|
||||||
out.close();
|
padSectionBytes();
|
||||||
/* Pad to multiple of 4 bytes so that even the Windows shell (explorer)
|
return sectionBytes.size();
|
||||||
* shows custom properties. */
|
|
||||||
sectionBytes = Util.pad4(out.toByteArray());
|
|
||||||
return sectionBytes.length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void padSectionBytes() {
|
||||||
|
byte[] padArray = { 0, 0, 0 };
|
||||||
|
/* Pad to multiple of 4 bytes so that even the Windows shell (explorer)
|
||||||
|
* shows custom properties. */
|
||||||
|
int pad = (4 - (sectionBytes.size() & 0x3)) & 0x3;
|
||||||
|
sectionBytes.write(padArray, 0, pad);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -623,12 +620,8 @@ public class Section {
|
|||||||
* Removes all properties from the section including 0 (dictionary) and
|
* Removes all properties from the section including 0 (dictionary) and
|
||||||
* 1 (codepage).
|
* 1 (codepage).
|
||||||
*/
|
*/
|
||||||
public void clear()
|
public void clear() {
|
||||||
{
|
for (Property p : getProperties()) {
|
||||||
final Property[] properties = getProperties();
|
|
||||||
for (int i = 0; i < properties.length; i++)
|
|
||||||
{
|
|
||||||
final Property p = properties[i];
|
|
||||||
removeProperty(p.getID());
|
removeProperty(p.getID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -639,17 +632,17 @@ public class Section {
|
|||||||
*
|
*
|
||||||
* <ul>
|
* <ul>
|
||||||
*
|
*
|
||||||
* <li>The other object is not a {@link Section}.</li>
|
* <li>The other object is not a {@link Section}.
|
||||||
*
|
*
|
||||||
* <li>The format IDs of the two sections are not equal.</li>
|
* <li>The format IDs of the two sections are not equal.
|
||||||
*
|
*
|
||||||
* <li>The sections have a different number of properties. However,
|
* <li>The sections have a different number of properties. However,
|
||||||
* properties with ID 1 (codepage) are not counted.</li>
|
* properties with ID 1 (codepage) are not counted.
|
||||||
*
|
*
|
||||||
* <li>The other object is not a {@link Section}.</li>
|
* <li>The other object is not a {@link Section}.
|
||||||
*
|
*
|
||||||
* <li>The properties have different values. The order of the properties
|
* <li>The properties have different values. The order of the properties
|
||||||
* is irrelevant.</li>
|
* is irrelevant.
|
||||||
*
|
*
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
@ -695,7 +688,9 @@ public class Section {
|
|||||||
* @param id The ID of the property to be removed
|
* @param id The ID of the property to be removed
|
||||||
*/
|
*/
|
||||||
public void removeProperty(final long id) {
|
public void removeProperty(final long id) {
|
||||||
dirty |= (properties.remove(id) != null);
|
if (properties.remove(id) != null) {
|
||||||
|
sectionBytes.reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -716,9 +711,9 @@ public class Section {
|
|||||||
public int write(final OutputStream out) throws WritingNotSupportedException, IOException {
|
public int write(final OutputStream out) throws WritingNotSupportedException, IOException {
|
||||||
/* Check whether we have already generated the bytes making out the
|
/* Check whether we have already generated the bytes making out the
|
||||||
* section. */
|
* section. */
|
||||||
if (!dirty && sectionBytes != null) {
|
if (sectionBytes.size() > 0) {
|
||||||
out.write(sectionBytes);
|
sectionBytes.writeTo(out);
|
||||||
return sectionBytes.length;
|
return sectionBytes.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Writing the section's dictionary it tricky. If there is a dictionary
|
/* Writing the section's dictionary it tricky. If there is a dictionary
|
||||||
@ -971,6 +966,10 @@ public class Section {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
return toString(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString(PropertyIDMap idMap) {
|
||||||
final StringBuffer b = new StringBuffer();
|
final StringBuffer b = new StringBuffer();
|
||||||
final Property[] pa = getProperties();
|
final Property[] pa = getProperties();
|
||||||
b.append("\n\n\n");
|
b.append("\n\n\n");
|
||||||
@ -990,7 +989,7 @@ public class Section {
|
|||||||
codepage = Property.DEFAULT_CODEPAGE;
|
codepage = Property.DEFAULT_CODEPAGE;
|
||||||
}
|
}
|
||||||
for (Property p : pa) {
|
for (Property p : pa) {
|
||||||
b.append(p.toString(codepage));
|
b.append(p.toString(codepage, idMap));
|
||||||
b.append(",\n");
|
b.append(",\n");
|
||||||
}
|
}
|
||||||
b.append(']');
|
b.append(']');
|
||||||
|
@ -351,7 +351,7 @@ public final class SummaryInformation extends SpecialPropertySet {
|
|||||||
if (d == null) {
|
if (d == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return Util.dateToFileTime(d);
|
return Filetime.dateToFileTime(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -362,7 +362,7 @@ public final class SummaryInformation extends SpecialPropertySet {
|
|||||||
* @param time The time to set.
|
* @param time The time to set.
|
||||||
*/
|
*/
|
||||||
public void setEditTime(final long time) {
|
public void setEditTime(final long time) {
|
||||||
final Date d = Util.filetimeToDate(time);
|
final Date d = Filetime.filetimeToDate(time);
|
||||||
getFirstSection().setProperty(PropertyIDMap.PID_EDITTIME, Variant.VT_FILETIME, d);
|
getFirstSection().setProperty(PropertyIDMap.PID_EDITTIME, Variant.VT_FILETIME, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,153 +0,0 @@
|
|||||||
/* ====================================================================
|
|
||||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
contributor license agreements. See the NOTICE file distributed with
|
|
||||||
this work for additional information regarding copyright ownership.
|
|
||||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
|
||||||
(the "License"); you may not use this file except in compliance with
|
|
||||||
the License. You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
==================================================================== */
|
|
||||||
|
|
||||||
package org.apache.poi.hpsf;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import org.apache.poi.util.Internal;
|
|
||||||
import org.apache.poi.util.SuppressForbidden;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Provides various static utility methods.</p>
|
|
||||||
*/
|
|
||||||
@Internal
|
|
||||||
public class Util
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* <p>The difference between the Windows epoch (1601-01-01
|
|
||||||
* 00:00:00) and the Unix epoch (1970-01-01 00:00:00) in
|
|
||||||
* milliseconds: 11644473600000L. (Use your favorite spreadsheet
|
|
||||||
* program to verify the correctness of this value. By the way,
|
|
||||||
* did you notice that you can tell from the epochs which
|
|
||||||
* operating system is the modern one? :-))</p>
|
|
||||||
*/
|
|
||||||
public static final long EPOCH_DIFF = 11644473600000L;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Converts a Windows FILETIME into a {@link Date}. The Windows
|
|
||||||
* FILETIME structure holds a date and time associated with a
|
|
||||||
* file. The structure identifies a 64-bit integer specifying the
|
|
||||||
* number of 100-nanosecond intervals which have passed since
|
|
||||||
* January 1, 1601. This 64-bit value is split into the two double
|
|
||||||
* words stored in the structure.</p>
|
|
||||||
*
|
|
||||||
* @param high The higher double word of the FILETIME structure.
|
|
||||||
* @param low The lower double word of the FILETIME structure.
|
|
||||||
* @return The Windows FILETIME as a {@link Date}.
|
|
||||||
*/
|
|
||||||
public static Date filetimeToDate(final int high, final int low)
|
|
||||||
{
|
|
||||||
final long filetime = ((long) high) << 32 | (low & 0xffffffffL);
|
|
||||||
return filetimeToDate(filetime);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Converts a Windows FILETIME into a {@link Date}. The Windows
|
|
||||||
* FILETIME structure holds a date and time associated with a
|
|
||||||
* file. The structure identifies a 64-bit integer specifying the
|
|
||||||
* number of 100-nanosecond intervals which have passed since
|
|
||||||
* January 1, 1601.</p>
|
|
||||||
*
|
|
||||||
* @param filetime The filetime to convert.
|
|
||||||
* @return The Windows FILETIME as a {@link Date}.
|
|
||||||
*/
|
|
||||||
public static Date filetimeToDate(final long filetime)
|
|
||||||
{
|
|
||||||
final long ms_since_16010101 = filetime / (1000 * 10);
|
|
||||||
final long ms_since_19700101 = ms_since_16010101 - EPOCH_DIFF;
|
|
||||||
return new Date(ms_since_19700101);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Converts a {@link Date} into a filetime.</p>
|
|
||||||
*
|
|
||||||
* @param date The date to be converted
|
|
||||||
* @return The filetime
|
|
||||||
*
|
|
||||||
* @see #filetimeToDate(long)
|
|
||||||
* @see #filetimeToDate(int, int)
|
|
||||||
*/
|
|
||||||
public static long dateToFileTime(final Date date)
|
|
||||||
{
|
|
||||||
long ms_since_19700101 = date.getTime();
|
|
||||||
long ms_since_16010101 = ms_since_19700101 + EPOCH_DIFF;
|
|
||||||
return ms_since_16010101 * (1000 * 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Pads a byte array with 0x00 bytes so that its length is a multiple of
|
|
||||||
* 4.</p>
|
|
||||||
*
|
|
||||||
* @param ba The byte array to pad.
|
|
||||||
* @return The padded byte array.
|
|
||||||
*/
|
|
||||||
public static byte[] pad4(final byte[] ba)
|
|
||||||
{
|
|
||||||
final int PAD = 4;
|
|
||||||
final byte[] result;
|
|
||||||
int l = ba.length % PAD;
|
|
||||||
if (l == 0)
|
|
||||||
result = ba;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
l = PAD - l;
|
|
||||||
result = new byte[ba.length + l];
|
|
||||||
System.arraycopy(ba, 0, result, 0, ba.length);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Returns a textual representation of a {@link Throwable}, including a
|
|
||||||
* stacktrace.</p>
|
|
||||||
*
|
|
||||||
* @param t The {@link Throwable}
|
|
||||||
*
|
|
||||||
* @return a string containing the output of a call to
|
|
||||||
* <code>t.printStacktrace()</code>.
|
|
||||||
*/
|
|
||||||
@SuppressForbidden("uses printStackTrace")
|
|
||||||
public static String toString(final Throwable t)
|
|
||||||
{
|
|
||||||
final StringWriter sw = new StringWriter();
|
|
||||||
final PrintWriter pw = new PrintWriter(sw);
|
|
||||||
t.printStackTrace(pw);
|
|
||||||
pw.close();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
sw.close();
|
|
||||||
return sw.toString();
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
final StringBuffer b = new StringBuffer(t.getMessage());
|
|
||||||
b.append("\n");
|
|
||||||
b.append("Could not create a stacktrace. Reason: ");
|
|
||||||
b.append(e.getMessage());
|
|
||||||
return b.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -207,7 +207,7 @@ public class VariantSupport extends Variant {
|
|||||||
|
|
||||||
case Variant.VT_FILETIME:
|
case Variant.VT_FILETIME:
|
||||||
Filetime filetime = (Filetime) typedPropertyValue.getValue();
|
Filetime filetime = (Filetime) typedPropertyValue.getValue();
|
||||||
return Util.filetimeToDate( (int) filetime.getHigh(), (int) filetime.getLow() );
|
return filetime.getJavaValue();
|
||||||
|
|
||||||
case Variant.VT_LPSTR:
|
case Variant.VT_LPSTR:
|
||||||
CodePageString cpString = (CodePageString) typedPropertyValue.getValue();
|
CodePageString cpString = (CodePageString) typedPropertyValue.getValue();
|
||||||
@ -413,13 +413,8 @@ public class VariantSupport extends Variant {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Variant.VT_FILETIME:
|
case Variant.VT_FILETIME:
|
||||||
if (value instanceof Date) {
|
Filetime filetimeValue = (value instanceof Date) ? new Filetime((Date)value) : new Filetime();
|
||||||
long filetime = Util.dateToFileTime((Date) value);
|
length = filetimeValue.write( out );
|
||||||
int high = (int) ((filetime >> 32) & 0x00000000FFFFFFFFL);
|
|
||||||
int low = (int) (filetime & 0x00000000FFFFFFFFL);
|
|
||||||
Filetime filetimeValue = new Filetime( low, high);
|
|
||||||
length = filetimeValue.write( out );
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -17,9 +17,14 @@
|
|||||||
|
|
||||||
package org.apache.poi.hpsf.wellknown;
|
package org.apache.poi.hpsf.wellknown;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
||||||
|
import org.apache.poi.hpsf.SummaryInformation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a dictionary which maps property ID values to property
|
* This is a dictionary which maps property ID values to property
|
||||||
@ -31,7 +36,7 @@ import java.util.Map;
|
|||||||
* should treat them as unmodifiable, copy them and modifiy the
|
* should treat them as unmodifiable, copy them and modifiy the
|
||||||
* copies.
|
* copies.
|
||||||
*/
|
*/
|
||||||
public class PropertyIDMap extends HashMap<Long,String> {
|
public class PropertyIDMap implements Map<Long,String> {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following definitions are for property IDs in the first
|
* The following definitions are for property IDs in the first
|
||||||
@ -317,6 +322,26 @@ public class PropertyIDMap extends HashMap<Long,String> {
|
|||||||
* details!
|
* details!
|
||||||
*/
|
*/
|
||||||
private static PropertyIDMap summaryInformationProperties;
|
private static PropertyIDMap summaryInformationProperties;
|
||||||
|
private static final Object[][] summaryInformationIdValues = {
|
||||||
|
{ (long)PID_TITLE, "PID_TITLE" },
|
||||||
|
{ (long)PID_SUBJECT, "PID_SUBJECT" },
|
||||||
|
{ (long)PID_AUTHOR, "PID_AUTHOR" },
|
||||||
|
{ (long)PID_KEYWORDS, "PID_KEYWORDS" },
|
||||||
|
{ (long)PID_COMMENTS, "PID_COMMENTS" },
|
||||||
|
{ (long)PID_TEMPLATE, "PID_TEMPLATE" },
|
||||||
|
{ (long)PID_LASTAUTHOR, "PID_LASTAUTHOR" },
|
||||||
|
{ (long)PID_REVNUMBER, "PID_REVNUMBER" },
|
||||||
|
{ (long)PID_EDITTIME, "PID_EDITTIME" },
|
||||||
|
{ (long)PID_LASTPRINTED, "PID_LASTPRINTED" },
|
||||||
|
{ (long)PID_CREATE_DTM, "PID_CREATE_DTM" },
|
||||||
|
{ (long)PID_LASTSAVE_DTM, "PID_LASTSAVE_DTM" },
|
||||||
|
{ (long)PID_PAGECOUNT, "PID_PAGECOUNT" },
|
||||||
|
{ (long)PID_WORDCOUNT, "PID_WORDCOUNT" },
|
||||||
|
{ (long)PID_CHARCOUNT, "PID_CHARCOUNT" },
|
||||||
|
{ (long)PID_THUMBNAIL, "PID_THUMBNAIL" },
|
||||||
|
{ (long)PID_APPNAME, "PID_APPNAME" },
|
||||||
|
{ (long)PID_SECURITY, "PID_SECURITY" },
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains the summary information property ID values and
|
* Contains the summary information property ID values and
|
||||||
@ -324,144 +349,181 @@ public class PropertyIDMap extends HashMap<Long,String> {
|
|||||||
* details!
|
* details!
|
||||||
*/
|
*/
|
||||||
private static PropertyIDMap documentSummaryInformationProperties;
|
private static PropertyIDMap documentSummaryInformationProperties;
|
||||||
|
private static final Object[][] documentSummaryInformationIdValues = {
|
||||||
|
{ (long)PID_DICTIONARY, "PID_DICTIONARY" },
|
||||||
|
{ (long)PID_CODEPAGE, "PID_CODEPAGE" },
|
||||||
|
{ (long)PID_CATEGORY, "PID_CATEGORY" },
|
||||||
|
{ (long)PID_PRESFORMAT, "PID_PRESFORMAT" },
|
||||||
|
{ (long)PID_BYTECOUNT, "PID_BYTECOUNT" },
|
||||||
|
{ (long)PID_LINECOUNT, "PID_LINECOUNT" },
|
||||||
|
{ (long)PID_PARCOUNT, "PID_PARCOUNT" },
|
||||||
|
{ (long)PID_SLIDECOUNT, "PID_SLIDECOUNT" },
|
||||||
|
{ (long)PID_NOTECOUNT, "PID_NOTECOUNT" },
|
||||||
|
{ (long)PID_HIDDENCOUNT, "PID_HIDDENCOUNT" },
|
||||||
|
{ (long)PID_MMCLIPCOUNT, "PID_MMCLIPCOUNT" },
|
||||||
|
{ (long)PID_SCALE, "PID_SCALE" },
|
||||||
|
{ (long)PID_HEADINGPAIR, "PID_HEADINGPAIR" },
|
||||||
|
{ (long)PID_DOCPARTS, "PID_DOCPARTS" },
|
||||||
|
{ (long)PID_MANAGER, "PID_MANAGER" },
|
||||||
|
{ (long)PID_COMPANY, "PID_COMPANY" },
|
||||||
|
{ (long)PID_LINKSDIRTY, "PID_LINKSDIRTY" },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link PropertyIDMap}.
|
* Contains the fallback property ID values and associated strings.
|
||||||
*
|
* This is only used for lookups and not for initializing a property set
|
||||||
* @param initialCapacity The initial capacity as defined for
|
|
||||||
* {@link HashMap}
|
|
||||||
* @param loadFactor The load factor as defined for {@link HashMap}
|
|
||||||
*/
|
*/
|
||||||
public PropertyIDMap(final int initialCapacity, final float loadFactor)
|
private static PropertyIDMap fallbackProperties;
|
||||||
{
|
private static final Object[][] fallbackIdValues = {
|
||||||
super(initialCapacity, loadFactor);
|
{ (long)PID_DICTIONARY, "PID_DICTIONARY" },
|
||||||
}
|
{ (long)PID_CODEPAGE, "PID_CODEPAGE" },
|
||||||
|
{ (long)PID_CATEGORY, "PID_CATEGORY" },
|
||||||
|
{ (long)PID_PRESFORMAT, "PID_PRESFORMAT" },
|
||||||
|
{ (long)PID_BYTECOUNT, "PID_BYTECOUNT" },
|
||||||
|
{ (long)PID_LINECOUNT, "PID_LINECOUNT" },
|
||||||
|
{ (long)PID_PARCOUNT, "PID_PARCOUNT" },
|
||||||
|
{ (long)PID_SLIDECOUNT, "PID_SLIDECOUNT" },
|
||||||
|
{ (long)PID_NOTECOUNT, "PID_NOTECOUNT" },
|
||||||
|
{ (long)PID_HIDDENCOUNT, "PID_HIDDENCOUNT" },
|
||||||
|
{ (long)PID_MMCLIPCOUNT, "PID_MMCLIPCOUNT" },
|
||||||
|
{ (long)PID_SCALE, "PID_SCALE" },
|
||||||
|
{ (long)PID_HEADINGPAIR, "PID_HEADINGPAIR" },
|
||||||
|
{ (long)PID_DOCPARTS, "PID_DOCPARTS" },
|
||||||
|
{ (long)PID_MANAGER, "PID_MANAGER" },
|
||||||
|
{ (long)PID_COMPANY, "PID_COMPANY" },
|
||||||
|
{ (long)PID_LINKSDIRTY, "PID_LINKSDIRTY" },
|
||||||
|
{ (long)PID_CCHWITHSPACES, "PID_CCHWITHSPACES" },
|
||||||
|
// 0x12 Unused
|
||||||
|
// 0x13 GKPIDDSI_SHAREDDOC - Must be False
|
||||||
|
// 0x14 GKPIDDSI_LINKBASE - Must not be written
|
||||||
|
// 0x15 GKPIDDSI_HLINKS - Must not be written
|
||||||
|
{ (long)PID_HYPERLINKSCHANGED, "PID_HYPERLINKSCHANGED" },
|
||||||
|
{ (long)PID_VERSION, "PID_VERSION" },
|
||||||
|
{ (long)PID_DIGSIG, "PID_DIGSIG" },
|
||||||
|
// 0x19 Unused
|
||||||
|
{ (long)PID_CONTENTTYPE, "PID_CONTENTTYPE" },
|
||||||
|
{ (long)PID_CONTENTSTATUS, "PID_CONTENTSTATUS" },
|
||||||
|
{ (long)PID_LANGUAGE, "PID_LANGUAGE" },
|
||||||
|
{ (long)PID_DOCVERSION, "PID_DOCVERSION" },
|
||||||
|
{ (long)PID_MAX, "PID_MAX" },
|
||||||
|
{ (long)PID_LOCALE, "PID_LOCALE" },
|
||||||
|
{ (long)PID_BEHAVIOUR, "PID_BEHAVIOUR" },
|
||||||
|
};
|
||||||
|
|
||||||
|
private final Map<Long,String> idMap;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link PropertyIDMap} backed by another map.
|
* Creates a {@link PropertyIDMap} backed by another map.
|
||||||
*
|
*
|
||||||
* @param map The instance to be created is backed by this map.
|
* @param map The instance to be created is backed by this map.
|
||||||
*/
|
*/
|
||||||
public PropertyIDMap(final Map<Long,String> map)
|
private PropertyIDMap(Object[][] idValues) {
|
||||||
{
|
Map<Long,String> m = new HashMap<Long,String>(idValues.length);
|
||||||
super(map);
|
for (Object[] idValue : idValues) {
|
||||||
|
m.put((Long)idValue[0], (String)idValue[1]);
|
||||||
|
}
|
||||||
|
idMap = Collections.unmodifiableMap(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Puts a ID string for an ID into the {@link
|
|
||||||
* PropertyIDMap}.
|
|
||||||
*
|
|
||||||
* @param id The ID.
|
|
||||||
* @param idString The ID string.
|
|
||||||
* @return As specified by the {@link java.util.Map} interface, this method
|
|
||||||
* returns the previous value associated with the specified
|
|
||||||
* <var>id</var>, or <code>null</code> if there was no mapping for
|
|
||||||
* key.
|
|
||||||
*/
|
|
||||||
public Object put(final long id, final String idString)
|
|
||||||
{
|
|
||||||
return put(Long.valueOf(id), idString);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the ID string for an ID from the {@link
|
|
||||||
* PropertyIDMap}.
|
|
||||||
*
|
|
||||||
* @param id The ID.
|
|
||||||
* @return The ID string associated with <var>id</var>.
|
|
||||||
*/
|
|
||||||
public Object get(final long id)
|
|
||||||
{
|
|
||||||
return get(Long.valueOf(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the Summary Information properties singleton
|
* @return the Summary Information properties singleton
|
||||||
*/
|
*/
|
||||||
public static synchronized PropertyIDMap getSummaryInformationProperties()
|
public static synchronized PropertyIDMap getSummaryInformationProperties() {
|
||||||
{
|
if (summaryInformationProperties == null) {
|
||||||
if (summaryInformationProperties == null)
|
summaryInformationProperties = new PropertyIDMap(summaryInformationIdValues);
|
||||||
{
|
|
||||||
PropertyIDMap m = new PropertyIDMap(18, (float) 1.0);
|
|
||||||
m.put(PID_TITLE, "PID_TITLE");
|
|
||||||
m.put(PID_SUBJECT, "PID_SUBJECT");
|
|
||||||
m.put(PID_AUTHOR, "PID_AUTHOR");
|
|
||||||
m.put(PID_KEYWORDS, "PID_KEYWORDS");
|
|
||||||
m.put(PID_COMMENTS, "PID_COMMENTS");
|
|
||||||
m.put(PID_TEMPLATE, "PID_TEMPLATE");
|
|
||||||
m.put(PID_LASTAUTHOR, "PID_LASTAUTHOR");
|
|
||||||
m.put(PID_REVNUMBER, "PID_REVNUMBER");
|
|
||||||
m.put(PID_EDITTIME, "PID_EDITTIME");
|
|
||||||
m.put(PID_LASTPRINTED, "PID_LASTPRINTED");
|
|
||||||
m.put(PID_CREATE_DTM, "PID_CREATE_DTM");
|
|
||||||
m.put(PID_LASTSAVE_DTM, "PID_LASTSAVE_DTM");
|
|
||||||
m.put(PID_PAGECOUNT, "PID_PAGECOUNT");
|
|
||||||
m.put(PID_WORDCOUNT, "PID_WORDCOUNT");
|
|
||||||
m.put(PID_CHARCOUNT, "PID_CHARCOUNT");
|
|
||||||
m.put(PID_THUMBNAIL, "PID_THUMBNAIL");
|
|
||||||
m.put(PID_APPNAME, "PID_APPNAME");
|
|
||||||
m.put(PID_SECURITY, "PID_SECURITY");
|
|
||||||
summaryInformationProperties =
|
|
||||||
new PropertyIDMap(Collections.unmodifiableMap(m));
|
|
||||||
}
|
}
|
||||||
return summaryInformationProperties;
|
return summaryInformationProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Document Summary Information properties
|
|
||||||
* singleton.
|
|
||||||
*
|
|
||||||
* @return The Document Summary Information properties singleton.
|
* @return The Document Summary Information properties singleton.
|
||||||
*/
|
*/
|
||||||
public static synchronized PropertyIDMap getDocumentSummaryInformationProperties()
|
public static synchronized PropertyIDMap getDocumentSummaryInformationProperties() {
|
||||||
{
|
if (documentSummaryInformationProperties == null) {
|
||||||
if (documentSummaryInformationProperties == null)
|
documentSummaryInformationProperties = new PropertyIDMap(documentSummaryInformationIdValues);
|
||||||
{
|
|
||||||
PropertyIDMap m = new PropertyIDMap(17, (float) 1.0);
|
|
||||||
m.put(PID_DICTIONARY, "PID_DICTIONARY");
|
|
||||||
m.put(PID_CODEPAGE, "PID_CODEPAGE");
|
|
||||||
m.put(PID_CATEGORY, "PID_CATEGORY");
|
|
||||||
m.put(PID_PRESFORMAT, "PID_PRESFORMAT");
|
|
||||||
m.put(PID_BYTECOUNT, "PID_BYTECOUNT");
|
|
||||||
m.put(PID_LINECOUNT, "PID_LINECOUNT");
|
|
||||||
m.put(PID_PARCOUNT, "PID_PARCOUNT");
|
|
||||||
m.put(PID_SLIDECOUNT, "PID_SLIDECOUNT");
|
|
||||||
m.put(PID_NOTECOUNT, "PID_NOTECOUNT");
|
|
||||||
m.put(PID_HIDDENCOUNT, "PID_HIDDENCOUNT");
|
|
||||||
m.put(PID_MMCLIPCOUNT, "PID_MMCLIPCOUNT");
|
|
||||||
m.put(PID_SCALE, "PID_SCALE");
|
|
||||||
m.put(PID_HEADINGPAIR, "PID_HEADINGPAIR");
|
|
||||||
m.put(PID_DOCPARTS, "PID_DOCPARTS");
|
|
||||||
m.put(PID_MANAGER, "PID_MANAGER");
|
|
||||||
m.put(PID_COMPANY, "PID_COMPANY");
|
|
||||||
m.put(PID_LINKSDIRTY, "PID_LINKSDIRTY");
|
|
||||||
documentSummaryInformationProperties =
|
|
||||||
new PropertyIDMap(Collections.unmodifiableMap(m));
|
|
||||||
}
|
}
|
||||||
return documentSummaryInformationProperties;
|
return documentSummaryInformationProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a property map, which is only used as a fallback, i.e. if available, the correct map
|
||||||
|
* for {@link DocumentSummaryInformation} or {@link SummaryInformation} should be used.
|
||||||
|
*/
|
||||||
|
public static synchronized PropertyIDMap getFallbackProperties() {
|
||||||
|
if (fallbackProperties == null) {
|
||||||
|
fallbackProperties = new PropertyIDMap(fallbackIdValues);
|
||||||
|
}
|
||||||
|
return fallbackProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return idMap.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return idMap.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsKey(Object key) {
|
||||||
|
return idMap.containsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsValue(Object value) {
|
||||||
|
return idMap.containsValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String get(Object key) {
|
||||||
|
return idMap.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String put(Long key, String value) {
|
||||||
|
return idMap.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String remove(Object key) {
|
||||||
|
return idMap.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putAll(Map<? extends Long, ? extends String> m) {
|
||||||
|
idMap.putAll(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
idMap.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Long> keySet() {
|
||||||
|
return idMap.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<String> values() {
|
||||||
|
return idMap.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Entry<Long, String>> entrySet() {
|
||||||
|
return idMap.entrySet();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For the most basic testing.
|
* For the most basic testing.
|
||||||
*
|
*
|
||||||
* @param args The command-line arguments
|
* @param args The command-line arguments
|
||||||
*/
|
*/
|
||||||
public static void main(final String[] args)
|
public static void main(final String[] args) {
|
||||||
{
|
|
||||||
PropertyIDMap s1 = getSummaryInformationProperties();
|
PropertyIDMap s1 = getSummaryInformationProperties();
|
||||||
PropertyIDMap s2 = getDocumentSummaryInformationProperties();
|
PropertyIDMap s2 = getDocumentSummaryInformationProperties();
|
||||||
System.out.println("s1: " + s1);
|
System.out.println("s1: " + s1);
|
||||||
|
@ -25,7 +25,7 @@ import java.util.Locale;
|
|||||||
|
|
||||||
import org.apache.poi.hmef.Attachment;
|
import org.apache.poi.hmef.Attachment;
|
||||||
import org.apache.poi.hmef.HMEFMessage;
|
import org.apache.poi.hmef.HMEFMessage;
|
||||||
import org.apache.poi.hpsf.Util;
|
import org.apache.poi.hpsf.Filetime;
|
||||||
import org.apache.poi.hsmf.datatypes.MAPIProperty;
|
import org.apache.poi.hsmf.datatypes.MAPIProperty;
|
||||||
import org.apache.poi.util.LittleEndian;
|
import org.apache.poi.util.LittleEndian;
|
||||||
import org.apache.poi.util.LocaleUtil;
|
import org.apache.poi.util.LocaleUtil;
|
||||||
@ -53,7 +53,7 @@ public final class MAPIDateAttribute extends MAPIAttribute {
|
|||||||
super(property, type, data);
|
super(property, type, data);
|
||||||
|
|
||||||
// The value is a 64 bit Windows Filetime
|
// The value is a 64 bit Windows Filetime
|
||||||
this.data = Util.filetimeToDate(
|
this.data = Filetime.filetimeToDate(
|
||||||
LittleEndian.getLong(data, 0)
|
LittleEndian.getLong(data, 0)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ import java.util.Locale;
|
|||||||
|
|
||||||
import org.apache.poi.hmef.Attachment;
|
import org.apache.poi.hmef.Attachment;
|
||||||
import org.apache.poi.hmef.HMEFMessage;
|
import org.apache.poi.hmef.HMEFMessage;
|
||||||
import org.apache.poi.hpsf.Util;
|
import org.apache.poi.hpsf.Filetime;
|
||||||
import org.apache.poi.util.LittleEndian;
|
import org.apache.poi.util.LittleEndian;
|
||||||
import org.apache.poi.util.LocaleUtil;
|
import org.apache.poi.util.LocaleUtil;
|
||||||
import org.apache.poi.util.POILogFactory;
|
import org.apache.poi.util.POILogFactory;
|
||||||
@ -52,7 +52,7 @@ public final class TNEFDateAttribute extends TNEFAttribute {
|
|||||||
byte[] binData = getData();
|
byte[] binData = getData();
|
||||||
if(binData.length == 8) {
|
if(binData.length == 8) {
|
||||||
// The value is a 64 bit Windows Filetime
|
// The value is a 64 bit Windows Filetime
|
||||||
this.data = Util.filetimeToDate(
|
this.data = Filetime.filetimeToDate(
|
||||||
LittleEndian.getLong(getData(), 0)
|
LittleEndian.getLong(getData(), 0)
|
||||||
);
|
);
|
||||||
} else if(binData.length == 14) {
|
} else if(binData.length == 14) {
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
package org.apache.poi.hpsf.basic;
|
package org.apache.poi.hpsf.basic;
|
||||||
|
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
@ -28,10 +27,13 @@ import java.io.FileNotFoundException;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.poi.POIDataSamples;
|
import org.apache.poi.POIDataSamples;
|
||||||
|
import org.apache.poi.hpsf.ClassID;
|
||||||
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
||||||
|
import org.apache.poi.hpsf.Filetime;
|
||||||
import org.apache.poi.hpsf.HPSFException;
|
import org.apache.poi.hpsf.HPSFException;
|
||||||
import org.apache.poi.hpsf.MarkUnsupportedException;
|
import org.apache.poi.hpsf.MarkUnsupportedException;
|
||||||
import org.apache.poi.hpsf.NoPropertySetStreamException;
|
import org.apache.poi.hpsf.NoPropertySetStreamException;
|
||||||
@ -48,33 +50,24 @@ import org.junit.Test;
|
|||||||
*/
|
*/
|
||||||
public final class TestBasic {
|
public final class TestBasic {
|
||||||
|
|
||||||
private static final String POI_FS = "TestGermanWord90.doc";
|
private static final POIDataSamples samples = POIDataSamples.getHPSFInstance();
|
||||||
private static final String[] POI_FILES = new String[]
|
|
||||||
{
|
|
||||||
"\005SummaryInformation",
|
|
||||||
"\005DocumentSummaryInformation",
|
|
||||||
"WordDocument",
|
|
||||||
"\001CompObj",
|
|
||||||
"1Table"
|
|
||||||
};
|
|
||||||
private static final int BYTE_ORDER = 0xfffe;
|
|
||||||
private static final int FORMAT = 0x0000;
|
|
||||||
private static final int OS_VERSION = 0x00020A04;
|
|
||||||
private static final byte[] CLASS_ID =
|
|
||||||
{
|
|
||||||
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
|
||||||
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
|
||||||
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
|
||||||
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00
|
|
||||||
};
|
|
||||||
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};
|
|
||||||
|
|
||||||
private POIFile[] poiFiles;
|
private static final String[] POI_FILES = {
|
||||||
|
"\005SummaryInformation",
|
||||||
|
"\005DocumentSummaryInformation",
|
||||||
|
"WordDocument",
|
||||||
|
"\001CompObj",
|
||||||
|
"1Table"
|
||||||
|
};
|
||||||
|
private static final int BYTE_ORDER = 0xfffe;
|
||||||
|
private static final int FORMAT = 0x0000;
|
||||||
|
private static final int OS_VERSION = 0x00020A04;
|
||||||
|
private static final ClassID CLASS_ID = new ClassID("{00000000-0000-0000-0000-000000000000}");
|
||||||
|
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};
|
||||||
|
|
||||||
|
private List<POIFile> poiFiles;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -84,10 +77,8 @@ public final class TestBasic {
|
|||||||
* @exception IOException if any other I/O exception occurs.
|
* @exception IOException if any other I/O exception occurs.
|
||||||
*/
|
*/
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws IOException
|
public void setUp() throws IOException {
|
||||||
{
|
final File data = samples.getFile("TestGermanWord90.doc");
|
||||||
POIDataSamples samples = POIDataSamples.getHPSFInstance();
|
|
||||||
final File data = samples.getFile(POI_FS);
|
|
||||||
poiFiles = Util.readPOIFiles(data);
|
poiFiles = Util.readPOIFiles(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,11 +87,11 @@ public final class TestBasic {
|
|||||||
* are expected to be in a certain order.</p>
|
* are expected to be in a certain order.</p>
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testReadFiles()
|
public void testReadFiles() {
|
||||||
{
|
|
||||||
String[] expected = POI_FILES;
|
String[] expected = POI_FILES;
|
||||||
for (int i = 0; i < expected.length; i++)
|
for (int i = 0; i < expected.length; i++) {
|
||||||
assertEquals(poiFiles[i].getName(), expected[i]);
|
assertEquals(poiFiles.get(i).getName(), expected[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -119,30 +110,22 @@ public final class TestBasic {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testCreatePropertySets()
|
public void testCreatePropertySets()
|
||||||
throws UnsupportedEncodingException, IOException
|
throws UnsupportedEncodingException, IOException {
|
||||||
{
|
Class<?>[] expected = {
|
||||||
Class<?>[] expected = new Class[]
|
SummaryInformation.class,
|
||||||
{
|
DocumentSummaryInformation.class,
|
||||||
SummaryInformation.class,
|
NoPropertySetStreamException.class,
|
||||||
DocumentSummaryInformation.class,
|
NoPropertySetStreamException.class,
|
||||||
NoPropertySetStreamException.class,
|
NoPropertySetStreamException.class
|
||||||
NoPropertySetStreamException.class,
|
};
|
||||||
NoPropertySetStreamException.class
|
for (int i = 0; i < expected.length; i++) {
|
||||||
};
|
InputStream in = new ByteArrayInputStream(poiFiles.get(i).getBytes());
|
||||||
for (int i = 0; i < expected.length; i++)
|
|
||||||
{
|
|
||||||
InputStream in = new ByteArrayInputStream(poiFiles[i].getBytes());
|
|
||||||
Object o;
|
Object o;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
o = PropertySetFactory.create(in);
|
o = PropertySetFactory.create(in);
|
||||||
}
|
} catch (NoPropertySetStreamException ex) {
|
||||||
catch (NoPropertySetStreamException ex)
|
|
||||||
{
|
|
||||||
o = ex;
|
o = ex;
|
||||||
}
|
} catch (MarkUnsupportedException ex) {
|
||||||
catch (MarkUnsupportedException ex)
|
|
||||||
{
|
|
||||||
o = ex;
|
o = ex;
|
||||||
}
|
}
|
||||||
in.close();
|
in.close();
|
||||||
@ -159,17 +142,15 @@ public final class TestBasic {
|
|||||||
* @exception HPSFException if any HPSF exception occurs
|
* @exception HPSFException if any HPSF exception occurs
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testPropertySetMethods() throws IOException, HPSFException
|
public void testPropertySetMethods() throws IOException, HPSFException {
|
||||||
{
|
|
||||||
/* Loop over the two property sets. */
|
/* Loop over the two property sets. */
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++) {
|
||||||
{
|
byte[] b = poiFiles.get(i).getBytes();
|
||||||
byte[] b = poiFiles[i].getBytes();
|
|
||||||
PropertySet ps = PropertySetFactory.create(new ByteArrayInputStream(b));
|
PropertySet ps = PropertySetFactory.create(new ByteArrayInputStream(b));
|
||||||
assertEquals(BYTE_ORDER, ps.getByteOrder());
|
assertEquals(BYTE_ORDER, ps.getByteOrder());
|
||||||
assertEquals(FORMAT, ps.getFormat());
|
assertEquals(FORMAT, ps.getFormat());
|
||||||
assertEquals(OS_VERSION, ps.getOSVersion());
|
assertEquals(OS_VERSION, ps.getOSVersion());
|
||||||
assertArrayEquals(CLASS_ID, ps.getClassID().getBytes());
|
assertEquals(CLASS_ID, ps.getClassID());
|
||||||
assertEquals(SECTION_COUNT[i], ps.getSectionCount());
|
assertEquals(SECTION_COUNT[i], ps.getSectionCount());
|
||||||
assertEquals(IS_SUMMARY_INFORMATION[i], ps.isSummaryInformation());
|
assertEquals(IS_SUMMARY_INFORMATION[i], ps.isSummaryInformation());
|
||||||
assertEquals(IS_DOCUMENT_SUMMARY_INFORMATION[i], ps.isDocumentSummaryInformation());
|
assertEquals(IS_DOCUMENT_SUMMARY_INFORMATION[i], ps.isDocumentSummaryInformation());
|
||||||
@ -185,11 +166,9 @@ public final class TestBasic {
|
|||||||
* @exception HPSFException if any HPSF exception occurs
|
* @exception HPSFException if any HPSF exception occurs
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testSectionMethods() throws IOException, HPSFException
|
public void testSectionMethods() throws IOException, HPSFException {
|
||||||
{
|
InputStream is = new ByteArrayInputStream(poiFiles.get(0).getBytes());
|
||||||
final SummaryInformation si = (SummaryInformation)
|
final SummaryInformation si = (SummaryInformation)PropertySetFactory.create(is);
|
||||||
PropertySetFactory.create(new ByteArrayInputStream
|
|
||||||
(poiFiles[0].getBytes()));
|
|
||||||
final List<Section> sections = si.getSections();
|
final List<Section> sections = si.getSections();
|
||||||
final Section s = sections.get(0);
|
final Section s = sections.get(0);
|
||||||
assertEquals(s.getFormatID(), SectionIDMap.SUMMARY_INFORMATION_ID);
|
assertEquals(s.getFormatID(), SectionIDMap.SUMMARY_INFORMATION_ID);
|
||||||
@ -198,4 +177,16 @@ public final class TestBasic {
|
|||||||
assertEquals("Titel", s.getProperty(2));
|
assertEquals("Titel", s.getProperty(2));
|
||||||
assertEquals(1764, s.getSize());
|
assertEquals(1764, s.getSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void bug52117LastPrinted() throws IOException, HPSFException {
|
||||||
|
File f = samples.getFile("TestBug52117.doc");
|
||||||
|
POIFile poiFile = Util.readPOIFiles(f, new String[]{POI_FILES[0]}).get(0);
|
||||||
|
InputStream in = new ByteArrayInputStream(poiFile.getBytes());
|
||||||
|
SummaryInformation si = (SummaryInformation)PropertySetFactory.create(in);
|
||||||
|
Date lastPrinted = si.getLastPrinted();
|
||||||
|
long editTime = si.getEditTime();
|
||||||
|
assertTrue(Filetime.isUndefined(lastPrinted));
|
||||||
|
assertEquals(1800000000L, editTime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,14 +17,17 @@
|
|||||||
|
|
||||||
package org.apache.poi.hpsf.basic;
|
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 java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.util.List;
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
import org.apache.poi.POIDataSamples;
|
import org.apache.poi.POIDataSamples;
|
||||||
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
||||||
@ -35,27 +38,29 @@ import org.apache.poi.hpsf.PropertySet;
|
|||||||
import org.apache.poi.hpsf.PropertySetFactory;
|
import org.apache.poi.hpsf.PropertySetFactory;
|
||||||
import org.apache.poi.hpsf.SummaryInformation;
|
import org.apache.poi.hpsf.SummaryInformation;
|
||||||
import org.apache.poi.hpsf.Variant;
|
import org.apache.poi.hpsf.Variant;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Test case for OLE2 files with empty properties. An empty property's type
|
* Test case for OLE2 files with empty properties.
|
||||||
* is {@link Variant#VT_EMPTY}.</p>
|
* An empty property's type is {@link Variant#VT_EMPTY}.
|
||||||
*/
|
*/
|
||||||
public final class TestEmptyProperties extends TestCase {
|
public final class TestEmptyProperties {
|
||||||
|
|
||||||
|
private static final POIDataSamples samples = POIDataSamples.getHPSFInstance();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>This test file's summary information stream contains some empty
|
* This test file's summary information stream contains some empty properties.
|
||||||
* properties.</p>
|
|
||||||
*/
|
*/
|
||||||
private static final String POI_FS = "TestCorel.shw";
|
private static final String POI_FS = "TestCorel.shw";
|
||||||
|
|
||||||
private static final String[] POI_FILES = new String[]
|
private static final String[] POI_FILES = {
|
||||||
{
|
"PerfectOffice_MAIN",
|
||||||
"PerfectOffice_MAIN",
|
"\005SummaryInformation",
|
||||||
"\005SummaryInformation",
|
"Main"
|
||||||
"Main"
|
};
|
||||||
};
|
|
||||||
|
|
||||||
private POIFile[] poiFiles;
|
private List<POIFile> poiFiles;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Read a the test file from the "data" directory.</p>
|
* <p>Read a the test file from the "data" directory.</p>
|
||||||
@ -64,24 +69,21 @@ public final class TestEmptyProperties extends TestCase {
|
|||||||
* does not exist
|
* does not exist
|
||||||
* @exception IOException if an I/O exception occurs
|
* @exception IOException if an I/O exception occurs
|
||||||
*/
|
*/
|
||||||
@Override
|
@Before
|
||||||
public void setUp() throws FileNotFoundException, IOException
|
public void setUp() throws IOException {
|
||||||
{
|
|
||||||
POIDataSamples samples = POIDataSamples.getHPSFInstance();
|
|
||||||
final File data = samples.getFile(POI_FS);
|
final File data = samples.getFile(POI_FS);
|
||||||
|
|
||||||
poiFiles = Util.readPOIFiles(data);
|
poiFiles = Util.readPOIFiles(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Checks the names of the files in the POI filesystem. They
|
* Checks the names of the files in the POI filesystem. They
|
||||||
* are expected to be in a certain order.</p>
|
* are expected to be in a certain order.
|
||||||
*/
|
*/
|
||||||
public void testReadFiles()
|
@Test
|
||||||
{
|
public void testReadFiles() {
|
||||||
String[] expected = POI_FILES;
|
String[] expected = POI_FILES;
|
||||||
for (int i = 0; i < expected.length; i++)
|
for (int i = 0; i < expected.length; i++)
|
||||||
assertEquals(poiFiles[i].getName(), expected[i]);
|
assertEquals(poiFiles.get(i).getName(), expected[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -98,29 +100,22 @@ public final class TestEmptyProperties extends TestCase {
|
|||||||
* @exception UnsupportedEncodingException if a character encoding is not
|
* @exception UnsupportedEncodingException if a character encoding is not
|
||||||
* supported.
|
* supported.
|
||||||
*/
|
*/
|
||||||
|
@Test
|
||||||
public void testCreatePropertySets()
|
public void testCreatePropertySets()
|
||||||
throws UnsupportedEncodingException, IOException
|
throws UnsupportedEncodingException, IOException {
|
||||||
{
|
Class<?>[] expected = {
|
||||||
Class<?>[] expected = new Class[]
|
NoPropertySetStreamException.class,
|
||||||
{
|
SummaryInformation.class,
|
||||||
NoPropertySetStreamException.class,
|
NoPropertySetStreamException.class
|
||||||
SummaryInformation.class,
|
};
|
||||||
NoPropertySetStreamException.class
|
for (int i = 0; i < expected.length; i++) {
|
||||||
};
|
InputStream in = new ByteArrayInputStream(poiFiles.get(i).getBytes());
|
||||||
for (int i = 0; i < expected.length; i++)
|
|
||||||
{
|
|
||||||
InputStream in = new ByteArrayInputStream(poiFiles[i].getBytes());
|
|
||||||
Object o;
|
Object o;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
o = PropertySetFactory.create(in);
|
o = PropertySetFactory.create(in);
|
||||||
}
|
} catch (NoPropertySetStreamException ex) {
|
||||||
catch (NoPropertySetStreamException ex)
|
|
||||||
{
|
|
||||||
o = ex;
|
o = ex;
|
||||||
}
|
} catch (MarkUnsupportedException ex) {
|
||||||
catch (MarkUnsupportedException ex)
|
|
||||||
{
|
|
||||||
o = ex;
|
o = ex;
|
||||||
}
|
}
|
||||||
in.close();
|
in.close();
|
||||||
@ -136,11 +131,10 @@ public final class TestEmptyProperties extends TestCase {
|
|||||||
* @exception IOException if an I/O exception occurs
|
* @exception IOException if an I/O exception occurs
|
||||||
* @exception HPSFException if an HPSF operation fails
|
* @exception HPSFException if an HPSF operation fails
|
||||||
*/
|
*/
|
||||||
public void testPropertySetMethods() throws IOException, HPSFException
|
@Test
|
||||||
{
|
public void testPropertySetMethods() throws IOException, HPSFException {
|
||||||
byte[] b = poiFiles[1].getBytes();
|
byte[] b = poiFiles.get(1).getBytes();
|
||||||
PropertySet ps =
|
PropertySet ps = PropertySetFactory.create(new ByteArrayInputStream(b));
|
||||||
PropertySetFactory.create(new ByteArrayInputStream(b));
|
|
||||||
SummaryInformation s = (SummaryInformation) ps;
|
SummaryInformation s = (SummaryInformation) ps;
|
||||||
assertNull(s.getTitle());
|
assertNull(s.getTitle());
|
||||||
assertNull(s.getSubject());
|
assertNull(s.getSubject());
|
||||||
|
@ -17,13 +17,14 @@
|
|||||||
|
|
||||||
package org.apache.poi.hpsf.basic;
|
package org.apache.poi.hpsf.basic;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
import org.apache.poi.POIDataSamples;
|
import org.apache.poi.POIDataSamples;
|
||||||
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
||||||
import org.apache.poi.hpsf.HPSFException;
|
import org.apache.poi.hpsf.HPSFException;
|
||||||
@ -32,30 +33,30 @@ import org.apache.poi.hpsf.PropertySetFactory;
|
|||||||
import org.apache.poi.hpsf.Section;
|
import org.apache.poi.hpsf.Section;
|
||||||
import org.apache.poi.hpsf.SummaryInformation;
|
import org.apache.poi.hpsf.SummaryInformation;
|
||||||
import org.apache.poi.util.CodePageUtil;
|
import org.apache.poi.util.CodePageUtil;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Tests whether Unicode string can be read from a
|
* Tests whether Unicode string can be read from a DocumentSummaryInformation.
|
||||||
* DocumentSummaryInformation.</p>
|
|
||||||
*/
|
*/
|
||||||
public class TestUnicode extends TestCase {
|
public class TestUnicode {
|
||||||
|
|
||||||
static final String POI_FS = "TestUnicode.xls";
|
static final String POI_FS = "TestUnicode.xls";
|
||||||
static final String[] POI_FILES = new String[]
|
static final String[] POI_FILES = {
|
||||||
{
|
"\005DocumentSummaryInformation",
|
||||||
"\005DocumentSummaryInformation",
|
};
|
||||||
};
|
|
||||||
File data;
|
File data;
|
||||||
POIFile[] poiFiles;
|
POIFile[] poiFiles;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Read a the test file from the "data" directory.</p>
|
* Read a the test file from the "data" directory.
|
||||||
*
|
*
|
||||||
* @exception FileNotFoundException if the file to be read does not exist.
|
* @exception FileNotFoundException if the file to be read does not exist.
|
||||||
* @exception IOException if any other I/O exception occurs
|
* @exception IOException if any other I/O exception occurs
|
||||||
*/
|
*/
|
||||||
@Override
|
@Before
|
||||||
protected void setUp() {
|
public void setUp() {
|
||||||
POIDataSamples samples = POIDataSamples.getHPSFInstance();
|
POIDataSamples samples = POIDataSamples.getHPSFInstance();
|
||||||
data = samples.getFile(POI_FS);
|
data = samples.getFile(POI_FS);
|
||||||
}
|
}
|
||||||
@ -63,31 +64,25 @@ public class TestUnicode extends TestCase {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Tests the {@link PropertySet} methods. The test file has two
|
* Tests the {@link PropertySet} methods. The test file has two
|
||||||
* property set: the first one is a {@link SummaryInformation},
|
* property set: the first one is a {@link SummaryInformation},
|
||||||
* the second one is a {@link DocumentSummaryInformation}.</p>
|
* the second one is a {@link DocumentSummaryInformation}.
|
||||||
*
|
*
|
||||||
* @exception IOException if an I/O exception occurs
|
* @exception IOException if an I/O exception occurs
|
||||||
* @exception HPSFException if an HPSF exception occurs
|
* @exception HPSFException if an HPSF exception occurs
|
||||||
*/
|
*/
|
||||||
public void testPropertySetMethods() throws IOException, HPSFException
|
@Test
|
||||||
{
|
public void testPropertySetMethods() throws IOException, HPSFException {
|
||||||
POIFile poiFile = Util.readPOIFiles(data, POI_FILES)[0];
|
POIFile poiFile = Util.readPOIFiles(data, POI_FILES).get(0);
|
||||||
byte[] b = poiFile.getBytes();
|
byte[] b = poiFile.getBytes();
|
||||||
PropertySet ps =
|
PropertySet ps = PropertySetFactory.create(new ByteArrayInputStream(b));
|
||||||
PropertySetFactory.create(new ByteArrayInputStream(b));
|
|
||||||
assertTrue(ps.isDocumentSummaryInformation());
|
assertTrue(ps.isDocumentSummaryInformation());
|
||||||
assertEquals(ps.getSectionCount(), 2);
|
assertEquals(ps.getSectionCount(), 2);
|
||||||
Section s = ps.getSections().get(1);
|
Section s = ps.getSections().get(1);
|
||||||
assertEquals(s.getProperty(1),
|
assertEquals(s.getProperty(1), CodePageUtil.CP_UTF16);
|
||||||
Integer.valueOf(CodePageUtil.CP_UTF16));
|
assertEquals(s.getProperty(2), -96070278);
|
||||||
assertEquals(s.getProperty(2),
|
assertEquals(s.getProperty(3), "MCon_Info zu Office bei Schreiner");
|
||||||
Integer.valueOf(-96070278));
|
assertEquals(s.getProperty(4), "petrovitsch@schreiner-online.de");
|
||||||
assertEquals(s.getProperty(3),
|
assertEquals(s.getProperty(5), "Petrovitsch, Wilhelm");
|
||||||
"MCon_Info zu Office bei Schreiner");
|
|
||||||
assertEquals(s.getProperty(4),
|
|
||||||
"petrovitsch@schreiner-online.de");
|
|
||||||
assertEquals(s.getProperty(5),
|
|
||||||
"Petrovitsch, Wilhelm");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -237,7 +237,7 @@ public class TestWrite {
|
|||||||
try {
|
try {
|
||||||
psa[0] = PropertySetFactory.create(event.getStream());
|
psa[0] = PropertySetFactory.create(event.getStream());
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
fail(org.apache.poi.hpsf.Util.toString(ex));
|
fail(ex.getMessage());
|
||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
SummaryInformation.DEFAULT_STREAM_NAME
|
SummaryInformation.DEFAULT_STREAM_NAME
|
||||||
@ -340,7 +340,7 @@ public class TestWrite {
|
|||||||
try {
|
try {
|
||||||
PropertySetFactory.create(event.getStream());
|
PropertySetFactory.create(event.getStream());
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
fail(org.apache.poi.hpsf.Util.toString(ex));
|
fail(ex.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,17 +18,13 @@
|
|||||||
|
|
||||||
package org.apache.poi.hpsf.basic;
|
package org.apache.poi.hpsf.basic;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
import org.apache.poi.hpsf.PropertySet;
|
import org.apache.poi.hpsf.PropertySet;
|
||||||
import org.apache.poi.poifs.eventfilesystem.POIFSReader;
|
import org.apache.poi.poifs.eventfilesystem.POIFSReader;
|
||||||
@ -43,31 +39,6 @@ import org.apache.poi.util.IOUtils;
|
|||||||
*/
|
*/
|
||||||
final class Util {
|
final class Util {
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Reads all files from a POI filesystem and returns them as an
|
|
||||||
* array of {@link POIFile} instances. This method loads all files
|
|
||||||
* into memory and thus does not cope well with large POI
|
|
||||||
* filessystems.</p>
|
|
||||||
*
|
|
||||||
* @param poiFs The name of the POI filesystem as seen by the
|
|
||||||
* operating system. (This is the "filename".)
|
|
||||||
*
|
|
||||||
* @return The POI files. The elements are ordered in the same way
|
|
||||||
* as the files in the POI filesystem.
|
|
||||||
*
|
|
||||||
* @exception FileNotFoundException if the file containing the POI
|
|
||||||
* filesystem does not exist
|
|
||||||
*
|
|
||||||
* @exception IOException if an I/O exception occurs
|
|
||||||
*/
|
|
||||||
public static POIFile[] readPOIFiles(final File poiFs)
|
|
||||||
throws FileNotFoundException, IOException
|
|
||||||
{
|
|
||||||
return readPOIFiles(poiFs, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Reads a set of files from a POI filesystem and returns them
|
* <p>Reads a set of files from a POI filesystem and returns them
|
||||||
* as an array of {@link POIFile} instances. This method loads all
|
* as an array of {@link POIFile} instances. This method loads all
|
||||||
@ -87,42 +58,34 @@ final class Util {
|
|||||||
*
|
*
|
||||||
* @exception IOException if an I/O exception occurs
|
* @exception IOException if an I/O exception occurs
|
||||||
*/
|
*/
|
||||||
public static POIFile[] readPOIFiles(final File poiFs,
|
public static List<POIFile> readPOIFiles(final File poiFs, final String... poiFiles)
|
||||||
final String[] poiFiles)
|
throws FileNotFoundException, IOException {
|
||||||
throws FileNotFoundException, IOException
|
|
||||||
{
|
|
||||||
final List<POIFile> files = new ArrayList<POIFile>();
|
final List<POIFile> files = new ArrayList<POIFile>();
|
||||||
POIFSReader r = new POIFSReader();
|
POIFSReader r = new POIFSReader();
|
||||||
POIFSReaderListener pfl = new POIFSReaderListener()
|
POIFSReaderListener pfl = new POIFSReaderListener() {
|
||||||
{
|
|
||||||
@Override
|
@Override
|
||||||
public void processPOIFSReaderEvent(final POIFSReaderEvent event)
|
public void processPOIFSReaderEvent(final POIFSReaderEvent event) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
final POIFile f = new POIFile();
|
final POIFile f = new POIFile();
|
||||||
f.setName(event.getName());
|
f.setName(event.getName());
|
||||||
f.setPath(event.getPath());
|
f.setPath(event.getPath());
|
||||||
final InputStream in = event.getStream();
|
final InputStream in = event.getStream();
|
||||||
final ByteArrayOutputStream out =
|
f.setBytes(IOUtils.toByteArray(in));
|
||||||
new ByteArrayOutputStream();
|
in.close();
|
||||||
IOUtils.copy(in, out);
|
|
||||||
out.close();
|
|
||||||
f.setBytes(out.toByteArray());
|
|
||||||
files.add(f);
|
files.add(f);
|
||||||
}
|
} catch (IOException ex) {
|
||||||
catch (IOException ex)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(ex);
|
throw new RuntimeException(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (poiFiles == null)
|
if (poiFiles.length == 0) {
|
||||||
/* Register the listener for all POI files. */
|
/* Register the listener for all POI files. */
|
||||||
r.registerListener(pfl);
|
r.registerListener(pfl);
|
||||||
else
|
} else {
|
||||||
for (String poiFile : poiFiles)
|
for (String poiFile : poiFiles) {
|
||||||
r.registerListener(pfl, poiFile);
|
r.registerListener(pfl, poiFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Read the POI filesystem. */
|
/* Read the POI filesystem. */
|
||||||
FileInputStream stream = new FileInputStream(poiFs);
|
FileInputStream stream = new FileInputStream(poiFs);
|
||||||
@ -131,10 +94,7 @@ final class Util {
|
|||||||
} finally {
|
} finally {
|
||||||
stream.close();
|
stream.close();
|
||||||
}
|
}
|
||||||
POIFile[] result = new POIFile[files.size()];
|
return files;
|
||||||
for (int i = 0; i < result.length; i++)
|
|
||||||
result[i] = files.get(i);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -155,18 +115,7 @@ final class Util {
|
|||||||
*
|
*
|
||||||
* @exception IOException if an I/O exception occurs
|
* @exception IOException if an I/O exception occurs
|
||||||
*/
|
*/
|
||||||
public static List<POIFile> readPropertySets(final File poiFs)
|
public static List<POIFile> readPropertySets(final File poiFs) throws IOException {
|
||||||
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 List<POIFile> files = new ArrayList<POIFile>(7);
|
||||||
final POIFSReader r = new POIFSReader();
|
final POIFSReader r = new POIFSReader();
|
||||||
POIFSReaderListener pfl = new POIFSReaderListener() {
|
POIFSReaderListener pfl = new POIFSReaderListener() {
|
||||||
@ -191,28 +140,13 @@ final class Util {
|
|||||||
r.registerListener(pfl);
|
r.registerListener(pfl);
|
||||||
|
|
||||||
/* Read the POI filesystem. */
|
/* Read the POI filesystem. */
|
||||||
r.read(poiFs);
|
InputStream is = new FileInputStream(poiFs);
|
||||||
|
try {
|
||||||
|
r.read(is);
|
||||||
|
} finally {
|
||||||
|
is.close();
|
||||||
|
}
|
||||||
|
|
||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Prints the system properties to System.out.</p>
|
|
||||||
*/
|
|
||||||
public static void printSystemProperties()
|
|
||||||
{
|
|
||||||
final Properties p = System.getProperties();
|
|
||||||
final List<String> names = new LinkedList<String>();
|
|
||||||
for (String name : p.stringPropertyNames())
|
|
||||||
names.add(name);
|
|
||||||
Collections.sort(names);
|
|
||||||
for (String name : names) {
|
|
||||||
String value = p.getProperty(name);
|
|
||||||
System.out.println(name + ": " + value);
|
|
||||||
}
|
|
||||||
System.out.println("Current directory: " +
|
|
||||||
System.getProperty("user.dir"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user