private List<ComponentDeclaration> getDeclaredComponents(File jarFile) throws IOException { ZipInputStream zis = new ZipInputStream(new FileInputStream(jarFile)); List<ComponentDeclaration> componentDeclarations = null; List<ComponentDeclaration> componentOverrideDeclarations = null; try { for (ZipEntry entry = zis.getNextEntry(); entry != null && (componentDeclarations == null || componentOverrideDeclarations == null); entry = zis.getNextEntry()) { if (entry.getName().equals(ComponentAnnotationLoader.COMPONENT_LIST)) { componentDeclarations = this.jarLoader.getDeclaredComponents(zis); } else if (entry.getName().equals(ComponentAnnotationLoader.COMPONENT_OVERRIDE_LIST)) { componentOverrideDeclarations = this.jarLoader.getDeclaredComponents(zis); } } } finally { zis.close(); } // Merge all overrides found with a priority of 0. This is purely for backward compatibility // since the // override files is now deprecated. if (componentOverrideDeclarations != null) { if (componentDeclarations == null) { componentDeclarations = new ArrayList<ComponentDeclaration>(); } for (ComponentDeclaration componentOverrideDeclaration : componentOverrideDeclarations) { componentDeclarations.add( new ComponentDeclaration(componentOverrideDeclaration.getImplementationClassName(), 0)); } } return componentDeclarations; }
private void unloadComponents(File jarFile, ExtensionURLClassLoader classLoader) throws UninstallException { try { List<ComponentDeclaration> componentDeclarations = getDeclaredComponents(jarFile); if (componentDeclarations == null) { this.logger.debug("[{}] does not contain any component", jarFile); return; } for (ComponentDeclaration componentDeclaration : componentDeclarations) { try { for (ComponentDescriptor componentDescriptor : this.jarLoader.getComponentsDescriptors( classLoader.loadClass(componentDeclaration.getImplementationClassName()))) { this.componentManager.unregisterComponent( componentDescriptor.getRole(), componentDescriptor.getRoleHint()); } } catch (ClassNotFoundException e) { this.logger.error( "Failed to load class [{}]", componentDeclaration.getImplementationClassName(), e); } } } catch (Exception e) { throw new UninstallException("Failed to load jar file components", e); } }
/** * Loads all components defined using annotations. * * @param manager the component manager to use to dynamically register components * @param classLoader the classloader to use to look for the Component list declaration file ( * {@code META-INF/components.txt}) */ public void initialize(ComponentManager manager, ClassLoader classLoader) { try { // Find all declared components by retrieving the list defined in COMPONENT_LIST. List<ComponentDeclaration> componentDeclarations = getDeclaredComponents(classLoader, COMPONENT_LIST); // Find all the Component overrides and adds them to the bottom of the list as component // declarations with // the highest priority of 0. This is purely for backward compatibility since the override // files is now // deprecated. List<ComponentDeclaration> componentOverrideDeclarations = getDeclaredComponents(classLoader, COMPONENT_OVERRIDE_LIST); for (ComponentDeclaration componentOverrideDeclaration : componentOverrideDeclarations) { // Since the old way to declare an override was to define it in both a component.txt and a // component-overrides.txt file we first need to remove the override component declaration // stored in // componentDeclarations. componentDeclarations.remove(componentOverrideDeclaration); // Add it to the end of the list with the highest priority. componentDeclarations.add( new ComponentDeclaration(componentOverrideDeclaration.getImplementationClassName(), 0)); } initialize(manager, classLoader, componentDeclarations); } catch (Exception e) { // Make sure we make the calling code fail in order to fail fast and prevent the application // to start // if something is amiss. throw new RuntimeException("Failed to get the list of components to load", e); } }
/** * @param manager the component manager to use to dynamically register components * @param classLoader the classloader to use to look for the Component list declaration file ( * {@code META-INF/components.txt}) * @param componentDeclarations the declarations of components to register * @since 4.0M1 */ public void unregister( ComponentManager manager, ClassLoader classLoader, List<ComponentDeclaration> componentDeclarations) { for (ComponentDeclaration componentDeclaration : componentDeclarations) { try { for (ComponentDescriptor<?> componentDescriptor : getComponentsDescriptors( classLoader.loadClass(componentDeclaration.getImplementationClassName()))) { manager.unregisterComponent(componentDescriptor); if (componentDescriptor.getRoleType() instanceof ParameterizedType) { Class roleClass = ReflectionUtils.getTypeClass(componentDescriptor.getRoleType()); DefaultComponentDescriptor<?> classComponentDescriptor = new DefaultComponentDescriptor(componentDescriptor); classComponentDescriptor.setRoleType(roleClass); manager.unregisterComponent(classComponentDescriptor); } } } catch (ClassNotFoundException e) { getLogger() .warn( "Can't find any existing component with class [{}]. Ignoring it.", componentDeclaration.getImplementationClassName()); } } }
/** * @param manager the component manager to use to dynamically register components * @param classLoader the classloader to use to look for the Component list declaration file ( * {@code META-INF/components.txt}) * @param componentDeclarations the declarations of components to register * @since 4.0M1 */ public void register( ComponentManager manager, ClassLoader classLoader, List<ComponentDeclaration> componentDeclarations) { try { // 2) For each component class name found, load its class and use introspection to find the // necessary // annotations required to create a Component Descriptor. Map<RoleHint<?>, ComponentDescriptor<?>> descriptorMap = new HashMap<RoleHint<?>, ComponentDescriptor<?>>(); Map<RoleHint<?>, Integer> priorityMap = new HashMap<RoleHint<?>, Integer>(); for (ComponentDeclaration componentDeclaration : componentDeclarations) { Class<?> componentClass = classLoader.loadClass(componentDeclaration.getImplementationClassName()); // Look for ComponentRole annotations and register one component per ComponentRole found for (Type componentRoleType : findComponentRoleTypes(componentClass)) { for (ComponentDescriptor<?> componentDescriptor : this.factory.createComponentDescriptors(componentClass, componentRoleType)) { // If there's already a existing role/hint in the list of descriptors then decide which // one // to keep by looking at their priorities. Highest priority wins (i.e. lowest integer // value). RoleHint<?> roleHint = new RoleHint(componentDescriptor.getRoleType(), componentDescriptor.getRoleHint()); addComponent( descriptorMap, priorityMap, roleHint, componentDescriptor, componentDeclaration, true); } } } // 3) Activate all component descriptors for (ComponentDescriptor<?> descriptor : descriptorMap.values()) { manager.registerComponent(descriptor); } } catch (Exception e) { // Make sure we make the calling code fail in order to fail fast and prevent the application // to start // if something is amiss. throw new RuntimeException("Failed to dynamically load components with annotations", e); } }
@Override public boolean equals(Object object) { if (object == null) { return false; } if (object == this) { return true; } if (object.getClass() != getClass()) { return false; } ComponentDeclaration rhs = (ComponentDeclaration) object; return new EqualsBuilder() .append(getImplementationClassName(), rhs.getImplementationClassName()) .append(getPriority(), rhs.getPriority()) .isEquals(); }
private void addComponent( Map<RoleHint<?>, ComponentDescriptor<?>> descriptorMap, Map<RoleHint<?>, Integer> priorityMap, RoleHint<?> roleHint, ComponentDescriptor<?> componentDescriptor, ComponentDeclaration componentDeclaration, boolean warn) { if (descriptorMap.containsKey(roleHint)) { // Compare priorities int currentPriority = priorityMap.get(roleHint); if (componentDeclaration.getPriority() < currentPriority) { // Override! descriptorMap.put(roleHint, componentDescriptor); priorityMap.put(roleHint, componentDeclaration.getPriority()); } else if (componentDeclaration.getPriority() == currentPriority) { if (warn) { // Warning that we're not overwriting since they have the same priorities getLogger() .warn( "Component [{}] which implements [{}] tried to overwrite component " + "[{}]. However, no action was taken since both components have the same priority " + "level of [{}].", new Object[] { componentDeclaration.getImplementationClassName(), roleHint, descriptorMap.get(roleHint).getImplementation().getName(), currentPriority }); } } else { getLogger() .debug( "Ignored component [{}] since its priority level of [{}] is lower " + "than the currently registered component [{}] which has a priority of [{}]", new Object[] { componentDeclaration.getImplementationClassName(), componentDeclaration.getPriority(), currentPriority }); } } else { descriptorMap.put(roleHint, componentDescriptor); priorityMap.put(roleHint, componentDeclaration.getPriority()); } }