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