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