2009-04-07 5 views
2

J'essaie d'étendre un constructeur de code Eclipse (pour générer des DTOs à partir de VO Hibernate) - et il utilise Groovy pour son système de template.Comment définir un classpath de scripts Groovy incorporés?

Le code qu'il utilise pour créer le script groovy est un peu bizarre (pas ce que je vois dans la documentation Groovy) mais il fonctionne, la plupart du temps:

GroovyShell shell = new GroovyShell(); 
script = shell.parse(source); 

Puis, plus tard:

Binding binding = (bindings == null ? new Binding() : new Binding(bindings)); 
Script scriptInstance = InvokerHelper.createScript(script.getClass(), binding); 
scriptInstance.setProperty("out", out); 
scriptInstance.run(); 
out.flush(); 

Maintenant, cela fonctionne très bien, jusqu'à ce qu'il frappe une référence à un objet qui n'est pas directement dans le projet. Dans le script, il parcourt les propriétés de la classe qu'il traite - quand il le fait, Groovy regarde toutes les méthodes et quand il ne peut pas trouver une définition de classe pour l'un des paramètres de la méthode, il craps. Dans ce cas, il est en train de mourir quand il trouve des références à Hibernate, mais je suis sûr qu'il va s'en sortir avec beaucoup plus. Il n'a pas besoin de leur faire quoi que ce soit, mais il ne peut pas vivre sans savoir ce qu'ils sont apparemment.

Script ne semble pas avoir un chargeur de classe que je peux fournir des informations de chemin de classe, donc j'ai essayé de le fournir à la GroovyShell - aucune différence.

Quelle est la bonne façon de résoudre ce problème afin que l'interpréteur Groovy puisse trouver mes projets référencés Jars?

Répondre

2

J'ai eu ce problème exact et résolu le problème en créant mon propre URLClassLoader, et en utilisant la réflexion pour appeler une méthode protégée pour ajouter un nouveau chemin d'accès au ClassPath

// Specify the path you want to add 
URL url = new URL("file://path/to/classes/here"); 

// Create a new class loader as a child of the default system class loader 
ClassLoader loader = new URLClassLoader(System.getClass().getClassLoader()); 

// Get the AddURL method and call it 
Method method = URLClassLoader.class.getDeclaredMethod("addURL",new Class[]{URL.class}); 
method.setAccessible(true); 
method.invoke(loader,new Object[]{ url }); 

GroovyShell shell = new GroovyShell(loader); 
+0

Est-ce que quelque chose de similaire peut être fait directement avec les fichiers .groovy? (c'est-à-dire sans les compiler en premier) – hithwen

0

Je vais avoir le même problème en essayant de automatiser les scripts Gant en cours d'exécution. La solution que je trouve est:

  1. copie-starter.conf Gant (ou groovy-starter.conf si elle est juste groovy) à partir de $ GROOVY_HOME/conf à votre propre dir;

  2. ajouter "charge [répertoire]" ou "charge [pot]" là, comme décrit dans javadocs à org.codehaus.groovy.tools.LoaderConfiguration, trouvé dans la distribution source Groovy;

  3. avant de commencer le système de jeu groovy.starter.conf.override groovy propriété au nom de ce fichier, comme -Dgroovy.starter.conf.override = [nom]

2

Le même chose que @James peut être fait sans utiliser de réflexion, en chargeant tous les fichiers jar d'un certain dossier:

URLClassLoader classLoader = new URLClassLoader(getExtraJarUrls(), getClass().getClassLoader()); 
GroovyShell shell = new GroovyShell(classLoader, binding, compilerConfiguration); 


private URL[] getExtraJarUrls() throws MalformedURLException 
{ 
    logger.debug("Loading extra jars from {}", EXTRA_JARS_DIR.getAbsolutePath()); 
    URL[] result; 
    File[] files = EXTRA_JARS_DIR.listFiles(new JarFilenameFilter()); 
    if (files != null) 
    { 
     List<URL> urls = new ArrayList<URL>(files.length); 
     for (File file : files) 
     { 
      urls.add(file.toURI().toURL()); 
     } 
     result = urls.toArray(new URL[urls.size()]); 
    } 
    else 
    { 
     result = new URL[0]; 
    } 
    logger.debug("Adding URLs to classloader: {}", Arrays.toString(result)); 
    return result; 
} 

private static class JarFilenameFilter implements FilenameFilter 
{ 
    public boolean accept(File dir, String name) 
    { 
     return name.endsWith(".jar"); 
    } 
} 
Questions connexes