org.cruk.genologics.api.cache.RestCallTrackingAspect.java Source code

Java tutorial

Introduction

Here is the source code for org.cruk.genologics.api.cache.RestCallTrackingAspect.java

Source

/*
 * CRUK-CI Genologics REST API Java Client.
 * Copyright (C) 2013 Cancer Research UK Cambridge Institute.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.cruk.genologics.api.cache;

import java.net.URI;
import java.text.Collator;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;

import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Ehcache;

import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.junit.Assert;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.http.ResponseEntity;

import com.genologics.ri.GenologicsBatchRetrieveResult;
import com.genologics.ri.Links;
import com.genologics.ri.Locatable;

@Aspect
public class RestCallTrackingAspect {
    private static final String[] EMPTY_ARRAY = new String[0];

    private static final Pattern SEARCH_TERM_SPLIT = Pattern.compile("&");

    private boolean enabled = false;
    private String[] allowedUris = EMPTY_ARRAY;

    protected CacheManager cacheManager;

    public RestCallTrackingAspect() {
    }

    @Required
    public void setCacheManager(CacheManager cacheManager) {
        this.cacheManager = cacheManager;
    }

    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    public String[] getAllowedUris() {
        return allowedUris;
    }

    public void setAllowedUris(String... uris) {
        allowedUris = uris;
    }

    public void setAllowedUris(URI... uris) {
        allowedUris = new String[uris.length];
        for (int i = 0; i < uris.length; i++) {
            allowedUris[i] = uris[i].toString();
        }
    }

    public void setAllowedUris(Locatable... objects) {
        allowedUris = new String[objects.length];
        for (int i = 0; i < objects.length; i++) {
            allowedUris[i] = objects[i].getUri().toString();
        }
    }

    public void clear() {
        allowedUris = EMPTY_ARRAY;
    }

    public Object getForObject(ProceedingJoinPoint pjp) throws Throwable {
        if (!enabled) {
            return pjp.proceed();
        }

        Object uri = pjp.getArgs()[0];

        final String key = uri.toString();

        Object returned = pjp.proceed();

        boolean isBatch = returned.getClass().getAnnotation(GenologicsBatchRetrieveResult.class) != null;
        boolean links = Links.class.isAssignableFrom(returned.getClass());
        listCache();

        if (!isBatch && !links && !isSearch(key) && !ArrayUtils.contains(allowedUris, key)) {
            listCache();
            Assert.fail("Not allowed to fetch " + key + ". Should already be in the cache.");
        }

        return returned;
    }

    public ResponseEntity<?> getForEntity(ProceedingJoinPoint pjp) throws Throwable {
        if (!enabled) {
            return (ResponseEntity<?>) pjp.proceed();
        }

        Object uri = pjp.getArgs()[0];

        final String key = uri.toString();

        ResponseEntity<?> response = (ResponseEntity<?>) pjp.proceed();
        Object returned = response.getBody();

        boolean isBatch = returned.getClass().getAnnotation(GenologicsBatchRetrieveResult.class) != null;
        boolean links = Links.class.isAssignableFrom(returned.getClass());

        if (!isBatch && !links && !isSearch(key) && !ArrayUtils.contains(allowedUris, key)) {
            listCache();
            Assert.fail("Not allowed to fetch " + key + ". Should already be in the cache.");
        }

        return response;
    }

    void listCache() {
        Logger logger = LoggerFactory.getLogger(GenologicsAPICacheTest.class);

        if (logger.isDebugEnabled()) {
            String[] cacheNames = cacheManager.getCacheNames();
            Arrays.sort(cacheNames, Collator.getInstance());

            logger.debug("Cache dump");

            for (String cacheName : cacheNames) {
                Ehcache cache = cacheManager.getEhcache(cacheName);
                List<?> keys = cache.getKeys();

                logger.debug("Have " + keys.size() + " things in the " + cacheName + " cache.");

                for (Object key : keys) {
                    logger.debug(cache.get(key).toString());
                }
            }
        }
    }

    boolean isSearch(String uri) {
        boolean search = false;

        int queryIndex = uri.indexOf('?');
        if (queryIndex >= 0) {
            String[] terms = SEARCH_TERM_SPLIT.split(uri.substring(queryIndex + 1));

            for (int i = 0; i < terms.length && !search; i++) {
                int equal = terms[i].indexOf('=');
                String key = equal <= 0 ? terms[i] : terms[i].substring(0, equal);
                search = !"state".equals(key);
            }
        }

        return search;
    }
}