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