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