001
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.jsonwebservice.JSONWebServiceActionMapping;
020 import com.liferay.portal.kernel.log.Log;
021 import com.liferay.portal.kernel.log.LogFactoryUtil;
022 import com.liferay.portal.kernel.util.CamelCaseUtil;
023 import com.liferay.portal.kernel.util.GetterUtil;
024 import com.liferay.portal.kernel.util.LocaleUtil;
025 import com.liferay.portal.kernel.util.MethodParameter;
026 import com.liferay.portal.kernel.util.StringPool;
027 import com.liferay.portal.service.ServiceContext;
028
029 import java.lang.reflect.Array;
030 import java.lang.reflect.Method;
031
032 import java.util.ArrayList;
033 import java.util.Calendar;
034 import java.util.Collection;
035 import java.util.HashMap;
036 import java.util.List;
037 import java.util.Locale;
038 import java.util.Map;
039
040 import jodd.bean.BeanCopy;
041 import jodd.bean.BeanUtil;
042
043 import jodd.typeconverter.TypeConverterManager;
044
045 import jodd.util.NameValue;
046 import jodd.util.ReflectUtil;
047
048
051 public class JSONWebServiceActionImpl implements JSONWebServiceAction {
052
053 public JSONWebServiceActionImpl(
054 JSONWebServiceActionConfig jsonWebServiceActionConfig,
055 JSONWebServiceActionParameters jsonWebServiceActionParameters) {
056
057 _jsonWebServiceActionConfig = jsonWebServiceActionConfig;
058 _jsonWebServiceActionParameters = jsonWebServiceActionParameters;
059 }
060
061 @Override
062 public JSONWebServiceActionMapping getJSONWebServiceActionMapping() {
063 return _jsonWebServiceActionConfig;
064 }
065
066 @Override
067 public Object invoke() throws Exception {
068 JSONRPCRequest jsonRPCRequest =
069 _jsonWebServiceActionParameters.getJSONRPCRequest();
070
071 if (jsonRPCRequest == null) {
072 return _invokeActionMethod();
073 }
074
075 Object result = null;
076 Exception exception = null;
077
078 try {
079 result = _invokeActionMethod();
080 }
081 catch (Exception e) {
082 exception = e;
083
084 _log.error(e, e);
085 }
086
087 return new JSONRPCResponse(jsonRPCRequest, result, exception);
088 }
089
090 private Object _convertListToArray(List<?> list, Class<?> componentType) {
091 Object array = Array.newInstance(componentType, list.size());
092
093 for (int i = 0; i < list.size(); i++) {
094 Object entry = list.get(i);
095
096 if (entry != null) {
097 entry = TypeConverterManager.convertType(entry, componentType);
098 }
099
100 Array.set(array, i, entry);
101 }
102
103 return array;
104 }
105
106 private Object _convertValueToParameterValue(
107 Object value, Class<?> parameterType,
108 Class<?>[] genericParameterTypes) {
109
110 if (parameterType.isArray()) {
111 List<?> list = null;
112
113 if (value instanceof List) {
114 list = (List<?>)value;
115 }
116 else {
117 String valueString = value.toString();
118
119 valueString = valueString.trim();
120
121 if (!valueString.startsWith(StringPool.OPEN_BRACKET)) {
122 valueString = StringPool.OPEN_BRACKET.concat(
123 valueString).concat(StringPool.CLOSE_BRACKET);
124 }
125
126 list = JSONFactoryUtil.looseDeserializeSafe(
127 valueString, ArrayList.class);
128 }
129
130 return _convertListToArray(list, parameterType.getComponentType());
131 }
132 else if (parameterType.equals(Calendar.class)) {
133 Calendar calendar = Calendar.getInstance();
134
135 calendar.setLenient(false);
136
137 String valueString = value.toString();
138
139 valueString = valueString.trim();
140
141 long timeInMillis = GetterUtil.getLong(valueString);
142
143 calendar.setTimeInMillis(timeInMillis);
144
145 return calendar;
146 }
147 else if (Collection.class.isAssignableFrom(parameterType)) {
148 List<?> list = null;
149
150 if (value instanceof List) {
151 list = (List<?>)value;
152 }
153 else {
154 String valueString = value.toString();
155
156 valueString = valueString.trim();
157
158 if (!valueString.startsWith(StringPool.OPEN_BRACKET)) {
159 valueString = StringPool.OPEN_BRACKET.concat(
160 valueString).concat(StringPool.CLOSE_BRACKET);
161 }
162
163 list = JSONFactoryUtil.looseDeserializeSafe(
164 valueString, ArrayList.class);
165 }
166
167 return _generifyList(list, genericParameterTypes);
168 }
169 else if (parameterType.equals(Locale.class)) {
170 String valueString = value.toString();
171
172 valueString = valueString.trim();
173
174 return LocaleUtil.fromLanguageId(valueString);
175 }
176 else if (parameterType.equals(Map.class)) {
177 Map<?, ?> map = null;
178
179 if (value instanceof Map) {
180 map = (Map<Object, Object>)value;
181 }
182 else {
183 String valueString = value.toString();
184
185 valueString = valueString.trim();
186
187 map = JSONFactoryUtil.looseDeserializeSafe(
188 valueString, HashMap.class);
189 }
190
191 return _generifyMap(map, genericParameterTypes);
192 }
193 else {
194 Object parameterValue = null;
195
196 try {
197 parameterValue = TypeConverterManager.convertType(
198 value, parameterType);
199 }
200 catch (Exception e1) {
201 if (value instanceof Map) {
202 try {
203 parameterValue = _createDefaultParameterValue(
204 null, parameterType);
205 }
206 catch (Exception e2) {
207 throw new ClassCastException(e1.getMessage());
208 }
209
210 BeanCopy beanCopy = BeanCopy.beans(value, parameterValue);
211
212 beanCopy.copy();
213 }
214 else {
215 String valueString = value.toString();
216
217 valueString = valueString.trim();
218
219 if (!valueString.startsWith(StringPool.OPEN_CURLY_BRACE)) {
220 throw new ClassCastException(e1.getMessage());
221 }
222
223 parameterValue = JSONFactoryUtil.looseDeserializeSafe(
224 valueString, parameterType);
225 }
226 }
227
228 return parameterValue;
229 }
230 }
231
232 private Object _createDefaultParameterValue(
233 String parameterName, Class<?> parameterType)
234 throws Exception {
235
236 if ((parameterName != null) && parameterName.equals("serviceContext") &&
237 parameterType.equals(ServiceContext.class)) {
238
239 ServiceContext serviceContext =
240 _jsonWebServiceActionParameters.getServiceContext();
241
242 if (serviceContext == null) {
243 serviceContext = new ServiceContext();
244 }
245
246 return serviceContext;
247 }
248
249 String className = parameterType.getName();
250
251 if (className.contains("com.liferay") && className.contains("Util")) {
252 throw new IllegalArgumentException(
253 "Not instantiating " + className);
254 }
255
256 return parameterType.newInstance();
257 }
258
259 private List<?> _generifyList(List<?> list, Class<?>[] types) {
260 if (types == null) {
261 return list;
262 }
263
264 if (types.length != 1) {
265 return list;
266 }
267
268 List<Object> newList = new ArrayList<Object>(list.size());
269
270 for (Object entry : list) {
271 if (entry != null) {
272 entry = TypeConverterManager.convertType(entry, types[0]);
273 }
274
275 newList.add(entry);
276 }
277
278 return newList;
279 }
280
281 private Map<?, ?> _generifyMap(Map<?, ?> map, Class<?>[] types) {
282 if (types == null) {
283 return map;
284 }
285
286 if (types.length != 2) {
287 return map;
288 }
289
290 Map<Object, Object> newMap = new HashMap<Object, Object>(map.size());
291
292 for (Map.Entry<?, ?> entry : map.entrySet()) {
293 Object key = TypeConverterManager.convertType(
294 entry.getKey(), types[0]);
295
296 Object value = entry.getValue();
297
298 if (value != null) {
299 value = TypeConverterManager.convertType(value, types[1]);
300 }
301
302 newMap.put(key, value);
303 }
304
305 return newMap;
306 }
307
308 private void _injectInnerParametersIntoValue(
309 String parameterName, Object parameterValue) {
310
311 if (parameterValue == null) {
312 return;
313 }
314
315 List<NameValue<String, Object>> innerParameters =
316 _jsonWebServiceActionParameters.getInnerParameters(parameterName);
317
318 if (innerParameters == null) {
319 return;
320 }
321
322 for (NameValue<String, Object> innerParameter : innerParameters) {
323 try {
324 BeanUtil.setProperty(
325 parameterValue, innerParameter.getName(),
326 innerParameter.getValue());
327 }
328 catch (Exception e) {
329 if (_log.isDebugEnabled()) {
330 _log.debug(
331 "Unable to set inner parameter " + parameterName + "." +
332 innerParameter.getName(),
333 e);
334 }
335 }
336 }
337 }
338
339 private Object _invokeActionMethod() throws Exception {
340 Object actionObject = _jsonWebServiceActionConfig.getActionObject();
341
342 Method actionMethod = _jsonWebServiceActionConfig.getActionMethod();
343
344 Class<?> actionClass = _jsonWebServiceActionConfig.getActionClass();
345
346 Object[] parameters = _prepareParameters(actionClass);
347
348 return actionMethod.invoke(actionObject, parameters);
349 }
350
351 private Object[] _prepareParameters(Class<?> actionClass) throws Exception {
352 MethodParameter[] methodParameters =
353 _jsonWebServiceActionConfig.getMethodParameters();
354
355 Object[] parameters = new Object[methodParameters.length];
356
357 for (int i = 0; i < methodParameters.length; i++) {
358 String parameterName = methodParameters[i].getName();
359
360 parameterName = CamelCaseUtil.normalizeCamelCase(parameterName);
361
362 Object value = _jsonWebServiceActionParameters.getParameter(
363 parameterName);
364
365 Object parameterValue = null;
366
367 if (value != null) {
368 Class<?> parameterType = methodParameters[i].getType();
369
370 String parameterTypeName =
371 _jsonWebServiceActionParameters.getParameterTypeName(
372 parameterName);
373
374 if (parameterTypeName != null) {
375 ClassLoader classLoader = actionClass.getClassLoader();
376
377 parameterType = classLoader.loadClass(parameterTypeName);
378
379 if (!ReflectUtil.isSubclass(
380 parameterType, methodParameters[i].getType())) {
381
382 throw new IllegalArgumentException(
383 "Unmatched argument type " +
384 parameterType.getName() +
385 " for method argument " + i);
386 }
387 }
388
389 if (value.equals(Void.TYPE)) {
390 parameterValue = _createDefaultParameterValue(
391 parameterName, parameterType);
392 }
393 else {
394 parameterValue = _convertValueToParameterValue(
395 value, parameterType,
396 methodParameters[i].getGenericTypes());
397
398 ServiceContext serviceContext =
399 _jsonWebServiceActionParameters.getServiceContext();
400
401 if ((serviceContext != null) &&
402 parameterName.equals("serviceContext")) {
403
404 if ((parameterValue != null) &&
405 ServiceContext.class.isAssignableFrom(
406 parameterValue.getClass())) {
407
408 serviceContext.merge(
409 (ServiceContext)parameterValue);
410 }
411
412 parameterValue = serviceContext;
413 }
414 }
415 }
416
417 _injectInnerParametersIntoValue(parameterName, parameterValue);
418
419 parameters[i] = parameterValue;
420 }
421
422 return parameters;
423 }
424
425 private static Log _log = LogFactoryUtil.getLog(
426 JSONWebServiceActionImpl.class);
427
428 private JSONWebServiceActionConfig _jsonWebServiceActionConfig;
429 private JSONWebServiceActionParameters _jsonWebServiceActionParameters;
430
431 }