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 ****************************************************************/ 019 020package org.apache.james.domainlist.lib; 021 022import java.net.InetAddress; 023import java.net.UnknownHostException; 024import java.util.ArrayList; 025import java.util.List; 026import java.util.Locale; 027 028import javax.inject.Inject; 029 030import org.apache.commons.configuration.ConfigurationException; 031import org.apache.commons.configuration.HierarchicalConfiguration; 032import org.apache.james.dnsservice.api.DNSService; 033import org.apache.james.domainlist.api.DomainList; 034import org.apache.james.domainlist.api.DomainListException; 035import org.apache.james.lifecycle.api.Configurable; 036import org.apache.james.lifecycle.api.LogEnabled; 037import org.slf4j.Logger; 038import org.slf4j.LoggerFactory; 039 040import com.google.common.annotations.VisibleForTesting; 041import com.google.common.collect.ImmutableList; 042 043/** 044 * All implementations of the DomainList interface should extends this abstract 045 * class 046 */ 047public abstract class AbstractDomainList implements DomainList, LogEnabled, Configurable { 048 049 private static final Logger LOGGER = LoggerFactory.getLogger(AbstractDomainList.class); 050 051 protected static final String LOCALHOST = "localhost"; 052 053 private DNSService dns; 054 private boolean autoDetect = true; 055 private boolean autoDetectIP = true; 056 private Logger logger; 057 private String defaultDomain; 058 059 @Inject 060 public void setDNSService(DNSService dns) { 061 this.dns = dns; 062 } 063 064 public void setLog(Logger logger) { 065 this.logger = logger; 066 } 067 068 protected Logger getLogger() { 069 return logger; 070 } 071 072 @Override 073 public void configure(HierarchicalConfiguration config) throws ConfigurationException { 074 configureDefaultDomain(config); 075 076 setAutoDetect(config.getBoolean("autodetect", true)); 077 setAutoDetectIP(config.getBoolean("autodetectIP", true)); 078 } 079 080 @VisibleForTesting void configureDefaultDomain(HierarchicalConfiguration config) throws ConfigurationException { 081 082 try { 083 defaultDomain = config.getString("defaultDomain", LOCALHOST); 084 085 String hostName = InetAddress.getLocalHost().getHostName(); 086 if (mayChangeDefaultDomain()) { 087 setDefaultDomain(hostName); 088 } 089 } catch (UnknownHostException e) { 090 LOGGER.warn("Unable to retrieve hostname.", e); 091 } catch (DomainListException e) { 092 LOGGER.error("An error occured while creating the default domain", e); 093 } 094 } 095 096 private boolean mayChangeDefaultDomain() { 097 return LOCALHOST.equals(defaultDomain); 098 } 099 100 private void setDefaultDomain(String defaultDomain) throws DomainListException { 101 if (!containsDomain(defaultDomain)) { 102 addDomain(defaultDomain); 103 } 104 this.defaultDomain = defaultDomain; 105 } 106 107 @Override 108 public String getDefaultDomain() throws DomainListException { 109 if (defaultDomain!= null) { 110 return defaultDomain; 111 } else { 112 throw new DomainListException("Null default domain. Domain list might not be configured yet."); 113 } 114 } 115 116 @Override 117 public List<String> getDomains() throws DomainListException { 118 List<String> domains = getDomainListInternal(); 119 if (domains != null) { 120 121 // create mutable copy, some subclasses return ImmutableList 122 ArrayList<String> mutableDomains = new ArrayList<String>(domains); 123 124 String hostName; 125 try { 126 hostName = getDNSServer().getHostName(getDNSServer().getLocalHost()); 127 } catch (UnknownHostException ue) { 128 hostName = "localhost"; 129 } 130 131 getLogger().info("Local host is: " + hostName); 132 133 if (autoDetect && (!hostName.equals("localhost"))) { 134 mutableDomains.add(hostName.toLowerCase(Locale.US)); 135 } 136 137 if (autoDetectIP) { 138 mutableDomains.addAll(getDomainsIP(mutableDomains, dns, getLogger())); 139 } 140 141 if (getLogger().isInfoEnabled()) { 142 for (String domain : mutableDomains) { 143 getLogger().debug("Handling mail for: " + domain); 144 } 145 } 146 147 return ImmutableList.copyOf(mutableDomains); 148 } 149 return ImmutableList.of();// empty list 150 } 151 152 /** 153 * Return a List which holds all ipAddress of the domains in the given List 154 * 155 * @param domains 156 * List of domains 157 * @return domainIP List of ipaddress for domains 158 */ 159 private static List<String> getDomainsIP(List<String> domains, DNSService dns, Logger log) { 160 List<String> domainIP = new ArrayList<String>(); 161 if (domains.size() > 0) { 162 for (String domain : domains) { 163 List<String> domList = getDomainIP(domain, dns, log); 164 165 for (String aDomList : domList) { 166 if (!domainIP.contains(aDomList)) { 167 domainIP.add(aDomList); 168 } 169 } 170 } 171 } 172 return domainIP; 173 } 174 175 /** 176 * @see #getDomainsIP(List, DNSService, Logger) 177 */ 178 private static List<String> getDomainIP(String domain, DNSService dns, Logger log) { 179 List<String> domainIP = new ArrayList<String>(); 180 try { 181 InetAddress[] addrs = dns.getAllByName(domain); 182 for (InetAddress addr : addrs) { 183 String ip = addr.getHostAddress(); 184 if (!domainIP.contains(ip)) { 185 domainIP.add(ip); 186 } 187 } 188 } catch (UnknownHostException e) { 189 log.error("Cannot get IP address(es) for " + domain); 190 } 191 return domainIP; 192 } 193 194 /** 195 * Set to true to autodetect the hostname of the host on which james is 196 * running, and add this to the domain service Default is true 197 * 198 * @param autoDetect 199 * set to <code>false</code> for disable 200 */ 201 public synchronized void setAutoDetect(boolean autoDetect) { 202 getLogger().info("Set autodetect to: " + autoDetect); 203 this.autoDetect = autoDetect; 204 } 205 206 /** 207 * Set to true to lookup the ipaddresses for each given domain and add these 208 * to the domain service Default is true 209 * 210 * @param autoDetectIP 211 * set to <code>false</code> for disable 212 */ 213 public synchronized void setAutoDetectIP(boolean autoDetectIP) { 214 getLogger().info("Set autodetectIP to: " + autoDetectIP); 215 this.autoDetectIP = autoDetectIP; 216 } 217 218 /** 219 * Return dnsServer 220 * 221 * @return dns 222 */ 223 protected DNSService getDNSServer() { 224 return dns; 225 } 226 227 /** 228 * Return domainList 229 * 230 * @return List 231 */ 232 protected abstract List<String> getDomainListInternal() throws DomainListException; 233 234}