/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.portal.deploy.hot; import com.liferay.portal.kernel.bean.ClassLoaderBeanHandler; import com.liferay.portal.kernel.module.framework.service.IdentifiableOSGiService; import com.liferay.portal.kernel.service.ServiceWrapper; import com.liferay.portal.kernel.util.AggregateClassLoader; import com.liferay.portal.kernel.util.ProxyUtil; import java.lang.reflect.InvocationHandler; import org.springframework.aop.TargetSource; import org.springframework.aop.framework.AdvisedSupport; import org.springframework.aop.target.SingletonTargetSource; /** * @author Raymond Augé */ public class ServiceBag<V> { public ServiceBag( ClassLoader classLoader, AdvisedSupport advisedSupport, Class<?> serviceTypeClass, final ServiceWrapper<V> serviceWrapper) { _advisedSupport = advisedSupport; Object previousService = serviceWrapper.getWrappedService(); if (!(previousService instanceof ServiceWrapper)) { Class<?> previousServiceClass = previousService.getClass(); AggregateClassLoader previousServiceAggregateClassLoader = new AggregateClassLoader(previousServiceClass.getClassLoader()); previousServiceAggregateClassLoader.addClassLoader( IdentifiableOSGiService.class.getClassLoader()); previousService = ProxyUtil.newProxyInstance( previousServiceAggregateClassLoader, new Class<?>[] { serviceTypeClass, IdentifiableOSGiService.class }, new ClassLoaderBeanHandler( previousService, previousServiceAggregateClassLoader)); serviceWrapper.setWrappedService((V)previousService); } AggregateClassLoader newServiceAggregateClassLoader = new AggregateClassLoader(serviceTypeClass.getClassLoader()); newServiceAggregateClassLoader.addClassLoader( IdentifiableOSGiService.class.getClassLoader()); Object nextTarget = ProxyUtil.newProxyInstance( newServiceAggregateClassLoader, new Class<?>[] { serviceTypeClass, ServiceWrapper.class, IdentifiableOSGiService.class }, new ClassLoaderBeanHandler(serviceWrapper, classLoader)); TargetSource nextTargetSource = new SingletonTargetSource(nextTarget) { @Override public Class<?> getTargetClass() { return serviceWrapper.getClass(); } }; _advisedSupport.setTargetSource(nextTargetSource); _serviceWrapper = (ServiceWrapper<?>)nextTarget; } @SuppressWarnings("unchecked") public <T> void replace() throws Exception { TargetSource targetSource = _advisedSupport.getTargetSource(); Object currentService = targetSource.getTarget(); ServiceWrapper<T> previousService = null; // Loop through services while (true) { // A matching service was found if (currentService == _serviceWrapper) { Object wrappedService = _serviceWrapper.getWrappedService(); if (previousService == null) { // There is no previous service, so we need to unwrap the // portal class loader bean handler and change the target // source if (!(wrappedService instanceof ServiceWrapper) && ProxyUtil.isProxyClass(wrappedService.getClass())) { InvocationHandler invocationHandler = ProxyUtil.getInvocationHandler(wrappedService); if (invocationHandler instanceof ClassLoaderBeanHandler) { ClassLoaderBeanHandler classLoaderBeanHandler = (ClassLoaderBeanHandler)invocationHandler; wrappedService = classLoaderBeanHandler.getBean(); } } TargetSource previousTargetSource = new SingletonTargetSource(wrappedService); _advisedSupport.setTargetSource(previousTargetSource); } else { // Take ourselves out of the chain by setting our // wrapped service as the previous without changing the // target source previousService.setWrappedService((T)wrappedService); } break; } // Every item in the chain is a ServiceWrapper except the original // service if (!(currentService instanceof ServiceWrapper)) { break; } // Check the next service because no matching service was found previousService = (ServiceWrapper<T>)currentService; currentService = previousService.getWrappedService(); } } private final AdvisedSupport _advisedSupport; private final ServiceWrapper<?> _serviceWrapper; }