001    /**
002     * Copyright (c) 2000-present 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.deploy.hot;
016    
017    import com.liferay.portal.kernel.bean.BeanLocatorException;
018    import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.util.ProxyUtil;
022    import com.liferay.portal.service.ServiceWrapper;
023    import com.liferay.portal.spring.aop.ServiceBeanAopCacheManagerUtil;
024    import com.liferay.portal.spring.aop.ServiceBeanAopProxy;
025    import com.liferay.registry.Registry;
026    import com.liferay.registry.RegistryUtil;
027    import com.liferay.registry.ServiceReference;
028    import com.liferay.registry.ServiceTracker;
029    import com.liferay.registry.ServiceTrackerCustomizer;
030    
031    import java.lang.reflect.Method;
032    
033    import org.springframework.aop.TargetSource;
034    import org.springframework.aop.framework.AdvisedSupport;
035    
036    /**
037     * @author Raymond Aug??
038     */
039    public class ServiceWrapperRegistry {
040    
041            public ServiceWrapperRegistry() {
042                    Registry registry = RegistryUtil.getRegistry();
043    
044                    _serviceTracker = registry.trackServices(
045                            ServiceWrapper.class.getName(),
046                            new ServiceWrapperServiceTrackerCustomizer());
047    
048                    _serviceTracker.open();
049            }
050    
051            public void close() {
052                    _serviceTracker.close();
053            }
054    
055            private static final Log _log = LogFactoryUtil.getLog(
056                    ServiceWrapperRegistry.class);
057    
058            private final ServiceTracker<ServiceWrapper<?>, ServiceBag<?>>
059                    _serviceTracker;
060    
061            private class ServiceWrapperServiceTrackerCustomizer
062                    implements ServiceTrackerCustomizer<ServiceWrapper<?>, ServiceBag<?>> {
063    
064                    @Override
065                    public ServiceBag<?> addingService(
066                            ServiceReference<ServiceWrapper<?>> serviceReference) {
067    
068                            Registry registry = RegistryUtil.getRegistry();
069    
070                            ServiceWrapper<?> serviceWrapper = registry.getService(
071                                    serviceReference);
072    
073                            try {
074                                    return _getServiceBag(serviceWrapper);
075                            }
076                            catch (Throwable t) {
077                                    _log.error(t, t);
078                            }
079                            finally {
080                                    ServiceBeanAopCacheManagerUtil.reset();
081                            }
082    
083                            return null;
084                    }
085    
086                    @Override
087                    public void modifiedService(
088                            ServiceReference<ServiceWrapper<?>> serviceReference,
089                            ServiceBag<?> serviceHolder) {
090                    }
091    
092                    @Override
093                    public void removedService(
094                            ServiceReference<ServiceWrapper<?>> serviceReference,
095                            ServiceBag<?> serviceBag) {
096    
097                            Registry registry = RegistryUtil.getRegistry();
098    
099                            registry.ungetService(serviceReference);
100    
101                            try {
102                                    serviceBag.replace();
103    
104                                    ServiceBeanAopCacheManagerUtil.reset();
105                            }
106                            catch (Exception e) {
107                                    _log.error(e, e);
108                            }
109                    }
110    
111                    protected Object getServiceProxy(Class<?> serviceTypeClass) {
112                            Object service = null;
113    
114                            try {
115                                    service = PortalBeanLocatorUtil.locate(
116                                            serviceTypeClass.getName());
117                            }
118                            catch (BeanLocatorException ble) {
119                                    Registry registry = RegistryUtil.getRegistry();
120    
121                                    service = registry.getService(serviceTypeClass);
122                            }
123    
124                            return service;
125                    }
126    
127                    private <T> ServiceBag<?> _getServiceBag(
128                                    ServiceWrapper<T> serviceWrapper)
129                            throws Throwable {
130    
131                            Class<?> clazz = serviceWrapper.getClass();
132    
133                            ClassLoader classLoader = clazz.getClassLoader();
134    
135                            Method method = clazz.getMethod(
136                                    "getWrappedService", new Class<?>[0]);
137    
138                            Class<?> serviceTypeClass = method.getReturnType();
139    
140                            Object serviceProxy = getServiceProxy(serviceTypeClass);
141    
142                            if (!ProxyUtil.isProxyClass(serviceProxy.getClass())) {
143                                    _log.error(
144                                            "Service hooks require Spring to be configured to use " +
145                                                    "JdkDynamicProxy and will not work with CGLIB");
146    
147                                    return null;
148                            }
149    
150                            AdvisedSupport advisedSupport =
151                                    ServiceBeanAopProxy.getAdvisedSupport(serviceProxy);
152    
153                            TargetSource targetSource = advisedSupport.getTargetSource();
154    
155                            serviceWrapper.setWrappedService((T)targetSource.getTarget());
156    
157                            return new ServiceBag<>(
158                                    classLoader, advisedSupport, serviceTypeClass, serviceWrapper);
159                    }
160    
161            }
162    
163    }