1   /**
2    * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.action;
24  
25  import com.liferay.portal.kernel.json.JSONArray;
26  import com.liferay.portal.kernel.json.JSONFactoryUtil;
27  import com.liferay.portal.kernel.json.JSONObject;
28  import com.liferay.portal.kernel.util.ParamUtil;
29  import com.liferay.portal.kernel.util.StringUtil;
30  import com.liferay.portal.struts.JSONAction;
31  import com.liferay.portlet.tags.model.TagsAssetDisplay;
32  import com.liferay.portlet.tags.model.TagsAssetType;
33  
34  import java.lang.reflect.InvocationTargetException;
35  import java.lang.reflect.Method;
36  
37  import java.util.Date;
38  import java.util.HashMap;
39  import java.util.Map;
40  
41  import javax.servlet.http.HttpServletRequest;
42  import javax.servlet.http.HttpServletResponse;
43  
44  import org.apache.commons.logging.Log;
45  import org.apache.commons.logging.LogFactory;
46  import org.apache.struts.action.ActionForm;
47  import org.apache.struts.action.ActionMapping;
48  
49  /**
50   * <a href="JSONServiceAction.java.html"><b><i>View Source</i></b></a>
51   *
52   * @author Brian Wing Shun Chan
53   *
54   */
55  public class JSONServiceAction extends JSONAction {
56  
57      public String getJSON(
58              ActionMapping mapping, ActionForm form, HttpServletRequest request,
59              HttpServletResponse response)
60          throws Exception {
61  
62          String className = ParamUtil.getString(request, "serviceClassName");
63          String methodName = ParamUtil.getString(request, "serviceMethodName");
64          String[] serviceParameters = StringUtil.split(
65              ParamUtil.getString(request, "serviceParameters"));
66          String[] serviceParameterTypes = StringUtil.split(
67              ParamUtil.getString(request, "serviceParameterTypes"));
68  
69          Class<?> classObj = Class.forName(className);
70  
71          Object[] methodAndParameterTypes = getMethodAndParameterTypes(
72              classObj, methodName, serviceParameters, serviceParameterTypes);
73  
74          if (methodAndParameterTypes != null) {
75              Method method = (Method)methodAndParameterTypes[0];
76              Class<?>[] parameterTypes = (Class[])methodAndParameterTypes[1];
77              Object[] args = new Object[serviceParameters.length];
78  
79              for (int i = 0; i < serviceParameters.length; i++) {
80                  args[i] = getArgValue(
81                      request, classObj, methodName, serviceParameters[i],
82                      parameterTypes[i]);
83  
84                  if (args[i] == null) {
85                      return null;
86                  }
87              }
88  
89              try {
90                  if (_log.isDebugEnabled()) {
91                      _log.debug(
92                          "Invoking class " + classObj + " on method " +
93                              method.getName() + " with args " + args);
94                  }
95  
96                  Object returnObj = method.invoke(classObj, args);
97  
98                  if (returnObj != null) {
99                      if (returnObj instanceof JSONArray) {
100                         JSONArray jsonArray = (JSONArray)returnObj;
101 
102                         return jsonArray.toString();
103                     }
104                     else if (returnObj instanceof JSONObject) {
105                         JSONObject jsonObj = (JSONObject)returnObj;
106 
107                         return jsonObj.toString();
108                     }
109                     else if (returnObj instanceof Boolean ||
110                              returnObj instanceof Double ||
111                              returnObj instanceof Integer ||
112                              returnObj instanceof Long ||
113                              returnObj instanceof Short ||
114                              returnObj instanceof String) {
115 
116                         JSONObject jsonObj = JSONFactoryUtil.createJSONObject();
117 
118                         jsonObj.put("returnValue", returnObj.toString());
119 
120                         return jsonObj.toString();
121                     }
122                     else {
123                         String returnValue = getReturnValue(returnObj);
124 
125                         if (returnValue == null) {
126                             _log.error(
127                                 "Unsupported return type for class " +
128                                     classObj + " and method " + methodName);
129                         }
130 
131                         return returnValue;
132                     }
133                 }
134                 else {
135                     JSONObject jsonObj = JSONFactoryUtil.createJSONObject();
136 
137                     return jsonObj.toString();
138                 }
139             }
140             catch (InvocationTargetException ite) {
141                 JSONObject jsonObj = JSONFactoryUtil.createJSONObject();
142 
143                 jsonObj.put("exception", ite.getCause().toString());
144 
145                 return jsonObj.toString();
146             }
147         }
148 
149         return null;
150     }
151 
152     protected Object getArgValue(
153             HttpServletRequest request, Class<?> classObj, String methodName,
154             String parameter, Class<?> parameterType)
155         throws Exception {
156 
157         String parameterTypeName = parameterType.getName();
158 
159         if (parameterTypeName.equals("boolean") ||
160             parameterTypeName.equals(Boolean.class.getName())) {
161 
162             return Boolean.valueOf(ParamUtil.getBoolean(request, parameter));
163         }
164         else if (parameterTypeName.equals("double") ||
165                  parameterTypeName.equals(Double.class.getName())) {
166 
167             return new Double(ParamUtil.getDouble(request, parameter));
168         }
169         else if (parameterTypeName.equals("int") ||
170                  parameterTypeName.equals(Integer.class.getName())) {
171 
172             return new Integer(ParamUtil.getInteger(request, parameter));
173         }
174         else if (parameterTypeName.equals("long") ||
175                  parameterTypeName.equals(Long.class.getName())) {
176 
177             return new Long(ParamUtil.getLong(request, parameter));
178         }
179         else if (parameterTypeName.equals("short") ||
180                  parameterTypeName.equals(Short.class.getName())) {
181 
182             return new Short(ParamUtil.getShort(request, parameter));
183         }
184         else if (parameterTypeName.equals(Date.class.getName())) {
185             return new Date(ParamUtil.getLong(request, parameter));
186         }
187         else if (parameterTypeName.equals(String.class.getName())) {
188             return ParamUtil.getString(request, parameter);
189         }
190         else if (parameterTypeName.equals("[Ljava.lang.String;")) {
191             return StringUtil.split(ParamUtil.getString(request, parameter));
192         }
193         else {
194             _log.error(
195                 "Unsupported parameter type for class " + classObj +
196                     ", method " + methodName + ", parameter " + parameter +
197                         ", and type " + parameterTypeName);
198 
199             return null;
200         }
201     }
202 
203     protected Object[] getMethodAndParameterTypes(
204             Class<?> classObj, String methodName, String[] parameters,
205             String[] parameterTypes)
206         throws Exception {
207 
208         String parameterNames = StringUtil.merge(parameters);
209 
210         String key =
211             classObj.getName() + "_METHOD_NAME_" + methodName +
212                 "_PARAMETERS_" + parameterNames;
213 
214         Object[] methodAndParameterTypes = _methodCache.get(key);
215 
216         if (methodAndParameterTypes != null) {
217             return methodAndParameterTypes;
218         }
219 
220         Method method = null;
221         Class<?>[] methodParameterTypes = null;
222 
223         Method[] methods = classObj.getMethods();
224 
225         for (int i = 0; i < methods.length; i++) {
226             Method curMethod = methods[i];
227 
228             if (curMethod.getName().equals(methodName)) {
229                 Class<?>[] curParameterTypes = curMethod.getParameterTypes();
230 
231                 if (curParameterTypes.length == parameters.length) {
232                     if ((parameterTypes.length > 0) &&
233                         (parameterTypes.length == curParameterTypes.length)) {
234 
235                         boolean match = true;
236 
237                         for (int j = 0; j < parameterTypes.length; j++) {
238                             String t1 = parameterTypes[j];
239                             String t2 = curParameterTypes[j].getName();
240 
241                             if (!t1.equals(t2)) {
242                                 match = false;
243                             }
244                         }
245 
246                         if (match) {
247                             method = curMethod;
248                             methodParameterTypes = curParameterTypes;
249 
250                             break;
251                         }
252                     }
253                     else if (method != null) {
254                         _log.error(
255                             "Obscure method name for class " + classObj +
256                                 ", method " + methodName + ", and parameters " +
257                                     parameterNames);
258 
259                         return null;
260                     }
261                     else {
262                         method = curMethod;
263                         methodParameterTypes = curParameterTypes;
264                     }
265                 }
266             }
267         }
268 
269         if (method != null) {
270             methodAndParameterTypes =
271                 new Object[] {method, methodParameterTypes};
272 
273             _methodCache.put(key, methodAndParameterTypes);
274 
275             return methodAndParameterTypes;
276         }
277         else {
278             _log.error(
279                 "No method found for class " + classObj + ", method " +
280                     methodName + ", and parameters " + parameterNames);
281 
282             return null;
283         }
284     }
285 
286     protected String getReturnValue(Object returnObj) throws Exception {
287         if (returnObj instanceof TagsAssetDisplay) {
288             return getReturnValue((TagsAssetDisplay)returnObj);
289         }
290         else if (returnObj instanceof TagsAssetDisplay[]) {
291             return getReturnValue((TagsAssetDisplay[])returnObj);
292         }
293         else if (returnObj instanceof TagsAssetType) {
294             return getReturnValue((TagsAssetType)returnObj);
295         }
296         else if (returnObj instanceof TagsAssetType[]) {
297             return getReturnValue((TagsAssetType[])returnObj);
298         }
299 
300         return null;
301     }
302 
303     protected String getReturnValue(TagsAssetDisplay assetDisplay)
304         throws Exception {
305 
306         JSONObject jsonObj = toJSONObject(assetDisplay);
307 
308         return jsonObj.toString();
309     }
310 
311     protected String getReturnValue(TagsAssetDisplay[] assetDisplays)
312         throws Exception {
313 
314         JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
315 
316         for (int i = 0; i < assetDisplays.length; i++) {
317             TagsAssetDisplay assetDisplay = assetDisplays[i];
318 
319             jsonArray.put(toJSONObject(assetDisplay));
320         }
321 
322         return jsonArray.toString();
323     }
324 
325     protected String getReturnValue(TagsAssetType assetType)
326         throws Exception {
327 
328         JSONObject jsonObj = toJSONObject(assetType);
329 
330         return jsonObj.toString();
331     }
332 
333     protected String getReturnValue(TagsAssetType[] assetTypes)
334         throws Exception {
335 
336         JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
337 
338         for (int i = 0; i < assetTypes.length; i++) {
339             TagsAssetType assetType = assetTypes[i];
340 
341             jsonArray.put(toJSONObject(assetType));
342         }
343 
344         return jsonArray.toString();
345     }
346 
347     public static JSONObject toJSONObject(TagsAssetDisplay assetDisplay) {
348         JSONObject jsonObj = JSONFactoryUtil.createJSONObject();
349 
350         jsonObj.put("assetId", assetDisplay.getAssetId());
351         jsonObj.put("companyId", assetDisplay.getCompanyId());
352         jsonObj.put("userId", assetDisplay.getUserId());
353         jsonObj.put("userName", assetDisplay.getUserName());
354         jsonObj.put("createDate", assetDisplay.getCreateDate());
355         jsonObj.put("modifiedDate", assetDisplay.getModifiedDate());
356         jsonObj.put("classNameId", assetDisplay.getClassNameId());
357         jsonObj.put("className", assetDisplay.getClassName());
358         jsonObj.put("classPK", assetDisplay.getClassPK());
359         jsonObj.put("portletId", assetDisplay.getPortletId());
360         jsonObj.put("portletTitle", assetDisplay.getPortletTitle());
361         jsonObj.put("startDate", assetDisplay.getStartDate());
362         jsonObj.put("endDate", assetDisplay.getEndDate());
363         jsonObj.put("publishDate", assetDisplay.getPublishDate());
364         jsonObj.put("expirationDate", assetDisplay.getExpirationDate());
365         jsonObj.put("mimeType", assetDisplay.getMimeType());
366         jsonObj.put("title", assetDisplay.getTitle());
367         jsonObj.put("description", assetDisplay.getDescription());
368         jsonObj.put("summary", assetDisplay.getSummary());
369         jsonObj.put("url", assetDisplay.getUrl());
370         jsonObj.put("height", assetDisplay.getHeight());
371         jsonObj.put("width", assetDisplay.getWidth());
372         jsonObj.put("priority", assetDisplay.getPriority());
373         jsonObj.put("viewCount", assetDisplay.getViewCount());
374         jsonObj.put("tagsEntries", assetDisplay.getTagsEntries());
375 
376         return jsonObj;
377     }
378 
379     public static JSONObject toJSONObject(TagsAssetType assetType) {
380         JSONObject jsonObj = JSONFactoryUtil.createJSONObject();
381 
382         jsonObj.put("classNameId", assetType.getClassNameId());
383         jsonObj.put("className", assetType.getClassName());
384         jsonObj.put("portletId", assetType.getPortletId());
385         jsonObj.put("portletTitle", assetType.getPortletTitle());
386 
387         return jsonObj;
388     }
389 
390     private static Log _log = LogFactory.getLog(JSONServiceAction.class);
391 
392     private Map<String, Object[]> _methodCache =
393         new HashMap<String, Object[]>();
394 
395 }