/** * 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.jsonwebservice; import com.liferay.portal.kernel.annotation.AnnotationLocator; import com.liferay.portal.kernel.bean.BeanLocator; import com.liferay.portal.kernel.bean.BeanLocatorException; import com.liferay.portal.kernel.bean.ClassLoaderBeanHandler; import com.liferay.portal.kernel.jsonwebservice.JSONWebService; import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceActionsManagerUtil; import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceMappingResolver; import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceMode; import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceNaming; import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceRegistrator; import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceScannerStrategy; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.service.ServiceWrapper; import com.liferay.portal.kernel.util.ProxyUtil; import com.liferay.portal.spring.aop.AdvisedSupportProxy; import com.liferay.portal.spring.aop.ServiceBeanAopProxy; import com.liferay.portal.util.PropsValues; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import org.springframework.aop.TargetSource; import org.springframework.aop.framework.AdvisedSupport; /** * @author Igor Spasic */ public class DefaultJSONWebServiceRegistrator implements JSONWebServiceRegistrator { public DefaultJSONWebServiceRegistrator() { _jsonWebServiceNaming = JSONWebServiceActionsManagerUtil.getJSONWebServiceNaming(); _jsonWebServiceMappingResolver = new JSONWebServiceMappingResolver( _jsonWebServiceNaming); _jsonWebServiceScannerStrategy = new SpringJSONWebServiceScannerStrategy(); } public DefaultJSONWebServiceRegistrator( JSONWebServiceNaming jsonWebServiceNaming, JSONWebServiceScannerStrategy jsonWebServiceScannerStrategy) { _jsonWebServiceNaming = jsonWebServiceNaming; _jsonWebServiceScannerStrategy = jsonWebServiceScannerStrategy; _jsonWebServiceMappingResolver = new JSONWebServiceMappingResolver( _jsonWebServiceNaming); } public DefaultJSONWebServiceRegistrator( JSONWebServiceScannerStrategy jsonWebServiceScannerStrategy) { this( JSONWebServiceActionsManagerUtil.getJSONWebServiceNaming(), jsonWebServiceScannerStrategy); } public void processAllBeans( String contextName, String contextPath, BeanLocator beanLocator) { if (beanLocator == null) { return; } String[] beanNames = beanLocator.getNames(); for (String beanName : beanNames) { processBean(contextName, contextPath, beanLocator, beanName); } } public void processBean( String contextName, String contextPath, BeanLocator beanLocator, String beanName) { if (!PropsValues.JSON_WEB_SERVICE_ENABLED) { return; } Object bean = null; try { bean = beanLocator.locate(beanName); } catch (BeanLocatorException ble) { return; } if (bean == null) { return; } Class<?> targetClass = null; try { targetClass = getTargetClass(bean); } catch (Exception e) { _log.error( "Unable to compute target class of bean " + beanName + " with type " + bean.getClass(), e); return; } JSONWebService jsonWebService = AnnotationLocator.locate( targetClass, JSONWebService.class); if (jsonWebService != null) { try { onJSONWebServiceBean( contextName, contextPath, bean, jsonWebService); } catch (Exception e) { _log.error(e, e); } } } @Override public void processBean( String contextName, String contextPath, Object bean) { if (!PropsValues.JSON_WEB_SERVICE_ENABLED) { return; } JSONWebService jsonWebService = AnnotationLocator.locate( bean.getClass(), JSONWebService.class); if (jsonWebService == null) { return; } try { onJSONWebServiceBean( contextName, contextPath, bean, jsonWebService); } catch (Exception e) { _log.error(e, e); } } public void setWireViaUtil(boolean wireViaUtil) { _wireViaUtil = wireViaUtil; } protected Class<?> getTargetClass(Object service) throws Exception { while (ProxyUtil.isProxyClass(service.getClass())) { InvocationHandler invocationHandler = ProxyUtil.getInvocationHandler(service); if (invocationHandler instanceof AdvisedSupportProxy) { AdvisedSupport advisedSupport = ServiceBeanAopProxy.getAdvisedSupport(service); TargetSource targetSource = advisedSupport.getTargetSource(); service = targetSource.getTarget(); } else if (invocationHandler instanceof ClassLoaderBeanHandler) { ClassLoaderBeanHandler classLoaderBeanHandler = (ClassLoaderBeanHandler)invocationHandler; Object bean = classLoaderBeanHandler.getBean(); if (bean instanceof ServiceWrapper) { ServiceWrapper<?> serviceWrapper = (ServiceWrapper<?>)bean; service = serviceWrapper.getWrappedService(); } else { service = bean; } } else { if (_log.isDebugEnabled()) { _log.debug( "Unable to handle proxy of type " + invocationHandler); } break; } } return service.getClass(); } protected Class<?> loadUtilClass(Class<?> implementationClass) throws ClassNotFoundException { if (_utilClasses == null) { _utilClasses = new HashMap<>(); } Class<?> utilClass = _utilClasses.get(implementationClass); if (utilClass != null) { return utilClass; } String utilClassName = _jsonWebServiceNaming.convertServiceImplClassToUtilClassName( implementationClass); ClassLoader classLoader = implementationClass.getClassLoader(); utilClass = classLoader.loadClass(utilClassName); _utilClasses.put(implementationClass, utilClass); return utilClass; } protected void onJSONWebServiceBean( String contextName, String contextPath, Object serviceBean, JSONWebService jsonWebService) throws Exception { JSONWebServiceMode jsonWebServiceMode = JSONWebServiceMode.MANUAL; if (jsonWebService != null) { jsonWebServiceMode = jsonWebService.mode(); } JSONWebServiceScannerStrategy.MethodDescriptor[] methodDescriptors = _jsonWebServiceScannerStrategy.scan(serviceBean); for (JSONWebServiceScannerStrategy.MethodDescriptor methodDescriptor : methodDescriptors) { Method method = methodDescriptor.getMethod(); JSONWebService methodJSONWebService = method.getAnnotation( JSONWebService.class); if (methodJSONWebService == null) { if (!jsonWebServiceMode.equals(JSONWebServiceMode.AUTO)) { continue; } } else { JSONWebServiceMode methodJSONWebServiceMode = methodJSONWebService.mode(); if (methodJSONWebServiceMode.equals( JSONWebServiceMode.IGNORE)) { continue; } } Class<?> serviceBeanClass = methodDescriptor.getDeclaringClass(); String httpMethod = _jsonWebServiceMappingResolver.resolveHttpMethod(method); if (!_jsonWebServiceNaming.isValidHttpMethod(httpMethod)) { continue; } if (_wireViaUtil) { Class<?> utilClass = loadUtilClass(serviceBeanClass); try { method = utilClass.getMethod( method.getName(), method.getParameterTypes()); } catch (NoSuchMethodException nsme) { continue; } } String path = _jsonWebServiceMappingResolver.resolvePath( serviceBeanClass, method); if (!_jsonWebServiceNaming.isIncludedPath(contextPath, path)) { continue; } if (_jsonWebServiceNaming.isIncludedMethod(method)) { if (_wireViaUtil) { JSONWebServiceActionsManagerUtil. registerJSONWebServiceAction( contextName, contextPath, method.getDeclaringClass(), method, path, httpMethod); } else { JSONWebServiceActionsManagerUtil. registerJSONWebServiceAction( contextName, contextPath, serviceBean, serviceBeanClass, method, path, httpMethod); } } } } private static final Log _log = LogFactoryUtil.getLog( DefaultJSONWebServiceRegistrator.class); private final JSONWebServiceMappingResolver _jsonWebServiceMappingResolver; private final JSONWebServiceNaming _jsonWebServiceNaming; private final JSONWebServiceScannerStrategy _jsonWebServiceScannerStrategy; private Map<Class<?>, Class<?>> _utilClasses; private boolean _wireViaUtil; }