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