
org.apache.james.rrt.lib.AbstractRecipientRewriteTable Maven / Gradle / Ivy
/****************************************************************
* Licensed to the Apache Software Foundation (ASF) under one *
* or more contributor license agreements. See the NOTICE file *
* distributed with this work for additional information *
* regarding copyright ownership. The ASF licenses this file *
* to you 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.rrt.lib;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.annotation.Resource;
import javax.mail.internet.ParseException;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.james.domainlist.api.DomainList;
import org.apache.james.domainlist.api.DomainListException;
import org.apache.james.lifecycle.api.Configurable;
import org.apache.james.lifecycle.api.LogEnabled;
import org.apache.james.rrt.api.RecipientRewriteTable;
import org.apache.james.rrt.api.RecipientRewriteTableException;
import org.apache.mailet.MailAddress;
import org.slf4j.Logger;
/**
*
*/
public abstract class AbstractRecipientRewriteTable implements RecipientRewriteTable, LogEnabled, Configurable {
// The maximum mappings which will process before throwing exception
private int mappingLimit = 10;
private boolean recursive = true;
private Logger logger;
private DomainList domainList;
@Resource(name = "domainlist")
public void setDomainList(DomainList domainList) {
this.domainList = domainList;
}
/**
* @see org.apache.james.lifecycle.api.Configurable#configure(HierarchicalConfiguration)
*/
public void configure(HierarchicalConfiguration config) throws ConfigurationException {
setRecursiveMapping(config.getBoolean("recursiveMapping", true));
try {
setMappingLimit(config.getInt("mappingLimit", 10));
} catch (IllegalArgumentException e) {
throw new ConfigurationException(e.getMessage());
}
doConfigure(config);
}
public void setLog(Logger logger) {
this.logger = logger;
}
/**
* Override to handle config
*
* @param conf
* @throws ConfigurationException
*/
protected void doConfigure(HierarchicalConfiguration conf) throws ConfigurationException {
}
public void setRecursiveMapping(boolean recursive) {
this.recursive = recursive;
}
/**
* Set the mappingLimit
*
* @param mappingLimit
* the mappingLimit
* @throws IllegalArgumentException
* get thrown if mappingLimit smaller then 1 is used
*/
public void setMappingLimit(int mappingLimit) throws IllegalArgumentException {
if (mappingLimit < 1)
throw new IllegalArgumentException("The minimum mappingLimit is 1");
this.mappingLimit = mappingLimit;
}
/**
* @see org.apache.james.rrt.api.RecipientRewriteTable#getMappings(String,
* String)
*/
public Collection getMappings(String user, String domain) throws ErrorMappingException, RecipientRewriteTableException {
return getMappings(user, domain, mappingLimit);
}
public Collection getMappings(String user, String domain, int mappingLimit) throws ErrorMappingException, RecipientRewriteTableException {
// We have to much mappings throw ErrorMappingException to avoid
// infinity loop
if (mappingLimit == 0)
throw new ErrorMappingException("554 Too many mappings to process");
String targetString = mapAddress(user, domain);
// Only non-null mappings are translated
if (targetString != null) {
Collection mappings = new ArrayList();
if (targetString.startsWith(RecipientRewriteTable.ERROR_PREFIX)) {
throw new ErrorMappingException(targetString.substring(RecipientRewriteTable.ERROR_PREFIX.length()));
} else {
Iterator map = RecipientRewriteTableUtil.mappingToCollection(targetString).iterator();
while (map.hasNext()) {
String target = map.next();
if (target.startsWith(RecipientRewriteTable.REGEX_PREFIX)) {
try {
target = RecipientRewriteTableUtil.regexMap(new MailAddress(user, domain), target);
} catch (PatternSyntaxException e) {
getLogger().error("Exception during regexMap processing: ", e);
} catch (ParseException e) {
// should never happen
getLogger().error("Exception during regexMap processing: ", e);
}
} else if (target.startsWith(RecipientRewriteTable.ALIASDOMAIN_PREFIX)) {
target = user + "@" + target.substring(RecipientRewriteTable.ALIASDOMAIN_PREFIX.length());
}
if (target == null)
continue;
StringBuffer buf = new StringBuffer().append("Valid virtual user mapping ").append(user).append("@").append(domain).append(" to ").append(target);
getLogger().debug(buf.toString());
if (recursive) {
String userName = null;
String domainName = null;
String args[] = target.split("@");
if (args != null && args.length > 1) {
userName = args[0];
domainName = args[1];
} else {
// TODO Is that the right todo here?
userName = target;
domainName = domain;
}
// Check if the returned mapping is the same as the
// input. If so return null to avoid loops
if (userName.equalsIgnoreCase(user) && domainName.equalsIgnoreCase(domain)) {
return null;
}
Collection childMappings = getMappings(userName, domainName, mappingLimit - 1);
if (childMappings == null) {
// add mapping
mappings.add(target);
} else {
mappings.addAll(childMappings);
}
} else {
mappings.add(target);
}
}
}
return mappings;
}
return null;
}
/**
* @see org.apache.james.rrt.api.RecipientRewriteTable#addRegexMapping(java.lang.String,
* java.lang.String, java.lang.String)
*/
public void addRegexMapping(String user, String domain, String regex) throws RecipientRewriteTableException {
try {
Pattern.compile(regex);
} catch (PatternSyntaxException e) {
throw new RecipientRewriteTableException("Invalid regex: " + regex, e);
}
checkMapping(user, domain, regex);
getLogger().info("Add regex mapping => " + regex + " for user: " + user + " domain: " + domain);
addMappingInternal(user, domain, RecipientRewriteTable.REGEX_PREFIX + regex);
}
/**
* @see org.apache.james.rrt.api.RecipientRewriteTable#removeRegexMapping(java.lang.String,
* java.lang.String, java.lang.String)
*/
public void removeRegexMapping(String user, String domain, String regex) throws RecipientRewriteTableException {
getLogger().info("Remove regex mapping => " + regex + " for user: " + user + " domain: " + domain);
removeMappingInternal(user, domain, RecipientRewriteTable.REGEX_PREFIX + regex);
}
/**
* @see org.apache.james.rrt.api.RecipientRewriteTable#addAddressMapping(java.lang.String,
* java.lang.String, java.lang.String)
*/
public void addAddressMapping(String user, String domain, String address) throws RecipientRewriteTableException {
if (address.indexOf('@') < 0) {
try {
address = address + "@" + domainList.getDefaultDomain();
} catch (DomainListException e) {
throw new RecipientRewriteTableException("Unable to retrieve default domain", e);
}
}
try {
new MailAddress(address);
} catch (ParseException e) {
throw new RecipientRewriteTableException("Invalid emailAddress: " + address, e);
}
checkMapping(user, domain, address);
getLogger().info("Add address mapping => " + address + " for user: " + user + " domain: " + domain);
addMappingInternal(user, domain, address);
}
/**
* @see org.apache.james.rrt.api.RecipientRewriteTable#removeAddressMapping(java.lang.String,
* java.lang.String, java.lang.String)
*/
public void removeAddressMapping(String user, String domain, String address) throws RecipientRewriteTableException {
if (address.indexOf('@') < 0) {
try {
address = address + "@" + domainList.getDefaultDomain();
} catch (DomainListException e) {
throw new RecipientRewriteTableException("Unable to retrieve default domain", e);
}
}
getLogger().info("Remove address mapping => " + address + " for user: " + user + " domain: " + domain);
removeMappingInternal(user, domain, address);
}
/**
* @see org.apache.james.rrt.api.RecipientRewriteTable#addErrorMapping(java.lang.String,
* java.lang.String, java.lang.String)
*/
public void addErrorMapping(String user, String domain, String error) throws RecipientRewriteTableException {
checkMapping(user, domain, error);
getLogger().info("Add error mapping => " + error + " for user: " + user + " domain: " + domain);
addMappingInternal(user, domain, RecipientRewriteTable.ERROR_PREFIX + error);
}
/**
* @see org.apache.james.rrt.api.RecipientRewriteTable#removeErrorMapping(java.lang.String,
* java.lang.String, java.lang.String)
*/
public void removeErrorMapping(String user, String domain, String error) throws RecipientRewriteTableException {
getLogger().info("Remove error mapping => " + error + " for user: " + user + " domain: " + domain);
removeMappingInternal(user, domain, RecipientRewriteTable.ERROR_PREFIX + error);
}
/**
* @see org.apache.james.rrt.api.RecipientRewriteTable#addMapping(java.lang.String,
* java.lang.String, java.lang.String)
*/
public void addMapping(String user, String domain, String mapping) throws RecipientRewriteTableException {
String map = mapping.toLowerCase();
if (map.startsWith(RecipientRewriteTable.ERROR_PREFIX)) {
addErrorMapping(user, domain, map.substring(RecipientRewriteTable.ERROR_PREFIX.length()));
} else if (map.startsWith(RecipientRewriteTable.REGEX_PREFIX)) {
addRegexMapping(user, domain, map.substring(RecipientRewriteTable.REGEX_PREFIX.length()));
} else if (map.startsWith(RecipientRewriteTable.ALIASDOMAIN_PREFIX)) {
if (user != null)
throw new RecipientRewriteTableException("User must be null for aliasDomain mappings");
addAliasDomainMapping(domain, map.substring(RecipientRewriteTable.ALIASDOMAIN_PREFIX.length()));
} else {
addAddressMapping(user, domain, map);
}
}
/**
* @see org.apache.james.rrt.api.RecipientRewriteTable#removeMapping(java.lang.String,
* java.lang.String, java.lang.String)
*/
public void removeMapping(String user, String domain, String mapping) throws RecipientRewriteTableException {
String map = mapping.toLowerCase();
if (map.startsWith(RecipientRewriteTable.ERROR_PREFIX)) {
removeErrorMapping(user, domain, map.substring(RecipientRewriteTable.ERROR_PREFIX.length()));
} else if (map.startsWith(RecipientRewriteTable.REGEX_PREFIX)) {
removeRegexMapping(user, domain, map.substring(RecipientRewriteTable.REGEX_PREFIX.length()));
} else if (map.startsWith(RecipientRewriteTable.ALIASDOMAIN_PREFIX)) {
if (user != null)
throw new RecipientRewriteTableException("User must be null for aliasDomain mappings");
removeAliasDomainMapping(domain, map.substring(RecipientRewriteTable.ALIASDOMAIN_PREFIX.length()));
} else {
removeAddressMapping(user, domain, map);
}
}
/**
* @see org.apache.james.rrt.api.RecipientRewriteTable#getAllMappings()
*/
public Map> getAllMappings() throws RecipientRewriteTableException {
int count = 0;
Map> mappings = getAllMappingsInternal();
if (mappings != null) {
count = mappings.size();
}
getLogger().debug("Retrieve all mappings. Mapping count: " + count);
return mappings;
}
/**
* @see org.apache.james.rrt.api.RecipientRewriteTable#getUserDomainMappings(java.lang.String,
* java.lang.String)
*/
public Collection getUserDomainMappings(String user, String domain) throws RecipientRewriteTableException {
return getUserDomainMappingsInternal(user, domain);
}
/**
* @see org.apache.james.rrt.api.RecipientRewriteTable#addAliasDomainMapping(java.lang.String,
* java.lang.String)
*/
public void addAliasDomainMapping(String aliasDomain, String realDomain) throws RecipientRewriteTableException {
getLogger().info("Add domain mapping: " + aliasDomain + " => " + realDomain);
addMappingInternal(null, aliasDomain, RecipientRewriteTable.ALIASDOMAIN_PREFIX + realDomain);
}
/**
* @see org.apache.james.rrt.api.RecipientRewriteTable#removeAliasDomainMapping(java.lang.String,
* java.lang.String)
*/
public void removeAliasDomainMapping(String aliasDomain, String realDomain) throws RecipientRewriteTableException {
getLogger().info("Remove domain mapping: " + aliasDomain + " => " + realDomain);
removeMappingInternal(null, aliasDomain, RecipientRewriteTable.ALIASDOMAIN_PREFIX + realDomain);
}
protected Logger getLogger() {
return logger;
}
/**
* Add new mapping
*
* @param user
* the user
* @param domain
* the domain
* @param mapping
* the mapping
* @throws InvalidMappingException
*/
protected abstract void addMappingInternal(String user, String domain, String mapping) throws RecipientRewriteTableException;
/**
* Remove mapping
*
* @param user
* the user
* @param domain
* the domain
* @param mapping
* the mapping
* @throws InvalidMappingException
*/
protected abstract void removeMappingInternal(String user, String domain, String mapping) throws RecipientRewriteTableException;
/**
* Return Collection of all mappings for the given username and domain
*
* @param user
* the user
* @param domain
* the domain
* @return Collection which hold the mappings
*/
protected abstract Collection getUserDomainMappingsInternal(String user, String domain) throws RecipientRewriteTableException;
/**
* Return a Map which holds all Mappings
*
* @return Map
*/
protected abstract Map> getAllMappingsInternal() throws RecipientRewriteTableException;
/**
* Override to map virtual recipients to real recipients, both local and
* non-local. Each key in the provided map corresponds to a potential
* virtual recipient, stored as a MailAddress
object.
*
* Translate virtual recipients to real recipients by mapping a string
* containing the address of the real recipient as a value to a key. Leave
* the value null
* if no mapping should be performed. Multiple recipients may be specified by delineating
* the mapped string with commas, semi-colons or colons.
*
* @param user
* the mapping of virtual to real recipients, as
* MailAddress
es to String
s.
*/
protected abstract String mapAddressInternal(String user, String domain) throws RecipientRewriteTableException;
/**
* Get all mappings for the given user and domain. If a aliasdomain mapping
* was found get sure it is in the map as first mapping.
*
* @param user
* the username
* @param domain
* the domain
* @return the mappings
*/
private String mapAddress(String user, String domain) throws RecipientRewriteTableException {
String mappings = mapAddressInternal(user, domain);
// check if we need to sort
// TODO: Maybe we should just return the aliasdomain mapping
if (mappings != null && mappings.indexOf(RecipientRewriteTable.ALIASDOMAIN_PREFIX) > -1) {
Collection mapCol = RecipientRewriteTableUtil.mappingToCollection(mappings);
Iterator mapIt = mapCol.iterator();
List col = new ArrayList(mapCol.size());
while (mapIt.hasNext()) {
int i = 0;
String mapping = mapIt.next().toString();
if (mapping.startsWith(RecipientRewriteTable.ALIASDOMAIN_PREFIX)) {
col.add(i, mapping);
i++;
} else {
col.add(mapping);
}
}
return RecipientRewriteTableUtil.CollectionToMapping(col);
} else {
return mappings;
}
}
private void checkMapping(String user, String domain, String mapping) throws RecipientRewriteTableException {
Collection mappings = getUserDomainMappings(user, domain);
if (mappings != null && mappings.contains(mapping)) {
throw new RecipientRewriteTableException("Mapping " + mapping + " for user " + user + " domain " + domain + " already exist!");
}
}
/**
* Return user String for the given argument.
* If give value is null, return a wildcard.
*
* @param user the given user String
* @return fixedUser the fixed user String
* @throws InvalidMappingException get thrown on invalid argument
*/
protected String getFixedUser(String user) {
if (user != null) {
if (user.equals(WILDCARD) || user.indexOf("@") < 0) {
return user;
} else {
throw new IllegalArgumentException("Invalid user: " + user);
}
} else {
return WILDCARD;
}
}
/**
* Fix the domain for the given argument.
* If give value is null, return a wildcard.
*
* @param domain the given domain String
* @return fixedDomain the fixed domain String
* @throws InvalidMappingException get thrown on invalid argument
*/
protected String getFixedDomain(String domain) {
if (domain != null) {
if (domain.equals(WILDCARD) || domain.indexOf("@") < 0) {
return domain;
} else {
throw new IllegalArgumentException("Invalid domain: " + domain);
}
} else {
return WILDCARD;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy