001/* 002 GRANITE DATA SERVICES 003 Copyright (C) 2011 GRANITE DATA SERVICES S.A.S. 004 005 This file is part of Granite Data Services. 006 007 Granite Data Services is free software; you can redistribute it and/or modify 008 it under the terms of the GNU Library General Public License as published by 009 the Free Software Foundation; either version 2 of the License, or (at your 010 option) any later version. 011 012 Granite Data Services is distributed in the hope that it will be useful, but 013 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License 015 for more details. 016 017 You should have received a copy of the GNU Library General Public License 018 along with this library; if not, see <http://www.gnu.org/licenses/>. 019*/ 020 021package org.granite.tide.seam.async; 022 023import java.lang.annotation.Annotation; 024import java.util.Date; 025 026import org.granite.tide.seam.AbstractSeamServiceContext; 027import org.granite.tide.seam.TideInvocation; 028import org.jboss.seam.Component; 029import org.jboss.seam.annotations.async.Asynchronous; 030import org.jboss.seam.annotations.async.Duration; 031import org.jboss.seam.annotations.async.Expiration; 032import org.jboss.seam.annotations.async.FinalExpiration; 033import org.jboss.seam.annotations.async.IntervalCron; 034import org.jboss.seam.annotations.async.IntervalDuration; 035import org.jboss.seam.annotations.intercept.AroundInvoke; 036import org.jboss.seam.annotations.intercept.Interceptor; 037import org.jboss.seam.annotations.intercept.InterceptorType; 038import org.jboss.seam.async.AbstractDispatcher; 039import org.jboss.seam.async.AsynchronousInterceptor; 040import org.jboss.seam.contexts.Contexts; 041import org.jboss.seam.intercept.AbstractInterceptor; 042import org.jboss.seam.intercept.InvocationContext; 043 044/** 045 * Slightly modified version of the Seam asynchronous interceptor which saves the current username 046 * 047 * Dispatches method calls to @Asynchronous methods 048 * asynchronously, and returns the "timer" object 049 * if necessary. 050 * 051 * @author William DRAI 052 * 053 */ 054@Interceptor(stateless=true, type=InterceptorType.CLIENT, around={ AsynchronousInterceptor.class }) 055public class TideAsynchronousInterceptor extends AbstractInterceptor { 056 057 private static final long serialVersionUID = 9194177339867853303L; 058 059 060 @AroundInvoke 061 public Object aroundInvoke(InvocationContext invocation) throws Exception { 062 if (invocation.getTarget() instanceof AsynchronousInvoker) { 063 if (Contexts.getEventContext().isSet(AbstractDispatcher.EXECUTING_ASYNCHRONOUS_CALL)) 064 TideInvocation.init(); 065 return invocation.proceed(); 066 } 067 068 boolean scheduleAsync = invocation.getMethod().isAnnotationPresent(Asynchronous.class) && 069 (!Contexts.getEventContext().isSet(AbstractDispatcher.EXECUTING_ASYNCHRONOUS_CALL) 070 || Contexts.getEventContext().isSet("org.jboss.seam.async.AsynchronousIntercepter.REENTRANT")); 071 if (scheduleAsync) { 072 AbstractSeamServiceContext serviceContext = (AbstractSeamServiceContext)Component.getInstance(AbstractSeamServiceContext.COMPONENT_NAME, false); 073 if (serviceContext != null && serviceContext.getSessionId() != null) { 074 Annotation[][] parameterAnnotations = invocation.getMethod().getParameterAnnotations(); 075 Long duration = null; 076 Date expiration = null; 077 Date finalExpiration = null; 078 Long intervalDuration = null; 079 String intervalCron = null; 080 for (int i = 0; i < parameterAnnotations.length; i++) { 081 Annotation[] annotations = parameterAnnotations[i]; 082 for (Annotation annotation : annotations) { 083 if (annotation.annotationType().equals(Duration.class)) 084 duration = (Long)invocation.getParameters()[i]; 085 else if (annotation.annotationType().equals(Expiration.class)) 086 expiration = (Date)invocation.getParameters()[i]; 087 else if (annotation.annotationType().equals(FinalExpiration.class)) 088 finalExpiration = (Date)invocation.getParameters()[i]; 089 else if (annotation.annotationType().equals(IntervalDuration.class)) 090 intervalDuration = (Long)invocation.getParameters()[i]; 091 else if (annotation.annotationType().equals(IntervalCron.class)) 092 intervalCron = (String)invocation.getParameters()[i]; 093 } 094 } 095 096 String targetComponentName = getComponent().getName(); 097 Class<?> targetComponentClass = getComponent().getBeanClass(); 098 String methodName = invocation.getMethod().getName(); 099 Class<?>[] paramTypes = invocation.getMethod().getParameterTypes(); 100 Object[] params = invocation.getParameters(); 101 102 AsynchronousInvoker invoker = (AsynchronousInvoker)Component.getInstance("org.granite.tide.seam.asynchronousInvoker"); 103 104 AsyncContext asyncContext = serviceContext.getAsyncContext(); 105 106 if (intervalCron != null) 107 return invoker.invokeAsynchronousCron(asyncContext, targetComponentName, targetComponentClass, methodName, paramTypes, params, 108 duration, expiration, finalExpiration, intervalCron); 109 110 if (finalExpiration != null) 111 return invoker.invokeAsynchronousDuration(asyncContext, targetComponentName, targetComponentClass, methodName, paramTypes, params, 112 duration, expiration, finalExpiration, intervalDuration); 113 114 return invoker.invokeAsynchronousDuration(asyncContext, targetComponentName, targetComponentClass, methodName, paramTypes, params, 115 duration, expiration, intervalDuration); 116 } 117 } 118 119 return invocation.proceed(); 120 } 121 122 // Needed for Seam 2.1 123 public boolean isInterceptorEnabled() { 124 return true; 125 } 126}