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