| /**************************************************************** |
| * 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.james.mime4j.samples.tree; |
| |
| import java.awt.Dimension; |
| import java.awt.GridLayout; |
| import java.io.FileInputStream; |
| import java.io.FileNotFoundException; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.Reader; |
| import java.util.Date; |
| import java.util.Iterator; |
| import java.util.Map; |
| |
| import javax.swing.JFrame; |
| import javax.swing.JPanel; |
| import javax.swing.JScrollPane; |
| import javax.swing.JSplitPane; |
| import javax.swing.JTextArea; |
| import javax.swing.JTree; |
| import javax.swing.event.TreeSelectionEvent; |
| import javax.swing.event.TreeSelectionListener; |
| import javax.swing.tree.DefaultMutableTreeNode; |
| import javax.swing.tree.TreeSelectionModel; |
| |
| import org.mime4j.field.AddressListField; |
| import org.mime4j.field.ContentTypeField; |
| import org.mime4j.field.DateTimeField; |
| import org.mime4j.field.Field; |
| import org.mime4j.field.UnstructuredField; |
| import org.mime4j.field.address.Mailbox; |
| import org.mime4j.field.address.MailboxList; |
| import org.mime4j.message.BinaryBody; |
| import org.mime4j.message.Body; |
| import org.mime4j.message.BodyPart; |
| import org.mime4j.message.Entity; |
| import org.mime4j.message.Header; |
| import org.mime4j.message.Message; |
| import org.mime4j.message.Multipart; |
| import org.mime4j.message.TextBody; |
| |
| /** |
| * Displays a parsed Message in a window. The window will be divided into |
| * two panels. The left panel displays the Message tree. Clicking on a |
| * node in the tree shows information on that node in the right panel. |
| * |
| * Some of this code have been copied from the Java tutorial's JTree section. |
| * |
| * |
| * @version $Id: MessageTree.java 509117 2007-02-19 07:41:05Z norman $ |
| */ |
| public class MessageTree extends JPanel implements TreeSelectionListener { |
| private JPanel contentPane; |
| private JTextArea textView; |
| private JTree tree; |
| |
| /** |
| * Wraps an Object and associates it with a text. All message parts |
| * (headers, bodies, multiparts, body parts) will be wrapped in |
| * ObjectWrapper instances before they are added to the JTree instance. |
| */ |
| public static class ObjectWrapper { |
| private String text = ""; |
| private Object object = null; |
| |
| public ObjectWrapper(String text, Object object) { |
| this.text = text; |
| this.object = object; |
| } |
| |
| public String toString() { |
| return text; |
| } |
| |
| public Object getObject() { |
| return object; |
| } |
| } |
| |
| /** |
| * Creates a new <code>MessageTree</code> instance displaying the |
| * specified <code>Message</code>. |
| * |
| * @param message the message to display. |
| */ |
| public MessageTree(Message message) { |
| super(new GridLayout(1,0)); |
| |
| DefaultMutableTreeNode root = createNode(message); |
| |
| tree = new JTree(root); |
| tree.getSelectionModel().setSelectionMode( |
| TreeSelectionModel.SINGLE_TREE_SELECTION); |
| |
| tree.addTreeSelectionListener(this); |
| |
| JScrollPane treeView = new JScrollPane(tree); |
| |
| contentPane = new JPanel(new GridLayout(1,0)); |
| JScrollPane contentView = new JScrollPane(contentPane); |
| |
| JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); |
| splitPane.setLeftComponent(treeView); |
| splitPane.setRightComponent(contentView); |
| |
| Dimension minimumSize = new Dimension(100, 50); |
| contentView.setMinimumSize(minimumSize); |
| treeView.setMinimumSize(minimumSize); |
| splitPane.setDividerLocation(250); |
| splitPane.setPreferredSize(new Dimension(750, 500)); |
| |
| add(splitPane); |
| |
| textView = new JTextArea(); |
| textView.setEditable(false); |
| textView.setLineWrap(true); |
| contentPane.add(textView); |
| } |
| |
| /** |
| * Create a node given a Multipart body. |
| * Add the Preamble, all Body parts and the Epilogue to the node. |
| * |
| * @param multipart the Multipart. |
| * @return the root node of the tree. |
| */ |
| private DefaultMutableTreeNode createNode(Header header) { |
| DefaultMutableTreeNode node = new DefaultMutableTreeNode( |
| new ObjectWrapper("Header", header)); |
| |
| for (Iterator it = header.getFields().iterator(); it.hasNext();) { |
| Field field = (Field) it.next(); |
| String name = field.getName(); |
| |
| node.add(new DefaultMutableTreeNode(new ObjectWrapper(name, field))); |
| } |
| |
| return node; |
| } |
| |
| /** |
| * Create a node given a Multipart body. |
| * Add the Preamble, all Body parts and the Epilogue to the node. |
| * |
| * @param multipart the Multipart. |
| * @return the root node of the tree. |
| */ |
| private DefaultMutableTreeNode createNode(Multipart multipart) { |
| DefaultMutableTreeNode node = new DefaultMutableTreeNode( |
| new ObjectWrapper("Multipart", multipart)); |
| |
| node.add(new DefaultMutableTreeNode( |
| new ObjectWrapper("Preamble", multipart.getPreamble()))); |
| for (Iterator it = multipart.getBodyParts().iterator(); it.hasNext();) { |
| BodyPart part = (BodyPart) it.next(); |
| node.add(createNode(part)); |
| } |
| node.add(new DefaultMutableTreeNode( |
| new ObjectWrapper("Epilogue", multipart.getEpilogue()))); |
| |
| return node; |
| } |
| |
| /** |
| * Creates the tree nodes given a MIME entity (either a Message or |
| * a BodyPart). |
| * |
| * @param entity the entity. |
| * @return the root node of the tree displaying the specified entity and |
| * its children. |
| */ |
| private DefaultMutableTreeNode createNode(Entity entity) { |
| |
| /* |
| * Create the root node for the entity. It's either a |
| * Message or a Body part. |
| */ |
| String type = "Message"; |
| if (entity instanceof BodyPart) { |
| type = "Body part"; |
| } |
| DefaultMutableTreeNode node = new DefaultMutableTreeNode( |
| new ObjectWrapper(type, entity)); |
| |
| /* |
| * Add the node encapsulating the entity Header. |
| */ |
| node.add(createNode(entity.getHeader())); |
| |
| Body body = entity.getBody(); |
| |
| if (body instanceof Multipart) { |
| /* |
| * The body of the entity is a Multipart. |
| */ |
| |
| node.add(createNode((Multipart) body)); |
| } else if (body instanceof Message) { |
| /* |
| * The body is another Message. |
| */ |
| |
| node.add(createNode((Message) body)); |
| |
| } else { |
| /* |
| * Discrete Body (either of type TextBody or BinaryBody). |
| */ |
| type = "Text body"; |
| if (body instanceof BinaryBody) { |
| type = "Binary body"; |
| } |
| |
| type += " (" + entity.getMimeType() + ")"; |
| node.add(new DefaultMutableTreeNode(new ObjectWrapper(type, body))); |
| |
| } |
| |
| return node; |
| } |
| |
| /** |
| * Called whenever the selection changes in the JTree instance showing |
| * the Message nodes. |
| * |
| * @param e the event. |
| */ |
| public void valueChanged(TreeSelectionEvent e) { |
| DefaultMutableTreeNode node = (DefaultMutableTreeNode) |
| tree.getLastSelectedPathComponent(); |
| |
| textView.setText(""); |
| |
| if (node == null) { |
| return; |
| } |
| |
| Object o = ((ObjectWrapper) node.getUserObject()).getObject(); |
| |
| if (node.isLeaf()) { |
| |
| if (o instanceof TextBody){ |
| /* |
| * A text body. Display its contents. |
| */ |
| TextBody body = (TextBody) o; |
| StringBuffer sb = new StringBuffer(); |
| try { |
| Reader r = body.getReader(); |
| int c; |
| while ((c = r.read()) != -1) { |
| sb.append((char) c); |
| } |
| } catch (IOException ex) { |
| ex.printStackTrace(); |
| } |
| textView.setText(sb.toString()); |
| |
| } else if (o instanceof BinaryBody){ |
| /* |
| * A binary body. Display its MIME type and length in bytes. |
| */ |
| BinaryBody body = (BinaryBody) o; |
| int size = 0; |
| try { |
| InputStream is = body.getInputStream(); |
| int b; |
| while ((b = is.read()) != -1) { |
| size++; |
| } |
| } catch (IOException ex) { |
| ex.printStackTrace(); |
| } |
| textView.setText("Binary body\n" |
| + "MIME type: " |
| + body.getParent().getMimeType() + "\n" |
| + "Size of decoded data: " + size + " bytes"); |
| |
| } else if (o instanceof ContentTypeField) { |
| /* |
| * Content-Type field. |
| */ |
| ContentTypeField field = (ContentTypeField) o; |
| StringBuffer sb = new StringBuffer(); |
| sb.append("MIME type: " + field.getMimeType() + "\n"); |
| Map params = field.getParameters(); |
| for (Iterator it = params.keySet().iterator(); it.hasNext();) { |
| String name = (String) it.next(); |
| sb.append(name + " = " + params.get(name) + "\n"); |
| } |
| textView.setText(sb.toString()); |
| |
| } else if (o instanceof AddressListField) { |
| /* |
| * An address field (From, To, Cc, etc) |
| */ |
| AddressListField field = (AddressListField) o; |
| MailboxList list = field.getAddressList().flatten(); |
| StringBuffer sb = new StringBuffer(); |
| for (int i = 0; i < list.size(); i++) { |
| Mailbox mb = list.get(i); |
| sb.append(mb.getAddressString() + "\n"); |
| } |
| textView.setText(sb.toString()); |
| |
| } else if (o instanceof DateTimeField) { |
| Date date = ((DateTimeField) o).getDate(); |
| textView.setText(date.toString()); |
| } else if (o instanceof UnstructuredField){ |
| textView.setText(((UnstructuredField) o).getValue()); |
| } else if (o instanceof Field){ |
| textView.setText(((Field) o).getBody()); |
| } else { |
| /* |
| * The Object should be a Header or a String containing a |
| * Preamble or Epilogue. |
| */ |
| textView.setText(o.toString()); |
| } |
| |
| } |
| } |
| |
| /** |
| * Creates and displays the gui. |
| * |
| * @param message the Message to display in the tree. |
| */ |
| private static void createAndShowGUI(Message message) { |
| /* |
| * Create and set up the window. |
| */ |
| JFrame frame = new JFrame("MessageTree"); |
| frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); |
| |
| /* |
| * Create and set up the content pane. |
| */ |
| MessageTree newContentPane = new MessageTree(message); |
| newContentPane.setOpaque(true); |
| frame.setContentPane(newContentPane); |
| |
| /* |
| * Display the window. |
| */ |
| frame.pack(); |
| frame.setVisible(true); |
| } |
| |
| public static void main(String[] args) { |
| try { |
| |
| final Message message = new Message(new FileInputStream(args[0])); |
| |
| javax.swing.SwingUtilities.invokeLater(new Runnable() { |
| public void run() { |
| createAndShowGUI(message); |
| } |
| }); |
| |
| } catch (ArrayIndexOutOfBoundsException e) { |
| System.err.println("Wrong number of arguments."); |
| System.err.println("Usage: org.mime4j.samples.tree.MessageTree" |
| + " path/to/message"); |
| } catch (FileNotFoundException e) { |
| System.err.println("The file '" + args[0] + "' could not be found."); |
| } catch (IOException e) { |
| System.err.println("The file '" + args[0] + "' could not be read."); |
| } |
| } |
| |
| } |