001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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.util.AutoResetThreadLocal;
020    import com.liferay.portal.kernel.util.MethodKey;
021    import com.liferay.portal.monitoring.MonitoringProcessor;
022    import com.liferay.portal.monitoring.RequestStatus;
023    import com.liferay.portal.monitoring.statistics.DataSampleThreadLocal;
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            public void afterReturning(MethodInvocation methodInvocation, Object result)
065                    throws Throwable {
066    
067                    ServiceRequestDataSample serviceRequestDataSample =
068                            _serviceRequestDataSampleThreadLocal.get();
069    
070                    if (serviceRequestDataSample != null) {
071                            serviceRequestDataSample.capture(RequestStatus.SUCCESS);
072                    }
073            }
074    
075            public void afterThrowing(
076                            MethodInvocation methodInvocation, Throwable throwable)
077                    throws Throwable {
078    
079                    ServiceRequestDataSample serviceRequestDataSample =
080                            _serviceRequestDataSampleThreadLocal.get();
081    
082                    if (serviceRequestDataSample != null) {
083                            serviceRequestDataSample.capture(RequestStatus.ERROR);
084                    }
085            }
086    
087            public Object before(MethodInvocation methodInvocation) throws Throwable {
088                    if (!_active) {
089                            return null;
090                    }
091    
092                    Class<?> classObj = methodInvocation.getThis().getClass();
093    
094                    Class<?>[] interfaces = classObj.getInterfaces();
095    
096                    for (int i = 0; i < interfaces.length; i++) {
097                            if (interfaces[i].isAssignableFrom(MonitoringProcessor.class)) {
098                                    return null;
099                            }
100                    }
101    
102                    if (!_permissiveMode && !isMonitored(methodInvocation)) {
103                            return null;
104                    }
105    
106                    ServiceRequestDataSample serviceRequestDataSample =
107                            new ServiceRequestDataSample(methodInvocation);
108    
109                    serviceRequestDataSample.prepare();
110    
111                    _serviceRequestDataSampleThreadLocal.set(serviceRequestDataSample);
112    
113                    return null;
114            }
115    
116            public void duringFinally(MethodInvocation methodInvocation) {
117                    ServiceRequestDataSample serviceRequestDataSample =
118                            _serviceRequestDataSampleThreadLocal.get();
119    
120                    if (serviceRequestDataSample != null) {
121                            _serviceRequestDataSampleThreadLocal.remove();
122    
123                            DataSampleThreadLocal.addDataSample(serviceRequestDataSample);
124    
125                            MessageBusUtil.sendMessage(
126                                    _monitoringDestinationName, serviceRequestDataSample);
127                    }
128            }
129    
130            public Set<String> getMonitoredClasses() {
131                    return _monitoredClasses;
132            }
133    
134            public Set<MethodKey> getMonitoredMethods() {
135                    return _monitoredMethods;
136            }
137    
138            public String getMonitoringDestinationName() {
139                    return _monitoringDestinationName;
140            }
141    
142            public boolean isActive() {
143                    return _active;
144            }
145    
146            public boolean isPermissiveMode() {
147                    return _permissiveMode;
148            }
149    
150            public void setActive(boolean active) {
151                    _active = active;
152            }
153    
154            public void setMonitoredClasses(Set<String> monitoredClasses) {
155                    _monitoredClasses = monitoredClasses;
156            }
157    
158            public void setMonitoredMethods(Set<MethodKey> monitoredMethods) {
159                    _monitoredMethods = monitoredMethods;
160            }
161    
162            public void setMonitoringDestinationName(String monitoringDestinationName) {
163                    _monitoringDestinationName = monitoringDestinationName;
164            }
165    
166            public void setPermissiveMode(boolean permissiveMode) {
167                    _permissiveMode = permissiveMode;
168            }
169    
170            protected boolean isMonitored(MethodInvocation methodInvocation) {
171                    Method method = methodInvocation.getMethod();
172    
173                    Class<?> declaringClass = method.getDeclaringClass();
174    
175                    String className = declaringClass.getName();
176    
177                    if (_monitoredClasses.contains(className)) {
178                            return true;
179                    }
180    
181                    String methodName = method.getName();
182                    Class<?>[] parameterTypes = method.getParameterTypes();
183    
184                    MethodKey methodKey = new MethodKey(
185                            className, methodName, parameterTypes);
186    
187                    if (_monitoredMethods.contains(methodKey)) {
188                            return true;
189                    }
190    
191                    return false;
192            }
193    
194            private static ThreadLocal<ServiceRequestDataSample>
195                    _serviceRequestDataSampleThreadLocal =
196                            new AutoResetThreadLocal<ServiceRequestDataSample>(
197                                    ServiceRequestDataSample.class +
198                                            "._serviceRequestDataSampleThreadLocal");
199    
200            private static boolean _active;
201            private static Set<String> _monitoredClasses = new HashSet<String>();
202            private static Set<MethodKey> _monitoredMethods = new HashSet<MethodKey>();
203            private static String _monitoringDestinationName;
204            private static boolean _permissiveMode;
205    
206    }