blob: d2c62095076410f356e4220d7c6afd892fafeefa [file] [log] [blame]
/****************************************************************
* 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.jspf.policies.local;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.apache.james.jspf.core.SPF1Record;
import org.apache.james.jspf.core.SPFRecordParser;
import org.apache.james.jspf.core.exceptions.NeutralException;
import org.apache.james.jspf.core.exceptions.NoneException;
import org.apache.james.jspf.core.exceptions.PermErrorException;
import org.apache.james.jspf.core.exceptions.SPFResultException;
import org.apache.james.jspf.core.exceptions.TempErrorException;
import org.apache.james.jspf.policies.PolicyPostFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Class to support Fallback feature
*/
public class FallbackPolicy implements PolicyPostFilter {
private static final Logger LOGGER = LoggerFactory.getLogger(FallbackPolicy.class);
private Map<String,SPF1Record> entryMap;
private SPFRecordParser parser;
public FallbackPolicy(SPFRecordParser parser) {
entryMap = Collections.synchronizedMap(new HashMap<String,SPF1Record>());
this.parser = parser;
}
/**
* Add a entry.
*
* @param rawHost
* the host or ipaddress for which the entry should be added.
* @param rawSpfRecord
* the spfRecord to add
* @throws IllegalArgumentException
* get thrown on invalid spfRecord
*/
public void addEntry(String rawHost, String rawSpfRecord)
throws IllegalArgumentException {
String host;
try {
LOGGER.debug("Start parsing SPF-Record: {}", rawSpfRecord);
SPF1Record spfRecord = parser.parse(rawSpfRecord);
if (rawHost.startsWith("*")) {
host = rawHost.substring(1);
LOGGER.debug("Convert host {} to {}", rawHost, host);
} else if (rawHost.endsWith("*")) {
int length = rawHost.length();
host = rawHost.substring(length - 1, length);
LOGGER.debug("Convert host {} to {}", rawHost, host);
} else {
host = rawHost;
}
entryMap.put(host, spfRecord);
} catch (SPFResultException e) {
throw new IllegalArgumentException("Invalid SPF-Record: "
+ rawSpfRecord);
}
}
/**
* Clear all entries
*
*/
public void clearEntrys() {
LOGGER.debug("Clear all entries");
entryMap.clear();
}
/**
* Remove entry
*
* @param host
* The host
*/
public void removeEntry(String host) {
LOGGER.debug("Remove fallback entry for host: {}", host);
synchronized (entryMap) {
entryMap.remove(getRawEntry(host));
}
}
/**
* @see org.apache.james.jspf.policies.PolicyPostFilter#getSPFRecord(java.lang.String, org.apache.james.jspf.core.SPF1Record)
*/
public SPF1Record getSPFRecord(String currentDomain, SPF1Record res) throws PermErrorException, TempErrorException, NoneException, NeutralException {
if (res == null) {
return getMySPFRecord(currentDomain);
} else {
return res;
}
}
/**
* Return the SPF1Record for the given host
*
* @param host
* the hostname or ipaddress
* @return the SPF1Record of null if no SPF1Record was found in fallback for
* the given host
*/
protected SPF1Record getMySPFRecord(String host) {
SPF1Record entry = null;
synchronized (entryMap) {
entry = getRawEntry(host);
}
if (entry != null) {
return entry;
} else {
return null;
}
}
/**
* Return the Object stored in the map which match the given host. Keep in
* mind that this method should only called in a synchronized method or
* block
*
* @param host
* the host
* @return the stored object for the given host or null
*/
private SPF1Record getRawEntry(String host) {
Iterator<String> fallBackIt = entryMap.keySet().iterator();
while (fallBackIt.hasNext()) {
String rawHost = fallBackIt.next();
if ((rawHost.startsWith(".") && host.startsWith(rawHost))
|| rawHost.endsWith(".") && host.endsWith(rawHost)) {
return entryMap.get(rawHost);
}
}
return null;
}
}