001    /**
002     * Copyright (c) 2000-2012 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;
016    
017    import com.liferay.portal.kernel.json.JSONFactoryUtil;
018    import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceAction;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.util.LocaleUtil;
022    import com.liferay.portal.kernel.util.MethodParameter;
023    import com.liferay.portal.service.ServiceContext;
024    
025    import java.lang.reflect.Method;
026    
027    import java.util.ArrayList;
028    import java.util.Calendar;
029    import java.util.HashMap;
030    import java.util.List;
031    import java.util.Locale;
032    import java.util.Map;
033    
034    import jodd.bean.BeanUtil;
035    
036    import jodd.util.KeyValue;
037    import jodd.util.ReflectUtil;
038    
039    /**
040     * @author Igor Spasic
041     */
042    public class JSONWebServiceActionImpl implements JSONWebServiceAction {
043    
044            public JSONWebServiceActionImpl(
045                    JSONWebServiceActionConfig jsonWebServiceActionConfig,
046                    JSONWebServiceActionParameters jsonWebServiceActionParameters) {
047    
048                    _jsonWebServiceActionConfig = jsonWebServiceActionConfig;
049                    _jsonWebServiceActionParameters = jsonWebServiceActionParameters;
050            }
051    
052            public Object invoke() throws Exception {
053                    JSONRPCRequest jsonRpcRequest =
054                            _jsonWebServiceActionParameters.getJSONRPCRequest();
055    
056                    if (jsonRpcRequest == null) {
057                            return _invokeActionMethod();
058                    }
059    
060                    Object result = null;
061                    Exception exception = null;
062    
063                    try {
064                            result = _invokeActionMethod();
065                    }
066                    catch (Exception e) {
067                            exception = e;
068    
069                            _log.error(e, e);
070                    }
071    
072                    return new JSONRPCResponse(jsonRpcRequest, result, exception);
073            }
074    
075            private Object _createDefaultParameterValue(
076                            String parameterName, Class<?> parameterType)
077                    throws Exception {
078    
079                    if (parameterName.equals("serviceContext") &&
080                            parameterType.equals(ServiceContext.class)) {
081    
082                            return new ServiceContext();
083                    }
084    
085                    return parameterType.newInstance();
086            }
087    
088            private List<?> _generifyList(List<?> list, Class<?>[] types) {
089                    if (types == null) {
090                            return list;
091                    }
092    
093                    if (types.length != 1) {
094                            return list;
095                    }
096    
097                    List<Object> newList = new ArrayList<Object>(list.size());
098    
099                    for (Object entry : list) {
100                            if (entry != null) {
101                                    entry = ReflectUtil.castType(entry, types[0]);
102                            }
103    
104                            newList.add(entry);
105                    }
106    
107                    return newList;
108            }
109    
110            private Map<?, ?> _generifyMap(Map<?, ?> map, Class<?>[] types) {
111                    if (types == null) {
112                            return map;
113                    }
114    
115                    if (types.length != 2) {
116                            return map;
117                    }
118    
119                    Map<Object, Object> newMap = new HashMap<Object, Object>(map.size());
120    
121                    for (Map.Entry<?, ?> entry : map.entrySet()) {
122                            Object key = ReflectUtil.castType(entry.getKey(), types[0]);
123    
124                            Object value = entry.getValue();
125    
126                            if (value != null) {
127                                    value = ReflectUtil.castType(value, types[1]);
128                            }
129    
130                            newMap.put(key, value);
131                    }
132    
133                    return newMap;
134            }
135    
136            private Object _invokeActionMethod() throws Exception {
137                    Method actionMethod = _jsonWebServiceActionConfig.getActionMethod();
138    
139                    Class<?> actionClass = _jsonWebServiceActionConfig.getActionClass();
140    
141                    Object[] parameters = _prepareParameters(actionClass);
142    
143                    return actionMethod.invoke(actionClass, parameters);
144            }
145    
146            private Object[] _prepareParameters(Class<?> actionClass) throws Exception {
147                    MethodParameter[] methodParameters =
148                            _jsonWebServiceActionConfig.getMethodParameters();
149    
150                    Object[] parameters = new Object[methodParameters.length];
151    
152                    for (int i = 0; i < methodParameters.length; i++) {
153                            String parameterName = methodParameters[i].getName();
154    
155                            parameterName = CamelCaseUtil.normalizeCamelCase(parameterName);
156    
157                            Object value = _jsonWebServiceActionParameters.getParameter(
158                                    parameterName);
159    
160                            Object parameterValue = null;
161    
162                            if (value != null) {
163                                    Class<?> parameterType = methodParameters[i].getType();
164    
165                                    if (value.equals(Void.TYPE)) {
166                                            String parameterTypeName =
167                                                    _jsonWebServiceActionParameters.getParameterTypeName(
168                                                            parameterName);
169    
170                                            if (parameterTypeName != null) {
171                                                    ClassLoader classLoader = actionClass.getClassLoader();
172    
173                                                    parameterType = classLoader.loadClass(
174                                                            parameterTypeName);
175                                            }
176    
177                                            parameterValue = _createDefaultParameterValue(
178                                                    parameterName, parameterType);
179                                    }
180                                    else if (parameterType.equals(Calendar.class)) {
181                                            Calendar calendar = Calendar.getInstance();
182    
183                                            calendar.setLenient(false);
184                                            calendar.setTimeInMillis(Long.parseLong(value.toString()));
185    
186                                            parameterValue = calendar;
187                                    }
188                                    else if (parameterType.equals(List.class)) {
189                                            List<?> list = JSONFactoryUtil.looseDeserialize(
190                                                    value.toString(), ArrayList.class);
191    
192                                            list = _generifyList(
193                                                    list, methodParameters[i].getGenericTypes());
194    
195                                            parameterValue = list;
196                                    }
197                                    else if (parameterType.equals(Locale.class)) {
198                                            parameterValue = LocaleUtil.fromLanguageId(
199                                                    value.toString());
200                                    }
201                                    else if (parameterType.equals(Map.class)) {
202                                            Map<?, ?> map = JSONFactoryUtil.looseDeserialize(
203                                                    value.toString(), HashMap.class);
204    
205                                            map = _generifyMap(
206                                                    map, methodParameters[i].getGenericTypes());
207    
208                                            parameterValue = map;
209                                    }
210                                    else {
211                                            parameterValue = ReflectUtil.castType(value, parameterType);
212                                    }
213                            }
214    
215                            if (parameterValue != null) {
216                                    List<KeyValue<String, Object>> innerParameters =
217                                            _jsonWebServiceActionParameters.getInnerParameters(
218                                                    parameterName);
219    
220                                    if (innerParameters != null) {
221                                            for (KeyValue<String, Object> innerParameter :
222                                                            innerParameters) {
223    
224                                                    BeanUtil.setPropertySilent(
225                                                            parameterValue, innerParameter.getKey(),
226                                                            innerParameter.getValue());
227                                            }
228                                    }
229                            }
230    
231                            parameters[i] = parameterValue;
232                    }
233    
234                    return parameters;
235            }
236    
237            private static Log _log = LogFactoryUtil.getLog(
238                    JSONWebServiceActionImpl.class);
239    
240            private JSONWebServiceActionConfig _jsonWebServiceActionConfig;
241            private JSONWebServiceActionParameters _jsonWebServiceActionParameters;
242    
243    }