~ubuntu-branches/ubuntu/saucy/apache-mime4j/saucy

« back to all changes in this revision

Viewing changes to examples/src/java/org/apache/james/mime4j/samples/tree/MessageTree.java

  • Committer: Bazaar Package Importer
  • Author(s): David Paleino
  • Date: 2010-07-13 09:28:28 UTC
  • Revision ID: james.westby@ubuntu.com-20100713092828-g6wafdtidgmtx7su
Tags: upstream-0.6
ImportĀ upstreamĀ versionĀ 0.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************
 
2
 * Licensed to the Apache Software Foundation (ASF) under one   *
 
3
 * or more contributor license agreements.  See the NOTICE file *
 
4
 * distributed with this work for additional information        *
 
5
 * regarding copyright ownership.  The ASF licenses this file   *
 
6
 * to you under the Apache License, Version 2.0 (the            *
 
7
 * "License"); you may not use this file except in compliance   *
 
8
 * with the License.  You may obtain a copy of the License at   *
 
9
 *                                                              *
 
10
 *   http://www.apache.org/licenses/LICENSE-2.0                 *
 
11
 *                                                              *
 
12
 * Unless required by applicable law or agreed to in writing,   *
 
13
 * software distributed under the License is distributed on an  *
 
14
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
 
15
 * KIND, either express or implied.  See the License for the    *
 
16
 * specific language governing permissions and limitations      *
 
17
 * under the License.                                           *
 
18
 ****************************************************************/
 
19
 
 
20
package org.apache.james.mime4j.samples.tree;
 
21
 
 
22
import java.awt.Dimension;
 
23
import java.awt.GridLayout;
 
24
import java.io.FileInputStream;
 
25
import java.io.FileNotFoundException;
 
26
import java.io.IOException;
 
27
import java.io.InputStream;
 
28
import java.io.Reader;
 
29
import java.util.Date;
 
30
import java.util.Map;
 
31
 
 
32
import javax.swing.JFrame;
 
33
import javax.swing.JPanel;
 
34
import javax.swing.JScrollPane;
 
35
import javax.swing.JSplitPane;
 
36
import javax.swing.JTextArea;
 
37
import javax.swing.JTree;
 
38
import javax.swing.event.TreeSelectionEvent;
 
39
import javax.swing.event.TreeSelectionListener;
 
40
import javax.swing.tree.DefaultMutableTreeNode;
 
41
import javax.swing.tree.TreeSelectionModel;
 
42
 
 
43
import org.apache.james.mime4j.field.AddressListField;
 
44
import org.apache.james.mime4j.field.ContentTypeField;
 
45
import org.apache.james.mime4j.field.DateTimeField;
 
46
import org.apache.james.mime4j.field.UnstructuredField;
 
47
import org.apache.james.mime4j.field.address.Mailbox;
 
48
import org.apache.james.mime4j.field.address.MailboxList;
 
49
import org.apache.james.mime4j.message.BinaryBody;
 
50
import org.apache.james.mime4j.message.Body;
 
51
import org.apache.james.mime4j.message.BodyPart;
 
52
import org.apache.james.mime4j.message.Entity;
 
53
import org.apache.james.mime4j.message.Header;
 
54
import org.apache.james.mime4j.message.Message;
 
55
import org.apache.james.mime4j.message.Multipart;
 
56
import org.apache.james.mime4j.message.TextBody;
 
57
import org.apache.james.mime4j.parser.Field;
 
58
 
 
59
/**
 
60
 * Displays a parsed Message in a window. The window will be divided into
 
61
 * two panels. The left panel displays the Message tree. Clicking on a 
 
62
 * node in the tree shows information on that node in the right panel.
 
63
 *
 
64
 * Some of this code have been copied from the Java tutorial's JTree section.
 
65
 */
 
