001    /**
002     * Copyright (c) 2000-2011 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.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                            Object value =
156                                    _jsonWebServiceActionParameters.getParameter(parameterName);
157    
158                            Object parameterValue = null;
159    
160                            if (value != null) {
161                                    Class<?> parameterType = methodParameters[i].getType();
162    
163                                    if (value.equals(Void.TYPE)) {
164                                            String parameterTypeName =
165                                                    _jsonWebServiceActionParameters.getParameterTypeName(
166                                                            parameterName);
167    
168                                            if (parameterTypeName != null) {
169                                                    ClassLoader classLoader = actionClass.getClassLoader();
170    
171                                                    parameterType = classLoader.loadClass(
172                                                            parameterTypeName);
173                                            }
174    
175                                            parameterValue = _createDefaultParameterValue(
176                                                    parameterName, parameterType);
177                                    }
178                                    else if (parameterType.equals(Calendar.class)) {
179                                            Calendar calendar = Calendar.getInstance();
180    
181                                            calendar.setLenient(false);
182                                            calendar.setTimeInMillis(Long.parseLong(value.toString()));
183    
184                                            parameterValue = calendar;
185                                    }
186                                    else if (parameterType.equals(List.class)) {
187                                            List<?> list = JSONFactoryUtil.looseDeserialize(
188                                                    value.toString(), ArrayList.class);
189    
190                                            list = _generifyList(
191                                                    list, methodParameters[i].getGenericTypes());
192    
193                                            parameterValue = list;
194                                    }
195                                    else if (parameterType.equals(Locale.class)) {
196                                            parameterValue = LocaleUtil.fromLanguageId(
197                                                    value.toString());
198                                    }
199                                    else if (parameterType.equals(Map.class)) {
200                                            Map<?, ?> map = JSONFactoryUtil.looseDeserialize(
201                                                    value.toString(), HashMap.class);
202    
203                                            map = _generifyMap(
204                                                    map, methodParameters[i].getGenericTypes());
205    
206                                            parameterValue = map;
207                                    }
208                                    else {
209                                            parameterValue = ReflectUtil.castType(value, parameterType);
210                                    }
211                            }
212    
213                            if (parameterValue != null) {
214                                    List<KeyValue<String, Object>> innerParameters =
215                                            _jsonWebServiceActionParameters.getInnerParameters(
216                                                    parameterName);
217    
218                                    if (innerParameters != null) {
219                                            for (KeyValue<String, Object> innerParameter :
220                                                            innerParameters) {
221    
222                                                    BeanUtil.setPropertySilent(
223                                                            parameterValue, innerParameter.getKey(),
224                                                            innerParameter.getValue());
225                                            }
226                                    }
227                            }
228    
229                            parameters[i] = parameterValue;
230                    }
231    
232                    return parameters;
233            }
234    
235            private static Log _log = LogFactoryUtil.getLog(
236                    JSONWebServiceActionImpl.class);
237    
238            private JSONWebServiceActionConfig _jsonWebServiceActionConfig;
239            private JSONWebServiceActionParameters _jsonWebServiceActionParameters;
240    
241    }