KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > james > imapserver > JamesHost


1 /***********************************************************************
2  * Copyright (c) 2000-2004 The Apache Software Foundation. *
3  * All rights reserved. *
4  * ------------------------------------------------------------------- *
5  * Licensed under the Apache License, Version 2.0 (the "License"); you *
6  * may not use this file except in compliance with the License. You *
7  * may obtain a copy of the License at: *
8  * *
9  * http://www.apache.org/licenses/LICENSE-2.0 *
10  * *
11  * Unless required by applicable law or agreed to in writing, software *
12  * distributed under the License is distributed on an "AS IS" BASIS, *
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
14  * implied. See the License for the specific language governing *
15  * permissions and limitations under the License. *
16  ***********************************************************************/

17
18 package org.apache.james.imapserver;
19
20 import org.apache.avalon.framework.activity.Initializable;
21 import org.apache.avalon.framework.component.Component;
22 import org.apache.avalon.framework.component.ComponentManager;
23 import org.apache.avalon.framework.component.Composable;
24 import org.apache.avalon.framework.configuration.Configurable;
25 import org.apache.avalon.framework.configuration.Configuration;
26 import org.apache.avalon.framework.configuration.ConfigurationException;
27 import org.apache.avalon.framework.context.Context;
28 import org.apache.avalon.framework.context.Contextualizable;
29 import org.apache.avalon.framework.logger.AbstractLogEnabled;
30 import org.apache.james.imapserver.AccessControlException;
31 import org.apache.james.imapserver.AuthorizationException;
32 import org.apache.james.services.MailServer;
33 import org.apache.james.services.UsersRepository;
34 import org.apache.james.services.UsersStore;
35 import org.apache.james.util.Assert;
36
37 import java.io.File JavaDoc;
38 import java.io.FileInputStream JavaDoc;
39 import java.io.ObjectInputStream JavaDoc;
40 import java.util.*;
41
42
43 /**
44  * A single host that has an IMAP4rev1 messaging server.
45  * There should be one instance of this class per instance of James.
46  * An IMAP messaging system may span more than one host.
47  * <p><code>String</code> parameters representing mailbox names must be the
48  * full hierarchical name of the target, with namespace, as used by the
49  * specified user. Examples:
50  * '#mail.Inbox' or '#shared.finance.Q2Earnings'.
51  * <p>An imap Host must keep track of existing and deleted mailboxes.
52  *
53  * References: rfc 2060
54  * @version 0.2 on 04 Aug 2002
55  * @see FolderRecord
56  * @see RecordRepository
57  */

