001: /****************************************************************
002: * Licensed to the Apache Software Foundation (ASF) under one *
003: * or more contributor license agreements. See the NOTICE file *
004: * distributed with this work for additional information *
005: * regarding copyright ownership. The ASF licenses this file *
006: * to you under the Apache License, Version 2.0 (the *
007: * "License"); you may not use this file except in compliance *
008: * with the License. You may obtain a copy of the License at *
009: * *
010: * http://www.apache.org/licenses/LICENSE-2.0 *
011: * *
012: * Unless required by applicable law or agreed to in writing, *
013: * software distributed under the License is distributed on an *
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
015: * KIND, either express or implied. See the License for the *
016: * specific language governing permissions and limitations *
017: * under the License. *
018: ****************************************************************/package org.apache.james.transport.matchers;
019:
020: import org.apache.avalon.framework.service.ServiceException;
021: import org.apache.avalon.framework.service.ServiceManager;
022: import org.apache.james.Constants;
023: import org.apache.james.services.JamesUser;
024: import org.apache.james.services.MailRepository;
025: import org.apache.james.services.MailServer;
026: import org.apache.james.services.UsersRepository;
027: import org.apache.mailet.Mail;
028: import org.apache.mailet.MailAddress;
029: import org.apache.mailet.MailetContext;
030:
031: import javax.mail.MessagingException;
032:
033: import java.util.Iterator;
034:
035: /**
036: * <P>Experimental: Abstract matcher checking whether a recipient has exceeded a maximum allowed
037: * <I>storage</I> quota for messages standing in his inbox.</P>
038: * <P>"Storage quota" at this level is still an abstraction whose specific interpretation
039: * will be done by subclasses (e.g. could be specific for each user or common to all of them).</P>
040: *
041: * <P>This matcher need to calculate the mailbox size everytime it is called. This can slow down things if there are many mails in
042: * the mailbox. Some users also report big problems with the matcher if a JDBC based mailrepository is used. </P>
043: *
044: * @version CVS $Revision: 494058 $ $Date: 2007-01-08 14:18:22 +0100 (Mo, 08 Jan 2007) $
045: * @since 2.2.0
046: */
047: abstract public class AbstractStorageQuota extends AbstractQuotaMatcher {
048:
049: private MailServer mailServer;
050:
051: /** The user repository for this mail server. Contains all the users with inboxes
052: * on this server.
053: */
054: private UsersRepository localusers;
055:
056: /**
057: * Standard matcher initialization.
058: * Overriding classes must do a <CODE>super.init()</CODE>.
059: */
060: public void init() throws MessagingException {
061: super .init();
062: ServiceManager compMgr = (ServiceManager) getMailetContext()
063: .getAttribute(Constants.AVALON_COMPONENT_MANAGER);
064: try {
065: mailServer = (MailServer) compMgr.lookup(MailServer.ROLE);
066: } catch (ServiceException e) {
067: log("Exception in getting the MailServer: "
068: + e.getMessage() + e.getKey());
069: }
070: try {
071: localusers = (UsersRepository) compMgr
072: .lookup(UsersRepository.ROLE);
073: } catch (ServiceException e) {
074: log("Exception in getting the UsersStore: "
075: + e.getMessage() + e.getKey());
076: }
077: }
078:
079: /**
080: * Checks the recipient.
081: * Does a <CODE>super.isRecipientChecked</CODE> and checks that the recipient
082: * is a known user in the local server.
083: * If a subclass overrides this method it should "and" <CODE>super.isRecipientChecked</CODE>
084: * to its check.
085: *
086: * @param recipient the recipient to check
087: */
088: protected boolean isRecipientChecked(MailAddress recipient)
089: throws MessagingException {
090: MailetContext mailetContext = getMailetContext();
091: return super .isRecipientChecked(recipient)
092: && (mailetContext.isLocalServer(recipient.getHost()) && mailetContext
093: .isLocalUser(recipient.getUser()));
094: }
095:
096: /**
097: * Gets the storage used in the recipient's inbox.
098: *
099: * @param recipient the recipient to check
100: */
101: protected long getUsed(MailAddress recipient, Mail _)
102: throws MessagingException {
103: long size = 0;
104: MailRepository userInbox = mailServer
105: .getUserInbox(getPrimaryName(recipient.getUser()));
106: for (Iterator it = userInbox.list(); it.hasNext();) {
107: String key = (String) it.next();
108: Mail mc = userInbox.retrieve(key);
109: // Retrieve can return null if the mail is no longer in the store.
110: if (mc != null)
111: try {
112: size += mc.getMessageSize();
113: } catch (Throwable e) {
114: // MailRepository.retrieve() does NOT lock the message.
115: // It could be deleted while we're looping.
116: log("Exception in getting message size: "
117: + e.getMessage());
118: }
119: }
120: return size;
121: }
122:
123: /**
124: * Gets the main name of a local customer, handling aliases.
125: *
126: * @param originalUsername the user name to look for; it can be already the primary name or an alias
127: * @return the primary name, or originalUsername unchanged if not found
128: */
129: protected String getPrimaryName(String originalUsername) {
130: String username;
131: try {
132: username = localusers.getRealName(originalUsername);
133: JamesUser user = (JamesUser) localusers
134: .getUserByName(username);
135: if (user.getAliasing()) {
136: username = user.getAlias();
137: }
138: } catch (Exception e) {
139: username = originalUsername;
140: }
141: return username;
142: }
143:
144: }
|