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  
21  
22  package org.apache.james.impl.vut;
23  
24  import java.util.ArrayList;
25  import java.util.Collection;
26  import java.util.HashMap;
27  import java.util.Iterator;
28  import java.util.Map;
29  import java.util.StringTokenizer;
30  
31  import org.apache.james.api.vut.VirtualUserTable;
32  import org.apache.james.util.XMLResources;
33  import org.apache.mailet.MailAddress;
34  import org.apache.oro.text.regex.MalformedPatternException;
35  import org.apache.oro.text.regex.MatchResult;
36  import org.apache.oro.text.regex.Pattern;
37  import org.apache.oro.text.regex.Perl5Compiler;
38  import org.apache.oro.text.regex.Perl5Matcher;
39  
40  /**
41   * This helper class contains methods for the VirtualUserTable implementations
42   */
43  public class VirtualUserTableUtil {
44  
45      private VirtualUserTableUtil() {}
46      
47  
48      public static String QUERY = "select VirtualUserTable.target_address from VirtualUserTable, VirtualUserTable as VUTDomains where (VirtualUserTable.user like ? or VirtualUserTable.user like '\\%') and (VirtualUserTable.domain like ? or (VirtualUserTable.domain like '\\%' and VUTDomains.domain like ?)) order by concat(VirtualUserTable.user,'@',VirtualUserTable.domain) desc limit 1";
49      
50      /**
51       * Processes regex virtual user mapping
52       *
53       * If a mapped target string begins with the prefix regex:, it must be
54       * formatted as regex:<regular-expression>:<parameterized-string>,
55       * e.g., regex:(.*)@(.*):${1}@tld
56       *
57       * @param address the MailAddress to be mapped
58       * @param targetString a String specifying the mapping
59       * @throws MalformedPatternException 
60       */
61       public static String regexMap( MailAddress address, String targetString) throws MalformedPatternException {
62          String result = null;
63          int identifierLength = VirtualUserTable.REGEX_PREFIX.length();
64  
65          int msgPos = targetString.indexOf(':', identifierLength + 1);
66  
67          // Throw exception on invalid format
68          if (msgPos < identifierLength + 1) throw new MalformedPatternException("Regex should be formatted as regex:<regular-expression>:<parameterized-string>");
69          
70          // log("regex: targetString = " + targetString);
71          // log("regex: msgPos = " + msgPos);
72          // log("regex: compile " + targetString.substring("regex:".length(), msgPos));
73          // log("regex: address = " + address.toString());
74          // log("regex: replace = " + targetString.substring(msgPos + 1));
75  
76          Pattern pattern = new Perl5Compiler().compile(targetString.substring(identifierLength, msgPos));
77          Perl5Matcher matcher = new Perl5Matcher();
78  
79          if (matcher.matches(address.toString(), pattern)) {
80              MatchResult match = matcher.getMatch();
81              Map parameters = new HashMap(match.groups());
82              for (int i = 1; i < match.groups(); i++) {
83                  parameters.put(Integer.toString(i), match.group(i));
84              }
85              result = XMLResources.replaceParameters(targetString.substring(msgPos + 1), parameters);
86          }    
87          return result;
88      }
89       
90       /**
91        * Returns the real recipient given a virtual username and domain.
92        * 
93        * @param user the virtual user
94        * @param domain the virtual domain
95        * @return the real recipient address, or <code>null</code> if no mapping exists
96        */
97       public static String getTargetString(String user, String domain, Map mappings) {
98           StringBuffer buf;
99           String target;
100          
101          //Look for exact (user@domain) match
102          buf = new StringBuffer().append(user).append("@").append(domain);
103          target = (String)mappings.get(buf.toString());
104          if (target != null) {
105              return target;
106          }
107          
108          //Look for user@* match
109          buf = new StringBuffer().append(user).append("@*");
110          target = (String)mappings.get(buf.toString());
111          if (target != null) {
112              return target;
113          }
114          
115          //Look for *@domain match
116          buf = new StringBuffer().append("*@").append(domain);
117          target = (String)mappings.get(buf.toString());
118          if (target != null) {
119              return target;
120          }
121          
122          return null;
123      }
124      
125      /**
126       * Returns the character used to delineate multiple addresses.
127       * 
128       * @param targetString the string to parse
129       * @return the character to tokenize on
130       */
131      public static String getSeparator(String targetString) {
132         return (targetString.indexOf(',') > -1 ? "," : (targetString
133         .indexOf(';') > -1 ? ";" : ((targetString.indexOf(VirtualUserTable.ERROR_PREFIX) > -1 
134             || targetString.indexOf(VirtualUserTable.REGEX_PREFIX) > -1 || targetString.indexOf(VirtualUserTable.ALIASDOMAIN_PREFIX) > -1)? "" : ":")));
135      }
136      
137      /**
138       * Returns a Map which contains the mappings
139       * 
140       * @param mapping A String which contains a list of mappings
141       * @return Map which contains the mappings
142       */
143      public static Map getXMLMappings(String mapping) {
144          Map mappings = new HashMap();
145          StringTokenizer tokenizer = new StringTokenizer(mapping, ",");
146          while(tokenizer.hasMoreTokens()) {
147            String mappingItem = tokenizer.nextToken();
148            int index = mappingItem.indexOf('=');
149            String virtual = mappingItem.substring(0, index).trim().toLowerCase();
150            String real = mappingItem.substring(index + 1).trim().toLowerCase();
151            mappings.put(virtual, real);
152          }
153          return mappings;
154      }
155      
156      
157     /**
158      * Return a Collection which holds the extracted mappings of the given String
159      * 
160      * @param rawMapping
161      * @deprecated Use mappingToCollection(String rawMapping)
162      */
163      public static Collection getMappings(String rawMapping) {
164         return mappingToCollection(rawMapping);
165     }
166      
167      /**
168       * Convert a raw mapping String to a Collection
169       * 
170       * @param rawMapping the mapping Strin
171       * @return map a collection which holds all mappings
172       */
173      public static ArrayList mappingToCollection(String rawMapping) {
174          ArrayList map = new ArrayList();
175          StringTokenizer tokenizer = new StringTokenizer(rawMapping,
176          VirtualUserTableUtil.getSeparator(rawMapping));
177 
178          while (tokenizer.hasMoreTokens()) {
179              String raw = tokenizer.nextToken().trim();
180              map.add(raw);
181          }
182          return map;
183     }
184      
185 
186      /**
187       * Convert a Collection which holds mappings to a raw mapping String
188       * 
189       * @param map the Collection
190       * @return mapping the mapping String
191       */
192      public static String CollectionToMapping(Collection map) {
193          StringBuffer mapping = new StringBuffer();
194      
195          Iterator mappings = map.iterator();
196      
197          while (mappings.hasNext()) {
198              mapping.append(mappings.next());
199          
200              if (mappings.hasNext()) {
201                  mapping.append(";");
202              }
203          }  
204          return mapping.toString();  
205     }
206 }