001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portal.jsonwebservice;
016    
017    import com.liferay.portal.kernel.annotation.AnnotationLocator;
018    import com.liferay.portal.kernel.bean.BeanLocator;
019    import com.liferay.portal.kernel.bean.BeanLocatorException;
020    import com.liferay.portal.kernel.bean.ClassLoaderBeanHandler;
021    import com.liferay.portal.kernel.jsonwebservice.JSONWebService;
022    import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceActionsManagerUtil;
023    import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceMappingResolver;
024    import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceMode;
025    import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceNaming;
026    import com.liferay.portal.kernel.log.Log;
027    import com.liferay.portal.kernel.log.LogFactoryUtil;
028    import com.liferay.portal.kernel.util.ProxyUtil;
029    import com.liferay.portal.service.ServiceWrapper;
030    import com.liferay.portal.spring.aop.ServiceBeanAopProxy;
031    import com.liferay.portal.util.PropsValues;
032    
033    import java.lang.reflect.InvocationHandler;
034    import java.lang.reflect.Method;
035    
036    import java.util.HashMap;
037    import java.util.Map;
038    
039    import org.springframework.aop.TargetSource;
040    import org.springframework.aop.framework.AdvisedSupport;
041    
042    /**
043     * @author Igor Spasic
044     */
045    public class JSONWebServiceRegistrator {
046    
047            public JSONWebServiceRegistrator() {
048                    _jsonWebServiceNaming = new JSONWebServiceNaming();
049    
050                    _jsonWebServiceMappingResolver = new JSONWebServiceMappingResolver(
051                            _jsonWebServiceNaming);
052            }
053    
054            public JSONWebServiceRegistrator(
055                    JSONWebServiceNaming jsonWebServiceNaming) {
056    
057                    _jsonWebServiceNaming = jsonWebServiceNaming;
058    
059                    _jsonWebServiceMappingResolver = new JSONWebServiceMappingResolver(
060                            _jsonWebServiceNaming);
061            }
062    
063            public void processAllBeans(String contextPath, BeanLocator beanLocator) {
064                    if (beanLocator == null) {
065                            return;
066                    }
067    
068                    String[] beanNames = beanLocator.getNames();
069    
070                    for (String beanName : beanNames) {
071                            processBean(contextPath, beanLocator, beanName);
072                    }
073            }
074    
075            public void processBean(
076                    String contextPath, BeanLocator beanLocator, String beanName) {
077    
078                    if (!PropsValues.JSON_WEB_SERVICE_ENABLED) {
079                            return;
080                    }
081    
082                    Object bean = null;
083    
084                    try {
085                            bean = beanLocator.locate(beanName);
086                    }
087                    catch (BeanLocatorException ble) {
088                            return;
089                    }
090    
091                    if (bean == null) {
092                            return;
093                    }
094    
095                    Class<?> targetClass = null;
096    
097                    try {
098                            targetClass = getTargetClass(bean);
099                    }
100                    catch (Exception e) {
101                            _log.error(
102                                    "Unable to compute target class of bean " + beanName +
103                                            " with type " + bean.getClass(),
104                                    e);
105    
106                            return;
107                    }
108    
109                    JSONWebService jsonWebService = AnnotationLocator.locate(
110                            targetClass, JSONWebService.class);
111    
112                    if (jsonWebService != null) {
113                            try {
114                                    onJSONWebServiceBean(contextPath, bean, jsonWebService);
115                            }
116                            catch (Exception e) {
117                                    _log.error(e, e);
118                            }
119                    }
120            }
121    
122            public void processBean(String contextPath, Object bean) {
123                    if (!PropsValues.JSON_WEB_SERVICE_ENABLED) {
124                            return;
125                    }
126    
127                    JSONWebService jsonWebService = AnnotationLocator.locate(
128                            bean.getClass(), JSONWebService.class);
129    
130                    if (jsonWebService == null) {
131                            return;
132                    }
133    
134                    try {
135                            onJSONWebServiceBean(contextPath, bean, jsonWebService);
136                    }
137                    catch (Exception e) {
138                            _log.error(e, e);
139                    }
140            }
141    
142            public void setWireViaUtil(boolean wireViaUtil) {
143                    this._wireViaUtil = wireViaUtil;
144            }
145    
146            protected Class<?> getTargetClass(Object service) throws Exception {
147                    while (ProxyUtil.isProxyClass(service.getClass())) {
148                            InvocationHandler invocationHandler =
149                                    ProxyUtil.getInvocationHandler(service);
150    
151                            if (invocationHandler instanceof ServiceBeanAopProxy) {
152                                    AdvisedSupport advisedSupport =
153                                            ServiceBeanAopProxy.getAdvisedSupport(service);
154    
155                                    TargetSource targetSource = advisedSupport.getTargetSource();
156    
157                                    service = targetSource.getTarget();
158                            }
159                            else if (invocationHandler instanceof ClassLoaderBeanHandler) {
160                                    ClassLoaderBeanHandler classLoaderBeanHandler =
161                                            (ClassLoaderBeanHandler)invocationHandler;
162    
163                                    Object bean = classLoaderBeanHandler.getBean();
164    
165                                    if (bean instanceof ServiceWrapper) {
166                                            ServiceWrapper<?> serviceWrapper = (ServiceWrapper<?>)bean;
167    
168                                            service = serviceWrapper.getWrappedService();
169                                    }
170                                    else {
171                                            service = bean;
172                                    }
173                            }
174                            else {
175                                    if (_log.isDebugEnabled()) {
176                                            _log.debug(
177                                                    "Unable to handle proxy of type " + invocationHandler);
178                                    }
179    
180                                    break;
181                            }
182                    }
183    
184                    return service.getClass();
185            }
186    
187            protected Class<?> loadUtilClass(Class<?> implementationClass)
188                    throws ClassNotFoundException {
189    
190                    if (_utilClasses == null) {
191                            _utilClasses = new HashMap<Class<?>, Class<?>>();
192                    }
193    
194                    Class<?> utilClass = _utilClasses.get(implementationClass);
195    
196                    if (utilClass != null) {
197                            return utilClass;
198                    }
199    
200                    String utilClassName =
201                            _jsonWebServiceNaming.convertImplClassNameToUtilClassName(
202                                    implementationClass);
203    
204                    ClassLoader classLoader = implementationClass.getClassLoader();
205    
206                    utilClass = classLoader.loadClass(utilClassName);
207    
208                    _utilClasses.put(implementationClass, utilClass);
209    
210                    return utilClass;
211            }
212    
213            protected void onJSONWebServiceBean(
214                            String contextPath, Object serviceBean,
215                            JSONWebService jsonWebService)
216                    throws Exception {
217    
218                    JSONWebServiceMode jsonWebServiceMode = JSONWebServiceMode.MANUAL;
219    
220                    if (jsonWebService != null) {
221                            jsonWebServiceMode = jsonWebService.mode();
222                    }
223    
224                    Class<?> serviceBeanClass = getTargetClass(serviceBean);
225    
226                    Method[] methods = serviceBeanClass.getMethods();
227    
228                    for (Method method : methods) {
229                            Class<?> declaringClass = method.getDeclaringClass();
230    
231                            if (declaringClass != serviceBeanClass) {
232                                    continue;
233                            }
234    
235                            if (!_jsonWebServiceNaming.isIncludedMethod(method)) {
236                                    continue;
237                            }
238    
239                            JSONWebService methodJSONWebService = method.getAnnotation(
240                                    JSONWebService.class);
241    
242                            if (jsonWebServiceMode.equals(JSONWebServiceMode.AUTO)) {
243                                    if (methodJSONWebService == null) {
244                                            registerJSONWebServiceAction(
245                                                    contextPath, serviceBean, serviceBeanClass, method);
246                                    }
247                                    else {
248                                            JSONWebServiceMode methodJSONWebServiceMode =
249                                                    methodJSONWebService.mode();
250    
251                                            if (!methodJSONWebServiceMode.equals(
252                                                            JSONWebServiceMode.IGNORE)) {
253    
254                                                    registerJSONWebServiceAction(
255                                                            contextPath, serviceBean, serviceBeanClass, method);
256                                            }
257                                    }
258                            }
259                            else if (methodJSONWebService != null) {
260                                    JSONWebServiceMode methodJSONWebServiceMode =
261                                            methodJSONWebService.mode();
262    
263                                    if (!methodJSONWebServiceMode.equals(
264                                                    JSONWebServiceMode.IGNORE)) {
265    
266                                            registerJSONWebServiceAction(
267                                                    contextPath, serviceBean, serviceBeanClass, method);
268                                    }
269                            }
270                    }
271            }
272    
273            protected void registerJSONWebServiceAction(
274                            String contextPath, Object serviceBean, Class<?> serviceBeanClass,
275                            Method method)
276                    throws Exception {
277    
278                    String httpMethod = _jsonWebServiceMappingResolver.resolveHttpMethod(
279                            method);
280    
281                    if (!_jsonWebServiceNaming.isValidHttpMethod(httpMethod)) {
282                            return;
283                    }
284    
285                    if (_wireViaUtil) {
286                            Class<?> utilClass = loadUtilClass(serviceBeanClass);
287    
288                            try {
289                                    method = utilClass.getMethod(
290                                            method.getName(), method.getParameterTypes());
291                            }
292                            catch (NoSuchMethodException nsme) {
293                                    return;
294                            }
295                    }
296    
297                    String path = _jsonWebServiceMappingResolver.resolvePath(
298                            serviceBeanClass, method);
299    
300                    if (!_jsonWebServiceNaming.isIncludedPath(contextPath, path)) {
301                            return;
302                    }
303    
304                    if (_wireViaUtil) {
305                            JSONWebServiceActionsManagerUtil.registerJSONWebServiceAction(
306                                    contextPath, method.getDeclaringClass(), method, path,
307                                    httpMethod);
308                    }
309                    else {
310                            JSONWebServiceActionsManagerUtil.registerJSONWebServiceAction(
311                                    contextPath, serviceBean, serviceBeanClass, method, path,
312                                    httpMethod);
313                    }
314            }
315    
316            private static Log _log = LogFactoryUtil.getLog(
317                    JSONWebServiceRegistrator.class);
318    
319            private final JSONWebServiceMappingResolver _jsonWebServiceMappingResolver;
320            private final JSONWebServiceNaming _jsonWebServiceNaming;
321            private Map<Class<?>, Class<?>> _utilClasses;
322            private boolean _wireViaUtil;
323    
324    }