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