001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.messaging.async;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.messaging.MessageBusUtil;
020    import com.liferay.portal.kernel.messaging.async.Async;
021    import com.liferay.portal.kernel.transaction.TransactionCommitCallbackRegistryUtil;
022    import com.liferay.portal.spring.aop.AnnotationChainableMethodAdvice;
023    
024    import java.lang.annotation.Annotation;
025    import java.lang.reflect.Method;
026    
027    import java.util.Map;
028    import java.util.concurrent.Callable;
029    
030    import org.aopalliance.intercept.MethodInvocation;
031    
032    /**
033     * @author Shuyang Zhou
034     * @author Brian Wing Shun Chan
035     */
036    public class AsyncAdvice extends AnnotationChainableMethodAdvice<Async> {
037    
038            @Override
039            public Object before(final MethodInvocation methodInvocation)
040                    throws Throwable {
041    
042                    if (AsyncInvokeThreadLocal.isEnabled()) {
043                            return null;
044                    }
045    
046                    Async async = findAnnotation(methodInvocation);
047    
048                    if (async == _nullAsync) {
049                            return null;
050                    }
051    
052                    Method method = methodInvocation.getMethod();
053    
054                    if (method.getReturnType() != void.class) {
055                            if (_log.isWarnEnabled()) {
056                                    _log.warn(
057                                            "Async annotation on method " + method.getName() +
058                                                    " does not return void");
059                            }
060    
061                            return null;
062                    }
063    
064                    String destinationName = null;
065    
066                    if ((_destinationNames != null) && !_destinationNames.isEmpty()) {
067                            Object thisObject = methodInvocation.getThis();
068    
069                            destinationName = _destinationNames.get(thisObject.getClass());
070                    }
071    
072                    if (destinationName == null) {
073                            destinationName = _defaultDestinationName;
074                    }
075    
076                    final String callbackDestinationName = destinationName;
077    
078                    TransactionCommitCallbackRegistryUtil.registerCallback(
079                            new Callable<Void>() {
080    
081                                    @Override
082                                    public Void call() throws Exception {
083                                            MessageBusUtil.sendMessage(
084                                                    callbackDestinationName,
085                                                    new AsyncProcessCallable(methodInvocation));
086    
087                                            return null;
088                                    }
089    
090                            });
091    
092                    return nullResult;
093            }
094    
095            public String getDefaultDestinationName() {
096                    return _defaultDestinationName;
097            }
098    
099            @Override
100            public Async getNullAnnotation() {
101                    return _nullAsync;
102            }
103    
104            public void setDefaultDestinationName(String defaultDestinationName) {
105                    _defaultDestinationName = defaultDestinationName;
106            }
107    
108            public void setDestinationNames(Map<Class<?>, String> destinationNames) {
109                    _destinationNames = destinationNames;
110            }
111    
112            private static Log _log = LogFactoryUtil.getLog(AsyncAdvice.class);
113    
114            private static Async _nullAsync =
115                    new Async() {
116    
117                            @Override
118                            public Class<? extends Annotation> annotationType() {
119                                    return Async.class;
120                            }
121    
122                    };
123    
124            private String _defaultDestinationName;
125            private Map<Class<?>, String> _destinationNames;
126    
127    }