001    /**
002     * Copyright (c) 2000-2013 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.jsonwebservice.spring;
016    
017    import com.liferay.portal.kernel.annotation.AnnotationLocator;
018    import com.liferay.portal.kernel.jsonwebservice.JSONWebService;
019    import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceActionsManagerUtil;
020    import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceMappingResolver;
021    import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceMode;
022    import com.liferay.portal.kernel.log.Log;
023    import com.liferay.portal.kernel.log.LogFactoryUtil;
024    import com.liferay.portal.kernel.portlet.PortletClassLoaderUtil;
025    import com.liferay.portal.kernel.servlet.ServletContextPool;
026    import com.liferay.portal.kernel.util.PropsKeys;
027    import com.liferay.portal.kernel.util.PropsUtil;
028    import com.liferay.portal.kernel.util.SetUtil;
029    import com.liferay.portal.kernel.util.StringPool;
030    import com.liferay.portal.kernel.util.StringUtil;
031    import com.liferay.portal.util.PropsValues;
032    
033    import java.lang.reflect.Method;
034    
035    import java.util.HashMap;
036    import java.util.Map;
037    import java.util.Set;
038    
039    import javax.servlet.ServletContext;
040    
041    import org.springframework.beans.BeansException;
042    import org.springframework.beans.factory.config.BeanPostProcessor;
043    
044    /**
045     * @author Igor Spasic
046     */
047    public class JSONWebServiceDetectorBeanPostProcessor
048            implements BeanPostProcessor {
049    
050            public Object postProcessAfterInitialization(Object bean, String beanName)
051                    throws BeansException {
052    
053                    return bean;
054            }
055    
056            public Object postProcessBeforeInitialization(Object bean, String beanName)
057                    throws BeansException {
058    
059                    if (!PropsValues.JSON_WEB_SERVICE_ENABLED ||
060                            !beanName.endsWith("Service")) {
061    
062                            return bean;
063                    }
064    
065                    JSONWebService jsonWebService = AnnotationLocator.locate(
066                            bean.getClass(), JSONWebService.class);
067    
068                    if (jsonWebService != null) {
069                            try {
070                                    onJSONWebServiceBean(bean, jsonWebService);
071                            }
072                            catch (Exception e) {
073                                    _log.error(e, e);
074                            }
075                    }
076    
077                    return bean;
078            }
079    
080            protected Class<?> loadUtilClass(Class<?> implementationClass)
081                    throws ClassNotFoundException {
082    
083                    Class<?> utilClass = _utilClasses.get(implementationClass);
084    
085                    if (utilClass != null) {
086                            return utilClass;
087                    }
088    
089                    String implementationClassName = implementationClass.getName();
090    
091                    if (implementationClassName.endsWith("Impl")) {
092                            implementationClassName = implementationClassName.substring(
093                                    0, implementationClassName.length() - 4);
094                    }
095    
096                    String utilClassName = implementationClassName + "Util";
097    
098                    utilClassName = StringUtil.replace(
099                            utilClassName, ".impl.", StringPool.PERIOD);
100    
101                    ClassLoader classLoader = implementationClass.getClassLoader();
102    
103                    utilClass = classLoader.loadClass(utilClassName);
104    
105                    _utilClasses.put(implementationClass, utilClass);
106    
107                    return utilClass;
108            }
109    
110            protected void onJSONWebServiceBean(
111                            Object serviceBean, JSONWebService jsonWebService)
112                    throws Exception {
113    
114                    JSONWebServiceMode jsonWebServiceMode = JSONWebServiceMode.MANUAL;
115    
116                    if (jsonWebService != null) {
117                            jsonWebServiceMode = jsonWebService.mode();
118                    }
119    
120                    Class<?> serviceBeanClass = serviceBean.getClass();
121    
122                    Method[] methods = serviceBeanClass.getMethods();
123    
124                    for (Method method : methods) {
125                            Class<?> declaringClass = method.getDeclaringClass();
126    
127                            if (declaringClass != serviceBeanClass) {
128                                    continue;
129                            }
130    
131                            if ((_excludedMethodNames != null) &&
132                                    _excludedMethodNames.contains(method.getName())) {
133    
134                                    continue;
135                            }
136    
137                            JSONWebService methodJSONWebService = method.getAnnotation(
138                                    JSONWebService.class);
139    
140                            if (jsonWebServiceMode.equals(JSONWebServiceMode.AUTO)) {
141                                    if (methodJSONWebService == null) {
142                                            registerJSONWebServiceAction(serviceBean, method);
143                                    }
144                                    else {
145                                            JSONWebServiceMode methodJSONWebServiceMode =
146                                                    methodJSONWebService.mode();
147    
148                                            if (!methodJSONWebServiceMode.equals(
149                                                            JSONWebServiceMode.IGNORE)) {
150    
151                                                    registerJSONWebServiceAction(serviceBean, method);
152                                            }
153                                    }
154                            }
155                            else if (methodJSONWebService != null) {
156                                    JSONWebServiceMode methodJSONWebServiceMode =
157                                            methodJSONWebService.mode();
158    
159                                    if (!methodJSONWebServiceMode.equals(
160                                                    JSONWebServiceMode.IGNORE)) {
161    
162                                            registerJSONWebServiceAction(serviceBean, method);
163                                    }
164                            }
165                    }
166            }
167    
168            protected void registerJSONWebServiceAction(
169                            Object serviceBean, Method method)
170                    throws Exception {
171    
172                    String httpMethod = _jsonWebServiceMappingResolver.resolveHttpMethod(
173                            method);
174    
175                    if (_invalidHttpMethods.contains(httpMethod)) {
176                            return;
177                    }
178    
179                    String servletContextName =
180                            PortletClassLoaderUtil.getServletContextName();
181    
182                    if (servletContextName != null) {
183                            ServletContext servletContext = ServletContextPool.get(
184                                    servletContextName);
185    
186                            servletContextName = servletContext.getContextPath();
187                    }
188                    else {
189                            servletContextName = PropsValues.PORTAL_CTX;
190    
191                            if (servletContextName.equals(StringPool.SLASH)) {
192                                    servletContextName = StringPool.BLANK;
193                            }
194                    }
195    
196                    Class<?> serviceBeanClass = serviceBean.getClass();
197    
198                    Class<?> utilClass = loadUtilClass(serviceBeanClass);
199    
200                    try {
201                            method = utilClass.getMethod(
202                                    method.getName(), method.getParameterTypes());
203                    }
204                    catch (NoSuchMethodException nsme) {
205                            return;
206                    }
207    
208                    String path = _jsonWebServiceMappingResolver.resolvePath(
209                            serviceBeanClass, method);
210    
211                    JSONWebServiceActionsManagerUtil.registerJSONWebServiceAction(
212                            servletContextName, method.getDeclaringClass(), method, path,
213                            httpMethod);
214            }
215    
216            private static Log _log = LogFactoryUtil.getLog(
217                    JSONWebServiceDetectorBeanPostProcessor.class);
218    
219            private static Set<String> _excludedMethodNames = SetUtil.fromArray(
220                    new String[] {"getBeanIdentifier", "setBeanIdentifier"});
221    
222            private Set<String> _invalidHttpMethods = SetUtil.fromArray(
223                    PropsUtil.getArray(PropsKeys.JSONWS_WEB_SERVICE_INVALID_HTTP_METHODS));
224            private JSONWebServiceMappingResolver _jsonWebServiceMappingResolver =
225                    new JSONWebServiceMappingResolver();
226            private Map<Class<?>, Class<?>> _utilClasses =
227                    new HashMap<Class<?>, Class<?>>();
228    
229    }