1
2
3
4
5 package gboat2.base.core.web;
6
7 import gboat2.base.bridge.util.ClassHelper;
8 import gboat2.base.core.GBoatClassLoader;
9 import gboat2.base.core.annotation.DateFormat;
10 import gboat2.base.core.dao.Page;
11 import gboat2.base.core.dao.PageBean;
12 import gboat2.base.core.model.Opera;
13 import gboat2.base.core.service.IBaseService;
14 import gboat2.base.core.service.IOperationProvider;
15 import gboat2.base.core.service.ModuleService;
16 import gboat2.base.core.util.ActionUtil;
17 import gboat2.base.core.util.EnumTypeUtils;
18 import gboat2.base.core.util.EnumTypeWrapper;
19 import gboat2.base.core.util.JsonConfigUtil;
20 import gboat2.base.core.util.JsonUtil;
21 import gboat2.base.core.util.json.GboatJsonDateValueProcessor;
22 import gboat2.base.core.validate.PrivilegeCheckServiceFactory;
23 import gboat2.base.core.web.md.MetadataSupport;
24
25 import java.beans.PropertyDescriptor;
26 import java.lang.reflect.Field;
27 import java.lang.reflect.InvocationTargetException;
28 import java.lang.reflect.Method;
29 import java.text.SimpleDateFormat;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.HashMap;
33 import java.util.Iterator;
34 import java.util.LinkedList;
35 import java.util.List;
36 import java.util.Map;
37
38 import javax.persistence.Enumerated;
39
40 import net.sf.json.JSONArray;
41 import net.sf.json.JSONObject;
42 import net.sf.json.JsonConfig;
43
44 import org.apache.commons.beanutils.PropertyUtils;
45 import org.apache.commons.collections.CollectionUtils;
46 import org.apache.commons.lang3.StringUtils;
47 import org.osgi.framework.Bundle;
48 import org.osgi.framework.BundleContext;
49 import org.osgi.framework.FrameworkUtil;
50 import org.osgi.framework.ServiceReference;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53 import org.springframework.util.Assert;
54 import org.springframework.util.ReflectionUtils;
55
56 import com.opensymphony.xwork2.ActionSupport;
57
58
59
60
61
62
63
64
65
66
67 public abstract class MetadataSupportStrategy {
68 protected final static String FILTER_PARAMS = "filter_params_";
69 protected final static String DEFINED_OPERATIONS = "defined_operations_";
70
71
72 protected static Logger logger = LoggerFactory.getLogger(MetadataSupportStrategy.class);
73
74
75 static Map<Class<?>, List<Class<?>>> enumsInClass = new HashMap<Class<?>, List<Class<?>>>();
76
77
78
79
80
81
82
83 abstract Object getMetadata(String metadataType, String invokeMethod, BaseActionSupport action);
84
85
86
87
88
89
90
91
92
93 public JSONObject getMetadataFromResource(String invokeMethod, BaseActionSupport action) {
94 JSONObject jObj = MetadataSupport.parseMetadata(invokeMethod, action);
95 if (jObj == null) {
96 jObj = new JSONObject();
97 jObj.accumulate("success", false);
98 jObj.accumulate("message", "failed to read metadata for " + action.getClass().getName());
99 }
100
101 return jObj;
102 }
103
104
105
106
107
108
109
110
111
112 public JSONObject decorateMetadata(JSONObject returned, String invokeMethod, BaseActionSupport action) {
113 SplitMetadataStrategy splitMetadataStrategy;
114 if (ActionUtil.isListPage(invokeMethod, action)) {
115 splitMetadataStrategy = MetadataList.getInstance();
116 } else if (ActionUtil.isFormPage(invokeMethod, action)) {
117 splitMetadataStrategy = MetadataEdit.getInstance();
118 } else {
119 splitMetadataStrategy = MetadataOthers.getInstance();
120 }
121 return splitMetadataStrategy.decorateMetadata(returned, invokeMethod, action);
122 }
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137 public JSONObject decorateWithData(boolean calledInvokeMethod, JSONObject metadata, String invokeMethod, BaseActionSupport action,
138 JSONObject returned) {
139 JsonConfig jsonConf;
140 Class<?> checkClazz;
141
142 if (ActionUtil.isListPage(invokeMethod, action)) {
143 Bundle bundle = FrameworkUtil.getBundle(action.getClass());
144
145
146 List<Opera> operaList;
147
148 BundleContext context = bundle.getBundleContext();
149 ServiceReference<?> sf = context.getServiceReference(IOperationProvider.class);
150 if (sf != null) {
151
152 IOperationProvider provider = (IOperationProvider) context.getService(sf);
153 List<Opera> moduleOperaList = provider.getOperations(action);
154
155 String definedOperationsStr = action.request.getParameter(DEFINED_OPERATIONS);
156
157 if(StringUtils.isBlank(definedOperationsStr) || CollectionUtils.isEmpty(moduleOperaList)) {
158
159 operaList = moduleOperaList;
160 } else {
161 String[] definedOperations = StringUtils.split(definedOperationsStr, ',');
162 operaList = new ArrayList<Opera>(definedOperations.length);
163
164 for (String code : definedOperations) {
165 for (Opera opera : moduleOperaList) {
166 if(StringUtils.equals(StringUtils.trim(code), StringUtils.trim(opera.getCode()))) {
167 operaList.add(opera);
168 break;
169 }
170 }
171 }
172 }
173 } else {
174 operaList = ModuleService.getOperaForMetadata(bundle.getSymbolicName(), action.getClass().getName());
175 }
176
177 jsonConf = JsonConfigUtil.getJsonConfig(EnumTypeUtils.getEnumClassInDomain(action.getDomainClassAnnotationedForList()));
178 if (!calledInvokeMethod) {
179 try {
180 Method method = ReflectionUtils.findMethod(action.getClass(), invokeMethod);
181 if (method != null) {
182 ReflectionUtils.makeAccessible(method);
183 method.invoke(action, new Object[] {});
184 } else {
185 action.executeListQuery(action.getListParameterMap());
186 }
187 } catch (Exception e) {
188 throw new MetadataException(e);
189 }
190 }
191 Page<?> page = action.getPage();
192
193
194 String postMethodName = ActionUtil.getPostMethodName(invokeMethod);
195
196 if (!postMethodName.equals("postList")) {
197 try {
198 Method postListMethod = ReflectionUtils.findMethod(action.getClass(), postMethodName, new Class[] { Page.class });
199 if (null != postListMethod) {
200 ReflectionUtils.makeAccessible(postListMethod);
201 postListMethod.invoke(action, page);
202 }
203 } catch (Exception e) {
204 throw new MetadataException(e);
205 }
206 }
207
208 List<?> items = page.getResult();
209 JSONArray jsonObjs = new JSONArray();
210 List<Opera> priviArray = getOperationByPriviledge(operaList, action);
211 for (Object item : items) {
212 JSONObject finalObj = null;
213 if(StringUtils.isNotEmpty(action.request.getParameter(FILTER_PARAMS))){
214
215 finalObj = filterDataByParam(item, action);
216 }else{
217
218 finalObj = filterDataByMetadata(metadata, item, action);
219 }
220 if(finalObj != null){
221
222 finalObj.accumulate("operations", getOperationByData(priviArray, action, item));
223 jsonObjs.add(finalObj);
224 }
225 }
226
227 returned.accumulate("success", true);
228 returned.accumulate("data", jsonObjs);
229 PageBean pb = page.getPageBean();
230 returned.accumulate("results", pb.getCount());
231 returned.accumulate("total", pb.getPages());
232 returned.accumulate("page", pb.getPage());
233 } else {
234 jsonConf = JsonConfigUtil.getJsonConfig(EnumTypeUtils.getEnumClassInDomain(action.getDomainClassAnnotationed()));
235 checkClazz = action.getClass();
236 Method ajaxMethod, initMethod;
237 ajaxMethod = ReflectionUtils.findMethod(checkClazz, invokeMethod);
238 initMethod = ReflectionUtils.findMethod(checkClazz, ActionUtil.getInitMethodName(invokeMethod));
239 if (ajaxMethod == null && initMethod == null) {
240 returned.accumulate("success", false);
241 returned.accumulate("message", "can't get method[" + invokeMethod + "] for " + action.getClass().getName());
242 } else {
243 try {
244 if (!calledInvokeMethod && ajaxMethod != null) {
245 ReflectionUtils.makeAccessible(ajaxMethod);
246 ajaxMethod.invoke(action);
247 }
248 returned.accumulate("success", true);
249
250 boolean isAddData = true;
251 JSONObject jso = (JSONObject) metadata.get("cfg");
252 if (jso != null && !"request".equals(jso.get("backfill"))) {
253 isAddData = false;
254 }
255 if (isAddData) {
256 Map<String, Object> models = new HashMap<String, Object>();
257 List<Object> result = new ArrayList<Object>();
258 addGetDataToModels(action, action.getClass(), models);
259 result.add(models);
260 returned.accumulate("data", result.toArray(), jsonConf);
261 }
262
263
264 } catch (InvocationTargetException e) {
265 logger.warn("error in get data", e);
266 returned.accumulate("success", false);
267 Throwable throwable = e.getTargetException();
268 String message = null;
269 if (throwable != null) {
270 message = throwable.getMessage();
271 }
272 returned.accumulate("message", "error: " + message);
273 } catch (Exception e) {
274 logger.warn("error in get data", e);
275 returned.accumulate("success", false);
276 returned.accumulate("message", "error while get data : " + e.getMessage());
277 }
278 }
279 }
280 return returned;
281 }
282
283
284
285
286
287
288
289
290 private JSONObject filterDataByParam(Object data, BaseActionSupport action){
291 String filterParams = action.request.getParameter(FILTER_PARAMS);
292 String[] params = filterParams.split(",");
293 List<String> toCompare = Arrays.asList(params);
294
295 JsonConfig jsonConf = JsonConfigUtil.getJsonConfig(EnumTypeUtils.getEnumClassInDomain(action.getDomainClassAnnotationedForList()));
296
297 return filter(data, toCompare, action, jsonConf);
298 }
299
300
301
302
303
304
305
306 private JSONObject filterDataByMetadata(JSONObject metadata, Object data, BaseActionSupport action) {
307
308 JsonConfig jsonConf = JsonConfigUtil.getJsonConfig(EnumTypeUtils.getEnumClassInDomain(action.getDomainClassAnnotationedForList()));
309 JSONObject returnJSONObj = new JSONObject();
310 List<String> toCompare = new LinkedList<String>();
311 if (null != metadata) {
312
313 JSONArray headers = (JSONArray) metadata.get("headers");
314 if (null != headers) {
315 Iterator<?> headerItera = headers.iterator();
316
317 while (headerItera.hasNext()) {
318 JSONObject tempObj = (JSONObject) headerItera.next();
319
320 String dateFormat = (String) tempObj.get("dateFormat");
321 if (!StringUtils.isEmpty(dateFormat)) {
322 jsonConf.registerJsonValueProcessor((String) tempObj.get("dataIndex"), new GboatJsonDateValueProcessor(dateFormat));
323 }
324 }
325 String dataIndexObj;
326 Iterator<?> hIt = headers.iterator();
327 while (hIt.hasNext()) {
328 JSONObject tempObj = (JSONObject) hIt.next();
329 dataIndexObj = (String) tempObj.get("dataIndex");
330 if (!StringUtils.isEmpty(dataIndexObj) && !toCompare.contains(dataIndexObj)) {
331 toCompare.add(dataIndexObj);
332 }
333 }
334 }
335
336 returnJSONObj = filter(data, toCompare, action, jsonConf);
337 }
338 return returnJSONObj;
339 }
340
341 private JSONObject filter(Object data,List<String> toCompare,BaseActionSupport action,JsonConfig jsonConf){
342 JSONObject returnJSONObj = new JSONObject();
343 if(toCompare!=null && toCompare.size()>0){
344
345 JSONObject dataObj = JSONObject.fromObject(data, jsonConf);
346 JSONObject translatedObj;
347 Object value;
348 String dataIndexObj;
349 Iterator<?> hIt = toCompare.iterator();
350 while (hIt.hasNext()) {
351 dataIndexObj = (String) hIt.next();
352 if (!StringUtils.isEmpty(dataIndexObj)) {
353 value = dataObj.get(dataIndexObj);
354 if(value!=null){
355 translatedObj = JsonUtil.translateJSONOjbject(dataIndexObj, dataObj);
356 returnJSONObj.accumulate(dataIndexObj, translatedObj.get(dataIndexObj));
357 }
358 }
359 }
360 }else{
361 returnJSONObj = JSONObject.fromObject(data, jsonConf);
362 }
363
364 return returnJSONObj;
365 }
366
367 private void addGetDataToModels(BaseActionSupport action, Class<?> actionClass, Map<String, Object> models) {
368 getActionPropertiesValues(action, models, Boolean.FALSE);
369 }
370
371
372
373
374
375
376
377
378 private JSONArray getOperationByData(List<Opera> priviArray, BaseActionSupport action, Object data) {
379
380 Method getOperMethod = ReflectionUtils.findMethod(action.getClass(), "operationCheck", new Class[] { data.getClass(), String.class });
381 if (getOperMethod == null) {
382 getOperMethod = ReflectionUtils.findMethod(action.getClass(), "operationCheck", new Class[] { Object.class, String.class });
383 }
384
385 Iterator<Opera> it = priviArray.iterator();
386 List<String> operList = new ArrayList<String>();
387 Opera opera;
388 while (it.hasNext()) {
389 opera = (Opera) it.next();
390 String operCode = opera.getCode();
391 if ("sumbit".equals(operCode) || "add".equals(operCode)) {
392 continue;
393 }
394 if (!StringUtils.isEmpty(operCode)) {
395
396
397 boolean dataOperation = false;
398 if (null != getOperMethod) {
399 dataOperation = (Boolean) ReflectionUtils.invokeMethod(getOperMethod, action, new Object[] { data, operCode });
400 }
401
402 if (dataOperation) {
403 operList.add(operCode);
404 }
405 }
406 }
407
408 JSONArray returnJSONObj = JSONArray.fromObject(operList);
409 return returnJSONObj;
410 }
411
412
413
414
415
416
417
418 protected boolean callInitInvokedMethod(String invokeMethod, BaseActionSupport action) {
419 Assert.hasText(invokeMethod, "被调用的方法不能为空!");
420
421
422 if ("edit".equals(invokeMethod) || "view".equals(invokeMethod) || "list".equals(invokeMethod)) {
423
424 try {
425 Method method = action.getClass().getDeclaredMethod(invokeMethod, new Class[] {});
426 if (method == null) {
427 return false;
428 }
429 } catch (Exception ignore) {
430
431 return false;
432 }
433 }
434
435 String initMethodName = ActionUtil.getInitMethodName(invokeMethod);
436 try {
437 Method initMethod;
438 if (ActionUtil.isListPage(invokeMethod, action)) {
439
440 initMethod = ReflectionUtils.findMethod(action.getClass(), initMethodName, new Class[] { Map.class });
441 if (initMethod != null) {
442 ReflectionUtils.makeAccessible(initMethod);
443 initMethod.invoke(action, action.getListParameterMap());
444 return true;
445 }
446 } else {
447 initMethod = ReflectionUtils.findMethod(action.getClass(), initMethodName);
448 if (null != initMethod) {
449 ReflectionUtils.makeAccessible(initMethod);
450 ReflectionUtils.invokeMethod(initMethod, action);
451 return true;
452 }
453 }
454 } catch (SecurityException e) {
455 e.printStackTrace();
456 } catch (Exception e) {
457 e.printStackTrace();
458 }
459 return false;
460 }
461
462
463
464
465
466
467 public Map<String, Object> getActionParam(BaseActionSupport action) {
468 Map<String, Object> params = new HashMap<String, Object>();
469
470 params = getActionPropertiesValues(action, params, Boolean.TRUE);
471
472
473 List<Class<?>> toWrapper = new LinkedList<Class<?>>();
474
475 try {
476 if (action.getDomainClassAnnotationed() != null) {
477 toWrapper.add(action.getDomainClassAnnotationed());
478 }
479 } catch (Exception ignore) {
480
481 }
482 try {
483 Class<?> listDomainClass = action.getDomainClassAnnotationedForList();
484 while (listDomainClass != null && listDomainClass != Object.class) {
485 if (!toWrapper.contains(listDomainClass)) {
486 toWrapper.add(listDomainClass);
487 }
488 listDomainClass = listDomainClass.getSuperclass();
489 }
490 params.putAll(getEnumWrappers(toWrapper));
491 } catch (Exception ignore) {
492
493 }
494
495
496 EnumTypeUtils.registerEnumClass(action, params);
497
498 return params;
499 }
500
501
502
503
504
505
506
507 public Map<String, Object> getActionPropertiesValues(BaseActionSupport action, Map<String, Object> actionPropertiesValues, boolean isVelocityFill) {
508
509 PropertyDescriptor[] propertyDescriptors = PropertyUtils.getPropertyDescriptors(action);
510 List<PropertyDescriptor> asList = Arrays.asList(propertyDescriptors);
511
512 Map<String, Method> readMethodMap = new HashMap<String, Method>();
513
514 for (Iterator<PropertyDescriptor> iterator = asList.iterator(); iterator.hasNext();) {
515 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) iterator.next();
516 String name = propertyDescriptor.getName();
517
518
519 if (name.equals("priCheckParams")) {
520 continue;
521 }
522
523 Method readMethod = propertyDescriptor.getReadMethod();
524 if (readMethod != null) {
525 readMethodMap.put(name, readMethod);
526 }
527 }
528
529 Object value;
530 for (Class<?> clazz = action.getClass(); clazz != ActionSupport.class; clazz = clazz.getSuperclass()) {
531
532 Field[] declaredFields = clazz.getDeclaredFields();
533 for (int i = 0; i < declaredFields.length; i++) {
534 String name = declaredFields[i].getName();
535 Method readMethod = readMethodMap.get(name);
536 if (readMethod == null)
537 continue;
538 try {
539 value = readMethod.invoke(action, new Object[] {});
540
541 if (name.equals("model")) {
542 name = "_M";
543 }
544
545
546 if (value != null && !(value instanceof IBaseService)) {
547 actionPropertiesValues.put(name, value);
548 if (needToDealAsObject(value.getClass()) && !isVelocityFill) {
549
550 parseGetterOfObject(value, actionPropertiesValues, name + ".");
551 }
552 }
553
554 } catch (Exception e) {
555 }
556 }
557
558 }
559
560 return actionPropertiesValues;
561 }
562
563 private Map<String, Object> getEnumWrappers(List<Class<?>> classes) {
564 Map<String, Object> wrappers = new HashMap<String, Object>();
565 for (Class<?> domainClass : classes) {
566 if (domainClass != null) {
567 List<Class<?>> clazzes;
568 if (enumsInClass.containsKey(domainClass)) {
569 clazzes = enumsInClass.get(domainClass);
570 } else {
571 clazzes = EnumTypeUtils.getEnumClassInDomain(domainClass);
572 enumsInClass.put(domainClass, clazzes);
573 }
574 EnumTypeWrapper wrapper;
575 for (Class<?> enumClass : clazzes) {
576
577 wrapper = new EnumTypeWrapper(enumClass);
578 wrappers.put(enumClass.getName().replaceAll("\\.", "-"), wrapper);
579 wrappers.put(ClassHelper.getNameWithoutPackage(enumClass), wrapper);
580 }
581 }
582 }
583 return wrappers;
584 }
585
586 private boolean needToDealAsObject(Class<?> clazz) {
587 Package pack = clazz.getPackage();
588 return !(clazz.isPrimitive() || (pack != null && pack.getName().startsWith("java.lang"))
589 || (pack != null && pack.getName().startsWith("java.util")) || (pack != null && pack.getName().startsWith("java.math")) || (pack != null && pack
590 .getName().startsWith("java.sql")));
591 }
592
593 private void parseGetterOfObject(Object obj, Map<String, Object> models, String prefix) {
594 Method[] ms = obj.getClass().getMethods();
595 String name;
596 Object attObj;
597 for (Method m : ms) {
598 if (m.getName().startsWith("get") && m.getName().length() > 3) {
599 name = String.valueOf(m.getName().charAt(3)).toLowerCase() + m.getName().substring(4);
600 try {
601 if (ReflectionUtils.findField(obj.getClass(), name) != null) {
602 attObj = m.invoke(obj, new Object[] {});
603 if (attObj != null) {
604
605 if (attObj instanceof java.util.Date && m.isAnnotationPresent(DateFormat.class)) {
606 DateFormat pattern = m.getAnnotation(DateFormat.class);
607 SimpleDateFormat format = new SimpleDateFormat(pattern.value());
608 models.put(prefix + name, format.format(attObj));
609 } else if (m.isAnnotationPresent(Enumerated.class)) {
610 Enumerated enumAnno = m.getAnnotation(Enumerated.class);
611 if (enumAnno.value() == javax.persistence.EnumType.STRING) {
612 models.put(prefix + name, ((Enum<?>) attObj).name());
613 } else if (enumAnno.value() == javax.persistence.EnumType.ORDINAL) {
614 models.put(prefix + name, ((Enum<?>) attObj).ordinal());
615 }
616 } else {
617 if (!needToDealAsObject(attObj.getClass())) {
618 models.put(prefix + name, attObj);
619 } else {
620 parseGetterOfObject(attObj, models, prefix + name + ".");
621 }
622 }
623 }
624 }
625 } catch (SecurityException e) {
626 e.printStackTrace();
627 } catch (IllegalArgumentException e) {
628 e.printStackTrace();
629 } catch (IllegalAccessException e) {
630 e.printStackTrace();
631 } catch (InvocationTargetException e) {
632 e.printStackTrace();
633 }
634 }
635 }
636 }
637
638 private List<Opera> getOperationByPriviledge(List<Opera> operas, BaseActionSupport action) {
639 Iterator<Opera> it = operas.iterator();
640 List<Opera> operList = new LinkedList<Opera>();
641 Bundle bd = GBoatClassLoader.getInstance().getBundle(action.getClass().getPackage().getName());
642 Opera opera;
643 while (it.hasNext()) {
644 opera = it.next();
645 String operCode = opera.getCode();
646 if (!StringUtils.isEmpty(operCode)) {
647 Map<Object, Object> params = action.getPriCheckParams();
648 params.put("ACTION_NAME", action.getClass().getName());
649 params.put("METHOD_NAME", StringUtils.defaultIfBlank(opera.getInvokeMethod(), opera.getCode()));
650 params.put("REQUEST", action.request);
651 boolean priCheckResult = PrivilegeCheckServiceFactory.operationCheckServiceByMethodName(params, bd);
652
653 if (priCheckResult) {
654 operList.add(opera);
655 }
656 }
657 }
658
659 return operList;
660 }
661 }