001
014
015 package com.liferay.portal.jsonwebservice;
016
017 import com.liferay.portal.kernel.json.JSONFactoryUtil;
018 import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceAction;
019 import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceActionMapping;
020 import com.liferay.portal.kernel.log.Log;
021 import com.liferay.portal.kernel.log.LogFactoryUtil;
022 import com.liferay.portal.kernel.util.CamelCaseUtil;
023 import com.liferay.portal.kernel.util.GetterUtil;
024 import com.liferay.portal.kernel.util.LocaleUtil;
025 import com.liferay.portal.kernel.util.MethodParameter;
026 import com.liferay.portal.kernel.util.StringUtil;
027 import com.liferay.portal.service.ServiceContext;
028
029 import java.lang.reflect.Method;
030
031 import java.util.ArrayList;
032 import java.util.Calendar;
033 import java.util.HashMap;
034 import java.util.List;
035 import java.util.Locale;
036 import java.util.Map;
037
038 import jodd.bean.BeanUtil;
039
040 import jodd.typeconverter.TypeConverterManager;
041
042 import jodd.util.KeyValue;
043 import jodd.util.ReflectUtil;
044
045
048 public class JSONWebServiceActionImpl implements JSONWebServiceAction {
049
050 public JSONWebServiceActionImpl(
051 JSONWebServiceActionConfig jsonWebServiceActionConfig,
052 JSONWebServiceActionParameters jsonWebServiceActionParameters) {
053
054 _jsonWebServiceActionConfig = jsonWebServiceActionConfig;
055 _jsonWebServiceActionParameters = jsonWebServiceActionParameters;
056 }
057
058 @Override
059 public JSONWebServiceActionMapping getJSONWebServiceActionMapping() {
060 return _jsonWebServiceActionConfig;
061 }
062
063 @Override
064 public Object invoke() throws Exception {
065 JSONRPCRequest jsonRPCRequest =
066 _jsonWebServiceActionParameters.getJSONRPCRequest();
067
068 if (jsonRPCRequest == null) {
069 return _invokeActionMethod();
070 }
071
072 Object result = null;
073 Exception exception = null;
074
075 try {
076 result = _invokeActionMethod();
077 }
078 catch (Exception e) {
079 exception = e;
080
081 _log.error(e, e);
082 }
083
084 return new JSONRPCResponse(jsonRPCRequest, result, exception);
085 }
086
087 private Object _createDefaultParameterValue(
088 String parameterName, Class<?> parameterType)
089 throws Exception {
090
091 if (parameterName.equals("serviceContext") &&
092 parameterType.equals(ServiceContext.class)) {
093
094 return new ServiceContext();
095 }
096
097 String className = parameterType.getName();
098
099 if (className.contains("com.liferay") && className.contains("Util")) {
100 throw new IllegalArgumentException(
101 "Not instantiating " + className);
102 }
103
104 return parameterType.newInstance();
105 }
106
107 private List<?> _generifyList(List<?> list, Class<?>[] types) {
108 if (types == null) {
109 return list;
110 }
111
112 if (types.length != 1) {
113 return list;
114 }
115
116 List<Object> newList = new ArrayList<Object>(list.size());
117
118 for (Object entry : list) {
119 if (entry != null) {
120 entry = TypeConverterManager.convertType(entry, types[0]);
121 }
122
123 newList.add(entry);
124 }
125
126 return newList;
127 }
128
129 private Map<?, ?> _generifyMap(Map<?, ?> map, Class<?>[] types) {
130 if (types == null) {
131 return map;
132 }
133
134 if (types.length != 2) {
135 return map;
136 }
137
138 Map<Object, Object> newMap = new HashMap<Object, Object>(map.size());
139
140 for (Map.Entry<?, ?> entry : map.entrySet()) {
141 Object key = TypeConverterManager.convertType(
142 entry.getKey(), types[0]);
143
144 Object value = entry.getValue();
145
146 if (value != null) {
147 value = TypeConverterManager.convertType(value, types[1]);
148 }
149
150 newMap.put(key, value);
151 }
152
153 return newMap;
154 }
155
156 private void _injectInnerParametersIntoValue(
157 String parameterName, Object parameterValue) {
158
159 if (parameterValue == null) {
160 return;
161 }
162
163 List<KeyValue<String, Object>> innerParameters =
164 _jsonWebServiceActionParameters.getInnerParameters(parameterName);
165
166 if (innerParameters == null) {
167 return;
168 }
169
170 for (KeyValue<String, Object> innerParameter : innerParameters) {
171 try {
172 BeanUtil.setProperty(
173 parameterValue, innerParameter.getKey(),
174 innerParameter.getValue());
175 }
176 catch (Exception e) {
177 if (_log.isDebugEnabled()) {
178 _log.debug(
179 "Unable to set inner parameter " + parameterName + "." +
180 innerParameter.getKey(),
181 e);
182 }
183 }
184 }
185 }
186
187 private Object _invokeActionMethod() throws Exception {
188 Method actionMethod = _jsonWebServiceActionConfig.getActionMethod();
189
190 Class<?> actionClass = _jsonWebServiceActionConfig.getActionClass();
191
192 Object[] parameters = _prepareParameters(actionClass);
193
194 return actionMethod.invoke(actionClass, parameters);
195 }
196
197 private Object[] _prepareParameters(Class<?> actionClass) throws Exception {
198 MethodParameter[] methodParameters =
199 _jsonWebServiceActionConfig.getMethodParameters();
200
201 Object[] parameters = new Object[methodParameters.length];
202
203 for (int i = 0; i < methodParameters.length; i++) {
204 String parameterName = methodParameters[i].getName();
205
206 parameterName = CamelCaseUtil.normalizeCamelCase(parameterName);
207
208 Object value = _jsonWebServiceActionParameters.getParameter(
209 parameterName);
210
211 Object parameterValue = null;
212
213 if (value != null) {
214 Class<?> parameterType = methodParameters[i].getType();
215
216 if (value.equals(Void.TYPE)) {
217 String parameterTypeName =
218 _jsonWebServiceActionParameters.getParameterTypeName(
219 parameterName);
220
221 if (parameterTypeName != null) {
222 ClassLoader classLoader = actionClass.getClassLoader();
223
224 parameterType = classLoader.loadClass(
225 parameterTypeName);
226 }
227
228 if (!ReflectUtil.isSubclass(
229 parameterType, methodParameters[i].getType())) {
230
231 throw new IllegalArgumentException(
232 "Unmatched argument type " +
233 parameterType.getName() +
234 " for method argument " + i);
235 }
236
237 parameterValue = _createDefaultParameterValue(
238 parameterName, parameterType);
239 }
240 else if (parameterType.equals(Calendar.class)) {
241 Calendar calendar = Calendar.getInstance();
242
243 calendar.setLenient(false);
244 calendar.setTimeInMillis(
245 GetterUtil.getLong(_valueToString(value)));
246
247 parameterValue = calendar;
248 }
249 else if (parameterType.equals(List.class)) {
250 List<?> list = JSONFactoryUtil.looseDeserializeSafe(
251 _valueToString(value), ArrayList.class);
252
253 list = _generifyList(
254 list, methodParameters[i].getGenericTypes());
255
256 parameterValue = list;
257 }
258 else if (parameterType.equals(Locale.class)) {
259 parameterValue = LocaleUtil.fromLanguageId(
260 _valueToString(value));
261 }
262 else if (parameterType.equals(Map.class)) {
263 Map<?, ?> map = JSONFactoryUtil.looseDeserializeSafe(
264 _valueToString(value), HashMap.class);
265
266 map = _generifyMap(
267 map, methodParameters[i].getGenericTypes());
268
269 parameterValue = map;
270 }
271 else {
272 parameterValue = TypeConverterManager.convertType(
273 value, parameterType);
274 }
275 }
276
277 _injectInnerParametersIntoValue(parameterName, parameterValue);
278
279 parameters[i] = parameterValue;
280 }
281
282 return parameters;
283 }
284
285 private String _valueToString(Object value) {
286 Class<?> valueType = value.getClass();
287
288 if (valueType.isArray()) {
289 return StringUtil.merge((Object[])value);
290 }
291
292 return value.toString();
293 }
294
295 private static Log _log = LogFactoryUtil.getLog(
296 JSONWebServiceActionImpl.class);
297
298 private JSONWebServiceActionConfig _jsonWebServiceActionConfig;
299 private JSONWebServiceActionParameters _jsonWebServiceActionParameters;
300
301 }