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.kernel.util;
016    
017    import com.liferay.portal.kernel.bean.ClassLoaderBeanHandler;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.registry.Filter;
021    import com.liferay.registry.Registry;
022    import com.liferay.registry.RegistryUtil;
023    import com.liferay.registry.ServiceTracker;
024    
025    import java.lang.reflect.InvocationHandler;
026    import java.lang.reflect.InvocationTargetException;
027    import java.lang.reflect.Method;
028    
029    /**
030     * @author Brian Wing Shun Chan
031     */
032    public class ProxyFactory {
033    
034            public static <T> T newDummyInstance(Class<T> interfaceClass) {
035                    return (T)ProxyUtil.newProxyInstance(
036                            interfaceClass.getClassLoader(), new Class[] {interfaceClass},
037                            new DummyInvocationHandler<T>());
038            }
039    
040            public static Object newInstance(
041                            ClassLoader classLoader, Class<?> interfaceClass,
042                            String implClassName)
043                    throws Exception {
044    
045                    return newInstance(
046                            classLoader, new Class[] {interfaceClass}, implClassName);
047            }
048    
049            public static Object newInstance(
050                            ClassLoader classLoader, Class<?>[] interfaceClasses,
051                            String implClassName)
052                    throws Exception {
053    
054                    Object instance = InstanceFactory.newInstance(
055                            classLoader, implClassName);
056    
057                    return ProxyUtil.newProxyInstance(
058                            classLoader, interfaceClasses,
059                            new ClassLoaderBeanHandler(instance, classLoader));
060            }
061    
062            public static <T> T newServiceTrackedInstance(Class<T> interfaceClass) {
063                    return (T)ProxyUtil.newProxyInstance(
064                            interfaceClass.getClassLoader(), new Class[] {interfaceClass},
065                            new ServiceTrackedInvocationHandler<>(interfaceClass));
066            }
067    
068            public static <T> T newServiceTrackedInstance(
069                    Class<T> interfaceClass, String filterString) {
070    
071                    return (T)ProxyUtil.newProxyInstance(
072                            interfaceClass.getClassLoader(), new Class[] {interfaceClass},
073                            new ServiceTrackedInvocationHandler<>(
074                                    interfaceClass, filterString));
075            }
076    
077            private static final Log _log = LogFactoryUtil.getLog(ProxyFactory.class);
078    
079            private static class DummyInvocationHandler<T>
080                    implements InvocationHandler {
081    
082                    @Override
083                    public Object invoke(Object proxy, Method method, Object[] arguments)
084                            throws Throwable {
085    
086                            Class<?> returnType = method.getReturnType();
087    
088                            if (returnType.equals(boolean.class)) {
089                                    return GetterUtil.DEFAULT_BOOLEAN;
090                            }
091                            else if (returnType.equals(byte.class)) {
092                                    return GetterUtil.DEFAULT_BYTE;
093                            }
094                            else if (returnType.equals(double.class)) {
095                                    return GetterUtil.DEFAULT_DOUBLE;
096                            }
097                            else if (returnType.equals(float.class)) {
098                                    return GetterUtil.DEFAULT_FLOAT;
099                            }
100                            else if (returnType.equals(int.class)) {
101                                    return GetterUtil.DEFAULT_INTEGER;
102                            }
103                            else if (returnType.equals(long.class)) {
104                                    return GetterUtil.DEFAULT_LONG;
105                            }
106                            else if (returnType.equals(short.class)) {
107                                    return GetterUtil.DEFAULT_SHORT;
108                            }
109    
110                            return method.getDefaultValue();
111                    }
112    
113            }
114    
115            private static class ServiceTrackedInvocationHandler<T>
116                    implements InvocationHandler {
117    
118                    @Override
119                    public Object invoke(Object proxy, Method method, Object[] arguments)
120                            throws Throwable {
121    
122                            T service = _serviceTracker.getService();
123    
124                            if (service != null) {
125                                    try {
126                                            return method.invoke(service, arguments);
127                                    }
128                                    catch (InvocationTargetException ite) {
129                                            throw ite.getTargetException();
130                                    }
131                            }
132    
133                            if (_log.isWarnEnabled()) {
134                                    _log.warn(
135                                            "Skipping " + method.getName() + " because " +
136                                                    _interfaceClassName + " is not registered");
137                            }
138    
139                            Class<?> returnType = method.getReturnType();
140    
141                            if (returnType.equals(boolean.class)) {
142                                    return GetterUtil.DEFAULT_BOOLEAN;
143                            }
144                            else if (returnType.equals(byte.class)) {
145                                    return GetterUtil.DEFAULT_BYTE;
146                            }
147                            else if (returnType.equals(double.class)) {
148                                    return GetterUtil.DEFAULT_DOUBLE;
149                            }
150                            else if (returnType.equals(float.class)) {
151                                    return GetterUtil.DEFAULT_FLOAT;
152                            }
153                            else if (returnType.equals(int.class)) {
154                                    return GetterUtil.DEFAULT_INTEGER;
155                            }
156                            else if (returnType.equals(long.class)) {
157                                    return GetterUtil.DEFAULT_LONG;
158                            }
159                            else if (returnType.equals(short.class)) {
160                                    return GetterUtil.DEFAULT_SHORT;
161                            }
162    
163                            return method.getDefaultValue();
164                    }
165    
166                    private ServiceTrackedInvocationHandler(Class<T> interfaceClass) {
167                            this(interfaceClass, null);
168                    }
169    
170                    private ServiceTrackedInvocationHandler(
171                            Class<T> interfaceClass, String filterString) {
172    
173                            _interfaceClassName = interfaceClass.getName();
174    
175                            Registry registry = RegistryUtil.getRegistry();
176    
177                            if (Validator.isNull(filterString)) {
178                                    _serviceTracker = registry.trackServices(interfaceClass);
179                            }
180                            else {
181                                    StringBundler sb = new StringBundler(7);
182    
183                                    sb.append("(&(objectClass=");
184                                    sb.append(_interfaceClassName);
185                                    sb.append(StringPool.CLOSE_PARENTHESIS);
186    
187                                    if (!filterString.startsWith(StringPool.OPEN_PARENTHESIS)) {
188                                            sb.append(StringPool.OPEN_PARENTHESIS);
189                                    }
190    
191                                    sb.append(filterString);
192    
193                                    if (!filterString.endsWith(StringPool.CLOSE_PARENTHESIS)) {
194                                            sb.append(StringPool.CLOSE_PARENTHESIS);
195                                    }
196    
197                                    sb.append(StringPool.CLOSE_PARENTHESIS);
198    
199                                    Filter filter = registry.getFilter(sb.toString());
200    
201                                    _serviceTracker = registry.trackServices(filter);
202                            }
203    
204                            _serviceTracker.open();
205                    }
206    
207                    private final String _interfaceClassName;
208                    private final ServiceTracker<T, T> _serviceTracker;
209    
210            }
211    
212    }