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.util.ParamUtil;
26  import com.liferay.portal.kernel.util.StringUtil;
27  import com.liferay.portal.struts.JSONAction;
28  import com.liferay.portlet.tags.model.TagsAssetDisplay;
29  import com.liferay.portlet.tags.model.TagsAssetType;
30  import com.liferay.util.JSONUtil;
31  
32  import java.lang.reflect.InvocationTargetException;
33  import java.lang.reflect.Method;
34  
35  import java.util.Date;
36  import java.util.HashMap;
37  import java.util.Map;
38  
39  import javax.servlet.http.HttpServletRequest;
40  import javax.servlet.http.HttpServletResponse;
41  
42  import org.apache.commons.logging.Log;
43  import org.apache.commons.logging.LogFactory;
44  import org.apache.struts.action.ActionForm;
45  import org.apache.struts.action.ActionMapping;
46  
47  import org.json.JSONArray;
48  import org.json.JSONObject;
49  
50  /**
51   * <a href="JSONServiceAction.java.html"><b><i>View Source</i></b></a>
52   *
53   * @author Brian Wing Shun Chan
54   *
55   */
56  public class JSONServiceAction extends JSONAction {
57  
58      public String getJSON(
59              ActionMapping mapping, ActionForm form, HttpServletRequest req,
60              HttpServletResponse res)
61          throws Exception {
62  
63          String className = ParamUtil.getString(req, "serviceClassName");
64          String methodName = ParamUtil.getString(req, "serviceMethodName");
65          String[] parameters = StringUtil.split(
66              ParamUtil.getString(req, "serviceParameters"));
67  
68          Class<?> classObj = Class.forName(className);
69  
70          Object[] methodAndParameterTypes = getMethodAndParameterTypes(
71              classObj, methodName, parameters.length);
72  
73          if (methodAndParameterTypes != null) {
74              Method method = (Method)methodAndParameterTypes[0];
75              Class<?>[] parameterTypes = (Class[])methodAndParameterTypes[1];
76              Object[] args = new Object[parameters.length];
77  
78              for (int i = 0; i < parameters.length; i++) {
79                  args[i] = getArgValue(
80                      req, classObj, methodName, parameters[i],
81                      parameterTypes[i]);
82  
83                  if (args[i] == null) {
84                      return null;
85                  }
86              }
87  
88              try {
89                  if (_log.isDebugEnabled()) {
90                      _log.debug(
91                          "Invoking class " + classObj + " on method " +
92                              method.getName() + " with args " + args);
93                  }
94  
95                  Object returnObj = method.invoke(classObj, args);
96  
97                  if (returnObj != null) {
98                      if (returnObj instanceof JSONArray) {
99                          JSONArray jsonArray = (JSONArray)returnObj;
100 
101                         return jsonArray.toString();
102                     }
103                     else if (returnObj instanceof JSONObject) {
104                         JSONObject jsonObj = (JSONObject)returnObj;
105 
106                         return jsonObj.toString();
107                     }
108                     else if (returnObj instanceof Boolean ||
109                              returnObj instanceof Double ||
110                              returnObj instanceof Integer ||
111                              returnObj instanceof Long ||
112                              returnObj instanceof Short ||
113                              returnObj instanceof String) {
114 
115                         JSONObject jsonObj = new JSONObject();
116 
117                         jsonObj.put("returnValue", returnObj.toString());
118 
119                         return jsonObj.toString();
120                     }
121                     else {
122                         String returnValue = getReturnValue(returnObj);
123 
124                         if (returnValue == null) {
125                             _log.error(
126                                 "Unsupported return type for class " +
127                                     classObj + " and method " + methodName);
128                         }
129 
130                         return returnValue;
131                     }
132                 }
133                 else {
134                     JSONObject jsonObj = new JSONObject();
135 
136                     return jsonObj.toString();
137                 }
138             }
139             catch (InvocationTargetException ite) {
140                 JSONObject jsonObj = new JSONObject();
141 
142                 jsonObj.put("exception", ite.getCause().toString());
143 
144                 return jsonObj.toString();
145             }
146         }
147 
148         return null;
149     }
150 
151     protected Object getArgValue(
152             HttpServletRequest req, Class<?> classObj, String methodName,
153             String parameter, Class<?> parameterType)
154         throws Exception {
155 
156         String parameterTypeName = parameterType.getName();
157 
158         if (parameterTypeName.equals("boolean") ||
159             parameterTypeName.equals(Boolean.class.getName())) {
160 
161             return Boolean.valueOf(ParamUtil.getBoolean(req, parameter));
162         }
163         else if (parameterTypeName.equals("double") ||
164                  parameterTypeName.equals(Double.class.getName())) {
165 
166             return new Double(ParamUtil.getDouble(req, parameter));
167         }
168         else if (parameterTypeName.equals("int") ||
169                  parameterTypeName.equals(Integer.class.getName())) {
170 
171             return new Integer(ParamUtil.getInteger(req, parameter));
172         }
173         else if (parameterTypeName.equals("long") ||
174                  parameterTypeName.equals(Long.class.getName())) {
175 
176             return new Long(ParamUtil.getLong(req, parameter));
177         }
178         else if (parameterTypeName.equals("short") ||
179                  parameterTypeName.equals(Short.class.getName())) {
180 
181             return new Short(ParamUtil.getShort(req, parameter));
182         }
183         else if (parameterTypeName.equals(Date.class.getName())) {
184             return new Date(ParamUtil.getLong(req, parameter));
185         }
186         else if (parameterTypeName.equals(String.class.getName())) {
187             return ParamUtil.getString(req, parameter);
188         }
189         else if (parameterTypeName.equals("[Ljava.lang.String;")) {
190             return StringUtil.split(ParamUtil.getString(req, parameter));
191         }
192         else {
193             _log.error(
194                 "Unsupported parameter type for class " + classObj +
195                     ", method " + methodName + ", parameter " + parameter +
196                         ", and type " + parameterTypeName);
197 
198             return null;
199         }
200     }
201 
202     protected Object[] getMethodAndParameterTypes(
203             Class<?> classObj, String methodName, int paramtersCount)
204         throws Exception {
205 
206         String key =
207             classObj.getName() + "_METHOD_NAME_" + methodName +
208                 "_PARAMETERS_COUNT_" + paramtersCount;
209 
210         Object[] methodAndParameterTypes = _methodCache.get(key);
211 
212         if (methodAndParameterTypes != null) {
213             return methodAndParameterTypes;
214         }
215 
216         Method method = null;
217         Class<?>[] parameterTypes = null;
218 
219         Method[] methods = classObj.getMethods();
220 
221         for (int i = 0; i < methods.length; i++) {
222             Method curMethod = methods[i];
223 
224             if (curMethod.getName().equals(methodName)) {
225                 Class<?>[] curParameterTypes = curMethod.getParameterTypes();
226 
227                 if (curParameterTypes.length == paramtersCount) {
228                     if (method != null) {
229                         _log.error(
230                             "Obscure method name for class " + classObj +
231                                 ", method " + methodName +
232                                     ", and parameter count " + paramtersCount);
233 
234                         return null;
235                     }
236                     else {
237                         method = curMethod;
238                         parameterTypes = curParameterTypes;
239                     }
240                 }
241             }
242         }
243 
244         if (method != null) {
245             methodAndParameterTypes = new Object[] {method, parameterTypes};
246 
247             _methodCache.put(key, methodAndParameterTypes);
248 
249             return methodAndParameterTypes;
250         }
251         else {
252             _log.error(
253                 "No method found for class " + classObj + ", method " +
254                     methodName + ", and parameter count " + paramtersCount);
255 
256             return null;
257         }
258     }
259 
260     protected String getReturnValue(Object returnObj) throws Exception {
261         if (returnObj instanceof TagsAssetDisplay) {
262             return getReturnValue((TagsAssetDisplay)returnObj);
263         }
264         else if (returnObj instanceof TagsAssetDisplay[]) {
265             return getReturnValue((TagsAssetDisplay[])returnObj);
266         }
267         else if (returnObj instanceof TagsAssetType) {
268             return getReturnValue((TagsAssetType)returnObj);
269         }
270         else if (returnObj instanceof TagsAssetType[]) {
271             return getReturnValue((TagsAssetType[])returnObj);
272         }
273 
274         return null;
275     }
276 
277     protected String getReturnValue(TagsAssetDisplay assetDisplay)
278         throws Exception {
279 
280         JSONObject jsonObj = toJSONObject(assetDisplay);
281 
282         return jsonObj.toString();
283     }
284 
285     protected String getReturnValue(TagsAssetDisplay[] assetDisplays)
286         throws Exception {
287 
288         JSONArray jsonArray = new JSONArray();
289 
290         for (int i = 0; i < assetDisplays.length; i++) {
291             TagsAssetDisplay assetDisplay = assetDisplays[i];
292 
293             jsonArray.put(toJSONObject(assetDisplay));
294         }
295 
296         return jsonArray.toString();
297     }
298 
299     protected String getReturnValue(TagsAssetType assetType)
300         throws Exception {
301 
302         JSONObject jsonObj = toJSONObject(assetType);
303 
304         return jsonObj.toString();
305     }
306 
307     protected String getReturnValue(TagsAssetType[] assetTypes)
308         throws Exception {
309 
310         JSONArray jsonArray = new JSONArray();
311 
312         for (int i = 0; i < assetTypes.length; i++) {
313             TagsAssetType assetType = assetTypes[i];
314 
315             jsonArray.put(toJSONObject(assetType));
316         }
317 
318         return jsonArray.toString();
319     }
320 
321     public static JSONObject toJSONObject(TagsAssetDisplay assetDisplay) {
322         JSONObject jsonObj = new JSONObject();
323 
324         JSONUtil.put(jsonObj, "assetId", assetDisplay.getAssetId());
325         JSONUtil.put(jsonObj, "companyId", assetDisplay.getCompanyId());
326         JSONUtil.put(jsonObj, "userId", assetDisplay.getUserId());
327         JSONUtil.put(jsonObj, "userName", assetDisplay.getUserName());
328         JSONUtil.put(jsonObj, "createDate", assetDisplay.getCreateDate());
329         JSONUtil.put(jsonObj, "modifiedDate", assetDisplay.getModifiedDate());
330         JSONUtil.put(jsonObj, "classNameId", assetDisplay.getClassNameId());
331         JSONUtil.put(jsonObj, "className", assetDisplay.getClassName());
332         JSONUtil.put(jsonObj, "classPK", assetDisplay.getClassPK());
333         JSONUtil.put(jsonObj, "portletId", assetDisplay.getPortletId());
334         JSONUtil.put(jsonObj, "portletTitle", assetDisplay.getPortletTitle());
335         JSONUtil.put(jsonObj, "startDate", assetDisplay.getStartDate());
336         JSONUtil.put(jsonObj, "endDate", assetDisplay.getEndDate());
337         JSONUtil.put(jsonObj, "publishDate", assetDisplay.getPublishDate());
338         JSONUtil.put(
339             jsonObj, "expirationDate", assetDisplay.getExpirationDate());
340         JSONUtil.put(jsonObj, "mimeType", assetDisplay.getMimeType());
341         JSONUtil.put(jsonObj, "title", assetDisplay.getTitle());
342         JSONUtil.put(jsonObj, "description", assetDisplay.getDescription());
343         JSONUtil.put(jsonObj, "summary", assetDisplay.getSummary());
344         JSONUtil.put(jsonObj, "url", assetDisplay.getUrl());
345         JSONUtil.put(jsonObj, "height", assetDisplay.getHeight());
346         JSONUtil.put(jsonObj, "width", assetDisplay.getWidth());
347         JSONUtil.put(jsonObj, "priority", assetDisplay.getPriority());
348         JSONUtil.put(jsonObj, "viewCount", assetDisplay.getViewCount());
349         JSONUtil.put(jsonObj, "tagsEntries", assetDisplay.getTagsEntries());
350 
351         return jsonObj;
352     }
353 
354     public static JSONObject toJSONObject(TagsAssetType assetType) {
355         JSONObject jsonObj = new JSONObject();
356 
357         JSONUtil.put(jsonObj, "classNameId", assetType.getClassNameId());
358         JSONUtil.put(jsonObj, "className", assetType.getClassName());
359         JSONUtil.put(jsonObj, "portletId", assetType.getPortletId());
360         JSONUtil.put(jsonObj, "portletTitle", assetType.getPortletTitle());
361 
362         return jsonObj;
363     }
364 
365     private static Log _log = LogFactory.getLog(JSONServiceAction.class);
366 
367     private Map<String, Object[]> _methodCache =
368         new HashMap<String, Object[]>();
369 
370 }