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[] serviceParameters = StringUtil.split(
66              ParamUtil.getString(req, "serviceParameters"));
67          String[] serviceParameterTypes = StringUtil.split(
68              ParamUtil.getString(req, "serviceParameterTypes"));
69  
70          Class<?> classObj = Class.forName(className);
71  
72          Object[] methodAndParameterTypes = getMethodAndParameterTypes(
73              classObj, methodName, serviceParameters, serviceParameterTypes);
74  
75          if (methodAndParameterTypes != null) {
76              Method method = (Method)methodAndParameterTypes[0];
77              Class<?>[] parameterTypes = (Class[])methodAndParameterTypes[1];
78              Object[] args = new Object[serviceParameters.length];
79  
80              for (int i = 0; i < serviceParameters.length; i++) {
81                  args[i] = getArgValue(
82                      req, classObj, methodName, serviceParameters[i],
83                      parameterTypes[i]);
84  
85                  if (args[i] == null) {
86                      return null;
87                  }
88              }
89  
90              try {
91                  if (_log.isDebugEnabled()) {
92                      _log.debug(
93                          "Invoking class " + classObj + " on method " +
94                              method.getName() + " with args " + args);
95                  }
96  
97                  Object returnObj = method.invoke(classObj, args);
98  
99                  if (returnObj != null) {
100                     if (returnObj instanceof JSONArray) {
101                         JSONArray jsonArray = (JSONArray)returnObj;
102 
103                         return jsonArray.toString();
104                     }
105                     else if (returnObj instanceof JSONObject) {
106                         JSONObject jsonObj = (JSONObject)returnObj;
107 
108                         return jsonObj.toString();
109                     }
110                     else if (returnObj instanceof Boolean ||
111                              returnObj instanceof Double ||
112                              returnObj instanceof Integer ||
113                              returnObj instanceof Long ||
114                              returnObj instanceof Short ||
115                              returnObj instanceof String) {
116 
117                         JSONObject jsonObj = new JSONObject();
118 
119                         jsonObj.put("returnValue", returnObj.toString());
120 
121                         return jsonObj.toString();
122                     }
123                     else {
124                         String returnValue = getReturnValue(returnObj);
125 
126                         if (returnValue == null) {
127                             _log.error(
128                                 "Unsupported return type for class " +
129                                     classObj + " and method " + methodName);
130                         }
131 
132                         return returnValue;
133                     }
134                 }
135                 else {
136                     JSONObject jsonObj = new JSONObject();
137 
138                     return jsonObj.toString();
139                 }
140             }
141             catch (InvocationTargetException ite) {
142                 JSONObject jsonObj = new JSONObject();
143 
144                 jsonObj.put("exception", ite.getCause().toString());
145 
146                 return jsonObj.toString();
147             }
148         }
149 
150         return null;
151     }
152 
153     protected Object getArgValue(
154             HttpServletRequest req, Class<?> classObj, String methodName,
155             String parameter, Class<?> parameterType)
156         throws Exception {
157 
158         String parameterTypeName = parameterType.getName();
159 
160         if (parameterTypeName.equals("boolean") ||
161             parameterTypeName.equals(Boolean.class.getName())) {
162 
163             return Boolean.valueOf(ParamUtil.getBoolean(req, parameter));
164         }
165         else if (parameterTypeName.equals("double") ||
166                  parameterTypeName.equals(Double.class.getName())) {
167 
168             return new Double(ParamUtil.getDouble(req, parameter));
169         }
170         else if (parameterTypeName.equals("int") ||
171                  parameterTypeName.equals(Integer.class.getName())) {
172 
173             return new Integer(ParamUtil.getInteger(req, parameter));
174         }
175         else if (parameterTypeName.equals("long") ||
176                  parameterTypeName.equals(Long.class.getName())) {
177 
178             return new Long(ParamUtil.getLong(req, parameter));
179         }
180         else if (parameterTypeName.equals("short") ||
181                  parameterTypeName.equals(Short.class.getName())) {
182 
183             return new Short(ParamUtil.getShort(req, parameter));
184         }
185         else if (parameterTypeName.equals(Date.class.getName())) {
186             return new Date(ParamUtil.getLong(req, parameter));
187         }
188         else if (parameterTypeName.equals(String.class.getName())) {
189             return ParamUtil.getString(req, parameter);
190         }
191         else if (parameterTypeName.equals("[Ljava.lang.String;")) {
192             return StringUtil.split(ParamUtil.getString(req, parameter));
193         }
194         else {
195             _log.error(
196                 "Unsupported parameter type for class " + classObj +
197                     ", method " + methodName + ", parameter " + parameter +
198                         ", and type " + parameterTypeName);
199 
200             return null;
201         }
202     }
203 
204     protected Object[] getMethodAndParameterTypes(
205             Class<?> classObj, String methodName, String[] parameters,
206             String[] parameterTypes)
207         throws Exception {
208 
209         String parameterNames = StringUtil.merge(parameters);
210 
211         String key =
212             classObj.getName() + "_METHOD_NAME_" + methodName +
213                 "_PARAMETERS_" + parameterNames;
214 
215         Object[] methodAndParameterTypes = _methodCache.get(key);
216 
217         if (methodAndParameterTypes != null) {
218             return methodAndParameterTypes;
219         }
220 
221         Method method = null;
222         Class<?>[] methodParameterTypes = null;
223 
224         Method[] methods = classObj.getMethods();
225 
226         for (int i = 0; i < methods.length; i++) {
227             Method curMethod = methods[i];
228 
229             if (curMethod.getName().equals(methodName)) {
230                 Class<?>[] curParameterTypes = curMethod.getParameterTypes();
231 
232                 if (curParameterTypes.length == parameters.length) {
233                     if ((parameterTypes.length > 0) &&
234                         (parameterTypes.length == curParameterTypes.length)) {
235 
236                         boolean match = true;
237 
238                         for (int j = 0; j < parameterTypes.length; j++) {
239                             String t1 = parameterTypes[j];
240                             String t2 = curParameterTypes[j].getName();
241 
242                             if (!t1.equals(t2)) {
243                                 match = false;
244                             }
245                         }
246 
247                         if (match) {
248                             method = curMethod;
249                             methodParameterTypes = curParameterTypes;
250 
251                             break;
252                         }
253                     }
254                     else if (method != null) {
255                         _log.error(
256                             "Obscure method name for class " + classObj +
257                                 ", method " + methodName + ", and parameters " +
258                                     parameterNames);
259 
260                         return null;
261                     }
262                     else {
263                         method = curMethod;
264                         methodParameterTypes = curParameterTypes;
265                     }
266                 }
267             }
268         }
269 
270         if (method != null) {
271             methodAndParameterTypes =
272                 new Object[] {method, methodParameterTypes};
273 
274             _methodCache.put(key, methodAndParameterTypes);
275 
276             return methodAndParameterTypes;
277         }
278         else {
279             _log.error(
280                 "No method found for class " + classObj + ", method " +
281                     methodName + ", and parameters " + parameterNames);
282 
283             return null;
284         }
285     }
286 
287     protected String getReturnValue(Object returnObj) throws Exception {
288         if (returnObj instanceof TagsAssetDisplay) {
289             return getReturnValue((TagsAssetDisplay)returnObj);
290         }
291         else if (returnObj instanceof TagsAssetDisplay[]) {
292             return getReturnValue((TagsAssetDisplay[])returnObj);
293         }
294         else if (returnObj instanceof TagsAssetType) {
295             return getReturnValue((TagsAssetType)returnObj);
296         }
297         else if (returnObj instanceof TagsAssetType[]) {
298             return getReturnValue((TagsAssetType[])returnObj);
299         }
300 
301         return null;
302     }
303 
304     protected String getReturnValue(TagsAssetDisplay assetDisplay)
305         throws Exception {
306 
307         JSONObject jsonObj = toJSONObject(assetDisplay);
308 
309         return jsonObj.toString();
310     }
311 
312     protected String getReturnValue(TagsAssetDisplay[] assetDisplays)
313         throws Exception {
314 
315         JSONArray jsonArray = new JSONArray();
316 
317         for (int i = 0; i < assetDisplays.length; i++) {
318             TagsAssetDisplay assetDisplay = assetDisplays[i];
319 
320             jsonArray.put(toJSONObject(assetDisplay));
321         }
322 
323         return jsonArray.toString();
324     }
325 
326     protected String getReturnValue(TagsAssetType assetType)
327         throws Exception {
328 
329         JSONObject jsonObj = toJSONObject(assetType);
330 
331         return jsonObj.toString();
332     }
333 
334     protected String getReturnValue(TagsAssetType[] assetTypes)
335         throws Exception {
336 
337         JSONArray jsonArray = new JSONArray();
338 
339         for (int i = 0; i < assetTypes.length; i++) {
340             TagsAssetType assetType = assetTypes[i];
341 
342             jsonArray.put(toJSONObject(assetType));
343         }
344 
345         return jsonArray.toString();
346     }
347 
348     public static JSONObject toJSONObject(TagsAssetDisplay assetDisplay) {
349         JSONObject jsonObj = new JSONObject();
350 
351         JSONUtil.put(jsonObj, "assetId", assetDisplay.getAssetId());
352         JSONUtil.put(jsonObj, "companyId", assetDisplay.getCompanyId());
353         JSONUtil.put(jsonObj, "userId", assetDisplay.getUserId());
354         JSONUtil.put(jsonObj, "userName", assetDisplay.getUserName());
355         JSONUtil.put(jsonObj, "createDate", assetDisplay.getCreateDate());
356         JSONUtil.put(jsonObj, "modifiedDate", assetDisplay.getModifiedDate());
357         JSONUtil.put(jsonObj, "classNameId", assetDisplay.getClassNameId());
358         JSONUtil.put(jsonObj, "className", assetDisplay.getClassName());
359         JSONUtil.put(jsonObj, "classPK", assetDisplay.getClassPK());
360         JSONUtil.put(jsonObj, "portletId", assetDisplay.getPortletId());
361         JSONUtil.put(jsonObj, "portletTitle", assetDisplay.getPortletTitle());
362         JSONUtil.put(jsonObj, "startDate", assetDisplay.getStartDate());
363         JSONUtil.put(jsonObj, "endDate", assetDisplay.getEndDate());
364         JSONUtil.put(jsonObj, "publishDate", assetDisplay.getPublishDate());
365         JSONUtil.put(
366             jsonObj, "expirationDate", assetDisplay.getExpirationDate());
367         JSONUtil.put(jsonObj, "mimeType", assetDisplay.getMimeType());
368         JSONUtil.put(jsonObj, "title", assetDisplay.getTitle());
369         JSONUtil.put(jsonObj, "description", assetDisplay.getDescription());
370         JSONUtil.put(jsonObj, "summary", assetDisplay.getSummary());
371         JSONUtil.put(jsonObj, "url", assetDisplay.getUrl());
372         JSONUtil.put(jsonObj, "height", assetDisplay.getHeight());
373         JSONUtil.put(jsonObj, "width", assetDisplay.getWidth());
374         JSONUtil.put(jsonObj, "priority", assetDisplay.getPriority());
375         JSONUtil.put(jsonObj, "viewCount", assetDisplay.getViewCount());
376         JSONUtil.put(jsonObj, "tagsEntries", assetDisplay.getTagsEntries());
377 
378         return jsonObj;
379     }
380 
381     public static JSONObject toJSONObject(TagsAssetType assetType) {
382         JSONObject jsonObj = new JSONObject();
383 
384         JSONUtil.put(jsonObj, "classNameId", assetType.getClassNameId());
385         JSONUtil.put(jsonObj, "className", assetType.getClassName());
386         JSONUtil.put(jsonObj, "portletId", assetType.getPortletId());
387         JSONUtil.put(jsonObj, "portletTitle", assetType.getPortletTitle());
388 
389         return jsonObj;
390     }
391 
392     private static Log _log = LogFactory.getLog(JSONServiceAction.class);
393 
394     private Map<String, Object[]> _methodCache =
395         new HashMap<String, Object[]>();
396 
397 }