/* * ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . */ package org.apache.poi.hpsf; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.LinkedList; import java.util.ListIterator; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndianConsts; /** *

Adds writing support to the {@link PropertySet} class.

* *

Please be aware that this class' functionality will be merged into the * {@link PropertySet} class at a later time, so the API will change.

* * @author Rainer Klute <klute@rainer-klute.de> * @version $Id$ * @since 2003-02-19 */ public class MutablePropertySet extends PropertySet { /** *

Constructs a MutablePropertySet instance. Its * primary task is to initialize the immutable field with their proper * values. It also sets fields that might change to reasonable defaults.

*/ 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()); } /** *

The length of the property set stream header.

*/ 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 */ /** *

Sets the "byteOrder" property.

* * @param byteOrder the byteOrder value to set */ public void setByteOrder(final int byteOrder) { this.byteOrder = byteOrder; } /** *

Sets the "format" property.

* * @param format the format value to set */ public void setFormat(final int format) { this.format = format; } /** *

Sets the "osVersion" property.

* * @param osVersion the osVersion value to set */ public void setOSVersion(final int osVersion) { this.osVersion = osVersion; } /** *

Sets the property set stream's low-level "class ID" * field.

* * @param classID The property set stream's low-level "class ID" field. * * @see #getClassID */ public void setClassID(final ClassID classID) { this.classID = classID; } /** *

Removes all sections from this property set.

*/ public void clearSections() { sections = null; } /** *

Adds a section to this property set.

* * @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); } /** *

Writes the property set to an output stream.

* * @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 * entry in the section list consist of a class ID and the offset to the * section's begin. */ 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(); length += TypeWriter.writeToStream(out, s.getFormatID()); length += TypeWriter.writeUIntToStream(out, offset); offset += s.getSize(); } /* Write the sections themselves. */ offset = sectionsBegin; for (final ListIterator i = sections.listIterator(); i.hasNext();) { final MutableSection s = (MutableSection) i.next(); offset = s.write(out, offset); } } /** *

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.

* * @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); } }