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