Package com.ccbill.clessidra.aspect

Source Code of com.ccbill.clessidra.aspect.BaseRateLimiter

package com.ccbill.clessidra.aspect;

import java.util.UUID;

import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import com.ccbill.clessidra.annotations.RateLimited;
import com.ccbill.clessidra.exception.RateLimiterException;
import com.ccbill.clessidra.strategy.AbstractLimiterStrategy;
import com.ccbill.clessidra.strategy.LimiterStrategyConclusion;

/**
*
* {@link BaseRateLimiter} holds the core logic of when a method call is intercepted for rate limiting.
*
* @author reubena
*
*/
public class BaseRateLimiter implements ApplicationContextAware {

  private Logger logger = Logger.getLogger(BaseRateLimiter.class);

  private ApplicationContext applicationContext;

  public BaseRateLimiter() {
  }

  /**
   * The core Rate Limiter logic. This method will call the limiter strategy chain and decide whether to annotated method will run or not.
   *
   * @param joinPoint
   * @return The object returned by the annotated method
   * @throws Throwable
   */
  public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable {

    // extract MethodSignature
    MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
    logger.debug("Intercepted a method call on " + methodSignature.toString());

    // find the RateLimited annotation, method gets priority over class
    RateLimited annotation = methodSignature.getMethod().getAnnotation(RateLimited.class);
    if (annotation == null) {
      annotation = (RateLimited) joinPoint.getSourceLocation().getWithinType().getAnnotation(RateLimited.class);
    }

    // resolve method group name based on the methodGrouping in the annotation
    String methodGroupName = null;
    switch (annotation.methodGrouping()) {
    case GROUPED:
      methodGroupName = annotation.groupName();
      break;
    case UNGROUPED:
      methodGroupName = methodSignature.toString();
      break;
    default:
      methodGroupName = methodSignature.toString();
      break;
    }

    // get the limiter strategy chain from the spring context
    AbstractLimiterStrategy limiterStrategyChain = (AbstractLimiterStrategy) applicationContext.getBean(annotation.limiterBean());

    // generate a uuid to be used later on if rollback is required
    UUID methodInvocationUUID = UUIDGenerator.generateUUID();

    // run through the limiter strategy chain and get the conclusion
    LimiterStrategyConclusion conclusion = limiterStrategyChain.hasLimitBeenExceededChain(methodGroupName, methodInvocationUUID,
        joinPoint.getArgs());

    // if limit is not exceeded call the method and do a post invocation clean up where needed
    if (!conclusion.getHasLimitBeenExceeded()) {
      logger.trace("About to run method " + methodSignature.toString());
      try {
        Object obj = joinPoint.proceed(joinPoint.getArgs());
        logger.trace("Finished running " + methodSignature.toString());
        return obj;
      } catch (Throwable t) {
        logger.debug("Method " + methodSignature.toString() + " did not exit gracefully. " + t);
        throw t;
      } finally {
        limiterStrategyChain.postInvocationCleanupChain(methodGroupName, methodInvocationUUID, joinPoint.getArgs());
      }
    }

    // throw an exception containing the conclusion
    throw new RateLimiterException("Method call blocked.", conclusion);
  }

  /**
   * Spring will automagically set the application context using this method thanks to {@link ApplicationContextAware}
   */
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.applicationContext = applicationContext;
  }

}
TOP

Related Classes of com.ccbill.clessidra.aspect.BaseRateLimiter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.