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