Constructors Summary |
---|
public PropertySet(byte[] stream)Creates a {@link PropertySet} instance from a byte array
that represents a stream in the Horrible Property Set
Format.
this(stream, 0, stream.length);
|
protected PropertySet()Creates an empty (uninitialized) {@link PropertySet}.
Please note: For the time being this
constructor is protected since it is used for internal purposes
only, but expect it to become public once the property set's
writing functionality is implemented.
|
public PropertySet(InputStream stream)Creates a {@link PropertySet} instance from an {@link
InputStream} in the Horrible Property Set Format.
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.
if (isPropertySetStream(stream))
{
final int avail = stream.available();
final byte[] buffer = new byte[avail];
stream.read(buffer, 0, buffer.length);
init(buffer, 0, buffer.length);
}
else
throw new NoPropertySetStreamException();
|
public PropertySet(byte[] stream, int offset, int length)Creates a {@link PropertySet} instance from a byte array
that represents a stream in the Horrible Property Set
Format.
if (isPropertySetStream(stream, offset, length))
init(stream, offset, length);
else
throw new NoPropertySetStreamException();
|
Methods Summary |
---|
public boolean | equals(java.lang.Object o)Returns true if the PropertySet is equal
to the specified parameter, else false .
if (o == null || !(o instanceof PropertySet))
return false;
final PropertySet ps = (PropertySet) o;
int byteOrder1 = ps.getByteOrder();
int byteOrder2 = getByteOrder();
ClassID classID1 = ps.getClassID();
ClassID classID2 = getClassID();
int format1 = ps.getFormat();
int format2 = getFormat();
int osVersion1 = ps.getOSVersion();
int osVersion2 = getOSVersion();
int sectionCount1 = ps.getSectionCount();
int sectionCount2 = getSectionCount();
if (byteOrder1 != byteOrder2 ||
!classID1.equals(classID2) ||
format1 != format2 ||
osVersion1 != osVersion2 ||
sectionCount1 != sectionCount2)
return false;
/* Compare the sections: */
return Util.equals(getSections(), ps.getSections());
|
public int | getByteOrder()Returns the property set stream's low-level "byte order"
field. It is always 0xFFFE .
return byteOrder;
|
public org.apache.poi.hpsf.ClassID | getClassID()Returns the property set stream's low-level "class ID"
field.
return classID;
|
public org.apache.poi.hpsf.Section | getFirstSection()Gets the {@link PropertySet}'s first section.
if (getSectionCount() < 1)
throw new MissingSectionException("Property set does not contain any sections.");
return ((Section) sections.get(0));
|
public int | getFormat()Returns the property set stream's low-level "format"
field. It is always 0x0000 .
return format;
|
public int | getOSVersion()Returns the property set stream's low-level "OS version"
field.
return osVersion;
|
public org.apache.poi.hpsf.Property[] | getProperties()Convenience method returning the {@link Property} array
contained in this property set. It is a shortcut for getting
the {@link PropertySet}'s {@link Section}s list and then
getting the {@link Property} array from the first {@link
Section}.
return getFirstSection().getProperties();
|
protected java.lang.Object | getProperty(int id)Convenience method returning the value of the property with
the specified ID. If the property is not available,
null is returned and a subsequent call to {@link
#wasNull} will return true .
return getFirstSection().getProperty(id);
|
protected boolean | getPropertyBooleanValue(int id)Convenience method returning the value of a boolean property
with the specified ID. If the property is not available,
false is returned. A subsequent call to {@link
#wasNull} will return true to let the caller
distinguish that case from a real property value of
false .
return getFirstSection().getPropertyBooleanValue(id);
|
protected int | getPropertyIntValue(int id)Convenience method returning the value of the numeric
property with the specified ID. If the property is not
available, 0 is returned. A subsequent call to {@link #wasNull}
will return true to let the caller distinguish
that case from a real property value of 0.
return getFirstSection().getPropertyIntValue(id);
|
public int | getSectionCount()Returns the number of {@link Section}s in the property
set.
return sections.size();
|
public java.util.List | getSections()Returns the {@link Section}s in the property set.
return sections;
|
public org.apache.poi.hpsf.Section | getSingleSection()If the {@link PropertySet} has only a single section this
method returns it.
final int sectionCount = getSectionCount();
if (sectionCount != 1)
throw new NoSingleSectionException
("Property set contains " + sectionCount + " sections.");
return ((Section) sections.get(0));
|
public int | hashCode()
throw new UnsupportedOperationException("FIXME: Not yet implemented.");
|
private void | init(byte[] src, int offset, int length)Initializes this {@link PropertySet} instance from a byte
array. The method assumes that it has been checked already that
the byte array indeed represents a property set stream. It does
no more checks on its own.
/* FIXME (3): Ensure that at most "length" bytes are read. */
/*
* Read the stream's header fields.
*/
int o = offset;
byteOrder = LittleEndian.getUShort(src, o);
o += LittleEndian.SHORT_SIZE;
format = LittleEndian.getUShort(src, o);
o += LittleEndian.SHORT_SIZE;
osVersion = (int) LittleEndian.getUInt(src, o);
o += LittleEndian.INT_SIZE;
classID = new ClassID(src, o);
o += ClassID.LENGTH;
final int sectionCount = LittleEndian.getInt(src, o);
o += LittleEndian.INT_SIZE;
if (sectionCount <= 0)
throw new HPSFRuntimeException("Section count " + sectionCount +
" must be greater than 0.");
/*
* Read the sections, which are following the header. They
* start with an array of section descriptions. Each one
* consists of a format ID telling what the section contains
* and an offset telling how many bytes from the start of the
* stream the section begins.
*/
/*
* Most property sets have only one section. The Document
* Summary Information stream has 2. Everything else is a rare
* exception and is no longer fostered by Microsoft.
*/
sections = new ArrayList(sectionCount);
/*
* Loop over the section descriptor array. Each descriptor
* consists of a ClassID and a DWord, and we have to increment
* "offset" accordingly.
*/
for (int i = 0; i < sectionCount; i++)
{
final Section s = new Section(src, o);
o += ClassID.LENGTH + LittleEndian.INT_SIZE;
sections.add(s);
}
|
public boolean | isDocumentSummaryInformation()Checks whether this {@link PropertySet} is a Document
Summary Information.
return Util.equal(((Section) sections.get(0)).getFormatID().getBytes(),
SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID[0]);
|
public static boolean | isPropertySetStream(java.io.InputStream stream)Checks whether an {@link InputStream} is in the Horrible
Property Set Format.
/*
* Read at most this many bytes.
*/
final int BUFFER_SIZE = 50;
/*
* Mark the current position in the stream so that we can
* reset to this position if the stream does not contain a
* property set.
*/
if (!stream.markSupported())
throw new MarkUnsupportedException(stream.getClass().getName());
stream.mark(BUFFER_SIZE);
/*
* Read a couple of bytes from the stream.
*/
final byte[] buffer = new byte[BUFFER_SIZE];
final int bytes =
stream.read(buffer, 0,
Math.min(buffer.length, stream.available()));
final boolean isPropertySetStream =
isPropertySetStream(buffer, 0, bytes);
stream.reset();
return isPropertySetStream;
|
public static boolean | isPropertySetStream(byte[] src, int offset, int length)Checks whether a byte array is in the Horrible Property Set
Format.
/* FIXME (3): Ensure that at most "length" bytes are read. */
/*
* Read the header fields of the stream. They must always be
* there.
*/
int o = offset;
final int byteOrder = LittleEndian.getUShort(src, o);
o += LittleEndian.SHORT_SIZE;
byte[] temp = new byte[LittleEndian.SHORT_SIZE];
LittleEndian.putShort(temp, (short) byteOrder);
if (!Util.equal(temp, BYTE_ORDER_ASSERTION))
return false;
final int format = LittleEndian.getUShort(src, o);
o += LittleEndian.SHORT_SIZE;
temp = new byte[LittleEndian.SHORT_SIZE];
LittleEndian.putShort(temp, (short) format);
if (!Util.equal(temp, FORMAT_ASSERTION))
return false;
// final long osVersion = LittleEndian.getUInt(src, offset);
o += LittleEndian.INT_SIZE;
// final ClassID classID = new ClassID(src, offset);
o += ClassID.LENGTH;
final long sectionCount = LittleEndian.getUInt(src, o);
o += LittleEndian.INT_SIZE;
if (sectionCount < 1)
return false;
return true;
|
public boolean | isSummaryInformation()Checks whether this {@link PropertySet} represents a Summary
Information.
return Util.equal(((Section) sections.get(0)).getFormatID().getBytes(),
SectionIDMap.SUMMARY_INFORMATION_ID);
|
public java.lang.String | toString()
final StringBuffer b = new StringBuffer();
final int sectionCount = getSectionCount();
b.append(getClass().getName());
b.append('[");
b.append("byteOrder: ");
b.append(getByteOrder());
b.append(", classID: ");
b.append(getClassID());
b.append(", format: ");
b.append(getFormat());
b.append(", OSVersion: ");
b.append(getOSVersion());
b.append(", sectionCount: ");
b.append(sectionCount);
b.append(", sections: [\n");
final List sections = getSections();
for (int i = 0; i < sectionCount; i++)
b.append(((Section) sections.get(i)).toString());
b.append(']");
b.append(']");
return b.toString();
|
public boolean | wasNull()Checks whether the property which the last call to {@link
#getPropertyIntValue} or {@link #getProperty} tried to access
was available or not. This information might be important for
callers of {@link #getPropertyIntValue} since the latter
returns 0 if the property does not exist. Using {@link
#wasNull}, the caller can distiguish this case from a
property's real value of 0.
return getFirstSection().wasNull();
|