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.spring.aop;
016    
017    import com.liferay.portal.kernel.util.ProxyUtil;
018    import com.liferay.portal.kernel.util.ReflectionUtil;
019    
020    import java.io.Closeable;
021    import java.io.IOException;
022    
023    import java.lang.reflect.Constructor;
024    import java.lang.reflect.Field;
025    
026    import org.springframework.aop.TargetSource;
027    import org.springframework.aop.framework.AdvisedSupport;
028    import org.springframework.aop.target.SingletonTargetSource;
029    
030    /**
031     * @author Shuyang Zhou
032     */
033    public class ServiceWrapperProxyUtil {
034    
035            public static Closeable createProxy(
036                            Object springServiceProxy, Class<?> serviceWrapperClass)
037                    throws Exception {
038    
039                    if (!ProxyUtil.isProxyClass(springServiceProxy.getClass())) {
040                            throw new IllegalArgumentException(
041                                    springServiceProxy + " is not a Spring service proxy");
042                    }
043    
044                    final AdvisedSupport advisedSupport =
045                            ServiceBeanAopProxy.getAdvisedSupport(springServiceProxy);
046    
047                    final TargetSource targetSource = advisedSupport.getTargetSource();
048    
049                    final Object previousService = targetSource.getTarget();
050    
051                    Constructor<?>[] constructors =
052                            serviceWrapperClass.getDeclaredConstructors();
053    
054                    Constructor<?> constructor = constructors[0];
055    
056                    constructor.setAccessible(true);
057    
058                    advisedSupport.setTargetSource(
059                            new SingletonTargetSource(
060                                    constructor.newInstance(previousService)));
061    
062                    return new Closeable() {
063    
064                            @Override
065                            public void close() throws IOException {
066                                    advisedSupport.setTargetSource(targetSource);
067    
068                                    try {
069                                            targetSource.releaseTarget(previousService);
070                                    }
071                                    catch (Exception e) {
072                                            throw new IOException(e);
073                                    }
074                            }
075    
076                    };
077            }
078    
079            public static Closeable injectFieldProxy(
080                            Object springServiceProxy, String fieldName, Class<?> wrapperClass)
081                    throws Exception {
082    
083                    if (!ProxyUtil.isProxyClass(springServiceProxy.getClass())) {
084                            throw new IllegalArgumentException(
085                                    springServiceProxy + " is not a Spring service proxy");
086                    }
087    
088                    AdvisedSupport advisedSupport = ServiceBeanAopProxy.getAdvisedSupport(
089                            springServiceProxy);
090    
091                    TargetSource targetSource = advisedSupport.getTargetSource();
092    
093                    final Object targetService = targetSource.getTarget();
094    
095                    Class<?> clazz = targetService.getClass();
096    
097                    Field field = null;
098    
099                    while (clazz != null) {
100                            try {
101                                    field = ReflectionUtil.getDeclaredField(clazz, fieldName);
102    
103                                    break;
104                            }
105                            catch (NoSuchFieldException nsfe) {
106                                    clazz = clazz.getSuperclass();
107                            }
108                    }
109    
110                    if (field == null) {
111                            throw new IllegalArgumentException(
112                                    "Unable to locate field " + fieldName + " in " + targetService);
113                    }
114    
115                    final Field finalField = field;
116    
117                    final Object previousValue = finalField.get(targetService);
118    
119                    Constructor<?>[] constructors = wrapperClass.getDeclaredConstructors();
120    
121                    Constructor<?> constructor = constructors[0];
122    
123                    constructor.setAccessible(true);
124    
125                    finalField.set(targetService, constructor.newInstance(previousValue));
126    
127                    return new Closeable() {
128    
129                            @Override
130                            public void close() throws IOException {
131                                    try {
132                                            finalField.set(targetService, previousValue);
133                                    }
134                                    catch (ReflectiveOperationException roe) {
135                                            throw new IOException(roe);
136                                    }
137                            }
138    
139                    };
140            }
141    
142    }