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