/** * Setup is used to get the document ready. Gets the DocumentSummaryInformation and the * SummaryInformation to reasonable values */ public void setUp() { bout = new ByteArrayOutputStream(); poifs = new POIFSFileSystem(); dir = poifs.getRoot(); dsi = null; try { DocumentEntry dsiEntry = (DocumentEntry) dir.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME); DocumentInputStream dis = new DocumentInputStream(dsiEntry); PropertySet ps = new PropertySet(dis); dis.close(); dsi = new DocumentSummaryInformation(ps); } catch (FileNotFoundException ex) { /* There is no document summary information yet. We have to create a * new one. */ dsi = PropertySetFactory.newDocumentSummaryInformation(); assertNotNull(dsi); } catch (IOException e) { e.printStackTrace(); fail(); } catch (NoPropertySetStreamException e) { e.printStackTrace(); fail(); } catch (MarkUnsupportedException e) { e.printStackTrace(); fail(); } catch (UnexpectedPropertySetTypeException e) { e.printStackTrace(); fail(); } assertNotNull(dsi); try { DocumentEntry dsiEntry = (DocumentEntry) dir.getEntry(SummaryInformation.DEFAULT_STREAM_NAME); DocumentInputStream dis = new DocumentInputStream(dsiEntry); PropertySet ps = new PropertySet(dis); dis.close(); si = new SummaryInformation(ps); } catch (FileNotFoundException ex) { /* There is no document summary information yet. We have to create a * new one. */ si = PropertySetFactory.newSummaryInformation(); assertNotNull(si); } catch (IOException e) { e.printStackTrace(); fail(); } catch (NoPropertySetStreamException e) { e.printStackTrace(); fail(); } catch (MarkUnsupportedException e) { e.printStackTrace(); fail(); } catch (UnexpectedPropertySetTypeException e) { e.printStackTrace(); fail(); } assertNotNull(dsi); }
/** * Writes a {@link PropertySet} to a POI filesystem. * * @param poiFs The POI filesystem to write to. * @param path The file's path in the POI filesystem. * @param name The file's name in the POI filesystem. * @param ps The property set to write. * @throws WritingNotSupportedException * @throws IOException */ public void copy( final POIFSFileSystem poiFs, final POIFSDocumentPath path, final String name, final PropertySet ps) throws WritingNotSupportedException, IOException { final DirectoryEntry de = getPath(poiFs, path); final MutablePropertySet mps = new MutablePropertySet(ps); de.createDocument(name, mps.toInputStream()); }
/** * Compares two {@link DirectoryEntry} instances of a POI file system. The directories must * contain the same streams with the same names and contents. * * @param d1 The first directory. * @param d2 The second directory. * @param msg The method may append human-readable comparison messages to this string buffer. * @return <code>true</code> if the directories are equal, else <code>false</code>. * @exception MarkUnsupportedException if a POI document stream does not support the mark() * operation. * @exception NoPropertySetStreamException if the application tries to create a property set from * a POI document stream that is not a property set stream. * @throws UnsupportedEncodingException * @exception IOException if any I/O exception occurs. */ private static boolean equal( final DirectoryEntry d1, final DirectoryEntry d2, final StringBuffer msg) throws NoPropertySetStreamException, MarkUnsupportedException, UnsupportedEncodingException, IOException { boolean equal = true; /* Iterate over d1 and compare each entry with its counterpart in d2. */ for (final Iterator i = d1.getEntries(); equal && i.hasNext(); ) { final Entry e1 = (Entry) i.next(); final String n1 = e1.getName(); Entry e2 = null; try { e2 = d2.getEntry(n1); } catch (FileNotFoundException ex) { msg.append("Document \"" + e1 + "\" exists, document \"" + e2 + "\" does not.\n"); equal = false; break; } if (e1.isDirectoryEntry() && e2.isDirectoryEntry()) equal = equal((DirectoryEntry) e1, (DirectoryEntry) e2, msg); else if (e1.isDocumentEntry() && e2.isDocumentEntry()) equal = equal((DocumentEntry) e1, (DocumentEntry) e2, msg); else { msg.append( "One of \"" + e1 + "\" and \"" + e2 + "\" is a " + "document while the other one is a directory.\n"); equal = false; } } /* Iterate over d2 just to make sure that there are no entries in d2 * that are not in d1. */ for (final Iterator i = d2.getEntries(); equal && i.hasNext(); ) { final Entry e2 = (Entry) i.next(); final String n2 = e2.getName(); Entry e1 = null; try { e1 = d1.getEntry(n2); } catch (FileNotFoundException ex) { msg.append("Document \"" + e2 + "\" exitsts, document \"" + e1 + "\" does not.\n"); equal = false; break; } } return equal; }
/** * Copies the bytes from a {@link DocumentInputStream} to a new stream in a POI filesystem. * * @param poiFs The POI filesystem to write to. * @param path The source document's path. * @param name The source document's name. * @param stream The stream containing the source document. * @throws IOException */ public void copy( final POIFSFileSystem poiFs, final POIFSDocumentPath path, final String name, final DocumentInputStream stream) throws IOException { final DirectoryEntry de = getPath(poiFs, path); final ByteArrayOutputStream out = new ByteArrayOutputStream(); int c; while ((c = stream.read()) != -1) out.write(c); stream.close(); out.close(); final InputStream in = new ByteArrayInputStream(out.toByteArray()); de.createDocument(name, in); }
/** * Is this one of the kinds of formats which uses CompObj to store all of their data, eg Star * Draw, Star Impress or (older) Works? If not, it's likely an embedded resource */ private static MediaType processCompObjFormatType(DirectoryEntry root) { try { Entry e = root.getEntry("\u0001CompObj"); if (e != null && e.isDocumentEntry()) { DocumentNode dn = (DocumentNode) e; DocumentInputStream stream = new DocumentInputStream(dn); byte[] bytes = IOUtils.toByteArray(stream); /* * This array contains a string with a normal ASCII name of the * application used to create this file. We want to search for that * name. */ if (arrayContains(bytes, MS_GRAPH_CHART_BYTES)) { return MS_GRAPH_CHART; } else if (arrayContains(bytes, STAR_DRAW)) { return SDA; } else if (arrayContains(bytes, STAR_IMPRESS)) { return SDD; } else if (arrayContains(bytes, WORKS_QUILL96)) { return WPS; } } } catch (Exception e) { /* * "root.getEntry" can throw FileNotFoundException. The code inside * "if" can throw IOExceptions. Theoretically. Practically no * exceptions will likely ever appear. * * Swallow all of them. If any occur, we just assume that we can't * distinguish between Draw and Impress and return something safe: * x-tika-msoffice */ } return OLE; }
protected void copy(DirectoryEntry sourceDir, DirectoryEntry destDir) throws IOException { for (org.apache.poi.poifs.filesystem.Entry entry : sourceDir) { if (entry instanceof DirectoryEntry) { // Need to recurse DirectoryEntry newDir = destDir.createDirectory(entry.getName()); copy((DirectoryEntry) entry, newDir); } else { // Copy entry InputStream contents = new DocumentInputStream((DocumentEntry) entry); try { destDir.createDocument(entry.getName(), contents); } finally { contents.close(); } } } }
/** * Ensures that the directory hierarchy for a document in a POI fileystem is in place. When a * document is to be created somewhere in a POI filesystem its directory must be created first. * This method creates all directories between the POI filesystem root and the directory the * document should belong to which do not yet exist. * * <p>Unfortunately POI does not offer a simple method to interrogate the POIFS whether a * certain child node (file or directory) exists in a directory. However, since we always start * with an empty POIFS which contains the root directory only and since each directory in the * POIFS is created by this method we can maintain the POIFS's directory hierarchy ourselves: * The {@link DirectoryEntry} of each directory created is stored in a {@link Map}. The * directories' path names map to the corresponding {@link DirectoryEntry} instances. * * @param poiFs The POI filesystem the directory hierarchy is created in, if needed. * @param path The document's path. This method creates those directory components of this * hierarchy which do not yet exist. * @return The directory entry of the document path's parent. The caller should use this {@link * DirectoryEntry} to create documents in it. */ public DirectoryEntry getPath(final POIFSFileSystem poiFs, final POIFSDocumentPath path) { try { /* Check whether this directory has already been created. */ final String s = path.toString(); DirectoryEntry de = (DirectoryEntry) paths.get(s); if (de != null) /* Yes: return the corresponding DirectoryEntry. */ return de; /* No: We have to create the directory - or return the root's * DirectoryEntry. */ int l = path.length(); if (l == 0) /* Get the root directory. It does not have to be created * since it always exists in a POIFS. */ de = poiFs.getRoot(); else { /* Create a subordinate directory. The first step is to * ensure that the parent directory exists: */ de = getPath(poiFs, path.getParent()); /* Now create the target directory: */ de = de.createDirectory(path.getComponent(path.length() - 1)); } paths.put(s, de); return de; } catch (IOException ex) { /* This exception will be thrown if the directory already * exists. However, since we have full control about directory * creation we can ensure that this will never happen. */ ex.printStackTrace(System.err); throw new RuntimeException(ex.toString()); /* FIXME (2): Replace the previous line by the following once we * no longer need JDK 1.3 compatibility. */ // throw new RuntimeException(ex); } }
/** * Closes the ByteArrayOutputStream and reads it into a ByteArrayInputStream. When finished * writing information this method is used in the tests to start reading from the created document * and then the see if the results match. */ public void closeAndReOpen() { try { dsi.write(dir, DocumentSummaryInformation.DEFAULT_STREAM_NAME); si.write(dir, SummaryInformation.DEFAULT_STREAM_NAME); } catch (WritingNotSupportedException e) { e.printStackTrace(); fail(); } catch (IOException e) { e.printStackTrace(); fail(); } si = null; dsi = null; try { poifs.writeFilesystem(bout); bout.flush(); } catch (IOException e) { e.printStackTrace(); fail(); } InputStream is = new ByteArrayInputStream(bout.toByteArray()); assertNotNull(is); POIFSFileSystem poifs = null; try { poifs = new POIFSFileSystem(is); } catch (IOException e) { e.printStackTrace(); fail(); } try { is.close(); } catch (IOException e) { e.printStackTrace(); fail(); } assertNotNull(poifs); /* Read the document summary information. */ DirectoryEntry dir = poifs.getRoot(); try { DocumentEntry dsiEntry = (DocumentEntry) dir.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME); DocumentInputStream dis = new DocumentInputStream(dsiEntry); PropertySet ps = new PropertySet(dis); dis.close(); dsi = new DocumentSummaryInformation(ps); } catch (FileNotFoundException ex) { fail(); } catch (IOException e) { e.printStackTrace(); fail(); } catch (NoPropertySetStreamException e) { e.printStackTrace(); fail(); } catch (MarkUnsupportedException e) { e.printStackTrace(); fail(); } catch (UnexpectedPropertySetTypeException e) { e.printStackTrace(); fail(); } try { DocumentEntry dsiEntry = (DocumentEntry) dir.getEntry(SummaryInformation.DEFAULT_STREAM_NAME); DocumentInputStream dis = new DocumentInputStream(dsiEntry); PropertySet ps = new PropertySet(dis); dis.close(); si = new SummaryInformation(ps); } catch (FileNotFoundException ex) { /* There is no document summary information yet. We have to create a * new one. */ si = PropertySetFactory.newSummaryInformation(); assertNotNull(si); } catch (IOException e) { e.printStackTrace(); fail(); } catch (NoPropertySetStreamException e) { e.printStackTrace(); fail(); } catch (MarkUnsupportedException e) { e.printStackTrace(); fail(); } catch (UnexpectedPropertySetTypeException e) { e.printStackTrace(); fail(); } }