001: /* ====================================================================
002: Licensed to the Apache Software Foundation (ASF) under one or more
003: contributor license agreements. See the NOTICE file distributed with
004: this work for additional information regarding copyright ownership.
005: The ASF licenses this file to You under the Apache License, Version 2.0
006: (the "License"); you may not use this file except in compliance with
007: the License. You may obtain a copy of the License at
008:
009: http://www.apache.org/licenses/LICENSE-2.0
010:
011: Unless required by applicable law or agreed to in writing, software
012: distributed under the License is distributed on an "AS IS" BASIS,
013: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: See the License for the specific language governing permissions and
015: limitations under the License.
016: ==================================================================== */
017:
018: package org.apache.poi.hpsf.basic;
019:
020: import java.io.ByteArrayInputStream;
021: import java.io.ByteArrayOutputStream;
022: import java.io.File;
023: import java.io.FileFilter;
024: import java.io.FileInputStream;
025: import java.io.FileOutputStream;
026: import java.io.IOException;
027: import java.io.InputStream;
028: import java.io.OutputStream;
029: import java.io.PrintWriter;
030: import java.io.StringWriter;
031: import java.io.UnsupportedEncodingException;
032: import java.nio.charset.Charset;
033: import java.util.Date;
034: import java.util.HashMap;
035: import java.util.Map;
036:
037: import junit.framework.Assert;
038: import junit.framework.TestCase;
039:
040: import org.apache.poi.hpsf.ClassID;
041: import org.apache.poi.hpsf.Constants;
042: import org.apache.poi.hpsf.HPSFRuntimeException;
043: import org.apache.poi.hpsf.IllegalPropertySetDataException;
044: import org.apache.poi.hpsf.MutableProperty;
045: import org.apache.poi.hpsf.MutablePropertySet;
046: import org.apache.poi.hpsf.MutableSection;
047: import org.apache.poi.hpsf.NoFormatIDException;
048: import org.apache.poi.hpsf.NoPropertySetStreamException;
049: import org.apache.poi.hpsf.PropertySet;
050: import org.apache.poi.hpsf.PropertySetFactory;
051: import org.apache.poi.hpsf.ReadingNotSupportedException;
052: import org.apache.poi.hpsf.Section;
053: import org.apache.poi.hpsf.SummaryInformation;
054: import org.apache.poi.hpsf.UnsupportedVariantTypeException;
055: import org.apache.poi.hpsf.Variant;
056: import org.apache.poi.hpsf.VariantSupport;
057: import org.apache.poi.hpsf.WritingNotSupportedException;
058: import org.apache.poi.hpsf.wellknown.PropertyIDMap;
059: import org.apache.poi.hpsf.wellknown.SectionIDMap;
060: import org.apache.poi.poifs.eventfilesystem.POIFSReader;
061: import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
062: import org.apache.poi.poifs.eventfilesystem.POIFSReaderListener;
063: import org.apache.poi.poifs.filesystem.POIFSFileSystem;
064: import org.apache.poi.util.LittleEndian;
065: import org.apache.poi.util.TempFile;
066:
067: /**
068: * <p>Tests HPSF's writing functionality.</p>
069: *
070: * @author Rainer Klute (klute@rainer-klute.de)
071: * @since 2003-02-07
072: * @version $Id: TestWrite.java 489730 2006-12-22 19:18:16Z bayard $
073: */
074: public class TestWrite extends TestCase {
075:
076: static final String POI_FS = "TestHPSFWritingFunctionality.doc";
077:
078: static final int BYTE_ORDER = 0xfffe;
079: static final int FORMAT = 0x0000;
080: static final int OS_VERSION = 0x00020A04;
081: static final int[] SECTION_COUNT = { 1, 2 };
082: static final boolean[] IS_SUMMARY_INFORMATION = { true, false };
083: static final boolean[] IS_DOCUMENT_SUMMARY_INFORMATION = { false,
084: true };
085:
086: final String IMPROPER_DEFAULT_CHARSET_MESSAGE = "Your default character set is "
087: + getDefaultCharsetName()
088: + ". However, this testcase must be run in an environment "
089: + "with a default character set supporting at least "
090: + "8-bit-characters. You can achieve this by setting the "
091: + "LANG environment variable to a proper value, e.g. "
092: + "\"de_DE\".";
093:
094: POIFile[] poiFiles;
095:
096: /**
097: * <p>Constructor</p>
098: *
099: * @param name the test case's name
100: */
101: public TestWrite(final String name) {
102: super (name);
103: }
104:
105: /**
106: * @see TestCase#setUp()
107: */
108: public void setUp() {
109: VariantSupport.setLogUnsupportedTypes(false);
110: }
111:
112: /**
113: * <p>Writes an empty property set to a POIFS and reads it back
114: * in.</p>
115: *
116: * @exception IOException if an I/O exception occurs
117: */
118: public void testNoFormatID() throws IOException {
119: final String dataDirName = System
120: .getProperty("HPSF.testdata.path");
121: final File dataDir = new File(dataDirName);
122: final File filename = new File(dataDir, POI_FS);
123: filename.deleteOnExit();
124:
125: /* Create a mutable property set with a section that does not have the
126: * formatID set: */
127: final OutputStream out = new FileOutputStream(filename);
128: final POIFSFileSystem poiFs = new POIFSFileSystem();
129: final MutablePropertySet ps = new MutablePropertySet();
130: ps.clearSections();
131: ps.addSection(new MutableSection());
132:
133: /* Write it to a POIFS and the latter to disk: */
134: try {
135: final ByteArrayOutputStream psStream = new ByteArrayOutputStream();
136: ps.write(psStream);
137: psStream.close();
138: final byte[] streamData = psStream.toByteArray();
139: poiFs.createDocument(new ByteArrayInputStream(streamData),
140: SummaryInformation.DEFAULT_STREAM_NAME);
141: poiFs.writeFilesystem(out);
142: out.close();
143: Assert.fail("Should have thrown a NoFormatIDException.");
144: } catch (Exception ex) {
145: Assert.assertTrue(ex instanceof NoFormatIDException);
146: } finally {
147: out.close();
148: }
149: }
150:
151: /**
152: * <p>Writes an empty property set to a POIFS and reads it back
153: * in.</p>
154: *
155: * @exception IOException if an I/O exception occurs
156: * @exception UnsupportedVariantTypeException if HPSF does not yet support
157: * a variant type to be written
158: */
159: public void testWriteEmptyPropertySet() throws IOException,
160: UnsupportedVariantTypeException {
161: final File dataDir = new File(System
162: .getProperty("HPSF.testdata.path"));
163: final File filename = new File(dataDir, POI_FS);
164: filename.deleteOnExit();
165:
166: /* Create a mutable property set and write it to a POIFS: */
167: final OutputStream out = new FileOutputStream(filename);
168: final POIFSFileSystem poiFs = new POIFSFileSystem();
169: final MutablePropertySet ps = new MutablePropertySet();
170: final MutableSection s = (MutableSection) ps.getSections().get(
171: 0);
172: s.setFormatID(SectionIDMap.SUMMARY_INFORMATION_ID);
173:
174: final ByteArrayOutputStream psStream = new ByteArrayOutputStream();
175: ps.write(psStream);
176: psStream.close();
177: final byte[] streamData = psStream.toByteArray();
178: poiFs.createDocument(new ByteArrayInputStream(streamData),
179: SummaryInformation.DEFAULT_STREAM_NAME);
180: poiFs.writeFilesystem(out);
181: out.close();
182:
183: /* Read the POIFS: */
184: final POIFSReader r = new POIFSReader();
185: r.registerListener(new MyPOIFSReaderListener(),
186: SummaryInformation.DEFAULT_STREAM_NAME);
187: r.read(new FileInputStream(filename));
188: }
189:
190: /**
191: * <p>Writes a simple property set with a SummaryInformation section to a
192: * POIFS and reads it back in.</p>
193: *
194: * @exception IOException if an I/O exception occurs
195: * @exception UnsupportedVariantTypeException if HPSF does not yet support
196: * a variant type to be written
197: */
198: public void testWriteSimplePropertySet() throws IOException,
199: UnsupportedVariantTypeException {
200: final String AUTHOR = "Rainer Klute";
201: final String TITLE = "Test Document";
202: final File dataDir = new File(System
203: .getProperty("HPSF.testdata.path"));
204: final File filename = new File(dataDir, POI_FS);
205: filename.deleteOnExit();
206: final OutputStream out = new FileOutputStream(filename);
207: final POIFSFileSystem poiFs = new POIFSFileSystem();
208:
209: final MutablePropertySet ps = new MutablePropertySet();
210: final MutableSection si = new MutableSection();
211: si.setFormatID(SectionIDMap.SUMMARY_INFORMATION_ID);
212: ps.getSections().set(0, si);
213:
214: final MutableProperty p = new MutableProperty();
215: p.setID(PropertyIDMap.PID_AUTHOR);
216: p.setType(Variant.VT_LPWSTR);
217: p.setValue(AUTHOR);
218: si.setProperty(p);
219: si
220: .setProperty(PropertyIDMap.PID_TITLE, Variant.VT_LPSTR,
221: TITLE);
222:
223: poiFs.createDocument(ps.toInputStream(),
224: SummaryInformation.DEFAULT_STREAM_NAME);
225: poiFs.writeFilesystem(out);
226: out.close();
227:
228: /* Read the POIFS: */
229: final PropertySet[] psa = new PropertySet[1];
230: final POIFSReader r = new POIFSReader();
231: r.registerListener(new POIFSReaderListener() {
232: public void processPOIFSReaderEvent(
233: final POIFSReaderEvent event) {
234: try {
235: psa[0] = PropertySetFactory.create(event
236: .getStream());
237: } catch (Exception ex) {
238: fail(org.apache.poi.hpsf.Util.toString(ex));
239: }
240: }
241:
242: }, SummaryInformation.DEFAULT_STREAM_NAME);
243: r.read(new FileInputStream(filename));
244: Assert.assertNotNull(psa[0]);
245: Assert.assertTrue(psa[0].isSummaryInformation());
246:
247: final Section s = (Section) (psa[0].getSections().get(0));
248: Object p1 = s.getProperty(PropertyIDMap.PID_AUTHOR);
249: Object p2 = s.getProperty(PropertyIDMap.PID_TITLE);
250: Assert.assertEquals(AUTHOR, p1);
251: Assert.assertEquals(TITLE, p2);
252: }
253:
254: /**
255: * <p>Writes a simple property set with two sections to a POIFS and reads it
256: * back in.</p>
257: *
258: * @exception IOException if an I/O exception occurs
259: * @exception WritingNotSupportedException if HPSF does not yet support
260: * a variant type to be written
261: */
262: public void testWriteTwoSections()
263: throws WritingNotSupportedException, IOException {
264: final String STREAM_NAME = "PropertySetStream";
265: final String SECTION1 = "Section 1";
266: final String SECTION2 = "Section 2";
267:
268: final File dataDir = new File(System
269: .getProperty("HPSF.testdata.path"));
270: final File filename = new File(dataDir, POI_FS);
271: filename.deleteOnExit();
272: final OutputStream out = new FileOutputStream(filename);
273:
274: final POIFSFileSystem poiFs = new POIFSFileSystem();
275: final MutablePropertySet ps = new MutablePropertySet();
276: ps.clearSections();
277:
278: final ClassID formatID = new ClassID();
279: formatID.setBytes(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
280: 10, 11, 12, 13, 14, 15 });
281: final MutableSection s1 = new MutableSection();
282: s1.setFormatID(formatID);
283: s1.setProperty(2, SECTION1);
284: ps.addSection(s1);
285:
286: final MutableSection s2 = new MutableSection();
287: s2.setFormatID(formatID);
288: s2.setProperty(2, SECTION2);
289: ps.addSection(s2);
290:
291: poiFs.createDocument(ps.toInputStream(), STREAM_NAME);
292: poiFs.writeFilesystem(out);
293: out.close();
294:
295: /* Read the POIFS: */
296: final PropertySet[] psa = new PropertySet[1];
297: final POIFSReader r = new POIFSReader();
298: r.registerListener(new POIFSReaderListener() {
299: public void processPOIFSReaderEvent(
300: final POIFSReaderEvent event) {
301: try {
302: psa[0] = PropertySetFactory.create(event
303: .getStream());
304: } catch (Exception ex) {
305: ex.printStackTrace();
306: throw new RuntimeException(ex.toString());
307: /* FIXME (2): Replace the previous line by the following
308: * one once we no longer need JDK 1.3 compatibility. */
309: // throw new RuntimeException(ex);
310: }
311: }
312: }, STREAM_NAME);
313: r.read(new FileInputStream(filename));
314: Assert.assertNotNull(psa[0]);
315: Section s = (Section) (psa[0].getSections().get(0));
316: assertEquals(s.getFormatID(), formatID);
317: Object p = s.getProperty(2);
318: Assert.assertEquals(SECTION1, p);
319: s = (Section) (psa[0].getSections().get(1));
320: p = s.getProperty(2);
321: Assert.assertEquals(SECTION2, p);
322: }
323:
324: static class MyPOIFSReaderListener implements POIFSReaderListener {
325: public void processPOIFSReaderEvent(final POIFSReaderEvent event) {
326: try {
327: PropertySetFactory.create(event.getStream());
328: } catch (Exception ex) {
329: fail(org.apache.poi.hpsf.Util.toString(ex));
330: }
331: }
332: }
333:
334: private static final int CODEPAGE_DEFAULT = -1;
335: private static final int CODEPAGE_1252 = 1252;
336: private static final int CODEPAGE_UTF8 = Constants.CP_UTF8;
337: private static final int CODEPAGE_UTF16 = Constants.CP_UTF16;
338:
339: /**
340: * <p>Writes and reads back various variant types and checks whether the
341: * stuff that has been read back equals the stuff that was written.</p>
342: */
343: public void testVariantTypes() {
344: Throwable t = null;
345: final int codepage = CODEPAGE_DEFAULT;
346: if (!hasProperDefaultCharset()) {
347: System.err.println(IMPROPER_DEFAULT_CHARSET_MESSAGE
348: + " This testcase is skipped.");
349: return;
350: }
351:
352: try {
353: check(Variant.VT_EMPTY, null, codepage);
354: check(Variant.VT_BOOL, new Boolean(true), codepage);
355: check(Variant.VT_BOOL, new Boolean(false), codepage);
356: check(Variant.VT_CF, new byte[] { 0 }, codepage);
357: check(Variant.VT_CF, new byte[] { 0, 1 }, codepage);
358: check(Variant.VT_CF, new byte[] { 0, 1, 2 }, codepage);
359: check(Variant.VT_CF, new byte[] { 0, 1, 2, 3 }, codepage);
360: check(Variant.VT_CF, new byte[] { 0, 1, 2, 3, 4 }, codepage);
361: check(Variant.VT_CF, new byte[] { 0, 1, 2, 3, 4, 5 },
362: codepage);
363: check(Variant.VT_CF, new byte[] { 0, 1, 2, 3, 4, 5, 6 },
364: codepage);
365: check(Variant.VT_CF, new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 },
366: codepage);
367: check(Variant.VT_I4, new Integer(27), codepage);
368: check(Variant.VT_I8, new Long(28), codepage);
369: check(Variant.VT_R8, new Double(29.0), codepage);
370: check(Variant.VT_I4, new Integer(-27), codepage);
371: check(Variant.VT_I8, new Long(-28), codepage);
372: check(Variant.VT_R8, new Double(-29.0), codepage);
373: check(Variant.VT_FILETIME, new Date(), codepage);
374: check(Variant.VT_I4, new Integer(Integer.MAX_VALUE),
375: codepage);
376: check(Variant.VT_I4, new Integer(Integer.MIN_VALUE),
377: codepage);
378: check(Variant.VT_I8, new Long(Long.MAX_VALUE), codepage);
379: check(Variant.VT_I8, new Long(Long.MIN_VALUE), codepage);
380: check(Variant.VT_R8, new Double(Double.MAX_VALUE), codepage);
381: check(Variant.VT_R8, new Double(Double.MIN_VALUE), codepage);
382:
383: check(Variant.VT_LPSTR, "", codepage);
384: check(Variant.VT_LPSTR, "\u00e4", codepage);
385: check(Variant.VT_LPSTR, "\u00e4\u00f6", codepage);
386: check(Variant.VT_LPSTR, "\u00e4\u00f6\u00fc", codepage);
387: check(Variant.VT_LPSTR, "\u00e4\u00f6\u00fc\u00df",
388: codepage);
389: check(Variant.VT_LPSTR, "\u00e4\u00f6\u00fc\u00df\u00c4",
390: codepage);
391: check(Variant.VT_LPSTR,
392: "\u00e4\u00f6\u00fc\u00df\u00c4\u00d6", codepage);
393: check(Variant.VT_LPSTR,
394: "\u00e4\u00f6\u00fc\u00df\u00c4\u00d6\u00dc",
395: codepage);
396:
397: check(Variant.VT_LPWSTR, "", codepage);
398: check(Variant.VT_LPWSTR, "\u00e4", codepage);
399: check(Variant.VT_LPWSTR, "\u00e4\u00f6", codepage);
400: check(Variant.VT_LPWSTR, "\u00e4\u00f6\u00fc", codepage);
401: check(Variant.VT_LPWSTR, "\u00e4\u00f6\u00fc\u00df",
402: codepage);
403: check(Variant.VT_LPWSTR, "\u00e4\u00f6\u00fc\u00df\u00c4",
404: codepage);
405: check(Variant.VT_LPWSTR,
406: "\u00e4\u00f6\u00fc\u00df\u00c4\u00d6", codepage);
407: check(Variant.VT_LPWSTR,
408: "\u00e4\u00f6\u00fc\u00df\u00c4\u00d6\u00dc",
409: codepage);
410: } catch (Exception ex) {
411: t = ex;
412: } catch (Error ex) {
413: t = ex;
414: }
415: if (t != null)
416: fail(org.apache.poi.hpsf.Util.toString(t));
417: }
418:
419: /**
420: * <p>Writes and reads back strings using several different codepages and
421: * checks whether the stuff that has been read back equals the stuff that
422: * was written.</p>
423: */
424: public void testCodepages() {
425: Throwable thr = null;
426: final int[] validCodepages = new int[] { CODEPAGE_DEFAULT,
427: CODEPAGE_UTF8, CODEPAGE_UTF16, CODEPAGE_1252 };
428: for (int i = 0; i < validCodepages.length; i++) {
429: final int cp = validCodepages[i];
430: if (cp == -1 && !hasProperDefaultCharset()) {
431: System.err
432: .println(IMPROPER_DEFAULT_CHARSET_MESSAGE
433: + " This testcase is skipped for the default codepage.");
434: continue;
435: }
436:
437: final long t = cp == CODEPAGE_UTF16 ? Variant.VT_LPWSTR
438: : Variant.VT_LPSTR;
439: try {
440: check(t, "", cp);
441: check(t, "\u00e4", cp);
442: check(t, "\u00e4\u00f6", cp);
443: check(t, "\u00e4\u00f6\u00fc", cp);
444: check(t, "\u00e4\u00f6\u00fc\u00c4", cp);
445: check(t, "\u00e4\u00f6\u00fc\u00c4\u00d6", cp);
446: check(t, "\u00e4\u00f6\u00fc\u00c4\u00d6\u00dc", cp);
447: check(t, "\u00e4\u00f6\u00fc\u00c4\u00d6\u00dc\u00df",
448: cp);
449: if (cp == Constants.CP_UTF16 || cp == Constants.CP_UTF8)
450: check(t, "\u79D1\u5B78", cp);
451: } catch (Exception ex) {
452: thr = ex;
453: } catch (Error ex) {
454: thr = ex;
455: }
456: if (thr != null)
457: fail(org.apache.poi.hpsf.Util.toString(thr)
458: + " with codepage " + cp);
459: }
460:
461: final int[] invalidCodepages = new int[] { 0, 1, 2, 4711, 815 };
462: for (int i = 0; i < invalidCodepages.length; i++) {
463: int cp = invalidCodepages[i];
464: final long type = cp == CODEPAGE_UTF16 ? Variant.VT_LPWSTR
465: : Variant.VT_LPSTR;
466: try {
467: check(type, "", cp);
468: check(type, "\u00e4", cp);
469: check(type, "\u00e4\u00f6", cp);
470: check(type, "\u00e4\u00f6\u00fc", cp);
471: check(type, "\u00e4\u00f6\u00fc\u00c4", cp);
472: check(type, "\u00e4\u00f6\u00fc\u00c4\u00d6", cp);
473: check(type, "\u00e4\u00f6\u00fc\u00c4\u00d6\u00dc", cp);
474: check(type,
475: "\u00e4\u00f6\u00fc\u00c4\u00d6\u00dc\u00df",
476: cp);
477: fail("UnsupportedEncodingException for codepage " + cp
478: + " expected.");
479: } catch (UnsupportedEncodingException ex) {
480: /* This is the expected behaviour. */
481: } catch (Exception ex) {
482: thr = ex;
483: } catch (Error ex) {
484: thr = ex;
485: }
486: if (thr != null)
487: fail(org.apache.poi.hpsf.Util.toString(thr));
488: }
489:
490: }
491:
492: /**
493: * <p>Tests whether writing 8-bit characters to a Unicode property
494: * succeeds.</p>
495: */
496: public void testUnicodeWrite8Bit() {
497: final String TITLE = "This is a sample title";
498: final MutablePropertySet mps = new MutablePropertySet();
499: final MutableSection ms = (MutableSection) mps.getSections()
500: .get(0);
501: ms.setFormatID(SectionIDMap.SUMMARY_INFORMATION_ID);
502: final MutableProperty p = new MutableProperty();
503: p.setID(PropertyIDMap.PID_TITLE);
504: p.setType(Variant.VT_LPSTR);
505: p.setValue(TITLE);
506: ms.setProperty(p);
507:
508: Throwable t = null;
509: try {
510: ByteArrayOutputStream out = new ByteArrayOutputStream();
511: mps.write(out);
512: out.close();
513: byte[] bytes = out.toByteArray();
514:
515: PropertySet psr = new PropertySet(bytes);
516: assertTrue(psr.isSummaryInformation());
517: Section sr = (Section) psr.getSections().get(0);
518: String title = (String) sr
519: .getProperty(PropertyIDMap.PID_TITLE);
520: assertEquals(TITLE, title);
521: } catch (WritingNotSupportedException e) {
522: t = e;
523: } catch (IOException e) {
524: t = e;
525: } catch (NoPropertySetStreamException e) {
526: t = e;
527: }
528: if (t != null)
529: fail(t.getMessage());
530: }
531:
532: /**
533: * <p>Writes a property and reads it back in.</p>
534: *
535: * @param variantType The property's variant type.
536: * @param value The property's value.
537: * @param codepage The codepage to use for writing and reading.
538: * @throws UnsupportedVariantTypeException if the variant is not supported.
539: * @throws IOException if an I/O exception occurs.
540: * @throws ReadingNotSupportedException
541: * @throws UnsupportedEncodingException
542: */
543: private void check(final long variantType, final Object value,
544: final int codepage) throws UnsupportedVariantTypeException,
545: IOException, ReadingNotSupportedException,
546: UnsupportedEncodingException {
547: final ByteArrayOutputStream out = new ByteArrayOutputStream();
548: VariantSupport.write(out, variantType, value, codepage);
549: out.close();
550: final byte[] b = out.toByteArray();
551: final Object objRead = VariantSupport.read(b, 0, b.length
552: + LittleEndian.INT_SIZE, variantType, codepage);
553: if (objRead instanceof byte[]) {
554: final int diff = diff((byte[]) value, (byte[]) objRead);
555: if (diff >= 0)
556: fail("Byte arrays are different. First different byte is at "
557: + "index " + diff + ".");
558: } else if (value != null && !value.equals(objRead)) {
559: fail("Expected: \""
560: + value
561: + "\" but was: \""
562: + objRead
563: + "\". Codepage: "
564: + codepage
565: + (codepage == -1 ? " ("
566: + System.getProperty("file.encoding")
567: + ")." : "."));
568: } else
569: assertEquals(value, objRead);
570: }
571:
572: /**
573: * <p>Compares two byte arrays.</p>
574: *
575: * @param a The first byte array
576: * @param b The second byte array
577: * @return The index of the first byte that is different. If the byte arrays
578: * are equal, -1 is returned.
579: */
580: private int diff(final byte[] a, final byte[] b) {
581: final int min = Math.min(a.length, b.length);
582: for (int i = 0; i < min; i++)
583: if (a[i] != b[i])
584: return i;
585: if (a.length != b.length)
586: return min;
587: return -1;
588: }
589:
590: /**
591: * <p>This test method does a write and read back test with all POI
592: * filesystems in the "data" directory by performing the following
593: * actions for each file:</p>
594: *
595: * <ul>
596: *
597: * <li><p>Read its property set streams.</p></li>
598: *
599: * <li><p>Create a new POI filesystem containing the origin file's
600: * property set streams.</p></li>
601: *
602: * <li><p>Read the property set streams from the POI filesystem just
603: * created.</p></li>
604: *
605: * <li><p>Compare each property set stream with the corresponding one from
606: * the origin file and check whether they are equal.</p></li>
607: *
608: * </ul>
609: */
610: public void testRecreate() {
611: final File dataDir = new File(System
612: .getProperty("HPSF.testdata.path"));
613: final File[] fileList = dataDir.listFiles(new FileFilter() {
614: public boolean accept(final File f) {
615: return f.getName().startsWith("Test");
616: }
617: });
618: for (int i = 0; i < fileList.length; i++)
619: testRecreate(fileList[i]);
620: }
621:
622: /**
623: * <p>Performs the check described in {@link #testRecreate()} for a single
624: * POI filesystem.</p>
625: *
626: * @param f the POI filesystem to check
627: */
628: private void testRecreate(final File f) {
629: System.out.println("Recreating file \"" + f + "\"");
630: try {
631: /* Read the POI filesystem's property set streams: */
632: final POIFile[] psf1 = Util.readPropertySets(f);
633:
634: /* Create a new POI filesystem containing the origin file's
635: * property set streams: */
636: final File copy = TempFile.createTempFile(f.getName(), "");
637: copy.deleteOnExit();
638: final OutputStream out = new FileOutputStream(copy);
639: final POIFSFileSystem poiFs = new POIFSFileSystem();
640: for (int i = 0; i < psf1.length; i++) {
641: final InputStream in = new ByteArrayInputStream(psf1[i]
642: .getBytes());
643: final PropertySet psIn = PropertySetFactory.create(in);
644: final MutablePropertySet psOut = new MutablePropertySet(
645: psIn);
646: final ByteArrayOutputStream psStream = new ByteArrayOutputStream();
647: psOut.write(psStream);
648: psStream.close();
649: final byte[] streamData = psStream.toByteArray();
650: poiFs.createDocument(new ByteArrayInputStream(
651: streamData), psf1[i].getName());
652: poiFs.writeFilesystem(out);
653: }
654: out.close();
655:
656: /* Read the property set streams from the POI filesystem just
657: * created. */
658: final POIFile[] psf2 = Util.readPropertySets(copy);
659: for (int i = 0; i < psf2.length; i++) {
660: final byte[] bytes1 = psf1[i].getBytes();
661: final byte[] bytes2 = psf2[i].getBytes();
662: final InputStream in1 = new ByteArrayInputStream(bytes1);
663: final InputStream in2 = new ByteArrayInputStream(bytes2);
664: final PropertySet ps1 = PropertySetFactory.create(in1);
665: final PropertySet ps2 = PropertySetFactory.create(in2);
666:
667: /* Compare the property set stream with the corresponding one
668: * from the origin file and check whether they are equal. */
669: assertEquals("Equality for file " + f.getName(), ps1,
670: ps2);
671: }
672: } catch (Exception ex) {
673: handle(ex);
674: }
675: }
676:
677: /**
678: * <p>Tests writing and reading back a proper dictionary.</p>
679: */
680: public void testDictionary() {
681: try {
682: final File copy = TempFile.createTempFile("Test-HPSF",
683: "ole2");
684: copy.deleteOnExit();
685:
686: /* Write: */
687: final OutputStream out = new FileOutputStream(copy);
688: final POIFSFileSystem poiFs = new POIFSFileSystem();
689: final MutablePropertySet ps1 = new MutablePropertySet();
690: final MutableSection s = (MutableSection) ps1.getSections()
691: .get(0);
692: final Map m = new HashMap(3, 1.0f);
693: m.put(new Long(1), "String 1");
694: m.put(new Long(2), "String 2");
695: m.put(new Long(3), "String 3");
696: s.setDictionary(m);
697: s
698: .setFormatID(SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID[0]);
699: int codepage = Constants.CP_UNICODE;
700: s.setProperty(PropertyIDMap.PID_CODEPAGE, Variant.VT_I2,
701: new Integer(codepage));
702: poiFs.createDocument(ps1.toInputStream(), "Test");
703: poiFs.writeFilesystem(out);
704: out.close();
705:
706: /* Read back: */
707: final POIFile[] psf = Util.readPropertySets(copy);
708: Assert.assertEquals(1, psf.length);
709: final byte[] bytes = psf[0].getBytes();
710: final InputStream in = new ByteArrayInputStream(bytes);
711: final PropertySet ps2 = PropertySetFactory.create(in);
712:
713: /* Check if the result is a DocumentSummaryInformation stream, as
714: * specified. */
715: assertTrue(ps2.isDocumentSummaryInformation());
716:
717: /* Compare the property set stream with the corresponding one
718: * from the origin file and check whether they are equal. */
719: assertEquals(ps1, ps2);
720: } catch (Exception ex) {
721: handle(ex);
722: }
723: }
724:
725: /**
726: * <p>Tests writing and reading back a proper dictionary with an invalid
727: * codepage. (HPSF writes Unicode dictionaries only.)</p>
728: */
729: public void testDictionaryWithInvalidCodepage() {
730: try {
731: final File copy = TempFile.createTempFile("Test-HPSF",
732: "ole2");
733: copy.deleteOnExit();
734:
735: /* Write: */
736: final OutputStream out = new FileOutputStream(copy);
737: final POIFSFileSystem poiFs = new POIFSFileSystem();
738: final MutablePropertySet ps1 = new MutablePropertySet();
739: final MutableSection s = (MutableSection) ps1.getSections()
740: .get(0);
741: final Map m = new HashMap(3, 1.0f);
742: m.put(new Long(1), "String 1");
743: m.put(new Long(2), "String 2");
744: m.put(new Long(3), "String 3");
745: s.setDictionary(m);
746: s
747: .setFormatID(SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID[0]);
748: int codepage = 12345;
749: s.setProperty(PropertyIDMap.PID_CODEPAGE, Variant.VT_I2,
750: new Integer(codepage));
751: poiFs.createDocument(ps1.toInputStream(), "Test");
752: poiFs.writeFilesystem(out);
753: out.close();
754: fail("This testcase did not detect the invalid codepage value.");
755: } catch (IllegalPropertySetDataException ex) {
756: assertTrue(true);
757: } catch (Exception ex) {
758: handle(ex);
759: }
760: }
761:
762: /**
763: * <p>Handles unexpected exceptions in testcases.</p>
764: *
765: * @param ex The exception that has been thrown.
766: */
767: private void handle(final Exception ex) {
768: final StringWriter sw = new StringWriter();
769: final PrintWriter pw = new PrintWriter(sw);
770: Throwable t = ex;
771: while (t != null) {
772: t.printStackTrace(pw);
773: if (t instanceof HPSFRuntimeException)
774: t = ((HPSFRuntimeException) t).getReason();
775: else
776: t = null;
777: if (t != null)
778: pw.println("Caused by:");
779: }
780: pw.close();
781: try {
782: sw.close();
783: } catch (IOException ex2) {
784: ex.printStackTrace();
785: }
786: fail(sw.toString());
787: }
788:
789: /**
790: * <p>Returns the display name of the default character set.</p>
791: *
792: * @return the display name of the default character set.
793: */
794: private String getDefaultCharsetName() {
795: final String charSetName = System.getProperty("file.encoding");
796: final Charset charSet = Charset.forName(charSetName);
797: return charSet.displayName();
798: }
799:
800: /**
801: * <p>In order to execute tests with characters beyond US-ASCII, this
802: * method checks whether the application is runing in an environment
803: * where the default character set is 16-bit-capable.</p>
804: *
805: * @return <code>true</code> if the default character set is 16-bit-capable,
806: * else <code>false</code>.
807: */
808: private boolean hasProperDefaultCharset() {
809: final String charSetName = System.getProperty("file.encoding");
810: final Charset charSet = Charset.forName(charSetName);
811: return charSet.newEncoder().canEncode('\u00e4');
812: }
813:
814: /**
815: * <p>Runs the test cases stand-alone.</p>
816: *
817: * @param args The command-line parameters.
818: * @throws Throwable if anything goes wrong.
819: */
820: public static void main(final String[] args) throws Throwable {
821: System.setProperty("HPSF.testdata.path",
822: "./src/testcases/org/apache/poi/hpsf/data");
823: junit.textui.TestRunner.run(TestWrite.class);
824: }
825:
826: }
|