001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.aspects.asynch;
023:
024: import java.io.Serializable;
025:
026: import org.jboss.aop.Advisor;
027: import org.jboss.aop.Dispatcher;
028: import org.jboss.aop.InstanceAdvised;
029: import org.jboss.aop.joinpoint.MethodInvocation;
030: import org.jboss.aop.proxy.ProxyFactory;
031: import org.jboss.aspects.NullOrZero;
032: import org.jboss.aspects.remoting.InvokeRemoteInterceptor;
033: import org.jboss.aspects.remoting.Remoting;
034: import org.jboss.remoting.InvokerLocator;
035: import org.jboss.util.id.GUID;
036:
037: /**
038: * Comment
039: *
040: * @author <a href="mailto:bill@jboss.org">Bill Burke</a>
041: * @version $Revision: 57186 $
042: */
043: public class AsynchAspect {
044: public static final String FUTURE = "ASYNCH_FUTURE";
045:
046: private static GUID futureClassGUID = new GUID();
047: private static Class[] futureIntf = { Future.class };
048: private static Class[] futureDynamicIntf = { Future.class,
049: Serializable.class, InstanceAdvised.class };
050: private Advisor advisor;
051: protected ExecutorAbstraction executor;
052: private boolean generateFutureProxy = true;
053:
054: public Advisor getAdvisor() {
055: return advisor;
056: }
057:
058: public void setAdvisor(Advisor advisor) {
059: this .advisor = advisor;
060: Class executorClass = null;
061: AsynchExecutor executorAnnotation = (AsynchExecutor) advisor
062: .resolveAnnotation(AsynchExecutor.class);
063: if (executorAnnotation == null) {
064: executorClass = ThreadPoolExecutor.class;
065: } else {
066: executorClass = executorAnnotation.value();
067: }
068:
069: try {
070: executor = (ExecutorAbstraction) executorClass
071: .newInstance();
072: } catch (InstantiationException e) {
073: throw new RuntimeException(e);
074: } catch (IllegalAccessException e) {
075: throw new RuntimeException(e);
076: }
077: executor.setAdvisor(advisor);
078:
079: }
080:
081: public void setGenerateDynamicProxy(boolean gen) {
082: this .generateFutureProxy = gen;
083: }
084:
085: public Object execute(MethodInvocation invocation) throws Throwable {
086: RemotableFuture future = executor.execute(invocation);
087:
088: InvokerLocator locator = (InvokerLocator) invocation
089: .getMetaData(InvokeRemoteInterceptor.REMOTING,
090: InvokeRemoteInterceptor.INVOKER_LOCATOR);
091:
092: // this is a remote invocation so just stuff the future within the response
093: if (locator != null) {
094: setupRemoteFuture(invocation, future, locator);
095: } else {
096: setupLocalFuture(invocation, future);
097: }
098:
099: return NullOrZero.nullOrZero(invocation.getMethod()
100: .getReturnType());
101: }
102:
103: protected void setupRemoteFuture(MethodInvocation invocation,
104: RemotableFuture future, InvokerLocator locator)
105: throws Exception {
106: GUID futureGUID = new GUID();
107: Dispatcher.singleton.registerTarget(futureGUID, future);
108: InstanceAdvised ia = (generateProxy()) ? ProxyFactory
109: .createInterfaceProxy(futureClassGUID, Future.class
110: .getClassLoader(), futureIntf)
111: : (InstanceAdvised) FutureInvocationHandler
112: .createFutureProxy(futureClassGUID,
113: Future.class.getClassLoader(),
114: futureDynamicIntf);
115: Remoting.makeRemotable(ia, locator, futureGUID);
116: future.setRemoteObjectID(futureGUID);
117: invocation.addResponseAttachment(FUTURE, ia);
118: }
119:
120: /**
121: * Default behaviour is to generate a proxy using aop.
122: * This can be overridden, e.g. by the EJB3 AsynchronousInterceptor to avoid dependencies on javassist for EJB3 clients
123: */
124: protected boolean generateProxy() {
125: return generateFutureProxy;
126: }
127:
128: protected void setupLocalFuture(MethodInvocation invocation,
129: Future future) {
130: FutureHolder provider = (FutureHolder) invocation
131: .getTargetObject();
132: provider.setFuture(future);
133: invocation.addResponseAttachment(FUTURE, future);
134: }
135:
136: }
|