org.wisdom.cache.ehcache.CachedActionInterceptor.java Source code

Java tutorial

Introduction

Here is the source code for org.wisdom.cache.ehcache.CachedActionInterceptor.java

Source

/*
 * #%L
 * Wisdom-Framework
 * %%
 * Copyright (C) 2013 - 2014 Wisdom Framework
 * %%
 * 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.
 * #L%
 */
package org.wisdom.cache.ehcache;

import com.google.common.base.Strings;
import org.apache.felix.ipojo.annotations.Component;
import org.apache.felix.ipojo.annotations.Instantiate;
import org.apache.felix.ipojo.annotations.Provides;
import org.apache.felix.ipojo.annotations.Requires;
import org.joda.time.Duration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wisdom.api.cache.Cache;
import org.wisdom.api.cache.Cached;
import org.wisdom.api.http.HeaderNames;
import org.wisdom.api.http.Result;
import org.wisdom.api.interception.Interceptor;
import org.wisdom.api.interception.RequestContext;

/**
 * An action interceptor caching the result of an action and returning the cached result if it was cached already.
 */
@Component
@Provides(specifications = Interceptor.class)
@Instantiate
public class CachedActionInterceptor extends Interceptor<Cached> {

    @Requires
    protected Cache cache;

    private static final Logger LOGGER = LoggerFactory.getLogger(CachedActionInterceptor.class);

    /**
     * Intercepts a @Cached action method.
     * If the result of the action is cached, returned it immediately without having actually invoked the action method.
     * In this case, the interception chain is cut.
     * <p>
     * If the result is not yet cached, the interception chain continues, and the result is cached to be used during
     * the next invocation.
     *
     * @param configuration the interception configuration
     * @param context       the interception context
     * @return the result.
     * @throws Exception something bad happened
     */
    @Override
    public Result call(Cached configuration, RequestContext context) throws Exception {
        // Can we use the Cached version ?
        boolean nocache = HeaderNames.NOCACHE_VALUE
                .equalsIgnoreCase(context.context().header(HeaderNames.CACHE_CONTROL));

        String key;
        if (Strings.isNullOrEmpty(configuration.key())) {
            key = context.request().uri();
        } else {
            key = configuration.key();
        }

        Result result = null;
        if (!nocache) {
            result = (Result) cache.get(key);
        }

        if (result == null) {
            result = context.proceed();
        } else {
            LOGGER.info("Returning cached result for {} (key:{})", context.request().uri(), key);
            return result;
        }

        Duration duration;
        if (configuration.duration() == 0) {
            // Eternity == 1 year.
            duration = Duration.standardDays(365);
        } else {
            duration = Duration.standardSeconds(configuration.duration());
        }

        cache.set(key, result, duration);
        LoggerFactory.getLogger(this.getClass()).info("Caching result of {} for {} seconds (key:{})",
                context.request().uri(), configuration.duration(), key);

        return result;
    }

    /**
     * @return the cached annotation class.
     */
    @Override
    public Class<Cached> annotation() {
        return Cached.class;
    }
}