View Javadoc
1   /**
2    * Copyright By Grandsoft Company Limited.  
3    * 2012-2-28 上午11:28:45
4    */
5   package gboat2.base.core.service;
6   
7   import gboat2.base.core.GBoatClassLoader;
8   import gboat2.base.core.annotation.Attach;
9   import gboat2.base.core.annotation.Attachs;
10  import gboat2.base.core.annotation.Modules;
11  import gboat2.base.core.annotation.Operation;
12  import gboat2.base.core.annotation.Operations;
13  import gboat2.base.core.annotation.Preference;
14  import gboat2.base.core.model.Module;
15  import gboat2.base.core.model.ModuleAttach;
16  import gboat2.base.core.model.Opera;
17  import gboat2.base.core.model.PreferenceDefinition;
18  import gboat2.base.bridge.util.BundleUtil;
19  
20  import java.lang.reflect.Method;
21  import java.util.ArrayList;
22  import java.util.HashMap;
23  import java.util.LinkedList;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Vector;
27  import java.util.concurrent.CopyOnWriteArrayList;
28  
29  import org.apache.commons.lang3.StringUtils;
30  import org.osgi.framework.Bundle;
31  import org.slf4j.Logger;
32  import org.slf4j.LoggerFactory;
33  
34  /**
35   * 
36   * @author zhaic
37   * @since jdk1.6
38   * @date 2012-2-28
39   */
40  
41  public class ModuleService implements IModuleService {
42  
43  	private static Logger logger = LoggerFactory.getLogger(ModuleService.class);
44  
45  	private static final List<Module> moduleList = new CopyOnWriteArrayList<Module>();
46  
47  	private static List<String> toRegistActionPackages = new LinkedList<String>();
48  
49  	//记录类对应的operations
50  	private static Map<String, List<Operation>> operationsInClass = new HashMap<String, List<Operation>>();
51  
52  	//记录操作间的关联关系,@Operation中invokeAction记录其关联关系
53  	//private static Map<String, List<String>> referOperas = new HashMap<String, List<String>>();
54  
55  	/**
56  	 * key: invokeAction.invokeMethod, value : actionClass.operationCode列表
57  	 * 一个action中的method可以有多个注解操作.为了解决在方法上的注解,当code与方法名不同时,出现权限出错的问题。
58  	 * 将每个方法对应的所有注解挂载到该方法下面,是一对多的关系。
59  	 */
60  	private static Map<String, List<String>> actionMethod2actionOperaCodesMapping = new HashMap<String, List<String>>();
61  
62  	/**
63  	 * 记录所有首选项定义
64  	 */
65  	private static List<PreferenceDefinition> preferences = new Vector<PreferenceDefinition>();
66  
67  	/**
68  	 * 记录所有模块附件集定义
69  	 */
70  	private static List<ModuleAttach> moduleAttachList = new Vector<ModuleAttach>();
71  
72  	public static List<String> getOperationCodesOf(String actionClass, String method) {
73  		return actionMethod2actionOperaCodesMapping.get(actionClass + "." + method);
74  	}
75  
76  	/**
77  	 * 解析Oprea对象,将其中的operaCodes挂载到actionMethod下
78  	 * @param opera
79  	 */
80  	private static void mountOpera2actionMethod(Opera opera) {
81  		String actionMethod = opera.getInvokeAction() + "." + opera.getInvokeMethod();
82  		if (actionMethod2actionOperaCodesMapping.containsKey(actionMethod)) {
83  			List<String> operas = actionMethod2actionOperaCodesMapping.get(actionMethod);
84  			if (!operas.contains(opera.getCode())) {//避免重复追加
85  				operas.add(opera.getCode());
86  			}
87  		} else {
88  			List<String> operaCodes = new LinkedList<String>();
89  			operaCodes.add(opera.getCode());
90  			actionMethod2actionOperaCodesMapping.put(actionMethod, operaCodes);
91  		}
92  	}
93  
94  	@Override
95  	public List<Module> getModuleListByBundleName(String bundleName) {
96  		List<Module> moduleList = new ArrayList<Module>();
97  		if (!StringUtils.isEmpty(bundleName)) {
98  			for (Module module : getModuleList()) {
99  				if (bundleName.equals(module.getBundleName()) && !moduleList.contains(module)) {
100 					moduleList.add(module);
101 				}
102 			}
103 		}
104 		return moduleList;
105 	}
106 
107 	@Override
108 	public List<Module> getModules() {
109 		return getModuleList();
110 	}
111 
112 	@Override
113 	public List<Module> getModules(String queryString) {
114 		List<Module> moduleList = new ArrayList<Module>();
115 		for (Module module : getModuleList()) {
116 			if (judgeModule(queryString, module)) {
117 				moduleList.add(module);
118 			}
119 		}
120 		return moduleList;
121 	}
122 
123 	@Override
124 	public List<Module> getModuleByBundleAddAction(String bundleName, String actionName) {
125 		List<Module> moduleList = new ArrayList<Module>();
126 		if (!StringUtils.isEmpty(bundleName) && !StringUtils.isEmpty(actionName)) {
127 			for (Module module : getModuleList()) {
128 				if (bundleName.equals(module.getBundleName())) {
129 					moduleList.add(module);
130 				}
131 			}
132 		}
133 		return moduleList;
134 	}
135 
136 	public static Module getModuleForMetadata(String bundleName, String actionName) {
137 		if (!StringUtils.isEmpty(bundleName) && !StringUtils.isEmpty(actionName)) {
138 			for (Module module : getModuleList()) {
139 				if (bundleName.equals(module.getBundleName()) && actionName.equals(module.getClassName())) {
140 					return module;
141 				}
142 			}
143 		}
144 		return null;
145 	}
146 
147 	@Override
148 	public List<Opera> getOperaByBundleAddAction(String bundleName, String actionName) {
149 		List<Opera> operaList = new ArrayList<Opera>();
150 		Module module = getModuleForMetadata(bundleName, actionName);
151 		if (module != null) {
152 			//将Module中的的operation注解值注册
153 			operaList.addAll(module.getOperas());
154 		}
155 		return operaList;
156 	}
157 
158 	@Override
159 	public List<Opera> getOperaByAction(String actionName) {
160 		if (actionName.indexOf(".") != -1) {
161 			String packageName = actionName.substring(0, actionName.lastIndexOf("."));
162 			Bundle bundle = GBoatClassLoader.getInstance().getBundle(packageName);
163 			if (null != bundle) {
164 				return getOperaByBundleAddAction(bundle.getSymbolicName(), actionName);
165 			}
166 		}
167 		return null;
168 	}
169 
170 	/**
171 	 * 获取某个Action的所有操作
172 	 * @param bundleName bundle名称
173 	 * @param actionName actionName名称
174 	 * @return  List<Opera>
175 	 */
176 	public static List<Opera> getOperaForMetadata(String bundleName, String actionName) {
177 		List<Opera> operaList = new ArrayList<Opera>();
178 		Module module = getModuleForMetadata(bundleName, actionName);
179 		if (module != null) {
180 			//将Module中的的operation注解值注册
181 			operaList.addAll(module.getOperas());
182 		}
183 		return operaList;
184 	}
185 
186 	/**
187 	 * 判断某个方法是否被Operations或者Operation注解注释
188 	 * @param method 方法名称
189 	 * @param clazz 当前类
190 	 * @return 当前类的当前方法是否有注解
191 	 */
192 	public static boolean isMethodOperationAnnotationed(Class<?> clazz, Method method, String privilegeMethod) {
193 		List<Operation> operations;
194 		if (operationsInClass.containsKey(clazz.getName())) {
195 			operations = (List<Operation>) operationsInClass.get(clazz.getName());
196 		} else {
197 			operations = new LinkedList<Operation>();
198 			//先判断是不是Action类级别的Operations注解中的方法
199 			Operations operAnnotationClass = (Operations) clazz.getAnnotation(Operations.class);
200 			if (null != operAnnotationClass) {
201 				Operation[] operas = operAnnotationClass.value();
202 				for (Operation opera : operas) {
203 					operations.add(opera);
204 				}
205 			}
206 			operationsInClass.put(clazz.getName(), operations);
207 		}
208 		for (Operation opera : operations) {
209 			if ((!StringUtils.isEmpty(opera.invokeMethod()) && opera.invokeMethod().equals(privilegeMethod))
210 					|| (StringUtils.isEmpty(opera.invokeMethod()) && opera.code().equals(privilegeMethod))) {
211 				return true;
212 			}
213 		}
214 		//再判断是不是在方法级别使用Operations或者Operation注解的方法
215 		return method.isAnnotationPresent(Operations.class) || method.isAnnotationPresent(Operation.class);
216 	}
217 
218 	//注册某个Bundle里的某个package下的Action的Module
219 	public static void registModule(String pkg) {
220 		//注册是不解析,在第一次使用时解析,参见getModuleList
221 		synchronized (toRegistActionPackages) {
222 			toRegistActionPackages.add(pkg);
223 		}
224 	}
225 
226 	private static List<Module> getModuleList() {
227 		synchronized (toRegistActionPackages) {
228 			if (toRegistActionPackages.size() > 0) {
229 				Bundle bundle;
230 				for (String pkg : toRegistActionPackages) {
231 					bundle = GBoatClassLoader.getInstance().getBundle(pkg);
232 					if (bundle == null) {
233 						logger.error("Can't find bundle for package[" + pkg + "]");
234 					}
235 					List<String> classList = BundleUtil.getClasses(pkg, bundle);
236 					List<Class<?>> actionList = getClassesFromBundle(classList, bundle);
237 					for (Class<?> actionClass : actionList) {
238 						//处理首选项的注解
239 						processPreferenceAnnotation(actionClass, bundle.getSymbolicName());
240 
241 						processAttachAnnotation(actionClass);
242 
243 						//处理操作注解
244 						List<Opera> operas = processOperationAnnotationsOfAction(actionClass);
245 
246 						//处理模块注解
247 						processModuleAnnotationsOfAction(bundle.getSymbolicName(), actionClass, operas);
248 					}
249 				}
250 				toRegistActionPackages.clear();
251 			}
252 		}
253 		return moduleList;
254 	}
255 
256 	/**
257 	 * 处理action class上的所有模块注解
258 	 * @param string 
259 	 * @param action
260 	 * @param operas 
261 	 * @return
262 	 */
263 	private static void processModuleAnnotationsOfAction(String bundle, Class<?> action, List<Opera> operas) {
264 		//处理单个注解
265 		gboat2.base.core.annotation.Module m = action.getAnnotation(gboat2.base.core.annotation.Module.class);
266 		if (null != m) {
267 			Module module = new Module(m, bundle, action, operas);
268 			if (!moduleList.contains(module)) {
269 				moduleList.add(module);
270 			}
271 		}
272 
273 		//处理集合注解
274 		Modules tmp = action.getAnnotation(Modules.class);
275 		if (null != tmp) {
276 			gboat2.base.core.annotation.Module[] modules = tmp.value();
277 			for (gboat2.base.core.annotation.Module mod : modules) {
278 				Module module = new Module(mod, bundle, action, operas);
279 				if (!moduleList.contains(module)) {
280 					moduleList.add(module);
281 				}
282 			}
283 		}
284 	}
285 
286 	public static void unRegistModule(Bundle bundle) {
287 		for (Module module : moduleList) {
288 			if (bundle.getSymbolicName().equals(module.getBundleName())) {
289 				moduleList.remove(module);
290 			}
291 		}
292 	}
293 
294 	/**
295 	 * 判断一个Operation注解的是否为一个跨action调用的注解
296 	 * 如果Opera中的action与invokeAction不相同,则表示跨action
297 	 * @param opera
298 	 * @return 
299 	 */
300 	private static boolean isCrossAction(Opera opera) {
301 		return !opera.getAction().equals(opera.getInvokeAction());
302 	}
303 
304 	/**
305 	 * 根据方法级别上的Operation注解构造Opera操作对象,并将相应的actionOperationCode挂载到actionMethod下
306 	 * @param operation
307 	 * @param method
308 	 * @param action
309 	 * @return
310 	 */
311 	private static Opera constructMethodLevelOpera(Operation operation, Method method, Class<?> action) {
312 		Opera opera = new Opera(operation, method, action);
313 
314 		//opera构造完毕后需要挂载到actionMethod下
315 		mountOpera2actionMethod(opera);
316 
317 		//opera构造完毕后需要判断是否跨Action,如果跨action,则需要为该方法也挂载一个相同的actionOperationCode
318 		if (isCrossAction(opera)) {
319 			//需要多构造一个非跨action的opera,挂载到actionMethod, 但这个opera不添加到module的opera list中
320 			Opera tmp = new Opera("", operation.code(), action.getClass().getName(), action.getClass().getName(), method.getName(), "");
321 			mountOpera2actionMethod(tmp);//执行挂载
322 		}
323 		return opera;
324 	}
325 
326 	/**
327 	 * 根据类法级别上的Operation注解构造Opera操作对象,并将相应的actionOperationCode挂载到actionMethod下
328 	 * @param operation
329 	 * @param action
330 	 * @return
331 	 */
332 	private static Opera constructClassLevelOpera(Operation operation, Class<?> action) {
333 		Opera opera = new Opera(operation, action);
334 		//opera构造完毕后需要挂载到actionMethod下
335 		mountOpera2actionMethod(opera);
336 		return opera;
337 	}
338 
339 	/**
340 	 * 处理ationClass类上所有的Operation注解。
341 	 * 如果已经添加了方法级别的Operation注解,则类级别的重复的Operation注解自动失效
342 	 * @param action
343 	 * @return ationClass的所有操作
344 	 */
345 	private static List<Opera> processOperationAnnotationsOfAction(Class<?> action) {
346 		List<Opera> operas = new ArrayList<Opera>();
347 
348 		//处理所有方法级别的注解
349 		List<Method> methods = getMethodsOfOperationAnnotationed(action);
350 		Operations operations;
351 		Operation operation;
352 		if (null != methods) {
353 			for (Method method : methods) {
354 				operations = method.getAnnotation(Operations.class);
355 				if (null != operations) {
356 					Operation[] opers = operations.value();
357 					for (Operation tmp : opers) {
358 						operas.add(constructMethodLevelOpera(tmp, method, action));
359 					}
360 				}
361 				operation = method.getAnnotation(Operation.class);
362 				if (null != operation) {
363 					operas.add(constructMethodLevelOpera(operation, method, action));
364 				}
365 			}
366 		}
367 
368 		//处理类级别的注解
369 		operations = action.getAnnotation(Operations.class);
370 		if (null != operations) {
371 			Operation[] opers = operations.value();
372 			for (Operation tmp : opers) {
373 				//如果已经添加了方法级别的Operation注解,则类级别的重复的Operation注解自动失效,不再添加
374 				if (null == getOperaByClassAndcode(operas, tmp.code())) {
375 					operas.add(constructClassLevelOpera(tmp, action));
376 				}
377 			}
378 		}
379 		operation = action.getAnnotation(Operation.class);
380 		if (null != operation) {
381 			//如果已经添加了方法级别的Operation注解,则类级别的重复的Operation注解自动失效,不再添加
382 			if (null == getOperaByClassAndcode(operas, operation.code())) {
383 				operas.add(constructClassLevelOpera(operation, action));
384 			}
385 		}
386 
387 		return operas;
388 	}
389 
390 	//将传入的Method对象提取注解,解析为Opera对象
391 	//	private static List<Opera> getOperasMethodByMethodList(Class actionClass, List<Method> methodList) {
392 	//		List<Opera> operaList = new ArrayList<Opera>();
393 	//		for (Method method : methodList) {
394 	//			Operations operations = method.getAnnotation(Operations.class);
395 	//			if (null != operations) {
396 	//				//获取其子注解
397 	//				Operation[] opers = ((Operations) operations).value();
398 	//				for (Operation tempOper : opers) {
399 	//					Opera tempOpera = new Opera();
400 	//					tempOpera.setName(tempOper.name());
401 	//					tempOpera.setDesc(tempOper.desc());
402 	//					tempOpera.setAction(actionClass.getName());
403 	//					tempOpera.setInvokeMethod(method.getName());
404 	//					tempOpera.setCode(tempOper.code());
405 	//					operaList.add(tempOpera);
406 	//					checkReferAtAnnotation(tempOper, actionClass, method.getName());
407 	//				}
408 	//			}
409 	//			Operation operation = method.getAnnotation(Operation.class);
410 	//			if (null != operation) {
411 	//				Opera tempOpera = new Opera();
412 	//				tempOpera.setName(operation.name());
413 	//				tempOpera.setDesc(operation.desc());
414 	//				tempOpera.setAction(actionClass.getName());
415 	//				tempOpera.setInvokeMethod(method.getName());
416 	//				tempOpera.setCode(operation.code());
417 	//				operaList.add(tempOpera);
418 	//				checkReferAtAnnotation(operation, actionClass, method.getName());
419 	//			}
420 	//		}
421 	//		return operaList;
422 	//	}
423 
424 	//	private static void checkReferAtAnnotation(Operation tempOper, Class actionClass, String methodName) {
425 	//		//如果注解包含了invokeAction,记录关联关系
426 	//		if (!StringUtils.isEmpty(tempOper.invokeAction())) {
427 	//			String key = tempOper.invokeAction() + "." + tempOper.invokeMethod();
428 	//			String referedName = actionClass.getName() + "." + tempOper.code();
429 	//			if (referOperas.containsKey(key)) {
430 	//				List<String> refers = referOperas.get(key);
431 	//				if (!refers.contains(referedName)) {
432 	//					refers.add(referedName);
433 	//				}
434 	//			} else {
435 	//				List<String> refers = new LinkedList();
436 	//				refers.add(referedName);
437 	//				referOperas.put(key, refers);
438 	//			}
439 	//		}
440 	//	}
441 
442 	//解析某个类上的@Operations注解
443 	//	private static List<Opera> getOperasByClass(Class<?> clazz, List<Opera> opera) {
444 	//		List<Opera> operaList = new ArrayList<Opera>();
445 	//		if (null != clazz) {
446 	//			Operations operations = clazz.getAnnotation(Operations.class);
447 	//			if (null != operations) {
448 	//				//获取其子注解
449 	//				Operation[] opers = ((Operations) operations).value();
450 	//				String methodName;
451 	//				for (Operation tempOper : opers) {
452 	//					//已经在Action的方法上添加了注解,则Action类上的注解自动失效,不再添加
453 	//					if (null == getOperaByClassAndcode(opera, tempOper.code())) {
454 	//						Opera tempOpera = new Opera();
455 	//						tempOpera.setName(tempOper.name());
456 	//						tempOpera.setDesc(tempOper.desc());
457 	//						tempOpera.setAction(clazz.getName());
458 	//						//如果不是注解在方法上就默认和code保持一致
459 	//						methodName = StringUtils.isEmpty(tempOper.invokeMethod()) ? tempOper.code() : tempOper
460 	//						        .invokeMethod();
461 	//						tempOpera.setInvokeMethod(methodName);
462 	//						tempOpera.setCode(tempOper.code());
463 	//						operaList.add(tempOpera);
464 	//						checkReferAtAnnotation(tempOper, clazz, methodName);
465 	//					}
466 	//				}
467 	//			}
468 	//		}
469 	//		return operaList;
470 	//	}
471 
472 	//获取某个类中被某个注解注释了的所有方法
473 	private static List<Method> getMethodsOfOperationAnnotationed(Class<?> clazz) {
474 		List<Method> methodList = new ArrayList<Method>();
475 		Method[] methodArray = clazz.getMethods();
476 		for (Method method : methodArray) {
477 			if (method.isAnnotationPresent(Operations.class) || method.isAnnotationPresent(Operation.class)) {
478 				methodList.add(method);
479 			}
480 		}
481 		return methodList;
482 	}
483 
484 	//判断是否符合查询条件
485 	private boolean judgeModule(String queryStr, Module module) {
486 		if (!StringUtils.isEmpty(queryStr)) {
487 			//如果Bundle名、类名、Bundle描述、节点名中包含要查询的字符串,则返回true
488 			if (module.getBundleName().indexOf(queryStr) != -1) {
489 				return true;
490 			}
491 			if (module.getClassName().indexOf(queryStr) != -1) {
492 				return true;
493 			}
494 			if (module.getModuleDesc().indexOf(queryStr) != -1) {
495 				return true;
496 			}
497 			if (module.getModuleName().indexOf(queryStr) != -1) {
498 				return true;
499 			}
500 		}
501 		return false;
502 	}
503 
504 	//获取某个Bundle中某个包下的所有类
505 	private static List<Class<?>> getClassesFromBundle(List<String> classNames, Bundle bundle) {
506 		List<Class<?>> classes = new ArrayList<Class<?>>();
507 		for (String className : classNames) {
508 			try {
509 				Class<?> clazz = bundle.loadClass(className);
510 				if (null != clazz) {
511 					classes.add(clazz);
512 				}
513 			} catch (ClassNotFoundException e) {
514 				e.printStackTrace();
515 			}
516 		}
517 		return classes;
518 	}
519 
520 	/** 
521 	 * 根据Action名和Opera的code属性,获取符合等于该两个属性的Opera
522 	 * @param className 该Opera所在的类
523 	 * @param operaCode 该Opera的code
524 	 * @return Opera对象
525 	 */
526 	private static Opera getOperaByClassAndcode(List<Opera> opera, String operaCode) {
527 		if (!StringUtils.isEmpty(operaCode)) {
528 			for (Opera tempOpera : opera) {
529 				if (operaCode.equals(tempOpera.getCode())) {
530 					return tempOpera;
531 				}
532 			}
533 		}
534 		return null;
535 	}
536 
537 	//	public static List<String> getReferActions(String opera) {
538 	//		return referOperas.get(opera);
539 	//	}
540 
541 	@Override
542 	public List<PreferenceDefinition> getPreferences() {
543 		return preferences;
544 	}
545 
546 	@Override
547 	public List<ModuleAttach> getModuleAttachList() {
548 		return moduleAttachList;
549 	}
550 
551 	//action上处理首选项注解Preference
552 	private static void processPreferenceAnnotation(Class<?> actionClass, String bundle) {
553 		Preference pre = actionClass.getAnnotation(Preference.class);//解析类上的Preference注解
554 		PreferenceDefinition preDef;
555 		if (null != pre) {
556 			preDef = new PreferenceDefinition();
557 			preDef.setBundle(bundle);
558 			preDef.setActionClass(actionClass.getName());
559 			preDef.setFullname(pre.value());
560 			preferences.add(preDef);
561 		}
562 
563 		Method[] methods = actionClass.getMethods();
564 		if (null != methods) {
565 			for (Method method : methods) {//解析每个方法上的Preference注解
566 				pre = method.getAnnotation(Preference.class);
567 				if (null != pre) {
568 					preDef = new PreferenceDefinition();
569 					preDef.setBundle(bundle);
570 					preDef.setActionClass(actionClass.getName());
571 					preDef.setFullname(pre.value());
572 					preDef.setMethod(method.getName());
573 					preferences.add(preDef);
574 				}
575 			}
576 		}
577 	}
578 
579 	//action上处理首选项注解Preference
580 	private static void processAttachAnnotation(Class<?> actionClass) {
581 
582 		ModuleAttach moduleAttach;
583 		//处理单个Attach注解
584 		Attach attach = actionClass.getAnnotation(Attach.class);
585 
586 		if (null != attach) {
587 			moduleAttach = new ModuleAttach();
588 			if (StringUtils.isEmpty(attach.targetName())) {
589 				gboat2.base.core.annotation.Module module = actionClass.getAnnotation(gboat2.base.core.annotation.Module.class);
590 				if (null != module) {
591 					moduleAttach.setModuleName(module.name());
592 				}
593 			} else {
594 				moduleAttach.setModuleName(attach.targetName());
595 			}
596 			moduleAttach.setAttachCode(attach.code());
597 			moduleAttachList.add(moduleAttach);
598 		}
599 
600 		//处理集合注解(Attachs)
601 		Attachs attachs = actionClass.getAnnotation(Attachs.class);
602 		if (null != attachs) {
603 			Attach[] attachArray = attachs.value();
604 			for (Attach att : attachArray) {
605 				moduleAttach = new ModuleAttach();
606 				moduleAttach.setAttachCode(att.targetCode());
607 				moduleAttach.setModuleName(att.targetName());
608 				if (!moduleAttachList.contains(moduleAttach)) {
609 					moduleAttachList.add(moduleAttach);
610 				}
611 			}
612 		}
613 
614 	}
615 
616 }