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