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.ioc.MethodAdviceReceiver; 027import org.apache.tapestry5.ioc.ObjectLocator; 028import org.apache.tapestry5.ioc.ServiceBinder; 029import org.apache.tapestry5.ioc.annotations.Match; 030import org.apache.tapestry5.jcache.internal.CacheLookupUtil; 031import org.apache.tapestry5.jcache.internal.CacheMethodAdvice; 032import org.apache.tapestry5.jcache.internal.CachePutMethodAdvice; 033import org.apache.tapestry5.jcache.internal.CacheRemoveAllMethodAdvice; 034import org.apache.tapestry5.jcache.internal.CacheRemoveMethodAdvice; 035import org.apache.tapestry5.jcache.internal.CacheResultMethodAdvice; 036import org.apache.tapestry5.plastic.MethodAdvice; 037import org.jsr107.ri.annotations.CacheContextSource; 038import org.jsr107.ri.annotations.DefaultCacheKeyGenerator; 039import org.jsr107.ri.annotations.DefaultCacheResolverFactory; 040 041/** 042 * Tapestry-IoC module that 043 */ 044public final class JCacheModule 045{ 046 047 private JCacheModule() 048 { 049 } 050 051 /** 052 * Declares some services. 053 * 054 * @param binder 055 * a {@link ServiceBinder}. 056 */ 057 public static void bind(ServiceBinder binder) 058 { 059 binder.bind(CacheKeyGenerator.class, DefaultCacheKeyGenerator.class); 060 binder.bind(CacheResolverFactory.class, DefaultCacheResolverFactory.class); 061 binder.bind(CacheContextSource.class, CacheLookupUtil.class); 062 } 063 064 /** 065 * Applies the advice to the services. 066 * 067 * @param receiver 068 * a {@link MethodAdviceReceiver}. 069 * @param objectLocator 070 * an {@link ObjectLocator}. 071 */ 072 @Match("*") 073 public static void adviseCache(MethodAdviceReceiver receiver, ObjectLocator objectLocator) 074 { 075 advise(CachePut.class, objectLocator, CachePutMethodAdvice.class, receiver); 076 advise(CacheRemoveAll.class, objectLocator, CacheRemoveAllMethodAdvice.class, 077 receiver); 078 advise(CacheRemove.class, objectLocator, CacheRemoveMethodAdvice.class, receiver); 079 advise(CacheResult.class, objectLocator, CacheResultMethodAdvice.class, receiver); 080 } 081 082 private static void advise(Class<? extends Annotation> annotationClass, ObjectLocator objectLocator, 083 Class<? extends CacheMethodAdvice> adviceClass, MethodAdviceReceiver methodAdviceReceiver) 084 { 085 // TAP5-2466: create the advice on-demand to avoid recursion issues 086 MethodAdvice advice = null; 087 088 if (methodAdviceReceiver.getClassAnnotationProvider().getAnnotation(annotationClass) != null) 089 { 090 advice = build(objectLocator, adviceClass); 091 092 methodAdviceReceiver.adviseAllMethods(advice); 093 } 094 else 095 { 096 for (Method method : methodAdviceReceiver.getInterface().getMethods()) 097 { 098 if (methodAdviceReceiver.getMethodAnnotation(method, annotationClass) != null) 099 { 100 if(advice== null) 101 { 102 advice = build(objectLocator, adviceClass); 103 } 104 105 methodAdviceReceiver.adviseMethod(method, advice); 106 } 107 } 108 } 109 } 110 111 private static CacheMethodAdvice build(ObjectLocator objectLocator, Class<? extends CacheMethodAdvice> advice) 112 { 113 return objectLocator.autobuild(advice); 114 } 115}