public NodeFactoryImpl()

in mixins/core-mixins/src/main/java/org/apache/axiom/core/NodeFactoryImpl.java [41:120]


    public NodeFactoryImpl(ClassLoader cl, String factory2ClassName, String... packages) {
        try {
            factory2 =
                    (NodeFactory2)
                            cl.loadClass(factory2ClassName).getDeclaredField("INSTANCE").get(null);
        } catch (ReflectiveOperationException ex) {
            throw new NodeFactoryException("Failed to instantiate NodeFactory2 implementation", ex);
        }
        List<Class<?>> implementations = new ArrayList<Class<?>>();
        for (String pkg : packages) {
            try {
                BufferedReader in =
                        new BufferedReader(
                                new InputStreamReader(
                                        cl.getResourceAsStream(
                                                pkg.replace('.', '/') + "/nodetypes.index"),
                                        StandardCharsets.UTF_8));
                try {
                    String line;
                    while ((line = in.readLine()) != null) {
                        if (line.startsWith("#")) {
                            continue;
                        }
                        String className = pkg + "." + line;
                        try {
                            implementations.add(cl.loadClass(className));
                        } catch (ClassNotFoundException ex) {
                            throw new NodeFactoryException("Failed to load class " + className, ex);
                        }
                    }
                } finally {
                    in.close();
                }
            } catch (IOException ex) {
                throw new NodeFactoryException(
                        "Failed to load node type index for package " + pkg, ex);
            }
        }
        implementations =
                TopologicalSort.sort(
                        implementations,
                        new EdgeRelation<Class<?>>() {
                            @Override
                            public boolean isEdge(Class<?> from, Class<?> to) {
                                return to.isAssignableFrom(from);
                            }
                        });
        Map<Class<?>, Class<?>> interfaceToImplementationMap = new HashMap<Class<?>, Class<?>>();
        Map<Class<?>, Constructor<?>> implementationToConstructorMap =
                new HashMap<Class<?>, Constructor<?>>();
        Set<Class<?>> ambiguousInterfaces = new HashSet<Class<?>>();
        for (Class<?> implementation : implementations) {
            Set<Class<?>> interfaces = new HashSet<Class<?>>();
            collectInterfaces(implementation, interfaces);
            for (Class<?> iface : interfaces) {
                if (!ambiguousInterfaces.contains(iface)) {
                    Class<?> clazz = interfaceToImplementationMap.get(iface);
                    if (clazz == null || implementation.isAssignableFrom(clazz)) {
                        interfaceToImplementationMap.put(iface, implementation);
                    } else if (!clazz.isAssignableFrom(implementation)) {
                        interfaceToImplementationMap.remove(iface);
                        ambiguousInterfaces.add(iface);
                    }
                }
            }
            try {
                implementationToConstructorMap.put(implementation, implementation.getConstructor());
            } catch (NoSuchMethodException ex) {
                throw new NodeFactoryException(
                        "Failed to get constructor for " + implementation.getName(), ex);
            }
        }
        constructorMap = new HashMap<Class<?>, Constructor<?>>();
        for (Map.Entry<Class<?>, Class<?>> entry : interfaceToImplementationMap.entrySet()) {
            constructorMap.put(
                    entry.getKey(), implementationToConstructorMap.get(entry.getValue()));
        }
        // TODO: this should eventually go away
        constructorMap.putAll(implementationToConstructorMap);
    }