001
014
015 package com.liferay.portal.jsonwebservice;
016
017 import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceAction;
018 import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceActionMapping;
019 import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceActionsManager;
020 import com.liferay.portal.kernel.log.Log;
021 import com.liferay.portal.kernel.log.LogFactoryUtil;
022 import com.liferay.portal.kernel.security.pacl.DoPrivileged;
023 import com.liferay.portal.kernel.servlet.HttpMethods;
024 import com.liferay.portal.kernel.util.ArrayUtil;
025 import com.liferay.portal.kernel.util.BinarySearch;
026 import com.liferay.portal.kernel.util.CamelCaseUtil;
027 import com.liferay.portal.kernel.util.CharPool;
028 import com.liferay.portal.kernel.util.ContextPathUtil;
029 import com.liferay.portal.kernel.util.GetterUtil;
030 import com.liferay.portal.kernel.util.MethodParameter;
031 import com.liferay.portal.kernel.util.SortedArrayList;
032 import com.liferay.portal.kernel.util.StringPool;
033 import com.liferay.portal.util.PortalUtil;
034 import com.liferay.portal.util.PropsValues;
035
036 import java.lang.reflect.Method;
037
038 import java.util.ArrayList;
039 import java.util.Iterator;
040 import java.util.List;
041 import java.util.Map;
042 import java.util.Set;
043 import java.util.TreeSet;
044
045 import javax.servlet.ServletContext;
046 import javax.servlet.http.HttpServletRequest;
047 import javax.servlet.http.HttpSession;
048
049
052 @DoPrivileged
053 public class JSONWebServiceActionsManagerImpl
054 implements JSONWebServiceActionsManager {
055
056 public Set<String> getContextPaths() {
057 Set<String> contextPaths = new TreeSet<String>();
058
059 for (JSONWebServiceActionConfig jsonWebServiceActionConfig :
060 _jsonWebServiceActionConfigs) {
061
062 String contextPath = jsonWebServiceActionConfig.getContextPath();
063
064 contextPaths.add(contextPath);
065 }
066
067 return contextPaths;
068 }
069
070 public JSONWebServiceAction getJSONWebServiceAction(
071 HttpServletRequest request) {
072
073 String path = GetterUtil.getString(request.getPathInfo());
074
075 String method = GetterUtil.getString(request.getMethod());
076
077 String parameterPath = null;
078
079 JSONRPCRequest jsonRPCRequest = null;
080
081 int parameterPathIndex = _getParameterPathIndex(path);
082
083 if (parameterPathIndex != -1) {
084 parameterPath = path.substring(parameterPathIndex);
085
086 path = path.substring(0, parameterPathIndex);
087 }
088 else {
089 if (method.equals(HttpMethods.POST) &&
090 !PortalUtil.isMultipartRequest(request)) {
091
092 jsonRPCRequest = JSONRPCRequest.detectJSONRPCRequest(request);
093
094 if (jsonRPCRequest != null) {
095 path += StringPool.SLASH + jsonRPCRequest.getMethod();
096
097 method = null;
098 }
099 }
100 }
101
102 JSONWebServiceActionParameters jsonWebServiceActionParameters =
103 new JSONWebServiceActionParameters();
104
105 jsonWebServiceActionParameters.collectAll(
106 request, parameterPath, jsonRPCRequest, null);
107
108 String[] paths = _resolvePaths(request, path);
109
110 String contextPath = paths[0];
111
112 path = paths[1];
113
114 if (_log.isDebugEnabled()) {
115 _log.debug(
116 "Request JSON web service action with path " + path +
117 " and method " + method + " for /" + contextPath);
118 }
119
120 int jsonWebServiceActionConfigIndex =
121 _getJSONWebServiceActionConfigIndex(
122 contextPath, path, method,
123 jsonWebServiceActionParameters.getParameterNames());
124
125 if (jsonWebServiceActionConfigIndex == -1) {
126 throw new RuntimeException(
127 "No JSON web service action associated with path " + path +
128 " and method " + method + " for /" + contextPath);
129 }
130
131 JSONWebServiceActionConfig jsonWebServiceActionConfig =
132 _jsonWebServiceActionConfigs.get(jsonWebServiceActionConfigIndex);
133
134 return new JSONWebServiceActionImpl(
135 jsonWebServiceActionConfig, jsonWebServiceActionParameters);
136 }
137
138 public JSONWebServiceAction getJSONWebServiceAction(
139 HttpServletRequest request, String path, String method,
140 Map<String, Object> parameterMap) {
141
142 JSONWebServiceActionParameters jsonWebServiceActionParameters =
143 new JSONWebServiceActionParameters();
144
145 jsonWebServiceActionParameters.collectAll(
146 request, null, null, parameterMap);
147
148 String[] parameterNames =
149 jsonWebServiceActionParameters.getParameterNames();
150
151 String[] paths = _resolvePaths(request, path);
152
153 String contextPath = paths[0];
154
155 path = paths[1];
156
157 if (_log.isDebugEnabled()) {
158 _log.debug(
159 "Request JSON web service action with path " + path +
160 " and method " + method + " for /" + contextPath);
161 }
162
163 int jsonWebServiceActionConfigIndex =
164 _getJSONWebServiceActionConfigIndex(
165 contextPath, path, method, parameterNames);
166
167 if (jsonWebServiceActionConfigIndex == -1) {
168 throw new RuntimeException(
169 "No JSON web service action with path " + path +
170 " and method " + method + " for /" + contextPath);
171 }
172
173 JSONWebServiceActionConfig jsonWebServiceActionConfig =
174 _jsonWebServiceActionConfigs.get(jsonWebServiceActionConfigIndex);
175
176 return new JSONWebServiceActionImpl(
177 jsonWebServiceActionConfig, jsonWebServiceActionParameters);
178 }
179
180 public JSONWebServiceActionMapping getJSONWebServiceActionMapping(
181 String signature) {
182
183 for (JSONWebServiceActionConfig jsonWebServiceActionConfig :
184 _jsonWebServiceActionConfigs) {
185
186 if (signature.equals(jsonWebServiceActionConfig.getSignature())) {
187 return jsonWebServiceActionConfig;
188 }
189 }
190
191 return null;
192 }
193
194 public List<JSONWebServiceActionMapping> getJSONWebServiceActionMappings(
195 String contextPath) {
196
197 List<JSONWebServiceActionMapping> jsonWebServiceActionMappings =
198 new ArrayList<JSONWebServiceActionMapping>(
199 _jsonWebServiceActionConfigs.size());
200
201 for (JSONWebServiceActionConfig jsonWebServiceActionConfig :
202 _jsonWebServiceActionConfigs) {
203
204 String jsonWebServiceContextPath =
205 jsonWebServiceActionConfig.getContextPath();
206
207 if (contextPath.equals(jsonWebServiceContextPath)) {
208 jsonWebServiceActionMappings.add(jsonWebServiceActionConfig);
209 }
210 }
211
212 return jsonWebServiceActionMappings;
213 }
214
215 public int getJSONWebServiceActionsCount(String contextPath) {
216 int count = 0;
217
218 for (JSONWebServiceActionConfig jsonWebServiceActionConfig :
219 _jsonWebServiceActionConfigs) {
220
221 if (contextPath.equals(
222 jsonWebServiceActionConfig.getContextPath())) {
223
224 count++;
225 }
226 }
227
228 return count;
229 }
230
231 public void registerJSONWebServiceAction(
232 String contextPath, Class<?> actionClass, Method actionMethod,
233 String path, String method) {
234
235 JSONWebServiceActionConfig jsonWebServiceActionConfig =
236 new JSONWebServiceActionConfig(
237 contextPath, actionClass, actionMethod, path, method);
238
239 if (_jsonWebServiceActionConfigs.contains(jsonWebServiceActionConfig)) {
240 if (_log.isDebugEnabled()) {
241 _log.debug(
242 "A JSON web service action is already registered at " +
243 path);
244 }
245
246 return;
247 }
248
249 _jsonWebServiceActionConfigs.add(jsonWebServiceActionConfig);
250 }
251
252 public int unregisterJSONWebServiceActions(String contextPath) {
253 int count = 0;
254
255 Iterator<JSONWebServiceActionConfig> iterator =
256 _jsonWebServiceActionConfigs.iterator();
257
258 while (iterator.hasNext()) {
259 JSONWebServiceActionConfig jsonWebServiceActionConfig =
260 iterator.next();
261
262 if (contextPath.equals(
263 jsonWebServiceActionConfig.getContextPath())) {
264
265 iterator.remove();
266
267 count++;
268 }
269 }
270
271 return count;
272 }
273
274 private int _countMatchedElements(
275 String[] parameterNames, MethodParameter[] methodParameters) {
276
277 int matched = 0;
278
279 for (MethodParameter methodParameter : methodParameters) {
280 String methodParameterName = methodParameter.getName();
281
282 methodParameterName = CamelCaseUtil.normalizeCamelCase(
283 methodParameterName);
284
285 if (ArrayUtil.contains(parameterNames, methodParameterName)) {
286 matched++;
287 }
288 }
289
290 return matched;
291 }
292
293 private int _getJSONWebServiceActionConfigIndex(
294 String contextPath, String path, String method,
295 String[] parameterNames) {
296
297 int hint = -1;
298
299 int dotIndex = path.indexOf(CharPool.PERIOD);
300
301 if (dotIndex != -1) {
302 hint = GetterUtil.getInteger(path.substring(dotIndex + 1));
303
304 path = path.substring(0, dotIndex);
305 }
306
307 path = contextPath + path;
308
309 int firstIndex = _pathBinarySearch.findFirst(path);
310
311 if (firstIndex < 0) {
312 if (_log.isDebugEnabled()) {
313 _log.debug(
314 "Unable to find JSON web service actions with path " +
315 path + " for /" + contextPath);
316 }
317
318 return -1;
319 }
320
321 int lastIndex = _pathBinarySearch.findLast(path, firstIndex);
322
323 if (lastIndex < 0) {
324 lastIndex = firstIndex;
325 }
326
327 int index = -1;
328
329 int max = -1;
330
331 if (_log.isDebugEnabled()) {
332 int total = lastIndex - firstIndex + 1;
333
334 _log.debug(
335 "Found " + total + " JSON web service actions with path " +
336 path + " in for /" + contextPath);
337 }
338
339 for (int i = firstIndex; i <= lastIndex; i++) {
340 JSONWebServiceActionConfig jsonWebServiceActionConfig =
341 _jsonWebServiceActionConfigs.get(i);
342
343 String jsonWebServiceActionConfigMethod =
344 jsonWebServiceActionConfig.getMethod();
345
346 if (PropsValues.JSONWS_WEB_SERVICE_STRICT_HTTP_METHOD &&
347 (method != null)) {
348
349 if ((jsonWebServiceActionConfigMethod != null) &&
350 !jsonWebServiceActionConfigMethod.equals(method)) {
351
352 continue;
353 }
354 }
355
356 MethodParameter[] jsonWebServiceActionConfigMethodParameters =
357 jsonWebServiceActionConfig.getMethodParameters();
358
359 int methodParametersCount =
360 jsonWebServiceActionConfigMethodParameters.length;
361
362 if ((hint != -1) && (methodParametersCount != hint)) {
363 continue;
364 }
365
366 int count = _countMatchedElements(
367 parameterNames, jsonWebServiceActionConfigMethodParameters);
368
369 if (count > max) {
370 if ((hint != -1) || (count >= methodParametersCount)) {
371 max = count;
372
373 index = i;
374 }
375 }
376 }
377
378 if (_log.isDebugEnabled()) {
379 if (index == -1) {
380 _log.debug(
381 "Unable to match parameters to a JSON web service " +
382 "action with path " + path + " for /" +
383 contextPath);
384 }
385 else {
386 _log.debug(
387 "Matched parameters to a JSON web service action with " +
388 "path " + path + " for /" + contextPath);
389 }
390 }
391
392 return index;
393 }
394
395 private int _getParameterPathIndex(String path) {
396 int index = path.indexOf(CharPool.SLASH, 1);
397
398 if (index != -1) {
399 index = path.indexOf(CharPool.SLASH, index + 1);
400 }
401
402 return index;
403 }
404
405 private String[] _resolvePaths(HttpServletRequest request, String path) {
406 String contextPath = null;
407
408 int index = path.indexOf(CharPool.FORWARD_SLASH, 1);
409
410 if (index != -1) {
411 index = path.lastIndexOf(CharPool.PERIOD, index);
412
413 if (index != -1) {
414 contextPath = path.substring(0, index);
415
416 path = CharPool.FORWARD_SLASH + path.substring(index + 1);
417 }
418 }
419
420 if (contextPath == null) {
421 HttpSession session = request.getSession();
422
423 ServletContext servletContext = session.getServletContext();
424
425 contextPath = ContextPathUtil.getContextPath(servletContext);
426 }
427
428 return new String[] {contextPath, path};
429 }
430
431 private static Log _log = LogFactoryUtil.getLog(
432 JSONWebServiceActionParameters.class);
433
434 private SortedArrayList<JSONWebServiceActionConfig>
435 _jsonWebServiceActionConfigs =
436 new SortedArrayList<JSONWebServiceActionConfig>();
437 private BinarySearch<String> _pathBinarySearch = new PathBinarySearch();
438
439 private class PathBinarySearch extends BinarySearch<String> {
440
441 @Override
442 protected int compare(int index, String element) {
443 JSONWebServiceActionConfig jsonWebServiceActionConfig =
444 _jsonWebServiceActionConfigs.get(index);
445
446 String fullPath = jsonWebServiceActionConfig.getFullPath();
447
448 return fullPath.compareTo(element);
449 }
450
451 @Override
452 protected int getLastIndex() {
453 return _jsonWebServiceActionConfigs.size() - 1;
454 }
455
456 }
457
458 }