private void processDefaultAnnotation(final Class<?> cmb) { final DefaultImplementation di = cmb.getAnnotation(DefaultImplementation.class); // XXX hack: move to helper method + unify with rest of Tang! if (di != null) { final String diName = di.value() == Void.class ? di.name() : ReflectionUtilities.getFullName(di.value()); final ClassNode<?> cn = (ClassNode<?>) ch.getNode(cmb); final String cnS = cn.getFullName(); if (!usages.contains(diName, cnS)) { usages.put(diName, cnS); if (!knownClasses.contains(cn)) { knownClasses.add(cn); } } } }
@SuppressWarnings("unchecked") public Tint(final URL[] jars, final boolean checkTang) { final Object[] args = new Object[jars.length + 6]; for (int i = 0; i < jars.length; i++) { args[i] = jars[i]; } args[args.length - 1] = new TypeAnnotationsScanner(); args[args.length - 2] = new SubTypesScanner(); args[args.length - 3] = new MethodAnnotationsScanner(); args[args.length - 4] = new MethodParameterScanner(); args[args.length - 5] = "com.microsoft"; args[args.length - 6] = "org.apache"; final Reflections r = new Reflections(args); // Set<Class<?>> classes = new MonotonicSet<>(); final Set<String> strings = new TreeSet<>(); final Set<String> moduleBuilders = new MonotonicSet<>(); // Workaround bug in Reflections by keeping things stringly typed, and using Tang to parse them. // Set<Constructor<?>> injectConstructors = // (Set<Constructor<?>>)(Set)r.getMethodsAnnotatedWith(Inject.class); // for(Constructor<?> c : injectConstructors) { // classes.add(c.getDeclaringClass()); // } final Set<String> injectConstructors = r.getStore().getConstructorsAnnotatedWith(ReflectionUtilities.getFullName(Inject.class)); for (final String s : injectConstructors) { strings.add(s.replaceAll("\\.<.+$", "")); } final Set<String> parameterConstructors = r.getStore() .get(MethodParameterScanner.class, ReflectionUtilities.getFullName(Parameter.class)); for (final String s : parameterConstructors) { strings.add(s.replaceAll("\\.<.+$", "")); } // Set<Class> r.getConstructorsWithAnyParamAnnotated(Parameter.class); // for(Constructor<?> c : parameterConstructors) { // classes.add(c.getDeclaringClass()); // } final Set<String> defaultStrings = r.getStore() .get( TypeAnnotationsScanner.class, ReflectionUtilities.getFullName(DefaultImplementation.class)); strings.addAll(defaultStrings); strings.addAll( r.getStore() .get( TypeAnnotationsScanner.class, ReflectionUtilities.getFullName(NamedParameter.class))); strings.addAll( r.getStore() .get(TypeAnnotationsScanner.class, ReflectionUtilities.getFullName(Unit.class))); // classes.addAll(r.getTypesAnnotatedWith(DefaultImplementation.class)); // classes.addAll(r.getTypesAnnotatedWith(NamedParameter.class)); // classes.addAll(r.getTypesAnnotatedWith(Unit.class)); strings.addAll( r.getStore().get(SubTypesScanner.class, ReflectionUtilities.getFullName(Name.class))); moduleBuilders.addAll( r.getStore() .get( SubTypesScanner.class, ReflectionUtilities.getFullName(ConfigurationModuleBuilder.class))); // classes.addAll(r.getSubTypesOf(Name.class)); ch = Tang.Factory.getTang() .getDefaultClassHierarchy( jars, (Class<? extends ExternalConstructor<?>>[]) new Class[0]); // for(String s : defaultStrings) { // if(classFilter(checkTang, s)) { // try { // ch.getNode(s); // } catch(ClassHierarchyException | NameResolutionException | ClassNotFoundException e) // { // System.err.println(e.getMessage()); // } // } // } for (final String s : strings) { if (classFilter(checkTang, s)) { try { ch.getNode(s); } catch (ClassHierarchyException | NameResolutionException e) { System.err.println(e.getMessage()); } } } for (final String s : moduleBuilders) { if (classFilter(checkTang, s)) { try { ch.getNode(s); } catch (ClassHierarchyException | NameResolutionException e) { e.printStackTrace(); } } } final NodeVisitor<Node> v = new AbstractClassHierarchyNodeVisitor() { @Override public boolean visit(final NamedParameterNode<?> node) { final String nodeS = node.getFullName(); for (final String s : node.getDefaultInstanceAsStrings()) { if (!usages.contains(s, nodeS)) { usages.put(s, nodeS); } } return true; } @Override public boolean visit(final PackageNode node) { return true; } @Override public boolean visit(final ClassNode<?> node) { final String nodeS = node.getFullName(); for (final ConstructorDef<?> d : node.getInjectableConstructors()) { for (final ConstructorArg a : d.getArgs()) { if (a.getNamedParameterName() != null && !usages.contains(a.getNamedParameterName(), nodeS)) { usages.put(a.getNamedParameterName(), nodeS); } } } if (!knownClasses.contains(node)) { knownClasses.add(node); } return true; } }; int numClasses; do { numClasses = knownClasses.size(); Walk.preorder(v, null, ch.getNamespace()); for (final ClassNode<?> cn : knownClasses) { try { final String s = cn.getFullName(); if (classFilter(checkTang, s)) { final Class<?> c = ch.classForName(s); processDefaultAnnotation(c); processConfigurationModules(c); } } catch (final ClassNotFoundException e) { e.printStackTrace(); } } for (final Entry<Field, ConfigurationModule> entry : modules.entrySet()) { final String fS = ReflectionUtilities.getFullName(entry.getKey()); final Set<NamedParameterNode<?>> nps = entry.getValue().getBoundNamedParameters(); for (final NamedParameterNode<?> np : nps) { final String npS = np.getFullName(); if (!setters.contains(npS, fS)) { setters.put(npS, fS); } } } } while (numClasses != knownClasses .size()); // Note naive fixed point evaluation here. Semi-naive would be faster. }
private void processConfigurationModules(final Class<?> cmb) { for (final Field f : cmb.getFields()) { if (ReflectionUtilities.isCoercable(ConfigurationModule.class, f.getType())) { final int mod = f.getModifiers(); boolean ok = true; if (Modifier.isPrivate(mod)) { System.err.println("Found private ConfigurationModule " + f); ok = false; } if (!Modifier.isFinal(mod)) { System.err.println("Found non-final ConfigurationModule " + f); ok = false; } if (!Modifier.isStatic(f.getModifiers())) { System.err.println("Found non-static ConfigurationModule " + f); ok = false; } if (ok) { // System.err.println("OK: " + f); try { f.setAccessible(true); final String fS = ReflectionUtilities.getFullName(f); if (!modules.containsKey(f)) { modules.put(f, (ConfigurationModule) (f.get(null))); try { modules.get(f).assertStaticClean(); } catch (final ClassHierarchyException e) { System.err.println(fS + ": " + e.getMessage()); } for (final Entry<String, String> e : modules.get(f).toStringPairs()) { // System.err.println("e: " + e.getKey() + "=" + e.getValue()); try { final Node n = ch.getNode(e.getKey()); if (!setters.contains(e.getKey(), fS)) { setters.put(e.getKey(), fS); } if (n instanceof ClassNode) { final ClassNode<?> cn = (ClassNode<?>) n; if (!knownClasses.contains(cn)) { knownClasses.add(cn); } } } catch (final NameResolutionException ex) { // } try { final String s = e.getValue(); final Node n = ch.getNode(s); if (!usages.contains(ReflectionUtilities.getFullName(f), s)) { // System.err.println("Added usage: " + ReflectionUtilities.getFullName(f) + // "=" + s); usages.put(s, ReflectionUtilities.getFullName(f)); } if (n instanceof ClassNode) { final ClassNode<?> cn = (ClassNode<?>) n; if (!knownClasses.contains(cn)) { System.err.println("Added " + cn + " to known classes"); knownClasses.add(cn); } } } catch (final NameResolutionException ex) { // } } } } catch (final ExceptionInInitializerError e) { System.err.println( "Field " + ReflectionUtilities.getFullName(f) + ": " + e.getCause().getMessage()); } catch (final IllegalAccessException e) { throw new RuntimeException(e); } } } } }