grails.plugin.cache.CustomCacheKeyGenerator.java Source code

Java tutorial

Introduction

Here is the source code for grails.plugin.cache.CustomCacheKeyGenerator.java

Source

/* Copyright 2013 SpringSource.
 *
 * 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 grails.plugin.cache;

import org.codehaus.groovy.grails.plugins.GrailsVersionUtils;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.core.SpringVersion;

import java.io.Serializable;
import java.lang.reflect.Method;

/**
 * Includes the hashcode, method signature, and class name of the target (caller) in the cache key
 */
public class CustomCacheKeyGenerator implements KeyGenerator {

    private final KeyGenerator innerKeyGenerator;

    public CustomCacheKeyGenerator(KeyGenerator innerKeyGenerator) {
        this.innerKeyGenerator = innerKeyGenerator;
    }

    public CustomCacheKeyGenerator() {
        // Use the Spring key generator if the Spring version is 4.0.3 or later
        // Can't use the Spring key generator if < 4.0.3 because of https://jira.spring.io/browse/SPR-11505
        if (SpringVersion.getVersion() == null
                || GrailsVersionUtils.isVersionGreaterThan(SpringVersion.getVersion(), "4.0.3")) {
            this.innerKeyGenerator = new SimpleKeyGenerator();
        } else {
            try {
                this.innerKeyGenerator = (KeyGenerator) Class
                        .forName("org.springframework.cache.interceptor.SimpleKeyGenerator").newInstance();
            } catch (Exception e) {
                // this should never happen
                throw new RuntimeException(e);
            }
        }
    }

    @SuppressWarnings("serial")
    private static final class CacheKey implements Serializable {
        final String targetClassName;
        final String targetMethodName;
        final int targetObjectHashCode;
        final Object simpleKey;

        public CacheKey(String targetClassName, String targetMethodName, int targetObjectHashCode,
                Object simpleKey) {
            this.targetClassName = targetClassName;
            this.targetMethodName = targetMethodName;
            this.targetObjectHashCode = targetObjectHashCode;
            this.simpleKey = simpleKey;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((simpleKey == null) ? 0 : simpleKey.hashCode());
            result = prime * result + ((targetClassName == null) ? 0 : targetClassName.hashCode());
            result = prime * result + ((targetMethodName == null) ? 0 : targetMethodName.hashCode());
            result = prime * result + targetObjectHashCode;
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            CacheKey other = (CacheKey) obj;
            if (simpleKey == null) {
                if (other.simpleKey != null)
                    return false;
            } else if (!simpleKey.equals(other.simpleKey))
                return false;
            if (targetClassName == null) {
                if (other.targetClassName != null)
                    return false;
            } else if (!targetClassName.equals(other.targetClassName))
                return false;
            if (targetMethodName == null) {
                if (other.targetMethodName != null)
                    return false;
            } else if (!targetMethodName.equals(other.targetMethodName))
                return false;
            if (targetObjectHashCode != other.targetObjectHashCode)
                return false;
            return true;
        }
    }

    public Object generate(Object target, Method method, Object... params) {
        Class<?> objClass = AopProxyUtils.ultimateTargetClass(target);

        return new CacheKey(objClass.getName().intern(), method.toString().intern(), target.hashCode(),
                innerKeyGenerator.generate(target, method, params));
    }
}