1 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 ; 38 import java.io.FileInputStream ; 39 import java.io.ObjectInputStream ; 40 import java.util.*; 41 42 43 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 rootPath; private IMAPSystem imapSystem; 68 private UsersRepository localUsers; 69 private RecordRepository recordRep; 70 private OpenMailboxes openMailboxes; 72 public static final String HIERARCHY_SEPARATOR = "."; 73 public static final char HIERARCHY_SEPARATOR_CHAR = '.'; 74 public static final String NAMESPACE_TOKEN = "#"; 75 public static final String PRIVATE_NAMESPACE_PREFIX = ""; 76 private static final String USER_NAMESPACE = "user"; 77 private static final String SHARE_NAMESPACE = "share"; 78 public static final String USER_NAMESPACE_PREFIX = NAMESPACE_TOKEN + USER_NAMESPACE; 79 public static final String SHARE_NAMESPACE_PREFIX = NAMESPACE_TOKEN + SHARE_NAMESPACE; 80 81 102 103 110 111 112 113 116 public void contextualize( Context context ) { 117 this.context = context; 118 } 119 120 123 public void compose( ComponentManager comp ) { 124 compMgr = comp; 125 } 126 127 130 public void configure( Configuration conf ) throws ConfigurationException { 131 this.conf = conf; 132 } 133 134 137 public void initialize() throws Exception { 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 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 String usersPath = getPath( USER_NAMESPACE_PREFIX ); 159 prepareDir( usersPath ); 160 String sharePath = getPath( SHARE_NAMESPACE_PREFIX ); 161 prepareDir( sharePath ); 162 getLogger().info( "IMAP Mailbox Repository opened at " + rootPath ); 163 openMailboxes = new OpenMailboxes(); getLogger().info( "JamesHost ...init end" ); 165 } 166 167 170 private void prepareDir( String dir ) { 171 File newFolder = new File ( dir ); 172 if ( !newFolder.isDirectory() ) { 173 if ( !newFolder.mkdir() ) { 174 throw new RuntimeException ( "Error: Cannot create directory: " + dir ); 175 } 176 } else if ( !newFolder.canWrite() ) { 177 throw new RuntimeException ( "Error: Cannot write to directory: " + dir ); 178 } 179 } 180 181 190 public boolean isHomeServer( String username ) { 191 return localUsers.contains( username ); 192 } 193 194 203 public boolean hasLocalAccess( String username ) { 204 return localUsers.contains( username ); 205 } 206 207 219 public synchronized ACLMailbox getMailbox( String user, String 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 absoluteName = getAbsoluteMailboxName( user, mailboxName ); 228 return getAbsoluteMailbox( user, absoluteName ); 229 } 230 231 private synchronized ACLMailbox getAbsoluteMailbox( String user, String 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 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 owner = record.getUser(); 257 String key = getPath( absoluteName ); 258 ObjectInputStream in = null; 259 try { 260 in = new ObjectInputStream ( new FileInputStream ( 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 e ) { 269 e.printStackTrace(); 270 throw new RuntimeException ( "Exception caught while reading FileMailbox: " + e ); 271 } finally { 272 if ( in != null ) { 273 try { 274 in.close(); 275 } 276 catch ( Exception 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 312 public synchronized ACLMailbox createMailbox( String user, String mailboxName ) 313 throws AccessControlException, AuthorizationException, MailboxException { 314 Assert.isTrue( Assert.ON && 315 user != null && 316 user.length() > 0 && 317 mailboxName != null ); 318 319 String 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 user, String 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 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 String parent = absoluteName.substring( 0, absoluteName.lastIndexOf( HIERARCHY_SEPARATOR ) ); 346 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 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 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 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 392 public void releaseMailbox( String 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 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 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 445 public boolean deleteMailbox( String user, String 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 absoluteName = getAbsoluteMailboxName( user, mailboxName ); 454 getLogger().debug( "JamesHost deleteMailbox() called for: " + absoluteName ); 455 return deleteAbsoluteMailbox( user, absoluteName ); 456 } 457 458 private boolean deleteAbsoluteMailbox( String user, String 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 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 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 user ) 498 throws AccessControlException, AuthorizationException { 499 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 530 public boolean renameMailbox( String user, String oldMailboxName, String newMailboxName ) 531 throws MailboxException, AuthorizationException { 532 try { 536 ACLMailbox mailbox = this.getMailbox(user,oldMailboxName); 537 String oldAbsoluteName = getAbsoluteMailboxName(user, oldMailboxName); 538 539 Collection coll = this.listMailboxes(user,"",oldMailboxName+"*",false); 541 java.util.TreeMap tr = new java.util.TreeMap (); 542 Iterator it = coll.iterator(); 543 544 int mindepth=9999; 545 int maxdepth=0; 546 while(it.hasNext()) { 547 StringTokenizer strl = new StringTokenizer((String ) it.next()); 549 String mailboxname = ""; 550 boolean mbxfound=false; 551 while(strl.hasMoreTokens()) { 552 String token = strl.nextToken(); 553 if(token.equals("\""+this.HIERARCHY_SEPARATOR+"\"") || mbxfound) { 554 if(mbxfound){ 556 mailboxname += " "+token; 557 } else { 558 mailboxname += strl.nextToken(); 559 } 560 mbxfound=true; 561 } 562 } 563 strl = new StringTokenizer(mailboxname, this.HIERARCHY_SEPARATOR); 565 mailboxname = mailboxname.substring(1,mailboxname.length()-1); 566 System.out.println("RENAME: MAILBOXNAME FOUND: "+mailboxname); 567 Object oldcoll = tr.get(new Integer (strl.countTokens())); 572 if (oldcoll==null) { 573 HashSet hs = new HashSet(); 574 hs.add(mailboxname); 575 tr.put(new Integer (strl.countTokens()), hs); 576 } else { 577 HashSet hs = (HashSet) oldcoll; 578 hs.add(mailboxname); 579 tr.put(new Integer (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 (i)); 591 if (cole!=null) { 592 Iterator ite = cole.iterator(); 593 while(ite.hasNext()) { 594 String mbxhere = (String ) ite.next(); 595 String 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 suboldabsolutename = mmm.getAbsoluteName(); 600 mmm.renameSubMailbox(user, oldAbsoluteName, newMailboxName); 601 String subnewabsolutename = mmm.getAbsoluteName(); 603 FolderRecord fr = recordRep.retrieve(suboldabsolutename); 605 recordRep.deleteRecord(fr); 606 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 this.openMailboxes.removeMailbox(suboldabsolutename); 621 this.openMailboxes.addMailbox(subnewabsolutename,mmm); 622 } else { 623 System.out.println("NEWMAILBOXNAME WILL BE "+newMailboxName); 625 if (mmm.renameMailbox(user, newMailboxName)) { 626 String absolutenewName = getAbsoluteMailboxName(user, newMailboxName); 628 FolderRecord fr = recordRep.retrieve(oldAbsoluteName); 630 recordRep.deleteRecord(fr); 631 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 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 e) { 658 e.printStackTrace(); 659 throw new AuthorizationException("You have insufficient permission to change the Mailbox Name"); 660 } 661 } 662 663 670 public String getDefaultNamespace( String username ) { 671 return PRIVATE_NAMESPACE_PREFIX; 672 } 673 674 681 683 724 public synchronized Collection listMailboxes( String username, 725 String referenceName, 726 String 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 if ( mailboxName.equals( "" ) ) { 735 String 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 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 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 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 String 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 testMailboxName = (String ) 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 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 buf = new StringBuffer (); 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 e ) { 864 getLogger().error( "Exception with list request for mailbox " + mailboxName ); 865 e.printStackTrace(); 866 return null; 867 } 868 } 869 870 private String getNamespacePrefix( String 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 892 public boolean subscribe( String userName, String 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 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 917 public boolean unsubscribe( String userName, String 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 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 955 public String getMailboxStatus( String username, String mailboxName, 956 List dataItems ) 957 throws MailboxException, AccessControlException 958 { 959 String absoluteName = getAbsoluteMailboxName( username, mailboxName ); 960 ACLMailbox mailbox = null; 961 FolderRecord record = null; 962 Iterator it = dataItems.iterator(); 963 String response = null; 964 965 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 (); 974 mailbox = openMailboxes.getMailbox( absoluteName ); 975 if ( !mailbox.hasLookupRights( username ) ) { 976 throw new AccessControlException( "No lookup rights." ); 977 } 978 while ( it.hasNext() ) { 979 String dataItem = (String ) 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 (); 1002 while ( it.hasNext() ) { 1003 String dataItem = (String ) 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 1035 private String getAbsoluteMailboxName( String user, String fullMailboxName ) 1036 { 1037 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 1060 private String getUserAwareMailboxName( String user, String absoluteName ) 1061 { 1062 String userPrefix = USER_NAMESPACE_PREFIX + HIERARCHY_SEPARATOR + user + HIERARCHY_SEPARATOR; 1063 String response; 1064 if ( absoluteName.startsWith( userPrefix ) ) { 1065 response = absoluteName.substring( userPrefix.length() ); 1066 } else { 1067 response = absoluteName; 1068 } 1069 return response; 1070 } 1071 1072 1078 String getPath( String absoluteName ) { 1079 Assert.isTrue( Assert.ON && 1080 absoluteName.startsWith( NAMESPACE_TOKEN ) ); 1081 1082 String 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 user ) { 1089 Assert.isTrue( Assert.ON && 1090 user != null && 1091 user.length() > 0 ); 1092 1093 String userRootName 1094 = getAbsoluteMailboxName( user, "" ); 1095 String 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 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 absoluteName ) { 1149 return _mailboxes.containsKey( absoluteName ); 1150 } 1151 1152 private OpenMailbox getOpen( String absoluteName ) { 1153 return (OpenMailbox)_mailboxes.get( absoluteName ); 1154 } 1155 1156 void addMailbox( String absoluteName, ACLMailbox mailbox ) { 1157 OpenMailbox openMailbox = new OpenMailbox( mailbox ); 1158 _mailboxes.put( absoluteName, openMailbox ); 1159 } 1160 1161 void removeMailbox( String absoluteName ) { 1162 _mailboxes.remove( absoluteName ); 1163 } 1164 1165 ACLMailbox getMailbox( String absoluteName ) { 1166 return getOpen( absoluteName ).getMailbox(); 1167 } 1168 1169 int addReference( String absoluteName ) { 1170 return getOpen( absoluteName ).addReference(); 1171 } 1172 1173 int removeReference( String absoluteName ) { 1174 return getOpen( absoluteName ).removeReference(); 1175 } 1176 1177 int getReferenceCount( String 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 |