added a comment - - edited
I have a couple of class sources in a table on the database.
In a very simple example:
if I have a "Class_A" that depends on "Class_B", and I do...
ParseClass("Class_A");
...groovy will see that Class_A depends on Class_B, but if a had not set a classpath nor added a URL with "addURL(myURL)", groovy will not be able to resolve de dependency(ies).
I can't say to a GroovyClassLoader "my classpath is this table in my database" nor do something like addSource(an sourcecode got from my table).
The interface GroovyResourceLoader only has one method that returns a URL, but my classes are in DB... how could it help-me? I wanted to give a classname to it and receive the actual sourcecode, since my classes are in database, not in the filesystem...
So, I solved this creating a class that I called GroovyDBClassLoader (extends GroovyClassLoader) that overwrites parseClass() in a way that when I pass a classname to it, it will get the sourcecode for the given classname from the database, fetch its dependencies and parse everything (including the dependencies) in the same CompilationUnit and return the generatedClass.
To do this, I needed access the "generatedClass" attribute in the groovy.lang.GroovyClassLoader.ClassCollector, but it is privated...
Well, so I got the groovy sources, modified it creating a getter to "generatedClass" at groovy.lang.GroovyClassLoader.ClassCollector, and repack it in a groovy-all-xxx.jar
here is a resume of my GroovyDBClassLoader:
public class GroovyDBClassLoader extends GroovyClassLoader {
public Class parseDBClass(String classname, boolean shouldParseDeps,
boolean shouldCacheSource) throws ClassNotFoundException
{
synchronized (sourceCache) {
Class answer = (Class) sourceCache.get(classname);
if (answer != null) {
return answer;
}
Map<String, GroovyCodeSource> codeSources;
if (shouldParseDeps) {
codeSources = resourceLoader.loadSourceAndDeps(classname);
} else {
codeSources = new HashMap<String, GroovyCodeSource>();
codeSources.put(classname, resourceLoader.loadSource(classname));
}
GroovyCodeSource mainCodeSource = codeSources.remove(classname);
CompilationUnit unit = createCompilationUnit(config,
mainCodeSource.getCodeSource());
SourceUnit su = unit.addSource(mainCodeSource.getName(),
mainCodeSource.getInputStream());
Collection<GroovyCodeSource> dependencies = codeSources.values();
for (GroovyCodeSource cs : dependencies) {
if (classCache.get(cs.getName()) == null) {
unit.addSource(cs.getName(), cs.getInputStream());
}
}
GroovyClassLoader.ClassCollector collector = createCollector(unit, su);
unit.setClassgenCallback(collector);
int goalPhase = Phases.CLASS_GENERATION;
if (config != null && config.getTargetDirectory() != null) {
goalPhase = Phases.OUTPUT;
}
unit.compile(goalPhase);
answer = collector.getGeneratedClass();
if (mainCodeSource != null && mainCodeSource.isCachable()) {
sourceCache.put(classname, answer);
}
Collection<Class> loadedClasses = collector.getLoadedClasses();
for (Class clazz : loadedClasses) {
setClassCacheEntry(clazz);
String clazzname = clazz.getName();
GroovyCodeSource cs = codeSources.remove(clazzname);
if (cs != null && cs.isCachable()) {
sourceCache.put(clazzname, clazz);
}
}
return answer;
}
}
}
as you can see, I use a ResourceLoader, but this one is not the GroovyResourceLoader (cause it returns only URLs). I've written my on DatabaseResourceLoader...
Well... here is a resume of what I'm trying to do (with sample codes):
http://www.groovy-forum.org/viewtopic.php?t=511&sid=847d91df6a3a95ca53875c4bdfd07d99
thanks
I don't get a couple of things ...