/*
* Copyright 2005,2006 WSO2, Inc. http://wso2.com
*
* 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;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.synapse.commons.throttle.core.factory.CallerContextFactory;
/**
* Controls the access of remote callers according to the controlling policy .
* This provides abstraction that need to control access based on caller IP or caller domain name.
* This implementation is thread safe.
*/
public class AccessRateController {
private static Log log = LogFactory.getLog(AccessRateController.class.getName());
private static final String ACCESS_DENIED_TEMPORALLY =
"You cannot access this service since you have exceeded the allocated quota.";
private static final String ACCESS_DENIED =
"You cannot access this service since you have been prohibited permanently.";
/* The Object for used to lock in synchronizing */
private final Object lock = new Object();
private boolean debugOn = false; //is debug enable
public AccessRateController() {
debugOn = log.isDebugEnabled();
}
/**
* To check whether caller can access not not base on the controlling policy
*
* @param throttleContext - current states of throttle - RunTime Data
* @param callerID - Identifier for remote caller - ex: ip or domainname
* @param callerType - the type of the caller
* @return access information
* @throws ThrottleException
*/
public AccessInformation canAccess(ThrottleContext throttleContext, String callerID,
int callerType) throws ThrottleException {
String type = ThrottleConstants.IP_BASE == callerType ? "IP address" : "domain";
ThrottleConfiguration throttleConfigurationBean =
throttleContext.getThrottleConfiguration();
AccessInformation accessInformation = new AccessInformation();
if (throttleConfigurationBean == null) {
if (debugOn) {
log.debug("Throttle Configuration couldn't find - Throttling will not occur");
}
accessInformation.setAccessAllowed(true);
return accessInformation;
}
if (callerID == null) {
String msg = "Caller host or ip couldn't find !! - Access will be denied ";
if (debugOn) {
log.debug(msg);
}
accessInformation.setAccessAllowed(false);
accessInformation.setFaultReason(msg);
return accessInformation;
}
CallerConfiguration configuration =
throttleConfigurationBean.getCallerConfiguration(callerID);
if (configuration == null) {
if (debugOn) {
log.debug("Caller configuration couldn't find for " + type + " and for caller " +
callerID);
}
accessInformation.setAccessAllowed(true);
return accessInformation;
}
if (configuration.getAccessState() == ThrottleConstants.ACCESS_DENIED) {
log.info(ACCESS_DENIED);
accessInformation.setAccessAllowed(false);
accessInformation.setFaultReason(ACCESS_DENIED);
return accessInformation;
} else if (configuration.getAccessState() == ThrottleConstants.ACCESS_ALLOWED) {
accessInformation.setAccessAllowed(true);
return accessInformation;
} else if (configuration.getAccessState() == ThrottleConstants.ACCESS_CONTROLLED) {
synchronized (lock) {
CallerContext caller = throttleContext.getCallerContext(callerID);
if (caller == null) {
//if caller has not already registered ,then create new caller description and
//set it in throttle
caller = CallerContextFactory.createCaller(callerType, callerID);
}
if (caller != null) {
long currentTime = System.currentTimeMillis();
if (!caller.canAccess(throttleContext, configuration, currentTime)) {
//if current caller cannot access , then perform cleaning
log.info(ACCESS_DENIED_TEMPORALLY);
throttleContext.processCleanList(currentTime);
accessInformation.setAccessAllowed(false);
accessInformation.setFaultReason(ACCESS_DENIED_TEMPORALLY);
return accessInformation;
} else {
if (debugOn) {
log.debug("Access from " + type + " " + callerID + " is successful.");
}
accessInformation.setAccessAllowed(true);
return accessInformation;
}
} else {
if (debugOn) {
log.debug("Caller " + type + " not found! " + callerID);
}
accessInformation.setAccessAllowed(true);
return accessInformation;
}
}
}
accessInformation.setAccessAllowed(true);
return accessInformation;
}
}