KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > SnowMailClient > model > folders > FolderTreeNode


1 package SnowMailClient.model.folders;
2
3 import snow.utils.storage.*;
4 import snow.utils.gui.*;
5 import SnowMailClient.model.*;
6 import SnowMailClient.Language.Language;
7 import SnowMailClient.crypto.*;
8 import SnowMailClient.SnowMailClientApp;
9 import SnowMailClient.SpamFilter.*;
10
11 import java.awt.*;
12 import java.awt.event.*;
13 import javax.swing.*;
14 import javax.swing.tree.*;
15 import java.io.*;
16 import java.util.*;
17 import java.security.*;
18 import java.security.spec.*;
19 import javax.crypto.spec.*;
20 import javax.crypto.*;
21
22 /** This is a tree node representing a mail folder.
23     Use only this to access a folder because this has a kind of weak reference allowing
24     to save the folder and free memory if needed.
25
26 */

27 public final class FolderTreeNode extends DefaultMutableTreeNode //implements Iterable<FolderTreeNode>
28
{
29   boolean systemFolder = false;
30
31   // created or read from file on demand (for memory reasons)
32
private MailFolder mailFolder;
33
34   private static final String JavaDoc folder_File_Name = "content.mailFolder";
35
36
37   public FolderTreeNode( String JavaDoc name, DefaultMutableTreeNode parent ) throws Exception JavaDoc
38   {
39     super(name);
40     if(parent!=null)
41     {
42       parent.add(this);
43     }
44
45     // make file
46
File folderFile = new File( getFolderFullPath());
47     if(folderFile.exists())
48     {
49        if(!folderFile.isDirectory())
50        {
51           throw new Exception JavaDoc(Language.translate("Folder % is not a directory", folderFile.getAbsolutePath()));
52        }
53     }
54     else
55     {
56        if(!folderFile.mkdirs())
57        {
58           throw new Exception JavaDoc(Language.translate("Cannot create folder %",folderFile.getAbsolutePath()));
59        }
60     }
61
62     parseChilds();
63
64   }
65
66   /** use them to iterate. Is a copy of the child list !
67      remove on this vector has no influence !
68      But references can be used to safely remove from childs from this node
69   */

70   public Vector<FolderTreeNode> getFirstlevelChilds()
71   {
72     Vector<FolderTreeNode> flc = new Vector<FolderTreeNode>();
73     for(int i=0; i<getChildCount(); i++)
74     {
75       flc.addElement(getFolderChildAt(i));
76     }
77     return flc;
78   }
79
80   private void parseChilds() throws Exception JavaDoc
81   {
82      File thisFolder = new File(getFolderFullPath());
83      File[] dirs = thisFolder.listFiles( new FileFilter()
84      {
85        public boolean accept(File pathname)
86        {
87          return pathname.isDirectory();
88        }
89      } );
90
91      for(File ci: dirs)
92      {
93        new FolderTreeNode(ci.getName(), this);
94      }
95   }
96
97   public boolean hasChild(String JavaDoc name)
98   {
99     return new File(getFolderFullPath(), name).exists();
100   }
101
102   /** at first level
103   */

104   public FolderTreeNode getChild(String JavaDoc name)
105   {
106     File folderToSearch = new File(this.getFolderFile(), name);
107     //for(int i=0; i<this.getChildCount(); i++)
108

109     for(FolderTreeNode childNode: getFirstlevelChilds())
110     {
111       //FolderTreeNode childNode = (FolderTreeNode) this.getChildAt(i);
112
if(childNode.getFolderFile().equals(folderToSearch)) return childNode;
113     }
114     return null;
115   }
116
117   public FolderTreeNode getFolderChildAt(int i)
118   {
119     return (FolderTreeNode) this.getChildAt(i);
120   }
121
122   public String JavaDoc getFolderName()
123   {
124     return (String JavaDoc) this.getUserObject();
125   }
126
127   public FolderTreeNode getParentNode()
128   {
129     return (FolderTreeNode) this.getParent();
130   }
131
132   public String JavaDoc getFolderFullPath()
133   {
134     FolderTreeNode parent = (FolderTreeNode) getParent();
135     if(parent!=null)
136     {
137       return parent.getFolderFullPath()
138         + System.getProperty("file.separator","\\")
139         + this.getFolderName();
140     }
141     return this.getFolderName();
142   }
143
144
145   /** fill the search result with all hits
146   */

147   public void searchMailMessagesContaining(String JavaDoc search, final SearchResults result, boolean recurse) throws Exception JavaDoc
148   {
149     // Search in folder
150
//
151
MailFolder folder = this.getMailFolder();
152     for(int i=0; i<folder.getRowCount(); i++)
153     {
154        final MailMessage mess = folder.getMessageAt(i);
155        if(folder.hitForTextSearch(i, search, null)) // also looks in the message !
156
{
157          // already found in the table
158
EventQueue.invokeLater(new Runnable JavaDoc() // important: UI calls in the EDT !
159
{ public void run() {
160             result.addHit(new SearchHit(mess, FolderTreeNode.this));
161             SnowMailClientApp.getInstance().getSearchPanel().updateTree();
162          }});
163        }
164 /* else
165        {
166          // look in message
167          if(mess.searchText(search))
168          {
169            EventQueue.invokeLater(new Runnable()
170            { public void run() {
171               result.addHit(new SearchHit(mess, FolderTreeNode.this));
172               SnowMailClientApp.getInstance().getSearchPanel().updateTree();
173            }});
174          }
175        } */

176     }
177
178     // Recursion
179
//
180
if(recurse)
181     {
182        for(FolderTreeNode childNode: getFirstlevelChilds())
183        {
184          childNode.searchMailMessagesContaining(search, result, recurse);
185        }
186     }
187   }
188
189   public int getTotalNumberOfFoldersIncludingThis()
190   {
191     int n = 1; // itself
192
for(FolderTreeNode childNode: getFirstlevelChilds())
193     {
194       n += childNode.getTotalNumberOfFoldersIncludingThis();
195     }
196     return n;
197   }
198
199   public void analyseAllMailsToTrainSPAMFilter(WordStatistic stat, ProgressModalDialog progress, boolean recurse) throws Exception JavaDoc
200   {
201     // analyse this folder
202
MailFolder folder = this.getMailFolder();
203
204     progress.setProgressComment( ""+folder.getFolderName()
205          +", "+Language.translate("Total words count")+"="+stat.getNumberOfWords());
206     progress.incrementProgress(1);
207
208     for(MailMessage mess: folder.getAllMessages())
209     {
210        if(progress.wasCancelled())
211        {
212          throw new Exception JavaDoc(Language.translate("Training cancelled"));
213        }
214        stat.addMessageToStat( mess );
215     }
216
217     // Recursion
218
//
219
if(recurse)
220     {
221        for(FolderTreeNode childNode: getFirstlevelChilds())
222        {
223          childNode.analyseAllMailsToTrainSPAMFilter(stat, progress, recurse);
224        }
225     }
226   }
227
228   public void calculateSPAMNoteForEachMailRecurse(WordStatistic stat, ProgressModalDialog progress, boolean recurse) throws Exception JavaDoc
229   {
230     MailFolder folder = this.getMailFolder();
231     //folder.setContentHasChanged(false);
232

233     progress.setProgressComment( ""+folder.getFolderName());
234     progress.incrementProgress(1);
235
236     for(MailMessage mess: folder.getAllMessages())
237     {
238        if(progress.wasCancelled())
239        {
240          throw new Exception JavaDoc(Language.translate("SPAM Analysis cancelled"));
241        }
242
243        // message analysis
244

245        SpamResult sr = stat.calculateSpamProbability( mess );
246        double p = sr.getProbability();
247        mess.setSPAMProbability(p);
248
249        boolean isSpam = stat.isSpam(p);
250        if(isSpam && mess.getIsHAM())
251        {
252           stat.result_false_positives++;
253           System.out.println("False positive in "+this.getFolderFullPath());
254           stat.addFalsePositive(this.getFolderName()+ " "+mess.getFromAddress().toString());
255        }
256        if(isSpam && mess.getIsSPAM()) stat.result_detected_spams++;
257
258        // header analysis
259

260        Header header = mess.getHeader();
261        p = stat.calculateSpamProbability(header).getProbability();
262
263        isSpam = stat.isSpam(p);
264        if(isSpam && mess.getIsHAM())
265        {
266           stat.result_false_positives_header++;
267           stat.addFalsePositive(this.getFolderName()+ " "+mess.getFromAddress().toString()+" (Header detection only)");
268        }
269        if(isSpam && mess.getIsSPAM()) stat.result_detected_spams_header++;
270
271     }
272
273     // Recursion
274
//
275
if(recurse)
276     {
277        for(FolderTreeNode childNode: getFirstlevelChilds())
278        {
279          childNode.calculateSPAMNoteForEachMailRecurse(stat, progress, recurse);
280        }
281     }
282   }
283
284   /** @return the file where the folder is stored
285   */

286   public File getFolderFile() { return new File( getFolderFullPath() ); }
287
288   public void removeThisFolder() throws Exception JavaDoc
289   {
290      if(this.getParent()==null) throw new Exception JavaDoc("Cannot remove root folder");
291      if(systemFolder) throw new Exception JavaDoc("System folder "+getFolderName()+" cannot be removed");
292      File thisFolder = getFolderFile();
293      File[] files = thisFolder.listFiles();
294      if(files.length>0)
295      {
296        // look if mail folder file is present
297
File mailFolderFile = new File(getFolderFile(), folder_File_Name);
298        if(mailFolderFile.exists())
299        {
300          if(files.length>1)
301          {
302            throw new Exception JavaDoc("Folder "+thisFolder+" is not empty, it has extra files.");
303          }
304          else
305          {
306            MailFolder mf = this.getMailFolder();
307            if(mf.getRowCount()>0)
308            {
309              throw new Exception JavaDoc("Folder "+getFolderName()+" is not empty.");
310            }
311            else
312            {
313              // delete it
314
mailFolderFile.delete();
315            }
316          }
317        }
318        else
319        {
320          throw new Exception JavaDoc("Folder "+thisFolder+" is not empty, it has extra files.");
321        }
322      }
323
324      if(!thisFolder.delete())
325      {
326        throw new Exception JavaDoc("Folder "+getFolderName()+" was not deleted successfully");
327      }
328
329      removeAllChildren();
330      removeFromParent();
331
332   }
333
334   /** Renames the folder (copy the folder).
335   */

336   public void rename(String JavaDoc newName) throws Exception JavaDoc
337   {
338      if(this.getParent()==null) throw new Exception JavaDoc(Language.translate("Cannot rename root folder"));
339      if(systemFolder)
340      {
341        throw new Exception JavaDoc(Language.translate("System folder % cannot be renamed", getFolderName()));
342      }
343
344      // Test files
345
File thisFolderFile = getFolderFile();
346      File parentFile = thisFolderFile.getParentFile();
347
348      File newFolderParentFile = new File(parentFile, newName);
349      File newFolderContentFile = new File(newFolderParentFile, folder_File_Name);
350
351      if(newFolderContentFile.exists())
352      {
353        throw new Exception JavaDoc(Language.translate("Cannot rename folder, the destination folder already exists."));
354      }
355
356      if(!newFolderParentFile.exists())
357      {
358         if(!newFolderParentFile.mkdirs())
359         {
360            throw new Exception JavaDoc(Language.translate("Cannot create folder directory %",newFolderParentFile.getAbsolutePath()));
361         }
362      }
363
364      // read the mail folder
365
MailFolder mf = getMailFolder();
366      mf.setContentHasChanged(false); // force to ensure save !
367
// the folder name is the user object
368
this.setUserObject(newName);
369      // save it in the new location
370
saveMailFolder(false); // don't close
371

372      // everything was ok => delete the old...
373
File oldMailFolderFile = new File(thisFolderFile, "content.mailFolder");
374      if(oldMailFolderFile.exists() && !oldMailFolderFile.delete())
375      {
376         throw new Exception JavaDoc("Cannot delete the old folder "+oldMailFolderFile.getAbsolutePath());
377      }
378   }
379
380   public void setIsSystemFolder(boolean is)
381   {
382      systemFolder = is;
383   }
384
385   public boolean isSystemFolder() { return systemFolder; }
386
387   // Folder
388
//
389

390   public boolean isMailFolderOpened()
391   {
392      return (mailFolder!=null);
393   }
394
395   /** @return the mail folder associated with this node.
396       At the first call (of the snowmail instance),
397       the folder is read from the file.
398       If the mail folder file doesn't exist (this is the case when
399       it is newly created, the file is created.
400   */

401   public MailFolder getMailFolder() throws Exception JavaDoc
402   {
403      if(mailFolder!=null) return mailFolder;
404
405      mailFolder = new MailFolder(this);
406
407      // is file existing ?
408
File mailFolderFile = new File(getFolderFile(), "content.mailFolder");
409      if(!mailFolderFile.exists())
410      {
411         // create it
412
// version 0
413
// FileUtils.saveVectorToFile(mailFolderFile, mailFolder.getVectorRepresentation());
414

415         // version 1: static easy key, just to avoid easy mail read in the folder files
416
// version 2: actual key used, if defined
417
FileCipherManager.getInstance().encipherVectorWithHeadToFile(
418                  new Vector<Object JavaDoc>(), new Vector<Object JavaDoc>(),
419                  mailFolder.getVectorRepresentation(),
420                  mailFolderFile,
421                  SecretKeyManager.getInstance().getActualKey());
422      }
423
424      // read it
425
try
426      {
427         try
428         {
429            Vector<Object JavaDoc> v = FileCipherManager.getInstance().decipherVectorFromFile_ASK_KEY_IF_NEEDED(
430                   mailFolderFile,
431                   SnowMailClientApp.getInstance(),
432                   Language.translate("Folder Password"),
433                   Language.translate("Enter the passphrase to decipher the folder %",this.getFolderName())
434                   );
435            mailFolder.createFromVectorRepresentation( v );
436         }
437         catch(EOFException eofex)
438         {
439            // this occurs when the folder was not fully wrote !
440
// TODO: recover !
441
throw eofex;
442         }
443         catch(Exception JavaDoc ee)
444         {
445            System.out.println("Error: cannot read "+mailFolderFile+"\n error="+ee.getMessage());
446            System.out.println("Trying old version 0");
447            // try old version 0
448
try
449            {
450              Vector<Object JavaDoc> v = FileUtils.loadVectorFromFile(mailFolderFile);
451              mailFolder.createFromVectorRepresentation( v );
452            }
453            catch(Exception JavaDoc eee)
454            {
455               // see the old error:
456
ee.printStackTrace();
457              throw eee;
458            }
459         }
460      }
461      catch(OutOfMemoryError JavaDoc e)
462      {
463         throw new Exception JavaDoc("Canot read mail folder from file "+mailFolderFile.getAbsolutePath()
464           +"\nBecause of an out of memory error. Restart Snowmail with more memory (-Xmx512m).");
465      }
466      catch(Exception JavaDoc e)
467      {
468         throw new Exception JavaDoc("Canot read mail folder from file "+mailFolderFile.getAbsolutePath()
469           +"\nException message="+e.getMessage());
470      }
471      catch(Error JavaDoc e)
472      {
473         throw new Exception JavaDoc("Canot read mail folder from file "+mailFolderFile.getAbsolutePath()
474           +"\nError message="+e.getMessage());
475      }
476
477      return mailFolder;
478   }
479
480   /** Save if content has changed
481       @param close if true, closes the folder (remove it from memory)
482   */

483   public void saveMailFolder(boolean close) throws Exception JavaDoc
484   {
485      if(mailFolder==null) return;
486
487      // not null
488

489      if(mailFolder.hasContentChanged())
490      {
491         File mailFolderFile = new File(getFolderFile(), "content.mailFolder");
492         // version 2: custom key possible, default static used if no pass set
493
FileCipherManager.getInstance().encipherVectorWithHeadToFile(
494              new Vector<Object JavaDoc>(),
495              new Vector<Object JavaDoc>(),
496              mailFolder.getVectorRepresentation(),
497              mailFolderFile, SecretKeyManager.getInstance().getActualKey());
498
499         mailFolder.setContentWasStored();
500      }
501
502      if(close)
503      {
504
505         mailFolder.notifyMailFolderListener_of_FolderClosed();
506         mailFolder = null;
507         // let GC close it...
508
}
509   }
510
511
512 } // FolderTreeNode
Popular Tags