Remove dependency on commons-collections4
This commit is contained in:
parent
7f216d8b6c
commit
640c88d640
5
pom.xml
5
pom.xml
@ -72,11 +72,6 @@
|
|||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
<version>4.12</version>
|
<version>4.12</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.commons</groupId>
|
|
||||||
<artifactId>commons-collections4</artifactId>
|
|
||||||
<version>4.1</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -1,350 +0,0 @@
|
|||||||
/* ====================================================================
|
|
||||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
contributor license agreements. See the NOTICE file distributed with
|
|
||||||
this work for additional information regarding copyright ownership.
|
|
||||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
|
||||||
(the "License"); you may not use this file except in compliance with
|
|
||||||
the License. You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
==================================================================== */
|
|
||||||
|
|
||||||
package org.apache.poi.hpsf;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.apache.commons.collections4.bidimap.TreeBidiMap;
|
|
||||||
import org.apache.poi.hpsf.wellknown.PropertyIDMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
* 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>
|
|
||||||
*
|
|
||||||
* This class is not thread-safe; concurrent access to instances of this
|
|
||||||
* class must be synchronized.<p>
|
|
||||||
*
|
|
||||||
* While this class is roughly HashMap<Long,CustomProperty>, that's the
|
|
||||||
* internal representation. To external calls, it should appear as
|
|
||||||
* HashMap<String,Object> mapping between Names and Custom Property Values.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("serial")
|
|
||||||
public class CustomProperties extends HashMap<Long,CustomProperty> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps property IDs to property names and vice versa.
|
|
||||||
*/
|
|
||||||
private final TreeBidiMap<Long,String> dictionary = new TreeBidiMap<Long,String>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tells whether this object is pure or not.
|
|
||||||
*/
|
|
||||||
private boolean isPure = true;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Puts a {@link CustomProperty} into this map. It is assumed that the
|
|
||||||
* {@link CustomProperty} already has a valid ID. Otherwise use
|
|
||||||
* {@link #put(CustomProperty)}.
|
|
||||||
*
|
|
||||||
* @param name the property name
|
|
||||||
* @param cp the property
|
|
||||||
*
|
|
||||||
* @return the previous property stored under this name
|
|
||||||
*/
|
|
||||||
public CustomProperty put(final String name, final CustomProperty cp) {
|
|
||||||
if (name == null) {
|
|
||||||
/* Ignoring a property without a name. */
|
|
||||||
isPure = false;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 */
|
|
||||||
super.remove(dictionary.getKey(name));
|
|
||||||
dictionary.put(cp.getID(), name);
|
|
||||||
|
|
||||||
/* Put the custom property into this map. */
|
|
||||||
return super.put(cp.getID(), cp);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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:
|
|
||||||
*
|
|
||||||
* <ul>
|
|
||||||
* <li>If there is already a property with the same name, take the ID
|
|
||||||
* of that property.
|
|
||||||
*
|
|
||||||
* <li>Otherwise find the highest ID and use its value plus one.
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @param customProperty
|
|
||||||
* @return If there was already a property with the same name, the old property
|
|
||||||
* @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 = (name == null) ? null : dictionary.getKey(name);
|
|
||||||
if (oldId != null) {
|
|
||||||
customProperty.setID(oldId);
|
|
||||||
} else {
|
|
||||||
long lastKey = (dictionary.isEmpty()) ? 0 : dictionary.lastKey();
|
|
||||||
customProperty.setID(Math.max(lastKey,PropertyIDMap.PID_MAX) + 1);
|
|
||||||
}
|
|
||||||
return this.put(name, customProperty);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes a custom property.
|
|
||||||
* @param name The name of the custom property to remove
|
|
||||||
* @return The removed property or {@code null} if the specified property was not found.
|
|
||||||
*
|
|
||||||
* @see java.util.HashSet#remove(java.lang.Object)
|
|
||||||
*/
|
|
||||||
public Object remove(final String name) {
|
|
||||||
final Long id = dictionary.removeValue(name);
|
|
||||||
return super.remove(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a named string property.
|
|
||||||
*
|
|
||||||
* @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} if there was no such property before.
|
|
||||||
*/
|
|
||||||
public Object put(final String name, final String value) {
|
|
||||||
final Property p = new Property(-1, Variant.VT_LPWSTR, value);
|
|
||||||
return put(new CustomProperty(p, name));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a named long property.
|
|
||||||
*
|
|
||||||
* @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} if there was no such property before.
|
|
||||||
*/
|
|
||||||
public Object put(final String name, final Long value) {
|
|
||||||
final Property p = new Property(-1, Variant.VT_I8, value);
|
|
||||||
return put(new CustomProperty(p, name));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a named double property.
|
|
||||||
*
|
|
||||||
* @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} if there was no such property before.
|
|
||||||
*/
|
|
||||||
public Object put(final String name, final Double value) {
|
|
||||||
final Property p = new Property(-1, Variant.VT_R8, value);
|
|
||||||
return put(new CustomProperty(p, name));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a named integer property.
|
|
||||||
*
|
|
||||||
* @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} if there was no such property before.
|
|
||||||
*/
|
|
||||||
public Object put(final String name, final Integer value) {
|
|
||||||
final Property p = new Property(-1, Variant.VT_I4, value);
|
|
||||||
return put(new CustomProperty(p, name));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a named boolean property.
|
|
||||||
*
|
|
||||||
* @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} if there was no such property before.
|
|
||||||
*/
|
|
||||||
public Object put(final String name, final Boolean value) {
|
|
||||||
final Property p = new Property(-1, Variant.VT_BOOL, value);
|
|
||||||
return put(new CustomProperty(p, name));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a named value from the custom properties.
|
|
||||||
*
|
|
||||||
* @param name the name of the value to get
|
|
||||||
* @return the value or {@code null} if a value with the specified
|
|
||||||
* name is not found in the custom properties.
|
|
||||||
*/
|
|
||||||
public Object get(final String name) {
|
|
||||||
final Long id = dictionary.getKey(name);
|
|
||||||
final CustomProperty cp = super.get(id);
|
|
||||||
return cp != null ? cp.getValue() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a named date property.
|
|
||||||
*
|
|
||||||
* @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} if there was no such property before.
|
|
||||||
*/
|
|
||||||
public Object put(final String name, final Date value) {
|
|
||||||
final Property p = new Property(-1, Variant.VT_FILETIME, value);
|
|
||||||
return put(new CustomProperty(p, name));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a set of all the names of our custom properties.
|
|
||||||
* Equivalent to {@link #nameSet()}
|
|
||||||
*
|
|
||||||
* @return a set of all the names of our custom properties
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
|
||||||
public Set keySet() {
|
|
||||||
return dictionary.values();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a set of all the names of our custom properties
|
|
||||||
*
|
|
||||||
* @return a set of all the names of our custom properties
|
|
||||||
*/
|
|
||||||
public Set<String> nameSet() {
|
|
||||||
return dictionary.values();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a set of all the IDs of our custom properties
|
|
||||||
*
|
|
||||||
* @return a set of all the IDs of our custom properties
|
|
||||||
*/
|
|
||||||
public Set<String> idSet() {
|
|
||||||
return dictionary.values();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the codepage.
|
|
||||||
*
|
|
||||||
* @param codepage the codepage
|
|
||||||
*/
|
|
||||||
public void setCodepage(final int codepage) {
|
|
||||||
Property p = new Property(PropertyIDMap.PID_CODEPAGE, Variant.VT_I2, codepage);
|
|
||||||
put(new CustomProperty(p));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Gets the dictionary which contains IDs and names of the named custom
|
|
||||||
* properties.
|
|
||||||
*
|
|
||||||
* @return the dictionary.
|
|
||||||
*/
|
|
||||||
Map<Long,String> getDictionary() {
|
|
||||||
return dictionary;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks against both String Name and Long ID
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean containsKey(Object key) {
|
|
||||||
return ((key instanceof Long && dictionary.containsKey(key)) || dictionary.containsValue(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks against both the property, and its values.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean containsValue(Object value) {
|
|
||||||
if(value instanceof CustomProperty) {
|
|
||||||
return super.containsValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(CustomProperty cp : super.values()) {
|
|
||||||
if(cp.getValue() == value) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the codepage.
|
|
||||||
*
|
|
||||||
* @return the codepage or -1 if the codepage is undefined.
|
|
||||||
*/
|
|
||||||
public int getCodepage() {
|
|
||||||
CustomProperty cp = get(PropertyIDMap.PID_CODEPAGE);
|
|
||||||
return (cp == null) ? -1 : (Integer)cp.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tells whether this {@link CustomProperties} instance is pure or one or
|
|
||||||
* more properties of the underlying low-level property set has been
|
|
||||||
* dropped.
|
|
||||||
*
|
|
||||||
* @return {@code true} if the {@link CustomProperties} is pure, else
|
|
||||||
* {@code false}.
|
|
||||||
*/
|
|
||||||
public boolean isPure() {
|
|
||||||
return isPure;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the purity of the custom property set.
|
|
||||||
*
|
|
||||||
* @param isPure the purity
|
|
||||||
*/
|
|
||||||
public void setPure(final boolean isPure) {
|
|
||||||
this.isPure = isPure;
|
|
||||||
}
|
|
||||||
}
|
|
@ -718,66 +718,6 @@ public class DocumentSummaryInformation extends SpecialPropertySet {
|
|||||||
remove1stProperty(PropertyIDMap.PID_DOCVERSION);
|
remove1stProperty(PropertyIDMap.PID_DOCVERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the custom properties.
|
|
||||||
*
|
|
||||||
* @return The custom properties.
|
|
||||||
*/
|
|
||||||
public CustomProperties getCustomProperties() {
|
|
||||||
CustomProperties cps = null;
|
|
||||||
if (getSectionCount() >= 2) {
|
|
||||||
cps = new CustomProperties();
|
|
||||||
final Section section = getSections().get(1);
|
|
||||||
final Map<Long,String> dictionary = section.getDictionary();
|
|
||||||
final Property[] properties = section.getProperties();
|
|
||||||
int propertyCount = 0;
|
|
||||||
for (int i = 0; i < properties.length; i++) {
|
|
||||||
final Property p = properties[i];
|
|
||||||
final long id = p.getID();
|
|
||||||
if (id != 0 && id != 1) {
|
|
||||||
propertyCount++;
|
|
||||||
final CustomProperty cp = new CustomProperty(p,
|
|
||||||
dictionary.get(Long.valueOf(id)));
|
|
||||||
cps.put(cp.getName(), cp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cps.size() != propertyCount) {
|
|
||||||
cps.setPure(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cps;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the custom properties.
|
|
||||||
*
|
|
||||||
* @param customProperties The custom properties
|
|
||||||
*/
|
|
||||||
public void setCustomProperties(final CustomProperties customProperties) {
|
|
||||||
ensureSection2();
|
|
||||||
final Section section = getSections().get(1);
|
|
||||||
final Map<Long,String> 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 = CodePageUtil.CP_UNICODE;
|
|
||||||
}
|
|
||||||
customProperties.setCodepage(cpCodepage);
|
|
||||||
section.setCodepage(cpCodepage);
|
|
||||||
section.setDictionary(dictionary);
|
|
||||||
for (CustomProperty p : customProperties.values()) {
|
|
||||||
section.setProperty(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates section 2 if it is not already present.
|
* Creates section 2 if it is not already present.
|
||||||
*/
|
*/
|
||||||
|
@ -25,7 +25,6 @@ import java.util.Date;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import org.apache.commons.collections4.bidimap.TreeBidiMap;
|
|
||||||
import org.apache.poi.hpsf.wellknown.PropertyIDMap;
|
import org.apache.poi.hpsf.wellknown.PropertyIDMap;
|
||||||
import org.apache.poi.hpsf.wellknown.SectionIDMap;
|
import org.apache.poi.hpsf.wellknown.SectionIDMap;
|
||||||
import org.apache.poi.util.CodePageUtil;
|
import org.apache.poi.util.CodePageUtil;
|
||||||
@ -115,136 +114,8 @@ public class Section {
|
|||||||
* @exception UnsupportedEncodingException if the section's codepage is not
|
* @exception UnsupportedEncodingException if the section's codepage is not
|
||||||
* supported.
|
* supported.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public Section(final byte[] src, final int offset) throws UnsupportedEncodingException {
|
public Section(final byte[] src, final int offset) throws UnsupportedEncodingException {
|
||||||
int o1 = offset;
|
throw new UnsupportedEncodingException("support for reading these has been removed in poi-fast-calc");
|
||||||
|
|
||||||
/*
|
|
||||||
* Read the format ID.
|
|
||||||
*/
|
|
||||||
formatID = new ClassID(src, o1);
|
|
||||||
o1 += ClassID.LENGTH;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read the offset from the stream's start and positions to
|
|
||||||
* the section header.
|
|
||||||
*/
|
|
||||||
this.offset = LittleEndian.getUInt(src, o1);
|
|
||||||
o1 = (int) this.offset;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read the section length.
|
|
||||||
*/
|
|
||||||
size = (int) LittleEndian.getUInt(src, o1);
|
|
||||||
o1 += LittleEndian.INT_SIZE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read the number of properties.
|
|
||||||
*/
|
|
||||||
final int propertyCount = (int) LittleEndian.getUInt(src, o1);
|
|
||||||
o1 += LittleEndian.INT_SIZE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read the properties. The offset is positioned at the first
|
|
||||||
* entry of the property list. There are two problems:
|
|
||||||
*
|
|
||||||
* 1. For each property we have to find out its length. In the
|
|
||||||
* property list we find each property's ID and its offset relative
|
|
||||||
* to the section's beginning. Unfortunately the properties in the
|
|
||||||
* property list need not to be in ascending order, so it is not
|
|
||||||
* possible to calculate the length as
|
|
||||||
* (offset of property(i+1) - offset of property(i)). Before we can
|
|
||||||
* that we first have to sort the property list by ascending offsets.
|
|
||||||
*
|
|
||||||
* 2. We have to read the property with ID 1 before we read other
|
|
||||||
* properties, at least before other properties containing strings.
|
|
||||||
* The reason is that property 1 specifies the codepage. If it is
|
|
||||||
* 1200, all strings are in Unicode. In other words: Before we can
|
|
||||||
* read any strings we have to know whether they are in Unicode or
|
|
||||||
* not. Unfortunately property 1 is not guaranteed to be the first in
|
|
||||||
* a section.
|
|
||||||
*
|
|
||||||
* The algorithm below reads the properties in two passes: The first
|
|
||||||
* one looks for property ID 1 and extracts the codepage number. The
|
|
||||||
* seconds pass reads the other properties.
|
|
||||||
*/
|
|
||||||
/* Pass 1: Read the property list. */
|
|
||||||
int pass1Offset = o1;
|
|
||||||
long cpOffset = -1;
|
|
||||||
final TreeBidiMap<Long,Long> offset2Id = new TreeBidiMap<Long,Long>();
|
|
||||||
for (int i = 0; i < propertyCount; i++) {
|
|
||||||
/* Read the property ID. */
|
|
||||||
long id = LittleEndian.getUInt(src, pass1Offset);
|
|
||||||
pass1Offset += LittleEndian.INT_SIZE;
|
|
||||||
|
|
||||||
/* Offset from the section's start. */
|
|
||||||
long off = LittleEndian.getUInt(src, pass1Offset);
|
|
||||||
pass1Offset += LittleEndian.INT_SIZE;
|
|
||||||
|
|
||||||
offset2Id.put(off, id);
|
|
||||||
|
|
||||||
if (id == PropertyIDMap.PID_CODEPAGE) {
|
|
||||||
cpOffset = off;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Look for the codepage. */
|
|
||||||
int codepage = -1;
|
|
||||||
if (cpOffset != -1) {
|
|
||||||
/* Read the property's value type. It must be VT_I2. */
|
|
||||||
long o = this.offset + cpOffset;
|
|
||||||
final long type = LittleEndian.getUInt(src, (int)o);
|
|
||||||
o += LittleEndian.INT_SIZE;
|
|
||||||
|
|
||||||
if (type != Variant.VT_I2) {
|
|
||||||
throw new HPSFRuntimeException
|
|
||||||
("Value type of property ID 1 is not VT_I2 but " +
|
|
||||||
type + ".");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read the codepage number. */
|
|
||||||
codepage = LittleEndian.getUShort(src, (int)o);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Pass 2: Read all properties - including the codepage property,
|
|
||||||
* if available. */
|
|
||||||
for (Map.Entry<Long,Long> me : offset2Id.entrySet()) {
|
|
||||||
long off = me.getKey();
|
|
||||||
long id = me.getValue();
|
|
||||||
Property p;
|
|
||||||
if (id == PropertyIDMap.PID_CODEPAGE) {
|
|
||||||
p = new Property(PropertyIDMap.PID_CODEPAGE, Variant.VT_I2, codepage);
|
|
||||||
} else {
|
|
||||||
int pLen = propLen(offset2Id, off, size);
|
|
||||||
long o = this.offset + off;
|
|
||||||
p = new Property(id, src, o, pLen, codepage);
|
|
||||||
}
|
|
||||||
properties.put(id, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Extract the dictionary (if available).
|
|
||||||
*/
|
|
||||||
dictionary = (Map<Long,String>) getProperty(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the length of the given property (by key)
|
|
||||||
*
|
|
||||||
* @param offset2Id the offset to id map
|
|
||||||
* @param entryOffset the current entry key
|
|
||||||
* @param maxSize the maximum offset/size of the section stream
|
|
||||||
* @return the length of the current property
|
|
||||||
*/
|
|
||||||
private static int propLen(
|
|
||||||
TreeBidiMap<Long,Long> offset2Id,
|
|
||||||
Long entryOffset,
|
|
||||||
long maxSize) {
|
|
||||||
Long nextKey = offset2Id.nextKey(entryOffset);
|
|
||||||
long begin = entryOffset;
|
|
||||||
long end = (nextKey != null) ? nextKey : maxSize;
|
|
||||||
return (int)(end - begin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@ import java.io.IOException;
|
|||||||
import org.apache.poi.POIDocument;
|
import org.apache.poi.POIDocument;
|
||||||
import org.apache.poi.POIOLE2TextExtractor;
|
import org.apache.poi.POIOLE2TextExtractor;
|
||||||
import org.apache.poi.POITextExtractor;
|
import org.apache.poi.POITextExtractor;
|
||||||
import org.apache.poi.hpsf.CustomProperties;
|
|
||||||
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
||||||
import org.apache.poi.hpsf.HPSFPropertiesOnlyDocument;
|
import org.apache.poi.hpsf.HPSFPropertiesOnlyDocument;
|
||||||
import org.apache.poi.hpsf.Property;
|
import org.apache.poi.hpsf.Property;
|
||||||
@ -64,15 +63,6 @@ public class HPSFPropertiesExtractor extends POIOLE2TextExtractor {
|
|||||||
// Normal properties
|
// Normal properties
|
||||||
text.append( getPropertiesText(dsi) );
|
text.append( getPropertiesText(dsi) );
|
||||||
|
|
||||||
// Now custom ones
|
|
||||||
CustomProperties cps = dsi == null ? null : dsi.getCustomProperties();
|
|
||||||
if (cps != null) {
|
|
||||||
for (String key : cps.nameSet()) {
|
|
||||||
String val = getPropertyValueText(cps.get(key));
|
|
||||||
text.append(key).append(" = ").append(val).append("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// All done
|
// All done
|
||||||
return text.toString();
|
return text.toString();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user