Compilar código Java

Entre los conectores de JDT se incluye un compilador Java incremental y un compilador Java por lotes para construir archivos .class Java a partir del código fuente. El compilador no ofrece ninguna API directa. Se instala como constructor en los proyectos Java. La compilación se desencadena mediante los mecanismos de construcción estándar de la plataforma.

Los mecanismos de construcción de la plataforma se describen con detalle en el tema Constructores de proyectos incrementales.

Compilar el código

Los archivos fuente Java de un proyecto se pueden compilar programáticamente utilizando la API de construcción.

   IProject myProject;
IProgressMonitor myProgressMonitor;
myProject.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, myProgressMonitor);

Para un proyecto Java, esto invoca el constructor incremental de proyectos Java (junto con los otros constructores incrementales de proyectos que se hayan añadido a la especificación de construcción del proyecto). Los archivos .class generados se escriben en la carpeta de salida designada. Los archivos de recursos adicionales también se copian en la carpeta de salida.  

En el caso de una construcción por lotes completa, todos los archivos .class de la carpeta de salida pueden quedar eliminados para asegurar que no se encuentran archivos obsoletos. Esto se controla mediante una opción del constructor núcleo de JDT (CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER). El valor por omisión de esta opción es hacer limpieza de las carpetas de salida. A menos que esta opción esté restablecida, debe asegurarse de que todos los archivos .class de los que no tenga sus correspondientes archivos fuente se colocan en una carpeta de archivo de clase aparte en la vía de acceso de clases, en vez de colocarlos en la carpeta de salida.

Los constructores incremental y por lotes se pueden configurar con otras opciones que controlan qué recursos se copian en la carpeta de salida. El siguiente ejemplo muestra cómo configurar un filtro de recursos para que los archivos que acaban en '.ignore' y las carpetas que se llaman 'META-INF' no se copien en la carpeta de salida: 

   Hashtable options = JavaCore.getOptions();
   options.put(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, "*.ignore,META-INF/");
   JavaCore.setOptions(options);

Los nombres de archivo se filtran si coinciden con uno de los patrones suministrados. Las carpetas enteras se filtran si su nombre coincide con uno de los nombres de carpeta suministrados que terminan en un separador de vía de acceso.

También pueden configurarse los constructores por lotes e incrementales para que solo generen un único error si el archivo .classpath contiene errores. Esta opción está establecida por omisión y elimina numerosos errores. En el tema Opciones de constructor de núcleo de herramientas de desarrollo Java (JDT) hallará una lista completa de las opciones relacionadas con los constructores y de sus valores por omisión.

El compilador también se puede configurar mediante opciones de JavaCore. Por ejemplo, puede definir la gravedad que debe utilizarse para los distintos tipos de problemas que se producen durante la compilación. En el tema Opciones de compilador de núcleo de herramientas de desarrollo Java (JDT) hallará una lista completa de las opciones relacionadas con el compilador y de sus valores por omisión.

Si configura programáticamente opciones para el constructor o el compilador, debe determinar el ámbito de la opción. Por ejemplo, la configuración de un filtro de recursos puede atañer solamente a un determinado proyecto. En el siguiente ejemplo se configura el mismo filtro de recursos que se mostraba anteriormente, pero tan solo atañe al proyecto individual.

   
   Hashtable options = myProject.getOptions(false);
// obtener tan solo las opciones configuradas en este proyecto
   options.put(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, "*.ignore,META-INF/");
   myProject.setOptions(options);

Utilizar el adaptador javac de Ant

El compilador Eclipse se puede utilizar dentro de un script Ant mediante el adaptador javac. Para poder utilizar el compilador Eclipse, basta con que solo defina la propiedad build.compiler en el script. A continuación se ofrece un pequeño ejemplo.
<?xml version="1.0" encoding="UTF-8" ?>
<project name="compile" default="main" basedir="../.">

	<property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>

	<property name="root" value="${basedir}/src"/>

	<property name="destdir" value="d:/temp/bin" />

	<target name="main">
		<javac srcdir="${root}" destdir="${destdir}" debug="on" nowarn="on" extdirs="d:/extdirs" source="1.4">
		    <classpath>
		      <pathelement location="${basedir}/../org.eclipse.jdt.core/bin"/>
		    </classpath>
		</javac>		
	</target>
</project>
La sintaxis utilizada para la tarea javac de Ant se encuentra en la documentación de las tareas javac de Ant. El adaptador actual da soporte a la tarea javac de Ant 1.4.1. Cuando se suministre Ant 1.5, estará disponible la versión 1.5.

Determinación de problemas

El núcleo de JDT define un marcador especializado (marcador de tipo "org.eclipse.jdt.core.problem") para señalar los problemas de compilación. Para descubrir programáticamente los problemas detectados por el compilador, debe utilizarse el protocolo estándar de marcadores de la plataforma. En el tema Marcadores de recursos hallará una visión general sobre cómo utilizar los marcadores.

El fragmento de código siguiente busca todos los marcadores de problemas Java de una unidad de compilación.

   public IMarker[] findJavaProblemMarkers(ICompilationUnit cu)
      throws CoreException {
      IResource javaSourceFile = cu.getUnderlyingResource();
      IMarker[] markers =
         javaSourceFile.findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER,
            true, IResource.DEPTH_INFINITE);
   }

El constructor de proyectos Java es el encargado del mantenimiento de los marcadores de problemas Java, y estos quedarán automáticamente eliminados en cuanto se solucionen los problemas y se recompile el código Java.

Una de las constantes de IProblem establece el valor del ID del problema. El ID del problema es fiable, pero el mensaje se traduce y, por lo tanto, puede cambiar según el entorno local por omisión. Las constantes definidas en IProblem son autodescriptivas.

Debe definirse una implementación de IProblemRequestor para recoger los problemas descubiertos durante una operación Java. Las copias de trabajo se pueden reconciliar con la detección de problemas si se ha suministrado una interfaz IProblemRequestor para la creación de copias de trabajo. Para ello, puede utilizar el método reconcile. A continuación se ofrece un ejemplo:

  ICompilationUnit unit = ..; // obtener una unidad de compilación
			
  // crear peticionario para acumular problemas descubiertos
  IProblemRequestor problemRequestor = new IProblemRequestor() {
    public void acceptProblem(IProblem problem) {
      System.out.println(problem.getID() + ": " + problem.getMessage());
    }
    public void beginReporting() {}
    public void endReporting() {}
    public boolean isActive() {	return true; } // detectará problemas si está activo
  };
    
  // utilizar copia de trabajo para guardar el fuente con error
  IWorkingCopy workingCopy = (IWorkingCopy)unit.getWorkingCopy(null, null, problemRequestor);
  ((IOpenable)workingCopy).getBuffer().setContents("public class X extends Zork {}");

  // desencadenar la reconciliación
  workingCopy.reconcile(true, null);
En el método acceptProblem(IProblem), puede añadir una acción en los problemas notificados. En este ejemplo, el problema notificado será que Zork no puede resolverse o no es una superclase válida y su ID es IProblem.SuperclassNotFound.

Copyright IBM Corporation y otras empresas 2000, 2003. Reservados todos los derechos.