KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > mail > providers > mbox > MboxFolder


1 /*
2  * MboxFolder.java
3  * Copyright (C) 1999 dog <dog@dog.net.uk>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * You also have permission to link it with the Sun Microsystems, Inc.
11  * JavaMail(tm) extension and run that combination.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  *
22  * Contributor(s): Daniel Thor Kristjan <danielk@cat.nyu.edu>
23  * close and expunge clarification.
24  * Sverre Huseby <sverrehu@online.no> gzipped mailboxes
25  */

26
27 package gnu.mail.providers.mbox;
28
29 import java.io.BufferedOutputStream JavaDoc;
30 import java.io.ByteArrayInputStream JavaDoc;
31 import java.io.ByteArrayOutputStream JavaDoc;
32 import java.io.File JavaDoc;
33 import java.io.FileInputStream JavaDoc;
34 import java.io.FileOutputStream JavaDoc;
35 import java.io.FilenameFilter JavaDoc;
36 import java.io.IOException JavaDoc;
37 import java.io.InputStream JavaDoc;
38 import java.io.OutputStream JavaDoc;
39 import java.text.DateFormat JavaDoc;
40 import java.text.SimpleDateFormat JavaDoc;
41 import java.util.Date JavaDoc;
42 import java.util.Vector JavaDoc;
43 import java.util.zip.GZIPInputStream JavaDoc;
44 import java.util.zip.GZIPOutputStream JavaDoc;
45 import javax.mail.Address JavaDoc;
46 import javax.mail.FetchProfile JavaDoc;
47 import javax.mail.Flags JavaDoc;
48 import javax.mail.Folder JavaDoc;
49 import javax.mail.Message JavaDoc;
50 import javax.mail.MessagingException JavaDoc;
51 import javax.mail.Store JavaDoc;
52 import javax.mail.URLName JavaDoc;
53 import javax.mail.event.ConnectionEvent JavaDoc;
54 import javax.mail.event.FolderEvent JavaDoc;
55 import javax.mail.internet.AddressException JavaDoc;
56 import javax.mail.internet.InternetAddress JavaDoc;
57 import javax.mail.internet.MimeMessage JavaDoc;
58 import gnu.mail.util.LineInputStream;
59 import gnu.mail.treeutil.StatusEvent;
60
61 /**
62  * The folder class implementing a UNIX mbox-format mailbox.
63  *
64  * @author dog@dog.net.uk
65  * @version 2.0
66  */

