aboutsummaryrefslogtreecommitdiffstats
path: root/src/java
diff options
context:
space:
mode:
authorRainer Klute <klute@apache.org>2006-03-03 16:57:55 +0000
committerRainer Klute <klute@apache.org>2006-03-03 16:57:55 +0000
commit73a9af683f7c986421d12e07e680111d94a609c4 (patch)
treeb315b5320a537d72619cae55c393357f4737b5c0 /src/java
parenta36d020021bb41eade6d653005ef42f60a0a609a (diff)
downloadpoi-73a9af683f7c986421d12e07e680111d94a609c4.tar.gz
poi-73a9af683f7c986421d12e07e680111d94a609c4.zip
* Writing support added to the SummaryInformation and DocumentSummaryInformation classes. These classes now have methods for setting and removing properties. Coherent extensions are:
** Documentation section about writing standard properties added to the HPSF HOW-TO. ** Example application added showing how to modify the document summary information. ** Testcases added for testing modifying summary information and document summary information. ** PropertySetFactory extended to create SummaryInformation and DocumentSummaryInformation instances. * Added MutablePropertySet.write(DirectoryEntry, String) to ease writing a property set to a POI filesystem document. * Improved codepage handling. * Bug fixed: Integral values were read and written as unsigned instead of signed. * Reworked the mapping between variant types and Java types: Variant.VT_I4 is mapped to Integer now and Variant.VT_I8 to Long. This might cause incompatibilities if you are doing low-level HPSF programming. * Changed SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID from a byte[] to a byte[][] in order to contain the format ID of the first and the second section. This is an incompatible change! * Added PropertySet.getFirstSection(). This method is similar to getSingleSection() won't choke if the property set has more than one section. * Support for low-level reading and writing of Variant.VT_I8 type properties added. * Unnecessary casts removed. * Poibrowser's display format changed slightly. git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@382887 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java')
-rw-r--r--src/java/org/apache/poi/hpsf/ClassID.java1
-rw-r--r--src/java/org/apache/poi/hpsf/Constants.java16
-rw-r--r--src/java/org/apache/poi/hpsf/CustomProperties.java367
-rw-r--r--src/java/org/apache/poi/hpsf/CustomProperty.java123
-rw-r--r--src/java/org/apache/poi/hpsf/DocumentSummaryInformation.java468
-rw-r--r--src/java/org/apache/poi/hpsf/HPSFException.java11
-rw-r--r--src/java/org/apache/poi/hpsf/HPSFRuntimeException.java1
-rw-r--r--src/java/org/apache/poi/hpsf/IllegalPropertySetDataException.java1
-rw-r--r--src/java/org/apache/poi/hpsf/MarkUnsupportedException.java1
-rw-r--r--src/java/org/apache/poi/hpsf/MissingSectionException.java76
-rw-r--r--src/java/org/apache/poi/hpsf/MutablePropertySet.java38
-rw-r--r--src/java/org/apache/poi/hpsf/MutableSection.java146
-rw-r--r--src/java/org/apache/poi/hpsf/NoFormatIDException.java1
-rw-r--r--src/java/org/apache/poi/hpsf/NoSingleSectionException.java1
-rw-r--r--src/java/org/apache/poi/hpsf/Property.java29
-rw-r--r--src/java/org/apache/poi/hpsf/PropertySet.java37
-rw-r--r--src/java/org/apache/poi/hpsf/PropertySetFactory.java51
-rw-r--r--src/java/org/apache/poi/hpsf/ReadingNotSupportedException.java1
-rw-r--r--src/java/org/apache/poi/hpsf/Section.java27
-rw-r--r--src/java/org/apache/poi/hpsf/SpecialPropertySet.java200
-rw-r--r--src/java/org/apache/poi/hpsf/SummaryInformation.java637
-rw-r--r--src/java/org/apache/poi/hpsf/Thumbnail.java1
-rw-r--r--src/java/org/apache/poi/hpsf/TypeWriter.java36
-rw-r--r--src/java/org/apache/poi/hpsf/UnexpectedPropertySetTypeException.java1
-rw-r--r--src/java/org/apache/poi/hpsf/UnsupportedVariantTypeException.java2
-rw-r--r--src/java/org/apache/poi/hpsf/Util.java21
-rw-r--r--src/java/org/apache/poi/hpsf/Variant.java1
-rw-r--r--src/java/org/apache/poi/hpsf/VariantSupport.java44
-rw-r--r--src/java/org/apache/poi/hpsf/WritingNotSupportedException.java1
-rw-r--r--src/java/org/apache/poi/hpsf/wellknown/PropertyIDMap.java6
-rw-r--r--src/java/org/apache/poi/hpsf/wellknown/SectionIDMap.java34
-rw-r--r--src/java/org/apache/poi/util/LittleEndian.java29
32 files changed, 2138 insertions, 271 deletions
diff --git a/src/java/org/apache/poi/hpsf/ClassID.java b/src/java/org/apache/poi/hpsf/ClassID.java
index 0f8d12221b..766453f584 100644
--- a/src/java/org/apache/poi/hpsf/ClassID.java
+++ b/src/java/org/apache/poi/hpsf/ClassID.java
@@ -1,4 +1,3 @@
-
/* ====================================================================
Copyright 2002-2004 Apache Software Foundation
diff --git a/src/java/org/apache/poi/hpsf/Constants.java b/src/java/org/apache/poi/hpsf/Constants.java
index 3cd1138c5d..32a0addf20 100644
--- a/src/java/org/apache/poi/hpsf/Constants.java
+++ b/src/java/org/apache/poi/hpsf/Constants.java
@@ -1,3 +1,19 @@
+/* ====================================================================
+ Copyright 2002-2006 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.
+==================================================================== */
+
package org.apache.poi.hpsf;
/**
diff --git a/src/java/org/apache/poi/hpsf/CustomProperties.java b/src/java/org/apache/poi/hpsf/CustomProperties.java
new file mode 100644
index 0000000000..77f577d5ce
--- /dev/null
+++ b/src/java/org/apache/poi/hpsf/CustomProperties.java
@@ -0,0 +1,367 @@
+/* ====================================================================
+ Copyright 2002-2006 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.
+==================================================================== */
+
+package org.apache.poi.hpsf;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.poi.hpsf.wellknown.PropertyIDMap;
+
+/**
+ * <p>Maintains the instances of {@link CustomProperty} that belong to a
+ * {@link DocumentSummaryInformation}. The class maintains the names of the
+ * custom properties in a dictionary. It implements the {@link Map} interface
+ * and by this provides a simplified view on custom properties: A property's
+ * name is the key that maps to a typed value. This implementation hides
+ * property IDs from the developer and regards the property names as keys to
+ * typed values.</p>
+ *
+ * <p>While this class provides a simple API to custom properties, it ignores
+ * the fact that not names, but IDs are the real keys to properties. Under the
+ * hood this class maintains a 1:1 relationship between IDs and names. Therefore
+ * you should not use this class to process property sets with several IDs
+ * mapping to the same name or with properties without a name: the result will
+ * contain only a subset of the original properties. If you really need to deal
+ * such property sets, use HPSF's low-level access methods.</p>
+ *
+ * <p>An application can call the {@link #isPure} method to check whether a
+ * property set parsed by {@link CustomProperties} is still pure (i.e.
+ * unmodified) or whether one or more properties have been dropped.</p>
+ *
+ * <p>This class is not thread-safe; concurrent access to instances of this
+ * class must be syncronized.</p>
+ *
+ * @author Rainer Klute <a
+ * href="mailto:klute@rainer-klute.de">&lt;klute@rainer-klute.de&gt;</a>
+ * @since 2006-02-09
+ * @version $Id$
+ */
+public class CustomProperties extends HashMap
+{
+
+ /**
+ * <p>Maps property IDs to property names.</p>
+ */
+ private Map dictionaryIDToName = new HashMap();
+
+ /**
+ * <p>Maps property names to property IDs.</p>
+ */
+ private Map dictionaryNameToID = new HashMap();
+
+ /**
+ * <p>Tells whether this object is pure or not.</p>
+ */
+ private boolean isPure = true;
+
+
+
+ /**
+ * <p>Puts a {@link CustomProperty} into this map. It is assumed that the
+ * {@link CustomProperty} already has a valid ID. Otherwise use
+ * {@link #put(CustomProperty)}.</p>
+ */
+ public Object put(final Object name, final Object customProperty) throws ClassCastException
+ {
+ final CustomProperty cp = (CustomProperty) customProperty;
+ if (name == null)
+ {
+ /* Ignoring a property without a name. */
+ isPure = false;
+ return null;
+ }
+ if (!(name instanceof String))
+ throw new ClassCastException("The name of a custom property must " +
+ "be a java.lang.String, but it is a " +
+ name.getClass().getName());
+ if (!(name.equals(cp.getName())))
+ throw new IllegalArgumentException("Parameter \"name\" (" + name +
+ ") and custom property's name (" + cp.getName() +
+ ") do not match.");
+
+ /* Register name and ID in the dictionary. Mapping in both directions is possible. If there is already a */
+ final Long idKey = new Long(cp.getID());
+ final Object oldID = dictionaryNameToID.get(name);
+ dictionaryIDToName.remove(oldID);
+ dictionaryNameToID.put(name, idKey);
+ dictionaryIDToName.put(idKey, name);
+
+ /* Put the custom property into this map. */
+ final Object oldCp = super.remove(oldID);
+ super.put(idKey, cp);
+ return oldCp;
+ }
+
+
+
+ /**
+ * <p>Puts a {@link CustomProperty} that has not yet a valid ID into this
+ * map. The method will allocate a suitable ID for the custom property:</p>
+ *
+ * <ul>
+ *
+ * <li><p>If there is already a property with the same name, take the ID
+ * of that property.</p></li>
+ *
+ * <li><p>Otherwise find the highest ID and use its value plus one.</p></li>
+ *
+ * </ul>
+ *
+ * @param customProperty
+ * @return If the was already a property with the same name, the
+ * @throws ClassCastException
+ */
+ private Object put(final CustomProperty customProperty) throws ClassCastException
+ {
+ final String name = customProperty.getName();
+
+ /* Check whether a property with this name is in the map already. */
+ final Long oldId = (Long) dictionaryNameToID.get(name);
+ if (oldId != null)
+ customProperty.setID(oldId.longValue());
+ else
+ {
+ long max = 1;
+ for (final Iterator i = dictionaryIDToName.keySet().iterator(); i.hasNext();)
+ {
+ final long id = ((Long) i.next()).longValue();
+ if (id > max)
+ max = id;
+ }
+ customProperty.setID(max + 1);
+ }
+ return this.put(name, customProperty);
+ }
+
+
+
+ /**
+ * <p>Removes a custom property.</p>
+ * @param name The name of the custom property to remove
+ * @return The removed property or <code>null</code> if the specified property was not found.
+ *
+ * @see java.util.HashSet#remove(java.lang.Object)
+ */
+ public Object remove(final String name)
+ {
+ final Long id = (Long) dictionaryNameToID.get(name);
+ if (id == null)
+ return null;
+ dictionaryIDToName.remove(id);
+ dictionaryNameToID.remove(name);
+ return super.remove(id);
+ }
+
+ /**
+ * <p>Adds a named string property.</p>
+ *
+ * @param name The property's name.
+ * @param value The property's value.
+ * @return the property that was stored under the specified name before, or
+ * <code>null</code> if there was no such property before.
+ */
+ public Object put(final String name, final String value)
+ {
+ final MutableProperty p = new MutableProperty();
+ p.setID(-1);
+ p.setType(Variant.VT_LPWSTR);
+ p.setValue(value);
+ final CustomProperty cp = new CustomProperty(p, name);
+ return put(cp);
+ }
+
+ /**
+ * <p>Adds a named long property.</p>
+ *
+ * @param name The property's name.
+ * @param value The property's value.
+ * @return the property that was stored under the specified name before, or
+ * <code>null</code> if there was no such property before.
+ */
+ public Object put(final String name, final Long value)
+ {
+ final MutableProperty p = new MutableProperty();
+ p.setID(-1);
+ p.setType(Variant.VT_I8);
+ p.setValue(value);
+ final CustomProperty cp = new CustomProperty(p, name);
+ return put(cp);
+ }
+
+ /**
+ * <p>Adds a named double property.</p>
+ *
+ * @param name The property's name.
+ * @param value The property's value.
+ * @return the property that was stored under the specified name before, or
+ * <code>null</code> if there was no such property before.
+ */
+ public Object put(final String name, final Double value)
+ {
+ final MutableProperty p = new MutableProperty();
+ p.setID(-1);
+ p.setType(Variant.VT_R8);
+ p.setValue(value);
+ final CustomProperty cp = new CustomProperty(p, name);
+ return put(cp);
+ }
+
+ /**
+ * <p>Adds a named integer property.</p>
+ *
+ * @param name The property's name.
+ * @param value The property's value.
+ * @return the property that was stored under the specified name before, or
+ * <code>null</code> if there was no such property before.
+ */
+ public Object put(final String name, final Integer value)
+ {
+ final MutableProperty p = new MutableProperty();
+ p.setID(-1);
+ p.setType(Variant.VT_I4);
+ p.setValue(value);
+ final CustomProperty cp = new CustomProperty(p, name);
+ return put(cp);
+ }
+
+ /**
+ * <p>Adds a named boolean property.</p>
+ *
+ * @param name The property's name.
+ * @param value The property's value.
+ * @return the property that was stored under the specified name before, or
+ * <code>null</code> if there was no such property before.
+ */
+ public Object put(final String name, final Boolean value)
+ {
+ final MutableProperty p = new MutableProperty();
+ p.setID(-1);
+ p.setType(Variant.VT_BOOL);
+ p.setValue(value);
+ final CustomProperty cp = new CustomProperty(p, name);
+ return put(cp);
+ }
+
+
+ /**
+ * <p>Gets a named value from the custom properties.</p>
+ *
+ * @param name the name of the value to get
+ * @return the value or <code>null</code> if a value with the specified
+ * name is not found in the custom properties.
+ */
+ public Object get(final String name)
+ {
+ final Long id = (Long) dictionaryNameToID.get(name);
+ final CustomProperty cp = (CustomProperty) super.get(id);
+ return cp != null ? cp.getValue() : null;
+ }
+
+
+
+ /**
+ * <p>Adds a named date property.</p>
+ *
+ * @param name The property's name.
+ * @param value The property's value.
+ * @return the property that was stored under the specified name before, or
+ * <code>null</code> if there was no such property before.
+ */
+ public Object put(final String name, final Date value)
+ {
+ final MutableProperty p = new MutableProperty();
+ p.setID(-1);
+ p.setType(Variant.VT_FILETIME);
+ p.setValue(value);
+ final CustomProperty cp = new CustomProperty(p, name);
+ return put(cp);
+ }
+
+ /**
+ * <p>Sets the codepage.</p>
+ *
+ * @param codepage the codepage
+ */
+ public void setCodepage(final int codepage)
+ {
+ final MutableProperty p = new MutableProperty();
+ p.setID(PropertyIDMap.PID_CODEPAGE);
+ p.setType(Variant.VT_I2);
+ p.setValue(new Integer(codepage));
+ put(new CustomProperty(p));
+ }
+
+
+
+ /**
+ * <p>Gets the dictionary which contains IDs and names of the named custom
+ * properties.
+ *
+ * @return the dictionary.
+ */
+ Map getDictionary()
+ {
+ return dictionaryIDToName;
+ }
+
+
+
+ /**
+ * <p>Gets the codepage.</p>
+ *
+ * @return the codepage or -1 if the codepage is undefined.
+ */
+ public int getCodepage()
+ {
+ int codepage = -1;
+ for (final Iterator i = this.values().iterator(); codepage == -1 && i.hasNext();)
+ {
+ final CustomProperty cp = (CustomProperty) i.next();
+ if (cp.getID() == PropertyIDMap.PID_CODEPAGE)
+ codepage = ((Integer) cp.getValue()).intValue();
+ }
+ return codepage;
+ }
+
+
+
+ /**
+ * <p>Tells whether this {@link CustomProperties} instance is pure or one or
+ * more properties of the underlying low-level property set has been
+ * dropped.</p>
+ *
+ * @return <code>true</code> if the {@link CustomProperties} is pure, else
+ * <code>false</code>.
+ */
+ public boolean isPure()
+ {
+ return isPure;
+ }
+
+ /**
+ * <p>Sets the purity of the custom property set.</p>
+ *
+ * @param isPure the purity
+ */
+ public void setPure(final boolean isPure)
+ {
+ this.isPure = isPure;
+ }
+
+}
diff --git a/src/java/org/apache/poi/hpsf/CustomProperty.java b/src/java/org/apache/poi/hpsf/CustomProperty.java
new file mode 100644
index 0000000000..7c87e1f9a0
--- /dev/null
+++ b/src/java/org/apache/poi/hpsf/CustomProperty.java
@@ -0,0 +1,123 @@
+/* ====================================================================
+ Copyright 2002-2006 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.
+==================================================================== */
+
+package org.apache.poi.hpsf;
+
+/**
+ * <p>This class represents custum properties in the document summary
+ * information stream. The difference to normal properties is that custom
+ * properties have an optional name. If the name is not <code>null</code> it
+ * will be maintained in the section's dictionary.</p>
+ *
+ * @author Rainer Klute <a
+ * href="mailto:klute@rainer-klute.de">&lt;klute@rainer-klute.de&gt;</a>
+ * @since 2006-02-09
+ * @version $Id$
+ */
+public class CustomProperty extends MutableProperty
+{
+
+ private String name;
+
+ /**
+ * <p>Creates an empty {@link CustomProperty}. The set methods must be
+ * called to make it usable.</p>
+ */
+ public CustomProperty()
+ {
+ this.name = null;
+ }
+
+ /**
+ * <p>Creates a {@link CustomProperty} without a name by copying the
+ * underlying {@link Property}' attributes.</p>
+ *
+ * @param property the property to copy
+ */
+ public CustomProperty(final Property property)
+ {
+ this(property, null);
+ }
+
+ /**
+ * <p>Creates a {@link CustomProperty} with a name.</p>
+ *
+ * @param property This property's attributes are copied to the new custom
+ * property.
+ * @param name The new custom property's name.
+ */
+ public CustomProperty(final Property property, final String name)
+ {
+ super(property);
+ this.name = name;
+ }
+
+ /**
+ * <p>Gets the property's name.</p>
+ *
+ * @return the property's name.
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * <p>Sets the property's name.</p>
+ *
+ * @param name The name to set.
+ */
+ public void setName(final String name)
+ {
+ this.name = name;
+ }
+
+
+ /**
+ * <p>Compares two custom properties for equality. The method returns
+ * <code>true</code> if all attributes of the two custom properties are
+ * equal.</p>
+ *
+ * @param o The custom property to compare with.
+ * @return <code>true</code> if both custom properties are equal, else
+ * <code>false</code>.
+ *
+ * @see java.util.AbstractSet#equals(java.lang.Object)
+ */
+ public boolean equalsContents(final Object o)
+ {
+ final CustomProperty c = (CustomProperty) o;
+ final String name1 = c.getName();
+ final String name2 = this.getName();
+ boolean equalNames = true;
+ if (name1 == null)
+ equalNames = name2 == null;
+ else
+ equalNames = name1.equals(name2);
+ return equalNames && c.getID() == this.getID()
+ && c.getType() == this.getType()
+ && c.getValue().equals(this.getValue());
+ }
+
+ /**
+ * @see java.util.AbstractSet#hashCode()
+ */
+ public int hashCode()
+ {
+ return (int) this.getID();
+ }
+
+}
diff --git a/src/java/org/apache/poi/hpsf/DocumentSummaryInformation.java b/src/java/org/apache/poi/hpsf/DocumentSummaryInformation.java
index 21b1b2a9fe..1fce462d62 100644
--- a/src/java/org/apache/poi/hpsf/DocumentSummaryInformation.java
+++ b/src/java/org/apache/poi/hpsf/DocumentSummaryInformation.java
@@ -1,6 +1,5 @@
-
/* ====================================================================
- Copyright 2002-2004 Apache Software Foundation
+ Copyright 2002-2006 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.
@@ -17,11 +16,11 @@
package org.apache.poi.hpsf;
-import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.apache.poi.hpsf.wellknown.PropertyIDMap;
+import org.apache.poi.hpsf.wellknown.SectionIDMap;
/**
* <p>Convenience class representing a DocumentSummary Information stream in a
@@ -68,7 +67,7 @@ public class DocumentSummaryInformation extends SpecialPropertySet
/**
- * <p>Returns the stream's category (or <code>null</code>).</p>
+ * <p>Returns the category (or <code>null</code>).</p>
*
* @return The category value
*/
@@ -77,23 +76,63 @@ public class DocumentSummaryInformation extends SpecialPropertySet
return (String) getProperty(PropertyIDMap.PID_CATEGORY);
}
+ /**
+ * <p>Sets the category.</p>
+ *
+ * @param category The category to set.
+ */
+ public void setCategory(final String category)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_CATEGORY, category);
+ }
+
+ /**
+ * <p>Removes the category.</p>
+ */
+ public void removeCategory()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_CATEGORY);
+ }
+
/**
- * <p>Returns the stream's presentation format (or
+ * <p>Returns the presentation format (or
* <code>null</code>).</p>
*
- * @return The presentationFormat value
+ * @return The presentation format value
*/
public String getPresentationFormat()
{
return (String) getProperty(PropertyIDMap.PID_PRESFORMAT);
}
+ /**
+ * <p>Sets the presentation format.</p>
+ *
+ * @param presentationFormat The presentation format to set.
+ */
+ public void setPresentationFormat(final String presentationFormat)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_PRESFORMAT, presentationFormat);
+ }
+
+ /**
+ * <p>Removes the presentation format.</p>
+ */
+ public void removePresentationFormat()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_PRESFORMAT);
+ }
+
/**
- * <p>Returns the stream's byte count or 0 if the {@link
+ * <p>Returns the byte count or 0 if the {@link
* DocumentSummaryInformation} does not contain a byte count.</p>
*
* @return The byteCount value
@@ -103,86 +142,226 @@ public class DocumentSummaryInformation extends SpecialPropertySet
return getPropertyIntValue(PropertyIDMap.PID_BYTECOUNT);
}
+ /**
+ * <p>Sets the byte count.</p>
+ *
+ * @param byteCount The byte count to set.
+ */
+ public void setByteCount(final int byteCount)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_BYTECOUNT, byteCount);
+ }
+
+ /**
+ * <p>Removes the byte count.</p>
+ */
+ public void removeByteCount()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_BYTECOUNT);
+ }
+
/**
- * <p>Returns the stream's line count or 0 if the {@link
+ * <p>Returns the line count or 0 if the {@link
* DocumentSummaryInformation} does not contain a line count.</p>
*
- * @return The lineCount value
+ * @return The line count value
*/
public int getLineCount()
{
return getPropertyIntValue(PropertyIDMap.PID_LINECOUNT);
}
+ /**
+ * <p>Sets the line count.</p>
+ *
+ * @param lineCount The line count to set.
+ */
+ public void setLineCount(final int lineCount)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_LINECOUNT, lineCount);
+ }
+
+ /**
+ * <p>Removes the line count.</p>
+ */
+ public void removeLineCount()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_LINECOUNT);
+ }
+
/**
- * <p>Returns the stream's par count or 0 if the {@link
+ * <p>Returns the par count or 0 if the {@link
* DocumentSummaryInformation} does not contain a par count.</p>
*
- * @return The parCount value
+ * @return The par count value
*/
public int getParCount()
{
return getPropertyIntValue(PropertyIDMap.PID_PARCOUNT);
}
+ /**
+ * <p>Sets the par count.</p>
+ *
+ * @param parCount The par count to set.
+ */
+ public void setParCount(final int parCount)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_PARCOUNT, parCount);
+ }
+
+ /**
+ * <p>Removes the par count.</p>
+ */
+ public void removeParCount()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_PARCOUNT);
+ }
+
/**
- * <p>Returns the stream's slide count or 0 if the {@link
+ * <p>Returns the slide count or 0 if the {@link
* DocumentSummaryInformation} does not contain a slide count.</p>
*
- * @return The slideCount value
+ * @return The slide count value
*/
public int getSlideCount()
{
return getPropertyIntValue(PropertyIDMap.PID_SLIDECOUNT);
}
+ /**
+ * <p>Sets the slideCount.</p>
+ *
+ * @param slideCount The slide count to set.
+ */
+ public void setSlideCount(final int slideCount)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_SLIDECOUNT, slideCount);
+ }
+
+ /**
+ * <p>Removes the slide count.</p>
+ */
+ public void removeSlideCount()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_SLIDECOUNT);
+ }
+
/**
- * <p>Returns the stream's note count or 0 if the {@link
+ * <p>Returns the note count or 0 if the {@link
* DocumentSummaryInformation} does not contain a note count.</p>
*
- * @return The noteCount value
+ * @return The note count value
*/
public int getNoteCount()
{
return getPropertyIntValue(PropertyIDMap.PID_NOTECOUNT);
}
+ /**
+ * <p>Sets the note count.</p>
+ *
+ * @param noteCount The note count to set.
+ */
+ public void setNoteCount(final int noteCount)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_NOTECOUNT, noteCount);
+ }
+
+ /**
+ * <p>Removes the noteCount.</p>
+ */
+ public void removeNoteCount()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_NOTECOUNT);
+ }
+
/**
- * <p>Returns the stream's hidden count or 0 if the {@link
+ * <p>Returns the hidden count or 0 if the {@link
* DocumentSummaryInformation} does not contain a hidden
* count.</p>
*
- * @return The hiddenCount value
+ * @return The hidden count value
*/
public int getHiddenCount()
{
return getPropertyIntValue(PropertyIDMap.PID_HIDDENCOUNT);
}
+ /**
+ * <p>Sets the hidden count.</p>
+ *
+ * @param hiddenCount The hidden count to set.
+ */
+ public void setHiddenCount(final int hiddenCount)
+ {
+ final MutableSection s = (MutableSection) getSections().get(0);
+ s.setProperty(PropertyIDMap.PID_HIDDENCOUNT, hiddenCount);
+ }
+
+ /**
+ * <p>Removes the hidden count.</p>
+ */
+ public void removeHiddenCount()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_HIDDENCOUNT);
+ }
+
/**
- * <p>Returns the stream's mmclip count or 0 if the {@link
+ * <p>Returns the mmclip count or 0 if the {@link
* DocumentSummaryInformation} does not contain a mmclip
* count.</p>
*
- * @return The mMClipCount value
+ * @return The mmclip count value
*/
public int getMMClipCount()
{
return getPropertyIntValue(PropertyIDMap.PID_MMCLIPCOUNT);
}
+ /**
+ * <p>Sets the mmclip count.</p>
+ *
+ * @param mmClipCount The mmclip count to set.
+ */
+ public void setMMClipCount(final int mmClipCount)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_MMCLIPCOUNT, mmClipCount);
+ }
+
+ /**
+ * <p>Removes the mmclip count.</p>
+ */
+ public void removeMMClipCount()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_MMCLIPCOUNT);
+ }
+
/**
@@ -196,42 +375,100 @@ public class DocumentSummaryInformation extends SpecialPropertySet
return getPropertyBooleanValue(PropertyIDMap.PID_SCALE);
}
+ /**
+ * <p>Sets the scale.</p>
+ *
+ * @param scale The scale to set.
+ */
+ public void setScale(final boolean scale)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_SCALE, scale);
+ }
+
+ /**
+ * <p>Removes the scale.</p>
+ */
+ public void removeScale()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_SCALE);
+ }
+
/**
- * <p>Returns the stream's heading pair (or <code>null</code>)
+ * <p>Returns the heading pair (or <code>null</code>)
* <strong>when this method is implemented. Please note that the
* return type is likely to change!</strong>
*
- * @return The headingPair value
+ * @return The heading pair value
*/
public byte[] getHeadingPair()
{
- if (true)
- throw new UnsupportedOperationException("FIXME");
+ notYetImplemented("Reading byte arrays ");
return (byte[]) getProperty(PropertyIDMap.PID_HEADINGPAIR);
}
+ /**
+ * <p>Sets the heading pair.</p>
+ *
+ * @param headingPair The heading pair to set.
+ */
+ public void setHeadingPair(final byte[] headingPair)
+ {
+ notYetImplemented("Writing byte arrays ");
+ }
+
+ /**
+ * <p>Removes the heading pair.</p>
+ */
+ public void removeHeadingPair()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_HEADINGPAIR);
+ }
+
/**
- * <p>Returns the stream's doc parts (or <code>null</code>)
+ * <p>Returns the doc parts (or <code>null</code>)
* <strong>when this method is implemented. Please note that the
* return type is likely to change!</strong>
*
- * @return The docparts value
+ * @return The doc parts value
*/
public byte[] getDocparts()
{
- if (true)
- throw new UnsupportedOperationException("FIXME");
+ notYetImplemented("Reading byte arrays");
return (byte[]) getProperty(PropertyIDMap.PID_DOCPARTS);
}
/**
- * <p>Returns the stream's manager (or <code>null</code>).</p>
+ * <p>Sets the doc parts.</p>
+ *
+ * @param docparts The doc parts to set.
+ */
+ public void setDocparts(final byte[] docparts)
+ {
+ notYetImplemented("Writing byte arrays");
+ }
+
+ /**
+ * <p>Removes the doc parts.</p>
+ */
+ public void removeDocparts()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_DOCPARTS);
+ }
+
+
+
+ /**
+ * <p>Returns the manager (or <code>null</code>).</p>
*
* @return The manager value
*/
@@ -240,10 +477,30 @@ public class DocumentSummaryInformation extends SpecialPropertySet
return (String) getProperty(PropertyIDMap.PID_MANAGER);
}
+ /**
+ * <p>Sets the manager.</p>
+ *
+ * @param manager The manager to set.
+ */
+ public void setManager(final String manager)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_MANAGER, manager);
+ }
+
+ /**
+ * <p>Removes the manager.</p>
+ */
+ public void removeManager()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_MANAGER);
+ }
+
/**
- * <p>Returns the stream's company (or <code>null</code>).</p>
+ * <p>Returns the company (or <code>null</code>).</p>
*
* @return The company value
*/
@@ -252,47 +509,168 @@ public class DocumentSummaryInformation extends SpecialPropertySet
return (String) getProperty(PropertyIDMap.PID_COMPANY);
}
+ /**
+ * <p>Sets the company.</p>
+ *
+ * @param company The company to set.
+ */
+ public void setCompany(final String company)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_COMPANY, company);
+ }
+
+ /**
+ * <p>Removes the company.</p>
+ */
+ public void removeCompany()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_COMPANY);
+ }
+
/**
* <p>Returns <code>true</code> if the custom links are dirty.</p> <p>
*
- * @return The linksDirty value
+ * @return The links dirty value
*/
public boolean getLinksDirty()
{
return getPropertyBooleanValue(PropertyIDMap.PID_LINKSDIRTY);
}
+ /**
+ * <p>Sets the linksDirty.</p>
+ *
+ * @param linksDirty The links dirty value to set.
+ */
+ public void setLinksDirty(final boolean linksDirty)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_LINKSDIRTY, linksDirty);
+ }
+
+ /**
+ * <p>Removes the links dirty.</p>
+ */
+ public void removeLinksDirty()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_LINKSDIRTY);
+ }
+
/**
- * <p>Gets the custom properties as a map from the property name to
- * value.</p>
+ * <p>Gets the custom properties.</p>
*
- * @return The custom properties if any exist, <code>null</code> otherwise.
- * @since 2003-10-22
+ * @return The custom properties.
+ * @since 2006-02-09
*/
- public Map getCustomProperties()
+ public CustomProperties getCustomProperties()
{
- Map nameToValue = null;
+ CustomProperties cps = null;
if (getSectionCount() >= 2)
{
+ cps = new CustomProperties();
final Section section = (Section) getSections().get(1);
- final Map pidToName =
- (Map) section.getProperty(PropertyIDMap.PID_DICTIONARY);
- if (pidToName != null)
+ final Map dictionary = section.getDictionary();
+ final Property[] properties = section.getProperties();
+ int propertyCount = 0;
+ for (int i = 0; i < properties.length; i++)
{
- nameToValue = new HashMap(pidToName.size());
- for (Iterator i = pidToName.entrySet().iterator(); i.hasNext();)
+ final Property p = properties[i];
+ final long id = p.getID();
+ if (id != 0 && id != 1)
{
- final Map.Entry e = (Map.Entry) i.next();
- final long pid = ((Number) e.getKey()).longValue();
- nameToValue.put(e.getValue(), section.getProperty(pid));
+ propertyCount++;
+ final CustomProperty cp = new CustomProperty(p,
+ (String) dictionary.get(new Long(id)));
+ cps.put(cp.getName(), cp);
}
}
+ if (cps.size() != propertyCount)
+ cps.setPure(false);
+ }
+ return cps;
+ }
+
+ /**
+ * <p>Sets the custom properties.</p>
+ *
+ * @param customProperties The custom properties
+ * @since 2006-02-07
+ */
+ public void setCustomProperties(final CustomProperties customProperties)
+ {
+ ensureSection2();
+ final MutableSection section = (MutableSection) getSections().get(1);
+ final Map dictionary = customProperties.getDictionary();
+ section.clear();
+
+ /* Set the codepage. If both custom properties and section have a
+ * codepage, the codepage from the custom properties wins, else take the
+ * one that is defined. If none is defined, take Unicode. */
+ int cpCodepage = customProperties.getCodepage();
+ if (cpCodepage < 0)
+ cpCodepage = section.getCodepage();
+ if (cpCodepage < 0)
+ cpCodepage = Constants.CP_UNICODE;
+ customProperties.setCodepage(cpCodepage);
+ section.setCodepage(cpCodepage);
+ section.setDictionary(dictionary);
+ for (final Iterator i = customProperties.values().iterator(); i.hasNext();)
+ {
+ final Property p = (Property) i.next();
+ section.setProperty(p);
+ }
+ }
+
+
+
+ /**
+ * <p>Creates section 2 if it is not already present.</p>
+ *
+ */
+ private void ensureSection2()
+ {
+ if (getSectionCount() < 2)
+ {
+ MutableSection s2 = new MutableSection();
+ s2.setFormatID(SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID[1]);
+ addSection(s2);
}
- return nameToValue;
+ }
+
+
+
+ /**
+ * <p>Removes the custom properties.</p>
+ *
+ * @since 2006-02-08
+ */
+ public void removeCustomProperties()
+ {
+ if (getSectionCount() >= 2)
+ getSections().remove(1);
+ else
+ throw new HPSFRuntimeException("Illegal internal format of Document SummaryInformation stream: second section is missing.");
+ }
+
+
+
+ /**
+ * <p>Throws an {@link UnsupportedOperationException} with a message text
+ * telling which functionality is not yet implemented.</p>
+ *
+ * @param msg text telling was leaves to be implemented, e.g.
+ * "Reading byte arrays".
+ */
+ private void notYetImplemented(final String msg)
+ {
+ throw new UnsupportedOperationException(msg + " is not yet implemented.");
}
}
diff --git a/src/java/org/apache/poi/hpsf/HPSFException.java b/src/java/org/apache/poi/hpsf/HPSFException.java
index ed6aa4ea44..7588be679e 100644
--- a/src/java/org/apache/poi/hpsf/HPSFException.java
+++ b/src/java/org/apache/poi/hpsf/HPSFException.java
@@ -1,4 +1,3 @@
-
/* ====================================================================
Copyright 2002-2004 Apache Software Foundation
@@ -18,12 +17,12 @@
package org.apache.poi.hpsf;
/**
- * <p>This exception is the superclass of all other checked exceptions
- * thrown in this package. It supports a nested "reason" throwable,
- * i.e. an exception that caused this one to be thrown.</p>
- *
+ * <p>This exception is the superclass of all other checked exceptions thrown
+ * in this package. It supports a nested "reason" throwable, i.e. an exception
+ * that caused this one to be thrown.</p>
+ *
* @author Rainer Klute <a
- * href="mailto:klute@rainer-klute.de">&lt;klute@rainer-klute.de&gt;</a>
+ * href="mailto:klute@rainer-klute.de">&lt;klute@rainer-klute.de&gt;</a>
* @version $Id$
* @since 2002-02-09
*/
diff --git a/src/java/org/apache/poi/hpsf/HPSFRuntimeException.java b/src/java/org/apache/poi/hpsf/HPSFRuntimeException.java
index 57c1a68f84..b997226bb1 100644
--- a/src/java/org/apache/poi/hpsf/HPSFRuntimeException.java
+++ b/src/java/org/apache/poi/hpsf/HPSFRuntimeException.java
@@ -1,4 +1,3 @@
-
/* ====================================================================
Copyright 2002-2004 Apache Software Foundation
diff --git a/src/java/org/apache/poi/hpsf/IllegalPropertySetDataException.java b/src/java/org/apache/poi/hpsf/IllegalPropertySetDataException.java
index a0ad11df71..6e2b06d5ba 100644
--- a/src/java/org/apache/poi/hpsf/IllegalPropertySetDataException.java
+++ b/src/java/org/apache/poi/hpsf/IllegalPropertySetDataException.java
@@ -1,4 +1,3 @@
-
/* ====================================================================
Copyright 2002-2004 Apache Software Foundation
diff --git a/src/java/org/apache/poi/hpsf/MarkUnsupportedException.java b/src/java/org/apache/poi/hpsf/MarkUnsupportedException.java
index ced098c323..a03c1738b8 100644
--- a/src/java/org/apache/poi/hpsf/MarkUnsupportedException.java
+++ b/src/java/org/apache/poi/hpsf/MarkUnsupportedException.java
@@ -1,4 +1,3 @@
-
/* ====================================================================
Copyright 2002-2004 Apache Software Foundation
diff --git a/src/java/org/apache/poi/hpsf/MissingSectionException.java b/src/java/org/apache/poi/hpsf/MissingSectionException.java
new file mode 100644
index 0000000000..76aba80bd8
--- /dev/null
+++ b/src/java/org/apache/poi/hpsf/MissingSectionException.java
@@ -0,0 +1,76 @@
+/* ====================================================================
+ Copyright 2002-2006 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.
+==================================================================== */
+
+package org.apache.poi.hpsf;
+
+/**
+ * <p>This exception is thrown if one of the {@link PropertySet}'s
+ * convenience methods does not find a required {@link Section}.</p>
+ *
+ * <p>The constructors of this class are analogous to those of its
+ * superclass and documented there.</p>
+ *
+ * @author Rainer Klute <a
+ * href="mailto:klute@rainer-klute.de">&lt;klute@rainer-klute.de&gt;</a>
+ * @version $Id: NoSingleSectionException.java 353545 2004-04-09 13:05:39Z glens $
+ * @since 2006-02-08
+ */
+public class MissingSectionException extends HPSFRuntimeException
+{
+
+ /**
+ * <p>Constructor</p>
+ */
+ public MissingSectionException()
+ {
+ super();
+ }
+
+
+ /**
+ * <p>Constructor</p>
+ *
+ * @param msg The exception's message string
+ */
+ public MissingSectionException(final String msg)
+ {
+ super(msg);
+ }
+
+
+ /**
+ * <p>Constructor</p>
+ *
+ * @param reason This exception's underlying reason
+ */
+ public MissingSectionException(final Throwable reason)
+ {
+ super(reason);
+ }
+
+
+ /**
+ * <p>Constructor</p>
+ *
+ * @param msg The exception's message string
+ * @param reason This exception's underlying reason
+ */
+ public MissingSectionException(final String msg, final Throwable reason)
+ {
+ super(msg, reason);
+ }
+
+}
diff --git a/src/java/org/apache/poi/hpsf/MutablePropertySet.java b/src/java/org/apache/poi/hpsf/MutablePropertySet.java
index d1dccf2949..bff912be3f 100644
--- a/src/java/org/apache/poi/hpsf/MutablePropertySet.java
+++ b/src/java/org/apache/poi/hpsf/MutablePropertySet.java
@@ -1,5 +1,5 @@
/* ====================================================================
- Copyright 2002-2004 Apache Software Foundation
+ Copyright 2002-2006 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.
@@ -18,6 +18,7 @@ package org.apache.poi.hpsf;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -26,6 +27,8 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;
+import org.apache.poi.poifs.filesystem.DirectoryEntry;
+import org.apache.poi.poifs.filesystem.Entry;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianConsts;
@@ -151,7 +154,7 @@ public class MutablePropertySet extends PropertySet
*
* @param classID The property set stream's low-level "class ID" field.
*
- * @see #getClassID
+ * @see PropertySet#getClassID()
*/
public void setClassID(final ClassID classID)
{
@@ -205,9 +208,9 @@ public class MutablePropertySet extends PropertySet
/* 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, getOSVersion());
length += TypeWriter.writeToStream(out, getClassID());
- length += TypeWriter.writeToStream(out, (int) nrSections);
+ length += TypeWriter.writeToStream(out, nrSections);
int offset = OFFSET_HEADER;
/* Write the section list, i.e. the references to the sections. Each
@@ -272,4 +275,31 @@ public class MutablePropertySet extends PropertySet
return new ByteArrayInputStream(streamData);
}
+ /**
+ * <p>Writes a property set to a document in a POI filesystem directory.</p>
+ *
+ * @param dir The directory in the POI filesystem to write the document to.
+ * @param name The document's name. If there is already a document with the
+ * same name in the directory the latter will be overwritten.
+ *
+ * @throws WritingNotSupportedException
+ * @throws IOException
+ */
+ public void write(final DirectoryEntry dir, final String name)
+ throws WritingNotSupportedException, IOException
+ {
+ /* If there is already an entry with the same name, remove it. */
+ try
+ {
+ final Entry e = dir.getEntry(name);
+ e.delete();
+ }
+ catch (FileNotFoundException ex)
+ {
+ /* Entry not found, no need to remove it. */
+ }
+ /* Create the new entry. */
+ dir.createDocument(name, toInputStream());
+ }
+
}
diff --git a/src/java/org/apache/poi/hpsf/MutableSection.java b/src/java/org/apache/poi/hpsf/MutableSection.java
index 6d6c1b11e9..96928051ab 100644
--- a/src/java/org/apache/poi/hpsf/MutableSection.java
+++ b/src/java/org/apache/poi/hpsf/MutableSection.java
@@ -1,5 +1,5 @@
/* ====================================================================
- Copyright 2002-2004 Apache Software Foundation
+ Copyright 2002-2006 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.
@@ -21,6 +21,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.Collections;
import java.util.Comparator;
+import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@@ -107,7 +108,7 @@ public class MutableSection extends Section
* @param formatID The section's format ID
*
* @see #setFormatID(byte[])
- * @see #getFormatID
+ * @see Section#getFormatID
*/
public void setFormatID(final ClassID formatID)
{
@@ -123,7 +124,7 @@ public class MutableSection extends Section
* are in big-endian format.
*
* @see #setFormatID(ClassID)
- * @see #getFormatID
+ * @see Section#getFormatID
*/
public void setFormatID(final byte[] formatID)
{
@@ -155,10 +156,7 @@ public class MutableSection extends Section
/**
- * <p>Sets the value of the property with the specified ID. If a
- * property with this ID is not yet present in the section, it
- * will be added. An already present property with the specified
- * ID will be overwritten.</p>
+ * <p>Sets the string value of the property with the specified ID.</p>
*
* @param id The property's ID
* @param value The property's value. It will be written as a Unicode
@@ -176,6 +174,57 @@ public class MutableSection extends Section
/**
+ * <p>Sets the int value of the property with the specified ID.</p>
+ *
+ * @param id The property's ID
+ * @param value The property's value.
+ *
+ * @see #setProperty(int, long, Object)
+ * @see #getProperty
+ */
+ public void setProperty(final int id, final int value)
+ {
+ setProperty(id, Variant.VT_I4, new Integer(value));
+ dirty = true;
+ }
+
+
+
+ /**
+ * <p>Sets the long value of the property with the specified ID.</p>
+ *
+ * @param id The property's ID
+ * @param value The property's value.
+ *
+ * @see #setProperty(int, long, Object)
+ * @see #getProperty
+ */
+ public void setProperty(final int id, final long value)
+ {
+ setProperty(id, Variant.VT_I8, new Long(value));
+ dirty = true;
+ }
+
+
+
+ /**
+ * <p>Sets the boolean value of the property with the specified ID.</p>
+ *
+ * @param id The property's ID
+ * @param value The property's value.
+ *
+ * @see #setProperty(int, long, Object)
+ * @see #getProperty
+ */
+ public void setProperty(final int id, final boolean value)
+ {
+ setProperty(id, Variant.VT_BOOL, new Boolean(value));
+ dirty = true;
+ }
+
+
+
+ /**
* <p>Sets the value and the variant type of the property with the
* specified ID. If a property with this ID is not yet present in
* the section, it will be added. An already present property with
@@ -204,15 +253,11 @@ public class MutableSection extends Section
/**
- * <p>Sets a property. If a property with the same ID is not yet present in
- * the section, the property will be added to the section. If there is
- * already a property with the same ID present in the section, it will be
- * overwritten.</p>
+ * <p>Sets a property.</p>
*
- * @param p The property to be added to the section
+ * @param p The property to be set.
*
* @see #setProperty(int, long, Object)
- * @see #setProperty(int, String)
* @see #getProperty
* @see Variant
*/
@@ -257,7 +302,7 @@ public class MutableSection extends Section
*/
protected void setPropertyBooleanValue(final int id, final boolean value)
{
- setProperty(id, (long) Variant.VT_BOOL, new Boolean(value));
+ setProperty(id, Variant.VT_BOOL, new Boolean(value));
}
@@ -296,6 +341,8 @@ public class MutableSection extends Section
* properties) and the properties themselves.</p>
*
* @return the section's length in bytes.
+ * @throws WritingNotSupportedException
+ * @throws IOException
*/
private int calcSize() throws WritingNotSupportedException, IOException
{
@@ -372,7 +419,7 @@ public class MutableSection extends Section
/* Warning: The codepage property is not set although a
* dictionary is present. In order to cope with this problem we
* add the codepage property and set it to Unicode. */
- setProperty(PropertyIDMap.PID_CODEPAGE, (long) Variant.VT_I2,
+ setProperty(PropertyIDMap.PID_CODEPAGE, Variant.VT_I2,
new Integer(Constants.CP_UNICODE));
codepage = getCodepage();
}
@@ -474,16 +521,15 @@ public class MutableSection extends Section
sLength++;
length += TypeWriter.writeUIntToStream(out, key.longValue());
length += TypeWriter.writeUIntToStream(out, sLength);
- final char[] ca = value.toCharArray();
- for (int j = 0; j < ca.length; j++)
+ final byte[] ca =
+ value.getBytes(VariantSupport.codepageToEncoding(codepage));
+ for (int j = 2; j < ca.length; j += 2)
{
- int high = (ca[j] & 0x0ff00) >> 8;
- int low = (ca[j] & 0x000ff);
- out.write(low);
- out.write(high);
+ out.write(ca[j+1]);
+ out.write(ca[j]);
length += 2;
- sLength--;
}
+ sLength -= value.length();
while (sLength > 0)
{
out.write(0x00);
@@ -610,4 +656,60 @@ public class MutableSection extends Section
removeProperty(PropertyIDMap.PID_DICTIONARY);
}
+
+
+ /**
+ * <p>Sets a property.</p>
+ *
+ * @param id The property ID.
+ * @param value The property's value. The value's class must be one of those
+ * supported by HPSF.
+ */
+ public void setProperty(final int id, final Object value)
+ {
+ if (value instanceof String)
+ setProperty(id, (String) value);
+ else if (value instanceof Long)
+ setProperty(id, ((Long) value).longValue());
+ else if (value instanceof Integer)
+ setProperty(id, ((Integer) value).intValue());
+ else if (value instanceof Short)
+ setProperty(id, ((Short) value).intValue());
+ else if (value instanceof Boolean)
+ setProperty(id, ((Boolean) value).booleanValue());
+ else if (value instanceof Date)
+ setProperty(id, Variant.VT_FILETIME, value);
+ else
+ throw new HPSFRuntimeException(
+ "HPSF does not support properties of type " +
+ value.getClass().getName() + ".");
+ }
+
+
+
+ /**
+ * <p>Removes all properties from the section including 0 (dictionary) and
+ * 1 (codepage).</p>
+ */
+ public void clear()
+ {
+ final Property[] properties = getProperties();
+ for (int i = 0; i < properties.length; i++)
+ {
+ final Property p = properties[i];
+ removeProperty(p.getID());
+ }
+ }
+
+ /**
+ * <p>Sets the codepage.</p>
+ *
+ * @param codepage the codepage
+ */
+ public void setCodepage(final int codepage)
+ {
+ setProperty(PropertyIDMap.PID_CODEPAGE, Variant.VT_I2,
+ new Integer(codepage));
+ }
+
}
diff --git a/src/java/org/apache/poi/hpsf/NoFormatIDException.java b/src/java/org/apache/poi/hpsf/NoFormatIDException.java
index 661189d7b7..4bcdf3311c 100644
--- a/src/java/org/apache/poi/hpsf/NoFormatIDException.java
+++ b/src/java/org/apache/poi/hpsf/NoFormatIDException.java
@@ -1,4 +1,3 @@
-
/* ====================================================================
Copyright 2002-2004 Apache Software Foundation
diff --git a/src/java/org/apache/poi/hpsf/NoSingleSectionException.java b/src/java/org/apache/poi/hpsf/NoSingleSectionException.java
index 9e5de03ab3..7cdf0d2d97 100644
--- a/src/java/org/apache/poi/hpsf/NoSingleSectionException.java
+++ b/src/java/org/apache/poi/hpsf/NoSingleSectionException.java
@@ -1,4 +1,3 @@
-
/* ====================================================================
Copyright 2002-2004 Apache Software Foundation
diff --git a/src/java/org/apache/poi/hpsf/Property.java b/src/java/org/apache/poi/hpsf/Property.java
index 81c346b815..e27b8beb35 100644
--- a/src/java/org/apache/poi/hpsf/Property.java
+++ b/src/java/org/apache/poi/hpsf/Property.java
@@ -1,5 +1,5 @@
/* ====================================================================
- Copyright 2002-2004 Apache Software Foundation
+ Copyright 2002-2006 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.
@@ -108,6 +108,22 @@ public class Property
/**
+ * <p>Creates a property.</p>
+ *
+ * @param id the property's ID.
+ * @param type the property's type, see {@link Variant}.
+ * @param value the property's value. Only certain types are allowed, see {@link Variant}.
+ */
+ public Property(final long id, final long type, final Object value)
+ {
+ this.id = id;
+ this.type = type;
+ this.value = value;
+ }
+
+
+
+ /**
* <p>Creates a {@link Property} instance by reading its bytes
* from the property set stream.</p>
*
@@ -222,12 +238,15 @@ public class Property
{
/* The length is the number of characters, i.e. the number
* of bytes is twice the number of the characters. */
- for (int j = 0; j < sLength; j++)
+ final int nrBytes = (int) (sLength * 2);
+ final byte[] h = new byte[nrBytes];
+ for (int i2 = 0; i2 < nrBytes; i2 += 2)
{
- final int i1 = o + (j * 2);
- final int i2 = i1 + 1;
- b.append((char) ((src[i2] << 8) + src[i1]));
+ h[i2] = src[o + i2 + 1];
+ h[i2 + 1] = src[o + i2];
}
+ b.append(new String(h, 0, nrBytes,
+ VariantSupport.codepageToEncoding(codepage)));
break;
}
default:
diff --git a/src/java/org/apache/poi/hpsf/PropertySet.java b/src/java/org/apache/poi/hpsf/PropertySet.java
index 134df3564b..821acf2d40 100644
--- a/src/java/org/apache/poi/hpsf/PropertySet.java
+++ b/src/java/org/apache/poi/hpsf/PropertySet.java
@@ -1,6 +1,5 @@
-
/* ====================================================================
- Copyright 2002-2004 Apache Software Foundation
+ Copyright 2002-2006 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.
@@ -402,8 +401,10 @@ public class PropertySet
*
* @param src Byte array containing the property set stream
* @param offset The property set stream starts at this offset
- * from the beginning of <var>src</src>
+ * from the beginning of <var>src</var>
* @param length Length of the property set stream.
+ * @throws UnsupportedEncodingException if HPSF does not (yet) support the
+ * property set's character encoding.
*/
private void init(final byte[] src, final int offset, final int length)
throws UnsupportedEncodingException
@@ -482,7 +483,7 @@ public class PropertySet
public boolean isDocumentSummaryInformation()
{
return Util.equal(((Section) sections.get(0)).getFormatID().getBytes(),
- SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID);
+ SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID[0]);
}
@@ -492,9 +493,7 @@ public class PropertySet
* 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}. However, it can only be used if the {@link
- * PropertySet} contains exactly one {@link Section}, so check
- * {@link #getSectionCount} first!</p>
+ * Section}.</p>
*
* @return The properties of the only {@link Section} of this
* {@link PropertySet}.
@@ -504,7 +503,7 @@ public class PropertySet
public Property[] getProperties()
throws NoSingleSectionException
{
- return getSingleSection().getProperties();
+ return getFirstSection().getProperties();
}
@@ -522,7 +521,7 @@ public class PropertySet
*/
protected Object getProperty(final int id) throws NoSingleSectionException
{
- return getSingleSection().getProperty(id);
+ return getFirstSection().getProperty(id);
}
@@ -543,7 +542,7 @@ public class PropertySet
protected boolean getPropertyBooleanValue(final int id)
throws NoSingleSectionException
{
- return getSingleSection().getPropertyBooleanValue(id);
+ return getFirstSection().getPropertyBooleanValue(id);
}
@@ -563,7 +562,7 @@ public class PropertySet
protected int getPropertyIntValue(final int id)
throws NoSingleSectionException
{
- return getSingleSection().getPropertyIntValue(id);
+ return getFirstSection().getPropertyIntValue(id);
}
@@ -585,7 +584,21 @@ public class PropertySet
*/
public boolean wasNull() throws NoSingleSectionException
{
- return getSingleSection().wasNull();
+ return getFirstSection().wasNull();
+ }
+
+
+
+ /**
+ * <p>Gets the {@link PropertySet}'s first section.</p>
+ *
+ * @return The {@link PropertySet}'s first section.
+ */
+ public Section getFirstSection()
+ {
+ if (getSectionCount() < 1)
+ throw new MissingSectionException("Property set does not contain any sections.");
+ return ((Section) sections.get(0));
}
diff --git a/src/java/org/apache/poi/hpsf/PropertySetFactory.java b/src/java/org/apache/poi/hpsf/PropertySetFactory.java
index e7b9576792..0a93982043 100644
--- a/src/java/org/apache/poi/hpsf/PropertySetFactory.java
+++ b/src/java/org/apache/poi/hpsf/PropertySetFactory.java
@@ -1,6 +1,5 @@
-
/* ====================================================================
- Copyright 2002-2004 Apache Software Foundation
+ Copyright 2002-2006 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.
@@ -22,6 +21,8 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.rmi.UnexpectedException;
+import org.apache.poi.hpsf.wellknown.SectionIDMap;
+
/**
* <p>Factory class to create instances of {@link SummaryInformation},
* {@link DocumentSummaryInformation} and {@link PropertySet}.</p>
@@ -74,4 +75,50 @@ public class PropertySetFactory
}
}
+
+
+ /**
+ * <p>Creates a new summary information.</p>
+ *
+ * @return the new summary information.
+ */
+ public static SummaryInformation newSummaryInformation()
+ {
+ final MutablePropertySet ps = new MutablePropertySet();
+ final MutableSection s = (MutableSection) ps.getFirstSection();
+ s.setFormatID(SectionIDMap.SUMMARY_INFORMATION_ID);
+ try
+ {
+ return new SummaryInformation(ps);
+ }
+ catch (UnexpectedPropertySetTypeException ex)
+ {
+ /* This should never happen. */
+ throw new HPSFRuntimeException(ex);
+ }
+ }
+
+
+
+ /**
+ * <p>Creates a new document summary information.</p>
+ *
+ * @return the new document summary information.
+ */
+ public static DocumentSummaryInformation newDocumentSummaryInformation()
+ {
+ final MutablePropertySet ps = new MutablePropertySet();
+ final MutableSection s = (MutableSection) ps.getFirstSection();
+ s.setFormatID(SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID[0]);
+ try
+ {
+ return new DocumentSummaryInformation(ps);
+ }
+ catch (UnexpectedPropertySetTypeException ex)
+ {
+ /* This should never happen. */
+ throw new HPSFRuntimeException(ex);
+ }
+ }
+
}
diff --git a/src/java/org/apache/poi/hpsf/ReadingNotSupportedException.java b/src/java/org/apache/poi/hpsf/ReadingNotSupportedException.java
index a6a97f1ee7..c7fed7fd0c 100644
--- a/src/java/org/apache/poi/hpsf/ReadingNotSupportedException.java
+++ b/src/java/org/apache/poi/hpsf/ReadingNotSupportedException.java
@@ -1,4 +1,3 @@
-
/* ====================================================================
Copyright 2002-2004 Apache Software Foundation
diff --git a/src/java/org/apache/poi/hpsf/Section.java b/src/java/org/apache/poi/hpsf/Section.java
index 913fc9116b..ee28158107 100644
--- a/src/java/org/apache/poi/hpsf/Section.java
+++ b/src/java/org/apache/poi/hpsf/Section.java
@@ -1,6 +1,5 @@
-
/* ====================================================================
- Copyright 2002-2004 Apache Software Foundation
+ Copyright 2002-2006 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.
@@ -278,9 +277,12 @@ public class Section
for (final Iterator i = propertyList.iterator(); i.hasNext();)
{
ple = (PropertyListEntry) i.next();
- properties[i1++] = new Property(ple.id, src,
- this.offset + ple.offset,
- ple.length, codepage);
+ Property p = new Property(ple.id, src,
+ this.offset + ple.offset,
+ ple.length, codepage);
+ if (p.getID() == PropertyIDMap.PID_CODEPAGE)
+ p = new Property(p.getID(), p.getType(), new Integer(codepage));
+ properties[i1++] = p;
}
/*
@@ -359,15 +361,15 @@ public class Section
*/
protected int getPropertyIntValue(final long id)
{
- final Long i;
+ final Number i;
final Object o = getProperty(id);
if (o == null)
return 0;
- if (!(o instanceof Long))
+ if (!(o instanceof Long || o instanceof Integer))
throw new HPSFRuntimeException
("This property is not an integer type, but " +
o.getClass().getName() + ".");
- i = (Long) o;
+ i = (Number) o;
return i.intValue();
}
@@ -545,6 +547,10 @@ public class Section
/**
* <p>Removes a field from a property array. The resulting array is
* compactified and returned.</p>
+ *
+ * @param pa The property array.
+ * @param i The index of the field to be removed.
+ * @return the compactified array.
*/
private Property[] remove(final Property[] pa, final int i)
{
@@ -629,7 +635,10 @@ public class Section
{
final Integer codepage =
(Integer) getProperty(PropertyIDMap.PID_CODEPAGE);
- return codepage != null ? codepage.intValue() : -1;
+ if (codepage == null)
+ return -1;
+ int cp = codepage.intValue();
+ return cp;
}
}
diff --git a/src/java/org/apache/poi/hpsf/SpecialPropertySet.java b/src/java/org/apache/poi/hpsf/SpecialPropertySet.java
index d114e41abf..e65de3c11b 100644
--- a/src/java/org/apache/poi/hpsf/SpecialPropertySet.java
+++ b/src/java/org/apache/poi/hpsf/SpecialPropertySet.java
@@ -1,6 +1,5 @@
-
/* ====================================================================
- Copyright 2002-2004 Apache Software Foundation
+ Copyright 2002-2006 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.
@@ -17,8 +16,13 @@
package org.apache.poi.hpsf;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.util.List;
+import org.apache.poi.poifs.filesystem.DirectoryEntry;
+
/**
* <p>Abstract superclass for the convenience classes {@link
* SummaryInformation} and {@link DocumentSummaryInformation}.</p>
@@ -50,25 +54,38 @@ import java.util.List;
* @version $Id$
* @since 2002-02-09
*/
-public abstract class SpecialPropertySet extends PropertySet
+public abstract class SpecialPropertySet extends MutablePropertySet
{
/**
* <p>The "real" property set <code>SpecialPropertySet</code>
* delegates to.</p>
*/
- private PropertySet delegate;
+ private MutablePropertySet delegate;
/**
* <p>Creates a <code>SpecialPropertySet</code>.
*
- * @param ps The property set encapsulated by the
+ * @param ps The property set to be encapsulated by the
* <code>SpecialPropertySet</code>
*/
public SpecialPropertySet(final PropertySet ps)
{
+ delegate = new MutablePropertySet(ps);
+ }
+
+
+
+ /**
+ * <p>Creates a <code>SpecialPropertySet</code>.
+ *
+ * @param ps The mutable property set to be encapsulated by the
+ * <code>SpecialPropertySet</code>
+ */
+ public SpecialPropertySet(final MutablePropertySet ps)
+ {
delegate = ps;
}
@@ -157,9 +174,178 @@ public abstract class SpecialPropertySet extends PropertySet
/**
* @see PropertySet#getSingleSection
*/
- public Section getSingleSection()
+ public Section getFirstSection()
+ {
+ return delegate.getFirstSection();
+ }
+
+
+ /**
+ * @see org.apache.poi.hpsf.MutablePropertySet#addSection(org.apache.poi.hpsf.Section)
+ */
+ public void addSection(final Section section)
+ {
+ delegate.addSection(section);
+ }
+
+
+
+ /**
+ * @see org.apache.poi.hpsf.MutablePropertySet#clearSections()
+ */
+ public void clearSections()
+ {
+ delegate.clearSections();
+ }
+
+
+
+ /**
+ * @see org.apache.poi.hpsf.MutablePropertySet#setByteOrder(int)
+ */
+ public void setByteOrder(final int byteOrder)
+ {
+ delegate.setByteOrder(byteOrder);
+ }
+
+
+
+ /**
+ * @see org.apache.poi.hpsf.MutablePropertySet#setClassID(org.apache.poi.hpsf.ClassID)
+ */
+ public void setClassID(final ClassID classID)
+ {
+ delegate.setClassID(classID);
+ }
+
+
+
+ /**
+ * @see org.apache.poi.hpsf.MutablePropertySet#setFormat(int)
+ */
+ public void setFormat(final int format)
+ {
+ delegate.setFormat(format);
+ }
+
+
+
+ /**
+ * @see org.apache.poi.hpsf.MutablePropertySet#setOSVersion(int)
+ */
+ public void setOSVersion(final int osVersion)
+ {
+ delegate.setOSVersion(osVersion);
+ }
+
+
+
+ /**
+ * @see org.apache.poi.hpsf.MutablePropertySet#toInputStream()
+ */
+ public InputStream toInputStream() throws IOException, WritingNotSupportedException
+ {
+ return delegate.toInputStream();
+ }
+
+
+
+ /**
+ * @see org.apache.poi.hpsf.MutablePropertySet#write(org.apache.poi.poifs.filesystem.DirectoryEntry, java.lang.String)
+ */
+ public void write(final DirectoryEntry dir, final String name) throws WritingNotSupportedException, IOException
+ {
+ delegate.write(dir, name);
+ }
+
+
+
+ /**
+ * @see org.apache.poi.hpsf.MutablePropertySet#write(java.io.OutputStream)
+ */
+ public void write(final OutputStream out) throws WritingNotSupportedException, IOException
+ {
+ delegate.write(out);
+ }
+
+
+
+ /**
+ * @see org.apache.poi.hpsf.PropertySet#equals(java.lang.Object)
+ */
+ public boolean equals(final Object o)
+ {
+ return delegate.equals(o);
+ }
+
+
+
+ /**
+ * @see org.apache.poi.hpsf.PropertySet#getProperties()
+ */
+ public Property[] getProperties() throws NoSingleSectionException
+ {
+ return delegate.getProperties();
+ }
+
+
+
+ /**
+ * @see org.apache.poi.hpsf.PropertySet#getProperty(int)
+ */
+ protected Object getProperty(final int id) throws NoSingleSectionException
+ {
+ return delegate.getProperty(id);
+ }
+
+
+
+ /**
+ * @see org.apache.poi.hpsf.PropertySet#getPropertyBooleanValue(int)
+ */
+ protected boolean getPropertyBooleanValue(final int id) throws NoSingleSectionException
+ {
+ return delegate.getPropertyBooleanValue(id);
+ }
+
+
+
+ /**
+ * @see org.apache.poi.hpsf.PropertySet#getPropertyIntValue(int)
+ */
+ protected int getPropertyIntValue(final int id) throws NoSingleSectionException
+ {
+ return delegate.getPropertyIntValue(id);
+ }
+
+
+
+ /**
+ * @see org.apache.poi.hpsf.PropertySet#hashCode()
+ */
+ public int hashCode()
+ {
+ return delegate.hashCode();
+ }
+
+
+
+ /**
+ * @see org.apache.poi.hpsf.PropertySet#toString()
+ */
+ public String toString()
+ {
+ return delegate.toString();
+ }
+
+
+
+ /**
+ * @see org.apache.poi.hpsf.PropertySet#wasNull()
+ */
+ public boolean wasNull() throws NoSingleSectionException
{
- return delegate.getSingleSection();
+ return delegate.wasNull();
}
}
diff --git a/src/java/org/apache/poi/hpsf/SummaryInformation.java b/src/java/org/apache/poi/hpsf/SummaryInformation.java
index a170225df0..7a4941448e 100644
--- a/src/java/org/apache/poi/hpsf/SummaryInformation.java
+++ b/src/java/org/apache/poi/hpsf/SummaryInformation.java
@@ -1,31 +1,33 @@
+/*
+ * ====================================================================
+ * Copyright 2002-2006 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.
+ * ====================================================================
+ */
-/* ====================================================================
- 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.
-==================================================================== */
-
package org.apache.poi.hpsf;
import java.util.Date;
+
import org.apache.poi.hpsf.wellknown.PropertyIDMap;
/**
* <p>Convenience class representing a Summary Information stream in a
* Microsoft Office document.</p>
- *
+ *
* @author Rainer Klute <a
- * href="mailto:klute@rainer-klute.de">&lt;klute@rainer-klute.de&gt;</a>
+ * href="mailto:klute@rainer-klute.de">&lt;klute@rainer-klute.de&gt;</a>
* @see DocumentSummaryInformation
* @version $Id$
* @since 2002-02-09
@@ -34,8 +36,8 @@ public class SummaryInformation extends SpecialPropertySet
{
/**
- * <p>The document name a summary information stream usually has
- * in a POIFS filesystem.</p>
+ * <p>The document name a summary information stream usually has in a POIFS
+ * filesystem.</p>
*/
public static final String DEFAULT_STREAM_NAME = "\005SummaryInformation";
@@ -44,26 +46,26 @@ public class SummaryInformation extends SpecialPropertySet
/**
* <p>Creates a {@link SummaryInformation} from a given {@link
* PropertySet}.</p>
- *
+ *
* @param ps A property set which should be created from a summary
- * information stream.
- * @throws UnexpectedPropertySetTypeException if <var>ps</var>
- * does not contain a summary information stream.
+ * information stream.
+ * @throws UnexpectedPropertySetTypeException if <var>ps</var> does not
+ * contain a summary information stream.
*/
public SummaryInformation(final PropertySet ps)
- throws UnexpectedPropertySetTypeException
+ throws UnexpectedPropertySetTypeException
{
super(ps);
if (!isSummaryInformation())
- throw new UnexpectedPropertySetTypeException
- ("Not a " + getClass().getName());
+ throw new UnexpectedPropertySetTypeException("Not a "
+ + getClass().getName());
}
/**
- * <p>Returns the stream's title (or <code>null</code>).</p>
- *
+ * <p>Returns the title (or <code>null</code>).</p>
+ *
* @return The title or <code>null</code>
*/
public String getTitle()
@@ -74,8 +76,32 @@ public class SummaryInformation extends SpecialPropertySet
/**
- * <p>Returns the stream's subject (or <code>null</code>).</p>
- *
+ * <p>Sets the title.</p>
+ *
+ * @param title The title to set.
+ */
+ public void setTitle(final String title)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_TITLE, title);
+ }
+
+
+
+ /**
+ * <p>Removes the title.</p>
+ */
+ public void removeTitle()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_TITLE);
+ }
+
+
+
+ /**
+ * <p>Returns the subject (or <code>null</code>).</p>
+ *
* @return The subject or <code>null</code>
*/
public String getSubject()
@@ -86,8 +112,32 @@ public class SummaryInformation extends SpecialPropertySet
/**
- * <p>Returns the stream's author (or <code>null</code>).</p>
- *
+ * <p>Sets the subject.</p>
+ *
+ * @param subject The subject to set.
+ */
+ public void setSubject(final String subject)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_SUBJECT, subject);
+ }
+
+
+
+ /**
+ * <p>Removes the subject.</p>
+ */
+ public void removeSubject()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_SUBJECT);
+ }
+
+
+
+ /**
+ * <p>Returns the author (or <code>null</code>).</p>
+ *
* @return The author or <code>null</code>
*/
public String getAuthor()
@@ -98,8 +148,32 @@ public class SummaryInformation extends SpecialPropertySet
/**
- * <p>Returns the stream's keywords (or <code>null</code>).</p>
- *
+ * <p>Sets the author.</p>
+ *
+ * @param author The author to set.
+ */
+ public void setAuthor(final String author)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_AUTHOR, author);
+ }
+
+
+
+ /**
+ * <p>Removes the author.</p>
+ */
+ public void removeAuthor()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_AUTHOR);
+ }
+
+
+
+ /**
+ * <p>Returns the keywords (or <code>null</code>).</p>
+ *
* @return The keywords or <code>null</code>
*/
public String getKeywords()
@@ -110,8 +184,32 @@ public class SummaryInformation extends SpecialPropertySet
/**
- * <p>Returns the stream's comments (or <code>null</code>).</p>
- *
+ * <p>Sets the keywords.</p>
+ *
+ * @param keywords The keywords to set.
+ */
+ public void setKeywords(final String keywords)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_KEYWORDS, keywords);
+ }
+
+
+
+ /**
+ * <p>Removes the keywords.</p>
+ */
+ public void removeKeywords()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_KEYWORDS);
+ }
+
+
+
+ /**
+ * <p>Returns the comments (or <code>null</code>).</p>
+ *
* @return The comments or <code>null</code>
*/
public String getComments()
@@ -122,8 +220,32 @@ public class SummaryInformation extends SpecialPropertySet
/**
- * <p>Returns the stream's template (or <code>null</code>).</p>
- *
+ * <p>Sets the comments.</p>
+ *
+ * @param comments The comments to set.
+ */
+ public void setComments(final String comments)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_COMMENTS, comments);
+ }
+
+
+
+ /**
+ * <p>Removes the comments.</p>
+ */
+ public void removeComments()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_COMMENTS);
+ }
+
+
+
+ /**
+ * <p>Returns the template (or <code>null</code>).</p>
+ *
* @return The template or <code>null</code>
*/
public String getTemplate()
@@ -134,8 +256,32 @@ public class SummaryInformation extends SpecialPropertySet
/**
- * <p>Returns the stream's last author (or <code>null</code>).</p>
- *
+ * <p>Sets the template.</p>
+ *
+ * @param template The template to set.
+ */
+ public void setTemplate(final String template)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_TEMPLATE, template);
+ }
+
+
+
+ /**
+ * <p>Removes the template.</p>
+ */
+ public void removeTemplate()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_TEMPLATE);
+ }
+
+
+
+ /**
+ * <p>Returns the last author (or <code>null</code>).</p>
+ *
* @return The last author or <code>null</code>
*/
public String getLastAuthor()
@@ -146,9 +292,32 @@ public class SummaryInformation extends SpecialPropertySet
/**
- * <p>Returns the stream's revision number (or
- * <code>null</code>). </p>
- *
+ * <p>Sets the last author.</p>
+ *
+ * @param lastAuthor The last author to set.
+ */
+ public void setLastAuthor(final String lastAuthor)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_LASTAUTHOR, lastAuthor);
+ }
+
+
+
+ /**
+ * <p>Removes the last author.</p>
+ */
+ public void removeLastAuthor()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_LASTAUTHOR);
+ }
+
+
+
+ /**
+ * <p>Returns the revision number (or <code>null</code>). </p>
+ *
* @return The revision number or <code>null</code>
*/
public String getRevNumber()
@@ -159,11 +328,35 @@ public class SummaryInformation extends SpecialPropertySet
/**
- * <p>Returns the total time spent in editing the document
- * (or <code>0</code>).</p>
- *
+ * <p>Sets the revision number.</p>
+ *
+ * @param revNumber The revision number to set.
+ */
+ public void setRevNumber(final String revNumber)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_REVNUMBER, revNumber);
+ }
+
+
+
+ /**
+ * <p>Removes the revision number.</p>
+ */
+ public void removeRevNumber()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_REVNUMBER);
+ }
+
+
+
+ /**
+ * <p>Returns the total time spent in editing the document (or
+ * <code>0</code>).</p>
+ *
* @return The total time spent in editing the document or 0 if the {@link
- * SummaryInformation} does not contain this information.
+ * SummaryInformation} does not contain this information.
*/
public long getEditTime()
{
@@ -177,9 +370,33 @@ public class SummaryInformation extends SpecialPropertySet
/**
- * <p>Returns the stream's last printed time (or
- * <code>null</code>).</p>
- *
+ * <p>Sets the total time spent in editing the document.</p>
+ *
+ * @param time The time to set.
+ */
+ public void setEditTime(final long time)
+ {
+ final Date d = Util.filetimeToDate(time);
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_EDITTIME, Variant.VT_FILETIME, d);
+ }
+
+
+
+ /**
+ * <p>Remove the total time spent in editing the document.</p>
+ */
+ public void removeEditTime()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_EDITTIME);
+ }
+
+
+
+ /**
+ * <p>Returns the last printed time (or <code>null</code>).</p>
+ *
* @return The last printed time or <code>null</code>
*/
public Date getLastPrinted()
@@ -190,9 +407,33 @@ public class SummaryInformation extends SpecialPropertySet
/**
- * <p>Returns the stream's creation time (or
- * <code>null</code>).</p>
- *
+ * <p>Sets the lastPrinted.</p>
+ *
+ * @param lastPrinted The lastPrinted to set.
+ */
+ public void setLastPrinted(final Date lastPrinted)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_LASTPRINTED, Variant.VT_FILETIME,
+ lastPrinted);
+ }
+
+
+
+ /**
+ * <p>Removes the lastPrinted.</p>
+ */
+ public void removeLastPrinted()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_LASTPRINTED);
+ }
+
+
+
+ /**
+ * <p>Returns the creation time (or <code>null</code>).</p>
+ *
* @return The creation time or <code>null</code>
*/
public Date getCreateDateTime()
@@ -203,9 +444,33 @@ public class SummaryInformation extends SpecialPropertySet
/**
- * <p>Returns the stream's last save time (or
- * <code>null</code>).</p>
- *
+ * <p>Sets the creation time.</p>
+ *
+ * @param createDateTime The creation time to set.
+ */
+ public void setCreateDateTime(final Date createDateTime)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_CREATE_DTM, Variant.VT_FILETIME,
+ createDateTime);
+ }
+
+
+
+ /**
+ * <p>Removes the creation time.</p>
+ */
+ public void removeCreateDateTime()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_CREATE_DTM);
+ }
+
+
+
+ /**
+ * <p>Returns the last save time (or <code>null</code>).</p>
+ *
* @return The last save time or <code>null</code>
*/
public Date getLastSaveDateTime()
@@ -216,11 +481,37 @@ public class SummaryInformation extends SpecialPropertySet
/**
- * <p>Returns the stream's page count or 0 if the {@link
- * SummaryInformation} does not contain a page count.</p>
- *
+ * <p>Sets the total time spent in editing the document.</p>
+ *
+ * @param time The time to set.
+ */
+ public void setLastSaveDateTime(final Date time)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s
+ .setProperty(PropertyIDMap.PID_LASTSAVE_DTM,
+ Variant.VT_FILETIME, time);
+ }
+
+
+
+ /**
+ * <p>Remove the total time spent in editing the document.</p>
+ */
+ public void removeLastSaveDateTime()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_LASTSAVE_DTM);
+ }
+
+
+
+ /**
+ * <p>Returns the page count or 0 if the {@link SummaryInformation} does
+ * not contain a page count.</p>
+ *
* @return The page count or 0 if the {@link SummaryInformation} does not
- * contain a page count.
+ * contain a page count.
*/
public int getPageCount()
{
@@ -230,9 +521,33 @@ public class SummaryInformation extends SpecialPropertySet
/**
- * <p>Returns the stream's word count or 0 if the {@link
- * SummaryInformation} does not contain a word count.</p>
- *
+ * <p>Sets the page count.</p>
+ *
+ * @param pageCount The page count to set.
+ */
+ public void setPageCount(final int pageCount)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_PAGECOUNT, pageCount);
+ }
+
+
+
+ /**
+ * <p>Removes the page count.</p>
+ */
+ public void removePageCount()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_PAGECOUNT);
+ }
+
+
+
+ /**
+ * <p>Returns the word count or 0 if the {@link SummaryInformation} does
+ * not contain a word count.</p>
+ *
* @return The word count or <code>null</code>
*/
public int getWordCount()
@@ -243,9 +558,33 @@ public class SummaryInformation extends SpecialPropertySet
/**
- * <p>Returns the stream's character count or 0 if the {@link
- * SummaryInformation} does not contain a char count.</p>
- *
+ * <p>Sets the word count.</p>
+ *
+ * @param wordCount The word count to set.
+ */
+ public void setWordCount(final int wordCount)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_WORDCOUNT, wordCount);
+ }
+
+
+
+ /**
+ * <p>Removes the word count.</p>
+ */
+ public void removeWordCount()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_WORDCOUNT);
+ }
+
+
+
+ /**
+ * <p>Returns the character count or 0 if the {@link SummaryInformation}
+ * does not contain a char count.</p>
+ *
* @return The character count or <code>null</code>
*/
public int getCharCount()
@@ -256,15 +595,39 @@ public class SummaryInformation extends SpecialPropertySet
/**
- * <p>Returns the stream's thumbnail (or <code>null</code>)
- * <strong>when this method is implemented. Please note that the
- * return type is likely to change!</strong></p>
- *
- * <p><strong>Hint to developers:</strong> Drew Varner &lt;Drew.Varner -at-
- * sc.edu&gt; said that this is an image in WMF or Clipboard (BMP?) format.
- * However, we won't do any conversion into any image type but instead just
- * return a byte array.</p>
- *
+ * <p>Sets the character count.</p>
+ *
+ * @param charCount The character count to set.
+ */
+ public void setCharCount(final int charCount)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_CHARCOUNT, charCount);
+ }
+
+
+
+ /**
+ * <p>Removes the character count.</p>
+ */
+ public void removeCharCount()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_CHARCOUNT);
+ }
+
+
+
+ /**
+ * <p>Returns the thumbnail (or <code>null</code>) <strong>when this
+ * method is implemented. Please note that the return type is likely to
+ * change!</strong></p>
+ *
+ * <p><strong>Hint to developers:</strong> Drew Varner &lt;Drew.Varner
+ * -at- sc.edu&gt; said that this is an image in WMF or Clipboard (BMP?)
+ * format. However, we won't do any conversion into any image type but
+ * instead just return a byte array.</p>
+ *
* @return The thumbnail or <code>null</code>
*/
public byte[] getThumbnail()
@@ -275,9 +638,33 @@ public class SummaryInformation extends SpecialPropertySet
/**
- * <p>Returns the stream's application name (or
- * <code>null</code>).</p>
- *
+ * <p>Sets the thumbnail.</p>
+ *
+ * @param thumbnail The thumbnail to set.
+ */
+ public void setThumbnail(final byte[] thumbnail)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_THUMBNAIL, /* FIXME: */
+ Variant.VT_LPSTR, thumbnail);
+ }
+
+
+
+ /**
+ * <p>Removes the thumbnail.</p>
+ */
+ public void removeThumbnail()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_THUMBNAIL);
+ }
+
+
+
+ /**
+ * <p>Returns the application name (or <code>null</code>).</p>
+ *
* @return The application name or <code>null</code>
*/
public String getApplicationName()
@@ -288,35 +675,49 @@ public class SummaryInformation extends SpecialPropertySet
/**
- * <p>Returns a security code which is one of the following
- * values:</p>
- *
+ * <p>Sets the application name.</p>
+ *
+ * @param applicationName The application name to set.
+ */
+ public void setApplicationName(final String applicationName)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_APPNAME, applicationName);
+ }
+
+
+
+ /**
+ * <p>Removes the application name.</p>
+ */
+ public void removeApplicationName()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_APPNAME);
+ }
+
+
+
+ /**
+ * <p>Returns a security code which is one of the following values:</p>
+ *
* <ul>
- * <li>
- * <p>0 if the {@link SummaryInformation} does not contain a
- * security field or if there is no security on the
- * document. Use {@link #wasNull} to distinguish between the
- * two cases!</p>
- * </li>
- *
- * <li>
- * <p>1 if the document is password protected</p>
- * </li>
- *
- * <li>
- * <p>2 if the document is read-only recommended</p>
- * </li>
- *
- * <li>
- * <p>4 if the document is read-only enforced</p>
- * </li>
- *
- * <li>
- * <p>8 if the document is locked for annotations</p>
- * </li>
- *
+ *
+ * <li><p>0 if the {@link SummaryInformation} does not contain a
+ * security field or if there is no security on the document. Use
+ * {@link PropertySet#wasNull()} to distinguish between the two
+ * cases!</p></li>
+ *
+ * <li><p>1 if the document is password protected</p></li>
+ *
+ * <li><p>2 if the document is read-only recommended</p></li>
+ *
+ * <li><p>4 if the document is read-only enforced</p></li>
+ *
+ * <li><p>8 if the document is locked for annotations</p></li>
+ *
* </ul>
- *
+ *
* @return The security code or <code>null</code>
*/
public int getSecurity()
@@ -324,4 +725,28 @@ public class SummaryInformation extends SpecialPropertySet
return getPropertyIntValue(PropertyIDMap.PID_SECURITY);
}
+
+
+ /**
+ * <p>Sets the security code.</p>
+ *
+ * @param security The security code to set.
+ */
+ public void setSecurity(final int security)
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.setProperty(PropertyIDMap.PID_SECURITY, security);
+ }
+
+
+
+ /**
+ * <p>Removes the security code.</p>
+ */
+ public void removeSecurity()
+ {
+ final MutableSection s = (MutableSection) getFirstSection();
+ s.removeProperty(PropertyIDMap.PID_SECURITY);
+ }
+
}
diff --git a/src/java/org/apache/poi/hpsf/Thumbnail.java b/src/java/org/apache/poi/hpsf/Thumbnail.java
index fd168822a8..14d1a0f3f7 100644
--- a/src/java/org/apache/poi/hpsf/Thumbnail.java
+++ b/src/java/org/apache/poi/hpsf/Thumbnail.java
@@ -1,4 +1,3 @@
-
/* ====================================================================
Copyright 2002-2004 Apache Software Foundation
diff --git a/src/java/org/apache/poi/hpsf/TypeWriter.java b/src/java/org/apache/poi/hpsf/TypeWriter.java
index c88e98d07b..acfcfa6c34 100644
--- a/src/java/org/apache/poi/hpsf/TypeWriter.java
+++ b/src/java/org/apache/poi/hpsf/TypeWriter.java
@@ -1,6 +1,5 @@
-
/* ====================================================================
- Copyright 2002-2004 Apache Software Foundation
+ Copyright 2002-2006 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.
@@ -46,7 +45,7 @@ public class TypeWriter
{
final int length = LittleEndian.SHORT_SIZE;
byte[] buffer = new byte[length];
- LittleEndian.putUShort(buffer, 0, n);
+ LittleEndian.putShort(buffer, 0, n); // FIXME: unsigned
out.write(buffer, 0, length);
return length;
}
@@ -75,6 +74,27 @@ public class TypeWriter
/**
+ * <p>Writes a eight-byte value to an output stream.</p>
+ *
+ * @param out The stream to write to.
+ * @param n The value to write.
+ * @exception IOException if an I/O error occurs
+ * @return The number of bytes written to the output stream.
+ */
+ public static int writeToStream(final OutputStream out, final long n)
+ throws IOException
+ {
+ final int l = LittleEndian.LONG_SIZE;
+ final byte[] buffer = new byte[l];
+ LittleEndian.putLong(buffer, 0, n);
+ out.write(buffer, 0, l);
+ return l;
+
+ }
+
+
+
+ /**
* <p>Writes an unsigned two-byte value to an output stream.</p>
*
* @param out The stream to write to
@@ -118,6 +138,7 @@ public class TypeWriter
*
* @param out The stream to write to
* @param n The value to write
+ * @return The number of bytes written
* @exception IOException if an I/O error occurs
*/
public static int writeToStream(final OutputStream out, final ClassID n)
@@ -134,10 +155,13 @@ public class TypeWriter
/**
* <p>Writes an array of {@link Property} instances to an output stream
* according to the Horrible Property Stream Format.</p>
- *
+ *
* @param out The stream to write to
* @param properties The array to write to the stream
+ * @param codepage The codepage number to use for writing strings
* @exception IOException if an I/O error occurs
+ * @throws UnsupportedVariantTypeException if HPSF does not support some
+ * variant type.
*/
public static void writeToStream(final OutputStream out,
final Property[] properties,
@@ -152,7 +176,7 @@ public class TypeWriter
* ID and offset into the stream. */
for (int i = 0; i < properties.length; i++)
{
- final Property p = (Property) properties[i];
+ final Property p = properties[i];
writeUIntToStream(out, p.getID());
writeUIntToStream(out, p.getSize());
}
@@ -160,7 +184,7 @@ public class TypeWriter
/* Write the properties themselves. */
for (int i = 0; i < properties.length; i++)
{
- final Property p = (Property) properties[i];
+ final Property p = properties[i];
long type = p.getType();
writeUIntToStream(out, type);
VariantSupport.write(out, (int) type, p.getValue(), codepage);
diff --git a/src/java/org/apache/poi/hpsf/UnexpectedPropertySetTypeException.java b/src/java/org/apache/poi/hpsf/UnexpectedPropertySetTypeException.java
index 02a47b1986..4f0aa8a9e2 100644
--- a/src/java/org/apache/poi/hpsf/UnexpectedPropertySetTypeException.java
+++ b/src/java/org/apache/poi/hpsf/UnexpectedPropertySetTypeException.java
@@ -1,4 +1,3 @@
-
/* ====================================================================
Copyright 2002-2004 Apache Software Foundation
diff --git a/src/java/org/apache/poi/hpsf/UnsupportedVariantTypeException.java b/src/java/org/apache/poi/hpsf/UnsupportedVariantTypeException.java
index 8503fdfb03..9cdf1805bd 100644
--- a/src/java/org/apache/poi/hpsf/UnsupportedVariantTypeException.java
+++ b/src/java/org/apache/poi/hpsf/UnsupportedVariantTypeException.java
@@ -21,7 +21,7 @@ import org.apache.poi.util.HexDump;
/**
* <p>This exception is thrown if HPSF encounters a variant type that isn't
* supported yet. Although a variant type is unsupported the value can still be
- * retrieved using the {@link #getValue} method.</p>
+ * retrieved using the {@link VariantTypeException#getValue} method.</p>
*
* <p>Obviously this class should disappear some day.</p>
*
diff --git a/src/java/org/apache/poi/hpsf/Util.java b/src/java/org/apache/poi/hpsf/Util.java
index 60e9e9b9d3..d58e254256 100644
--- a/src/java/org/apache/poi/hpsf/Util.java
+++ b/src/java/org/apache/poi/hpsf/Util.java
@@ -1,6 +1,5 @@
-
/* ====================================================================
- Copyright 2002-2004 Apache Software Foundation
+ Copyright 2002-2006 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.
@@ -152,6 +151,21 @@ public class Util
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);
@@ -165,7 +179,8 @@ public class Util
* @param date The date to be converted
* @return The filetime
*
- * @see #filetimeToDate
+ * @see #filetimeToDate(long)
+ * @see #filetimeToDate(int, int)
*/
public static long dateToFileTime(final Date date)
{
diff --git a/src/java/org/apache/poi/hpsf/Variant.java b/src/java/org/apache/poi/hpsf/Variant.java
index 7b300bc0e1..a64b05b661 100644
--- a/src/java/org/apache/poi/hpsf/Variant.java
+++ b/src/java/org/apache/poi/hpsf/Variant.java
@@ -1,4 +1,3 @@
-
/* ====================================================================
Copyright 2002-2004 Apache Software Foundation
diff --git a/src/java/org/apache/poi/hpsf/VariantSupport.java b/src/java/org/apache/poi/hpsf/VariantSupport.java
index 703f925de1..8994bb2fa1 100644
--- a/src/java/org/apache/poi/hpsf/VariantSupport.java
+++ b/src/java/org/apache/poi/hpsf/VariantSupport.java
@@ -1,5 +1,5 @@
/* ====================================================================
- Copyright 2002-2004 Apache Software Foundation
+ Copyright 2002-2006 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.
@@ -157,16 +157,25 @@ public class VariantSupport extends Variant
* Read a short. In Java it is represented as an
* Integer object.
*/
- value = new Integer(LittleEndian.getUShort(src, o1));
+ value = new Integer(LittleEndian.getShort(src, o1));
break;
}
case Variant.VT_I4:
{
/*
- * Read a word. In Java it is represented as a
+ * Read a word. In Java it is represented as an
+ * Integer object.
+ */
+ value = new Integer(LittleEndian.getInt(src, o1));
+ break;
+ }
+ case Variant.VT_I8:
+ {
+ /*
+ * Read a double word. In Java it is represented as a
* Long object.
*/
- value = new Long(LittleEndian.getUInt(src, o1));
+ value = new Long(LittleEndian.getLong(src, o1));
break;
}
case Variant.VT_R8:
@@ -204,9 +213,9 @@ public class VariantSupport extends Variant
last--;
final int l = (int) (last - first + 1);
value = codepage != -1 ?
- new String(src, (int) first, l,
+ new String(src, first, l,
codepageToEncoding(codepage)) :
- new String(src, (int) first, l);
+ new String(src, first, l);
break;
}
case Variant.VT_LPWSTR:
@@ -240,7 +249,7 @@ public class VariantSupport extends Variant
{
final byte[] v = new byte[l1];
for (int i = 0; i < l1; i++)
- v[i] = src[(int) (o1 + i)];
+ v[i] = src[(o1 + i)];
value = v;
break;
}
@@ -263,7 +272,7 @@ public class VariantSupport extends Variant
{
final byte[] v = new byte[l1];
for (int i = 0; i < l1; i++)
- v[i] = src[(int) (o1 + i)];
+ v[i] = src[(o1 + i)];
throw new ReadingNotSupportedException(type, v);
}
}
@@ -397,8 +406,8 @@ public class VariantSupport extends Variant
char[] s = Util.pad4((String) value);
for (int i = 0; i < s.length; i++)
{
- final int high = (int) ((s[i] & 0x0000ff00) >> 8);
- final int low = (int) (s[i] & 0x000000ff);
+ final int high = ((s[i] & 0x0000ff00) >> 8);
+ final int low = (s[i] & 0x000000ff);
final byte highb = (byte) high;
final byte lowb = (byte) low;
out.write(lowb);
@@ -431,8 +440,21 @@ public class VariantSupport extends Variant
}
case Variant.VT_I4:
{
+ if (!(value instanceof Integer))
+ {
+ throw new ClassCastException("Could not cast an object to "
+ + Integer.class.toString() + ": "
+ + value.getClass().toString() + ", "
+ + value.toString());
+ }
length += TypeWriter.writeToStream(out,
- ((Long) value).intValue());
+ ((Integer) value).intValue());
+ break;
+ }
+ case Variant.VT_I8:
+ {
+ TypeWriter.writeToStream(out, ((Long) value).longValue());
+ length = LittleEndianConsts.LONG_SIZE;
break;
}
case Variant.VT_R8:
diff --git a/src/java/org/apache/poi/hpsf/WritingNotSupportedException.java b/src/java/org/apache/poi/hpsf/WritingNotSupportedException.java
index 64e955a703..f35b5c6070 100644
--- a/src/java/org/apache/poi/hpsf/WritingNotSupportedException.java
+++ b/src/java/org/apache/poi/hpsf/WritingNotSupportedException.java
@@ -1,4 +1,3 @@
-
/* ====================================================================
Copyright 2002-2004 Apache Software Foundation
diff --git a/src/java/org/apache/poi/hpsf/wellknown/PropertyIDMap.java b/src/java/org/apache/poi/hpsf/wellknown/PropertyIDMap.java
index 77a17b5224..517af3b1ed 100644
--- a/src/java/org/apache/poi/hpsf/wellknown/PropertyIDMap.java
+++ b/src/java/org/apache/poi/hpsf/wellknown/PropertyIDMap.java
@@ -1,4 +1,3 @@
-
/* ====================================================================
Copyright 2002-2004 Apache Software Foundation
@@ -231,6 +230,11 @@ public class PropertyIDMap extends HashMap
* re-evaluated.</p>
*/
public static final int PID_LINKSDIRTY = 16;
+
+ /**
+ * <p>The highest well-known property ID. Applications are free to use higher values for custom purposes.</p>
+ */
+ public static final int PID_MAX = PID_LINKSDIRTY;
diff --git a/src/java/org/apache/poi/hpsf/wellknown/SectionIDMap.java b/src/java/org/apache/poi/hpsf/wellknown/SectionIDMap.java
index 93e837f2c6..e5e2045896 100644
--- a/src/java/org/apache/poi/hpsf/wellknown/SectionIDMap.java
+++ b/src/java/org/apache/poi/hpsf/wellknown/SectionIDMap.java
@@ -1,6 +1,5 @@
-
/* ====================================================================
- Copyright 2002-2004 Apache Software Foundation
+ Copyright 2002-2006 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.
@@ -53,16 +52,23 @@ public class SectionIDMap extends HashMap
};
/**
- * <p>The DocumentSummaryInformation's first section's format
- * ID. The second section has a different format ID which is not
- * well-known.</p>
+ * <p>The DocumentSummaryInformation's first and second sections' format
+ * ID.</p>
*/
- public static final byte[] DOCUMENT_SUMMARY_INFORMATION_ID = new byte[]
+ public static final byte[][] DOCUMENT_SUMMARY_INFORMATION_ID = new byte[][]
{
- (byte) 0xD5, (byte) 0xCD, (byte) 0xD5, (byte) 0x02,
- (byte) 0x2E, (byte) 0x9C, (byte) 0x10, (byte) 0x1B,
- (byte) 0x93, (byte) 0x97, (byte) 0x08, (byte) 0x00,
- (byte) 0x2B, (byte) 0x2C, (byte) 0xF9, (byte) 0xAE
+ {
+ (byte) 0xD5, (byte) 0xCD, (byte) 0xD5, (byte) 0x02,
+ (byte) 0x2E, (byte) 0x9C, (byte) 0x10, (byte) 0x1B,
+ (byte) 0x93, (byte) 0x97, (byte) 0x08, (byte) 0x00,
+ (byte) 0x2B, (byte) 0x2C, (byte) 0xF9, (byte) 0xAE
+ },
+ {
+ (byte) 0xD5, (byte) 0xCD, (byte) 0xD5, (byte) 0x05,
+ (byte) 0x2E, (byte) 0x9C, (byte) 0x10, (byte) 0x1B,
+ (byte) 0x93, (byte) 0x97, (byte) 0x08, (byte) 0x00,
+ (byte) 0x2B, (byte) 0x2C, (byte) 0xF9, (byte) 0xAE
+ }
};
/**
@@ -91,7 +97,7 @@ public class SectionIDMap extends HashMap
final SectionIDMap m = new SectionIDMap();
m.put(SUMMARY_INFORMATION_ID,
PropertyIDMap.getSummaryInformationProperties());
- m.put(DOCUMENT_SUMMARY_INFORMATION_ID,
+ m.put(DOCUMENT_SUMMARY_INFORMATION_ID[0],
PropertyIDMap.getDocumentSummaryInformationProperties());
defaultMap = m;
}
@@ -116,8 +122,7 @@ public class SectionIDMap extends HashMap
public static String getPIDString(final byte[] sectionFormatID,
final long pid)
{
- final PropertyIDMap m =
- (PropertyIDMap) getInstance().get(sectionFormatID);
+ final PropertyIDMap m = getInstance().get(sectionFormatID);
if (m == null)
return UNDEFINED;
else
@@ -178,7 +183,8 @@ public class SectionIDMap extends HashMap
/**
* @deprecated Use {@link #put(byte[], PropertyIDMap)} instead!
- * @link #put(byte[], PropertyIDMap)
+ *
+ * @see #put(byte[], PropertyIDMap)
*
* @param key This parameter remains undocumented since the method is
* deprecated.
diff --git a/src/java/org/apache/poi/util/LittleEndian.java b/src/java/org/apache/poi/util/LittleEndian.java
index d215469247..f6c95d3d41 100644
--- a/src/java/org/apache/poi/util/LittleEndian.java
+++ b/src/java/org/apache/poi/util/LittleEndian.java
@@ -1,5 +1,5 @@
/* ====================================================================
- Copyright 2003-2004 Apache Software Foundation
+ Copyright 2003-2006 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.
@@ -64,9 +64,9 @@ public class LittleEndian
short num = (short) getNumber(data, offset, SHORT_SIZE);
int retNum;
if (num < 0) {
- retNum = ((int) Short.MAX_VALUE + 1) * 2 + (int) num;
+ retNum = (Short.MAX_VALUE + 1) * 2 + num;
} else {
- retNum = (int) num;
+ retNum = num;
}
return retNum;
}
@@ -163,9 +163,9 @@ public class LittleEndian
int num = (int) getNumber(data, offset, INT_SIZE);
long retNum;
if (num < 0) {
- retNum = ((long) Integer.MAX_VALUE + 1) * 2 + (long) num;
+ retNum = ((long) Integer.MAX_VALUE + 1) * 2 + num;
} else {
- retNum = (int) num;
+ retNum = num;
}
return retNum;
}
@@ -522,7 +522,7 @@ public class LittleEndian
*@return Description of the Return Value
*/
public static int ubyteToInt(byte b) {
- return ((b & 0x80) == 0 ? (int) b : (int) (b & (byte) 0x7f) + 0x80);
+ return ((b & 0x80) == 0 ? (int) b : (b & (byte) 0x7f) + 0x80);
}
@@ -566,5 +566,22 @@ public class LittleEndian
return copy;
}
+ /**
+ * <p>Gets an unsigned int value (8 bytes) from a byte array.</p>
+ *
+ * @param data the byte array
+ * @param offset a starting offset into the byte array
+ * @return the unsigned int (32-bit) value in a long
+ */
+ public static long getULong(final byte[] data, final int offset)
+ {
+ int num = (int) getNumber(data, offset, LONG_SIZE);
+ long retNum;
+ if (num < 0)
+ retNum = ((long) Integer.MAX_VALUE + 1) * 2 + num;
+ else
+ retNum = num;
+ return retNum;
+ }
}