2004-04-09 09:05:39 -04:00
|
|
|
/* ====================================================================
|
|
|
|
Copyright 2002-2004 Apache Software Foundation
|
|
|
|
|
|
|
|
Licensed 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.
|
|
|
|
==================================================================== */
|
|
|
|
|
2003-08-30 05:13:53 -04:00
|
|
|
package org.apache.poi.hpsf;
|
|
|
|
|
2003-09-01 14:51:08 -04:00
|
|
|
import java.io.ByteArrayInputStream;
|
|
|
|
import java.io.ByteArrayOutputStream;
|
2003-08-30 05:13:53 -04:00
|
|
|
import java.io.IOException;
|
2003-09-01 14:51:08 -04:00
|
|
|
import java.io.InputStream;
|
2003-08-30 05:13:53 -04:00
|
|
|
import java.io.OutputStream;
|
2004-08-31 16:47:09 -04:00
|
|
|
import java.io.UnsupportedEncodingException;
|
2003-09-04 16:15:24 -04:00
|
|
|
import java.util.Iterator;
|
2003-08-30 05:13:53 -04:00
|
|
|
import java.util.LinkedList;
|
|
|
|
import java.util.ListIterator;
|
2003-09-01 14:51:08 -04:00
|
|
|
|
2003-08-30 05:13:53 -04:00
|
|
|
import org.apache.poi.util.LittleEndian;
|
|
|
|
import org.apache.poi.util.LittleEndianConsts;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* <p>Adds writing support to the {@link PropertySet} class.</p>
|
|
|
|
*
|
|
|
|
* <p>Please be aware that this class' functionality will be merged into the
|
|
|
|
* {@link PropertySet} class at a later time, so the API will change.</p>
|
|
|
|
*
|
|
|
|
* @author Rainer Klute <a
|
|
|
|
* href="mailto:klute@rainer-klute.de"><klute@rainer-klute.de></a>
|
|
|
|
* @version $Id$
|
|
|
|
* @since 2003-02-19
|
|
|
|
*/
|
|
|
|
public class MutablePropertySet extends PropertySet
|
|
|
|
{
|
|
|
|
|
|
|
|
/**
|
|
|
|
* <p>Constructs a <code>MutablePropertySet</code> instance. Its
|
|
|
|
* primary task is to initialize the immutable field with their proper
|
|
|
|
* values. It also sets fields that might change to reasonable defaults.</p>
|
|
|
|
*/
|
|
|
|
public MutablePropertySet()
|
|
|
|
{
|
|
|
|
/* Initialize the "byteOrder" field. */
|
|
|
|
byteOrder = LittleEndian.getUShort(BYTE_ORDER_ASSERTION);
|
|
|
|
|
|
|
|
/* Initialize the "format" field. */
|
|
|
|
format = LittleEndian.getUShort(FORMAT_ASSERTION);
|
|
|
|
|
|
|
|
/* Initialize "osVersion" field as if the property has been created on
|
|
|
|
* a Win32 platform, whether this is the case or not. */
|
|
|
|
osVersion = (OS_WIN32 << 16) | 0x0A04;
|
|
|
|
|
|
|
|
/* Initailize the "classID" field. */
|
|
|
|
classID = new ClassID();
|
|
|
|
|
|
|
|
/* Initialize the sections. Since property set must have at least
|
|
|
|
* one section it is added right here. */
|
|
|
|
sections = new LinkedList();
|
|
|
|
sections.add(new MutableSection());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2003-09-04 16:15:24 -04:00
|
|
|
/**
|
|
|
|
* <p>Constructs a <code>MutablePropertySet</code> by doing a deep copy of
|
|
|
|
* an existing <code>PropertySet</code>. All nested elements, i.e.
|
|
|
|
* <code>Section</code>s and <code>Property</code> instances, will be their
|
|
|
|
* mutable counterparts in the new <code>MutablePropertySet</code>.</p>
|
|
|
|
*
|
|
|
|
* @param ps The property set to copy
|
|
|
|
*/
|
|
|
|
public MutablePropertySet(final PropertySet ps)
|
|
|
|
{
|
|
|
|
byteOrder = ps.getByteOrder();
|
|
|
|
format = ps.getFormat();
|
|
|
|
osVersion = ps.getOSVersion();
|
2003-09-18 14:56:35 -04:00
|
|
|
setClassID(ps.getClassID());
|
2003-09-04 16:15:24 -04:00
|
|
|
clearSections();
|
|
|
|
for (final Iterator i = ps.getSections().iterator(); i.hasNext();)
|
|
|
|
{
|
|
|
|
final MutableSection s = new MutableSection((Section) (i.next()));
|
|
|
|
addSection(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2003-08-30 05:13:53 -04:00
|
|
|
/**
|
|
|
|
* <p>The length of the property set stream header.</p>
|
|
|
|
*/
|
|
|
|
private final int OFFSET_HEADER =
|
|
|
|
BYTE_ORDER_ASSERTION.length + /* Byte order */
|
|
|
|
FORMAT_ASSERTION.length + /* Format */
|
|
|
|
LittleEndianConsts.INT_SIZE + /* OS version */
|
|
|
|
ClassID.LENGTH + /* Class ID */
|
|
|
|
LittleEndianConsts.INT_SIZE; /* Section count */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* <p>Sets the "byteOrder" property.</p>
|
|
|
|
*
|
|
|
|
* @param byteOrder the byteOrder value to set
|
|
|
|
*/
|
|
|
|
public void setByteOrder(final int byteOrder)
|
|
|
|
{
|
|
|
|
this.byteOrder = byteOrder;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* <p>Sets the "format" property.</p>
|
|
|
|
*
|
|
|
|
* @param format the format value to set
|
|
|
|
*/
|
|
|
|
public void setFormat(final int format)
|
|
|
|
{
|
|
|
|
this.format = format;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* <p>Sets the "osVersion" property.</p>
|
|
|
|
*
|
|
|
|
* @param osVersion the osVersion value to set
|
|
|
|
*/
|
|
|
|
public void setOSVersion(final int osVersion)
|
|
|
|
{
|
|
|
|
this.osVersion = osVersion;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* <p>Sets the property set stream's low-level "class ID"
|
|
|
|
* field.</p>
|
|
|
|
*
|
|
|
|
* @param classID The property set stream's low-level "class ID" field.
|
|
|
|
*
|
|
|
|
* @see #getClassID
|
|
|
|
*/
|
|
|
|
public void setClassID(final ClassID classID)
|
|
|
|
{
|
|
|
|
this.classID = classID;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* <p>Removes all sections from this property set.</p>
|
|
|
|
*/
|
|
|
|
public void clearSections()
|
|
|
|
{
|
|
|
|
sections = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* <p>Adds a section to this property set.</p>
|
|
|
|
*
|
|
|
|
* @param section The {@link Section} to add. It will be appended
|
|
|
|
* after any sections that are already present in the property set
|
|
|
|
* and thus become the last section.
|
|
|
|
*/
|
|
|
|
public void addSection(final Section section)
|
|
|
|
{
|
|
|
|
if (sections == null)
|
|
|
|
sections = new LinkedList();
|
|
|
|
sections.add(section);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* <p>Writes the property set to an output stream.</p>
|
|
|
|
*
|
|
|
|
* @param out the output stream to write the section to
|
|
|
|
* @exception IOException if an error when writing to the output stream
|
|
|
|
* occurs
|
|
|
|
* @exception WritingNotSupportedException if HPSF does not yet support
|
|
|
|
* writing a property's variant type.
|
|
|
|
*/
|
|
|
|
public void write(final OutputStream out)
|
|
|
|
throws WritingNotSupportedException, IOException
|
|
|
|
{
|
|
|
|
/* Write the number of sections in this property set stream. */
|
|
|
|
final int nrSections = sections.size();
|
|
|
|
int length = 0;
|
|
|
|
|
|
|
|
/* Write the property set's header. */
|
|
|
|
length += TypeWriter.writeToStream(out, (short) getByteOrder());
|
|
|
|
length += TypeWriter.writeToStream(out, (short) getFormat());
|
|
|
|
length += TypeWriter.writeToStream(out, (int) getOSVersion());
|
|
|
|
length += TypeWriter.writeToStream(out, getClassID());
|
|
|
|
length += TypeWriter.writeToStream(out, (int) nrSections);
|
|
|
|
int offset = OFFSET_HEADER;
|
|
|
|
|
|
|
|
/* Write the section list, i.e. the references to the sections. Each
|
2003-09-04 16:15:24 -04:00
|
|
|
* entry in the section list consist of the section's class ID and the
|
|
|
|
* section's offset relative to the beginning of the stream. */
|
2003-08-30 05:13:53 -04:00
|
|
|
offset += nrSections * (ClassID.LENGTH + LittleEndian.INT_SIZE);
|
|
|
|
final int sectionsBegin = offset;
|
|
|
|
for (final ListIterator i = sections.listIterator(); i.hasNext();)
|
|
|
|
{
|
|
|
|
final MutableSection s = (MutableSection) i.next();
|
2003-09-04 16:15:24 -04:00
|
|
|
final ClassID formatID = s.getFormatID();
|
|
|
|
if (formatID == null)
|
|
|
|
throw new NoFormatIDException();
|
2003-08-30 05:13:53 -04:00
|
|
|
length += TypeWriter.writeToStream(out, s.getFormatID());
|
|
|
|
length += TypeWriter.writeUIntToStream(out, offset);
|
2004-08-31 16:47:09 -04:00
|
|
|
try
|
|
|
|
{
|
|
|
|
offset += s.getSize();
|
|
|
|
}
|
|
|
|
catch (HPSFRuntimeException ex)
|
|
|
|
{
|
|
|
|
final Throwable cause = ex.getReason();
|
|
|
|
if (cause instanceof UnsupportedEncodingException)
|
|
|
|
throw new IllegalPropertySetDataException(cause);
|
|
|
|
else
|
|
|
|
throw ex;
|
|
|
|
}
|
2003-08-30 05:13:53 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Write the sections themselves. */
|
|
|
|
offset = sectionsBegin;
|
|
|
|
for (final ListIterator i = sections.listIterator(); i.hasNext();)
|
|
|
|
{
|
|
|
|
final MutableSection s = (MutableSection) i.next();
|
2003-09-04 16:15:24 -04:00
|
|
|
offset += s.write(out);
|
2003-08-30 05:13:53 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-09-01 14:51:08 -04:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* <p>Returns the contents of this property set stream as an input stream.
|
|
|
|
* The latter can be used for example to write the property set into a POIFS
|
|
|
|
* document. The input stream represents a snapshot of the property set.
|
|
|
|
* If the latter is modified while the input stream is still being
|
|
|
|
* read, the modifications will not be reflected in the input stream but in
|
|
|
|
* the {@link MutablePropertySet} only.</p>
|
|
|
|
*
|
|
|
|
* @return the contents of this property set stream
|
|
|
|
*
|
|
|
|
* @throws WritingNotSupportedException if HPSF does not yet support writing
|
|
|
|
* of a property's variant type.
|
|
|
|
* @throws IOException if an I/O exception occurs.
|
|
|
|
*/
|
|
|
|
public InputStream toInputStream()
|
|
|
|
throws IOException, WritingNotSupportedException
|
|
|
|
{
|
|
|
|
final ByteArrayOutputStream psStream = new ByteArrayOutputStream();
|
|
|
|
write(psStream);
|
|
|
|
psStream.close();
|
|
|
|
final byte[] streamData = psStream.toByteArray();
|
|
|
|
return new ByteArrayInputStream(streamData);
|
|
|
|
}
|
|
|
|
|
2004-04-09 09:05:39 -04:00
|
|
|
}
|