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