KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > suberic > pooka > gui > AttachmentHandler


1 package net.suberic.pooka.gui;
2
3 import java.io.*;
4 import java.awt.*;
5 import java.awt.event.*;
6 import javax.swing.*;
7
8 import javax.activation.*;
9
10 import net.suberic.pooka.*;
11 import net.suberic.util.swing.*;
12 import net.suberic.util.thread.*;
13
14 /**
15  * Handles opening, saving, etc. attachments.
16  */

17 public class AttachmentHandler {
18
19   // i'm hardcoding these, but i doubt that will be too much of a problem.
20

21   static int minTextWidth = 600;
22   static int maxTextWidth = 800;
23   static int minTextHeight = 600;
24   static int maxTextHeight = 800;
25
26   MessageProxy mProxy;
27
28   /**
29    * Creates a new AttachmentHandler instance.
30    */

31   public AttachmentHandler(MessageProxy pProxy) {
32     mProxy = pProxy;
33   }
34
35   /**
36    * Returns the associated MessageProxy.
37    */

38   public MessageProxy getMessageProxy() {
39     return mProxy;
40   }
41
42   /**
43    * Returns the associated MessageUI.
44    */

45   public MessageUI getMessageUI() {
46     return mProxy.getMessageUI();
47   }
48
49   /**
50    * Shows an error message, either on the MessageUI if there is one, or
51    * if not, on the main Pooka frame.
52    */

53   public void showError(String JavaDoc message, Exception JavaDoc ioe) {
54     MessageUI mui = getMessageUI();
55     if (mui != null) {
56       mui.showError(message,ioe);
57     } else {
58       Pooka.getUIFactory().showError(message,ioe);
59     }
60   }
61
62   /**
63    * Shows an error message, either on the MessageUI if there is one, or
64    * if not, on the main Pooka frame.
65    */

66   public void showError(String JavaDoc message, String JavaDoc title, Exception JavaDoc ioe) {
67     MessageUI mui = getMessageUI();
68     if (mui != null) {
69       mui.showError(message, title, ioe);
70     } else {
71       Pooka.getUIFactory().showError(message, title, ioe);
72     }
73   }
74
75   /**
76    * This opens up the selected Attachment using the default handler
77    * for the Attachment's Mime type.
78    */

79   public void openAttachment(Attachment pAttachment) {
80     // called on the folder thread.
81

82     if (pAttachment != null) {
83       DataHandler dh = null;
84       dh = pAttachment.getDataHandler();
85
86       if (dh != null) {
87         dh.setCommandMap(Pooka.getMailcap());
88
89         if (Pooka.isDebug()) {
90           CommandInfo[] cis = dh.getAllCommands();
91           if (cis != null && cis.length > 0) {
92             for (int i = 0; i < cis.length; i++) {
93               System.out.println(cis[i].getCommandName() + ", " + cis[i].getCommandClass());
94             }
95           } else {
96             System.out.println("No commands for mimetype.");
97           }
98         } // end debug
99

100         CommandInfo[] cmds = dh.getPreferredCommands();
101         if (cmds != null && cmds[0] != null) {
102           Object JavaDoc beanViewer = dh.getBean(cmds[0]);
103           if (beanViewer instanceof Frame) {
104             Frame frameViewer = (Frame)beanViewer;
105             try {
106               frameViewer.setTitle(pAttachment.getName());
107               frameViewer.setSize(frameViewer.getPreferredSize());
108             } catch (Exception JavaDoc e) {
109             }
110             frameViewer.setVisible(true);
111           } else if (beanViewer instanceof Component) {
112             String JavaDoc title = pAttachment.getName();
113             openAttachmentWindow((Component)beanViewer, title, false);
114           } else if (beanViewer instanceof ExternalLauncher) {
115             ((ExternalLauncher)beanViewer).show();
116           } else if (beanViewer instanceof com.sun.mail.handlers.text_plain || beanViewer instanceof com.sun.mail.handlers.text_html) {
117             // sigh
118
JTextPane jtp = new JTextPane();
119             try {
120               String JavaDoc content = (String JavaDoc) pAttachment.getContent();
121               if (pAttachment.isHtml()) {
122                 jtp.setContentType("text/html");
123               }
124               jtp.setText(content);
125               jtp.setEditable(false);
126               openAttachmentWindow(new JScrollPane(jtp), pAttachment.getName(), true);
127             } catch (IOException ioe) {
128               showError("Error showing attachment: ", ioe);
129             }
130           } else if (cmds[0].getCommandClass().equals("net.suberic.pooka.ExternalLauncher")) {
131             try {
132               ExternalLauncher el = new ExternalLauncher();
133
134               // create a progress dialog for the external launcher
135
int attachmentSize = pAttachment.getSize();
136               if (pAttachment.getEncoding() != null && pAttachment.getEncoding().equalsIgnoreCase("base64"))
137                 attachmentSize = (int) (attachmentSize * .73);
138
139               ProgressDialog dlg;
140               if (getMessageUI() != null) {
141                 dlg = getMessageUI().createProgressDialog(0, attachmentSize, 0, "Fetching attachment...","Fetching attachment");
142               } else {
143                 dlg = Pooka.getUIFactory().createProgressDialog(0, attachmentSize, 0, "Fetching attachment","Fetching attachment");
144               }
145
146               final ExternalLauncher fLauncher = el;
147               dlg.addCancelListener(new ProgressDialogListener() {
148                   public void dialogCancelled() {
149                     fLauncher.cancelSave();
150                   }
151                 });
152
153               el.setProgressDialog(dlg);
154
155               el.setCommandContext(cmds[0].getCommandName(), null);
156
157               el.show();
158             } catch (IOException ioe) {
159               //
160
}
161           } else {
162             openWith(pAttachment);
163           }
164         } else if (isWindows()) {
165           try {
166             String JavaDoc mimeType = pAttachment.getMimeType().toString();
167             if (mimeType.indexOf(';') != -1)
168               mimeType = mimeType.substring(0, mimeType.indexOf(';'));
169
170             String JavaDoc cmd = "rundll32 url.dll,FileProtocolHandler %s";
171
172             ExternalLauncher el = new ExternalLauncher();
173
174             el.setCommandContext(cmd, dh);
175
176             // create a progress dialog for the external launcher
177
int attachmentSize = pAttachment.getSize();
178             if (pAttachment.getEncoding() != null && pAttachment.getEncoding().equalsIgnoreCase("base64"))
179               attachmentSize = (int) (attachmentSize * .73);
180
181             ProgressDialog dlg;
182             if (getMessageUI() != null) {
183               dlg = getMessageUI().createProgressDialog(0, attachmentSize, 0, "Fetching attachment","Fetching attachment");
184             } else {
185               dlg = Pooka.getUIFactory().createProgressDialog(0, attachmentSize, 0, "Fetching attachment","Fetching attachment");
186             }
187
188             final ExternalLauncher fLauncher = el;
189             dlg.addCancelListener(new ProgressDialogListener() {
190                 public void dialogCancelled() {
191                   fLauncher.cancelSave();
192                 }
193               });
194
195             el.setProgressDialog(dlg);
196
197             if (Pooka.isDebug())
198               System.out.println("opening external launcher with ");
199             el.show();
200           } catch (Exception JavaDoc elException) {
201             getMessageUI().showError("Error opening attachment", elException);
202           }
203
204         } else {
205           openWith(pAttachment);
206         }
207       }
208     }
209   }
210
211   /**
212    * Returns whether or not we're running on a Windows platform.
213    */

214   public boolean isWindows() {
215     return (System.getProperty("os.name").toLowerCase().indexOf("windows") > -1);
216   }
217
218   /**
219    * Opens either a JFrame or a JInternalFrame, whichever is appropriate,
220    * with the given Component as a content pane and the given title.
221    */

222   private void openAttachmentWindow(Component pContent, String JavaDoc pTitle, boolean pResize) {
223     // threading: this can be called on any thread, since it calls
224
// SwingUtilities.invokeLater().
225

226     final Component content = pContent;
227     final String JavaDoc title = pTitle;
228     final boolean resize = pResize;
229
230     SwingUtilities.invokeLater(new Runnable JavaDoc() {
231         public void run() {
232           MessageUI mui = getMessageUI();
233           if (Pooka.isDebug())
234             System.out.println("opening attachment window.");
235
236           if ((mui != null && mui instanceof JInternalFrame) || (mui == null && Pooka.getUIFactory() instanceof PookaDesktopPaneUIFactory) ) {
237             JDesktopPane desktop = ((PookaDesktopPaneUIFactory) Pooka.getUIFactory()).getMessagePanel();
238             JInternalFrame jif = new JInternalFrame(title, true, true, true, true);
239             jif.getContentPane().add(content);
240             jif.pack();
241             if (resize) {
242               // let's be reasonable here....
243
Dimension frameSize = jif.getSize();
244               if (frameSize.width < minTextWidth) {
245                 frameSize.width = minTextWidth;
246               } else if (frameSize.width > maxTextWidth) {
247                 frameSize.width = maxTextWidth;
248               }
249
250               if (frameSize.height < minTextHeight) {
251                 frameSize.height = minTextHeight;
252               } else if (frameSize.height > maxTextHeight) {
253                 frameSize.height = maxTextHeight;
254               }
255
256               jif.setSize(frameSize);
257             }
258
259             desktop.add(jif);
260             if (desktop instanceof MessagePanel) {
261               jif.setLocation(((MessagePanel) desktop).getNewWindowLocation(jif, false));
262             }
263             jif.setVisible(true);
264             try {
265               jif.setSelected(true);
266             } catch (java.beans.PropertyVetoException JavaDoc e) {
267             }
268           } else {
269             JFrame frame = new JFrame(title);
270             frame.getContentPane().add(content);
271             frame.pack();
272
273             if (resize) {
274               // let's be reasonable here....
275
Dimension frameSize = frame.getSize();
276               if (frameSize.width < minTextWidth) {
277                 frameSize.width = minTextWidth;
278               } else if (frameSize.width > maxTextWidth) {
279                 frameSize.width = maxTextWidth;
280               }
281
282               if (frameSize.height < minTextHeight) {
283                 frameSize.height = minTextHeight;
284               } else if (frameSize.height > maxTextHeight) {
285                 frameSize.height = maxTextHeight;
286               }
287
288               frame.setSize(frameSize);
289             }
290             frame.setVisible(true);
291           }
292         }
293       });
294   }
295
296   /**
297    * This opens the Attachment with the program of the user's choice.
298    */

299   public void openWith(Attachment pAttachment) {
300     if (Pooka.isDebug())
301       System.out.println("calling AttachmentHandler.openWith()");
302
303     try {
304       String JavaDoc mimeType = pAttachment.getMimeType().toString();
305       if (mimeType.indexOf(';') != -1)
306         mimeType = mimeType.substring(0, mimeType.indexOf(';'));
307
308       final String JavaDoc mType = mimeType;
309
310       final Attachment fAttachment = pAttachment;
311
312       // have to get the ActionThread for later.
313
ActionThread actionThread = null;
314       Thread JavaDoc currentThread = Thread.currentThread();
315       if (currentThread instanceof ActionThread) {
316         actionThread = (ActionThread) currentThread;
317       }
318       final ActionThread fActionThread = actionThread;
319
320       SwingUtilities.invokeLater(new Runnable JavaDoc() {
321           public void run() {
322
323             String JavaDoc inputMessage = Pooka.getProperty("AttchmentPane.openWith.message", "Enter the command with which \r\nto open the attchment.");
324             String JavaDoc inputTitle = Pooka.getProperty("AttachmentPane.openWith.title", "Open Attachment With");
325             String JavaDoc makeDefaultLabel = Pooka.getProperty("AttachmentPane.openWith.makeDefaultMessage", "Make default command?");
326
327             JLabel toggleMsgLabel = new JLabel(makeDefaultLabel);
328             toggleMsgLabel.setForeground(Color.getColor("Black"));
329             JRadioButton toggleButton = new JRadioButton();
330             JPanel togglePanel = new JPanel();
331             togglePanel.add(toggleMsgLabel);
332             togglePanel.add(toggleButton);
333
334             Object JavaDoc[] messageArray = new Object JavaDoc[2];
335             messageArray[0] = inputMessage;
336             messageArray[1] = togglePanel;
337             String JavaDoc cmd = null;
338             if (getMessageUI() != null)
339               cmd = getMessageUI().showInputDialog(messageArray, inputTitle);
340             else
341               cmd = Pooka.getUIFactory().showInputDialog(messageArray, inputTitle);
342
343             if (cmd != null) {
344               if (cmd.indexOf("%s") == -1)
345                 cmd = cmd.concat(" %s");
346
347               if (toggleButton.isSelected()) {
348                 String JavaDoc newMailcap = new String JavaDoc(mType.toLowerCase() + ";" + cmd);
349                 ((FullMailcapCommandMap)Pooka.getMailcap()).addMailcap(newMailcap);
350               }
351
352
353               final DataHandler dh = fAttachment.getDataHandler();
354               final String JavaDoc fCmd = cmd;
355
356               if (dh != null) {
357                 AbstractAction action = new AbstractAction() {
358                     public void actionPerformed(java.awt.event.ActionEvent JavaDoc ae) {
359                       try {
360                         dh.setCommandMap(Pooka.getMailcap());
361                         ExternalLauncher el = new ExternalLauncher();
362
363                         el.setCommandContext(fCmd, dh);
364
365                         // create a progress dialog for the external launcher
366
int attachmentSize = fAttachment.getSize();
367                         if (fAttachment.getEncoding() != null && fAttachment.getEncoding().equalsIgnoreCase("base64"))
368                           attachmentSize = (int) (attachmentSize * .73);
369
370                         ProgressDialog dlg;
371                         if (getMessageUI() != null) {
372                           dlg = getMessageUI().createProgressDialog(0, attachmentSize, 0, "Fetching attachment","Fetching attachment");
373                         } else {
374                           dlg = Pooka.getUIFactory().createProgressDialog(0, attachmentSize, 0, "Fetching attachment","Fetching attachment");
375                         }
376
377                         final ExternalLauncher fLauncher = el;
378                         dlg.addCancelListener(new ProgressDialogListener() {
379                             public void dialogCancelled() {
380                               fLauncher.cancelSave();
381                             }
382                           });
383
384                         el.setProgressDialog(dlg);
385
386                         if (Pooka.isDebug())
387                           System.out.println("opening external launcher with ");
388                         el.show();
389                       } catch (Exception JavaDoc elException) {
390                         getMessageUI().showError("Error opening attachment", elException);
391                       }
392                     }
393                   };
394
395                 if (fActionThread != null) {
396                   fActionThread.addToQueue(action, new java.awt.event.ActionEvent JavaDoc(AttachmentHandler.this, 0, "attachment-open"));
397                 } else {
398                   action.actionPerformed( new java.awt.event.ActionEvent JavaDoc(AttachmentHandler.this, 0, "attachment-open"));
399                 }
400               }
401             }
402           }
403         });
404
405     } catch (Exception JavaDoc e) {
406       e.printStackTrace();
407     }
408   }
409
410
411   /**
412    * This opens up a JFileChooser to let the user choose under what
413    * name and where the selected Attachment should be saved. It then
414    * calls saveFileAs() to save the file.
415    */

416   public void saveAttachment(Attachment pAttachment, Component pComponent) {
417     // usually called on the folder thread. so we need to throw the
418
// filechooser over to the AWTEvent thread.
419

420     if (pAttachment != null) {
421       final Attachment fAttachment = pAttachment;
422       final Component fComponent = pComponent;
423       final String JavaDoc fileName = pAttachment.getName();
424
425       SwingUtilities.invokeLater(new Runnable JavaDoc() {
426           public void run() {
427             JFileChooser saveChooser;
428             String JavaDoc currentDirectoryPath = Pooka.getProperty("Pooka.tmp.currentDirectory", "");
429             if (currentDirectoryPath == "")
430               saveChooser = new JFileChooser();
431             else
432               saveChooser = new JFileChooser(currentDirectoryPath);
433
434             if (fileName != null)
435               saveChooser.setSelectedFile(new File(fileName));
436
437             int saveConfirm = saveChooser.showSaveDialog(fComponent);
438             Pooka.getResources().setProperty("Pooka.tmp.currentDirectory", saveChooser.getCurrentDirectory().getPath(), true);
439             if (saveConfirm == JFileChooser.APPROVE_OPTION) {
440               try {
441                 // saveFileAs creates a new thread, so don't bother
442
// dispatching this somewhere else.
443
saveFileAs(fAttachment, saveChooser.getSelectedFile());
444               } catch (IOException exc) {
445                 showError(Pooka.getProperty("error.SaveFile", "Error saving file") + ":\n", Pooka.getProperty("error.SaveFile", "Error saving file"), exc);
446               }
447             }
448           }
449         });
450     }
451   }
452
453   /**
454    * This opens up a JFileChooser to let the user choose the location
455    * to which to save the attachments. Then it calls saveFileAs() to save
456    * the attachments with their default filenames.
457    */

458   public void saveAllAttachments(Component pComponent) {
459     // usually called on the folder thread. so we need to throw the
460
// filechooser over to the AWTEvent thread.
461
try {
462       final Component fComponent = pComponent;
463       final java.util.List JavaDoc fAttachmentList = mProxy.getAttachments();
464
465       SwingUtilities.invokeLater(new Runnable JavaDoc() {
466           public void run() {
467             JFileChooser saveChooser;
468             String JavaDoc currentDirectoryPath = Pooka.getProperty("Pooka.tmp.currentDirectory", "");
469             if (currentDirectoryPath == "")
470               saveChooser = new JFileChooser();
471             else
472               saveChooser = new JFileChooser(currentDirectoryPath);
473
474             saveChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
475
476             int saveConfirm = saveChooser.showSaveDialog(fComponent);
477             File selectedDir = saveChooser.getSelectedFile();
478             Pooka.getResources().setProperty("Pooka.tmp.currentDirectory", saveChooser.getCurrentDirectory().getPath(), true);
479             if (saveConfirm == JFileChooser.APPROVE_OPTION) {
480               for (int i = 0; i < fAttachmentList.size(); i++) {
481                 Attachment currentAttachment = (Attachment) fAttachmentList.get(i);
482                 String JavaDoc filename = currentAttachment.getName();
483                 if (filename == null || filename.equals("")) {
484                   filename = "savedFile_" + i;
485                 }
486                 File currentFile = new File(selectedDir, filename);
487                 try {
488                   // saveFileAs creates a new thread, so don't bother
489
// dispatching this somewhere else.
490
saveFileAs(currentAttachment, currentFile);
491                 } catch (IOException exc) {
492                   showError(Pooka.getProperty("error.SaveFile", "Error saving file") + ":\n", Pooka.getProperty("error.SaveFile", "Error saving file"), exc);
493                 }
494               }
495             }
496           }
497         });
498     } catch (javax.mail.MessagingException JavaDoc me) {
499       showError("Error getting attachment list", me);
500     }
501
502
503   }
504
505   /**
506    * This actually saves the Attachment as the File saveFile.
507    */

508   public void saveFileAs(Attachment mbp, File saveFile) throws IOException {
509     SaveAttachmentThread thread = new SaveAttachmentThread(mbp, saveFile);
510     thread.start();
511   }
512
513
514   class SaveAttachmentThread extends Thread JavaDoc {
515
516     Attachment attachment;
517     File saveFile;
518     ProgressDialog dialog;
519     boolean running = true;
520
521     SaveAttachmentThread(Attachment newAttachment, File newSaveFile) {
522       attachment = newAttachment;
523       saveFile = newSaveFile;
524     }
525
526     public void run() {
527       InputStream decodedIS = null;
528       BufferedOutputStream outStream = null;
529
530       int attachmentSize = 0;
531
532       try {
533         decodedIS = attachment.getInputStream();
534         attachmentSize = attachment.getSize();
535         if (attachment.getEncoding() != null && attachment.getEncoding().equalsIgnoreCase("base64"))
536           attachmentSize = (int) (attachmentSize * .73);
537
538         dialog = createDialog(attachmentSize);
539         dialog.show();
540
541         outStream = new BufferedOutputStream(new FileOutputStream(saveFile));
542         int b=0;
543         byte[] buf = new byte[32768];
544
545         b = decodedIS.read(buf);
546         while (b != -1 && running) {
547           outStream.write(buf, 0, b);
548           dialog.setValue(dialog.getValue() + b);
549           if (dialog.isCancelled())
550             running=false;
551
552           b = decodedIS.read(buf);
553         }
554
555       } catch (IOException ioe) {
556         showError("Error saving file", ioe);
557         cancelSave();
558       } finally {
559         if (outStream != null) {
560           try {
561             outStream.flush();
562             outStream.close();
563           } catch (IOException ioe) {}
564         }
565         if (dialog != null)
566           dialog.dispose();
567       }
568     }
569
570     /**
571      * Creates a progress dialog to show the downloading of an attachment.
572      */

573     public ProgressDialog createDialog(int attachmentSize) {
574       ProgressDialog dlg;
575       if (getMessageUI() != null) {
576         dlg = getMessageUI().createProgressDialog(0, attachmentSize, 0, saveFile.getName(), saveFile.getName());
577       } else {
578         dlg = Pooka.getUIFactory().createProgressDialog(0, attachmentSize, 0, saveFile.getName(), saveFile.getName());
579       }
580
581       dlg.addCancelListener(new ProgressDialogListener() {
582           public void dialogCancelled() {
583             cancelSave();
584           }
585         });
586       return dlg;
587     }
588
589     public void cancelSave() {
590       try {
591         saveFile.delete();
592       } catch (Exception JavaDoc e) {}
593       dialog.dispose();
594     }
595   } // SaveAttachmentThread
596

597 }
598
599
Popular Tags