/*
* Copyright 2005,2006 WSO2, Inc. http://www.wso2.org
*
* Licensed 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.synapse.commons.throttle.core.impl.ipbase;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.synapse.commons.throttle.core.CallerConfiguration;
import org.apache.synapse.commons.throttle.core.ThrottleConfiguration;
import org.apache.synapse.commons.throttle.core.ThrottleConstants;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class IPBaseThrottleConfiguration implements ThrottleConfiguration {
private static Log log = LogFactory.getLog(IPBaseThrottleConfiguration.class.getName());
/* The key for "Other" configuration */
private String keyOfOther;
/* The default configuration for a throttle and this will apply to callersMap
that have not a custom configuration */
private CallerConfiguration defaultCallerConfiguration;
/* To hold configurations */
private Map configurationsMap;
public IPBaseThrottleConfiguration() {
this.configurationsMap = new HashMap();
}
/**
* To get a IPBaseCallerConfiguration - if a configuration for given key found ,it returns ,
* other wise , the default configuration will return.
*
* @param ID - The Remote caller id (IP)
* @return Returns the corresponding configuration for the caller with given ID
*/
public CallerConfiguration getCallerConfiguration(String ID) {
if (ID.equals(ThrottleConstants.KEY_OF_DEFAULT_CONFIGURATION_FOR_OTHER)) {
return defaultCallerConfiguration;
} else {
String key = getConfigurationKeyOfCaller(ID);
if (key != null) {
if (key.equals(ThrottleConstants.KEY_OF_DEFAULT_CONFIGURATION_FOR_OTHER)) {
return defaultCallerConfiguration;
}
return (CallerConfiguration) configurationsMap.get(key);
}
}
return null;
}
/**
* To add a IPBaseCallerConfiguration
*
* @param configuration The configuration for a caller
*/
public void addCallerConfiguration(CallerConfiguration configuration) {
//TODO need to allow overlapping of ip with FirstPartOfIPRange
IPBaseCallerConfiguration ipBaseCallerConfiguration =
(IPBaseCallerConfiguration) configuration;
String key = ipBaseCallerConfiguration.getFirstPartOfIPRange();
if (key == null) {
return;
}
key = key.trim();
if (key.equals(ThrottleConstants.KEY_OF_DEFAULT_CONFIGURATION_FOR_OTHER)) {
keyOfOther = ThrottleConstants.KEY_OF_DEFAULT_CONFIGURATION_FOR_OTHER;
defaultCallerConfiguration = ipBaseCallerConfiguration;
} else {
configurationsMap.put(key, ipBaseCallerConfiguration);
}
}
/**
* To get key for access configuration
*
* @param callerID The remote caller id (ip)
* @return Object-String representation of corrected epr-key for get configuration
*/
public String getConfigurationKeyOfCaller(String callerID) {
if (callerID != null) {
callerID = callerID.trim();
//if there is a unique IP
if (configurationsMap.containsKey(callerID)) {
return callerID;
} else {
int index = callerID.lastIndexOf(".");
if (index > 0) {
String net = callerID.substring(0, index); // get the network portion
String host = callerID.substring(index + 1, callerID.length());
//get the host portion
if (net != null && host != null) {
Set keys = configurationsMap.keySet();
if (keys != null && !keys.isEmpty()) {
for (Iterator it = keys.iterator(); it.hasNext(); ) {
String key = (String) it.next();
if (key != null && key.startsWith(net) && isAfter(key, host)) {
// all ips with in same network
IPBaseCallerConfiguration con =
(IPBaseCallerConfiguration) configurationsMap.get(key);
if (con != null) {
String secondPart = con.getSecondPartOfIPRange();
if (secondPart != null && isBefore(secondPart, host)) {
return key;
}
}
}
}
String all = net + ".*";
if (configurationsMap.containsKey(all)) {
return all;
}
}
}
}
}
}
return keyOfOther;
}
/**
* Helper method to check the ip with the given host is exists after the given ip
*
* @param ip The lower IP
* @param host host
* @return true if the ip with host is higher than given ip ,ow. false
*/
private boolean isAfter(String ip, String host) {
int index = ip.lastIndexOf(".");
if (index > 0) {
// host of first part of ip
String hostfromip = ip.substring(index + 1, ip.length());
if (hostfromip != null && host != null) {
return toInt(hostfromip) <= toInt(host);
}
}
return false;
}
/**
* Helper method to check the ip with the given host is exists before the given ip
*
* @param ip the higher ip
* @param host host
* @return true if the ip with host is lower than given ip ,ow. false
*/
private boolean isBefore(String ip, String host) {
int index = ip.lastIndexOf(".");
if (index > 0) {
// host of second part of ip
String hostfromip = ip.substring(index + 1, ip.length());
if (hostfromip != null && host != null) {
return toInt(hostfromip) >= toInt(host);
}
}
return false;
}
public int getType() {
return ThrottleConstants.IP_BASE;
}
private int toInt(String str) {
if (str == null || "".equals(str)) {
handleException("Invalid string - null value");
}
try {
return Integer.parseInt(str.trim());
} catch (NumberFormatException e) {
handleException("Invalid string '" + str + "' , except an integer value ");
}
return -1;
}
private void handleException(String message) {
String msg = "Error was occurred during ip(ip-range) processing " + message;
log.error(msg);
throw new IllegalArgumentException(msg);
}
}