2017-10-19 33 views
0

J'écris un plugin Gradle pour générer un json-schema pour les beans dans mon projet. Mon objectif est d'avoir le schéma généré et publié dans le cadre du processus de construction, donc je n'ai pas besoin de le mettre à jour manuellement.Comment autoriser un greffon Gradle à accéder aux classes dans les dépendances de projet

Actuellement, je passe project.compileJava.inputs.files à ma tâche et l'utilise pour construire un URLClassLoader. Ensuite, je passe ces classes à un schema generator.

Afin de garantir que le schéma json est généré correctement, je souhaite utiliser le ObjectMapper à partir de l'application cible. Malheureusement, mon ObjectMapper ajoute le jackson Hibernate5Module. Dans les profondeurs de ce module, il essaie de vérifier si ma classe est assignable à un HibernateProxy, et puisque le HibernateProxy est chargé avec le chargeur de classe de Gradle et que ma classe est chargée du URLClassLoader tout explose.

Je pourrais supprimer le module Hibernate, mais cela laisse toujours le bug être déclenché dans d'autres situations similaires, et cela rend mon plugin moins distribuable. J'ai donc besoin d'un moyen d'ajouter de nouvelles entrées au classpath de gradle ou au chargeur de classe par défaut lors de l'exécution.

Pour référence, voici les extraits de code relevent:

build.gradle du projet cible

jsonSchema { 
    classpath = project.compileJava.inputs.files 
} 

WriteJsonSchema public class étend DefaultTask

@TaskAction 
public void write() throws ClassNotFoundException, IOException { 
    ObjectMapper mapper = new ObjectMapper(); 

    mapper.registerModule(new Hibernate5Module()); 
    mapper.registerModule(new Jdk8Module()); 
    mapper.registerModule(new JavaTimeModule()); 

    mapper.configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, false); 
    mapper.configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS, false); 

    Set<File> files = getClasspath().getFiles(); 
    List<URL> urls = new ArrayList<URL>(files.size()); 
    for(File file : files) 
    { 
     urls.add(file.toURI().toURL()); 
    } 
    URLClassLoader classLoader = new URLClassLoader(urls.toArray(new URL[0]), Thread.currentThread().getContextClassLoader()); 

    JsonSchemaGenerator jsonSchemaGenerator = new JsonSchemaGenerator(mapper); 
    JsonNode jsonSchema = 
     jsonSchemaGenerator.generateJsonSchema(classLoader.loadClass("com.example.Widget")); 
    System.out.println(mapper.writeValueAsString(jsonSchema)); 
    classLoader.close(); 
} 

TL; DR: J'ai besoin d'un moyen t o soit ajouter de nouvelles entrées au classpath de gradle, soit au loader de classe par défaut à l'exécution.

Répondre

0

Si quelqu'un s'en soucie, j'ai fini par obtenir le classpath du projet en inspectant les sorties des tâches compilejava.

classpath = getProject().files(); 
    getProject() 
     .getTasksByName("compileJava", true) 
     .forEach(task -> classpath = Classpath.plus(((JavaCompile)task).getClasspath())); 
classpath = Classpath.plus(getProject().getTasks().getByName("jar").getOutputs().getFiles());