67 public class MboxFolder
68   extends Folder JavaDoc
69 {
70
71   static final DateFormat JavaDoc df = new SimpleDateFormat JavaDoc("EEE MMM d H:m:s yyyy");
72   static final String JavaDoc GNU_MESSAGE_ID = "X-GNU-Message-Id";
73   static final String JavaDoc FROM = "From ";
74     
75   File JavaDoc file;
76   MboxMessage[] messages;
77   boolean open;
78   boolean readOnly;
79   int type;
80   boolean inbox;
81   
82   Flags JavaDoc permanentFlags = null;
83         
84   /**
85    * Constructor.
86    */

87   protected MboxFolder(Store JavaDoc store, String JavaDoc filename, boolean inbox)
88   {
89     super(store);
90     
91     file = new File JavaDoc(filename);
92     if (file.exists() && file.isDirectory())
93       type = HOLDS_FOLDERS;
94     else
95       type = HOLDS_MESSAGES;
96     this.inbox = inbox;
97     open = false;
98     readOnly = true;
99     messages = new MboxMessage[0];
100   }
101     
102   /**
103    * Constructor.
104    */

105   protected MboxFolder(Store JavaDoc store, String JavaDoc filename)
106   {
107     this(store, filename, false);
108   }
109
110   /**
111    * Returns the name of this folder.
112    */

113   public String JavaDoc getName()
114   {
115     if (inbox)
116       return "INBOX";
117     return file.getName();
118   }
119     
120   /**
121    * Returns the full name of this folder.
122    */

123   public String JavaDoc getFullName()
124   {
125     if (inbox)
126       return "INBOX";
127     return file.getPath();
128   }
129
130   /**
131    * Return a URLName representing this folder.
132    */

133   public URLName JavaDoc getURLName()
134     throws MessagingException JavaDoc
135   {
136     URLName JavaDoc url = super.getURLName();
137     return new URLName JavaDoc(url.getProtocol(),
138         null, -1, url.getFile(),
139         null, null);
140   }
141
142   /**
143    * Returns the type of this folder.
144    * @exception MessagingException if a messaging error occurred
145    */

146   public int getType()
147     throws MessagingException JavaDoc
148   {
149     return type;
150   }
151
152   /**
153    * Indicates whether this folder exists.
154    * @exception MessagingException if a messaging error occurred
155    */

156   public boolean exists()
157     throws MessagingException JavaDoc
158   {
159     return file.exists();
160   }
161
162   /**
163    * Indicates whether this folder contains new messages.
164    * @exception MessagingException if a messaging error occurred
165    */

166   public boolean hasNewMessages()
167     throws MessagingException JavaDoc
168   {
169     return getNewMessageCount()>0;
170   }
171
172   /**
173    * Opens this folder.
174    * If the folder is opened for writing, a lock must be acquired on the
175    * mbox. If this fails a MessagingException is thrown.
176    * @exception MessagingException if a messaging error occurred
177    */

178   public void open(int mode)
179     throws MessagingException JavaDoc
180   {
181     if (mode==READ_WRITE)
182     {
183       if (!file.canWrite())
184         throw new MessagingException JavaDoc("Folder is read-only");
185       if (!acquireLock())
186         throw new MessagingException JavaDoc("Unable to acquire lock");
187       readOnly = false;
188     }
189
190     if (!file.canRead())
191       throw new MessagingException JavaDoc("Can't read folder: "+file.getName());
192
193     LineInputStream in = null;
194     String JavaDoc filename = file.getAbsolutePath();
195     try
196     {
197       // Read messages
198
MboxStore store = (MboxStore)this.store;
199       store.log("reading "+filename);
200       
201       Vector JavaDoc vm = new Vector JavaDoc(256);
202       in = new LineInputStream(getInputStream());
203       int count = 1;
204       String JavaDoc line, fromLine = null;
205       ByteArrayOutputStream JavaDoc buf = null;
206
207       // notify listeners
208
store.processStatusEvent(new StatusEvent(store,
209             StatusEvent.OPERATION_START,
210             "open"));
211           
212       for (line = in.readLine(); line!=null; line = in.readLine())
213       {
214         if (line.indexOf(FROM)==0)
215         {
216           if (buf!=null)
217           {
218             byte[] bytes = buf.toByteArray();
219             ByteArrayInputStream JavaDoc bin = new ByteArrayInputStream JavaDoc(bytes);
220             MboxMessage m = new MboxMessage(this, fromLine, bin, count++);
221             vm.addElement(m);
222
223             store.processStatusEvent(new StatusEvent(store,
224                   StatusEvent.OPERATION_UPDATE,
225                   "open",
226                   1,
227                   StatusEvent.UNKNOWN,
228                   count-1));
229           }
230           fromLine = line;
231           buf = new ByteArrayOutputStream JavaDoc();
232         }
233         else if (buf!=null)
234         {
235           byte[] bytes = decodeFrom(line).getBytes();
236           buf.write(bytes, 0, bytes.length);
237           buf.write(10); // LF
238
}
239       }
240       if (buf!=null)
241       {
242         byte[] bytes = buf.toByteArray();
243         ByteArrayInputStream JavaDoc bin = new ByteArrayInputStream JavaDoc(bytes);
244         MboxMessage m = new MboxMessage(this, fromLine, bin, count++);
245         vm.addElement(m);
246
247         store.processStatusEvent(new StatusEvent(store,
248               StatusEvent.OPERATION_UPDATE,
249               "open",
250               1,
251               StatusEvent.UNKNOWN,
252               count-1));
253       }
254       messages = new MboxMessage[vm.size()];
255       vm.copyInto(messages);
256       buf = null;
257       vm = null;
258
259       store.processStatusEvent(new StatusEvent(store,
260             StatusEvent.OPERATION_END,
261             "open"));
262
263       // OK
264
open = true;
265       notifyConnectionListeners(ConnectionEvent.OPENED);
266     }
267     catch (IOException JavaDoc e)
268     {
269       throw new MessagingException JavaDoc("Unable to open folder: "+filename, e);
270     }
271     finally
272     {
273       // release any file descriptors
274
try
275       {
276         if (in!=null)
277           in.close();
278       }
279       catch (IOException JavaDoc e)
280       {
281         // we tried
282
}
283     }
284   }
285
286   /**
287    * Returns the specified line with any From_ line encoding removed.
288    */

289   public static String JavaDoc decodeFrom(String JavaDoc line)
290   {
291     if (line!=null)
292     {
293       int len = line.length();
294       for (int i=0; i<(len-5); i++)
295       {
296         char c = line.charAt(i);
297         if (i>0 &&
298             (c=='F' &&
299              line.charAt(i+1)=='r' &&
300              line.charAt(i+2)=='o' &&
301              line.charAt(i+3)=='m' &&
302              line.charAt(i+4)==' '))
303           return line.substring(1);
304         if (c!='>')
305           break;
306       }
307     }
308     return line;
309   }
310   
311   /**
312    * Closes this folder.
313    * @param expunge if the folder is to be expunged before it is closed
314    * @exception MessagingException if a messaging error occurred
315    */

316   public void close(boolean expunge)
317     throws MessagingException JavaDoc
318   {
319     if (open)
320     {
321       if (expunge)
322         expunge();
323     
324       if (!readOnly)
325       {
326         // Save messages
327
MboxStore store = (MboxStore)this.store;
328         store.log("saving "+file.getAbsolutePath());
329         synchronized (this)
330         {
331           OutputStream JavaDoc os = null;
332           try
333           {
334             os = getOutputStream();
335             BufferedOutputStream JavaDoc bos = new BufferedOutputStream JavaDoc(os);
336             MboxOutputStream mos = new MboxOutputStream(bos);
337
338             store.processStatusEvent(new StatusEvent(store,
339                   StatusEvent.OPERATION_START,
340                   "close"));
341             for (int i=0; i<messages.length; i++)
342             {
343               String JavaDoc fromLine = fromLine(messages[i]);
344               bos.write(fromLine.getBytes());
345               bos.write('\n');
346               bos.flush();
347               messages[i].writeTo(mos);
348               mos.flush();
349
350               store.processStatusEvent(new StatusEvent(store,
351                     StatusEvent.OPERATION_UPDATE,
352                     "close",
353                     1,
354                     messages.length,
355                     i+1));
356             }
357
358             store.processStatusEvent(new StatusEvent(store,
359                   StatusEvent.OPERATION_END,
360                   "close"));
361           }
362           catch (IOException JavaDoc e)
363           {
364             throw new MessagingException JavaDoc("I/O error writing mailbox", e);
365           }
366           finally
367           {
368             // close any file descriptors
369
try
370             {
371               if (os!=null)
372                 os.close();
373             }
374             catch (IOException JavaDoc e)
375             {
376               // we tried
377
}
378           }
379         }
380         if (!releaseLock())
381           store.log("unable to clear up lock file!");
382       }
383       
384       open = false;
385       messages = new MboxMessage[0]; // release memory
386
notifyConnectionListeners(ConnectionEvent.CLOSED);
387     }
388   }
389
390   /**
391    * Returns the From_ line for the specified mbox message.
392    * If this does not already exist (the message was appended to the folder
393    * since it was last opened), we will attempt to generate a suitable From_
394    * line for it.
395    */

396   protected String JavaDoc fromLine(MboxMessage message)
397     throws MessagingException JavaDoc
398   {
399     String JavaDoc fromLine = message.fromLine;
400     if (fromLine==null)
401     {
402       StringBuffer JavaDoc buf = new StringBuffer JavaDoc("From ");
403       
404       String JavaDoc from = "-";
405       try
406       {
407         Address JavaDoc[] f = message.getFrom();
408         if (f!=null && f.length>0)
409         {
410           if (f[0] instanceof InternetAddress JavaDoc)
411             from = ((InternetAddress JavaDoc)f[0]).getAddress();
412           else
413             from = f[0].toString();
414         }
415       }
416       catch (AddressException JavaDoc e)
417       {
418         // these things happen...
419
}
420       buf.append(from);
421       buf.append(' ');
422       
423       Date JavaDoc date = message.getSentDate();
424       if (date==null)
425         date = message.getReceivedDate();
426       if (date==null)
427         date = new Date JavaDoc();
428       buf.append(df.format(date));
429       
430       fromLine = buf.toString();
431     }
432     return fromLine;
433   }
434     
435   /**
436    * Expunges this folder.
437    * This deletes all the messages marked as deleted.
438    * @exception MessagingException if a messaging error occurred
439    */

440   public synchronized Message JavaDoc[] expunge()
441     throws MessagingException JavaDoc
442   {
443     Vector JavaDoc ve = new Vector JavaDoc();
444     if (open)
445     {
446       Vector JavaDoc vm = new Vector JavaDoc();
447       for (int i=0; i<messages.length; i++)
448       {
449         Flags JavaDoc flags = messages[i].getFlags();
450         if (flags.contains(Flags.Flag.DELETED))
451         {
452           ve.addElement(messages[i]);
453           if (messages[i] instanceof MboxMessage)
454             ((MboxMessage)messages[i]).setExpunged(true);
455         }
456         else
457           vm.addElement(messages[i]);
458       }
459       messages = new MboxMessage[vm.size()];
460       vm.copyInto(messages);
461     }
462     Message JavaDoc[] expunged = new Message JavaDoc[ve.size()];
463     ve.copyInto(expunged);
464     if (expunged.length>0)
465       notifyMessageRemovedListeners(true, expunged);
466     return expunged;
467   }
468   
469   /**
470    * Indicates whether this folder is open.
471    */

472   public boolean isOpen()
473   {
474     return open;
475   }
476     
477   /**
478    * Returns the permanent flags for this folder.
479    */

480   public Flags JavaDoc getPermanentFlags()
481   {
482     if (permanentFlags == null)
483     {
484       Flags JavaDoc flags = new Flags JavaDoc();
485       flags.add(Flags.Flag.DELETED);
486       flags.add(Flags.Flag.SEEN);
487       flags.add(Flags.Flag.RECENT);
488       permanentFlags = flags;
489     }
490     return permanentFlags;
491   }
492     
493   /**
494    * Returns the number of messages in this folder.
495    * @exception MessagingException if a messaging error occurred
496    */

497   public int getMessageCount()
498     throws MessagingException JavaDoc
499   {
500     return messages.length;
501   }
502
503   /**
504    * Returns the specified message number from this folder.
505    * @exception MessagingException if a messaging error occurred
506    */

507   public Message JavaDoc getMessage(int msgnum)
508     throws MessagingException JavaDoc
509   {
510     int index = msgnum-1;
511     if (index<0 || index>=messages.length)
512       throw new MessagingException JavaDoc("No such message: "+msgnum);
513     return messages[index];
514   }
515     
516   /**
517    * Returns the messages in this folder.
518    * @exception MessagingException if a messaging error occurred
519    */

520   public synchronized Message JavaDoc[] getMessages()
521     throws MessagingException JavaDoc
522   {
523     // Return a copy of the message array
524
Message JavaDoc[] m = new Message JavaDoc[messages.length];
525     System.arraycopy(messages, 0, m, 0, messages.length);
526     return m;
527   }
528     
529   /**
530    * Appends messages to this folder.
531    * Only MimeMessages within the array will be appended, as we don't know
532    * how to retrieve internet content for other kinds.
533    * @param m an array of messages to be appended
534    */

535   public synchronized void appendMessages(Message JavaDoc[] m)
536     throws MessagingException JavaDoc
537   {
538     Vector JavaDoc appended = new Vector JavaDoc(m.length);
539     int count = messages.length;
540     for (int i=0; i<m.length; i++)
541     {
542       if (m[i] instanceof MimeMessage JavaDoc)
543       {
544         MimeMessage JavaDoc mimem = (MimeMessage JavaDoc)m[i];
545         MboxMessage mboxm = new MboxMessage(this, mimem, count++);
546         if (mimem instanceof MboxMessage)
547           mboxm.fromLine = ((MboxMessage)mimem).fromLine;
548         appended.addElement(mboxm);
549       }
550     }
551     int appendedLength = appended.size();
552     if (appendedLength>0)
553     {
554       MboxMessage[] n = new MboxMessage[appendedLength];
555       appended.copyInto(n);
556
557       // copy into the messages array
558
Vector JavaDoc accumulator = new Vector JavaDoc(messages.length+n.length);
559       for (int i=0; i<messages.length; i++)
560         accumulator.addElement(messages[i]);
561       for (int i=0; i<n.length; i++)
562         accumulator.addElement(n[i]);
563       messages = new MboxMessage[accumulator.size()];
564       accumulator.copyInto(messages);
565       
566       // propagate event
567
notifyMessageAddedListeners(n);
568     }
569   }
570
571   /**
572    * Does nothing.
573    * @exception MessagingException ignore
574    */

575   public void fetch(Message JavaDoc[] messages, FetchProfile JavaDoc fetchprofile)
576     throws MessagingException JavaDoc
577   {
578   }
579
580   /**
581    * Returns the parent folder.
582    */

583   public Folder JavaDoc getParent()
584     throws MessagingException JavaDoc
585   {
586     return store.getFolder(file.getParent());
587   }
588
589   /**
590    * Returns the subfolders of this folder.
591    */

592   public Folder JavaDoc[] list()
593     throws MessagingException JavaDoc
594   {
595     if (type!=HOLDS_FOLDERS)
596       throw new MessagingException JavaDoc("This folder can't contain subfolders");
597     try
598     {
599       String JavaDoc[] files = file.list();
600       Folder JavaDoc[] folders = new Folder JavaDoc[files.length];
601       for (int i=0; i<files.length; i++)
602       folders[i] =
603         store.getFolder(file.getAbsolutePath()+File.separator+files[i]);
604       return folders;
605     }
606     catch (SecurityException JavaDoc e)
607     {
608       throw new MessagingException JavaDoc("Access denied", e);
609     }
610   }
611
612   /**
613    * Returns the subfolders of this folder matching the specified pattern.
614    */

615   public Folder JavaDoc[] list(String JavaDoc pattern)
616     throws MessagingException JavaDoc
617   {
618     if (type!=HOLDS_FOLDERS)
619       throw new MessagingException JavaDoc("This folder can't contain subfolders");
620     try
621     {
622       String JavaDoc[] files = file.list(new MboxFilenameFilter(pattern));
623       Folder JavaDoc[] folders = new Folder JavaDoc[files.length];
624       for (int i=0; i<files.length; i++)
625       folders[i] =
626         store.getFolder(file.getAbsolutePath()+File.separator+files[i]);
627       return folders;
628     }
629     catch (SecurityException JavaDoc e)
630     {
631       throw new MessagingException JavaDoc("Access denied", e);
632     }
633   }
634
635   /**
636    * Returns the separator character.
637    */

638   public char getSeparator()
639     throws MessagingException JavaDoc
640   {
641     return File.separatorChar;
642   }
643
644   /**
645    * Creates this folder in the store.
646    */

647   public boolean create(int type)
648     throws MessagingException JavaDoc
649   {
650     if (file.exists())
651       throw new MessagingException JavaDoc("Folder already exists");
652     switch (type)
653     {
654       case HOLDS_FOLDERS:
655         try
656         {
657           file.mkdirs();
658           this.type = type;
659           notifyFolderListeners(FolderEvent.CREATED);
660           return true;
661         }
662         catch (SecurityException JavaDoc e)
663         {
664           throw new MessagingException JavaDoc("Access denied", e);
665         }
666       case HOLDS_MESSAGES:
667         try
668         {
669           synchronized (this)
670           {
671             createNewFile(file);
672           }
673           this.type = type;
674           notifyFolderListeners(FolderEvent.CREATED);
675           return true;
676         }
677         catch (IOException JavaDoc e)
678         {
679           throw new MessagingException JavaDoc("I/O error writing mailbox", e);
680         }
681         catch (SecurityException JavaDoc e)
682         {
683           throw new MessagingException JavaDoc("Access denied", e);
684         }
685     }
686     return false;
687   }
688
689   /**
690    * Deletes this folder.
691    */

692   public boolean delete(boolean recurse)
693     throws MessagingException JavaDoc
694   {
695     if (recurse)
696     {
697       try
698       {
699         if (type==HOLDS_FOLDERS)
700         {
701           Folder JavaDoc[] folders = list();
702           for (int i=0; i<folders.length; i++)
703             if (!folders[i].delete(recurse))
704               return false;
705         }
706         if (!readOnly)
707           releaseLock();
708         file.delete();
709         notifyFolderListeners(FolderEvent.DELETED);
710         return true;
711       }
712       catch (SecurityException JavaDoc e)
713       {
714         throw new MessagingException JavaDoc("Access denied", e);
715       }
716     }
717     else
718     {
719       try
720       {
721         if (type==HOLDS_FOLDERS)
722         {
723           Folder JavaDoc[] folders = list();
724           if (folders.length>0)
725             return false;
726         }
727         if (!readOnly)
728           releaseLock();
729         file.delete();
730         notifyFolderListeners(FolderEvent.DELETED);
731         return true;
732       }
733       catch (SecurityException JavaDoc e)
734       {
735         throw new MessagingException JavaDoc("Access denied", e);
736       }
737     }
738   }
739
740   /**
741    * Renames this folder.
742    */

743   public boolean renameTo(Folder JavaDoc folder)
744     throws MessagingException JavaDoc
745   {
746     try
747     {
748       String JavaDoc filename = folder.getFullName();
749       if (filename!=null)
750       {
751         file.renameTo(new File JavaDoc(filename));
752         notifyFolderListeners(FolderEvent.RENAMED);
753         return true;
754       }
755       else
756         throw new MessagingException JavaDoc("Illegal filename: null");
757     }
758     catch (SecurityException JavaDoc e)
759     {
760       throw new MessagingException JavaDoc("Access denied", e);
761     }
762   }
763
764   /**
765    * Returns the subfolder of this folder with the specified name.
766    */

767   public Folder JavaDoc getFolder(String JavaDoc filename)
768     throws MessagingException JavaDoc
769   {
770     String JavaDoc INBOX = "INBOX";
771     if (INBOX.equalsIgnoreCase(filename))
772     {
773       try
774       {
775         return store.getFolder(INBOX);
776       }
777       catch (MessagingException JavaDoc e)
778       {
779         // fall back to standard behaviour
780
}
781     }
782     return store.getFolder(file.getAbsolutePath()+File.separator+filename);
783   }
784
785   /**
786    * Checks if the current file is or is supposed to be
787    * compressed. Uses the filename to figure it out.
788    */

789   private boolean isGzip()
790   {
791     return file.getName().toLowerCase().endsWith(".gz");
792   }
793
794   /**
795    * Creates an input stream that possibly will decompress the
796    * file contents.
797    */

798   private InputStream JavaDoc getInputStream()
799     throws IOException JavaDoc
800   {
801     InputStream JavaDoc in;
802
803     in = new FileInputStream JavaDoc(file);
804     if (isGzip())
805       in = new GZIPInputStream JavaDoc(in);
806     return in;
807   }
808
809   /**
810    * Creates an output stream that possibly will compress
811    * whatever is sent to it, based on the current filename.
812    */

813   private OutputStream JavaDoc getOutputStream()
814     throws IOException JavaDoc
815   {
816     OutputStream JavaDoc out;
817
818     out = new FileOutputStream JavaDoc(file);
819     if (isGzip())
820       out = new GZIPOutputStream JavaDoc(out);
821     return out;
822   }
823     
824   /**
825    * Locks this mailbox.
826    * This uses a dotlock-like mechanism - see createNewFile().
827    * If the directory containing the mbox
828    * folder is not writable, we will not be able to open the mbox for
829    * writing either.
830    */

831   public synchronized boolean acquireLock()
832   {
833     try
834     {
835       String JavaDoc filename = file.getPath();
836       String JavaDoc lockFilename = filename+".lock";
837       File JavaDoc lock = new File JavaDoc(lockFilename);
838       MboxStore store = (MboxStore)this.store;
839       store.log("creating "+lock.getPath());
840       if (lock.exists())
841         return false;
842       //if (!lock.canWrite())
843
// return false;
844
createNewFile(lock);
845       return true;
846     }
847     catch (IOException JavaDoc e)
848     {
849       MboxStore store = (MboxStore)this.store;
850       store.log("I/O exception acquiring lock on "+file.getPath());
851     }
852     catch (SecurityException JavaDoc e)
853     {
854       MboxStore store = (MboxStore)this.store;
855       store.log("Security exception acquiring lock on "+file.getPath());
856     }
857     return false;
858   }
859
860   /**
861    * This method creates a new file.
862    * Because Java cannot properly dotlock a file by creating a temporary
863    * file and hardlinking it (some platforms do not support hard links) we
864    * must use this method to create a zero-length inode.
865    * This is a replacement for File.createNewFile(), which only exists in
866    * the JDK since 1.2.
867    * The idea is simply to touch the specified file.
868    */

869   private void createNewFile(File JavaDoc file)
870     throws IOException JavaDoc
871   {
872     // there may be another, more efficient way to do this.
873
// certainly just setLastModified() does not work.
874
BufferedOutputStream JavaDoc out = new BufferedOutputStream JavaDoc(new
875         FileOutputStream JavaDoc(file));
876     out.flush();
877     out.close();
878     
879   }
880     
881   /**
882    * Unlocks this mailbox.
883    * This deletes any associated lockfile if it exists. It returns false if
884    * an existing lockfile could not be deleted.
885    */

886   public synchronized boolean releaseLock()
887   {
888     try
889     {
890       String JavaDoc filename = file.getPath();
891       String JavaDoc lockFilename = filename+".lock";
892       File JavaDoc lock = new File JavaDoc(lockFilename);
893       MboxStore store = (MboxStore)this.store;
894       store.log("removing "+lock.getPath());
895       if (lock.exists())
896       {
897         if (!lock.delete())
898           return false;
899       }
900       return true;
901     }
902     catch (SecurityException JavaDoc e)
903     {
904       MboxStore store = (MboxStore)this.store;
905       store.log("Security exception releasing lock on "+file.getPath());
906     }
907     return false;
908   }
909
910   class MboxFilenameFilter
911     implements FilenameFilter JavaDoc
912   {
913
914     String JavaDoc pattern;
915     int asteriskIndex, percentIndex;
916        
917     MboxFilenameFilter(String JavaDoc pattern)
918     {
919       this.pattern = pattern;
920       asteriskIndex = pattern.indexOf('*');
921       percentIndex = pattern.indexOf('%');
922     }
923        
924     public boolean accept(File JavaDoc directory, String JavaDoc name)
925     {
926       if (asteriskIndex>-1)
927       {
928         String JavaDoc start = pattern.substring(0, asteriskIndex);
929         String JavaDoc end = pattern.substring(asteriskIndex+1, pattern.length());
930         return (name.startsWith(start) &&
931             name.endsWith(end));
932       }
933       else if (percentIndex>-1)
934       {
935         String JavaDoc start = pattern.substring(0, percentIndex);
936         String JavaDoc end = pattern.substring(percentIndex+1, pattern.length());
937         return (directory.equals(file) &&
938             name.startsWith(start) &&
939             name.endsWith(end));
940       }
941       return name.equals(pattern);
942     }
943   }
944     
945 }
946
Popular Tags