1 17 18 package org.apache.james.imapserver; 19 20 import org.apache.avalon.cornerstone.services.store.ObjectRepository; 21 import org.apache.avalon.cornerstone.services.store.Store; 22 import org.apache.avalon.framework.component.ComponentManager; 23 import org.apache.avalon.framework.configuration.Configuration; 24 import org.apache.avalon.framework.configuration.ConfigurationException; 25 import org.apache.avalon.framework.context.Context; 26 import org.apache.avalon.framework.logger.AbstractLogEnabled; 27 import org.apache.avalon.phoenix.BlockContext; 28 import org.apache.james.imapserver.AccessControlException; 29 import org.apache.james.imapserver.AuthorizationException; 30 import org.apache.james.core.MimeMessageWrapper; 31 import org.apache.james.services.UsersRepository; 32 import org.apache.james.services.UsersStore; 33 import org.apache.james.util.Assert; 34 35 import javax.mail.internet.InternetHeaders ; 36 import javax.mail.internet.MimeMessage ; 37 import javax.mail.MessagingException ; 38 import java.io.*; 39 import java.util.*; 40 41 101 public class FileMailbox 102 extends AbstractLogEnabled 103 implements ACLMailbox, Serializable { 104 105 public static final String MAILBOX_FILE_NAME = "mailbox.mbr"; 106 107 private static final String MESSAGE_EXTENSION = ".msg"; 108 private static final String ATTRIBUTES_EXTENSION = ".att"; 109 private static final String FLAGS_EXTENSION = ".flags"; 110 111 private static final int NUMBER_OF_RIGHTS = 9; 112 private static final int LOOKUP = 0; 115 private static final int READ = 1; 116 private static final int KEEP_SEEN = 2; 117 private static final int WRITE = 3; 118 private static final int INSERT = 4; 119 private static final int POST = 5; 120 private static final int CREATE = 6; 121 private static final int DELETE = 7; 122 private static final int ADMIN = 8; 123 private static final boolean[] NO_RIGHTS 124 = {false, false, false, false, false, false, false, false, false}; 125 private static final boolean[] ALL_RIGHTS 126 = {true, true, true, true, true, true, true, true, true}; 127 private static final String DENY_ACCESS = "Access denied by ACL"; 128 private static final String DENY_AUTH = "Action not authorized for: "; 129 private static final String OPTIONAL_RIGHTS = "l r s w i p c d a"; 130 private static final char[] DELETE_MODS 131 = {'-', 'l', 'r', 's', 'w', 'i', 'p', 'c', 'd', 'a'}; 132 133 134 private transient BlockContext context; 135 private transient Configuration conf; 136 private transient ComponentManager compMgr; 137 private transient UsersRepository localUsers; 138 private transient HashSet listeners; 139 140 141 private String path; private String rootPath; private File directory ; 144 private String owner; 145 private String absoluteName; 146 private Map acl; 147 private String name; 148 private int uidValidity; 149 private int mailboxSize; private boolean inferiorsAllowed; 151 private boolean marked; 152 private boolean notSelectableByAnyone; 153 154 private static HighestUID highestUID; 156 157 private List sequence; 160 private Set recentMessages; 162 163 private Set messagesForDeletion; 165 166 private Map oldestUnseenMessage; 168 169 private Set subscribedUsers = new HashSet(1000); 171 172 public void configure(Configuration conf) throws ConfigurationException { 173 this.conf = conf; 174 } 175 176 public void contextualize(Context context) { 177 this.context = (BlockContext)context; 178 } 179 180 public void compose(ComponentManager comp) { 181 compMgr = comp; 182 } 183 184 public void prepareMailbox(String user, String absName, String initialAdminUser, int uidValidity ) { 185 Assert.isTrue( Assert.ON && user != null && user.length() > 0 ); 186 owner = user; 187 188 Assert.isTrue( Assert.ON && absName != null && (absName.length() > 0)); 189 absoluteName = absName; 190 191 Assert.isTrue( Assert.ON && initialAdminUser != null && initialAdminUser.length() > 0 ); 192 acl = new HashMap(7); 193 acl.put(initialAdminUser, ALL_RIGHTS); 194 195 Assert.isTrue( Assert.ON && uidValidity > 0 ); 196 this.uidValidity = uidValidity; 197 } 198 199 public void initialize() throws Exception { 200 201 mailboxSize = 0; 202 inferiorsAllowed = true; 203 marked = false; 204 notSelectableByAnyone = false; 205 oldestUnseenMessage = new HashMap(); 206 listeners = new HashSet(); 207 sequence = new ArrayList(); 208 recentMessages = new HashSet(); 209 messagesForDeletion = new HashSet(); 210 getLogger().info("FileMailbox init for " + absoluteName); 211 UsersStore usersStore = (UsersStore)compMgr.lookup( "org.apache.james.services.UsersStore" ); 212 localUsers = usersStore.getRepository("LocalUsers"); 213 rootPath = conf.getChild( "mailboxRepository" ).getValue(); 214 if (!rootPath.endsWith(File.separator)) { 215 rootPath = rootPath + File.separator; 216 } 217 218 path = getPath( absoluteName, owner, rootPath ); 219 name = absoluteName.substring(absoluteName.lastIndexOf( JamesHost.HIERARCHY_SEPARATOR ) + 1); 220 if (name.equals(owner)) { 221 name = ""; 222 } 223 getLogger().info("MailboxDir " + path); 225 System.out.println("MailboxDir TO WRITE TO " + path); 226 File mailboxDir = new File(path); 227 if (mailboxDir.exists()) { 228 throw new RuntimeException ("Error: Attempt to overwrite mailbox directory at " + path); 229 } else if (! mailboxDir.mkdir()){ 230 throw new RuntimeException ("Error: Cannot create mailbox directory at " + path); 231 } else if (!mailboxDir.canWrite()) { 232 throw new RuntimeException ("Error: Cannot write to directory at " + path); 233 } 234 writeMailbox(); 235 getLogger().info("FileMailbox init complete: " + absoluteName); 236 } 237 238 239 240 246 private String getPath( String absoluteName, String owner, String rootPath ) 247 { 248 Assert.isTrue( Assert.ON && 249 absoluteName.startsWith( JamesHost.NAMESPACE_TOKEN ) ); 250 251 String filePath = absoluteName.substring( JamesHost.NAMESPACE_TOKEN.length() ); 253 filePath = filePath.replace( JamesHost.HIERARCHY_SEPARATOR_CHAR, File.separatorChar ); 254 return rootPath + filePath; 255 } 256 257 262 public void reinitialize() throws Exception { 263 listeners = new HashSet(); 264 getLogger().info("FileMailbox reInit for " + absoluteName); 265 UsersStore usersStore = (UsersStore)compMgr.lookup( "org.apache.james.services.UsersStore" ); 266 localUsers = usersStore.getRepository("LocalUsers"); 267 rootPath 268 = conf.getChild("mailboxRepository").getValue(); 269 if (!rootPath.endsWith(File.separator)) { 270 rootPath = rootPath + File.separator; 271 } 272 path = getPath( absoluteName, owner, rootPath ); 273 } 274 275 280 public void dispose() { 281 writeMailbox(); 282 getLogger().info("FileMailbox object destroyed: " + absoluteName); 283 } 284 285 288 public void removeMailbox() 289 { 290 path = getPath( absoluteName, owner, rootPath ); 292 String mailboxRecordFile = path + File.separator + MAILBOX_FILE_NAME; 293 File mailboxRecord = new File( mailboxRecordFile ); 294 Assert.isTrue( Assert.ON && 295 mailboxRecord.exists() && 296 mailboxRecord.isFile() ); 297 mailboxRecord.delete(); 298 299 File mailboxDir = new File(path); 301 Assert.isTrue( Assert.ON && 302 mailboxDir.exists() ); 303 Assert.isTrue( Assert.ON && 304 mailboxDir.isDirectory() ); 305 Assert.isTrue( Assert.ON && 306 mailboxDir.list().length == 0 ); 307 mailboxDir.delete(); 308 } 309 310 318 public boolean renameMailbox(String username, String newmailboxname) throws MailboxException, AuthorizationException { 319 try { 320 path = getPath( absoluteName, owner, rootPath ); 321 322 StringTokenizer strt = new StringTokenizer(newmailboxname,"."); 323 String lastnameofmailbox=""; 324 while(strt.hasMoreTokens()) 325 lastnameofmailbox=strt.nextToken(); 326 327 File fle = new File(this.path); 328 fle.renameTo(new File(fle.getParent(), lastnameofmailbox)); 329 330 this.path=fle.getParent()+File.separator+lastnameofmailbox; 331 this.absoluteName = this.absoluteName.substring(0,this.absoluteName.length()-this.name.length())+lastnameofmailbox; 332 this.name=lastnameofmailbox; 333 334 335 this.writeMailbox(); 336 return true; 337 }catch(Exception e) { 338 e.printStackTrace(); 339 return false; 340 } 341 } 342 343 353 public boolean renameSubMailbox(String username, String oldabsolutename, String newname) { 354 try { 355 System.out.println("renameSubMailbox ABSOLUTE NAME "+this.absoluteName); 356 StringTokenizer strt = new StringTokenizer(oldabsolutename,"."); 357 StringBuffer strbuff = new StringBuffer (); 358 359 for(int i=0;i<strt.countTokens();i++){ 360 String token = strt.nextToken(); 361 if(strbuff.length()>0) strbuff.append("."); 362 strbuff.append(token); 363 } 364 strbuff.append("."); 365 strbuff.append(newname); 366 367 this.absoluteName = strbuff.toString()+this.absoluteName.substring(oldabsolutename.length()); 368 System.out.println("renameSubMailbox TOKEN CONVERTED: "+this.absoluteName); 369 this.writeMailbox(); 370 return true; 371 }catch(Exception e) { 372 e.printStackTrace(); 373 return false; 374 } 375 } 376 377 386 public synchronized boolean checkpoint() { 387 writeMailbox(); 388 getLogger().info("FileMailbox: " + absoluteName + " checkpointed."); 389 return true; 390 } 391 392 396 public synchronized void unsetRecent() { 397 Iterator it = recentMessages.iterator(); 398 while(it.hasNext()) { 399 Integer uidObj =(Integer )it.next(); 400 int uid = uidObj.intValue(); 401 Flags flags = readFlags(uid); 402 if (flags != null) { 403 flags.setRecent(false); 404 writeFlags(uid, flags); 405 } 406 } 407 recentMessages.clear(); 408 } 409 410 411 413 421 public String getName() { 422 return name; 423 } 424 425 432 public String getAbsoluteName() { 433 return absoluteName; 434 } 435 436 441 443 449 public boolean matchesName(String testName) { 450 return (name.equals(testName) || name.equals(absoluteName)); 451 } 452 453 458 public int getUIDValidity() { 459 return uidValidity; 460 } 461 462 467 public int getNextUID() { 468 return highestUID.get() + 1; 469 } 470 471 477 public synchronized int getMailboxSize() { 478 return mailboxSize; 479 } 480 481 487 public boolean getInferiorsAllowed() { 488 return inferiorsAllowed; 489 } 490 491 498 public synchronized boolean isMarked() { 499 return marked; 500 } 501 502 509 public String getSupportedFlags() { 510 return SYSTEM_FLAGS; 511 } 512 517 public synchronized int getRecent() { 518 return recentMessages.size(); 519 } 520 521 527 public synchronized int getOldestUnseen(String user) { 528 int response = 0; 529 if (oldestUnseenMessage.containsKey(user)) { 530 Integer uidObj = ((Integer )oldestUnseenMessage.get(user)); 531 if (! (uidObj.intValue() == 0)) { 532 response = sequence.indexOf(uidObj) + 1; 533 } 534 } else { 535 if (sequence.size() > 0) { 536 response = 1; 537 oldestUnseenMessage.put(user, (Integer )sequence.get(0)); 538 } else { 539 oldestUnseenMessage.put(user, (new Integer (0))); 540 } 541 } 542 return response; 543 } 544 545 550 public synchronized int getExists() { 551 return sequence.size(); 552 } 553 554 559 public int getUnseen(String user) { 560 if (oldestUnseenMessage.containsKey(user)) { 561 int response = 0; Integer uidObj = ((Integer )oldestUnseenMessage.get(user)); 563 int oldUID = uidObj.intValue(); 564 if (oldUID != 0) { 565 ListIterator lit 566 = sequence.listIterator(sequence.indexOf(uidObj)); 567 while (lit.hasNext() ) { 568 int uid = ((Integer )lit.next()).intValue(); 569 Flags flags = readFlags(uid); 570 if (!flags.isSeen(user)) { 571 response ++; 572 } 573 } 574 } 575 return response; 576 } else { return sequence.size(); 578 } 579 } 580 581 584 public synchronized void addMailboxEventListener(MailboxEventListener mel) { 585 listeners.add(mel); 586 } 587 588 589 public synchronized void removeMailboxEventListener(MailboxEventListener mel) { 590 listeners.remove(mel); 591 } 592 593 599 public void setNotSelectableByAnyone(boolean state) { 600 notSelectableByAnyone = state; 601 } 602 603 public boolean isNotSelectableByAnyone() { 604 return notSelectableByAnyone; 605 } 606 607 609 635 public boolean setRights(String setter, String identifier, 636 String modification) 637 throws AccessControlException, AuthorizationException { 638 639 boolean[] settersRights = (boolean[]) acl.get(setter); 640 if (settersRights == null 641 || (settersRights[LOOKUP] == false)) { 642 throw new AccessControlException(DENY_ACCESS); 643 } else if (settersRights[ADMIN] == false) { 644 throw new AuthorizationException(DENY_AUTH + setter); 645 } 646 boolean[] existingRights = (boolean[]) acl.get(identifier); 647 char[] mods = modification.toCharArray(); 648 if (mods.length == 0) { mods = DELETE_MODS; 650 } 651 if(existingRights == null) { 652 if ( mods[0] == REMOVE_RIGHTS ) { 653 return false; 654 } else { 655 existingRights = new boolean[NUMBER_OF_RIGHTS]; 656 System.arraycopy(NO_RIGHTS, 0, existingRights, 0, 657 NUMBER_OF_RIGHTS); 658 } 659 } 660 661 boolean change; 662 boolean[] rights = new boolean[NUMBER_OF_RIGHTS]; 663 664 if (mods[0] == ADD_RIGHTS) { 665 change = true; 666 System.arraycopy(existingRights, 0, rights, 0, 667 NUMBER_OF_RIGHTS); 668 } else if (mods[0] == REMOVE_RIGHTS) { 669 change = false; 670 System.arraycopy(existingRights, 0, rights, 0, 671 NUMBER_OF_RIGHTS); 672 } else { System.arraycopy(NO_RIGHTS, 0, rights, 0, 674 NUMBER_OF_RIGHTS); 675 char[] new_mods = new char[mods.length + 1]; 676 System.arraycopy(mods, 0, new_mods, 1, mods.length); 677 mods = new_mods; 678 change = true; 679 } 680 681 for (int i=1; i <mods.length; i++) { 682 switch(mods[i]) { 683 case LOOKUP_RIGHTS: rights[LOOKUP] = change; 684 break; 685 case READ_RIGHTS: rights[READ] = change; 686 break; 687 case KEEP_SEEN_RIGHTS: rights[KEEP_SEEN] = change; 688 break; 689 case WRITE_RIGHTS: rights[WRITE] = change; 690 break; 691 case INSERT_RIGHTS: rights[INSERT] = change; 692 break; 693 case POST_RIGHTS: rights[POST] = change; 694 break; 695 case CREATE_RIGHTS: rights[CREATE] = change; 696 break; 697 case DELETE_RIGHTS: rights[DELETE] = change; 698 break; 699 case ADMIN_RIGHTS: rights[ADMIN] = change; 700 break; 701 default: return false; 702 } 703 } 704 705 if(rights[LOOKUP] == false && !Arrays.equals(rights, NO_RIGHTS)) { 707 return false; 708 } 709 int count = 0; 711 for (int i=1; i< NUMBER_OF_RIGHTS; i++) { 712 if(rights[i-1] ^ rights[i]) { 713 count++; 714 } 715 } 716 switch (count) { 717 case 0: if (rights[ADMIN]) { 719 acl.put(identifier, rights); 720 break; 721 } else { 722 if (otherAdmin(identifier)) { 723 acl.remove(identifier); 724 break; 725 } else { 726 return false; 727 } 728 } 729 case 2: return false; 731 case 1: if (otherAdmin(identifier)) { 742 acl.put(identifier, rights); 743 break; 744 } else { 745 return false; 746 } 747 default: return false; 749 } 750 writeMailbox(); 751 return true; 752 } 753 754 757 private boolean otherAdmin(String identifier) { 758 Iterator namesIt = acl.keySet().iterator(); 759 boolean result = false; 760 while(namesIt.hasNext() && !result) { 761 String name = (String )namesIt.next(); 762 if (!name.equals(identifier)) { 763 boolean[] otherRights = (boolean[]) acl.get(name); 764 result = otherRights[ADMIN]; 765 } 766 } 767 return result; 768 } 769 770 784 public String getRights(String getter, String identity) 785 throws AccessControlException, AuthorizationException { 786 boolean[] gettersRights = (boolean[]) acl.get(getter); 787 if (gettersRights == null 788 || (gettersRights[LOOKUP] == false)) { 789 throw new AccessControlException(DENY_ACCESS); 790 } else if (!getter.equals(identity) && gettersRights[ADMIN] == false) { 791 throw new AuthorizationException(DENY_AUTH + getter); 792 } 793 boolean[] rights = (boolean[]) acl.get(identity); 794 if (rights == null) { 795 return null; 796 } else { 797 StringBuffer buf = new StringBuffer (NUMBER_OF_RIGHTS); 798 for (int i = 0; i<NUMBER_OF_RIGHTS; i++) { 799 if (rights[i]) { 800 buf.append(RIGHTS[i]); 801 } 802 } 803 return buf.toString(); 804 } 805 } 806 807 819 public String getAllRights(String getter) 820 throws AccessControlException, AuthorizationException { 821 boolean[] gettersRights = (boolean[]) acl.get(getter); 822 if (gettersRights == null 823 || (gettersRights[LOOKUP] == false)) { 824 throw new AccessControlException(DENY_ACCESS); 825 } else if ( gettersRights[ADMIN] == false) { 826 throw new AuthorizationException(DENY_AUTH + getter); 827 } 828 Iterator namesIt = acl.keySet().iterator(); 829 StringBuffer response = new StringBuffer (20*acl.size()); 830 while(namesIt.hasNext()) { 831 String name = (String )namesIt.next(); 832 response.append("<" + name + " "); 833 boolean[] rights = (boolean[]) acl.get(name); 834 for (int i = 0; i<NUMBER_OF_RIGHTS; i++) { 835 if (rights[i]) { 836 response.append(RIGHTS[i]); 837 } 838 } 839 response.append("> "); 840 } 841 842 return response.toString(); 843 } 844 845 859 public String getRequiredRights(String getter, String identity) 860 throws AccessControlException, AuthorizationException { 861 boolean[] gettersRights = (boolean[]) acl.get(getter); 862 if (gettersRights == null 863 || (gettersRights[LOOKUP] == false)) { 864 throw new AccessControlException(DENY_ACCESS); 865 } else if (!getter.equals(identity) && gettersRights[ADMIN] == false) { 866 throw new AuthorizationException(DENY_AUTH + getter); 867 } 868 869 return "\"\""; 870 } 871 872 885 public String getOptionalRights(String getter, String identity) 886 throws AccessControlException, AuthorizationException { 887 boolean[] gettersRights = (boolean[]) acl.get(getter); 888 if (gettersRights == null 889 || (gettersRights[LOOKUP] == false)) { 890 throw new AccessControlException(DENY_ACCESS); 891 } else if (!getter.equals(identity) && gettersRights[ADMIN] == false) { 892 throw new AuthorizationException(DENY_AUTH + getter); 893 } 894 895 return OPTIONAL_RIGHTS; 896 } 897 898 908 public boolean hasLookupRights(String username) { 909 boolean[] usersRights = (boolean[]) acl.get(username); 910 return (( usersRights == null || (usersRights[LOOKUP] == false)) 911 ? false : true); 912 } 913 914 public boolean hasReadRights(String username) 915 throws AccessControlException { 916 boolean[] usersRights = (boolean[]) acl.get(username); 917 if (usersRights == null || (usersRights[LOOKUP] == false)) { 918 throw new AccessControlException(DENY_ACCESS); 919 } 920 return usersRights[READ]; 921 } 922 923 public boolean hasKeepSeenRights(String username) 924 throws AccessControlException { 925 boolean[] usersRights = (boolean[]) acl.get(username); 926 if (usersRights == null || (usersRights[LOOKUP] == false)) { 927 throw new AccessControlException(DENY_ACCESS); 928 } 929 return usersRights[KEEP_SEEN]; 930 } 931 932 public boolean hasWriteRights(String username) 933 throws AccessControlException { 934 boolean[] usersRights = (boolean[]) acl.get(username); 935 if (usersRights == null || (usersRights[LOOKUP] == false)) { 936 throw new AccessControlException(DENY_ACCESS); 937 } 938 return usersRights[WRITE]; 939 } 940 941 public boolean hasInsertRights(String username) 942 throws AccessControlException { 943 boolean[] usersRights = (boolean[]) acl.get(username); 944 if (usersRights == null || (usersRights[LOOKUP] == false)) { 945 throw new AccessControlException(DENY_ACCESS); 946 } 947 return usersRights[INSERT]; 948 } 949 950 public boolean hasCreateRights(String username) 951 throws AccessControlException { 952 boolean[] usersRights = (boolean[]) acl.get(username); 953 if (usersRights == null || (usersRights[LOOKUP] == false)) { 954 throw new AccessControlException(DENY_ACCESS); 955 } 956 return usersRights[CREATE]; 957 } 958 959 public boolean hasDeleteRights(String username) 960 throws AccessControlException { 961 boolean[] usersRights = (boolean[]) acl.get(username); 962 if (usersRights == null || (usersRights[LOOKUP] == false)) { 963 throw new AccessControlException(DENY_ACCESS); 964 } 965 return usersRights[DELETE]; 966 } 967 968 public boolean hasAdminRights(String username) 969 throws AccessControlException { 970 boolean[] usersRights = (boolean[]) acl.get(username); 971 if (usersRights == null || (usersRights[LOOKUP] == false)) { 972 throw new AccessControlException(DENY_ACCESS); 973 } 974 return usersRights[ADMIN]; 975 } 976 977 979 988 public synchronized boolean isSelectable(String username) 989 throws AccessControlException { 990 return ( ! notSelectableByAnyone && hasReadRights(username) ); 991 } 992 993 1000 public synchronized boolean allFlags(String username) 1001 throws AccessControlException { 1002 return hasDeleteRights(username); 1005 } 1006 1007 1016 public synchronized String getPermanentFlags(String username) 1017 throws AccessControlException { 1018 if (hasDeleteRights(username)) { 1019 return SYSTEM_FLAGS; 1020 } else if (hasWriteRights(username)) { 1021 return "\\Seen \\Answered \\Flagged \\Draft"; 1022 } else if (hasKeepSeenRights(username)) { 1023 return "\\Seen"; 1024 } else { 1025 return ""; 1026 } 1027 } 1028 1029 1034 1036 1050 public synchronized boolean isReadOnly(String username) 1051 throws AccessControlException { 1052 return (! hasWriteRights(username)); 1053 } 1054 1055 1057 1068 public synchronized boolean store(MimeMessage message, String username) 1069 throws AccessControlException, AuthorizationException, 1070 IllegalArgumentException { 1071 1072 if (message == null || username == null) { 1073 getLogger().error("Null argument received in store."); 1074 throw new IllegalArgumentException ("Null argument received in store."); 1075 } 1076 if (!hasInsertRights(username)) { throw new AuthorizationException("Not authorized to insert."); 1078 } 1079 1080 SimpleMessageAttributes attrs = new SimpleMessageAttributes(); 1081 try { 1082 setupLogger(attrs); 1083 attrs.setAttributesFor(message); 1084 } catch (javax.mail.MessagingException me) { 1085 throw new RuntimeException ("Exception creating SimpleMessageAttributes: " + me); 1086 } 1087 Flags flags = new Flags(); 1088 flags.initialize(); 1089 return store(message, username, attrs, flags); 1090 } 1091 1092 1107 public boolean store(MimeMessage message, String username, 1108 MessageAttributes msgAttrs, Flags flags) 1109 throws AccessControlException, AuthorizationException, 1110 IllegalArgumentException { 1111 1112 if (msgAttrs == null || message == null || username == null) { 1113 getLogger().error("Null argument received in store."); 1114 throw new IllegalArgumentException ("Null argument received in store."); 1115 } 1116 if (! (msgAttrs instanceof SimpleMessageAttributes)) { 1117 getLogger().error("Wrong class for Attributes"); 1118 throw new IllegalArgumentException ("Wrong class for Attributes"); 1119 } 1120 SimpleMessageAttributes attrs = (SimpleMessageAttributes)msgAttrs; 1121 1122 highestUID.increase(); 1123 int newUID = highestUID.get(); 1124 attrs.setUID(newUID); 1125 sequence.add(new Integer (newUID)); 1126 attrs.setMessageSequenceNumber(sequence.size()); 1127 1128 BufferedOutputStream outMsg = null; 1129 ObjectOutputStream outAttrs = null; 1130 1131 try { 1132 path = getPath( absoluteName, owner, rootPath ); 1134 outMsg = new BufferedOutputStream( new FileOutputStream(path + File.separator + newUID + MESSAGE_EXTENSION)); 1135 message.writeTo(outMsg); 1136 outMsg.close(); 1137 outAttrs = new ObjectOutputStream( new FileOutputStream(path + File.separator + newUID + ATTRIBUTES_EXTENSION)); 1138 outAttrs.writeObject(attrs); 1139 outAttrs.close(); 1140 } catch(Exception e) { 1141 getLogger().error("Error writing message to disc: " + e); 1142 e.printStackTrace(); 1143 throw new 1144 RuntimeException ("Exception caught while storing Mail: " 1145 + e); 1146 } finally { 1147 try { 1148 outMsg.close(); 1149 outAttrs.close(); 1150 } catch (IOException ie) { 1151 getLogger().error("Error closing streams: " + ie); 1152 } 1153 } 1154 marked = true; 1155 if (flags.isRecent()) { 1156 recentMessages.add(new Integer (newUID)); 1157 } 1158 if (flags.isDeleted()) { 1159 messagesForDeletion.add(new Integer (newUID)); 1160 } 1161 Iterator it = oldestUnseenMessage.keySet().iterator(); 1164 while (it.hasNext()) { 1165 String user = (String )it.next(); 1166 if ( ((Integer )oldestUnseenMessage.get(user)).intValue() == -1) { 1167 oldestUnseenMessage.put(user, new Integer (newUID)); 1168 } 1169 } 1170 writeFlags(newUID, flags); 1172 getLogger().info("Mail " + newUID + " written in " + absoluteName); 1173 1174 return true; 1175 } 1176 1177 1189 public synchronized MimeMessageWrapper retrieve(int msn, String user) 1190 throws AccessControlException, AuthorizationException { 1191 if (!hasReadRights(user)) { throw new AuthorizationException("Not authorized to read."); 1193 } 1194 1195 if (msn > sequence.size()) { 1196 return null; 1197 } else { 1198 int uid = ((Integer )sequence.get(msn - 1)).intValue(); 1199 return retrieveUID(uid, user); 1200 } 1201 } 1202 1203 1204 1216 public synchronized MimeMessageWrapper retrieveUID(int uid, String user) 1217 throws AccessControlException, AuthorizationException { 1218 if (!hasReadRights(user)) { throw new AuthorizationException("Not authorized to read."); 1220 } 1221 MimeMessageWrapper response = null; 1222 if (sequence.contains(new Integer (uid))) { 1223 try { 1225 path = getPath( absoluteName, owner, rootPath ); 1226 MimeMessageFileSource source = new MimeMessageFileSource(path + File.separator + uid + MESSAGE_EXTENSION); 1227 response = new MimeMessageWrapper(source); 1228 } catch(Exception e) { 1230 getLogger().error("Error reading message from disc: " + e); 1231 e.printStackTrace(); 1232 throw new 1233 RuntimeException ("Exception caught while retrieving Mail: " 1234 + e); 1235 } getLogger().info("MimeMessageWrapper " + uid + " read from " + absoluteName); 1243 return response; 1244 } else { 1245 return null; 1246 } 1247 } 1248 1249 1260 public synchronized boolean markDeleted(int msn, String user) 1261 throws AccessControlException, AuthorizationException { 1262 if (!hasDeleteRights(user)) { throw new AuthorizationException("Not authorized to delete."); 1264 } 1265 1266 Assert.notImplemented(); 1267 return false; 1269 } 1270 1271 1283 public synchronized boolean markDeletedUID(int uid, String user) 1284 throws AccessControlException, AuthorizationException { 1285 if (!hasDeleteRights(user)) { throw new AuthorizationException("Not authorized to delete."); 1287 } 1288 1289 Assert.notImplemented(); 1290 return false; 1292 } 1293 1294 1307 public synchronized MessageAttributes getMessageAttributes(int msn, String user) 1308 throws AccessControlException, AuthorizationException { 1309 if (!hasReadRights(user)) { throw new AuthorizationException("Not authorized to read."); 1311 } 1312 System.out.println("msn: "+msn); 1313 System.out.println("sequence.size: "+sequence.size()); 1314 if (msn > sequence.size()) { 1315 return null; 1316 } else { 1317 int uid = ((Integer )sequence.get(msn - 1)).intValue(); 1318 return getMessageAttributesUID(uid, user); 1319 } 1320 } 1321 1322 1335 public synchronized MessageAttributes getMessageAttributesUID(int uid, String user) 1336 throws AccessControlException, AuthorizationException { 1337 if (!hasReadRights(user)) { throw new AuthorizationException("Not authorized to read."); 1339 } 1340 System.out.println("getMessageAttributesUID()"); 1341 System.out.println("uid: "+uid); 1342 System.out.println("user: "+user); 1343 System.out.println("sequence.size: "+sequence.size()); 1344 SimpleMessageAttributes response = null; 1345 if (sequence.contains(new Integer (uid))) { 1346 System.out.println("reading from disk"); 1347 1348 ObjectInputStream inAttrs = null; 1349 try { 1350 path = getPath( absoluteName, owner, rootPath ); 1351 System.out.println( "FileInputStream("+(path + File.separator + uid + ATTRIBUTES_EXTENSION)); 1352 inAttrs = new ObjectInputStream( new FileInputStream(path + File.separator + uid + ATTRIBUTES_EXTENSION)); 1353 System.out.println("inAttrs="+inAttrs); 1354 response = (SimpleMessageAttributes)inAttrs.readObject(); 1355 System.out.println("response="+response); 1356 if (response != null) { 1357 System.out.println("response.parts="+response.parts); 1358 if (response.parts != null) { 1359 System.out.println("response.parts.len="+response.parts.length); 1360 System.out.println("response.parts[0]="+response.parts[0]); 1361 } 1362 } 1363 setupLogger(response); 1364 } catch(Exception e) { 1365 getLogger().error("Error reading attributes from disc: " + e); 1366 e.printStackTrace(); 1367 throw new 1368 RuntimeException ("Exception caught while retrieving Message attributes: " 1369 + e); 1370 } finally { 1371 try { 1372 inAttrs.close(); 1373 } catch (IOException ie) { 1374 getLogger().error("Error closing streams: " + ie); 1375 } 1376 } 1377 getLogger().info("MessageAttributes for " + uid + " read from " + absoluteName); 1378 return response; 1379 } else { 1380 return null; 1381 } 1382 } 1383 1384 1393 public boolean updateMessageAttributes(MessageAttributes attrs, String user) 1394 throws AccessControlException, AuthorizationException { 1395 if (!hasKeepSeenRights(user)) { throw new AuthorizationException("Not authorized to store flags."); 1397 } 1398 int uid = attrs.getUID(); 1399 if (sequence.contains(new Integer (uid))) { 1400 1401 ObjectOutputStream outAttrs = null; 1403 try { 1404 path = getPath( absoluteName, owner, rootPath ); 1405 outAttrs = new ObjectOutputStream( new FileOutputStream(path + File.separator + uid + ATTRIBUTES_EXTENSION)); 1406 outAttrs.writeObject(attrs); 1407 outAttrs.close(); 1408 } catch(Exception e) { 1409 getLogger().error("Error writing message to disc: " + e); 1410 e.printStackTrace(); 1411 throw new 1412 RuntimeException ("Exception caught while storing Attributes: " 1413 + e); 1414 } finally { 1415 try { 1416 outAttrs.close(); 1417 } catch (IOException ie) { 1418 getLogger().error("Error closing streams: " + ie); 1419 } 1420 } 1421 getLogger().info("MessageAttributes for " + uid + " written in " + absoluteName); 1422 1423 return true; 1424 } else { 1425 return false; 1426 } 1427 } 1428 1429 1440 public synchronized String getFlags(int msn, String user) 1441 throws AccessControlException, AuthorizationException { 1442 if (!hasReadRights(user)) { throw new AuthorizationException("Not authorized to read."); 1444 } 1445 if (msn > sequence.size()) { 1446 return null; 1447 } else { 1448 int uid = ((Integer )sequence.get(msn - 1)).intValue(); 1449 return getFlagsUID(uid, user); 1450 } 1451 } 1452 1453 1464 public synchronized String getFlagsUID(int uid, String user) 1465 throws AccessControlException, AuthorizationException { 1466 if (!hasReadRights(user)) { throw new AuthorizationException("Not authorized to read."); 1468 } 1469 java.util.Iterator it = sequence.iterator(); 1470 while(it.hasNext()) 1471 System.out.println("FILEMESSAGES...."+it.next().toString()); 1472 1473 1474 if (!sequence.contains(new Integer (uid))) { 1475 System.out.println("SEQUENCENOOO"); 1476 return null; 1477 } else { 1478 System.out.println("FLAGSRETURNED"); 1479 Flags flags = readFlags(uid); 1480 return flags.getFlags(user); 1481 } 1482 } 1483 1496 public synchronized boolean setFlags(int msn, String user, String request) 1497 throws AccessControlException, AuthorizationException, 1498 IllegalArgumentException { 1499 if (!hasKeepSeenRights(user)) { throw new AuthorizationException("Not authorized to store any flags."); 1501 } 1502 if (msn > sequence.size()) { 1503 return false; 1504 } else { 1505 int uid = ((Integer )sequence.get(msn - 1)).intValue(); 1506 return setFlagsUID(uid, user, request); 1507 } 1508 } 1509 1510 1522 public synchronized boolean setFlagsUID(int uid, String user, String request) 1523 throws AccessControlException, AuthorizationException, 1524 IllegalArgumentException { 1525 if (!hasKeepSeenRights(user)) { throw new AuthorizationException("Not authorized to store any flags."); 1527 } 1528 if ((request.toUpperCase().indexOf("DELETED") != -1) && (!hasDeleteRights(user))) { throw new AuthorizationException("Not authorized to delete."); 1530 } 1531 if (sequence.contains(new Integer (uid))) { 1532 1533 Flags flags = readFlags(uid); 1534 boolean wasRecent = flags.isRecent(); 1535 boolean wasDeleted = flags.isDeleted(); 1536 boolean wasSeen = flags.isSeen(user); 1537 1538 if (flags.setFlags(request, user)) { 1539 1540 if (flags.isDeleted()) { 1541 if (! wasDeleted) { messagesForDeletion.add(new Integer (uid)); } 1542 } 1543 if (flags.isSeen(user) != wasSeen) { 1544 if (flags.isSeen(user)) { 1545 int previousOld = ((Integer )oldestUnseenMessage.get(user)).intValue(); 1546 if (uid == previousOld) { 1547 int newOld = findOldestUnseen(user, previousOld); 1548 oldestUnseenMessage.put(user, (new Integer (newOld))); 1549 } 1550 } else { if (uid < ((Integer )oldestUnseenMessage.get(user)).intValue()) { 1552 oldestUnseenMessage.put(user, (new Integer (uid))); 1553 } 1554 } 1555 } 1556 1557 writeFlags(uid, flags); 1558 getLogger().debug("Flags for message uid " + uid + " in " + absoluteName + " updated."); 1559 return true; 1560 } else { 1561 return false; 1562 } 1563 } else { 1564 return false; 1565 } 1566 1567 } 1568 1569 private int findOldestUnseen(String user, int previousOld) 1570 throws AccessControlException, AuthorizationException { 1571 int response = 0; try { 1573 ListIterator lit = sequence.listIterator(previousOld); 1574 boolean found = false; 1575 while (!found && lit.hasNext() ) { 1576 int uid = ((Integer )lit.next()).intValue(); 1577 Flags flags = readFlags(uid); 1578 if (!flags.isSeen(user)) { 1579 response = uid; 1580 found = true; 1581 } 1582 } 1583 }catch(Exception e) { 1584 }finally{ 1587 return response; 1588 } 1589 } 1590 1591 private Flags readFlags(int uid) { 1592 Flags response = null; 1593 if (sequence.contains(new Integer (uid))) { 1594 ObjectInputStream inFlags = null; 1595 try { 1596 path = getPath( absoluteName, owner, rootPath ); 1597 inFlags = new ObjectInputStream( new FileInputStream(path + File.separator + uid + FLAGS_EXTENSION)); 1598 response = (Flags)inFlags.readObject(); 1599 } catch(Exception e) { 1600 getLogger().error("Error reading flags from disc: " + e); 1601 e.printStackTrace(); 1602 throw new 1603 RuntimeException ("Exception caught while retrieving Message flags: " 1604 + e); 1605 } finally { 1606 try { 1607 inFlags.close(); 1608 } catch (IOException ie) { 1609 getLogger().error("Error closing streams: " + ie); 1610 } 1611 } 1612 getLogger().info("Flags for " + uid + " read from " + absoluteName); 1613 } 1614 return response; 1615 } 1616 1617 private boolean writeFlags(int uid, Flags flags) { 1618 if (sequence.contains(new Integer (uid))) { 1619 ObjectOutputStream outFlags = null; 1620 try { 1621 path = getPath( absoluteName, owner, rootPath ); 1622 outFlags = new ObjectOutputStream( new FileOutputStream(path + File.separator + uid + FLAGS_EXTENSION)); 1623 outFlags.writeObject(flags); 1624 outFlags.close(); 1625 } catch(Exception e) { 1626 getLogger().error("Error writing message to disc: " + e); 1627 e.printStackTrace(); 1628 throw new 1629 RuntimeException ("Exception caught while storing Flags: " 1630 + e); 1631 } finally { 1632 try { 1633 outFlags.close(); 1634 } catch (IOException ie) { 1635 getLogger().error("Error closing streams: " + ie); 1636 } 1637 } 1638 getLogger().info("Flags for " + uid + " written in " + absoluteName); 1639 writeMailbox(); 1640 return true; 1641 } else { 1642 writeMailbox(); 1643 return false; 1644 } 1645 } 1646 1647 1657 public synchronized boolean expunge(String user) 1658 throws AccessControlException, AuthorizationException { 1659 if (!hasDeleteRights(user)) { throw new AuthorizationException("Not authorized to delete for user '" + user + "'."); 1661 } 1662 Iterator it = messagesForDeletion.iterator(); 1663 1664 while (it.hasNext()) { 1665 Integer uidObj = (Integer )it.next(); 1666 int uid = uidObj.intValue(); 1667 if (sequence.contains(uidObj)) { 1668 try { 1669 try 1671 { 1672 MimeMessageWrapper message = retrieveUID(uid, user); 1673 System.out.println("(before)decrementing mailboxSize ("+getName()+") = " + mailboxSize); 1674 System.out.println("decre message.getMessageSize() = " + (int)message.getMessageSize()); 1675 mailboxSize -= (int)message.getMessageSize(); 1676 System.out.println("(after)decrementing mailboxSize ("+getName()+") = " + mailboxSize); 1677 } 1678 catch (MessagingException me) 1679 { 1680 } 1682 path = getPath( absoluteName, owner, rootPath ); 1684 final File msgFile = new File(path + File.separator + uid + MESSAGE_EXTENSION ); 1685 msgFile.delete(); 1686 final File attrFile = new File(path + File.separator + uid + ATTRIBUTES_EXTENSION ); 1687 attrFile.delete(); 1688 final File flagFile = new File(path + File.separator + uid + FLAGS_EXTENSION ); 1690 flagFile.delete(); 1691 sequence.remove(uidObj); 1693 } catch ( final Exception e ) { 1694 throw new RuntimeException ( "Exception caught while removing" + 1695 " a message: " + e ); 1696 } 1697 } 1698 } 1699 1700 for (int i = 0; i < sequence.size(); i++) { 1701 System.err.println("Message with msn " + i + " has uid " + sequence.get(i)); 1702 } 1703 writeMailbox(); 1704 return true; 1705 } 1706 1707 private void writeMailbox() { 1708 String mailboxRecordFile = path + File.separator + MAILBOX_FILE_NAME; 1709 ObjectOutputStream out = null; 1710 FileOutputStream fout = null; 1711 try { 1712 fout = new FileOutputStream( mailboxRecordFile ); 1713 out = new ObjectOutputStream( fout ); 1714 out.writeObject(this); 1715 out.flush(); 1716 out.close(); 1717 fout.flush(); 1718 fout.close(); 1719 } catch(Exception e) { 1720 if (out != null) { 1721 try { 1722 out.close(); 1723 } catch (Exception ignored) { 1724 } 1725 } 1726 if (fout != null) { 1727 try { 1728 fout.close(); 1729 } catch (Exception ignored) { 1730 } 1731 } 1732 e.printStackTrace(); 1733 throw new 1734 RuntimeException ("Exception caught while storing Mailbox: " + e); 1735 } 1736 getLogger().info("FileMailbox written: " + absoluteName); 1737 } 1738 1739 1740 1746 public List listUIDs(String user) { 1747 return new ArrayList(Collections.unmodifiableList(sequence)); 1748 } 1749 1750 public Set getUsersWithLookupRights() { 1751 Set response = new HashSet(); 1752 Iterator it = acl.keySet().iterator(); 1753 while (it.hasNext()) { 1754 String user = (String ) it.next(); 1755 boolean[] rights = (boolean[]) acl.get(user); 1756 if (rights[LOOKUP] == true) { 1757 response.add(user); 1758 } 1759 } 1760 return response; 1761 } 1762 1763 public Set getUsersWithReadRights() { 1764 Set response = new HashSet(); 1765 Iterator it = acl.keySet().iterator(); 1766 while (it.hasNext()) { 1767 String user = (String ) it.next(); 1768 boolean[] rights = (boolean[]) acl.get(user); 1769 if (rights[READ] == true) { 1770 response.add(user); 1771 } 1772 } 1773 return response; 1774 } 1775 1776 public Map getUnseenByUser() { 1777 Map response = new HashMap(); 1778 Iterator it = oldestUnseenMessage.keySet().iterator(); 1779 while (it.hasNext()) { 1780 String user = (String ) it.next(); 1781 Integer uidObj = ((Integer )oldestUnseenMessage.get(user)); 1782 int oldUID = uidObj.intValue(); 1783 if (oldUID == 0) { 1784 response.put(user, uidObj); 1785 } else { 1786 int count = 0; 1787 ListIterator lit 1788 = sequence.listIterator(sequence.indexOf(uidObj)); 1789 while (lit.hasNext() ) { 1790 int uid = ((Integer )lit.next()).intValue(); 1791 Flags flags = readFlags(uid); 1792 if (!flags.isSeen(user)) { 1793 count ++; 1794 } 1795 } 1796 response.put(user, new Integer (count)); 1797 } 1798 } 1799 return response; 1800 } 1801 1802 1803 public InternetHeaders getInternetHeaders(int msn, String user) 1804 throws AccessControlException, AuthorizationException { 1805 if (!hasReadRights(user)) { throw new AuthorizationException("Not authorized to read."); 1807 } 1808 if (msn > sequence.size()) { 1809 return null; 1810 } else { 1811 int uid = ((Integer )sequence.get(msn - 1)).intValue(); 1812 return getInternetHeadersUID(uid, user); 1813 } 1814 } 1815 1816 public InternetHeaders getInternetHeadersUID(int uid, String user) 1817 throws AccessControlException, AuthorizationException { 1818 InternetHeaders response = null; 1819 if (sequence.contains(new Integer (uid))) { 1820 BufferedInputStream inMsg = null; 1821 try { 1822 inMsg = new BufferedInputStream( new FileInputStream(path + File.separator + uid + MESSAGE_EXTENSION)); 1823 response = new InternetHeaders (inMsg); 1824 inMsg.close(); 1825 } catch(Exception e) { 1826 getLogger().error("Error reading headers of message from disc: " + e); 1827 e.printStackTrace(); 1828 throw new 1829 RuntimeException ("Exception caughtt while retrieving InternetHeaders: " + e); 1830 } finally { 1831 try { 1832 inMsg.close(); 1833 } catch (IOException ie) { 1834 getLogger().error("Error closing streams: " + ie); 1835 } 1836 } 1837 getLogger().info("InternetHeaders for message " + uid + " read from " 1838 + absoluteName); 1839 return response; 1840 } else { 1841 return null; 1842 } 1843 } 1844 1845 1848 public boolean isSubscribed( String userName ) 1849 { 1850 return subscribedUsers.contains( userName.toLowerCase() ); 1851 } 1852 1853 1856 public void subscribe( String userName ) 1857 { 1858 subscribedUsers.add( userName.toLowerCase() ); 1859 } 1860 1861 1864 public void unsubscribe( String userName ) 1865 { 1866 subscribedUsers.remove( userName.toLowerCase() ); 1867 } 1868} 1869 1870 1871 1872 | Popular Tags |