📄 jameshost.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.framework.activity.Initializable;import org.apache.avalon.framework.component.Component;import org.apache.avalon.framework.component.ComponentManager;import org.apache.avalon.framework.component.Composable;import org.apache.avalon.framework.configuration.Configurable;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.context.Contextualizable;import org.apache.avalon.framework.logger.AbstractLogEnabled;import org.apache.james.imapserver.AccessControlException;import org.apache.james.imapserver.AuthorizationException;import org.apache.james.services.MailServer;import org.apache.james.services.UsersRepository;import org.apache.james.services.UsersStore;import org.apache.james.util.Assert;import java.io.File;import java.io.FileInputStream;import java.io.ObjectInputStream;import java.util.*;/** * A single host that has an IMAP4rev1 messaging server. * There should be one instance of this class per instance of James. * An IMAP messaging system may span more than one host. * <p><code>String</code> parameters representing mailbox names must be the * full hierarchical name of the target, with namespace, as used by the * specified user. Examples: * '#mail.Inbox' or '#shared.finance.Q2Earnings'. * <p>An imap Host must keep track of existing and deleted mailboxes. * * References: rfc 2060 * @version 0.2 on 04 Aug 2002 * @see FolderRecord * @see RecordRepository */public class JamesHost extends AbstractLogEnabled implements Host, Component, Composable, Configurable, Contextualizable, Initializable { private Context context; private Configuration conf; private ComponentManager compMgr; private String rootPath; // ends with File.separator private IMAPSystem imapSystem; private UsersRepository localUsers; private RecordRepository recordRep; private OpenMailboxes openMailboxes; //maps absoluteName to ACLMailbox public static final String HIERARCHY_SEPARATOR = "."; public static final char HIERARCHY_SEPARATOR_CHAR = '.'; public static final String NAMESPACE_TOKEN = "#"; public static final String PRIVATE_NAMESPACE_PREFIX = ""; private static final String USER_NAMESPACE = "user"; private static final String SHARE_NAMESPACE = "share"; public static final String USER_NAMESPACE_PREFIX = NAMESPACE_TOKEN + USER_NAMESPACE; public static final String SHARE_NAMESPACE_PREFIX = NAMESPACE_TOKEN + SHARE_NAMESPACE; /* * Note on implemented namespaces. * 3 namespaces are (partially) implemented. * 1) Private namespace ie access to a user's own mailboxes. * Full mailbox names (ie what user sees) of the form: * #mail.Inbox or #mail.apache.James * Absolute names of the form: * #mail.fred.flintstone.Inbox or #mail.fred.flintstone.apache.James * 2) Other users namespace ie access to other users mailboxes * subject to access control, of course * Full mailbox names (ie what user sees) of the form: * #users.captain.scarlet.Inbox or #users.RobinHood.apache.James * Absolute names of the form: * #mail.captain.scarlet.Inbox or #mail.RobinHood.apache.James * 3) Shared mailboxes * not fully implemented. * Full mailbox names (ie what user sees) of the form: * #shared.projectAlpha.masterplan or #shared.customerservice.Inbox * Absolute names of the form: * #shared.projectAlpha.masterplan or #shared.customerservice.Inbox */ /* * Note on filename extensions * Records in AvalonRecordRepository - no extension * Mailboxes - mbr * MimeMessage - msg * MessageAttributes - att */ /* No constructor */ /** * @see org.apache.avalon.framework.context.Contextualizable#contextualize(Context) */ public void contextualize( Context context ) { this.context = context; } /** * @see org.apache.avalon.framework.component.Composable#compose(ComponentManager) */ public void compose( ComponentManager comp ) { compMgr = comp; } /** * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration) */ public void configure( Configuration conf ) throws ConfigurationException { this.conf = conf; } /** * @see org.apache.avalon.framework.activity.Initializable#initialize() */ public void initialize() throws Exception { getLogger().info( "JamesHost init..." ); imapSystem = (IMAPSystem) compMgr.lookup( IMAPSystem.ROLE ); UsersStore usersStore = (UsersStore) compMgr.lookup( "org.apache.james.services.UsersStore" ); localUsers = usersStore.getRepository( "LocalUsers" ); String recordRepDest = conf.getChild( "recordRepository" ).getValue(); recordRep = new DefaultRecordRepository(); setupLogger( recordRep, "recordRep" ); recordRep.setPath( recordRepDest ); getLogger().info( "AvalonRecordRepository opened at " + recordRepDest ); rootPath = conf.getChild( "mailboxRepository" ).getValue(); if ( !rootPath.endsWith( File.separator ) ) { rootPath = rootPath + File.separator; } prepareDir( rootPath ); // Create directories for user and shared mailboxes. String usersPath = getPath( USER_NAMESPACE_PREFIX ); prepareDir( usersPath ); String sharePath = getPath( SHARE_NAMESPACE_PREFIX ); prepareDir( sharePath ); getLogger().info( "IMAP Mailbox Repository opened at " + rootPath ); openMailboxes = new OpenMailboxes(); // how big should this start? getLogger().info( "JamesHost ...init end" ); } /** * Checks that the Directory provided exists and is writeable, creating it if it is not. */ private void prepareDir( String dir ) { File newFolder = new File( dir ); if ( !newFolder.isDirectory() ) { if ( !newFolder.mkdir() ) { throw new RuntimeException( "Error: Cannot create directory: " + dir ); } } else if ( !newFolder.canWrite() ) { throw new RuntimeException( "Error: Cannot write to directory: " + dir ); } } /** * Establishes whether this host is the Home Server for the specified user. * Used during login to decide whether a LOGIN_REFERRAL has to be sent to * the client. * * @param username an email address * @return true if inbox (and private mailfolders) are accessible through * this host. */ public boolean isHomeServer( String username ) { return localUsers.contains( username ); } /** * Establishes if the specified user can access any mailboxes on this host. * Used during login process to decide what sort of LOGIN-REFERRAL must be * sent to client. * * @param username an email address * @return true if the specified user has at least read access to any * mailboxes on this host. */ public boolean hasLocalAccess( String username ) { return localUsers.contains( username ); } /** * Returns a reference to an existing Mailbox. The requested mailbox * must already exists on this server and the requesting user must have at * least lookup rights. * * @param user email address on whose behalf the request is made. * @param mailboxName String name of the target. * @return an Mailbox reference. * @throws AccessControlException if the user does not have at least * lookup rights. * @throws MailboxException if mailbox does not exist locally. */ public synchronized ACLMailbox getMailbox( String user, String mailboxName ) throws AccessControlException, MailboxException { Assert.isTrue( Assert.ON && user != null && user.length() > 0 && mailboxName != null ); getLogger().debug( "Getting mailbox " + mailboxName + " for " + user ); String absoluteName = getAbsoluteMailboxName( user, mailboxName ); return getAbsoluteMailbox( user, absoluteName ); } private synchronized ACLMailbox getAbsoluteMailbox( String user, String absoluteName ) throws AccessControlException, MailboxException { Assert.isTrue( Assert.ON && user != null && absoluteName.startsWith( NAMESPACE_TOKEN ) ); ACLMailbox mailbox = null; FolderRecord record = null; // Has a folder with this name ever been created? System.out.println("THISISTHE ABSOLUTENAME IN getAbsoluteMailbox " + absoluteName); if ( !recordRep.containsRecord( absoluteName ) ) { throw new MailboxException( "Mailbox: " + absoluteName + " has never been created.", MailboxException.NOT_LOCAL ); } else { record = recordRep.retrieve( absoluteName ); if ( record.isDeleted() ) { throw new MailboxException( "Mailbox has been deleted", MailboxException.LOCAL_BUT_DELETED ); } else if ( openMailboxes.contains( absoluteName ) ) { mailbox = openMailboxes.getMailbox( absoluteName ); if ( ! mailbox.hasLookupRights( user ) ) { throw new AccessControlException( "No lookup rights." ); } openMailboxes.addReference( absoluteName ); return mailbox; } else { String owner = record.getUser(); String key = getPath( absoluteName ); ObjectInputStream in = null; try { // SK:UPDATE in = new ObjectInputStream( new FileInputStream( key + File.separator + FileMailbox.MAILBOX_FILE_NAME ) ); mailbox = (FileMailbox) in.readObject(); setupLogger( mailbox ); mailbox.configure( conf ); mailbox.contextualize( context ); mailbox.compose( compMgr ); mailbox.reinitialize(); } catch ( Exception e ) { e.printStackTrace(); throw new RuntimeException( "Exception caught while reading FileMailbox: " + e ); } finally { if ( in != null ) { try { in.close(); } catch ( Exception ignored ) { } } notifyAll(); } if ( !mailbox.hasLookupRights( user ) ) { throw new AccessControlException( "No lookup rights." ); } openMailboxes.addMailbox( absoluteName, mailbox ); return mailbox; } } } /** * Returns a reference to a newly created Mailbox. The request should * specify a mailbox that does not already exist on this server, that * could exist on this server and that the user has rights to create. * If a system allocates different namespaces to different hosts then a * request to create a mailbox in a namespace not served by this host would * be an error. * It is an error to create a mailbox with the name of a mailbox that has * been deleted, if that name is still in use. * * @param user email address on whose behalf the request is made. * @param mailboxName String name of the target * @return an Mailbox reference. * @throws AccessControlException if the user does not have lookup rights * for parent or any needed ancestor folder
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -