Return-Path: Delivered-To: apmail-poi-commits-archive@locus.apache.org Received: (qmail 93323 invoked from network); 9 Jul 2007 22:19:49 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 9 Jul 2007 22:19:49 -0000 Received: (qmail 4372 invoked by uid 500); 9 Jul 2007 22:19:52 -0000 Delivered-To: apmail-poi-commits-archive@poi.apache.org Received: (qmail 4332 invoked by uid 500); 9 Jul 2007 22:19:50 -0000 Mailing-List: contact commits-help@poi.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@poi.apache.org Delivered-To: mailing list commits@poi.apache.org Received: (qmail 4323 invoked by uid 99); 9 Jul 2007 22:19:50 -0000 Received: from herse.apache.org (HELO herse.apache.org) (140.211.11.133) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 09 Jul 2007 15:19:50 -0700 X-ASF-Spam-Status: No, hits=-99.5 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 09 Jul 2007 15:19:46 -0700 Received: by eris.apache.org (Postfix, from userid 65534) id 1E57E1A981A; Mon, 9 Jul 2007 15:19:26 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r554774 - in /poi/trunk: ./ src/scratchpad/src/org/apache/poi/hsmf/ src/scratchpad/src/org/apache/poi/hsmf/datatypes/ src/scratchpad/src/org/apache/poi/hsmf/exceptions/ src/scratchpad/src/org/apache/poi/hsmf/parsers/ src/scratchpad/testcase... Date: Mon, 09 Jul 2007 22:19:25 -0000 To: commits@poi.apache.org From: nick@apache.org X-Mailer: svnmailer-1.1.0 Message-Id: <20070709221926.1E57E1A981A@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: nick Date: Mon Jul 9 15:19:21 2007 New Revision: 554774 URL: http://svn.apache.org/viewvc?view=rev&rev=554774 Log: Initial HSMF (outlook) support from Travis Added: poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/ poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/MAPIMessage.java (with props) poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/ poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunk.java (with props) poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunks.java (with props) poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/StringChunk.java (with props) poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Types.java (with props) poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/exceptions/ poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/exceptions/ChunkNotFoundException.java (with props) poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/exceptions/DirectoryChunkNotFoundException.java (with props) poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/parsers/ poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/parsers/POIFSChunkParser.java (with props) poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/ poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/AllTests.java (with props) poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/data/ poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/data/blank.msg (with props) poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/data/simple_test_msg.msg (with props) poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/model/ poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestBlankFileRead.java (with props) poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestChunkData.java (with props) poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestSimpleFileRead.java (with props) Modified: poi/trunk/build.xml Modified: poi/trunk/build.xml URL: http://svn.apache.org/viewvc/poi/trunk/build.xml?view=diff&rev=554774&r1=554773&r2=554774 ============================================================================== --- poi/trunk/build.xml (original) +++ poi/trunk/build.xml Mon Jul 9 15:19:21 2007 @@ -503,6 +503,7 @@ + @@ -536,6 +537,7 @@ + Added: poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/MAPIMessage.java URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/MAPIMessage.java?view=auto&rev=554774 ============================================================================== --- poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/MAPIMessage.java (added) +++ poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/MAPIMessage.java Mon Jul 9 15:19:21 2007 @@ -0,0 +1,146 @@ +/* ==================================================================== + 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.hsmf; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.poi.hsmf.datatypes.Chunk; +import org.apache.poi.hsmf.datatypes.Chunks; +import org.apache.poi.hsmf.datatypes.StringChunk; +import org.apache.poi.hsmf.exceptions.ChunkNotFoundException; +import org.apache.poi.hsmf.parsers.POIFSChunkParser; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; + +/** + * Reads an Outlook MSG File in and provides hooks into its data structure. + * + * @author Travis Ferguson + */ +public class MAPIMessage { + private POIFSChunkParser chunkParser; + private POIFSFileSystem fs; + + /** + * Constructor for creating new files. + * + */ + public MAPIMessage() { + //TODO make writing possible + } + + + /** + * Constructor for reading MSG Files. + * @param filename + * @throws IOException + */ + public MAPIMessage(String filename) throws IOException { + InputStream in = new FileInputStream(new File(filename)); + this.fs = new POIFSFileSystem(in); + chunkParser = new POIFSChunkParser(this.fs); + } + + /** + * Gets a string value based on the passed chunk. + * @param chunk + * @return + * @throws ChunkNotFoundException + */ + public String getStringFromChunk(StringChunk chunk) throws ChunkNotFoundException { + Chunk out = this.chunkParser.getDocumentNode(chunk); + StringChunk strchunk = (StringChunk)out; + return strchunk.toString(); + } + + + /** + * Gets the plain text body of this Outlook Message + * @return The string representation of the 'text' version of the body, if available. + * @throws IOException + * @throws ChunkNotFoundException + */ + public String getTextBody() throws IOException, ChunkNotFoundException { + return getStringFromChunk(Chunks.getInstance().textBodyChunk); + } + + /** + * Gets the subject line of the Outlook Message + * @return + * @throws ChunkNotFoundException + */ + public String getSubject() throws ChunkNotFoundException { + return getStringFromChunk(Chunks.getInstance().subjectChunk); + } + + + /** + * Gets the display value of the "TO" line of the outlook message + * This is not the actual list of addresses/values that will be sent to if you click Reply in the email. + * @return + * @throws ChunkNotFoundException + */ + public String getDisplayTo() throws ChunkNotFoundException { + return getStringFromChunk(Chunks.getInstance().displayToChunk); + } + + /** + * Gets the display value of the "TO" line of the outlook message + * This is not the actual list of addresses/values that will be sent to if you click Reply in the email. + * @return + * @throws ChunkNotFoundException + */ + public String getDisplayCC() throws ChunkNotFoundException { + return getStringFromChunk(Chunks.getInstance().displayCCChunk); + } + + /** + * Gets the display value of the "TO" line of the outlook message + * This is not the actual list of addresses/values that will be sent to if you click Reply in the email. + * @return + * @throws ChunkNotFoundException + */ + public String getDisplayBCC() throws ChunkNotFoundException { + return getStringFromChunk(Chunks.getInstance().displayBCCChunk); + } + + + /** + * Gets the conversation topic of the parsed Outlook Message. + * This is the part of the subject line that is after the RE: and FWD: + * @return + * @throws ChunkNotFoundException + */ + public String getConversationTopic() throws ChunkNotFoundException { + return getStringFromChunk(Chunks.getInstance().conversationTopic); + } + + /** + * Gets the message class of the parsed Outlook Message. + * (Yes, you can use this to determine if a message is a calendar item, note, or actual outlook Message) + * For emails the class will be IPM.Note + * + * @return + * @throws ChunkNotFoundException + */ + public String getMessageClass() throws ChunkNotFoundException { + return getStringFromChunk(Chunks.getInstance().messageClass); + } +} Propchange: poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/MAPIMessage.java ------------------------------------------------------------------------------ svn:eol-style = native Added: poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunk.java URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunk.java?view=auto&rev=554774 ============================================================================== --- poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunk.java (added) +++ poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunk.java Mon Jul 9 15:19:21 2007 @@ -0,0 +1,68 @@ +/* ==================================================================== + 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.hsmf.datatypes; + +import java.io.ByteArrayOutputStream; + +abstract public class Chunk { + protected int chunkId; + protected int type; + protected String namePrefix = "__substg1.0_"; + + /** + * Gets the id of this chunk + * @return + */ + public int getChunkId() { + return this.chunkId; + } + + /** + * Gets the numeric type of this chunk. + * @return + */ + public int getType() { + return this.type; + } + + /** + * Creates a string to use to identify this chunk in the POI file system object. + * @return + */ + public String getEntryName() { + String type = Integer.toHexString(this.type); + while(type.length() < 4) type = "0" + type; + + String chunkId = Integer.toHexString(this.chunkId); + while(chunkId.length() < 4) chunkId = "0" + chunkId; + + return this.namePrefix + chunkId.toUpperCase() + type.toUpperCase(); + } + + /** + * Gets a reference to a ByteArrayOutputStream that contains the value of this chunk. + * @return + */ + public abstract ByteArrayOutputStream getValueByteArray(); + + /** + * Sets the value of this chunk using a OutputStream + * @param value + */ + public abstract void setValue(ByteArrayOutputStream value); +} Propchange: poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunk.java ------------------------------------------------------------------------------ svn:eol-style = native Added: poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunks.java URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunks.java?view=auto&rev=554774 ============================================================================== --- poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunks.java (added) +++ poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunks.java Mon Jul 9 15:19:21 2007 @@ -0,0 +1,40 @@ +/* ==================================================================== + 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.hsmf.datatypes; + + +/** + * Collection of convenence chunks for standard parts of the MSG file. + * + * @author Travis Ferguson + */ +public class Chunks { + /* String parts of Outlook Messages that are currently known */ + public StringChunk messageClass = new StringChunk(0x001A); //Type of message that the MSG represents (ie. IPM.Note) + public StringChunk textBodyChunk = new StringChunk(0x1000); //BODY Chunk, for plain/text messages + public StringChunk subjectChunk = new StringChunk(0x0037); //Subject link chunk, in plain/text + public StringChunk displayToChunk = new StringChunk(0x0E04); //Value that is in the TO field (not actually the addresses as they are stored in recip directory nodes + public StringChunk displayCCChunk = new StringChunk(0x0E03); //value that shows in the CC field + public StringChunk displayBCCChunk = new StringChunk(0x0E02); //Value that shows in the BCC field + public StringChunk conversationTopic = new StringChunk(0x0070); //Sort of like the subject line, but without the RE: and FWD: parts. + public StringChunk sentByServerType = new StringChunk(0x0075); //Type of server that the message originated from (SMTP, etc). + + public static Chunks getInstance() { + return new Chunks(); + } +} Propchange: poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunks.java ------------------------------------------------------------------------------ svn:eol-style = native Added: poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/StringChunk.java URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/StringChunk.java?view=auto&rev=554774 ============================================================================== --- poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/StringChunk.java (added) +++ poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/StringChunk.java Mon Jul 9 15:19:21 2007 @@ -0,0 +1,53 @@ +/* ==================================================================== + 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.hsmf.datatypes; + +import java.io.ByteArrayOutputStream; + +/** + * A Chunk made up of a single string. + * @author Travis Ferguson + */ +public class StringChunk extends Chunk { + + private String value; + + public StringChunk(int chunkId) { + this.chunkId = chunkId; + this.type = Types.STRING; + } + + /* (non-Javadoc) + * @see org.apache.poi.hsmf.Chunk.Chunk#getValueByteArray() + */ + public ByteArrayOutputStream getValueByteArray() { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.apache.poi.hsmf.Chunk.Chunk#setValue(java.io.ByteArrayOutputStream) + */ + public void setValue(ByteArrayOutputStream value) { + this.value = value.toString().replaceAll("\0", ""); + } + + public String toString() { + return this.value; + } +} Propchange: poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/StringChunk.java ------------------------------------------------------------------------------ svn:eol-style = native Added: poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Types.java URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Types.java?view=auto&rev=554774 ============================================================================== --- poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Types.java (added) +++ poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Types.java Mon Jul 9 15:19:21 2007 @@ -0,0 +1,26 @@ +/* ==================================================================== + 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.hsmf.datatypes; + +public class Types { + public static int BINARY = 0x0102; + public static int STRING = 0x001E; + public static int LONG = 0x0003; + public static int TIME = 0x0040; + public static int BOOLEAN = 0x000B; +} Propchange: poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Types.java ------------------------------------------------------------------------------ svn:eol-style = native Added: poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/exceptions/ChunkNotFoundException.java URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/exceptions/ChunkNotFoundException.java?view=auto&rev=554774 ============================================================================== --- poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/exceptions/ChunkNotFoundException.java (added) +++ poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/exceptions/ChunkNotFoundException.java Mon Jul 9 15:19:21 2007 @@ -0,0 +1,26 @@ +/* ==================================================================== + 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.hsmf.exceptions; + +public class ChunkNotFoundException extends Exception { + private static final long serialVersionUID = 1L; + + public ChunkNotFoundException(String chunkName) { + super(chunkName + " was named, but not found in POIFS object"); + } +} Propchange: poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/exceptions/ChunkNotFoundException.java ------------------------------------------------------------------------------ svn:eol-style = native Added: poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/exceptions/DirectoryChunkNotFoundException.java URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/exceptions/DirectoryChunkNotFoundException.java?view=auto&rev=554774 ============================================================================== --- poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/exceptions/DirectoryChunkNotFoundException.java (added) +++ poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/exceptions/DirectoryChunkNotFoundException.java Mon Jul 9 15:19:21 2007 @@ -0,0 +1,30 @@ +/* ==================================================================== + 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.hsmf.exceptions; + +/** + * Exception for when a directory chunk is not found but is expected. + * @author Travis Ferguson + */ +public class DirectoryChunkNotFoundException extends Exception { + private static final long serialVersionUID = 1L; + + public DirectoryChunkNotFoundException(String directory) { + super("Directory Chunk " + directory + " was not found!"); + } +} Propchange: poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/exceptions/DirectoryChunkNotFoundException.java ------------------------------------------------------------------------------ svn:eol-style = native Added: poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/parsers/POIFSChunkParser.java URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/parsers/POIFSChunkParser.java?view=auto&rev=554774 ============================================================================== --- poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/parsers/POIFSChunkParser.java (added) +++ poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/parsers/POIFSChunkParser.java Mon Jul 9 15:19:21 2007 @@ -0,0 +1,232 @@ +/* ==================================================================== + 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.hsmf.parsers; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; + +import org.apache.poi.hsmf.datatypes.Chunk; +import org.apache.poi.hsmf.exceptions.ChunkNotFoundException; +import org.apache.poi.hsmf.exceptions.DirectoryChunkNotFoundException; +import org.apache.poi.poifs.filesystem.DirectoryEntry; +import org.apache.poi.poifs.filesystem.DirectoryNode; +import org.apache.poi.poifs.filesystem.DocumentNode; +import org.apache.poi.poifs.filesystem.POIFSDocument; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.poifs.property.DirectoryProperty; +import org.apache.poi.poifs.property.DocumentProperty; +import org.apache.poi.poifs.storage.BlockWritable; + +/** + * Provides a HashMap with the ability to parse a PIOFS object and provide + * an 'easy to access' hashmap structure for the document chunks inside it. + * + * @author Travis Ferguson + */ +public class POIFSChunkParser { + /** + * Constructor + * @param fs + * @throws IOException + */ + public POIFSChunkParser(POIFSFileSystem fs) throws IOException { + this.setFileSystem(fs); + } + + + /** + * Set the POIFileSystem object that this object is using. + * @param fs + * @throws IOException + */ + public void setFileSystem(POIFSFileSystem fs) throws IOException { + this.fs = fs; + this.reparseFileSystem(); + } + + /** + * Get a reference to the FileSystem object that this object is currently using. + * @return + */ + public POIFSFileSystem getFileSystem() { + return this.fs; + } + + /** + * Reparse the FileSystem object, resetting all the chunks stored in this object + * @throws IOException + * + */ + public void reparseFileSystem() throws IOException { + // first clear this object of all chunks + DirectoryEntry root = this.fs.getRoot(); + Iterator iter = root.getEntries(); + + this.directoryMap = this.processPOIIterator(iter); + } + + /** + * Pull the chunk data that's stored in this object's hashmap out and return it as a HashMap. + * @param entryName + * @return + */ + public Object getChunk(HashMap dirMap, String entryName) { + if(dirMap == null) return null; + else { + return dirMap.get(entryName); + } + } + + /** + * Pull a directory/hashmap out of this hashmap and return it + * @param directoryName + * @return HashMap containing the chunks stored in the named directoryChunk + * @throws DirectoryChunkNotFoundException This is thrown should the directoryMap HashMap on this object be null + * or for some reason the directory is not found, is equal to null, or is for some reason not a HashMap/aka Directory Node. + */ + public HashMap getDirectoryChunk(String directoryName) throws DirectoryChunkNotFoundException { + DirectoryChunkNotFoundException excep = new DirectoryChunkNotFoundException(directoryName); + Object obj = getChunk(this.directoryMap, directoryName); + if(obj == null || !(obj instanceof HashMap)) throw excep; + + return (HashMap)obj; + } + + /** + * Pulls a ByteArrayOutputStream from this objects HashMap, this can be used to read a byte array of the contents of the given chunk. + * @param directoryMap, chunk + * @return + * @throws ChunkNotFoundException + */ + public Chunk getDocumentNode(HashMap dirNode, Chunk chunk) throws ChunkNotFoundException { + String entryName = chunk.getEntryName(); + ChunkNotFoundException excep = new ChunkNotFoundException(entryName); + Object obj = getChunk(dirNode, entryName); + if(obj == null || !(obj instanceof ByteArrayOutputStream)) throw excep; + + chunk.setValue((ByteArrayOutputStream)obj); + + return chunk; + } + + /** + * Pulls a Chunk out of this objects root Node tree. + * @param chunk + * @return + * @throws ChunkNotFoundException + */ + public Chunk getDocumentNode(Chunk chunk) throws ChunkNotFoundException { + return getDocumentNode(this.directoryMap, chunk); + } + + + /** + * Processes an iterator returned by a POIFS call to getRoot().getEntries() + * @param iter + * @return + * @throws IOException + */ + private HashMap processPOIIterator(Iterator iter) throws IOException { + HashMap currentNode = new HashMap(); + + while(iter.hasNext()) { + Object obj = iter.next(); + if(obj instanceof DocumentNode) { + this.processDocumentNode((DocumentNode)obj, currentNode); + } else if(obj instanceof DirectoryNode) { + String blockName = ((DirectoryNode)obj).getName(); + Iterator viewIt = null; + if( ((DirectoryNode)obj).preferArray()) { + Object[] arr = ((DirectoryNode)obj).getViewableArray(); + ArrayList viewList = new ArrayList(arr.length); + + for(int i = 0; i < arr.length; i++) { + viewList.add(arr[i]); + } + viewIt = viewList.iterator(); + } else { + viewIt = ((DirectoryNode)obj).getViewableIterator(); + } + //store the next node on the hashmap + currentNode.put(blockName, processPOIIterator(viewIt)); + } else if(obj instanceof DirectoryProperty) { + //don't do anything with the directory property chunk... + } else { + System.err.println("Unknown node: " + obj.toString()); + } + } + return currentNode; + } + + /** + * Processes a document node and adds it to the current directory HashMap + * @param obj + * @throws java.io.IOException + */ + private void processDocumentNode(DocumentNode obj, HashMap currentObj) throws IOException { + String blockName = ((DocumentNode)obj).getName(); + + Iterator viewIt = null; + if( ((DocumentNode)obj).preferArray()) { + Object[] arr = ((DocumentNode)obj).getViewableArray(); + ArrayList viewList = new ArrayList(arr.length); + + for(int i = 0; i < arr.length; i++) { + viewList.add(arr[i]); + } + viewIt = viewList.iterator(); + } else { + viewIt = ((DocumentNode)obj).getViewableIterator(); + } + + while(viewIt.hasNext()) { + Object view = viewIt.next(); + + if(view instanceof DocumentProperty) { + //we don't care about the properties + } else if(view instanceof POIFSDocument) { + //check if our node has blocks or if it can just be read raw. + int blockCount = ((POIFSDocument)view).countBlocks(); + //System.out.println("Block Name: " + blockName); + if(blockCount <= 0) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + BlockWritable[] bws = ((POIFSDocument)view).getSmallBlocks(); + for(int i = 0; i < bws.length; i++) { + bws[i].writeBlocks(out); + } + currentObj.put(blockName, out); + } else { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ((POIFSDocument)view).writeBlocks(out); + currentObj.put(blockName, out); + } + } else { + System.err.println("Unknown View Type: " + view.toString()); + } + } + } + + /* private instance variables */ + private static final long serialVersionUID = 1L; + private POIFSFileSystem fs; + private HashMap directoryMap; +} Propchange: poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/parsers/POIFSChunkParser.java ------------------------------------------------------------------------------ svn:eol-style = native Added: poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/AllTests.java URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/AllTests.java?view=auto&rev=554774 ============================================================================== --- poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/AllTests.java (added) +++ poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/AllTests.java Mon Jul 9 15:19:21 2007 @@ -0,0 +1,40 @@ +/* ==================================================================== + 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.hsmf; + +import junit.framework.*; + +public class AllTests + extends TestCase +{ + + public AllTests(String s) + { + super(s); + } + + public static Test suite() + { + TestSuite suite = new TestSuite(); + suite.addTestSuite(org.apache.poi.hsmf.model.TestBlankFileRead.class); + suite.addTestSuite(org.apache.poi.hsmf.model.TestSimpleFileRead.class); + suite.addTestSuite(org.apache.poi.hsmf.model.TestChunkData.class); + + return suite; + } +} Propchange: poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/AllTests.java ------------------------------------------------------------------------------ svn:eol-style = native Added: poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/data/blank.msg URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/data/blank.msg?view=auto&rev=554774 ============================================================================== Binary file - no diff available. Propchange: poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/data/blank.msg ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Added: poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/data/simple_test_msg.msg URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/data/simple_test_msg.msg?view=auto&rev=554774 ============================================================================== Binary file - no diff available. Propchange: poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/data/simple_test_msg.msg ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Added: poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestBlankFileRead.java URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestBlankFileRead.java?view=auto&rev=554774 ============================================================================== --- poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestBlankFileRead.java (added) +++ poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestBlankFileRead.java Mon Jul 9 15:19:21 2007 @@ -0,0 +1,125 @@ +/* ==================================================================== + 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.hsmf.model; + +import java.io.IOException; + +import org.apache.poi.hsmf.MAPIMessage; +import org.apache.poi.hsmf.exceptions.ChunkNotFoundException; + +import junit.framework.TestCase; + + +/** + * Tests to verify that the library can read blank msg files. + * + * @author Travis Ferguson + * + */ +public class TestBlankFileRead extends TestCase { + private MAPIMessage mapiMessage; + + /** + * Initialize this test, load up the blank.msg mapi message. + * @throws IOException + */ + public TestBlankFileRead() throws IOException { + String dirname = System.getProperty("HSMF.testdata.path"); + this.mapiMessage = new MAPIMessage(dirname + "/blank.msg"); + } + + /** + * Check if we can read the body of the blank message, we expect "". + * + * @throws Exception + */ + public void testReadBody() throws Exception { + try { + mapiMessage.getTextBody(); + } catch(ChunkNotFoundException exp) { + return; + } + + TestCase.fail("Should have thrown a ChunkNotFoundException but didn't"); + } + + + /** + * Test to see if we can read the CC Chunk. + * @throws ChunkNotFoundException + * + */ + public void testReadDisplayCC() throws ChunkNotFoundException { + String obtained = mapiMessage.getDisplayCC(); + String expected = ""; + + TestCase.assertEquals(obtained, expected); + } + + /** + * Test to see if we can read the CC Chunk. + * @throws ChunkNotFoundException + * + */ + public void testReadDisplayTo() throws ChunkNotFoundException { + String obtained = mapiMessage.getDisplayTo(); + String expected = ""; + + TestCase.assertEquals(obtained, expected); + } + + /** + * Test to see if we can read the CC Chunk. + * @throws ChunkNotFoundException + * + */ + public void testReadDisplayBCC() throws ChunkNotFoundException { + String obtained = mapiMessage.getDisplayBCC(); + String expected = ""; + + TestCase.assertEquals(obtained, expected); + } + + + /** + * Check if we can read the subject line of the blank message, we expect "" + * + * @throws Exception + */ + public void testReadSubject() throws Exception { + String obtained = mapiMessage.getSubject(); + TestCase.assertEquals("", obtained); + } + + + /** + * Check if we can read the subject line of the blank message, we expect "" + * + * @throws Exception + */ + public void testReadConversationTopic() throws Exception { + try { + mapiMessage.getConversationTopic(); + } catch(ChunkNotFoundException exp) { + return; + } + TestCase.fail("We shouldn't have a ConversationTopic node on the blank.msg file."); + } + + +} Propchange: poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestBlankFileRead.java ------------------------------------------------------------------------------ svn:eol-style = native Added: poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestChunkData.java URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestChunkData.java?view=auto&rev=554774 ============================================================================== --- poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestChunkData.java (added) +++ poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestChunkData.java Mon Jul 9 15:19:21 2007 @@ -0,0 +1,72 @@ +/* ==================================================================== + 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.hsmf.model; + +import org.apache.poi.hsmf.datatypes.Chunk; +import org.apache.poi.hsmf.datatypes.Chunks; +import org.apache.poi.hsmf.datatypes.StringChunk; + +import junit.framework.TestCase; + +/** + * Verifies that the Chunks class is actually setup properly and hasn't been changed in ways + * that will break the library. + * + * @author Travis Ferguson + * + */ +public class TestChunkData extends TestCase { + public void testChunkCreate() { + StringChunk chunk = new StringChunk(0x0200); + TestCase.assertEquals("__substg1.0_0200001E", chunk.getEntryName()); + + /* test the lower and upper limits of the chunk ids */ + chunk = new StringChunk(0x0000); + TestCase.assertEquals("__substg1.0_0000001E", chunk.getEntryName()); + + chunk = new StringChunk(0xFFFF); + TestCase.assertEquals("__substg1.0_FFFF001E", chunk.getEntryName()); + } + + public void testTextBodyChunk() { + StringChunk chunk = new StringChunk(0x1000); + TestCase.assertEquals(chunk.getEntryName(), Chunks.getInstance().textBodyChunk.getEntryName()); + } + + public void testDisplayToChunk() { + StringChunk chunk = new StringChunk(0x0E04); + TestCase.assertEquals(chunk.getEntryName(), Chunks.getInstance().displayToChunk.getEntryName()); + } + + + public void testDisplayCCChunk() { + StringChunk chunk = new StringChunk(0x0E03); + TestCase.assertEquals(chunk.getEntryName(), Chunks.getInstance().displayCCChunk.getEntryName()); + } + + public void testDisplayBCCChunk() { + StringChunk chunk = new StringChunk(0x0E02); + TestCase.assertEquals(chunk.getEntryName(), Chunks.getInstance().displayBCCChunk.getEntryName()); + } + + public void testSubjectChunk() { + Chunk chunk = new StringChunk(0x0037); + TestCase.assertEquals(chunk.getEntryName(), Chunks.getInstance().subjectChunk.getEntryName()); + } + +} Propchange: poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestChunkData.java ------------------------------------------------------------------------------ svn:eol-style = native Added: poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestSimpleFileRead.java URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestSimpleFileRead.java?view=auto&rev=554774 ============================================================================== --- poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestSimpleFileRead.java (added) +++ poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestSimpleFileRead.java Mon Jul 9 15:19:21 2007 @@ -0,0 +1,129 @@ +/* ==================================================================== + 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.hsmf.model; + +import java.io.IOException; + +import org.apache.poi.hsmf.MAPIMessage; +import org.apache.poi.hsmf.exceptions.ChunkNotFoundException; + +import junit.framework.TestCase; + +/** + * Tests to verify that we can read a simple msg file, that is in plain/text format with no attachments + * or extra recipents. + * + * @author Travis Ferguson + */ +public class TestSimpleFileRead extends TestCase { +private MAPIMessage mapiMessage; + + /** + * Initialize this test, load up the blank.msg mapi message. + * @throws Exception + */ + public TestSimpleFileRead() throws IOException { + String dirname = System.getProperty("HSMF.testdata.path"); + this.mapiMessage = new MAPIMessage(dirname + "/simple_test_msg.msg"); + } + + /** + * Test to see if we can read the CC Chunk. + * @throws ChunkNotFoundException + * + */ + public void testReadDisplayCC() throws ChunkNotFoundException { + String obtained = mapiMessage.getDisplayCC(); + String expected = ""; + + TestCase.assertEquals(obtained, expected); + } + + /** + * Test to see if we can read the CC Chunk. + * @throws ChunkNotFoundException + * + */ + public void testReadDisplayTo() throws ChunkNotFoundException { + String obtained = mapiMessage.getDisplayTo(); + String expected = "travis@overwrittenstack.com"; + + TestCase.assertEquals(obtained, expected); + } + + /** + * Test to see if we can read the CC Chunk. + * @throws ChunkNotFoundException + * + */ + public void testReadDisplayBCC() throws ChunkNotFoundException { + String obtained = mapiMessage.getDisplayBCC(); + String expected = ""; + + TestCase.assertEquals(obtained, expected); + } + + + /** + * Check if we can read the body of the blank message, we expect "". + * + * @throws Exception + */ + public void testReadBody() throws Exception { + String obtained = mapiMessage.getTextBody(); + String expected = "This is a test message."; + + TestCase.assertEquals(obtained, expected); + } + + /** + * Check if we can read the subject line of the blank message, we expect "" + * + * @throws Exception + */ + public void testReadSubject() throws Exception { + String obtained = mapiMessage.getSubject(); + String expected = "test message"; + + TestCase.assertEquals(expected, obtained); + } + + /** + * Check if we can read the subject line of the blank message, we expect "" + * + * @throws Exception + */ + public void testReadConversationTopic() throws Exception { + String obtained = mapiMessage.getConversationTopic(); + TestCase.assertEquals("test message", obtained); + } + + + /** + * Check if we can read the subject line of the blank message, we expect "" + * + * @throws Exception + */ + public void testReadMessageClass() throws Exception { + String obtained = mapiMessage.getMessageClass(); + TestCase.assertEquals("IPM.Note", obtained); + } + + + +} Propchange: poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestSimpleFileRead.java ------------------------------------------------------------------------------ svn:eol-style = native --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org For additional commands, e-mail: commits-help@poi.apache.org