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
103 if (mc != null) try {
104 size += mc.getMessageSize();
105 } catch (Throwable e) {
106
107
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 }