66
public class MessageTree extends JPanel implements TreeSelectionListener {
 
67
    private static final long serialVersionUID = 1L;
 
68
 
 
69
    private JPanel contentPane;
 
70
    private JTextArea textView;
 
71
    private JTree tree;
 
72
 
 
73
    /**
 
74
     * Wraps an Object and associates it with a text. All message parts 
 
75
     * (headers, bodies, multiparts, body parts) will be wrapped in
 
76
     * ObjectWrapper instances before they are added to the JTree instance.
 
77
     */
 
78
    public static class ObjectWrapper {
 
79
        private String text = "";
 
80
        private Object object = null;
 
81
        
 
82
        public ObjectWrapper(String text, Object object) {
 
83
            this.text = text;
 
84
            this.object = object;
 
85
        }
 
86
        
 
87
        @Override
 
88
        public String toString() {
 
89
            return text;
 
90
        }
 
91
        
 
92
        public Object getObject() {
 
93
            return object;
 
94
        }
 
95
    }
 
96
    
 
97
    /**
 
98
     * Creates a new <code>MessageTree</code> instance displaying the 
 
99
     * specified <code>Message</code>.
 
100
     * 
 
101
     * @param message the message to display.
 
102
     */
 
103
    public MessageTree(Message message) {
 
104
        super(new GridLayout(1,0));
 
105
 
 
106
        DefaultMutableTreeNode root = createNode(message);
 
107
 
 
108
        tree = new JTree(root);
 
109
        tree.getSelectionModel().setSelectionMode(
 
110
                TreeSelectionModel.SINGLE_TREE_SELECTION);
 
111
 
 
112
        tree.addTreeSelectionListener(this);
 
113
 
 
114
        JScrollPane treeView = new JScrollPane(tree);
 
115
 
 
116
        contentPane = new JPanel(new GridLayout(1,0));
 
117
        JScrollPane contentView = new JScrollPane(contentPane);
 
118
 
 
119
        JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
 
120
        splitPane.setLeftComponent(treeView);
 
121
        splitPane.setRightComponent(contentView);
 
122
 
 
123
        Dimension minimumSize = new Dimension(100, 50);
 
124
        contentView.setMinimumSize(minimumSize);
 
125
        treeView.setMinimumSize(minimumSize);
 
126
        splitPane.setDividerLocation(250);
 
127
        splitPane.setPreferredSize(new Dimension(750, 500));
 
128
 
 
129
        add(splitPane);
 
130
        
 
131
        textView = new JTextArea();
 
132
        textView.setEditable(false);
 
133
        textView.setLineWrap(true);
 
134
        contentPane.add(textView);
 
135
    }
 
136
    
 
137
    /**
 
138
     * Create a node given a Multipart body.
 
139
     * Add the Preamble, all Body parts and the Epilogue to the node.
 
140
     * 
 
141
     * @param multipart the Multipart.
 
142
     * @return the root node of the tree.
 
143
     */
 
144
    private DefaultMutableTreeNode createNode(Header header) {
 
145
        DefaultMutableTreeNode node = new DefaultMutableTreeNode(
 
146
                new ObjectWrapper("Header", header));
 
147
 
 
148
        for (Field field : header.getFields()) {
 
149
            String name = field.getName();
 
150
            
 
151
            node.add(new DefaultMutableTreeNode(new ObjectWrapper(name, field)));
 
152
        }        
 
153
 
 
154
        return node;
 
155
    }
 
156
    
 
157
    /**
 
158
     * Create a node given a Multipart body.
 
159
     * Add the Preamble, all Body parts and the Epilogue to the node.
 
160
     * 
 
161
     * @param multipart the Multipart.
 
162
     * @return the root node of the tree.
 
163
     */
 
164
    private DefaultMutableTreeNode createNode(Multipart multipart) {
 
165
        DefaultMutableTreeNode node = new DefaultMutableTreeNode(
 
166
                new ObjectWrapper("Multipart", multipart));
 
167
 
 
168
        node.add(new DefaultMutableTreeNode(
 
169
                       new ObjectWrapper("Preamble", multipart.getPreamble())));
 
170
        for (BodyPart part : multipart.getBodyParts()) {
 
171
            node.add(createNode(part));
 
172
        }
 
173
        node.add(new DefaultMutableTreeNode(
 
174
                       new ObjectWrapper("Epilogue", multipart.getEpilogue())));
 
175
 
 
176
        return node;
 
177
    }
 
178
    
 
179
    /**
 
180
     * Creates the tree nodes given a MIME entity (either a Message or 
 
181
     * a BodyPart).
 
182
     * 
 
183
     * @param entity the entity.
 
184
     * @return the root node of the tree displaying the specified entity and 
 
185
     *         its children.
 
186
     */
 
187
    private DefaultMutableTreeNode createNode(Entity entity) {
 
188
        
 
189
        /*
 
190
         * Create the root node for the entity. It's either a
 
191
         * Message or a Body part.
 
192
         */
 
193
        String type = "Message";
 
194
        if (entity instanceof BodyPart) {
 
195
            type = "Body part";
 
196
        }
 
197
        DefaultMutableTreeNode node = new DefaultMutableTreeNode(
 
198
                                            new ObjectWrapper(type, entity));
 
199
 
 
200
        /*
 
201
         * Add the node encapsulating the entity Header.
 
202
         */
 
203
        node.add(createNode(entity.getHeader()));
 
204
        
 
205
        Body body = entity.getBody();
 
206
        
 
207
        if (body instanceof Multipart) {
 
208
            /*
 
209
             * The body of the entity is a Multipart.
 
210
             */
 
211
            
 
212
            node.add(createNode((Multipart) body));
 
213
        } else if (body instanceof Message) {
 
214
            /*
 
215
             * The body is another Message.
 
216
             */
 
217
            
 
218
            node.add(createNode((Message) body));
 
219
            
 
220
        } else {
 
221
            /*
 
222
             * Discrete Body (either of type TextBody or BinaryBody).
 
223
             */
 
224
            type = "Text body";
 
225
            if (body instanceof BinaryBody) {
 
226
                type = "Binary body";
 
227
            }
 
228
            
 
229
            type += " (" + entity.getMimeType() + ")";
 
230
            node.add(new DefaultMutableTreeNode(new ObjectWrapper(type, body)));
 
231
            
 
232
        }
 
233
        
 
234
        return node;
 
235
    }
 
236
    
 
237
    /**
 
238
     * Called whenever the selection changes in the JTree instance showing
 
239
     * the Message nodes.
 
240
     * 
 
241
     * @param e the event.
 
242
     */
 
243
    public void valueChanged(TreeSelectionEvent e) {
 
244
        DefaultMutableTreeNode node = (DefaultMutableTreeNode)
 
245
                tree.getLastSelectedPathComponent();
 
246
 
 
247
        textView.setText("");
 
248
        
 
249
        if (node == null) {
 
250
            return;
 
251
        }
 
252
        
 
253
        Object o = ((ObjectWrapper) node.getUserObject()).getObject();
 
254
 
 
255
        if (node.isLeaf()) {
 
256
            
 
257
            if (o instanceof TextBody){
 
258
                /*
 
259
                 * A text body. Display its contents.
 
260
                 */
 
261
                TextBody body = (TextBody) o;
 
262
                StringBuilder sb = new StringBuilder();
 
263
                try {
 
264
                    Reader r = body.getReader();
 
265
                    int c;
 
266
                    while ((c = r.read()) != -1) {
 
267
                        sb.append((char) c);
 
268
                    }
 
269
                } catch (IOException ex) {
 
270
                    ex.printStackTrace();
 
271
                }
 
272
                textView.setText(sb.toString());
 
273
                
 
274
            } else if (o instanceof BinaryBody){
 
275
                /*
 
276
                 * A binary body. Display its MIME type and length in bytes.
 
277
                 */
 
278
                BinaryBody body = (BinaryBody) o;
 
279
                int size = 0;
 
280
                try {
 
281
                    InputStream is = body.getInputStream();
 
282
                    while ((is.read()) != -1) {
 
283
                        size++;
 
284
                    }
 
285
                } catch (IOException ex) {
 
286
                    ex.printStackTrace();
 
287
                }
 
288
                textView.setText("Binary body\n"
 
289
                               + "MIME type: " 
 
290
                                   + body.getParent().getMimeType() + "\n" 
 
291
                               + "Size of decoded data: " + size + " bytes");
 
292
                
 
293
            } else if (o instanceof ContentTypeField) {
 
294
                /*
 
295
                 * Content-Type field.
 
296
                 */
 
297
                ContentTypeField field = (ContentTypeField) o;
 
298
                StringBuilder sb = new StringBuilder();
 
299
                sb.append("MIME type: " + field.getMimeType() + "\n");
 
300
                Map<String, String> params = field.getParameters();
 
301
                for (String name : params.keySet()) {
 
302
                    sb.append(name + " = " + params.get(name) + "\n");
 
303
                }
 
304
                textView.setText(sb.toString());
 
305
                
 
306
            } else if (o instanceof AddressListField) {
 
307
                /*
 
308
                 * An address field (From, To, Cc, etc)
 
309
                 */
 
310
                AddressListField field = (AddressListField) o;
 
311
                MailboxList list = field.getAddressList().flatten();
 
312
                StringBuilder sb = new StringBuilder();
 
313
                for (int i = 0; i < list.size(); i++) {
 
314
                    Mailbox mb = list.get(i);
 
315
                    sb.append(mb.getDisplayString() + "\n");
 
316
                }
 
317
                textView.setText(sb.toString());
 
318
                
 
319
            } else if (o instanceof DateTimeField) {
 
320
                Date date = ((DateTimeField) o).getDate();
 
321
                textView.setText(date.toString());                
 
322
            } else if (o instanceof UnstructuredField){
 
323
                textView.setText(((UnstructuredField) o).getValue());                
 
324
            } else if (o instanceof Field){
 
325
                textView.setText(((Field) o).getBody());                
 
326
            } else {
 
327
                /*
 
328
                 * The Object should be a Header or a String containing a 
 
329
                 * Preamble or Epilogue.
 
330
                 */
 
331
                textView.setText(o.toString());                
 
332
            }
 
333
            
 
334
        }
 
335
    }
 
336
    
 
337
    /**
 
338
     * Creates and displays the gui.
 
339
     * 
 
340
     * @param message the Message to display in the tree.
 
341
     */
 
342
    private static void createAndShowGUI(Message message) {
 
343
        /*
 
344
         * Create and set up the window.
 
345
         */
 
346
        JFrame frame = new JFrame("MessageTree");
 
347
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
348
 
 
349
        /*
 
350
         * Create and set up the content pane.
 
351
         */
 
352
        MessageTree newContentPane = new MessageTree(message);
 
353
        newContentPane.setOpaque(true);
 
354
        frame.setContentPane(newContentPane);
 
355
 
 
356
        /*
 
357
         * Display the window.
 
358
         */
 
359
        frame.pack();
 
360
        frame.setVisible(true);
 
361
    }
 
362
    
 
363
    public static void main(String[] args) {
 
364
        try {
 
365
            
 
366
            final Message message = new Message(new FileInputStream(args[0]));
 
367
            
 
368
            javax.swing.SwingUtilities.invokeLater(new Runnable() {
 
369
                public void run() {
 
370
                    createAndShowGUI(message);
 
371
                }
 
372
            });
 
373
        
 
374
        } catch (ArrayIndexOutOfBoundsException e) {
 
375
            System.err.println("Wrong number of arguments.");
 
376
            System.err.println("Usage: org.mime4j.samples.tree.MessageTree"
 
377
                             + " path/to/message");
 
378
        } catch (FileNotFoundException e) {
 
379
            System.err.println("The file '" + args[0] + "' could not be found.");
 
380
        } catch (IOException e) {
 
381
            System.err.println("The file '" + args[0] + "' could not be read.");
 
382
        }
 
383
    }
 
384
 
 
385
}