View Javadoc

1   /*****************************************************************
2    * Licensed to the Apache Software Foundation (ASF) under one   *
3    * or more contributor license agreements.  See the NOTICE file *
4    * distributed with this work for additional information        *
5    * regarding copyright ownership.  The ASF licenses this file   *
6    * to you under the Apache License, Version 2.0 (the            *
7    * "License"); you may not use this file except in compliance   *
8    * with the License.  You may obtain a copy of the License at   *
9    *                                                              *
10   *   http://www.apache.org/licenses/LICENSE-2.0                 *
11   *                                                              *
12   * Unless required by applicable law or agreed to in writing,   *
13   * software distributed under the License is distributed on an  *
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15   * KIND, either express or implied.  See the License for the    *
16   * specific language governing permissions and limitations      *
17   * under the License.                                           *
18   ****************************************************************/
19  
20  package org.apache.james.transport.matchers;
21  
22  import org.apache.avalon.framework.service.ServiceException;
23  import org.apache.avalon.framework.service.ServiceManager;
24  import org.apache.james.Constants;
25  import org.apache.james.services.JamesUser;
26  import org.apache.james.services.MailRepository;
27  import org.apache.james.services.MailServer;
28  import org.apache.james.services.UsersRepository;
29  import org.apache.mailet.Mail;
30  import org.apache.mailet.MailAddress;
31  import org.apache.mailet.MailetContext;
32  
33  import javax.mail.MessagingException;
34  
35  import java.util.Iterator;
36  
37  /***
38   * <P>Experimental: Abstract matcher checking whether a recipient has exceeded a maximum allowed
39   * <I>storage</I> quota for messages standing in his inbox.</P>
40   * <P>"Storage quota" at this level is still an abstraction whose specific interpretation
41   * will be done by subclasses (e.g. could be specific for each user or common to all of them).</P> 
42   *
43   * <P>This matcher need to calculate the mailbox size everytime it is called. This can slow down things if there are many mails in
44   * the mailbox. Some users also report big problems with the matcher if a JDBC based mailrepository is used. </P>
45   *
46   * @version CVS $Revision: 494058 $ $Date: 2007-01-08 13:18:22 +0000 (Mon, 08 Jan 2007) $
47   * @since 2.2.0
48   */
49  abstract public class AbstractStorageQuota extends AbstractQuotaMatcher { 
50  
51      private MailServer mailServer;
52  
53      /*** The user repository for this mail server.  Contains all the users with inboxes
54       * on this server.
55       */
56      private UsersRepository localusers;
57  
58      /***
59       * Standard matcher initialization.
60       * Overriding classes must do a <CODE>super.init()</CODE>.
61       */
62      public void init() throws MessagingException {
63          super.init();
64          ServiceManager compMgr = (ServiceManager)getMailetContext().getAttribute(Constants.AVALON_COMPONENT_MANAGER);
65          try {
66              mailServer = (MailServer) compMgr.lookup(MailServer.ROLE);
67          } catch (ServiceException e) {
68              log("Exception in getting the MailServer: " + e.getMessage() + e.getKey());
69          }
70          try {
71              localusers = (UsersRepository) compMgr.lookup(UsersRepository.ROLE);
72          } catch (ServiceException e) {
73              log("Exception in getting the UsersStore: " + e.getMessage() + e.getKey());
74          }
75      }
76  
77      /*** 
78       * Checks the recipient.
79       * Does a <CODE>super.isRecipientChecked</CODE> and checks that the recipient
80       * is a known user in the local server.
81       * If a subclass overrides this method it should "and" <CODE>super.isRecipientChecked</CODE>
82       * to its check.
83       *
84       * @param recipient the recipient to check
85       */    
86      protected boolean isRecipientChecked(MailAddress recipient) throws MessagingException {
87          MailetContext mailetContext = getMailetContext();
88          return super.isRecipientChecked(recipient) && (mailetContext.isLocalServer(recipient.getHost()) && mailetContext.isLocalUser(recipient.getUser()));
89      }
90  
91      /*** 
92       * Gets the storage used in the recipient's inbox.
93       *
94       * @param recipient the recipient to check
95       */    
96      protected long getUsed(MailAddress recipient, Mail _) throws MessagingException {
97          long size = 0;
98          MailRepository userInbox = mailServer.getUserInbox(getPrimaryName(recipient.getUser()));
99          for (Iterator it = userInbox.list(); it.hasNext(); ) {
100             String key = (String) it.next();
101             Mail mc = userInbox.retrieve(key);
102             // Retrieve can return null if the mail is no longer in the store.
103             if (mc != null) try {
104                 size += mc.getMessageSize();
105             } catch (Throwable e) {
106                 // MailRepository.retrieve() does NOT lock the message.
107                 // It could be deleted while we're looping.
108                 log("Exception in getting message size: " + e.getMessage());
109             }
110         }
111         return size;
112     }
113 
114     /***
115      * Gets the main name of a local customer, handling aliases.
116      *
117      * @param originalUsername the user name to look for; it can be already the primary name or an alias
118      * @return the primary name, or originalUsername unchanged if not found
119      */
120     protected String getPrimaryName(String originalUsername) {
121         String username;
122         try {
123             username = localusers.getRealName(originalUsername);
124             JamesUser user = (JamesUser) localusers.getUserByName(username);
125             if (user.getAliasing()) {
126                 username = user.getAlias();
127             }
128         }
129         catch (Exception e) {
130             username = originalUsername;
131         }
132         return username;
133     }
134     
135 }