Hi all guys, during my last year of work I've met a replicated behavior in different projects, like the classpath analysis. Scanning the classpath could be useful to dynamically find services implementations or to generate custom documentation, or some other uses nobody has not envisioned yet. Follow below a short list of met use cases:
- Misko Hevery of Google developed a light yet powerful classpath explorer, but it seems the project has a very low activity, you can find more info on http://code.google.com/p/classpath-explorer/; - The MyBatis (formerly Apache iBatis) project added an utility class to discover MyBatis components from the classpath (http://code.google.com/p/mybatis/source/browse/trunk/src/main/java/org/apache/ibatis/io/ResolverUtil.java) - The Jersey (JAX-RS) project has a config parameter, "com.sun.jersey.config.property.packages", where users can specify packages where look for JSR311 components, like showed at "1.2. Deploying the root resource" on https://jersey.dev.java.net/nonav/documentation/latest/user-guide.html For this reason, I think that something from the threes can be reused and improved to create a common stuff to scan the classpath. First of all, no more package-based filter policy only, but rather something closer to an expression language, like ---- Filter filter = and( inSubpackage("com.acme"), isPublic(), not(isAbstract()), not(isAnnotation()), not(classNameMatches(".*TestCase")); ---- Second, since analyzing the classpath is an operation that could take a long time, I think that the "scan" operation should accept one (or optionally more) classpath handler, each one accepts one filter (as described above) associated to one (or optionally more) classpath entry handler. To be more clear, I'd like to show an example: ---- scan(new ClassPathHandler(and( inSubpackage("com.acme"), isPublic(), not(isAbstract()), not(isAnnotation()), not(classNameMatches(".*TestCase"))), new ClassPathEntryHandler() { public void doHandle(ClassPathEntry classPathEntry) { Class<?> type = classPathEntry.getClazz(); // manipulate the class } }, new ClassPathEntryHandler() { public void doHandle(ClassPathEntry classPathEntry) { if (log.isInfoEnabled()) { log.info("Plugged in my ACME system " + classPathEntry); } } } ), new ClassPathHandler(any(), new ClassPathEntryHandler() { public void doHandle(ClassPathEntry classPathEntry) { if (log.isDebugEnabled()) { log.debug("Plugged class " + classPathEntry); } } })) ---- Finally, the bootstrap: * a classpath could be created starting from the JVM one (the System.getProperty("java.class.path")) or from a custom one (like the one in a Servlet context); * a custom ClassLoader or the default Thread.currentThread().getContextClassLoader() is needed to resolve classpath entries to Class<?> object; * an error Handler (a default one is provided) is needed to catch eventual errors that could occur while scanning the classpath. That could be resumed in a chained builders, like: ---- ClassPath classPath = new ClassPathBuilder() .createFromJVM() .usingDefaultClassLoader() .usingDefaultErrorHandler(); ---- A codebase for this already exists, I committed it on Google-Code (http://code.google.com/p/meiyo/) and licensed it under ASL2.0. If you guys agree I'd be more than happy to port it under Commons-Lang (at least my instinct suggested Lang as the better place). WDYT? Thanks in advance and thanks for reading, I hop you'ven't got bored :P Have a nice day, Simo http://people.apache.org/~simonetripodi/ http://www.99soft.org/ --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org For additional commands, e-mail: dev-h...@commons.apache.org