1
14
15 package com.liferay.portal.action;
16
17 import com.liferay.portal.kernel.json.JSONArray;
18 import com.liferay.portal.kernel.json.JSONException;
19 import com.liferay.portal.kernel.json.JSONFactoryUtil;
20 import com.liferay.portal.kernel.json.JSONObject;
21 import com.liferay.portal.kernel.log.Log;
22 import com.liferay.portal.kernel.log.LogFactoryUtil;
23 import com.liferay.portal.kernel.util.ArrayUtil;
24 import com.liferay.portal.kernel.util.GetterUtil;
25 import com.liferay.portal.kernel.util.ListUtil;
26 import com.liferay.portal.kernel.util.MethodHandler;
27 import com.liferay.portal.kernel.util.MethodKey;
28 import com.liferay.portal.kernel.util.ParamUtil;
29 import com.liferay.portal.kernel.util.StringUtil;
30 import com.liferay.portal.kernel.util.Validator;
31 import com.liferay.portal.model.BaseModel;
32 import com.liferay.portal.service.ServiceContext;
33 import com.liferay.portal.service.ServiceContextUtil;
34 import com.liferay.portal.struts.JSONAction;
35 import com.liferay.portal.util.PropsValues;
36 import com.liferay.portlet.tags.model.TagsAssetDisplay;
37 import com.liferay.portlet.tags.model.TagsAssetType;
38
39 import java.lang.reflect.InvocationTargetException;
40 import java.lang.reflect.Method;
41
42 import java.util.Arrays;
43 import java.util.Date;
44 import java.util.HashMap;
45 import java.util.HashSet;
46 import java.util.List;
47 import java.util.Map;
48 import java.util.Set;
49
50 import javax.servlet.http.HttpServletRequest;
51 import javax.servlet.http.HttpServletResponse;
52
53 import org.apache.struts.action.ActionForm;
54 import org.apache.struts.action.ActionMapping;
55
56
62 public class JSONServiceAction extends JSONAction {
63
64 public JSONServiceAction() {
65 _invalidClassNames.addAll(
66 ListUtil.fromArray(PropsValues.JSON_SERVICE_INVALID_CLASS_NAMES));
67
68 if (_log.isDebugEnabled()) {
69 for (String invalidClassName : _invalidClassNames) {
70 _log.debug("Invalid class name " + invalidClassName);
71 }
72 }
73 }
74
75 public String getJSON(
76 ActionMapping mapping, ActionForm form, HttpServletRequest request,
77 HttpServletResponse response)
78 throws Exception {
79
80 String className = ParamUtil.getString(request, "serviceClassName");
81 String methodName = ParamUtil.getString(request, "serviceMethodName");
82 String[] serviceParameters = getStringArrayFromJSON(
83 request, "serviceParameters");
84 String[] serviceParameterTypes = getStringArrayFromJSON(
85 request, "serviceParameterTypes");
86
87 if (!isValidRequest(request)) {
88 return null;
89 }
90
91 Thread currentThread = Thread.currentThread();
92
93 ClassLoader contextClassLoader = currentThread.getContextClassLoader();
94
95 Class<?> classObj = contextClassLoader.loadClass(className);
96
97 Object[] methodAndParameterTypes = getMethodAndParameterTypes(
98 classObj, methodName, serviceParameters, serviceParameterTypes);
99
100 if (methodAndParameterTypes != null) {
101 Method method = (Method)methodAndParameterTypes[0];
102 Class<?>[] parameterTypes = (Class[])methodAndParameterTypes[1];
103 Object[] args = new Object[serviceParameters.length];
104
105 for (int i = 0; i < serviceParameters.length; i++) {
106 args[i] = getArgValue(
107 request, classObj, methodName, serviceParameters[i],
108 parameterTypes[i]);
109 }
110
111 try {
112 if (_log.isDebugEnabled()) {
113 _log.debug(
114 "Invoking " + classObj + " on method " +
115 method.getName() + " with args " +
116 Arrays.toString(args));
117 }
118
119 Object returnObj = method.invoke(classObj, args);
120
121 if (returnObj != null) {
122 return getReturnValue(returnObj, method.getReturnType());
123 }
124 else {
125 JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
126
127 return jsonObject.toString();
128 }
129 }
130 catch (Exception e) {
131 if (_log.isDebugEnabled()) {
132 _log.debug(
133 "Invoked " + classObj + " on method " +
134 method.getName() + " with args " +
135 Arrays.toString(args),
136 e);
137 }
138
139 JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
140
141 if (e instanceof InvocationTargetException) {
142 jsonObject.put("exception", e.getCause().toString());
143 }
144 else {
145 jsonObject.put("exception", e.getMessage());
146 }
147
148 return jsonObject.toString();
149 }
150 }
151
152 return null;
153 }
154
155 protected Object getArgValue(
156 HttpServletRequest request, Class<?> classObj, String methodName,
157 String parameter, Class<?> parameterType)
158 throws Exception {
159
160 String parameterTypeName = parameterType.getName();
161
162 String value = ParamUtil.getString(request, parameter);
163
164 if (Validator.isNull(value) &&
165 !parameterTypeName.equals("[Ljava.lang.String;")) {
166
167 return null;
168 }
169 else if (parameterTypeName.equals("boolean") ||
170 parameterTypeName.equals(Boolean.class.getName())) {
171
172 return Boolean.valueOf(ParamUtil.getBoolean(request, parameter));
173 }
174 else if (parameterTypeName.equals("double") ||
175 parameterTypeName.equals(Double.class.getName())) {
176
177 return new Double(ParamUtil.getDouble(request, parameter));
178 }
179 else if (parameterTypeName.equals("int") ||
180 parameterTypeName.equals(Integer.class.getName())) {
181
182 return new Integer(ParamUtil.getInteger(request, parameter));
183 }
184 else if (parameterTypeName.equals("long") ||
185 parameterTypeName.equals(Long.class.getName())) {
186
187 return new Long(ParamUtil.getLong(request, parameter));
188 }
189 else if (parameterTypeName.equals("short") ||
190 parameterTypeName.equals(Short.class.getName())) {
191
192 return new Short(ParamUtil.getShort(request, parameter));
193 }
194 else if (parameterTypeName.equals(Date.class.getName())) {
195 return new Date(ParamUtil.getLong(request, parameter));
196 }
197 else if (parameterTypeName.equals(ServiceContext.class.getName())) {
198 JSONObject jsonObject = JSONFactoryUtil.createJSONObject(value);
199
200 jsonObject.put("javaClass", ServiceContext.class.getName());
201
202 return ServiceContextUtil.deserialize(jsonObject);
203 }
204 else if (parameterTypeName.equals(String.class.getName())) {
205 return value;
206 }
207 else if (parameterTypeName.equals("[Z")) {
208 return ParamUtil.getBooleanValues(request, parameter);
209 }
210 else if (parameterTypeName.equals("[D")) {
211 return ParamUtil.getDoubleValues(request, parameter);
212 }
213 else if (parameterTypeName.equals("[F")) {
214 return ParamUtil.getFloatValues(request, parameter);
215 }
216 else if (parameterTypeName.equals("[I")) {
217 return ParamUtil.getIntegerValues(request, parameter);
218 }
219 else if (parameterTypeName.equals("[J")) {
220 return ParamUtil.getLongValues(request, parameter);
221 }
222 else if (parameterTypeName.equals("[S")) {
223 return ParamUtil.getShortValues(request, parameter);
224 }
225 else if (parameterTypeName.equals("[Ljava.lang.String;")) {
226 return StringUtil.split(value);
227 }
228 else if (parameterTypeName.equals("[[Z")) {
229 String[] values = request.getParameterValues(parameter);
230
231 if ((values != null) && (values.length > 0)) {
232 String[] values0 = StringUtil.split(values[0]);
233
234 boolean[][] doubleArray =
235 new boolean[values.length][values0.length];
236
237 for (int i = 0; i < values.length; i++) {
238 String[] curValues = StringUtil.split(values[i]);
239
240 for (int j = 0; j < curValues.length; j++) {
241 doubleArray[i][j] = GetterUtil.getBoolean(curValues[j]);
242 }
243 }
244
245 return doubleArray;
246 }
247 else {
248 return new boolean[0][0];
249 }
250 }
251 else if (parameterTypeName.equals("[[D")) {
252 String[] values = request.getParameterValues(parameter);
253
254 if ((values != null) && (values.length > 0)) {
255 String[] values0 = StringUtil.split(values[0]);
256
257 double[][] doubleArray =
258 new double[values.length][values0.length];
259
260 for (int i = 0; i < values.length; i++) {
261 String[] curValues = StringUtil.split(values[i]);
262
263 for (int j = 0; j < curValues.length; j++) {
264 doubleArray[i][j] = GetterUtil.getDouble(curValues[j]);
265 }
266 }
267
268 return doubleArray;
269 }
270 else {
271 return new double[0][0];
272 }
273 }
274 else if (parameterTypeName.equals("[[F")) {
275 String[] values = request.getParameterValues(parameter);
276
277 if ((values != null) && (values.length > 0)) {
278 String[] values0 = StringUtil.split(values[0]);
279
280 float[][] doubleArray =
281 new float[values.length][values0.length];
282
283 for (int i = 0; i < values.length; i++) {
284 String[] curValues = StringUtil.split(values[i]);
285
286 for (int j = 0; j < curValues.length; j++) {
287 doubleArray[i][j] = GetterUtil.getFloat(curValues[j]);
288 }
289 }
290
291 return doubleArray;
292 }
293 else {
294 return new float[0][0];
295 }
296 }
297 else if (parameterTypeName.equals("[[I")) {
298 String[] values = request.getParameterValues(parameter);
299
300 if ((values != null) && (values.length > 0)) {
301 String[] values0 = StringUtil.split(values[0]);
302
303 int[][] doubleArray =
304 new int[values.length][values0.length];
305
306 for (int i = 0; i < values.length; i++) {
307 String[] curValues = StringUtil.split(values[i]);
308
309 for (int j = 0; j < curValues.length; j++) {
310 doubleArray[i][j] = GetterUtil.getInteger(curValues[j]);
311 }
312 }
313
314 return doubleArray;
315 }
316 else {
317 return new int[0][0];
318 }
319 }
320 else if (parameterTypeName.equals("[[J")) {
321 String[] values = request.getParameterValues(parameter);
322
323 if ((values != null) && (values.length > 0)) {
324 String[] values0 = StringUtil.split(values[0]);
325
326 long[][] doubleArray =
327 new long[values.length][values0.length];
328
329 for (int i = 0; i < values.length; i++) {
330 String[] curValues = StringUtil.split(values[i]);
331
332 for (int j = 0; j < curValues.length; j++) {
333 doubleArray[i][j] = GetterUtil.getLong(curValues[j]);
334 }
335 }
336
337 return doubleArray;
338 }
339 else {
340 return new long[0][0];
341 }
342 }
343 else if (parameterTypeName.equals("[[S")) {
344 String[] values = request.getParameterValues(parameter);
345
346 if ((values != null) && (values.length > 0)) {
347 String[] values0 = StringUtil.split(values[0]);
348
349 short[][] doubleArray =
350 new short[values.length][values0.length];
351
352 for (int i = 0; i < values.length; i++) {
353 String[] curValues = StringUtil.split(values[i]);
354
355 for (int j = 0; j < curValues.length; j++) {
356 doubleArray[i][j] = GetterUtil.getShort(curValues[j]);
357 }
358 }
359
360 return doubleArray;
361 }
362 else {
363 return new short[0][0];
364 }
365 }
366 else if (parameterTypeName.equals("[[Ljava.lang.String")) {
367 String[] values = request.getParameterValues(parameter);
368
369 if ((values != null) && (values.length > 0)) {
370 String[] values0 = StringUtil.split(values[0]);
371
372 String[][] doubleArray =
373 new String[values.length][values0.length];
374
375 for (int i = 0; i < values.length; i++) {
376 doubleArray[i] = StringUtil.split(values[i]);
377 }
378
379 return doubleArray;
380 }
381 else {
382 return new String[0][0];
383 }
384 }
385 else {
386 _log.error(
387 "Unsupported parameter type for class " + classObj +
388 ", method " + methodName + ", parameter " + parameter +
389 ", and type " + parameterTypeName);
390
391 return null;
392 }
393 }
394
395 protected Object[] getMethodAndParameterTypes(
396 Class<?> classObj, String methodName, String[] parameters,
397 String[] parameterTypes)
398 throws Exception {
399
400 String parameterNames = StringUtil.merge(parameters);
401
402 String key =
403 classObj.getName() + "_METHOD_NAME_" + methodName +
404 "_PARAMETERS_" + parameterNames;
405
406 Object[] methodAndParameterTypes = _methodCache.get(key);
407
408 if (methodAndParameterTypes != null) {
409 return methodAndParameterTypes;
410 }
411
412 Method method = null;
413 Class<?>[] methodParameterTypes = null;
414
415 Method[] methods = classObj.getMethods();
416
417 for (int i = 0; i < methods.length; i++) {
418 Method curMethod = methods[i];
419
420 if (curMethod.getName().equals(methodName)) {
421 Class<?>[] curParameterTypes = curMethod.getParameterTypes();
422
423 if (curParameterTypes.length == parameters.length) {
424 if ((parameterTypes.length > 0) &&
425 (parameterTypes.length == curParameterTypes.length)) {
426
427 boolean match = true;
428
429 for (int j = 0; j < parameterTypes.length; j++) {
430 String t1 = parameterTypes[j];
431 String t2 = curParameterTypes[j].getName();
432
433 if (!t1.equals(t2)) {
434 match = false;
435 }
436 }
437
438 if (match) {
439 method = curMethod;
440 methodParameterTypes = curParameterTypes;
441
442 break;
443 }
444 }
445 else if (method != null) {
446 _log.error(
447 "Obscure method name for class " + classObj +
448 ", method " + methodName + ", and parameters " +
449 parameterNames);
450
451 return null;
452 }
453 else {
454 method = curMethod;
455 methodParameterTypes = curParameterTypes;
456 }
457 }
458 }
459 }
460
461 if (method != null) {
462 methodAndParameterTypes = new Object[] {
463 method, methodParameterTypes
464 };
465
466 _methodCache.put(key, methodAndParameterTypes);
467
468 return methodAndParameterTypes;
469 }
470 else {
471 _log.error(
472 "No method found for class " + classObj + ", method " +
473 methodName + ", and parameters " + parameterNames);
474
475 return null;
476 }
477 }
478
479 protected String getReturnValue(Object returnObj, Class<?> returnType)
480 throws Exception {
481
482 if ((returnObj instanceof Boolean) || (returnObj instanceof Double) ||
483 (returnObj instanceof Integer) || (returnObj instanceof Long) ||
484 (returnObj instanceof Short) || (returnObj instanceof String)) {
485
486 JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
487
488 jsonObject.put("returnValue", returnObj.toString());
489
490 return jsonObject.toString();
491 }
492 else if (returnObj instanceof BaseModel<?>) {
493 String serlializerClassName = getSerializerClassName(returnObj);
494
495 MethodKey methodKey = new MethodKey(
496 serlializerClassName, "toJSONObject", returnType);
497
498 MethodHandler methodHandler = new MethodHandler(
499 methodKey, returnObj);
500
501 JSONObject jsonObject = (JSONObject)methodHandler.invoke(false);
502
503 return jsonObject.toString();
504 }
505 else if (returnObj instanceof BaseModel<?>[]) {
506 JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
507
508 BaseModel<?>[] returnArray = (BaseModel[])returnObj;
509
510 if (returnArray.length > 0) {
511 BaseModel<?> returnItem0 = returnArray[0];
512
513 String serializerClassName = getSerializerClassName(
514 returnItem0);
515
516 MethodKey methodKey = new MethodKey(
517 serializerClassName, "toJSONArray", returnType);
518
519 MethodHandler methodHandler = new MethodHandler(
520 methodKey, returnObj);
521
522 jsonArray = (JSONArray)methodHandler.invoke(false);
523 }
524
525 return jsonArray.toString();
526 }
527 else if (returnObj instanceof BaseModel<?>[][]) {
528 JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
529
530 BaseModel<?>[][] returnArray = (BaseModel<?>[][])returnObj;
531
532 if ((returnArray.length > 0) &&
533 (returnArray[0].length > 0)) {
534
535 BaseModel<?> returnItem0 = returnArray[0][0];
536
537 String serializerClassName = getSerializerClassName(
538 returnItem0);
539
540 MethodKey methodKey = new MethodKey(
541 serializerClassName, "toJSONArray", returnType);
542
543 MethodHandler methodHandler = new MethodHandler(
544 methodKey, returnObj);
545
546 jsonArray = (JSONArray)methodHandler.invoke(false);
547 }
548
549 return jsonArray.toString();
550 }
551 else if (returnObj instanceof List<?>) {
552 JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
553
554 List<Object> returnList = (List<Object>)returnObj;
555
556 if (!returnList.isEmpty()) {
557 Object returnItem0 = returnList.get(0);
558
559 String serlializerClassName = getSerializerClassName(
560 returnItem0);
561
562 MethodKey methodKey = new MethodKey(
563 serlializerClassName, "toJSONArray", returnType);
564
565 MethodHandler methodHandler = new MethodHandler(
566 methodKey, returnObj);
567
568 jsonArray = (JSONArray)methodHandler.invoke(false);
569 }
570
571 return jsonArray.toString();
572 }
573 else if (returnObj instanceof JSONArray) {
574 JSONArray jsonArray = (JSONArray)returnObj;
575
576 return jsonArray.toString();
577 }
578 else if (returnObj instanceof JSONObject) {
579 JSONObject jsonObject = (JSONObject)returnObj;
580
581 return jsonObject.toString();
582 }
583 else if (returnObj instanceof TagsAssetDisplay) {
584 return getReturnValue((TagsAssetDisplay)returnObj);
585 }
586 else if (returnObj instanceof TagsAssetDisplay[]) {
587 return getReturnValue((TagsAssetDisplay[])returnObj);
588 }
589 else if (returnObj instanceof TagsAssetType) {
590 return getReturnValue((TagsAssetType)returnObj);
591 }
592 else if (returnObj instanceof TagsAssetType[]) {
593 return getReturnValue((TagsAssetType[])returnObj);
594 }
595 else {
596 return JSONFactoryUtil.serialize(returnObj);
597 }
598 }
599
600 protected String getReturnValue(TagsAssetDisplay assetDisplay)
601 throws Exception {
602
603 JSONObject jsonObject = toJSONObject(assetDisplay);
604
605 return jsonObject.toString();
606 }
607
608 protected String getReturnValue(TagsAssetDisplay[] assetDisplays)
609 throws Exception {
610
611 JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
612
613 for (int i = 0; i < assetDisplays.length; i++) {
614 TagsAssetDisplay assetDisplay = assetDisplays[i];
615
616 jsonArray.put(toJSONObject(assetDisplay));
617 }
618
619 return jsonArray.toString();
620 }
621
622 protected String getReturnValue(TagsAssetType assetType)
623 throws Exception {
624
625 JSONObject jsonObject = toJSONObject(assetType);
626
627 return jsonObject.toString();
628 }
629
630 protected String getReturnValue(TagsAssetType[] assetTypes)
631 throws Exception {
632
633 JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
634
635 for (int i = 0; i < assetTypes.length; i++) {
636 TagsAssetType assetType = assetTypes[i];
637
638 jsonArray.put(toJSONObject(assetType));
639 }
640
641 return jsonArray.toString();
642 }
643
644 protected String getSerializerClassName(Object obj) {
645 String serlializerClassName = StringUtil.replace(
646 obj.getClass().getName(),
647 new String[] {".model.impl.", "Impl"},
648 new String[] {".service.http.", "JSONSerializer"});
649
650 return serlializerClassName;
651 }
652
653 protected String[] getStringArrayFromJSON(
654 HttpServletRequest request, String param)
655 throws JSONException {
656
657 String json = ParamUtil.getString(request, param, "[]");
658
659 JSONArray jsonArray = JSONFactoryUtil.createJSONArray(json);
660
661 return ArrayUtil.toStringArray(jsonArray);
662 }
663
664 protected boolean isValidRequest(HttpServletRequest request) {
665 String className = ParamUtil.getString(request, "serviceClassName");
666
667 if (className.contains(".service.") &&
668 className.endsWith("ServiceUtil") &&
669 !className.endsWith("LocalServiceUtil") &&
670 !_invalidClassNames.contains(className)) {
671
672 return true;
673 }
674 else {
675 return false;
676 }
677 }
678
679 protected JSONObject toJSONObject(TagsAssetDisplay assetDisplay) {
680 JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
681
682 jsonObject.put("assetId", assetDisplay.getAssetId());
683 jsonObject.put("companyId", assetDisplay.getCompanyId());
684 jsonObject.put("userId", assetDisplay.getUserId());
685 jsonObject.put("userName", assetDisplay.getUserName());
686 jsonObject.put("createDate", assetDisplay.getCreateDate());
687 jsonObject.put("modifiedDate", assetDisplay.getModifiedDate());
688 jsonObject.put("classNameId", assetDisplay.getClassNameId());
689 jsonObject.put("className", assetDisplay.getClassName());
690 jsonObject.put("classPK", assetDisplay.getClassPK());
691 jsonObject.put("portletId", assetDisplay.getPortletId());
692 jsonObject.put("portletTitle", assetDisplay.getPortletTitle());
693 jsonObject.put("startDate", assetDisplay.getStartDate());
694 jsonObject.put("endDate", assetDisplay.getEndDate());
695 jsonObject.put("publishDate", assetDisplay.getPublishDate());
696 jsonObject.put("expirationDate", assetDisplay.getExpirationDate());
697 jsonObject.put("mimeType", assetDisplay.getMimeType());
698 jsonObject.put("title", assetDisplay.getTitle());
699 jsonObject.put("description", assetDisplay.getDescription());
700 jsonObject.put("summary", assetDisplay.getSummary());
701 jsonObject.put("url", assetDisplay.getUrl());
702 jsonObject.put("height", assetDisplay.getHeight());
703 jsonObject.put("width", assetDisplay.getWidth());
704 jsonObject.put("priority", assetDisplay.getPriority());
705 jsonObject.put("viewCount", assetDisplay.getViewCount());
706 jsonObject.put("tagsEntries", assetDisplay.getTagsEntries());
707
708 return jsonObject;
709 }
710
711 protected JSONObject toJSONObject(TagsAssetType assetType) {
712 JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
713
714 jsonObject.put("classNameId", assetType.getClassNameId());
715 jsonObject.put("className", assetType.getClassName());
716 jsonObject.put("portletId", assetType.getPortletId());
717 jsonObject.put("portletTitle", assetType.getPortletTitle());
718
719 return jsonObject;
720 }
721
722 private static Log _log = LogFactoryUtil.getLog(JSONServiceAction.class);
723
724 private Set<String> _invalidClassNames = new HashSet<String>();
725 private Map<String, Object[]> _methodCache =
726 new HashMap<String, Object[]>();
727
728 }