001
014
015 package com.liferay.portal.jsonwebservice.action;
016
017 import com.liferay.portal.kernel.json.JSONFactoryUtil;
018 import com.liferay.portal.kernel.json.JSONSerializable;
019 import com.liferay.portal.kernel.json.JSONSerializer;
020 import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceAction;
021 import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceActionMapping;
022 import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceActionsManagerUtil;
023 import com.liferay.portal.kernel.util.CamelCaseUtil;
024 import com.liferay.portal.kernel.util.StringPool;
025 import com.liferay.portal.kernel.util.StringUtil;
026
027 import java.io.IOException;
028
029 import java.util.ArrayList;
030 import java.util.HashMap;
031 import java.util.Iterator;
032 import java.util.List;
033 import java.util.Map;
034 import java.util.Set;
035
036 import javax.servlet.http.HttpServletRequest;
037
038 import jodd.bean.BeanUtil;
039
040 import jodd.servlet.ServletUtil;
041
042 import jodd.util.KeyValue;
043
044
048 public class JSONWebServiceInvokerAction implements JSONWebServiceAction {
049
050 public JSONWebServiceInvokerAction(HttpServletRequest request) {
051 _request = request;
052
053 _command = request.getParameter("cmd");
054
055 if (_command == null) {
056 try {
057 _command = ServletUtil.readRequestBody(request);
058 }
059 catch (IOException ioe) {
060 throw new IllegalArgumentException(ioe);
061 }
062 }
063 }
064
065 public JSONWebServiceActionMapping getJSONWebServiceActionMapping() {
066 return null;
067 }
068
069 public Object invoke() throws Exception {
070 Object command = JSONFactoryUtil.looseDeserializeSafe(_command);
071
072 List<Object> list = null;
073
074 boolean batchMode = false;
075
076 if (command instanceof List) {
077 list = (List<Object>)command;
078
079 batchMode = true;
080 }
081 else if (command instanceof Map) {
082 list = new ArrayList<Object>(1);
083
084 list.add(command);
085
086 batchMode = false;
087 }
088 else {
089 throw new IllegalArgumentException();
090 }
091
092 for (int i = 0; i < list.size(); i++) {
093 Map<String, Map<String, Object>> map =
094 (Map<String, Map<String, Object>>)list.get(i);
095
096 if (map.isEmpty()) {
097 throw new IllegalArgumentException();
098 }
099
100 Set<Map.Entry<String, Map<String, Object>>> entrySet =
101 map.entrySet();
102
103 Iterator<Map.Entry<String, Map<String, Object>>> iterator =
104 entrySet.iterator();
105
106 Map.Entry<String, Map<String, Object>> entry = iterator.next();
107
108 Statement statement = _parseStatement(
109 entry.getKey(), entry.getValue());
110
111 Object result = _executeStatement(statement);
112
113 list.set(i, result);
114 }
115
116 Object result = null;
117
118 if (batchMode == false) {
119 result = list.get(0);
120 }
121 else {
122 result = list;
123 }
124
125 return new InvokerResult(result);
126 }
127
128 public class InvokerResult implements JSONSerializable {
129
130 public String toJSONString() {
131 if (_result == null) {
132 return JSONFactoryUtil.getNullJSON();
133 }
134
135 JSONSerializer jsonSerializer =
136 JSONFactoryUtil.createJSONSerializer();
137
138 jsonSerializer.exclude("*.class");
139
140 for (Statement statement : _statements) {
141 String name = statement.getName();
142
143 if (name == null) {
144 continue;
145 }
146
147 String includeName = name.substring(1);
148
149 _checkJSONSerializerIncludeName(includeName);
150
151 jsonSerializer.include(includeName);
152 }
153
154 return jsonSerializer.serialize(_result);
155 }
156
157 public Object getResult() {
158 return _result;
159 }
160
161 private InvokerResult(Object result) {
162 _result = result;
163 }
164
165 private Object _result;
166
167 }
168
169 private Object _addVariableStatement(
170 Statement statement, Statement variableStatement, Object result)
171 throws Exception {
172
173 result = _populateFlags(statement, result);
174
175 String name = variableStatement.getName();
176
177 Object variableResult = _executeStatement(variableStatement);
178
179 Map<String, Object> map = _convertObjectToMap(result);
180
181 map.put(name.substring(1), variableResult);
182
183 return map;
184 }
185
186 private Object _addVariableStatementList(
187 Statement statement, Statement variableStatement, Object result,
188 List<Object> results)
189 throws Exception {
190
191 List<Object> list = _convertObjectToList(result);
192
193 for (Object object : list) {
194 if (object instanceof List) {
195 Object value = _addVariableStatementList(
196 statement, variableStatement, object, results);
197
198 results.add(value);
199 }
200 else {
201 Object value = _addVariableStatement(
202 statement, variableStatement, object);
203
204 results.add(value);
205 }
206 }
207
208 return results;
209 }
210
211 private void _checkJSONSerializerIncludeName(String includeName) {
212 if (includeName.contains(StringPool.STAR)) {
213 throw new IllegalArgumentException(
214 includeName + " has special characters");
215 }
216 }
217
218 private List<Object> _convertObjectToList(Object object) {
219 if (!(object instanceof List)) {
220 String json = JSONFactoryUtil.looseSerialize(object);
221
222 object = JSONFactoryUtil.looseDeserialize(json, ArrayList.class);
223 }
224
225 return (List<Object>)object;
226 }
227
228 private Map<String, Object> _convertObjectToMap(Object object) {
229 if (!(object instanceof Map)) {
230 String json = JSONFactoryUtil.looseSerialize(object);
231
232 object = JSONFactoryUtil.looseDeserialize(json, HashMap.class);
233 }
234
235 return (Map<String, Object>)object;
236 }
237
238 private Object _executeStatement(Statement statement) throws Exception {
239 JSONWebServiceAction jsonWebServiceAction =
240 JSONWebServiceActionsManagerUtil.getJSONWebServiceAction(
241 _request, statement.getMethod(), null,
242 statement.getParameterMap());
243
244 Object result = jsonWebServiceAction.invoke();
245
246 result = _filterResult(statement, result);
247
248 List<Statement> variableStatements = statement.getVariableStatements();
249
250 if (variableStatements != null) {
251 for (Statement variableStatement : variableStatements) {
252 if (result instanceof List) {
253 result = _addVariableStatementList(
254 statement, variableStatement, result,
255 new ArrayList<Object>());
256 }
257 else {
258 result = _addVariableStatement(
259 statement, variableStatement, result);
260 }
261 }
262 }
263
264 return result;
265 }
266
267 private Object _filterResult(Statement statement, Object result) {
268 if (result instanceof List) {
269 result = _filterResultList(
270 statement, result, new ArrayList<Object>());
271 }
272 else {
273 result = _filterResultObject(statement, result);
274 }
275
276 return result;
277 }
278
279 private Object _filterResultList(
280 Statement statement, Object result, List<Object> results) {
281
282 List<Object> list = _convertObjectToList(result);
283
284 for (Object object : list) {
285 Object value = _filterResultObject(statement, object);
286
287 results.add(value);
288 }
289
290 return results;
291 }
292
293 private Object _filterResultObject(Statement statement, Object result) {
294 if (result == null) {
295 return result;
296 }
297
298 String[] whitelist = statement.getWhitelist();
299
300 if (whitelist == null) {
301 return result;
302 }
303
304 Map<String, Object> map = _convertObjectToMap(result);
305
306 Map<String, Object> whitelistMap = new HashMap<String, Object>(
307 whitelist.length);
308
309 for (String key : whitelist) {
310 Object value = map.get(key);
311
312 whitelistMap.put(key, value);
313 }
314
315 return whitelistMap;
316 }
317
318 private Statement _parseStatement(
319 String assignment, Map<String, Object> statementBody) {
320
321 Statement statement = new Statement();
322
323 _statements.add(statement);
324
325 int x = assignment.indexOf(StringPool.EQUAL);
326
327 if (x == -1) {
328 statement.setMethod(assignment.trim());
329 }
330 else {
331 String name = assignment.substring(0, x).trim();
332
333 int y = name.indexOf(StringPool.OPEN_BRACKET);
334
335 if (y != -1) {
336 String whitelistString = name.substring(
337 y + 1, name.length() - 1);
338
339 String[] whiteList = StringUtil.split(whitelistString);
340
341 for (int i = 0; i < whiteList.length; i++) {
342 whiteList[i] = whiteList[i].trim();
343 }
344
345 statement.setWhitelist(whiteList);
346
347 name = name.substring(0, y);
348 }
349
350 statement.setName(name);
351
352 statement.setMethod(assignment.substring(x + 1).trim());
353 }
354
355 HashMap<String, Object> parameterMap = new HashMap<String, Object>(
356 statementBody.size());
357
358 statement.setParameterMap(parameterMap);
359
360 for (String key : statementBody.keySet()) {
361 if (key.startsWith(StringPool.AT)) {
362 String value = (String)statementBody.get(key);
363
364 List<Flag> flags = statement.getFlags();
365
366 if (flags == null) {
367 flags = new ArrayList<Flag>();
368
369 statement.setFlags(flags);
370 }
371
372 Flag flag = new Flag();
373
374 flag.setKey(key.substring(1));
375 flag.setValue(value);
376
377 flags.add(flag);
378 }
379 else if (key.startsWith(StringPool.DOLLAR)) {
380 Map<String, Object> map =
381 (Map<String, Object>)statementBody.get(key);
382
383 List<Statement> variableStatements =
384 statement.getVariableStatements();
385
386 if (variableStatements == null) {
387 variableStatements = new ArrayList<Statement>();
388
389 statement.setVariableStatements(variableStatements);
390 }
391
392 Statement variableStatement = _parseStatement(key, map);
393
394 variableStatements.add(variableStatement);
395 }
396 else {
397 Object value = statementBody.get(key);
398
399 parameterMap.put(CamelCaseUtil.normalizeCamelCase(key), value);
400 }
401 }
402
403 return statement;
404 }
405
406 private Object _populateFlags(Statement statement, Object result) {
407 if (result instanceof List) {
408 result = _populateFlagsList(
409 statement.getName(), result, new ArrayList<Object>());
410 }
411 else {
412 _populateFlagsObject(statement.getName(), result);
413 }
414
415 return result;
416 }
417
418 private List<Object> _populateFlagsList(
419 String name, Object result, List<Object> results) {
420
421 List<Object> list = _convertObjectToList(result);
422
423 for (Object object : list) {
424 if (object instanceof List) {
425 Object value = _populateFlagsList(name, object, results);
426
427 results.add(value);
428 }
429 else {
430 _populateFlagsObject(name, object);
431
432 results.add(object);
433 }
434 }
435
436 return results;
437 }
438
439 private void _populateFlagsObject(String name, Object object) {
440 if (name == null) {
441 return;
442 }
443
444 name = name.concat(StringPool.PERIOD);
445
446 for (Statement statement : _statements) {
447 List<Flag> flags = statement.getFlags();
448
449 if (flags == null) {
450 continue;
451 }
452
453 for (Flag flag : flags) {
454 String value = flag.getValue();
455
456 if ((value == null) || !value.startsWith(name)) {
457 continue;
458 }
459
460 Map<String, Object> parameterMap = statement.getParameterMap();
461
462 Object propertyValue = BeanUtil.getDeclaredProperty(
463 object, value.substring(name.length()));
464
465 parameterMap.put(flag.getKey(), propertyValue);
466 }
467 }
468 }
469
470 private String _command;
471 private HttpServletRequest _request;
472 private List<Statement> _statements = new ArrayList<Statement>();
473
474 private class Flag extends KeyValue<String, String> {
475 }
476
477 private class Statement {
478
479 public List<Flag> getFlags() {
480 return _flags;
481 }
482
483 public String getMethod() {
484 return _method;
485 }
486
487 public String getName() {
488 return _name;
489 }
490
491 public Map<String, Object> getParameterMap() {
492 return _parameterMap;
493 }
494
495 public List<Statement> getVariableStatements() {
496 return _variableStatements;
497 }
498
499 public String[] getWhitelist() {
500 return _whitelist;
501 }
502
503 public void setFlags(List<Flag> flags) {
504 _flags = flags;
505 }
506
507 public void setMethod(String method) {
508 _method = method;
509 }
510
511 public void setName(String name) {
512 _name = name;
513 }
514
515 public void setParameterMap(Map<String, Object> parameterMap) {
516 _parameterMap = parameterMap;
517 }
518
519 public void setVariableStatements(List<Statement> variableStatements) {
520 _variableStatements = variableStatements;
521 }
522
523 public void setWhitelist(String[] whitelist) {
524 _whitelist = whitelist;
525 }
526
527 private List<Flag> _flags;
528 private String _method;
529 private String _name;
530 private Map<String, Object> _parameterMap;
531 private List<Statement> _variableStatements;
532 private String[] _whitelist;
533
534 }
535
536 }