package org.zstack.core.cloudbus; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; import org.springframework.core.type.filter.AnnotationTypeFilter; import org.springframework.core.type.filter.AssignableTypeFilter; import org.springframework.stereotype.Controller; import org.zstack.header.Component; import org.zstack.header.exception.CloudRuntimeException; import org.zstack.header.message.APIEvent; import org.zstack.header.message.APIMessage; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; public class MessageIntegrityChecker implements Component { private Set<String> basePkgs; private void check() { List<String> badMessages = new ArrayList<String>(); ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(true); scanner.addIncludeFilter(new AssignableTypeFilter(APIEvent.class)); scanner.addIncludeFilter(new AssignableTypeFilter(APIMessage.class)); scanner.addExcludeFilter(new AnnotationTypeFilter(Controller.class)); scanner.addExcludeFilter(new AnnotationTypeFilter(org.springframework.stereotype.Component.class)); for (String pkg : getBasePkgs()) { for (BeanDefinition bd : scanner.findCandidateComponents(pkg)) { Class<?> clazz; try { clazz = Class.forName(bd.getBeanClassName()); } catch (ClassNotFoundException e1) { throw new CloudRuntimeException(e1); } try { clazz.getConstructor(); } catch (NoSuchMethodException e) { badMessages.add(clazz.getName()); } catch (SecurityException e) { throw new CloudRuntimeException(e); } } } if (!badMessages.isEmpty()) { throw new CloudRuntimeException(String.format("Message %s must have a public zero-parameter constructor", badMessages)); } } @Override public boolean start() { check(); return true; } @Override public boolean stop() { return true; } public Set<String> getBasePkgs() { if (basePkgs == null) { basePkgs = new HashSet<String>(1); basePkgs.add("org.zstack"); } return basePkgs; } public void setBasePkgs(Set<String> basePkgs) { this.basePkgs = basePkgs; } }