58 public class JamesHost
59         extends AbstractLogEnabled
60         implements Host, Component, Composable,
61                    Configurable, Contextualizable, Initializable {
62
63     private Context context;
64     private Configuration conf;
65     private ComponentManager compMgr;
66     private String JavaDoc rootPath; // ends with File.separator
67
private IMAPSystem imapSystem;
68     private UsersRepository localUsers;
69     private RecordRepository recordRep;
70     private OpenMailboxes openMailboxes; //maps absoluteName to ACLMailbox
71

72     public static final String JavaDoc HIERARCHY_SEPARATOR = ".";
73     public static final char HIERARCHY_SEPARATOR_CHAR = '.';
74     public static final String JavaDoc NAMESPACE_TOKEN = "#";
75     public static final String JavaDoc PRIVATE_NAMESPACE_PREFIX = "";
76     private static final String JavaDoc USER_NAMESPACE = "user";
77     private static final String JavaDoc SHARE_NAMESPACE = "share";
78     public static final String JavaDoc USER_NAMESPACE_PREFIX = NAMESPACE_TOKEN + USER_NAMESPACE;
79     public static final String JavaDoc SHARE_NAMESPACE_PREFIX = NAMESPACE_TOKEN + SHARE_NAMESPACE;
80     
81     /*
82      * Note on implemented namespaces.
83      * 3 namespaces are (partially) implemented.
84      * 1) Private namespace ie access to a user's own mailboxes.
85      * Full mailbox names (ie what user sees) of the form:
86      * #mail.Inbox or #mail.apache.James
87      * Absolute names of the form:
88      * #mail.fred.flintstone.Inbox or #mail.fred.flintstone.apache.James
89      * 2) Other users namespace ie access to other users mailboxes
90      * subject to access control, of course
91      * Full mailbox names (ie what user sees) of the form:
92      * #users.captain.scarlet.Inbox or #users.RobinHood.apache.James
93      * Absolute names of the form:
94      * #mail.captain.scarlet.Inbox or #mail.RobinHood.apache.James
95      * 3) Shared mailboxes
96      * not fully implemented.
97      * Full mailbox names (ie what user sees) of the form:
98      * #shared.projectAlpha.masterplan or #shared.customerservice.Inbox
99      * Absolute names of the form:
100      * #shared.projectAlpha.masterplan or #shared.customerservice.Inbox
101      */

102
103     /*
104      * Note on filename extensions
105      * Records in AvalonRecordRepository - no extension
106      * Mailboxes - mbr
107      * MimeMessage - msg
108      * MessageAttributes - att
109      */

110
111     /* No constructor */
112
113     /**
114      * @see org.apache.avalon.framework.context.Contextualizable#contextualize(Context)
115      */

116     public void contextualize( Context context ) {
117         this.context = context;
118     }
119
120     /**
121      * @see org.apache.avalon.framework.component.Composable#compose(ComponentManager)
122      */

123     public void compose( ComponentManager comp ) {
124         compMgr = comp;
125     }
126
127     /**
128      * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
129      */

130     public void configure( Configuration conf ) throws ConfigurationException {
131         this.conf = conf;
132     }
133
134     /**
135      * @see org.apache.avalon.framework.activity.Initializable#initialize()
136      */

137     public void initialize() throws Exception JavaDoc {
138         getLogger().info( "JamesHost init..." );
139
140         imapSystem = (IMAPSystem) compMgr.lookup( IMAPSystem.ROLE );
141
142         UsersStore usersStore = (UsersStore) compMgr.lookup( "org.apache.james.services.UsersStore" );
143         localUsers = usersStore.getRepository( "LocalUsers" );
144
145         String JavaDoc recordRepDest
146                 = conf.getChild( "recordRepository" ).getValue();
147         recordRep = new DefaultRecordRepository();
148         setupLogger( recordRep, "recordRep" );
149         recordRep.setPath( recordRepDest );
150         getLogger().info( "AvalonRecordRepository opened at " + recordRepDest );
151         rootPath = conf.getChild( "mailboxRepository" ).getValue();
152         if ( !rootPath.endsWith( File.separator ) ) {
153             rootPath = rootPath + File.separator;
154         }
155         prepareDir( rootPath );
156
157         // Create directories for user and shared mailboxes.
158
String JavaDoc usersPath = getPath( USER_NAMESPACE_PREFIX );
159         prepareDir( usersPath );
160         String JavaDoc sharePath = getPath( SHARE_NAMESPACE_PREFIX );
161         prepareDir( sharePath );
162         getLogger().info( "IMAP Mailbox Repository opened at " + rootPath );
163         openMailboxes = new OpenMailboxes(); // how big should this start?
164
getLogger().info( "JamesHost ...init end" );
165     }
166
167     /**
168      * Checks that the Directory provided exists and is writeable, creating it if it is not.
169      */

170     private void prepareDir( String JavaDoc dir ) {
171         File JavaDoc newFolder = new File JavaDoc( dir );
172         if ( !newFolder.isDirectory() ) {
173             if ( !newFolder.mkdir() ) {
174                 throw new RuntimeException JavaDoc( "Error: Cannot create directory: " + dir );
175             }
176         } else if ( !newFolder.canWrite() ) {
177             throw new RuntimeException JavaDoc( "Error: Cannot write to directory: " + dir );
178         }
179     }
180
181     /**
182      * Establishes whether this host is the Home Server for the specified user.
183      * Used during login to decide whether a LOGIN_REFERRAL has to be sent to
184      * the client.
185      *
186      * @param username an email address
187      * @return true if inbox (and private mailfolders) are accessible through
188      * this host.
189      */

190     public boolean isHomeServer( String JavaDoc username ) {
191         return localUsers.contains( username );
192     }
193
194     /**
195      * Establishes if the specified user can access any mailboxes on this host.
196      * Used during login process to decide what sort of LOGIN-REFERRAL must be
197      * sent to client.
198      *
199      * @param username an email address
200      * @return true if the specified user has at least read access to any
201      * mailboxes on this host.
202      */

203     public boolean hasLocalAccess( String JavaDoc username ) {
204         return localUsers.contains( username );
205     }
206
207     /**
208      * Returns a reference to an existing Mailbox. The requested mailbox
209      * must already exists on this server and the requesting user must have at
210      * least lookup rights.
211      *
212      * @param user email address on whose behalf the request is made.
213      * @param mailboxName String name of the target.
214      * @return an Mailbox reference.
215      * @throws AccessControlException if the user does not have at least
216      * lookup rights.
217      * @throws MailboxException if mailbox does not exist locally.
218      */

219     public synchronized ACLMailbox getMailbox( String JavaDoc user, String JavaDoc mailboxName )
220             throws AccessControlException, MailboxException {
221         Assert.isTrue( Assert.ON &&
222                        user != null &&
223                        user.length() > 0 &&
224                        mailboxName != null );
225
226         getLogger().debug( "Getting mailbox " + mailboxName + " for " + user );
227         String JavaDoc absoluteName = getAbsoluteMailboxName( user, mailboxName );
228         return getAbsoluteMailbox( user, absoluteName );
229     }
230
231     private synchronized ACLMailbox getAbsoluteMailbox( String JavaDoc user, String JavaDoc absoluteName )
232             throws AccessControlException, MailboxException {
233         Assert.isTrue( Assert.ON &&
234                        user != null &&
235                        absoluteName.startsWith( NAMESPACE_TOKEN ) );
236
237         ACLMailbox mailbox = null;
238         FolderRecord record = null;
239
240         // Has a folder with this name ever been created?
241
System.out.println("THISISTHE ABSOLUTENAME IN getAbsoluteMailbox " + absoluteName);
242         if ( !recordRep.containsRecord( absoluteName ) ) {
243             throw new MailboxException( "Mailbox: " + absoluteName + " has never been created.", MailboxException.NOT_LOCAL );
244         } else {
245             record = recordRep.retrieve( absoluteName );
246             if ( record.isDeleted() ) {
247                 throw new MailboxException( "Mailbox has been deleted", MailboxException.LOCAL_BUT_DELETED );
248             } else if ( openMailboxes.contains( absoluteName ) ) {
249                 mailbox = openMailboxes.getMailbox( absoluteName );
250                 if ( ! mailbox.hasLookupRights( user ) ) {
251                     throw new AccessControlException( "No lookup rights." );
252                 }
253                 openMailboxes.addReference( absoluteName );
254                 return mailbox;
255             } else {
256                 String JavaDoc owner = record.getUser();
257                 String JavaDoc key = getPath( absoluteName );
258                 ObjectInputStream JavaDoc in = null;
259                 try {
260                     // SK:UPDATE
261
in = new ObjectInputStream JavaDoc( new FileInputStream JavaDoc( key + File.separator + FileMailbox.MAILBOX_FILE_NAME ) );
262                     mailbox = (FileMailbox) in.readObject();
263                     setupLogger( mailbox );
264                     mailbox.configure( conf );
265                     mailbox.contextualize( context );
266                     mailbox.compose( compMgr );
267                     mailbox.reinitialize();
268                 } catch ( Exception JavaDoc e ) {
269                     e.printStackTrace();
270                     throw new RuntimeException JavaDoc( "Exception caught while reading FileMailbox: " + e );
271                 } finally {
272                     if ( in != null ) {
273                         try {
274                             in.close();
275                         }
276                         catch ( Exception JavaDoc ignored ) {
277                         }
278                     }
279                     notifyAll();
280                 }
281                 if ( !mailbox.hasLookupRights( user ) ) {
282                     throw new AccessControlException( "No lookup rights." );
283                 }
284                 openMailboxes.addMailbox( absoluteName, mailbox );
285                 return mailbox;
286             }
287         }
288     }
289
290     /**
291      * Returns a reference to a newly created Mailbox. The request should
292      * specify a mailbox that does not already exist on this server, that
293      * could exist on this server and that the user has rights to create.
294      * If a system allocates different namespaces to different hosts then a
295      * request to create a mailbox in a namespace not served by this host would
296      * be an error.
297      * It is an error to create a mailbox with the name of a mailbox that has
298      * been deleted, if that name is still in use.
299      *
300      * @param user email address on whose behalf the request is made.
301      * @param mailboxName String name of the target
302      * @return an Mailbox reference.
303      * @throws AccessControlException if the user does not have lookup rights
304      * for parent or any needed ancestor folder
305      * lookup rights.
306      * @throws AuthorizationException if mailbox could be created locally but
307      * user does not have create rights.
308      * @throws MailboxException if mailbox already exists, locally or remotely,
309      * or if mailbox cannot be created locally.
310      * @see FolderRecord
311      */

312     public synchronized ACLMailbox createMailbox( String JavaDoc user, String JavaDoc mailboxName )
313             throws AccessControlException, AuthorizationException, MailboxException {
314         Assert.isTrue( Assert.ON &&
315                        user != null &&
316                        user.length() > 0 &&
317                        mailboxName != null );
318
319         String JavaDoc absoluteName = getAbsoluteMailboxName( user, mailboxName );
320         Assert.isTrue( Assert.ON &&
321                        absoluteName != null );
322
323         getLogger().debug( "JamesHost createMailbox() for: " + absoluteName );
324
325         return createAbsoluteMailbox( user, absoluteName );
326     }
327
328     private synchronized ACLMailbox createAbsoluteMailbox( String JavaDoc user, String JavaDoc absoluteName )
329             throws AccessControlException, AuthorizationException, MailboxException {
330
331         Assert.isTrue( Assert.ON &&
332                        absoluteName.startsWith( NAMESPACE_TOKEN ) &&
333                        absoluteName.indexOf( HIERARCHY_SEPARATOR ) != -1 );
334
335         ACLMailbox mailbox = null;
336         FolderRecord record = null;
337         ACLMailbox parentMailbox = null;
338
339         // Has a folder with this name ever been created?
340
if ( recordRep.containsRecord( absoluteName ) ) {
341                 getLogger().error( "Attempt to create an existing Mailbox." );
342                 throw new MailboxException( "Mailbox already exists", MailboxException.ALREADY_EXISTS_LOCALLY );
343         } else {
344             // Get the directory holding the new mailbox.
345
String JavaDoc parent = absoluteName.substring( 0, absoluteName.lastIndexOf( HIERARCHY_SEPARATOR ) );
346             //Recurse to a created and not deleted mailbox
347
try {
348                 parentMailbox = getAbsoluteMailbox( user, parent );
349             } catch ( MailboxException mbe ) {
350                 if ( mbe.getStatus().equals( MailboxException.NOT_LOCAL )
351                         || mbe.getStatus().equals( MailboxException.LOCAL_BUT_DELETED ) ) {
352                     parentMailbox = createAbsoluteMailbox( user, parent );
353                 } else {
354                     throw new MailboxException( mbe.getMessage(), mbe.getStatus() );
355                 }
356             }
357             // Does user have create rights in parent mailbox?
358
boolean hasCreateRights = parentMailbox.hasCreateRights( user );
359             releaseMailbox( user, parentMailbox );
360             if ( ! hasCreateRights ) {
361                 releaseMailbox( user, parentMailbox );
362                 throw new AuthorizationException( "User does not have create rights." );
363             }
364             try {
365                 //TODO: BUG! Here MUST be used a Factory for using FILE / JDBC !!!
366
mailbox = new FileMailbox();
367                 setupLogger( mailbox );
368                 mailbox.configure( conf );
369                 mailbox.contextualize( context );
370                 mailbox.compose( compMgr );
371                 mailbox.prepareMailbox( user, absoluteName, user, recordRep.nextUIDValidity() );
372                 mailbox.initialize();
373             } catch ( Exception JavaDoc e ) {
374                 getLogger().error( "Exception creating mailbox: " + e );
375                 throw new MailboxException( "Exception creating mailbox: " + e );
376             }
377             SimpleFolderRecord fr
378                     = new SimpleFolderRecord( user, absoluteName );
379             fr.initialize();
380             recordRep.store( fr );
381             openMailboxes.addMailbox( absoluteName, mailbox );
382         }
383
384         return mailbox;
385     }
386
387     /**
388      * Releases a reference to a mailbox, allowing Host to do any housekeeping.
389      *
390      * @param mailbox a non-null reference to an ACL Mailbox.
391      */

392     public void releaseMailbox( String JavaDoc user, ACLMailbox mailbox )
393     {
394         if ( mailbox == null ) {
395             getLogger().debug( "Attempt to release mailbox with null reference" );
396             return;
397         }
398         if ( user != MailServer.MDA ) {
399             mailbox.unsetRecent();
400         }
401         String JavaDoc absoluteName = mailbox.getAbsoluteName();
402         int count = openMailboxes.removeReference( absoluteName );
403         if ( count == 0 ) {
404             openMailboxes.removeMailbox( absoluteName );
405             try {
406                 FolderRecord fr = recordRep.retrieve( absoluteName );
407                 fr.setUidValidity( mailbox.getUIDValidity() );
408                 fr.setHighestUid( mailbox.getNextUID() - 1 );
409                 fr.setLookupRights( mailbox.getUsersWithLookupRights() );
410                 fr.setReadRights( mailbox.getUsersWithReadRights() );
411                 fr.setMarked( mailbox.isMarked() );
412                 fr.setNotSelectableByAnyone( mailbox.isNotSelectableByAnyone() );
413                 fr.setExists( mailbox.getExists() );
414                 fr.setRecent( mailbox.getRecent() );
415                 fr.setUnseenbyUser( mailbox.getUnseenByUser() );
416                 recordRep.store( fr );
417                 mailbox.dispose();
418                 mailbox = null;
419                 getLogger().info( "Mailbox object destroyed: " + absoluteName );
420             } catch ( Exception JavaDoc e ) {
421                 getLogger().error( "Exception destroying mailbox object: " + e );
422                 e.printStackTrace();
423             }
424         } else {
425             getLogger().info( "Mailbox " + absoluteName + " now has " + count + "live references" );
426         }
427     }
428
429     /**
430      * Deletes an existing MailBox. Specified mailbox must already exist on
431      * this server, and the user must have rights to delete it. (Mailbox delete
432      * rights are implementation defined, one way is if the user would have the
433      * right to create it).
434      * Implementations must track deleted mailboxes
435      *
436      * @param user email address on whose behalf the request is made.
437      * @param mailboxName String name of the target
438      * @return true if mailbox deleted successfully
439      * @throws MailboxException if mailbox does not exist locally or is any
440      * identities INBOX.
441      * @throws AuthorizationException if mailbox exists locally but user does
442      * not have rights to delete it.
443      * @see FolderRecord
444      */

445     public boolean deleteMailbox( String JavaDoc user, String JavaDoc mailboxName )
446             throws MailboxException, AuthorizationException, AccessControlException {
447         Assert.isTrue( Assert.ON &&
448                        user != null &&
449                        mailboxName != null &&
450                        user.length() > 0 &&
451                        mailboxName.length() > 0 );
452
453         String JavaDoc absoluteName = getAbsoluteMailboxName( user, mailboxName );
454         getLogger().debug( "JamesHost deleteMailbox() called for: " + absoluteName );
455         return deleteAbsoluteMailbox( user, absoluteName );
456     }
457
458     private boolean deleteAbsoluteMailbox( String JavaDoc user, String JavaDoc absoluteName )
459             throws MailboxException, AuthorizationException, AccessControlException {
460         if ( ! recordRep.containsRecord( absoluteName ) ) {
461             throw new MailboxException( "Mailbox doesn't exist" );
462         }
463
464         int count = openMailboxes.getReferenceCount( absoluteName );
465         if ( count > 0 ) {
466             throw new MailboxException( "Mailbox is currently selected by another user" );
467         }
468
469         ACLMailbox mailbox = getAbsoluteMailbox( user, absoluteName );
470         if ( ! mailbox.hasDeleteRights( user ) ) {
471             throw new AuthorizationException( "No delete rights" );
472         }
473
474         // Get child folders of this mailbox
475
Collection childList = listMailboxes( MailServer.MDA, absoluteName, "%", false );
476         if ( ! childList.isEmpty() ) {
477             if ( mailbox.isNotSelectableByAnyone() ) {
478                 throw new MailboxException( "Mailbox with \\Noselect AND subfolders cannot be deleted" );
479             } else {
480                 // Delete and expunge all messages, and set NotSelectableByAnyone.
481
deleteAllMessages( mailbox, user );
482                 mailbox.setNotSelectableByAnyone( true );
483                 releaseMailbox( user, mailbox );
484             }
485         } else {
486             deleteAllMessages( mailbox, user );
487             Assert.isTrue( Assert.ON &&
488                            mailbox.getExists() == 0 );
489
490             openMailboxes.removeMailbox( absoluteName );
491             recordRep.deleteRecord( recordRep.retrieve( absoluteName ) );
492             mailbox.removeMailbox();
493         }
494         return true;
495     }
496
497     private void deleteAllMessages( ACLMailbox mailbox, String JavaDoc user )
498             throws AccessControlException, AuthorizationException {
499         // Delete all messages in this box
500
int messageCount = mailbox.getExists();
501         for ( int i = 0; i < messageCount; i++ ) {
502             mailbox.markDeleted( i + 1, user );
503         }
504         mailbox.expunge( user );
505     }
506
507     /**
508      * Renames an existing MailBox. The specified mailbox must already
509      * exist locally, the requested name must not exist locally already but
510      * must be able to be created locally and the user must have rights to
511      * delete the existing mailbox and create a mailbox with the new name.
512      * Any inferior hierarchical names must also be renamed.
513      * If INBOX is renamed, the contents of INBOX are transferred to a new
514      * folder with the new name, but INBOX is not deleted. If INBOX has
515      * inferior mailboxes these are not renamed.
516      * It is an error to create a mailbox with the name of a mailbox that has
517      * been deleted, if that name is still in use.
518      * Implementations must track deleted mailboxes
519      *
520      * @param user email address on whose behalf the request is made.
521      * @param oldMailboxName String name of the existing mailbox
522      * @param newMailboxName String target new name
523      * @return true if rename completed successfully
524      * @throws MailboxException if mailbox does not exist locally, or there
525      * is an existing mailbox with the new name.
526      * @throws AuthorizationException if user does not have rights to delete
527      * the existing mailbox or create the new mailbox.
528      * @see FolderRecord
529      */

530     public boolean renameMailbox( String JavaDoc user, String JavaDoc oldMailboxName, String JavaDoc newMailboxName )
531             throws MailboxException, AuthorizationException {
532         // At first we MUST ensure, that the User has the rights for renaming not only the Directory
533
// that he wanted to rename, but all subdiretories too.
534
// Also we have to "rename" the subdirectories as well.
535
try {
536             ACLMailbox mailbox = this.getMailbox(user,oldMailboxName);
537             String JavaDoc oldAbsoluteName = getAbsoluteMailboxName(user, oldMailboxName);
538             
539             //trying to get children Mailboxes
540
Collection coll = this.listMailboxes(user,"",oldMailboxName+"*",false);
541             java.util.TreeMap JavaDoc tr = new java.util.TreeMap JavaDoc();
542             Iterator it = coll.iterator();
543             
544             int mindepth=9999;
545             int maxdepth=0;
546             while(it.hasNext()) {
547                 // BUG: Whats about Mailbox Names with an Whitespace ?
548
StringTokenizer strl = new StringTokenizer((String JavaDoc) it.next());
549                 String JavaDoc mailboxname = "";
550                 boolean mbxfound=false;
551                 while(strl.hasMoreTokens()) {
552                     String JavaDoc token = strl.nextToken();
553                     if(token.equals("\""+this.HIERARCHY_SEPARATOR+"\"") || mbxfound) {
554                         // This must be the FileSeparator Token. After that comes the name of the Mailbox
555
if(mbxfound){
556                             mailboxname += " "+token;
557                         } else {
558                             mailboxname += strl.nextToken();
559                         }
560                         mbxfound=true;
561                     }
562                 }
563                 // StringTokenizer is only used to get the depth of the Mailboxname
564
strl = new StringTokenizer(mailboxname, this.HIERARCHY_SEPARATOR);
565                 mailboxname = mailboxname.substring(1,mailboxname.length()-1);
566                 System.out.println("RENAME: MAILBOXNAME FOUND: "+mailboxname);
567                 // Create Collection (or first try to get one from the Sorted Tree) and then
568
// save this to the TreeMap. The TreeMap is used to order the found Mailbox Names after their
569
// depth. It's needed to first change the Mailbox Properties for all Subdirectories, and update the
570
// FolderRecords.
571
Object JavaDoc oldcoll = tr.get(new Integer JavaDoc(strl.countTokens()));
572                 if (oldcoll==null) {
573                     HashSet hs = new HashSet();
574                     hs.add(mailboxname);
575                     tr.put(new Integer JavaDoc(strl.countTokens()), hs);
576                 } else {
577                     HashSet hs = (HashSet) oldcoll;
578                     hs.add(mailboxname);
579                     tr.put(new Integer JavaDoc(strl.countTokens()), hs);
580                 }
581                 if(maxdepth<strl.countTokens()) {
582                     maxdepth=strl.countTokens();
583                 }
584                 if(mindepth>strl.countTokens()) {
585                     mindepth=strl.countTokens();
586                 }
587             }
588             System.out.println("RENAME: POSSIBLE MAXDEPTH FOUND: "+maxdepth+" THE MINDEPTH IS "+mindepth);
589             for(int i=maxdepth;i>=0;i--) {
590                 Collection cole = (Collection) tr.get(new Integer JavaDoc(i));
591                 if (cole!=null) {
592                     Iterator ite = cole.iterator();
593                     while(ite.hasNext()) {
594                         String JavaDoc mbxhere = (String JavaDoc) ite.next();
595                         String JavaDoc absoluteName = getAbsoluteMailboxName(user, mbxhere);
596                         System.out.println("RENAME: MAILBOXES FOR INTEGER "+i+ " NAME "+mbxhere+" ABSOLUTE "+absoluteName);
597                         ACLMailbox mmm = this.getAbsoluteMailbox(user,absoluteName);
598                         if (i!=mindepth) {
599                             String JavaDoc suboldabsolutename = mmm.getAbsoluteName();
600                             mmm.renameSubMailbox(user, oldAbsoluteName, newMailboxName);
601                            // THis is the new AbsoluteName with # and so on
602
String JavaDoc subnewabsolutename = mmm.getAbsoluteName();
603                             // Delete the old FolderRecord
604
FolderRecord fr = recordRep.retrieve(suboldabsolutename);
605                             recordRep.deleteRecord(fr);
606                             // Create a new FolderRecord and store this in the recordRepository
607
// Can anybody explain me the use of this repository ???
608
// I think OpenMailbox and Repository is relatively redundant
609
fr = new SimpleFolderRecord(user, subnewabsolutename);
610                             fr.setUidValidity( mmm.getUIDValidity() );
611                             fr.setLookupRights( mmm.getUsersWithLookupRights() );
612                             fr.setReadRights( mmm.getUsersWithReadRights() );
613                             fr.setMarked( mmm.isMarked() );
614                             fr.setNotSelectableByAnyone( mmm.isNotSelectableByAnyone() );
615                             fr.setExists( mmm.getExists() );
616                             fr.setRecent( mmm.getRecent() );
617                             fr.setUnseenbyUser( mmm.getUnseenByUser() );
618                             recordRep.store(fr);
619                             // Remove old entry from openMailboxes and create a new one
620
this.openMailboxes.removeMailbox(suboldabsolutename);
621                             this.openMailboxes.addMailbox(subnewabsolutename,mmm);
622                         } else {
623                             // RENAME MAILBOX MAIN
624
System.out.println("NEWMAILBOXNAME WILL BE "+newMailboxName);
625                             if (mmm.renameMailbox(user, newMailboxName)) {
626                                 // THis is the new AbsoluteName with # and so on
627
String JavaDoc absolutenewName = getAbsoluteMailboxName(user, newMailboxName);
628                                 // Delete the old FolderRecord
629
FolderRecord fr = recordRep.retrieve(oldAbsoluteName);
630                                 recordRep.deleteRecord(fr);
631                                 // Create a new FolderRecord and store this in the recordRepository
632
// Can anybody explain me the use of this repository ???
633
// I think OpenMailbox and Repository is relatively redundant
634
fr = new SimpleFolderRecord(user, absolutenewName);
635                                 fr.setUidValidity( mmm.getUIDValidity() );
636                                 fr.setLookupRights( mmm.getUsersWithLookupRights() );
637                                 fr.setReadRights( mmm.getUsersWithReadRights() );
638                                 fr.setMarked( mmm.isMarked() );
639                                 fr.setNotSelectableByAnyone( mmm.isNotSelectableByAnyone() );
640                                 fr.setExists( mmm.getExists() );
641                                 fr.setRecent( mmm.getRecent() );
642                                 fr.setUnseenbyUser( mmm.getUnseenByUser() );
643                                 recordRep.store(fr);
644                                 // Remove old entry from openMailboxes and create a new one
645
this.openMailboxes.removeMailbox(oldAbsoluteName);
646                                 mailbox = getAbsoluteMailbox( user, absolutenewName );
647                                 this.openMailboxes.addMailbox(absolutenewName,mailbox);
648                                 return true;
649                             } else {
650                                 return false;
651                             }
652                         }
653                     }
654                 }
655             }
656             return false;
657         } catch (Exception JavaDoc e) {
658             e.printStackTrace();
659             throw new AuthorizationException("You have insufficient permission to change the Mailbox Name");
660         }
661     }
662
663     /**
664      * Returns the namespace which should be used for this user unless they
665      * expicitly request another.
666      *
667      * @param username String an email address
668      * @return a String of a namespace
669      */

670     public String JavaDoc getDefaultNamespace( String JavaDoc username ) {
671         return PRIVATE_NAMESPACE_PREFIX;
672     }
673
674     /**
675      * Return UIDValidity for named mailbox. Implementations should track
676      * existing and deleted folders.
677      *
678      * @param mailbox String name of the existing mailbox
679      * @return an integer containing the current UID Validity value.
680      */

681     // public int getUIDValidity(String mailbox);
682

683     /**
684      * Returns an iterator over an unmodifiable collection of Strings
685      * representing mailboxes on this host and their attributes. The specified
686      * user must have at least lookup rights for each mailbox returned.
687      * If the subscribedOnly flag is set, only mailboxes to which the
688      * specified user is currently subscribed should be returned.
689      * Implementations that may export circular hierarchies SHOULD restrict the
690      * levels of hierarchy returned. The depth suggested by rfc 2683 is 20
691      * hierarchy levels.
692      * <p>The reference name must be non-empty. If the mailbox name is empty,
693      * implementations must not throw either exception but must return a single
694      * String (described below) if the reference name specifies a local mailbox
695      * accessible to the user and a one-character String containing the
696      * hierarchy delimiter of the referenced namespace, otherwise.
697      * <p>Each String returned should be a space seperated triple of name
698      * attributes, hierarchy delimiter and full mailbox name. The mailbox
699      * name should include the namespace and be relative to the specified user.
700      * <p> RFC comments: Implementations SHOULD return quickly. They SHOULD
701      * NOT go to excess trouble to calculate\Marked or \Unmarked status.
702      * <p>JAMES comment: By elimination, implementations should usually include
703      * \Noinferiors or \Noselect, if appropriate. Also, if the reference name
704      * and mailbox name resolve to a single local mailbox, implementations
705      * should establish all attributes.
706      * <p> Note that servers cannot unilaterally remove mailboxes from the
707      * subscribed list. A request with the subscribedOnly flag set that
708      * attempts to list a deleted mailbox must return that mailbox with the
709      * \Noselect attribute.
710      *
711      * @param username String non-empty email address of requester
712      * @param referenceName String non-empty name, including namespace, of a
713      * mailbox or level of mailbox hierarchy, relative to user.
714      * @param mailboxName String name of a mailbox possible including a
715      * wildcard.
716      * @param subscribedOnly only return mailboxes currently subscribed.
717      * @return Collection of strings representing a set of mailboxes.
718      * @throws AccessControlException if the user does not have at least
719      * lookup rights to at least one mailbox in the set requested.
720      * @throws MailboxException if the referenceName is not local or if
721      * referenceName and mailbox name resolve to a single mailbox which does
722      * not exist locally.
723      */

724     public synchronized Collection listMailboxes( String JavaDoc username,
725                                                   String JavaDoc referenceName,
726                                                   String JavaDoc mailboxName,
727                                                   boolean subscribedOnly )
728             throws MailboxException, AccessControlException {
729         getLogger().debug( "Listing for user: " + username + " ref " + referenceName + " mailbox " + mailboxName );
730         System.out.println( "Listing for user: '" + username + "' ref '" + referenceName + "' mailbox '" + mailboxName + "'");
731         List responseList = new ArrayList();
732
733         // For mailboxName == ""; return <"."> <namespace-of-reference>
734
if ( mailboxName.equals( "" ) ) {
735             String JavaDoc referenceNamespace = getNamespacePrefix( referenceName );
736             if ( referenceNamespace == null ) {
737                 getLogger().error( "Weird arguments for LIST? referenceName was: " + referenceName + " and mailbox names was " + mailboxName );
738                 return null;
739             }
740             if ( referenceNamespace.length() == 0 ) {
741                 referenceNamespace = "\"\"";
742             }
743
744             String JavaDoc response = "(\\Noselect) \"" + HIERARCHY_SEPARATOR
745                     + "\" " + referenceNamespace;
746             responseList.add( response );
747             return responseList;
748         }
749         try {
750             getLogger().debug( "Refined mailboxName to: " + mailboxName );
751             String JavaDoc userTarget;
752             if ( mailboxName.startsWith( NAMESPACE_TOKEN ) ) {
753                 userTarget = mailboxName;
754             } else {
755                 if ( referenceName.length() == 0 ||
756                         referenceName.endsWith( HIERARCHY_SEPARATOR ) ) {
757                     userTarget = referenceName + mailboxName;
758                 } else {
759                     userTarget = referenceName + HIERARCHY_SEPARATOR + mailboxName;
760                 }
761             }
762             String JavaDoc target = getAbsoluteMailboxName( username, userTarget );
763             getLogger().info( "Target is: " + target );
764             if ( target == null ) {
765                 return new HashSet();
766             }
767             int firstPercent = target.indexOf( "%" );
768             int firstStar = target.indexOf( "*" );
769             getLogger().info( "First percent at index: " + firstPercent );
770             getLogger().info( "First star at index: " + firstStar );
771             System.out.println( "First percent at index: " + firstPercent );
772             System.out.println( "First star at index: " + firstStar );
773
774             // For now, only handle wildcards as last character of target.
775
String JavaDoc targetMatch = target;
776             boolean starWildcard = false;
777             if ( firstStar > -1 ) {
778                 if ( firstStar != (target.length() - 1) ) {
779                     getLogger().debug( "Non-terminal * in LIST search." );
780                     return null;
781                 }
782                 starWildcard = true;
783                 targetMatch = target.substring( 0, target.length() - 1 );
784             }
785             boolean percentWildcard = false;
786             if ( firstPercent > -1 ) {
787                 if ( firstPercent != (target.length() - 1) ) {
788                     getLogger().debug( "Non-terminal % in LIST search." );
789                     return null;
790                 }
791                 percentWildcard = true;
792                 targetMatch = target.substring( 0, target.length() - 1 );
793             }
794
795             Iterator all = recordRep.getAbsoluteNames();
796             Set matches = new HashSet();
797
798             while ( all.hasNext() ) {
799                 boolean match = false;
800                 String JavaDoc testMailboxName = (String JavaDoc) all.next();
801                 getLogger().info( "Test is: " + testMailboxName );
802
803                 if ( starWildcard ) {
804                     match = testMailboxName.startsWith( targetMatch );
805                 } else if ( percentWildcard ) {
806                     match = (testMailboxName.startsWith( targetMatch )
807                             && testMailboxName.lastIndexOf( HIERARCHY_SEPARATOR ) < targetMatch.length());
808                 } else {
809                     // no wildcards so exact or nothing
810
match = testMailboxName.equals( target );
811                     getLogger().debug( "match/ no match at testMailboxName 1" );
812                 }
813
814                 if ( match && subscribedOnly ) {
815                     ACLMailbox mailbox = getAbsoluteMailbox( username, testMailboxName );
816                     if (! mailbox.isSubscribed( username ) ) {
817                         match = false;
818                     }
819                     releaseMailbox( username, mailbox );
820                 }
821
822                 if ( match ) {
823                     getLogger().info( "Processing match for : " + testMailboxName );
824                     FolderRecord record = recordRep.retrieve( testMailboxName );
825                     ACLMailbox mailbox = null;
826                     StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
827                     buf.append( "(" );
828                     if ( !record.isDeleted() && openMailboxes.contains( target ) ) {
829                         mailbox = openMailboxes.getMailbox( target );
830                     }
831                     if ( record.isDeleted() ) {
832                         buf.append( "\\Noselect" );
833                     } else if ( openMailboxes.contains( target ) ) {
834                         mailbox = openMailboxes.getMailbox( target );
835                         if ( !mailbox.isSelectable( username ) ) {
836                             buf.append( "\\Noselect" );
837                         }
838                         if ( mailbox.isMarked() ) {
839                             buf.append( "\\Marked" );
840                         } else {
841                             buf.append( "\\Unmarked" );
842                         }
843                     } else {
844                         if ( !record.isSelectable( username ) ) {
845                             buf.append( "\\Noselect" );
846                         }
847                         if ( record.isMarked() ) {
848                             buf.append( "\\Marked" );
849                         } else {
850                             buf.append( "\\Unmarked" );
851                         }
852                     }
853                     buf.append( ") \"" );
854                     buf.append( HIERARCHY_SEPARATOR );
855                     buf.append( "\" \"" );
856                     buf.append( getUserAwareMailboxName( username, testMailboxName ) );
857                     buf.append( "\"" );
858                     matches.add( buf.toString() );
859                 }
860             }
861             return matches;
862         }
863         catch ( Exception JavaDoc e ) {
864             getLogger().error( "Exception with list request for mailbox " + mailboxName );
865             e.printStackTrace();
866             return null;
867         }
868     }
869
870     private String JavaDoc getNamespacePrefix( String JavaDoc mailbox )
871     {
872         if ( mailbox.startsWith( USER_NAMESPACE_PREFIX ) ) {
873             return USER_NAMESPACE_PREFIX;
874         } else if ( mailbox.startsWith( SHARE_NAMESPACE_PREFIX ) ) {
875             return SHARE_NAMESPACE_PREFIX;
876         } else {
877             return PRIVATE_NAMESPACE_PREFIX;
878         }
879     }
880
881     /**
882      * Subscribes a userName to a mailbox. The mailbox must exist locally and the
883      * userName must have at least lookup rights to it.
884      *
885      * @param username String representation of an email address
886      * @param mailbox String representation of a mailbox name.
887      * @return true if subscribe completes successfully
888      * @throws AccessControlException if the mailbox exists but the userName does
889      * not have lookup rights.
890      * @throws MailboxException if the mailbox does not exist locally.
891      */

892     public boolean subscribe( String JavaDoc userName, String JavaDoc mailboxName )
893             throws MailboxException, AccessControlException
894     {
895         Assert.isTrue( Assert.ON &&
896                        userName != null &&
897                        mailboxName != null &&
898                        userName.length() > 0 &&
899                        mailboxName.length() > 0 );
900
901         String JavaDoc absoluteName = getAbsoluteMailboxName( userName, mailboxName );
902         ACLMailbox mailbox = getAbsoluteMailbox( userName, absoluteName );
903
904         mailbox.subscribe( userName );
905         releaseMailbox( userName, mailbox );
906
907         return true;
908     }
909
910     /**
911      * Unsubscribes from a given mailbox.
912      *
913      * @param username String representation of an email address
914      * @param mailbox String representation of a mailbox name.
915      * @return true if unsubscribe completes successfully
916      */

917     public boolean unsubscribe( String JavaDoc userName, String JavaDoc mailboxName )
918             throws MailboxException, AccessControlException
919     {
920         Assert.isTrue( Assert.ON &&
921                        userName != null &&
922                        mailboxName != null &&
923                        userName.length() > 0 &&
924                        mailboxName.length() > 0 );
925
926         String JavaDoc absoluteName = getAbsoluteMailboxName( userName, mailboxName );
927         ACLMailbox mailbox = getAbsoluteMailbox( userName, absoluteName );
928
929         mailbox.unsubscribe( userName );
930         releaseMailbox( userName, mailbox );
931
932         return true;
933     }
934
935     /**
936      * Returns a string giving the status of a mailbox on requested criteria.
937      * Currently defined staus items are:
938      * MESSAGES - Nummber of messages in mailbox
939      * RECENT - Number of messages with \Recent flag set
940      * UIDNEXT - The UID that will be assigned to the next message entering
941      * the mailbox
942      * UIDVALIDITY - The current UIDValidity value for the mailbox
943      * UNSEEN - The number of messages which do not have the \Seen flag set.
944      *
945      * @param username String non-empty email address of requester
946      * @param mailboxName String name of a mailbox (no wildcards allowed).
947      * @param dataItems Vector of one or more Strings each of a single
948      * status item.
949      * @return String consisting of space seperated pairs:
950      * dataItem-space-number.
951      * @throws AccessControlException if the user does not have at least
952      * lookup rights to the mailbox requested.
953      * @throws MailboxException if the mailboxName does not exist locally.
954      */

955     public String JavaDoc getMailboxStatus( String JavaDoc username, String JavaDoc mailboxName,
956                                     List dataItems )
957             throws MailboxException, AccessControlException
958     {
959         String JavaDoc absoluteName = getAbsoluteMailboxName( username, mailboxName );
960         ACLMailbox mailbox = null;
961         FolderRecord record = null;
962         Iterator it = dataItems.iterator();
963         String JavaDoc response = null;
964
965         // Has a folder with this name ever been created?
966
if ( !recordRep.containsRecord( absoluteName ) ) {
967             throw new MailboxException( "Mailbox: " + absoluteName + " has never been created.", MailboxException.NOT_LOCAL );
968         } else {
969             record = recordRep.retrieve( absoluteName );
970             if ( record.isDeleted() ) {
971                 throw new MailboxException( "Mailbox has been deleted", MailboxException.LOCAL_BUT_DELETED );
972             } else if ( openMailboxes.contains( absoluteName ) ) {
973                 response = new String JavaDoc();
974                 mailbox = openMailboxes.getMailbox( absoluteName );
975                 if ( !mailbox.hasLookupRights( username ) ) {
976                     throw new AccessControlException( "No lookup rights." );
977                 }
978                 while ( it.hasNext() ) {
979                     String JavaDoc dataItem = (String JavaDoc) it.next();
980                     if ( dataItem.equalsIgnoreCase( "MESSAGES" ) ) {
981                         response += "MESSAGES " + mailbox.getExists();
982                     } else if ( dataItem.equalsIgnoreCase( "RECENT" ) ) {
983                         response += "RECENT " + mailbox.getRecent();
984                     } else if ( dataItem.equalsIgnoreCase( "UIDNEXT" ) ) {
985                         response += "UIDNEXT " + mailbox.getNextUID();
986                     } else if ( dataItem.equalsIgnoreCase( "UIDVALIDITY" ) ) {
987                         response += "UIDVALIDITY " + mailbox.getUIDValidity();
988                     } else if ( dataItem.equalsIgnoreCase( "UNSEEN" ) ) {
989                         response += "UNSEEN " + mailbox.getUnseen( username );
990                     }
991                     if ( it.hasNext() ) {
992                         response += " ";
993                     }
994                 }
995                 return response;
996             }
997             else {
998                 if ( !record.hasLookupRights( username ) ) {
999                     throw new AccessControlException( "No lookup rights." );
1000                }
1001                response = new String JavaDoc();
1002                while ( it.hasNext() ) {
1003                    String JavaDoc dataItem = (String JavaDoc) it.next();
1004                    if ( dataItem.equalsIgnoreCase( "MESSAGES" ) ) {
1005                        response += "MESSAGES" + " " + record.getExists();
1006                    } else if ( dataItem.equalsIgnoreCase( "RECENT" ) ) {
1007                        response += "RECENT" + " " + record.getRecent();
1008                    } else if ( dataItem.equalsIgnoreCase( "UIDNEXT" ) ) {
1009                        response += "UIDNEXT" + " " + (record.getHighestUid() + 1);
1010                    } else if ( dataItem.equalsIgnoreCase( "UIDVALIDITY" ) ) {
1011                        response += "UIDVALIDITY" + " " + record.getUidValidity();
1012                    } else if ( dataItem.equalsIgnoreCase( "UNSEEN" ) ) {
1013                        response += "UNSEEN" + " " + record.getUnseen( username );
1014                    }
1015                    if ( it.hasNext() ) {
1016                        response += " ";
1017                    }
1018                }
1019                return response;
1020            }
1021        }
1022    }
1023
1024    /**
1025     * Convert a user-based full mailbox name into a server absolute name.
1026     * If the fullMailboxName begins with the namespace token,
1027     * return as-is.
1028     * If not, need to resolve the Mailbox name for this user.
1029     * Example:
1030     * <br> Convert "INBOX" for user "Fred.Flinstone" into
1031     * absolute name: "#user.Fred.Flintstone.INBOX"
1032     *
1033     * @return String of absoluteName, null if not valid selection
1034     */

1035    private String JavaDoc getAbsoluteMailboxName( String JavaDoc user, String JavaDoc fullMailboxName )
1036    {
1037        // First decode the mailbox name as an Atom / String.
1038

1039        if ( fullMailboxName.startsWith( NAMESPACE_TOKEN ) ) {
1040            return fullMailboxName;
1041        }
1042        else {
1043            if ( fullMailboxName.length() == 0 ) {
1044                return USER_NAMESPACE_PREFIX + HIERARCHY_SEPARATOR + user;
1045            }
1046            else {
1047                return USER_NAMESPACE_PREFIX + HIERARCHY_SEPARATOR + user + HIERARCHY_SEPARATOR + fullMailboxName;
1048            }
1049        }
1050    }
1051
1052    /**
1053     * Convert a server absolute name into a user-aware mailbox name.
1054     * If the absolute name starts with #user.<username>.
1055     * remove this section.
1056     * Otherwise, return as-is.
1057     *
1058     * @return user-aware mailbox name
1059     */

1060    private String JavaDoc getUserAwareMailboxName( String JavaDoc user, String JavaDoc absoluteName )
1061    {
1062        String JavaDoc userPrefix = USER_NAMESPACE_PREFIX + HIERARCHY_SEPARATOR + user + HIERARCHY_SEPARATOR;
1063        String JavaDoc response;
1064        if ( absoluteName.startsWith( userPrefix ) ) {
1065            response = absoluteName.substring( userPrefix.length() );
1066        } else {
1067            response = absoluteName;
1068        }
1069        return response;
1070    }
1071
1072    /**
1073     * Return the file-system path to a given absoluteName mailbox.
1074     *
1075     * @param absoluteName the user-independent name of the mailbox
1076     * @param owner string name of owner of mailbox
1077     */

1078    String JavaDoc getPath( String JavaDoc absoluteName ) {
1079        Assert.isTrue( Assert.ON &&
1080                       absoluteName.startsWith( NAMESPACE_TOKEN ) );
1081
1082        // Remove the leading '#' and replace Hierarchy separators with file separators.
1083
String JavaDoc filePath = absoluteName.substring( NAMESPACE_TOKEN.length() );
1084        filePath = filePath.replace( HIERARCHY_SEPARATOR_CHAR, File.separatorChar );
1085        return rootPath + filePath;
1086    }
1087
1088    public boolean createPrivateMailAccount( String JavaDoc user ) {
1089        Assert.isTrue( Assert.ON &&
1090                       user != null &&
1091                       user.length() > 0 );
1092
1093        String JavaDoc userRootName
1094                = getAbsoluteMailboxName( user, "" );
1095        String JavaDoc userInboxName
1096                = getAbsoluteMailboxName( user, "INBOX" );
1097        SimpleFolderRecord userRootRecord
1098                = new SimpleFolderRecord( user,
1099                                          userRootName );
1100        SimpleFolderRecord userInboxRecord
1101                = new SimpleFolderRecord( user, userInboxName );
1102
1103        ACLMailbox userRootFolder = new FileMailbox();
1104        ACLMailbox userInbox = new FileMailbox();
1105        try {
1106            setupLogger( userRootFolder );
1107            userRootFolder.configure( conf );
1108            userRootFolder.contextualize( context );
1109            userRootFolder.compose( compMgr );
1110            userRootFolder.prepareMailbox( user, userRootName, user, recordRep.nextUIDValidity() );
1111            setupLogger( userInbox );
1112            userInbox.configure( conf );
1113            userInbox.contextualize( context );
1114            userInbox.compose( compMgr );
1115            userInbox.prepareMailbox( user, userInboxName, user, recordRep.nextUIDValidity() );
1116            userRootFolder.initialize();
1117            userRootFolder.setNotSelectableByAnyone( true );
1118            userInbox.initialize();
1119            userInbox.setRights( user, MailServer.MDA, "lrswi" );
1120        }
1121        catch ( Exception JavaDoc e ) {
1122            getLogger().error( "Exception creating new account ", e );
1123            return false;
1124        }
1125        userInboxRecord.initialize();
1126        userInboxRecord.setUidValidity( userInbox.getUIDValidity() );
1127        userInboxRecord.setHighestUid( userInbox.getNextUID() - 1 );
1128        userInboxRecord.setLookupRights( userInbox.getUsersWithLookupRights() );
1129        userInboxRecord.setReadRights( userInbox.getUsersWithReadRights() );
1130        userInboxRecord.setNotSelectableByAnyone( userInbox.isNotSelectableByAnyone() );
1131        userRootRecord.initialize();
1132        userRootRecord.setLookupRights( userRootFolder.getUsersWithLookupRights() );
1133        userRootRecord.setReadRights( userRootFolder.getUsersWithReadRights() );
1134        userRootRecord.setNotSelectableByAnyone( userRootFolder.isNotSelectableByAnyone() );
1135        recordRep.store( userRootRecord );
1136        recordRep.store( userInboxRecord );
1137        
1138        userRootFolder = null;
1139        userInbox = null;
1140
1141        return true;
1142    }
1143
1144    private static final class OpenMailboxes {
1145
1146        private Map _mailboxes = new HashMap();
1147
1148        boolean contains( String JavaDoc absoluteName ) {
1149            return _mailboxes.containsKey( absoluteName );
1150        }
1151
1152        private OpenMailbox getOpen( String JavaDoc absoluteName ) {
1153            return (OpenMailbox)_mailboxes.get( absoluteName );
1154        }
1155
1156        void addMailbox( String JavaDoc absoluteName, ACLMailbox mailbox ) {
1157            OpenMailbox openMailbox = new OpenMailbox( mailbox );
1158            _mailboxes.put( absoluteName, openMailbox );
1159        }
1160
1161        void removeMailbox( String JavaDoc absoluteName ) {
1162            _mailboxes.remove( absoluteName );
1163        }
1164
1165        ACLMailbox getMailbox( String JavaDoc absoluteName ) {
1166            return getOpen( absoluteName ).getMailbox();
1167        }
1168
1169        int addReference( String JavaDoc absoluteName ) {
1170            return getOpen( absoluteName ).addReference();
1171        }
1172
1173        int removeReference( String JavaDoc absoluteName ) {
1174            return getOpen( absoluteName ).removeReference();
1175        }
1176
1177        int getReferenceCount( String JavaDoc absoluteName ) {
1178            OpenMailbox openMailbox = getOpen( absoluteName );
1179            if ( openMailbox == null ) {
1180                return 0;
1181            } else {
1182                return openMailbox.getReferenceCount();
1183            }
1184        }
1185    }
1186
1187    private static final class OpenMailbox {
1188        private ACLMailbox _mailbox;
1189        private int _referenceCount;
1190
1191        OpenMailbox( ACLMailbox mailbox ) {
1192            _mailbox = mailbox;
1193            _referenceCount = 1;
1194        }
1195
1196        ACLMailbox getMailbox() {
1197            return _mailbox;
1198        }
1199
1200        int getReferenceCount() {
1201            return _referenceCount;
1202        }
1203
1204        int addReference() {
1205            return ++_referenceCount;
1206        }
1207
1208        int removeReference() {
1209            return --_referenceCount;
1210        }
1211    }
1212}
1213
Popular Tags