/** * Builds an object for provided class. * * @param newClass class to construct * @param mode argument type * @param <T> The type of the class we're trying to build, so that we can return it typesafely * * @return constructed object * @throws InstantiationException if the class cannot be instantiated */ public <T> T constructObject(Class<T> newClass, Args mode) throws InstantiationException { return constructObject(newClass, mode, new Stack<>()); }
/** * Create a class scanner for provided base package. * * @param packageName The base package such as "com.yahoo.bard" * @param cacheValues Values to cache for use in object construction */ public ClassScanner(String packageName, Collection<Class> cacheValues) { this.packageName = packageName; putPrimitivesInValueCache(); putInArgumentValueCache(cacheValues); }
private <T> T constructArg(Class<T> cls, Args mode, Stack<Class> stack) throws InstantiationException { T arg = null; T cachedValue = getCachedValue(cls); arg = (T) new Object[0]; } else if (cls.isArray()) { Object arrayElement = constructArg(cls.getComponentType(), mode, stack); arg = (T) Array.newInstance(cls.getComponentType(), 1); Array.set(arg, 0, arrayElement); } else if (Modifier.isAbstract(cls.getModifiers())) { arg = constructSubclass(cls, mode, stack); } else { try { } catch (Throwable ignored) { try { arg = constructObject(cls, mode, stack); } catch (Throwable e2) { if (mode == Args.VALUES) { putInArgumentValueCache(arg.getClass(), arg);
private <T> T constructSubclass(Class<T> cls, Args mode, Stack<Class> stack) { T cachedValue = getCachedValue(cls); for (Class<?> subclass : getClasses()) { T arg = constructObject((Class<T>) subclass, mode, stack); if (arg != null) { return arg;
/** * Precompute all primitives. */ private void putPrimitivesInValueCache() { putInArgumentValueCache(int.class, 1); putInArgumentValueCache(long.class, 1L); putInArgumentValueCache(double.class, 1.0); putInArgumentValueCache(float.class, 1.0); putInArgumentValueCache(char.class, (char) 1); putInArgumentValueCache(byte.class, (byte) 1); putInArgumentValueCache(boolean.class, true); putInArgumentValueCache(Object[].class, new Object[0]); }
/** * Scans all classes accessible from the context class loader which belong to the given package and subpackages. * * @return The classes found under the class loader * * @throws IOException if a problem is encountered loading the resources from the package * @throws ClassNotFoundException if we're not able to find classes for the package in the directory */ public List<Class<?>> getClasses() throws IOException, ClassNotFoundException { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); assert classLoader != null; String path = packageName.replace('.', '/'); Enumeration<URL> resources = classLoader.getResources(path); TreeSet<File> dirs = new TreeSet<>(); while (resources.hasMoreElements()) { URL resource = resources.nextElement(); dirs.add(new File(resource.getFile())); } List<Class<?>> classes = new ArrayList<>(); for (File directory : dirs) { classes.addAll(findClasses(directory, packageName)); } return classes; }
return constructArg(newClass, mode, stack); Object arg = (cls == newClass ? null : constructArg(cls, argMode, stack));
private <T> T constructArg(Class<T> cls, Args mode, Stack<Class> stack) throws InstantiationException { T arg = null; T cachedValue = getCachedValue(cls); arg = (T) new Object[0]; } else if (cls.isArray()) { Object arrayElement = constructArg(cls.getComponentType(), mode, stack); arg = (T) Array.newInstance(cls.getComponentType(), 1); Array.set(arg, 0, arrayElement); } else if (Modifier.isAbstract(cls.getModifiers())) { arg = constructSubclass(cls, mode, stack); } else { try { } catch (Throwable ignored) { try { arg = constructObject(cls, mode, stack); } catch (Throwable e2) { if (mode == Args.VALUES) { putInArgumentValueCache(arg.getClass(), arg);
private <T> T constructSubclass(Class<T> cls, Args mode, Stack<Class> stack) { T cachedValue = getCachedValue(cls); for (Class<?> subclass : getClasses()) { T arg = constructObject((Class<T>) subclass, mode, stack); if (arg != null) { return arg;
/** * Precompute all primitives. */ private void putPrimitivesInValueCache() { putInArgumentValueCache(int.class, 1); putInArgumentValueCache(long.class, 1L); putInArgumentValueCache(double.class, 1.0); putInArgumentValueCache(float.class, 1.0); putInArgumentValueCache(char.class, (char) 1); putInArgumentValueCache(byte.class, (byte) 1); putInArgumentValueCache(boolean.class, true); putInArgumentValueCache(Object[].class, new Object[0]); }
/** * Scans all classes accessible from the context class loader which belong to the given package and subpackages. * * @return The classes found under the class loader * * @throws IOException if a problem is encountered loading the resources from the package * @throws ClassNotFoundException if we're not able to find classes for the package in the directory */ public List<Class<?>> getClasses() throws IOException, ClassNotFoundException { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); assert classLoader != null; String path = packageName.replace('.', '/'); Enumeration<URL> resources = classLoader.getResources(path); TreeSet<File> dirs = new TreeSet<>(); while (resources.hasMoreElements()) { URL resource = resources.nextElement(); dirs.add(new File(resource.getFile())); } List<Class<?>> classes = new ArrayList<>(); for (File directory : dirs) { classes.addAll(findClasses(directory, packageName)); } return classes; }
return constructArg(newClass, mode, stack); Object arg = (cls == newClass ? null : constructArg(cls, argMode, stack));
/** * Create a class scanner for provided base package. * * @param packageName The base package such as "com.yahoo.bard" * @param cacheValues Values to cache for use in object construction */ public ClassScanner(String packageName, Collection<Class> cacheValues) { this.packageName = packageName; putPrimitivesInValueCache(); putInArgumentValueCache(cacheValues); }
/** * Store a value in the argument value cache, keyed by its class. * * @param values The value being cached */ public void putInArgumentValueCache(Collection<?> values) { values.forEach(value -> putInArgumentValueCache(value.getClass(), value)); }
/** * Recursive method used to find all classes in a given directory and subdirectories. * * @param directory The base directory * @param packageName The package name for classes found inside the base directory * @return The classes * @throws ClassNotFoundException if a class in the directory cannot be loaded */ private List<Class<?>> findClasses(File directory, String packageName) throws ClassNotFoundException { List<Class<?>> classes = new ArrayList<>(); if (!directory.exists()) { return classes; } Iterable<File> files = new TreeSet<>(Arrays.asList(directory.listFiles())); for (File file : files) { String name = file.getName(); if (file.isDirectory()) { assert !name.contains("."); // Extend the package and recurse classes.addAll(findClasses(file, packageName + "." + name)); } else if (name.endsWith(".class")) { // Grab just the class name, stripping the .class extension name = packageName + '.' + name.substring(0, name.length() - 6); classes.add(Class.forName(name)); } } return classes; }
/** * Builds an object for provided class. * * @param newClass class to construct * @param mode argument type * @param <T> The type of the class we're trying to build, so that we can return it typesafely * * @return constructed object * @throws InstantiationException if the class cannot be instantiated */ public <T> T constructObject(Class<T> newClass, Args mode) throws InstantiationException { return constructObject(newClass, mode, new Stack<>()); }
/** * Store a value in the argument value cache, keyed by its class. * * @param values The value being cached */ public void putInArgumentValueCache(Collection<?> values) { values.forEach(value -> putInArgumentValueCache(value.getClass(), value)); }
/** * Recursive method used to find all classes in a given directory and subdirectories. * * @param directory The base directory * @param packageName The package name for classes found inside the base directory * @return The classes * @throws ClassNotFoundException if a class in the directory cannot be loaded */ private List<Class<?>> findClasses(File directory, String packageName) throws ClassNotFoundException { List<Class<?>> classes = new ArrayList<>(); if (!directory.exists()) { return classes; } Iterable<File> files = new TreeSet<>(Arrays.asList(directory.listFiles())); for (File file : files) { String name = file.getName(); if (file.isDirectory()) { assert !name.contains("."); // Extend the package and recurse classes.addAll(findClasses(file, packageName + "." + name)); } else if (name.endsWith(".class")) { // Grab just the class name, stripping the .class extension name = packageName + '.' + name.substring(0, name.length() - 6); classes.add(Class.forName(name)); } } return classes; }