mirror of
https://github.com/apache/poi.git
synced 2026-02-27 20:40:08 +08:00
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1839709 13f79535-47bb-0310-9956-ffa450edef68
759 lines
29 KiB
Java
759 lines
29 KiB
Java
/* ====================================================================
|
|
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.basic;
|
|
|
|
import static org.hamcrest.core.IsEqual.equalTo;
|
|
import static org.junit.Assert.assertArrayEquals;
|
|
import static org.junit.Assert.assertEquals;
|
|
import static org.junit.Assert.assertNotNull;
|
|
import static org.junit.Assert.assertNull;
|
|
import static org.junit.Assert.assertThat;
|
|
import static org.junit.Assert.assertTrue;
|
|
import static org.junit.Assert.fail;
|
|
|
|
import java.io.ByteArrayInputStream;
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.File;
|
|
import java.io.FileOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.OutputStream;
|
|
import java.io.UnsupportedEncodingException;
|
|
import java.nio.charset.Charset;
|
|
import java.util.Date;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
import java.util.Map;
|
|
|
|
import org.apache.poi.POIDataSamples;
|
|
import org.apache.poi.hpsf.ClassID;
|
|
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
|
import org.apache.poi.hpsf.HPSFException;
|
|
import org.apache.poi.hpsf.NoFormatIDException;
|
|
import org.apache.poi.hpsf.NoPropertySetStreamException;
|
|
import org.apache.poi.hpsf.Property;
|
|
import org.apache.poi.hpsf.PropertySet;
|
|
import org.apache.poi.hpsf.PropertySetFactory;
|
|
import org.apache.poi.hpsf.Section;
|
|
import org.apache.poi.hpsf.SummaryInformation;
|
|
import org.apache.poi.hpsf.UnsupportedVariantTypeException;
|
|
import org.apache.poi.hpsf.Variant;
|
|
import org.apache.poi.hpsf.VariantSupport;
|
|
import org.apache.poi.hpsf.WritingNotSupportedException;
|
|
import org.apache.poi.hpsf.wellknown.PropertyIDMap;
|
|
import org.apache.poi.poifs.eventfilesystem.POIFSReader;
|
|
import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
|
|
import org.apache.poi.poifs.eventfilesystem.POIFSReaderListener;
|
|
import org.apache.poi.poifs.filesystem.DirectoryEntry;
|
|
import org.apache.poi.poifs.filesystem.DocumentNode;
|
|
import org.apache.poi.poifs.filesystem.DocumentInputStream;
|
|
import org.apache.poi.poifs.filesystem.DocumentOutputStream;
|
|
import org.apache.poi.poifs.filesystem.POIFSDocument;
|
|
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
|
import org.apache.poi.util.CodePageUtil;
|
|
import org.apache.poi.util.IOUtils;
|
|
import org.apache.poi.util.LittleEndianConsts;
|
|
import org.apache.poi.util.TempFile;
|
|
import org.junit.Assume;
|
|
import org.junit.BeforeClass;
|
|
import org.junit.Test;
|
|
|
|
/**
|
|
* Tests HPSF's writing functionality
|
|
*/
|
|
public class TestWrite {
|
|
private static final POIDataSamples _samples = POIDataSamples.getHPSFInstance();
|
|
private static final int CODEPAGE_DEFAULT = -1;
|
|
|
|
private static final String POI_FS = "TestHPSFWritingFunctionality.doc";
|
|
|
|
private static final String IMPROPER_DEFAULT_CHARSET_MESSAGE =
|
|
"Your default character set is " + getDefaultCharsetName() +
|
|
". However, this testcase must be run in an environment " +
|
|
"with a default character set supporting at least " +
|
|
"8-bit-characters. You can achieve this by setting the " +
|
|
"LANG environment variable to a proper value, e.g. " +
|
|
"\"de_DE\".";
|
|
|
|
@BeforeClass
|
|
public static void setUp() {
|
|
VariantSupport.setLogUnsupportedTypes(false);
|
|
}
|
|
|
|
/**
|
|
* <p>Writes an empty property set to a POIFS and reads it back
|
|
* in.</p>
|
|
*
|
|
* @exception IOException if an I/O exception occurs
|
|
*/
|
|
@Test(expected=NoFormatIDException.class)
|
|
public void withoutAFormatID() throws Exception {
|
|
final File filename = TempFile.createTempFile(POI_FS, ".doc");
|
|
|
|
/* Create a mutable property set with a section that does not have the
|
|
* formatID set: */
|
|
final PropertySet ps = new PropertySet();
|
|
ps.clearSections();
|
|
ps.addSection(new Section());
|
|
|
|
/* Write it to a POIFS and the latter to disk: */
|
|
try (OutputStream out = new FileOutputStream(filename);
|
|
POIFSFileSystem poiFs = new POIFSFileSystem()) {
|
|
final ByteArrayOutputStream psStream = new ByteArrayOutputStream();
|
|
ps.write(psStream);
|
|
psStream.close();
|
|
final byte[] streamData = psStream.toByteArray();
|
|
poiFs.createDocument(new ByteArrayInputStream(streamData),
|
|
SummaryInformation.DEFAULT_STREAM_NAME);
|
|
poiFs.writeFilesystem(out);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* <p>Writes an empty property set to a POIFS and reads it back
|
|
* in.</p>
|
|
*
|
|
* @exception IOException if an I/O exception occurs
|
|
* @exception UnsupportedVariantTypeException if HPSF does not yet support
|
|
* a variant type to be written
|
|
*/
|
|
@Test
|
|
public void writeEmptyPropertySet()
|
|
throws IOException, UnsupportedVariantTypeException {
|
|
final File dataDir = _samples.getFile("");
|
|
final File filename = new File(dataDir, POI_FS);
|
|
filename.deleteOnExit();
|
|
|
|
/* Create a mutable property set and write it to a POIFS: */
|
|
final OutputStream out = new FileOutputStream(filename);
|
|
final POIFSFileSystem poiFs = new POIFSFileSystem();
|
|
final PropertySet ps = new PropertySet();
|
|
final Section s = ps.getSections().get(0);
|
|
s.setFormatID(SummaryInformation.FORMAT_ID);
|
|
|
|
final ByteArrayOutputStream psStream = new ByteArrayOutputStream();
|
|
ps.write(psStream);
|
|
psStream.close();
|
|
final byte[] streamData = psStream.toByteArray();
|
|
poiFs.createDocument(new ByteArrayInputStream(streamData),
|
|
SummaryInformation.DEFAULT_STREAM_NAME);
|
|
poiFs.writeFilesystem(out);
|
|
poiFs.close();
|
|
out.close();
|
|
|
|
/* Read the POIFS: */
|
|
final POIFSReader r = new POIFSReader();
|
|
r.registerListener(new MyPOIFSReaderListener(),
|
|
SummaryInformation.DEFAULT_STREAM_NAME);
|
|
r.read(filename);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* <p>Writes a simple property set with a SummaryInformation section to a
|
|
* POIFS and reads it back in.</p>
|
|
*
|
|
* @exception IOException if an I/O exception occurs
|
|
* @exception UnsupportedVariantTypeException if HPSF does not yet support
|
|
* a variant type to be written
|
|
*/
|
|
@Test
|
|
public void writeSimplePropertySet()
|
|
throws IOException, UnsupportedVariantTypeException {
|
|
final String AUTHOR = "Rainer Klute";
|
|
final String TITLE = "Test Document";
|
|
final File dataDir = _samples.getFile("");
|
|
final File filename = new File(dataDir, POI_FS);
|
|
filename.deleteOnExit();
|
|
final OutputStream out = new FileOutputStream(filename);
|
|
final POIFSFileSystem poiFs = new POIFSFileSystem();
|
|
|
|
final PropertySet ps = new PropertySet();
|
|
final Section si = new Section();
|
|
si.setFormatID(SummaryInformation.FORMAT_ID);
|
|
ps.clearSections();
|
|
ps.addSection(si);
|
|
|
|
final Property p = new Property();
|
|
p.setID(PropertyIDMap.PID_AUTHOR);
|
|
p.setType(Variant.VT_LPWSTR);
|
|
p.setValue(AUTHOR);
|
|
si.setProperty(p);
|
|
si.setProperty(PropertyIDMap.PID_TITLE, Variant.VT_LPSTR, TITLE);
|
|
|
|
poiFs.createDocument(ps.toInputStream(),
|
|
SummaryInformation.DEFAULT_STREAM_NAME);
|
|
poiFs.writeFilesystem(out);
|
|
poiFs.close();
|
|
out.close();
|
|
|
|
/* Read the POIFS: */
|
|
final PropertySet[] psa = new PropertySet[1];
|
|
final POIFSReader r = new POIFSReader();
|
|
final POIFSReaderListener listener = event -> {
|
|
try {
|
|
psa[0] = PropertySetFactory.create(event.getStream());
|
|
} catch (Exception ex) {
|
|
fail(ex.getMessage());
|
|
}
|
|
};
|
|
r.registerListener(listener, SummaryInformation.DEFAULT_STREAM_NAME);
|
|
|
|
r.read(filename);
|
|
assertNotNull(psa[0]);
|
|
assertTrue(psa[0].isSummaryInformation());
|
|
|
|
final Section s = (psa[0].getSections().get(0));
|
|
Object p1 = s.getProperty(PropertyIDMap.PID_AUTHOR);
|
|
Object p2 = s.getProperty(PropertyIDMap.PID_TITLE);
|
|
assertEquals(AUTHOR, p1);
|
|
assertEquals(TITLE, p2);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* <p>Writes a simple property set with two sections to a POIFS and reads it
|
|
* back in.</p>
|
|
*
|
|
* @exception IOException if an I/O exception occurs
|
|
* @exception WritingNotSupportedException if HPSF does not yet support
|
|
* a variant type to be written
|
|
*/
|
|
@Test
|
|
public void writeTwoSections() throws WritingNotSupportedException, IOException {
|
|
final String STREAM_NAME = "PropertySetStream";
|
|
final String SECTION1 = "Section 1";
|
|
final String SECTION2 = "Section 2";
|
|
|
|
final File dataDir = _samples.getFile("");
|
|
final File filename = new File(dataDir, POI_FS);
|
|
filename.deleteOnExit();
|
|
final OutputStream out = new FileOutputStream(filename);
|
|
|
|
final POIFSFileSystem poiFs = new POIFSFileSystem();
|
|
final PropertySet ps = new PropertySet();
|
|
ps.clearSections();
|
|
|
|
final ClassID formatID = new ClassID();
|
|
formatID.setBytes(new byte[]{0, 1, 2, 3, 4, 5, 6, 7,
|
|
8, 9, 10, 11, 12, 13, 14, 15});
|
|
final Section s1 = new Section();
|
|
s1.setFormatID(formatID);
|
|
s1.setProperty(2, SECTION1);
|
|
ps.addSection(s1);
|
|
|
|
final Section s2 = new Section();
|
|
s2.setFormatID(formatID);
|
|
s2.setProperty(2, SECTION2);
|
|
ps.addSection(s2);
|
|
|
|
poiFs.createDocument(ps.toInputStream(), STREAM_NAME);
|
|
poiFs.writeFilesystem(out);
|
|
poiFs.close();
|
|
out.close();
|
|
|
|
/* Read the POIFS: */
|
|
final PropertySet[] psa = new PropertySet[1];
|
|
final POIFSReader r = new POIFSReader();
|
|
final POIFSReaderListener listener = (event) -> {
|
|
try {
|
|
psa[0] = PropertySetFactory.create(event.getStream());
|
|
} catch (Exception ex) {
|
|
fail(ex.getMessage());
|
|
}
|
|
};
|
|
|
|
r.registerListener(listener,STREAM_NAME);
|
|
r.read(filename);
|
|
|
|
assertNotNull(psa[0]);
|
|
Section s = (psa[0].getSections().get(0));
|
|
assertEquals(s.getFormatID(), formatID);
|
|
Object p = s.getProperty(2);
|
|
assertEquals(SECTION1, p);
|
|
s = (psa[0].getSections().get(1));
|
|
p = s.getProperty(2);
|
|
assertEquals(SECTION2, p);
|
|
}
|
|
|
|
|
|
|
|
static class MyPOIFSReaderListener implements POIFSReaderListener {
|
|
@Override
|
|
public void processPOIFSReaderEvent(final POIFSReaderEvent event) {
|
|
try {
|
|
PropertySetFactory.create(event.getStream());
|
|
} catch (Exception ex) {
|
|
fail(ex.getMessage());
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Writes and reads back various variant types and checks whether the
|
|
* stuff that has been read back equals the stuff that was written.
|
|
*/
|
|
@Test
|
|
public void variantTypes() throws Exception {
|
|
final int codepage = CODEPAGE_DEFAULT;
|
|
Assume.assumeTrue(IMPROPER_DEFAULT_CHARSET_MESSAGE, hasProperDefaultCharset());
|
|
|
|
check(Variant.VT_EMPTY, null, codepage);
|
|
check(Variant.VT_BOOL, Boolean.TRUE, codepage);
|
|
check(Variant.VT_BOOL, Boolean.FALSE, codepage);
|
|
check( Variant.VT_CF, new byte[] { 8, 0, 0, 0, 1, 0, 0, 0, 1, 2, 3, 4 }, codepage );
|
|
check(Variant.VT_I4, 27, codepage);
|
|
check(Variant.VT_I8, 28L, codepage);
|
|
check(Variant.VT_R8, 29.0d, codepage);
|
|
check(Variant.VT_I4, -27, codepage);
|
|
check(Variant.VT_I8, -28L, codepage);
|
|
check(Variant.VT_R8, -29.0d, codepage);
|
|
check(Variant.VT_FILETIME, new Date(), codepage);
|
|
check(Variant.VT_I4, Integer.MAX_VALUE, codepage);
|
|
check(Variant.VT_I4, Integer.MIN_VALUE, codepage);
|
|
check(Variant.VT_I8, Long.MAX_VALUE, codepage);
|
|
check(Variant.VT_I8, Long.MIN_VALUE, codepage);
|
|
check(Variant.VT_R8, Double.MAX_VALUE, codepage);
|
|
check(Variant.VT_R8, Double.MIN_VALUE, codepage);
|
|
checkString(Variant.VT_LPSTR, "\u00e4\u00f6\u00fc\u00df\u00c4\u00d6\u00dc", codepage);
|
|
checkString(Variant.VT_LPWSTR, "\u00e4\u00f6\u00fc\u00df\u00c4\u00d6\u00dc", codepage);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Writes and reads back strings using several different codepages and
|
|
* checks whether the stuff that has been read back equals the stuff that
|
|
* was written.
|
|
*/
|
|
@Test
|
|
public void codepages() throws UnsupportedVariantTypeException, IOException
|
|
{
|
|
final int[] validCodepages = {CODEPAGE_DEFAULT, CodePageUtil.CP_UTF8, CodePageUtil.CP_UNICODE, CodePageUtil.CP_WINDOWS_1252};
|
|
for (final int cp : validCodepages) {
|
|
if (cp == -1 && !hasProperDefaultCharset())
|
|
{
|
|
System.err.println(IMPROPER_DEFAULT_CHARSET_MESSAGE +
|
|
" This testcase is skipped for the default codepage.");
|
|
continue;
|
|
}
|
|
|
|
final long t = (cp == CodePageUtil.CP_UNICODE) ? Variant.VT_LPWSTR : Variant.VT_LPSTR;
|
|
checkString(t, "\u00e4\u00f6\u00fc\u00c4\u00d6\u00dc\u00df", cp);
|
|
if (cp == CodePageUtil.CP_UTF16 || cp == CodePageUtil.CP_UTF8) {
|
|
check(t, "\u79D1\u5B78", cp);
|
|
}
|
|
}
|
|
|
|
final int[] invalidCodepages = new int[] {0, 1, 2, 4711, 815};
|
|
for (int cp : invalidCodepages) {
|
|
try {
|
|
checkString(Variant.VT_LPSTR, "\u00e4\u00f6\u00fc\u00c4\u00d6\u00dc\u00df", cp);
|
|
fail("UnsupportedEncodingException for codepage " + cp + " expected.");
|
|
} catch (UnsupportedEncodingException ex) {
|
|
/* This is the expected behaviour. */
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Tests whether writing 8-bit characters to a Unicode property succeeds.
|
|
*/
|
|
@Test
|
|
public void unicodeWrite8Bit() throws WritingNotSupportedException, IOException, NoPropertySetStreamException {
|
|
final String TITLE = "This is a sample title";
|
|
final PropertySet mps = new PropertySet();
|
|
final Section ms = mps.getSections().get(0);
|
|
ms.setFormatID(SummaryInformation.FORMAT_ID);
|
|
final Property p = new Property();
|
|
p.setID(PropertyIDMap.PID_TITLE);
|
|
p.setType(Variant.VT_LPSTR);
|
|
p.setValue(TITLE);
|
|
ms.setProperty(p);
|
|
|
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
mps.write(out);
|
|
out.close();
|
|
byte[] bytes = out.toByteArray();
|
|
|
|
PropertySet psr = new PropertySet(bytes);
|
|
assertTrue(psr.isSummaryInformation());
|
|
Section sr = psr.getSections().get(0);
|
|
String title = (String) sr.getProperty(PropertyIDMap.PID_TITLE);
|
|
assertEquals(TITLE, title);
|
|
}
|
|
|
|
private void checkString(final long variantType, final String value, final int codepage)
|
|
throws UnsupportedVariantTypeException, IOException {
|
|
for (int i=0; i<value.length(); i++) {
|
|
check(variantType, value.substring(0, i), codepage);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Writes a property and reads it back in.
|
|
*
|
|
* @param variantType The property's variant type.
|
|
* @param value The property's value.
|
|
* @param codepage The codepage to use for writing and reading.
|
|
* @throws UnsupportedVariantTypeException if the variant is not supported.
|
|
* @throws IOException if an I/O exception occurs.
|
|
*/
|
|
private void check(final long variantType, final Object value, final int codepage)
|
|
throws UnsupportedVariantTypeException, IOException
|
|
{
|
|
final ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
VariantSupport.write(out, variantType, value, codepage);
|
|
out.close();
|
|
final byte[] b = out.toByteArray();
|
|
final Object objRead =
|
|
VariantSupport.read(b, 0, b.length + LittleEndianConsts.INT_SIZE, variantType, codepage);
|
|
if (objRead instanceof byte[]) {
|
|
assertArrayEquals((byte[])value, (byte[])objRead);
|
|
} else if (value != null && !value.equals(objRead)) {
|
|
assertEquals(value, objRead);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* <p>Tests writing and reading back a proper dictionary.</p>
|
|
*/
|
|
@Test
|
|
public void dictionary() throws IOException, HPSFException {
|
|
final File copy = TempFile.createTempFile("Test-HPSF", "ole2");
|
|
copy.deleteOnExit();
|
|
|
|
/* Write: */
|
|
final OutputStream out = new FileOutputStream(copy);
|
|
final POIFSFileSystem poiFs = new POIFSFileSystem();
|
|
final PropertySet ps1 = new PropertySet();
|
|
final Section s = ps1.getSections().get(0);
|
|
final Map<Long,String> m = new HashMap<>(3, 1.0f);
|
|
m.put(1L, "String 1");
|
|
m.put(2L, "String 2");
|
|
m.put(3L, "String 3");
|
|
s.setDictionary(m);
|
|
s.setFormatID(DocumentSummaryInformation.FORMAT_ID[0]);
|
|
int codepage = CodePageUtil.CP_UNICODE;
|
|
s.setProperty(PropertyIDMap.PID_CODEPAGE, Variant.VT_I2, codepage);
|
|
poiFs.createDocument(ps1.toInputStream(), "Test");
|
|
poiFs.writeFilesystem(out);
|
|
poiFs.close();
|
|
out.close();
|
|
|
|
/* Read back: */
|
|
final List<POIFile> psf = Util.readPropertySets(copy);
|
|
assertEquals(1, psf.size());
|
|
final byte[] bytes = psf.get(0).getBytes();
|
|
final InputStream in = new ByteArrayInputStream(bytes);
|
|
final PropertySet ps2 = PropertySetFactory.create(in);
|
|
|
|
/* Check if the result is a DocumentSummaryInformation stream, as
|
|
* specified. */
|
|
assertTrue(ps2.isDocumentSummaryInformation());
|
|
|
|
/* Compare the property set stream with the corresponding one
|
|
* from the origin file and check whether they are equal. */
|
|
assertEquals(ps1, ps2);
|
|
}
|
|
|
|
/**
|
|
* Tests that when using NPOIFS, we can do an in-place write
|
|
* without needing to stream in + out the whole kitchen sink
|
|
*/
|
|
@Test
|
|
public void inPlaceNPOIFSWrite() throws Exception {
|
|
POIFSFileSystem fs;
|
|
DirectoryEntry root;
|
|
DocumentNode sinfDoc;
|
|
DocumentNode dinfDoc;
|
|
SummaryInformation sinf;
|
|
DocumentSummaryInformation dinf;
|
|
|
|
// We need to work on a File for in-place changes, so create a temp one
|
|
final File copy = TempFile.createTempFile("Test-HPSF", "ole2");
|
|
copy.deleteOnExit();
|
|
|
|
// Copy a test file over to our temp location
|
|
InputStream inp = _samples.openResourceAsStream("TestShiftJIS.doc");
|
|
FileOutputStream out = new FileOutputStream(copy);
|
|
IOUtils.copy(inp, out);
|
|
inp.close();
|
|
out.close();
|
|
|
|
|
|
// Open the copy in read/write mode
|
|
fs = new POIFSFileSystem(copy, false);
|
|
root = fs.getRoot();
|
|
|
|
|
|
// Read the properties in there
|
|
sinfDoc = (DocumentNode)root.getEntry(SummaryInformation.DEFAULT_STREAM_NAME);
|
|
dinfDoc = (DocumentNode)root.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
|
|
|
InputStream sinfStream = new DocumentInputStream(sinfDoc);
|
|
sinf = (SummaryInformation)PropertySetFactory.create(sinfStream);
|
|
sinfStream.close();
|
|
assertEquals(131077, sinf.getOSVersion());
|
|
|
|
InputStream dinfStream = new DocumentInputStream(dinfDoc);
|
|
dinf = (DocumentSummaryInformation)PropertySetFactory.create(dinfStream);
|
|
dinfStream.close();
|
|
assertEquals(131077, dinf.getOSVersion());
|
|
|
|
|
|
// Check they start as we expect
|
|
assertEquals("Reiichiro Hori", sinf.getAuthor());
|
|
assertEquals("Microsoft Word 9.0", sinf.getApplicationName());
|
|
assertEquals("\u7b2c1\u7ae0", sinf.getTitle());
|
|
|
|
assertEquals("", dinf.getCompany());
|
|
assertNull(dinf.getManager());
|
|
|
|
|
|
// Do an in-place replace via an InputStream
|
|
assertNotNull(sinfDoc);
|
|
assertNotNull(dinfDoc);
|
|
|
|
new POIFSDocument(sinfDoc).replaceContents(sinf.toInputStream());
|
|
new POIFSDocument(dinfDoc).replaceContents(dinf.toInputStream());
|
|
|
|
|
|
// Check it didn't get changed
|
|
sinfDoc = (DocumentNode)root.getEntry(SummaryInformation.DEFAULT_STREAM_NAME);
|
|
dinfDoc = (DocumentNode)root.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
|
|
|
InputStream sinfStream2 = new DocumentInputStream(sinfDoc);
|
|
sinf = (SummaryInformation)PropertySetFactory.create(sinfStream2);
|
|
sinfStream2.close();
|
|
assertEquals(131077, sinf.getOSVersion());
|
|
|
|
InputStream dinfStream2 = new DocumentInputStream(dinfDoc);
|
|
dinf = (DocumentSummaryInformation)PropertySetFactory.create(dinfStream2);
|
|
dinfStream2.close();
|
|
assertEquals(131077, dinf.getOSVersion());
|
|
|
|
|
|
// Start again!
|
|
fs.close();
|
|
inp = _samples.openResourceAsStream("TestShiftJIS.doc");
|
|
out = new FileOutputStream(copy);
|
|
IOUtils.copy(inp, out);
|
|
inp.close();
|
|
out.close();
|
|
|
|
fs = new POIFSFileSystem(copy, false);
|
|
root = fs.getRoot();
|
|
|
|
// Read the properties in once more
|
|
sinfDoc = (DocumentNode)root.getEntry(SummaryInformation.DEFAULT_STREAM_NAME);
|
|
dinfDoc = (DocumentNode)root.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
|
|
|
InputStream sinfStream3 = new DocumentInputStream(sinfDoc);
|
|
sinf = (SummaryInformation)PropertySetFactory.create(sinfStream3);
|
|
sinfStream3.close();
|
|
assertEquals(131077, sinf.getOSVersion());
|
|
|
|
InputStream dinfStream3 = new DocumentInputStream(dinfDoc);
|
|
dinf = (DocumentSummaryInformation)PropertySetFactory.create(dinfStream3);
|
|
dinfStream3.close();
|
|
assertEquals(131077, dinf.getOSVersion());
|
|
|
|
|
|
// Have them write themselves in-place with no changes, as an OutputStream
|
|
OutputStream soufStream = new DocumentOutputStream(sinfDoc);
|
|
sinf.write(soufStream);
|
|
soufStream.close();
|
|
OutputStream doufStream = new DocumentOutputStream(dinfDoc);
|
|
dinf.write(doufStream);
|
|
doufStream.close();
|
|
|
|
// And also write to some bytes for checking
|
|
ByteArrayOutputStream sinfBytes = new ByteArrayOutputStream();
|
|
sinf.write(sinfBytes);
|
|
ByteArrayOutputStream dinfBytes = new ByteArrayOutputStream();
|
|
dinf.write(dinfBytes);
|
|
|
|
|
|
// Check that the filesystem can give us back the same bytes
|
|
sinfDoc = (DocumentNode)root.getEntry(SummaryInformation.DEFAULT_STREAM_NAME);
|
|
dinfDoc = (DocumentNode)root.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
|
|
|
InputStream sinfStream4 = new DocumentInputStream(sinfDoc);
|
|
byte[] sinfData = IOUtils.toByteArray(sinfStream4);
|
|
sinfStream4.close();
|
|
InputStream dinfStream4 = new DocumentInputStream(dinfDoc);
|
|
byte[] dinfData = IOUtils.toByteArray(dinfStream4);
|
|
dinfStream4.close();
|
|
assertThat(sinfBytes.toByteArray(), equalTo(sinfData));
|
|
assertThat(dinfBytes.toByteArray(), equalTo(dinfData));
|
|
|
|
|
|
// Read back in as-is
|
|
InputStream sinfStream5 = new DocumentInputStream(sinfDoc);
|
|
sinf = (SummaryInformation)PropertySetFactory.create(sinfStream5);
|
|
sinfStream5.close();
|
|
assertEquals(131077, sinf.getOSVersion());
|
|
|
|
InputStream dinfStream5 = new DocumentInputStream(dinfDoc);
|
|
dinf = (DocumentSummaryInformation)PropertySetFactory.create(dinfStream5);
|
|
dinfStream5.close();
|
|
assertEquals(131077, dinf.getOSVersion());
|
|
|
|
assertEquals("Reiichiro Hori", sinf.getAuthor());
|
|
assertEquals("Microsoft Word 9.0", sinf.getApplicationName());
|
|
assertEquals("\u7b2c1\u7ae0", sinf.getTitle());
|
|
|
|
assertEquals("", dinf.getCompany());
|
|
assertNull(dinf.getManager());
|
|
|
|
|
|
// Now alter a few of them
|
|
sinf.setAuthor("Changed Author");
|
|
sinf.setTitle("Le titre \u00e9tait chang\u00e9");
|
|
dinf.setManager("Changed Manager");
|
|
|
|
|
|
// Save this into the filesystem
|
|
OutputStream soufStream2 = new DocumentOutputStream(sinfDoc);
|
|
sinf.write(soufStream2);
|
|
soufStream2.close();
|
|
OutputStream doufStream2 = new DocumentOutputStream(dinfDoc);
|
|
dinf.write(doufStream2);
|
|
doufStream2.close();
|
|
|
|
|
|
// Read them back in again
|
|
sinfDoc = (DocumentNode)root.getEntry(SummaryInformation.DEFAULT_STREAM_NAME);
|
|
InputStream sinfStream6 = new DocumentInputStream(sinfDoc);
|
|
sinf = (SummaryInformation)PropertySetFactory.create(sinfStream6);
|
|
sinfStream6.close();
|
|
assertEquals(131077, sinf.getOSVersion());
|
|
|
|
dinfDoc = (DocumentNode)root.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
|
InputStream dinfStream6 = new DocumentInputStream(dinfDoc);
|
|
dinf = (DocumentSummaryInformation)PropertySetFactory.create(dinfStream6);
|
|
dinfStream6.close();
|
|
assertEquals(131077, dinf.getOSVersion());
|
|
|
|
assertEquals("Changed Author", sinf.getAuthor());
|
|
assertEquals("Microsoft Word 9.0", sinf.getApplicationName());
|
|
assertEquals("Le titre \u00e9tait chang\u00e9", sinf.getTitle());
|
|
|
|
assertEquals("", dinf.getCompany());
|
|
assertEquals("Changed Manager", dinf.getManager());
|
|
|
|
|
|
// Close the whole filesystem, and open it once more
|
|
fs.writeFilesystem();
|
|
fs.close();
|
|
|
|
fs = new POIFSFileSystem(copy);
|
|
root = fs.getRoot();
|
|
|
|
// Re-check on load
|
|
sinfDoc = (DocumentNode)root.getEntry(SummaryInformation.DEFAULT_STREAM_NAME);
|
|
InputStream sinfStream7 = new DocumentInputStream(sinfDoc);
|
|
sinf = (SummaryInformation)PropertySetFactory.create(sinfStream7);
|
|
sinfStream7.close();
|
|
assertEquals(131077, sinf.getOSVersion());
|
|
|
|
dinfDoc = (DocumentNode)root.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
|
InputStream dinfStream7 = new DocumentInputStream(dinfDoc);
|
|
dinf = (DocumentSummaryInformation)PropertySetFactory.create(dinfStream7);
|
|
dinfStream7.close();
|
|
assertEquals(131077, dinf.getOSVersion());
|
|
|
|
assertEquals("Changed Author", sinf.getAuthor());
|
|
assertEquals("Microsoft Word 9.0", sinf.getApplicationName());
|
|
assertEquals("Le titre \u00e9tait chang\u00e9", sinf.getTitle());
|
|
|
|
assertEquals("", dinf.getCompany());
|
|
assertEquals("Changed Manager", dinf.getManager());
|
|
|
|
|
|
// Tidy up
|
|
fs.close();
|
|
//noinspection ResultOfMethodCallIgnored
|
|
copy.delete();
|
|
}
|
|
|
|
|
|
/**
|
|
* Tests writing and reading back a proper dictionary with an invalid
|
|
* codepage. (HPSF writes Unicode dictionaries only.)
|
|
*/
|
|
@Test(expected=UnsupportedEncodingException.class)
|
|
public void dictionaryWithInvalidCodepage() throws IOException, HPSFException {
|
|
final File copy = TempFile.createTempFile("Test-HPSF", "ole2");
|
|
copy.deleteOnExit();
|
|
|
|
/* Write: */
|
|
|
|
final PropertySet ps1 = new PropertySet();
|
|
final Section s = ps1.getSections().get(0);
|
|
final Map<Long,String> m = new HashMap<>(3, 1.0f);
|
|
m.put(1L, "String 1");
|
|
m.put(2L, "String 2");
|
|
m.put(3L, "String 3");
|
|
|
|
try (OutputStream out = new FileOutputStream(copy);
|
|
POIFSFileSystem poiFs = new POIFSFileSystem()) {
|
|
s.setDictionary(m);
|
|
s.setFormatID(DocumentSummaryInformation.FORMAT_ID[0]);
|
|
int codepage = 12345;
|
|
s.setProperty(PropertyIDMap.PID_CODEPAGE, Variant.VT_I2, codepage);
|
|
poiFs.createDocument(ps1.toInputStream(), "Test");
|
|
poiFs.writeFilesystem(out);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* <p>Returns the display name of the default character set.</p>
|
|
*
|
|
* @return the display name of the default character set.
|
|
*/
|
|
private static String getDefaultCharsetName() {
|
|
final String charSetName = System.getProperty("file.encoding");
|
|
final Charset charSet = Charset.forName(charSetName);
|
|
return charSet.displayName(Locale.ROOT);
|
|
}
|
|
|
|
/**
|
|
* <p>In order to execute tests with characters beyond US-ASCII, this
|
|
* method checks whether the application is runing in an environment
|
|
* where the default character set is 16-bit-capable.</p>
|
|
*
|
|
* @return <code>true</code> if the default character set is 16-bit-capable,
|
|
* else <code>false</code>.
|
|
*/
|
|
private boolean hasProperDefaultCharset() {
|
|
final String charSetName = System.getProperty("file.encoding");
|
|
final Charset charSet = Charset.forName(charSetName);
|
|
return charSet.newEncoder().canEncode('\u00e4');
|
|
}
|
|
}
|