2012-05-26 18 views
10

Deseo compilar fuente sin tener las dependencias presentes en la máquina.
Ejemplo: Archivo A.java:
JavaCompiler con ClassLoader y FileManager personalizados

import some.pkg.B; 
public class A extends B {...} 

no tengo la fuente B presente, deseo de conectar ya sea JavaFileManager o un cargador de clases personalizada con el fin de obtener los símbolos en cuestión (el paquete 'algunos. paquete 'y clase B) y luego use un servicio que tengo que recupera la cadena fuente.

El código de compilación: (inputFiles tiene A.java)

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 
CustomClassLoader classLoader = new CustomClassLoader(); 
StandardJavaFileManager standardfileManager = compiler.getStandardFileManager(this, null, null); 
JavaFileManager fileManager = new CustomFileManager(standardfileManager, output, classLoader); 
CompilationTask task = compiler.getTask(null, fileManager, this, null, null, inputFiles); 
boolean result = task.call(); 

Los ganchos en JavaFileManager (getFileForInput ..) y en mi cargador de clases (FindClass, loadClass ..) no se activan al compilar y yo tiene mensajes de error:

A.java:#: package some.pkg does not exist 
A.java:#: cannot find symbol 
symbol: class B 

EDIT

Después de jugar un poco con el API, repasando JavaCompiler (versión antigua) s piénsalo y lee Compilation Overview Aún no puedo encontrar un enlace API que pueda usar para proporcionarme Símbolos de los árboles de sintaxis. Parece que la API necesita obtener todos los recursos en función de los nombres de los paquetes sugeridos por kschneid.
Una solución temporal en la que pensé es ejecutar JavaCompiler y analizar los mensajes de error en busca de símbolos faltantes. De esa manera sabré qué símbolos son necesarios, consíguelos y recompile.
¿Alguna otra solución alternativa?

+0

Qué versión de JDK/compilador y la plataforma está usando? – matts

+0

JavaCompiler (javac), JDK 1.6.30 x64 en Windows. –

+0

No estoy del todo seguro. Pero, siento como si lo que intentas hacer es una carga dinámica de clases. ¿No puedes usar 'Class.forname()' para cargar la clase en tiempo de ejecución. Por favor corrígeme si malentendí. – Ankit

Respuesta

4

(supongo que en realidad no estás utilizando un nombre de paquete de "paquete", ya que eso sería ilegal ...)

Su encargo JavaFileManager debería estar recibiendo su método list invocado. Con suerte esta notación tiene sentido, pero la combinación de argumentos a ese método debe tener este aspecto:

[PLATFORM_CLASS_PATH, some, [CLASS], false] 
[CLASS_PATH, some, [SOURCE, CLASS], false] 
[PLATFORM_CLASS_PATH, some.pkg, [CLASS], false] 
[CLASS_PATH, some.pkg, [SOURCE, CLASS], false] 

No estoy seguro de lo difícil que será para su entorno específico para crear las instancias apropiadas Iterable<JavaFileObject>, pero creo eso es lo que se requeriría ...

+0

Gracias por la nota del paquete, he revisado la pregunta. –

+0

Me he perdido esta función, buena llamada.Es una buena ruta, sin embargo, no quiero compilar JavaFileObject para todas las clases del paquete, solo las que se usan en la compilación real del archivo Java que estoy tratando de compilar. ¿Hay alguna manera de obtener los nombres de las clases reales y no solo los paquetes? –

+0

Aquí hay una gran implementación para esto. http://atamur.blogspot.kr/2009/10/using-built-in-javacompiler-with-custom.html – zeodtr

1

He encontrado que una buena forma de enganchar las clases en tiempo de compilación es con Groovy AST Transformation. Puede echar un vistazo a lo que puede hacerse here

Ese no es el viejo y simple de Java sin embargo, pero puede ser una herramienta muy útil para saber

Cuestiones relacionadas