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