001    /**
002     * Copyright (c) 2000-2012 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.monitoring.statistics.service;
016    
017    import com.liferay.portal.kernel.exception.SystemException;
018    import com.liferay.portal.kernel.messaging.MessageBusUtil;
019    import com.liferay.portal.kernel.monitoring.MonitoringProcessor;
020    import com.liferay.portal.kernel.monitoring.RequestStatus;
021    import com.liferay.portal.kernel.monitoring.statistics.DataSampleThreadLocal;
022    import com.liferay.portal.kernel.util.AutoResetThreadLocal;
023    import com.liferay.portal.kernel.util.MethodKey;
024    import com.liferay.portal.spring.aop.ChainableMethodAdvice;
025    
026    import java.lang.reflect.Method;
027    
028    import java.util.HashSet;
029    import java.util.Set;
030    
031    import org.aopalliance.intercept.MethodInvocation;
032    
033    /**
034     * @author Michael C. Han
035     */
036    public class ServiceMonitorAdvice extends ChainableMethodAdvice {
037    
038            /**
039             * @deprecated
040             */
041            public static ServiceMonitorAdvice getInstance() {
042                    return new ServiceMonitorAdvice();
043            }
044    
045            public void addMonitoredClass(String className) {
046                    _monitoredClasses.add(className);
047            }
048    
049            public void addMonitoredMethod(
050                            String className, String methodName, String[] parameterTypes)
051                    throws SystemException {
052    
053                    try {
054                            MethodKey methodKey = new MethodKey(
055                                    className, methodName, parameterTypes);
056    
057                            _monitoredMethods.add(methodKey);
058                    }
059                    catch (ClassNotFoundException cnfe) {
060                            throw new SystemException("Unable to add method", cnfe);
061                    }
062            }
063    
064            @Override
065            public void afterReturning(MethodInvocation methodInvocation, Object result)
066                    throws Throwable {
067    
068                    ServiceRequestDataSample serviceRequestDataSample =
069                            _serviceRequestDataSampleThreadLocal.get();
070    
071                    if (serviceRequestDataSample != null) {
072                            serviceRequestDataSample.capture(RequestStatus.SUCCESS);
073                    }
074            }
075    
076            @Override
077            public boolean afterThrowing(
078                            MethodInvocation methodInvocation, Throwable throwable)
079                    throws Throwable {
080    
081                    ServiceRequestDataSample serviceRequestDataSample =
082                            _serviceRequestDataSampleThreadLocal.get();
083    
084                    if (serviceRequestDataSample != null) {
085                            serviceRequestDataSample.capture(RequestStatus.ERROR);
086                    }
087    
088                    return true;
089            }
090    
091            @Override
092            public Object before(MethodInvocation methodInvocation) throws Throwable {
093                    if (!_active) {
094                            return null;
095                    }
096    
097                    Object thisObject = methodInvocation.getThis();
098    
099                    Class<?> clazz = thisObject.getClass();
100    
101                    Class<?>[] interfaces = clazz.getInterfaces();
102    
103                    for (int i = 0; i < interfaces.length; i++) {
104                            if (interfaces[i].isAssignableFrom(MonitoringProcessor.class)) {
105                                    return null;
106                            }
107                    }
108    
109                    if (!_permissiveMode && !isMonitored(methodInvocation)) {
110                            return null;
111                    }
112    
113                    ServiceRequestDataSample serviceRequestDataSample =
114                            new ServiceRequestDataSample(methodInvocation);
115    
116                    serviceRequestDataSample.prepare();
117    
118                    _serviceRequestDataSampleThreadLocal.set(serviceRequestDataSample);
119    
120                    return null;
121            }
122    
123            @Override
124            public void duringFinally(MethodInvocation methodInvocation) {
125                    ServiceRequestDataSample serviceRequestDataSample =
126                            _serviceRequestDataSampleThreadLocal.get();
127    
128                    if (serviceRequestDataSample != null) {
129                            _serviceRequestDataSampleThreadLocal.remove();
130    
131                            DataSampleThreadLocal.addDataSample(serviceRequestDataSample);
132    
133                            MessageBusUtil.sendMessage(
134                                    _monitoringDestinationName, serviceRequestDataSample);
135                    }
136            }
137    
138            public Set<String> getMonitoredClasses() {
139                    return _monitoredClasses;
140            }
141    
142            public Set<MethodKey> getMonitoredMethods() {
143                    return _monitoredMethods;
144            }
145    
146            public String getMonitoringDestinationName() {
147                    return _monitoringDestinationName;
148            }
149    
150            public boolean isActive() {
151                    return _active;
152            }
153    
154            public boolean isPermissiveMode() {
155                    return _permissiveMode;
156            }
157    
158            public void setActive(boolean active) {
159                    _active = active;
160            }
161    
162            public void setMonitoredClasses(Set<String> monitoredClasses) {
163                    _monitoredClasses = monitoredClasses;
164            }
165    
166            public void setMonitoredMethods(Set<MethodKey> monitoredMethods) {
167                    _monitoredMethods = monitoredMethods;
168            }
169    
170            public void setMonitoringDestinationName(String monitoringDestinationName) {
171                    _monitoringDestinationName = monitoringDestinationName;
172            }
173    
174            public void setPermissiveMode(boolean permissiveMode) {
175                    _permissiveMode = permissiveMode;
176            }
177    
178            protected boolean isMonitored(MethodInvocation methodInvocation) {
179                    Method method = methodInvocation.getMethod();
180    
181                    Class<?> declaringClass = method.getDeclaringClass();
182    
183                    String className = declaringClass.getName();
184    
185                    if (_monitoredClasses.contains(className)) {
186                            return true;
187                    }
188    
189                    String methodName = method.getName();
190                    Class<?>[] parameterTypes = method.getParameterTypes();
191    
192                    MethodKey methodKey = new MethodKey(
193                            className, methodName, parameterTypes);
194    
195                    if (_monitoredMethods.contains(methodKey)) {
196                            return true;
197                    }
198    
199                    return false;
200            }
201    
202            private static ThreadLocal<ServiceRequestDataSample>
203                    _serviceRequestDataSampleThreadLocal =
204                            new AutoResetThreadLocal<ServiceRequestDataSample>(
205                                    ServiceRequestDataSample.class +
206                                            "._serviceRequestDataSampleThreadLocal");
207    
208            private static boolean _active;
209            private static Set<String> _monitoredClasses = new HashSet<String>();
210            private static Set<MethodKey> _monitoredMethods = new HashSet<MethodKey>();
211            private static String _monitoringDestinationName;
212            private static boolean _permissiveMode;
213    
214    }