/** * */ package jframe.core.plugin.service; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import jframe.core.plugin.annotation.InjectService; import jframe.core.plugin.annotation.Stop; /** * TODO 优化存储 * <p> * <li></li> * <li></li> * </p> * * @author dzh * @date Sep 16, 2014 6:40:15 AM * @since 1.1 */ public class ServiceContext { private static final Logger LOG = LoggerFactory.getLogger(ServiceContext.class); /** * <ServiceID,Service> */ Map<String, Service> _svcDef; /** * <ServiceID,List<Class>>,Class is injected Service */ Map<String, List<Class<?>>> _svcRef; public ServiceContext() { _svcDef = new HashMap<String, Service>(); _svcRef = new HashMap<String, List<Class<?>>>(); } public void regSvc(Service s) { if (s == null) return; synchronized (_svcDef) { _svcDef.put(s.getId(), s); } LOG.debug("Create Service Instance {}.", s.toString()); } /** * * @param id * service's id * @return */ public Service getSvcById(String id) { if (id == null) return null; synchronized (_svcDef) { return _svcDef.get(id); } } /** * Search service by service name * * @param name * @return */ public Service getSvcByName(String name) { if (name == null || "".equals(name)) return null; synchronized (_svcDef) { for (Service svc : _svcDef.values()) { if (svc.getName().equals(name)) return svc; } } return null; } public void unregSvc(String id) { synchronized (_svcDef) { _svcDef.remove(id); } } public void regSvcRef(String id, Class<?> clazz) { if (id == null || clazz == null) return; synchronized (_svcRef) { List<Class<?>> ref = _svcRef.get(id); if (ref == null) { ref = new LinkedList<Class<?>>(); _svcRef.put(id, ref); } if (!ref.contains(clazz)) ref.add(clazz); } } public void unregSvcRef(String id, Class<?> clazz) { if (id == null || clazz == null) return; synchronized (_svcRef) { List<Class<?>> ref = _svcRef.get(id); if (ref != null) { ref.remove(clazz); } if (ref.size() == 0) { _svcRef.remove(id); } } } /** * 这里假设只注入一次 inject service into obj * * @param svc * @param obj * @param reg * regSvcRef */ @Deprecated public void attachService(Service svc, Class<?> clazz, boolean reg) { if (svc == null || clazz == null) return; for (Field f : clazz.getDeclaredFields()) { if (Modifier.isStatic(f.getModifiers()) && f.isAnnotationPresent(InjectService.class) && svc.getId().equals(f.getAnnotation(InjectService.class).id())) { attachService(svc, f, reg); break; } } if (reg) { regSvcRef(svc.getId(), clazz); } } /** * TODO error if plug-in has not started * * @param svc * @param f * @param reg */ public void attachService(Service svc, Field f, boolean reg) { if (svc == null || f == null) return; if (hasInjected(svc, f.getDeclaringClass())) return; try { f.setAccessible(true); f.set(null, svc.getSingle()); if (reg) { regSvcRef(svc.getId(), f.getDeclaringClass()); } } catch (Exception e) { LOG.error(e.getMessage(), e.fillInStackTrace()); } LOG.debug("AttachService {} -> {}", svc.toString(), f.getDeclaringClass()); } boolean hasInjected(Service svc, Class<?> clazz) { if (svc == null || clazz == null) return false; synchronized (_svcRef) { List<Class<?>> list = _svcRef.get(svc.getId()); if (list == null) return false; return list.contains(clazz); } } /** * 这里假设只注入一次 * * @param svc * @param clazz * @param unreg * unregSvcRef() */ public void detachService(Service svc, Class<?> clazz, boolean unreg) { if (svc == null || clazz == null) return; for (Field f : clazz.getDeclaredFields()) { if (Modifier.isStatic(f.getModifiers()) && f.isAnnotationPresent(InjectService.class) && svc.getId().equals(f.getAnnotation(InjectService.class).id())) { try { f.setAccessible(true); f.set(null, null); } catch (Exception e) { LOG.error(e.getMessage()); } break; } } if (unreg) { unregSvcRef(svc.getId(), clazz); } LOG.debug("DetachService {} -> {}", svc.toString(), clazz); } /** * * @param id * serviceID */ public void detachService(String id) { Service svc = getSvcById(id); if (svc == null) return; try { synchronized (_svcRef) { if (_svcRef.get(id) != null) { for (Object clazz : _svcRef.get(id).toArray()) { detachService(svc, (Class<?>) clazz, true); } } } } finally { try { Service.invokeServiceMethod(svc.getSingle(), Stop.class); } catch (Exception e) { LOG.warn("Stop service {}!", svc.toString()); } } } /** * */ public void close() { if (_svcDef != null) { _svcDef.clear(); } if (_svcRef != null) { _svcRef.clear(); } } }