001// Copyright 2014 The Apache Software Foundation 002// 003// Licensed under the Apache License, Version 2.0 (the "License"); 004// you may not use this file except in compliance with the License. 005// You may obtain a copy of the License at 006// 007// http://www.apache.org/licenses/LICENSE-2.0 008// 009// Unless required by applicable law or agreed to in writing, software 010// distributed under the License is distributed on an "AS IS" BASIS, 011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012// See the License for the specific language governing permissions and 013// limitations under the License. 014package org.apache.tapestry5.jcache.module; 015 016import java.lang.annotation.Annotation; 017import java.lang.reflect.Method; 018 019import javax.cache.annotation.CacheKeyGenerator; 020import javax.cache.annotation.CachePut; 021import javax.cache.annotation.CacheRemove; 022import javax.cache.annotation.CacheRemoveAll; 023import javax.cache.annotation.CacheResolverFactory; 024import javax.cache.annotation.CacheResult; 025 026import org.apache.tapestry5.commons.ObjectLocator; 027import org.apache.tapestry5.ioc.MethodAdviceReceiver; 028import org.apache.tapestry5.ioc.ServiceBinder; 029import org.apache.tapestry5.ioc.annotations.Advise; 030import org.apache.tapestry5.ioc.annotations.Match; 031import org.apache.tapestry5.jcache.internal.CacheLookupUtil; 032import org.apache.tapestry5.jcache.internal.CacheMethodAdvice; 033import org.apache.tapestry5.jcache.internal.CachePutMethodAdvice; 034import org.apache.tapestry5.jcache.internal.CacheRemoveAllMethodAdvice; 035import org.apache.tapestry5.jcache.internal.CacheRemoveMethodAdvice; 036import org.apache.tapestry5.jcache.internal.CacheResultMethodAdvice; 037import org.apache.tapestry5.plastic.MethodAdvice; 038import org.jsr107.ri.annotations.CacheContextSource; 039import org.jsr107.ri.annotations.DefaultCacheKeyGenerator; 040import org.jsr107.ri.annotations.DefaultCacheResolverFactory; 041 042/** 043 * Tapestry-IoC module that 044 */ 045public final class JCacheModule 046{ 047 048 private JCacheModule() 049 { 050 } 051 052 /** 053 * Declares some services. 054 * 055 * @param binder 056 * a {@link ServiceBinder}. 057 */ 058 public static void bind(ServiceBinder binder) 059 { 060 binder.bind(CacheKeyGenerator.class, DefaultCacheKeyGenerator.class); 061 binder.bind(CacheResolverFactory.class, DefaultCacheResolverFactory.class); 062 binder.bind(CacheContextSource.class, CacheLookupUtil.class); 063 } 064 065 /** 066 * Applies the advice to the services. 067 * 068 * @param receiver 069 * a {@link MethodAdviceReceiver}. 070 * @param objectLocator 071 * an {@link ObjectLocator}. 072 */ 073 @Match("*") 074 @Advise(id = "JCache") 075 public static void adviseCache(MethodAdviceReceiver receiver, ObjectLocator objectLocator) 076 { 077 advise(CachePut.class, objectLocator, CachePutMethodAdvice.class, receiver); 078 advise(CacheRemoveAll.class, objectLocator, CacheRemoveAllMethodAdvice.class, 079 receiver); 080 advise(CacheRemove.class, objectLocator, CacheRemoveMethodAdvice.class, receiver); 081 advise(CacheResult.class, objectLocator, CacheResultMethodAdvice.class, receiver); 082 } 083 084 private static void advise(Class<? extends Annotation> annotationClass, ObjectLocator objectLocator, 085 Class<? extends CacheMethodAdvice> adviceClass, MethodAdviceReceiver methodAdviceReceiver) 086 { 087 // TAP5-2466: create the advice on-demand to avoid recursion issues 088 MethodAdvice advice = null; 089 090 if (methodAdviceReceiver.getClassAnnotationProvider().getAnnotation(annotationClass) != null) 091 { 092 advice = build(objectLocator, adviceClass); 093 094 methodAdviceReceiver.adviseAllMethods(advice); 095 } 096 else 097 { 098 for (Method method : methodAdviceReceiver.getInterface().getMethods()) 099 { 100 if (methodAdviceReceiver.getMethodAnnotation(method, annotationClass) != null) 101 { 102 if(advice== null) 103 { 104 advice = build(objectLocator, adviceClass); 105 } 106 107 methodAdviceReceiver.adviseMethod(method, advice); 108 } 109 } 110 } 111 } 112 113 private static CacheMethodAdvice build(ObjectLocator objectLocator, Class<? extends CacheMethodAdvice> advice) 114 { 115 return objectLocator.autobuild(advice); 116 } 117}