📄 filemailbox.java
字号:
/*********************************************************************** * Copyright (c) 2000-2004 The Apache Software Foundation. * * All rights reserved. * * ------------------------------------------------------------------- * * Licensed under the Apache License, Version 2.0 (the "License"); you * * may not use this file except in compliance with the License. You * * may obtain a copy of the License at: * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software * * distributed under the License is distributed on an "AS IS" BASIS, * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * * implied. See the License for the specific language governing * * permissions and limitations under the License. * ***********************************************************************/package org.apache.james.imapserver;import org.apache.avalon.cornerstone.services.store.ObjectRepository;import org.apache.avalon.cornerstone.services.store.Store;import org.apache.avalon.framework.component.ComponentManager;import org.apache.avalon.framework.configuration.Configuration;import org.apache.avalon.framework.configuration.ConfigurationException;import org.apache.avalon.framework.context.Context;import org.apache.avalon.framework.logger.AbstractLogEnabled;import org.apache.avalon.phoenix.BlockContext;import org.apache.james.imapserver.AccessControlException;import org.apache.james.imapserver.AuthorizationException;import org.apache.james.core.MimeMessageWrapper;import org.apache.james.services.UsersRepository;import org.apache.james.services.UsersStore;import org.apache.james.util.Assert;import javax.mail.internet.InternetHeaders;import javax.mail.internet.MimeMessage;import javax.mail.MessagingException;import java.io.*;import java.util.*;/** * Object representing an IMAP4rev1 mailbox (folder) on a local file system. * The mailbox contains messages, message attributes and an access control * list. * * <p> from Interface Mailbox * * <p>Mailbox Related Flags (rfc2060 name attributes) * <br> \Noinferiors It is not possible for any child levels of hierarchy * to exist under this name; no child levels exist now and none can be created * in the future. * <br> \Noselect It is not possible to use this name as a selectable * mailbox. * <br> \Marked The mailbox has been marked "interesting" by the * server; the mailbox probably contains messages that have been added since * the last time the mailbox was selected. * <br> \Unmarked The mailbox does not contain any additional * messages since the last time the mailbox was selected. * * <p>Message related flags. * <br>The flags allowed per message are specific to each mailbox. * <br>The minimum list (rfc2060 system flags) is: * <br> \Seen Message has been read * <br> \Answered Message has been answered * <br> \Flagged Message is "flagged" for urgent/special attention * <br> \Deleted Message is "deleted" for removal by later EXPUNGE * <br> \Draft Message has not completed composition (marked as a draft). * <br> \Recent Message is "recently" arrived in this mailbox. This * session is the first session to have been notified about this message; * subsequent sessions will not see \Recent set for this message. This flag * can not be altered by the client. * <br> If it is not possible to determine whether or not this * session is the first session to be notified about a message, then that * message SHOULD be considered recent. * * <p> From interface ACL </p> * * The standard rights in RFC2086 are: * <br>l - lookup (mailbox is visible to LIST/LSUB commands) * <br>r - read (SELECT the mailbox, perform CHECK, FETCH, PARTIAL, SEARCH, * COPY from mailbox) * <br>s - keep seen/unseen information across sessions (STORE SEEN flag) * <br>w - write (STORE flags other than SEEN and DELETED) * <br>i - insert (perform APPEND, COPY into mailbox) * <br>p - post (send mail to submission address for mailbox, not enforced by * IMAP4 itself) * <br>c - create (CREATE new sub-mailboxes in any implementation-defined * hierarchy) * <br>d - delete (STORE DELETED flag, perform EXPUNGE) * <br>a - administer (perform SETACL) * * <p> Serialization. Not all fields are serialized. Dispose() must be called to * write serialized fiels to disc before finishing with this object. * * <p> Deserialization. On recover from disc, configure, compose, * contextualize and reInit must be called before object is ready for use. * * Reference: RFC 2060 * @version 0.2 on 04 Aug 2002 */public class FileMailbox extends AbstractLogEnabled implements ACLMailbox, Serializable { public static final String MAILBOX_FILE_NAME = "mailbox.mbr"; private static final String MESSAGE_EXTENSION = ".msg"; private static final String ATTRIBUTES_EXTENSION = ".att"; private static final String FLAGS_EXTENSION = ".flags"; private static final int NUMBER_OF_RIGHTS = 9; // Map string identities to boolean[NUMBER_OF_RIGHTS] arrays of rights //The rights are, in order: l,r,s,w,i,p,c,d,a private static final int LOOKUP = 0; private static final int READ = 1; private static final int KEEP_SEEN = 2; private static final int WRITE = 3; private static final int INSERT = 4; private static final int POST = 5; private static final int CREATE = 6; private static final int DELETE = 7; private static final int ADMIN = 8; private static final boolean[] NO_RIGHTS = {false, false, false, false, false, false, false, false, false}; private static final boolean[] ALL_RIGHTS = {true, true, true, true, true, true, true, true, true}; private static final String DENY_ACCESS = "Access denied by ACL"; private static final String DENY_AUTH = "Action not authorized for: "; private static final String OPTIONAL_RIGHTS = "l r s w i p c d a"; private static final char[] DELETE_MODS = {'-', 'l', 'r', 's', 'w', 'i', 'p', 'c', 'd', 'a'}; /* Transient fields - reInit must be called on recover from disc. */ private transient BlockContext context; private transient Configuration conf; private transient ComponentManager compMgr; private transient UsersRepository localUsers; private transient HashSet listeners; /* Serialized fileds */ private String path; // does not end with File.separator private String rootPath; // does not end with File.separator private File directory ; private String owner; private String absoluteName; private Map acl; private String name; private int uidValidity; private int mailboxSize; // octets private boolean inferiorsAllowed; private boolean marked; private boolean notSelectableByAnyone; // Sets the UID for all Mailboxes private static HighestUID highestUID; // The message sequence number of a msg is its index in List sequence + 1 private List sequence; //List of UIDs of messages in mailbox // Set of UIDs of messages with recent flag set private Set recentMessages; // Set of UIDs of messages with delete flag set private Set messagesForDeletion; //map of user String to Integer uid, 0 for no unseen messages private Map oldestUnseenMessage; // Set of subscribed users. private Set subscribedUsers = new HashSet(1000); public void configure(Configuration conf) throws ConfigurationException { this.conf = conf; } public void contextualize(Context context) { this.context = (BlockContext)context; } public void compose(ComponentManager comp) { compMgr = comp; } public void prepareMailbox(String user, String absName, String initialAdminUser, int uidValidity ) { Assert.isTrue( Assert.ON && user != null && user.length() > 0 ); owner = user; Assert.isTrue( Assert.ON && absName != null && (absName.length() > 0)); absoluteName = absName; Assert.isTrue( Assert.ON && initialAdminUser != null && initialAdminUser.length() > 0 ); acl = new HashMap(7); acl.put(initialAdminUser, ALL_RIGHTS); Assert.isTrue( Assert.ON && uidValidity > 0 ); this.uidValidity = uidValidity; } public void initialize() throws Exception { mailboxSize = 0; inferiorsAllowed = true; marked = false; notSelectableByAnyone = false; oldestUnseenMessage = new HashMap(); listeners = new HashSet(); sequence = new ArrayList(); recentMessages = new HashSet(); messagesForDeletion = new HashSet(); getLogger().info("FileMailbox init for " + absoluteName); UsersStore usersStore = (UsersStore)compMgr.lookup( "org.apache.james.services.UsersStore" ); localUsers = usersStore.getRepository("LocalUsers"); rootPath = conf.getChild( "mailboxRepository" ).getValue(); if (!rootPath.endsWith(File.separator)) { rootPath = rootPath + File.separator; } path = getPath( absoluteName, owner, rootPath ); name = absoluteName.substring(absoluteName.lastIndexOf( JamesHost.HIERARCHY_SEPARATOR ) + 1); if (name.equals(owner)) { name = ""; } //Check for writable directory getLogger().info("MailboxDir " + path); System.out.println("MailboxDir TO WRITE TO " + path); File mailboxDir = new File(path); if (mailboxDir.exists()) { throw new RuntimeException("Error: Attempt to overwrite mailbox directory at " + path); } else if (! mailboxDir.mkdir()){ throw new RuntimeException("Error: Cannot create mailbox directory at " + path); } else if (!mailboxDir.canWrite()) { throw new RuntimeException("Error: Cannot write to directory at " + path); } writeMailbox(); getLogger().info("FileMailbox init complete: " + absoluteName); } /** * Return the file-system path to a given absoluteName mailbox. * * @param absoluteName the user-independent name of the mailbox * @param owner string name of owner of mailbox */ private String getPath( String absoluteName, String owner, String rootPath ) { Assert.isTrue( Assert.ON && absoluteName.startsWith( JamesHost.NAMESPACE_TOKEN ) ); // Remove the leading '#' and replace Hierarchy separators with file separators. String filePath = absoluteName.substring( JamesHost.NAMESPACE_TOKEN.length() ); filePath = filePath.replace( JamesHost.HIERARCHY_SEPARATOR_CHAR, File.separatorChar ); return rootPath + filePath; } /** * Re-initialises mailbox after reading from file-system. Cannot assume that this is the same instance of James that wrote it. * * <p> Contract is that re-init must be called after configure, contextualize, compose. */ public void reinitialize() throws Exception { listeners = new HashSet(); getLogger().info("FileMailbox reInit for " + absoluteName); UsersStore usersStore = (UsersStore)compMgr.lookup( "org.apache.james.services.UsersStore" ); localUsers = usersStore.getRepository("LocalUsers"); rootPath = conf.getChild("mailboxRepository").getValue(); if (!rootPath.endsWith(File.separator)) { rootPath = rootPath + File.separator; } path = getPath( absoluteName, owner, rootPath ); } /** * Call when host has finished with a mailbox. * This is really a stop rather than destroy. * Writes current mailbox object to disc. */ public void dispose() { writeMailbox(); getLogger().info("FileMailbox object destroyed: " + absoluteName); } /** * Permanently deletes the mailbox. */ public void removeMailbox() { // First delete the mailbox file path = getPath( absoluteName, owner, rootPath ); String mailboxRecordFile = path + File.separator + MAILBOX_FILE_NAME; File mailboxRecord = new File( mailboxRecordFile ); Assert.isTrue( Assert.ON && mailboxRecord.exists() && mailboxRecord.isFile() ); mailboxRecord.delete(); // Check for empty directory before deleting. File mailboxDir = new File(path); Assert.isTrue( Assert.ON && mailboxDir.exists() ); Assert.isTrue( Assert.ON && mailboxDir.isDirectory() ); Assert.isTrue( Assert.ON && mailboxDir.list().length == 0 ); mailboxDir.delete(); } /** * Renames this Mailbox. * @param usernmae The Username who calles this Command. * @param newmailboxname The new name for this Mailbox. * @return true if everythink was sucessfully, else false. * @throws MailboxException if mailbox does not exist locally. * @throws AuthorizationException if the user has no rights for changing the name of the Mailbox. */ public boolean renameMailbox(String username, String newmailboxname) throws MailboxException, AuthorizationException { try { path = getPath( absoluteName, owner, rootPath ); StringTokenizer strt = new StringTokenizer(newmailboxname,"."); String lastnameofmailbox=""; while(strt.hasMoreTokens()) lastnameofmailbox=strt.nextToken(); File fle = new File(this.path); fle.renameTo(new File(fle.getParent(), lastnameofmailbox)); this.path=fle.getParent()+File.separator+lastnameofmailbox;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -