2012-06-01 4 views
4

В настоящее время я создаю систему, которая позволит пользователю скомпилировать один или несколько проектов. Я занимался некоторыми исследованиями и решил использовать JavaCompilerAPI для этого. Я играю с ним, и мне удалось собрать отдельные java-файлы и составить список отдельных java-файлов.Использование JavaFileManager для компиляции проектов

Что я не могу сделать, это получить один проект java, не говоря уже о группе из них. Я где-то читал, что вы можете использовать JavaFileManager для этого, и я немного прочитал об этом, но я не могу найти никаких примеров этого, поэтому я застрял.

Это то, что я сделал до сих пор:

public List doCompilation(String sourceCode, String locationOfFile) { 
    List<String> compile = new ArrayList<>(); 

    SimpleJavaFileObject fileObject = new DynamicJavaSourceCodeObject(locationOfFile, sourceCode); 
    JavaFileObject javaFileObjects[] = new JavaFileObject[]{fileObject}; 

    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 

    StandardJavaFileManager stdFileManager = compiler.getStandardFileManager(null, Locale.getDefault(), null); 

    Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(javaFileObjects); 

    String[] compileOptions = new String[]{"-d", "C:/projects/Compiler/TempBINfolder/bin"}; 
    Iterable<String> compilationOptions = Arrays.asList(compileOptions); 

    DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>(); 

    CompilationTask compilerTask = compiler.getTask(null, stdFileManager, diagnostics, compilationOptions, null, compilationUnits); 

    boolean status = compilerTask.call(); 

    if (!status) {//If compilation error occurs 
     // Iterate through each compilation problem and print it 
     for (Diagnostic diagnostic : diagnostics.getDiagnostics()) { 
      compile.add(diagnostic.getKind().toString()+" on line "+ diagnostic.getLineNumber() +"\nIn file: \n"+ diagnostic.toString()+"\n\n"); 
     } 
    } 
    try { 
     stdFileManager.close();//Close the file manager 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

    return compile; 
} 

Кто-нибудь знает, как это сделать?

+0

Что вы подразумеваете под "java project"? Как это отличается от набора java-файлов (каждый из которых можно скомпилировать отдельно)? Какие проблемы вы испытываете при попытке скомпилировать «проект»? – Attila

+0

хорошо, когда я говорю java-проект, я имею в виду набор java-файлов в определенном каталоге. i no i я могу скомпилировать их индивидуально, но способ, которым я располагаю в данный момент, - это все файлы в JList, и пользователь может выбрать файл, который они хотят скомпилировать, что я хочу сделать, это добавить папки проекта (все java-файлы с папкой) в JTree, а затем скомпилировать отдельные проекты с использованием корневого узла проекта, например, вы можете скомпилировать полный проект в eclipse, щелкнув по проекту на экране пакета и скомпилировав затем компиляцию всех java-файлов в папка – newSpringer

+0

проблемы, с которыми я столкнулся, это то, что я получаю сообщение об ошибке «не могу найти символ» и указываю на класс, с которым вы используете метод, даже если файлы компилируются в eclipse и оператор import для класса, который вы используете используя метод from is is there there, он говорит, что я не могу найти класс – newSpringer

ответ

3
  • попробовать с помощью shrinkwrap, это очень простой в использовании ...
+0

Просто прочитайте здесь об усадке, кажется достаточно простым, чтобы использовать все в порядке. Предлагаете ли вы переместить все файлы для каждого проекта в новый «ShrinkWrap.create (JavaArchive.class,« archive.jar »)», а затем скомпилировать файлы jar, не так ли? – newSpringer

1

Вы могли бы перечислить файлы (и каталоги рекурсивно, если это необходимо) в указанной директории проекта и собрать их один за один как вы это делаете сейчас.

1

Вам необходимо включить выходной каталог в путь к компилятору. Обратите внимание, что я отношусь targetDirectory в пути к нижележащему пути:

/** 
* Compiles Java source-code. 
* <p/> 
* @author Gili Tzabari 
*/ 
public final class JavaCompiler 
{ 
    private List<Path> sourcePath = new ArrayList<>(); 
    private List<Path> classPath = new ArrayList<>(); 
    private final Set<DebugType> debugOptions = new HashSet<>(Arrays.asList(DebugType.LINES, 
     DebugType.SOURCE, DebugType.VARIABLES)); 

    /** 
    * Sets the compiler classpath. 
    * <p/> 
    * @param sourcePath the paths to search for the source format of dependent classes 
    * @throws NullPointerException if sourcePath is null 
    * @throws IllegalArgumentException if sourcePath refers to a non-existent path or a non-directory 
    * @return the JavaCompiler 
    */ 
    public JavaCompiler sourcePath(List<Path> sourcePath) 
    { 
     Preconditions.checkNotNull(sourcePath, "sourcePath may not be null"); 
     for (Path path: sourcePath) 
     { 
      if (!Files.exists(path)) 
      { 
       throw new IllegalArgumentException("sourcePath refers to non-existant path: " + path. 
        toAbsolutePath()); 
      } 
      if (!Files.isDirectory(path)) 
      { 
       throw new IllegalArgumentException("sourcePath refers to a non-directory: " + path. 
        toAbsolutePath()); 
      } 
     } 

     this.sourcePath = ImmutableList.copyOf(sourcePath); 
     return this; 
    } 

    /** 
    * Sets the compiler classpath. 
    * <p/> 
    * @param classPath the paths to search for the compiled format of dependent classes 
    * @throws NullPointerException if classPath is null 
    * @throws IllegalArgumentException if classPath refers to a non-existent path 
    * @return the JavaCompiler 
    */ 
    public JavaCompiler classPath(List<Path> classPath) 
    { 
     Preconditions.checkNotNull(classPath, "classPath may not be null"); 
     for (Path path: classPath) 
     { 
      if (!Files.exists(path)) 
      { 
       throw new IllegalArgumentException("classPath refers to non-existant path: " + path. 
        toAbsolutePath()); 
      } 
     } 

     this.classPath = ImmutableList.copyOf(classPath); 
     return this; 
    } 

    /** 
    * Indicates the kind of debugging information the generated files should contain. 
    * <p/> 
    * @param debugOptions the kind of debugging information the generated files should contain. By 
    * default all debugging information is generated. 
    * @return the JavaCompiler object 
    */ 
    public JavaCompiler debug(DebugType... debugOptions) 
    { 
     this.debugOptions.clear(); 
     this.debugOptions.addAll(Arrays.asList(debugOptions)); 
     return this; 
    } 

    /** 
    * Compiles the source code. 
    * <p/> 
    * @param sourceFiles the source files to compile 
    * @param targetDirectory the directory to compile into. This path included in the compiler 
    * classpath. 
    * @throws IllegalArgumentException if sourceFiles, targetDirectory are null; or if sourceFiles 
    * refers to a non-existent file or a non-file; or if targetDirectory is not a directory 
    * @throws CompilationException if the operation fails 
    */ 
    public void run(final Collection<Path> sourceFiles, final Path targetDirectory) 
     throws IllegalArgumentException, CompilationException 
    { 
     if (sourceFiles == null) 
      throw new IllegalArgumentException("sourceFiles may not be null"); 
     if (sourceFiles.isEmpty()) 
      return; 
     for (Path file: sourceFiles) 
     { 
      if (!Files.exists(file)) 
      { 
       throw new IllegalArgumentException("sourceFiles refers to a non-existant file: " 
        + file.toAbsolutePath()); 
      } 
      if (!Files.isRegularFile(file)) 
      { 
       throw new IllegalArgumentException("sourceFiles refers to a non-file: " 
        + file.toAbsolutePath()); 
      } 
     } 
     if (targetDirectory == null) 
      throw new IllegalArgumentException("targetDirectory may not be null"); 
     if (!Files.exists(targetDirectory)) 
     { 
      throw new IllegalArgumentException("targetDirectory must exist: " + targetDirectory. 
       toAbsolutePath()); 
     } 
     if (!Files.isDirectory(targetDirectory)) 
     { 
      throw new IllegalArgumentException("targetDirectory must be a directory: " + targetDirectory. 
       toAbsolutePath()); 
     } 
     Set<Path> uniqueSourceFiles = ImmutableSet.copyOf(sourceFiles); 
     Set<Path> uniqueSourcePath = ImmutableSet.copyOf(sourcePath); 
     final javax.tools.JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 
     if (compiler == null) 
     { 
      throw new AssertionError("javax.tools.JavaCompiler is not available. Is tools.jar missing " 
       + "from the classpath?"); 
     } 
     final DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>(); 
     final StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, 
      null); 

     Iterable<? extends JavaFileObject> compilationUnits; 
     try 
     { 
      Set<File> modifiedFiles = getModifiedFiles(uniqueSourceFiles, uniqueSourcePath, 
       targetDirectory, new HashSet<Path>()); 
      if (modifiedFiles.isEmpty()) 
       return; 
      compilationUnits = fileManager.getJavaFileObjectsFromFiles(modifiedFiles); 
     } 
     catch (IOException e) 
     { 
      throw new CompilationException(e); 
     } 
     final List<Path> effectiveClasspath = new ArrayList<>(); 
     effectiveClasspath.add(targetDirectory); 
     effectiveClasspath.addAll(classPath); 
     final List<String> options = new ArrayList<>(); 
     options.add("-cp"); 
     options.add(Joiner.on(File.pathSeparatorChar).join(effectiveClasspath)); 

     final StringBuilder debugLine = new StringBuilder("-g:"); 
     for (DebugType type: debugOptions) 
     { 
      switch (type) 
      { 
       case LINES: 
       { 
        debugLine.append("lines,"); 
        break; 
       } 
       case SOURCE: 
       { 
        debugLine.append("source,"); 
        break; 
       } 
       case VARIABLES: 
       { 
        debugLine.append("vars,"); 
        break; 
       } 
       default: 
        throw new AssertionError(type); 
      } 
     } 
     if (!debugOptions.isEmpty()) 
     { 
      debugLine.deleteCharAt(debugLine.length() - ",".length()); 
      options.add(debugLine.toString()); 
     } 

     if (!uniqueSourcePath.isEmpty()) 
     { 
      options.add("-sourcepath"); 
      options.add(Joiner.on(File.pathSeparatorChar).join(uniqueSourcePath)); 
     } 
     options.add("-s"); 
     options.add(targetDirectory.toString()); 
     options.add("-d"); 
     options.add(targetDirectory.toString()); 
     final Writer output = null; 
     final CompilationTask task = compiler.getTask(output, fileManager, diagnostics, options, null, 
      compilationUnits); 
     final boolean result = task.call(); 
     try 
     { 
      printDiagnostics(diagnostics, options, sourceFiles); 
     } 
     catch (IOException e) 
     { 
      throw new BuildException(e); 
     } 
     if (!result) 
      throw new CompilationException(); 
     try 
     { 
      fileManager.close(); 
     } 
     catch (IOException e) 
     { 
      throw new BuildException(e); 
     } 
    } 

    /** 
    * Returns the java source-code file corresponding to a class name. 
    * <p/> 
    * @param className the fully-qualified class name to look up 
    * @param sourcePath the source-code search path 
    * @return null if no match was found 
    */ 
    private static File getJavaSource(String className, Set<File> sourcePath) 
    { 
     // TODO: check for class files instead of source 
     for (File path: sourcePath) 
     { 
      File result = classNameToFile(path, className); 
      if (!result.exists()) 
       continue; 
      return result; 
     } 
     return null; 
    } 

    /** 
    * Converts a class name to its source-code file. 
    * <p/> 
    * @param sourcePath the source-code search path 
    * @param className the fully-qualified class name 
    * @return the source-code file 
    */ 
    private static File classNameToFile(File sourcePath, String className) 
    { 
     return new File(sourcePath, className.replace(".", "/") + ".java"); 
    } 

    /** 
    * Displays any compilation errors. 
    * <p/> 
    * @param diagnostics the compiler diagnostics 
    * @param options the command-line options passed to the compiler 
    * @param sourceFiles the source files to compile 
    * @throws IOException if an I/O error occurs 
    */ 
    private void printDiagnostics(final DiagnosticCollector<JavaFileObject> diagnostics, 
     final List<String> options, final Collection<Path> sourceFiles) throws IOException 
    { 
     Logger log = LoggerFactory.getLogger(JavaCompiler.class.getName() + ".stderr"); 
     int errors = 0; 
     int warnings = 0; 
     boolean firstTime = true; 
     for (Diagnostic<? extends JavaFileObject> diagnostic: diagnostics.getDiagnostics()) 
     { 
      if (firstTime) 
      { 
       firstTime = false; 
       StringBuilder message = new StringBuilder(); 
       message.append("Invoking: javac "); 
       for (String token: options) 
        message.append(token).append(" "); 
       message.append(Joiner.on(" ").join(sourceFiles)); 
       log.debug(message.toString()); 
      } 
      JavaFileObject source = diagnostic.getSource(); 
      if (source == null) 
       log.error(diagnostic.getMessage(null)); 
      else 
      { 
       StringBuilder message = new StringBuilder(); 
       message.append(source.getName()); 
       if (diagnostic.getLineNumber() != Diagnostic.NOPOS) 
        message.append(":").append(diagnostic.getLineNumber()); 
       message.append(": ").append(diagnostic.getMessage(null)); 
       log.error(message.toString()); 
       try (BufferedReader reader = 
         new BufferedReader(new InputStreamReader(source.openInputStream()))) 
       { 
        String line = null; 
        for (long lineNumber = 0, size = diagnostic.getLineNumber(); lineNumber < size; 
         ++lineNumber) 
        { 
         line = reader.readLine(); 
         if (line == null) 
          break; 
        } 
        if (line != null) 
        { 
         log.error(line); 
         message = new StringBuilder(); 
         for (long i = 1, size = diagnostic.getColumnNumber(); i < size; ++i) 
          message.append(" "); 
         message.append("^"); 
         log.error(message.toString()); 
        } 
       } 
      } 
      switch (diagnostic.getKind()) 
      { 
       case ERROR: 
       { 
        ++errors; 
        break; 
       } 
       case NOTE: 
       case OTHER: 
       case WARNING: 
       case MANDATORY_WARNING: 
       { 
        ++warnings; 
        break; 
       } 
       default: 
        throw new AssertionError(diagnostic.getKind()); 
      } 
     } 
     if (errors > 0) 
     { 
      StringBuilder message = new StringBuilder(); 
      message.append(errors).append(" error"); 
      if (errors > 1) 
       message.append("s"); 
      log.error(message.toString()); 
     } 
     if (warnings > 0) 
     { 
      StringBuilder message = new StringBuilder(); 
      message.append(warnings).append(" warning"); 
      if (warnings > 1) 
       message.append("s"); 
      log.warn(message.toString()); 
     } 
    } 

    /** 
    * Returns the source-code files that have been modified. 
    * <p/> 
    * @param sourceFiles the source files to process 
    * @param sourcePath the source file search path 
    * @param targetDirectory the directory to compile into 
    * @param unmodifiedFiles files that are known not to have been modified 
    * @return all changed source-code files that are accepted by the filter 
    * @throws IOException if an I/O error occurs 
    */ 
    private Set<File> getModifiedFiles(final Set<Path> sourceFiles, 
     final Set<Path> sourcePath, final Path targetDirectory, final Set<Path> unmodifiedFiles) 
     throws IOException 
    { 
     // TODO: Right now all files are assumed to have been modified 
     Set<File> result = new HashSet<>(); 
     for (Path path: sourceFiles) 
      result.add(path.toFile()); 
     return result; 
    } 

    /** 
    * Returns the command-line representation of the object. 
    * <p/> 
    * @param sourceFiles the source files to compile 
    * @param targetDirectory the directory to compile into 
    * @param sourcePath the source file search path 
    * @return the command-line representation of the object 
    * @throws IllegalArgumentException if the classpath contains non-file components 
    * @throws IOException if an I/O error occurs 
    */ 
    private List<String> toCommandLine(final Collection<Path> sourceFiles, final Path targetDirectory, 
     final Collection<Path> sourcePath) 
     throws IOException 
    { 
     final List<String> result = Lists.newArrayList("javac"); 
     if (!classPath.isEmpty()) 
     { 
      result.add("-cp"); 
      try 
      { 
       final StringBuilder line = new StringBuilder(); 
       for (final Iterator<Path> i = classPath.iterator(); i.hasNext();) 
       { 
        line.append(i.next().getParent().toString()); 
        if (i.hasNext()) 
         line.append(File.pathSeparatorChar); 
       } 
       result.add(line.toString()); 
      } 
      catch (IllegalArgumentException e) 
      { 
       // Occurs if URL does not refer to a file 
       throw new IllegalStateException(e); 
      } 
     } 
     for (File javaFile: getModifiedFiles(ImmutableSet.copyOf(sourceFiles), 
      ImmutableSet.copyOf(sourcePath), targetDirectory, new HashSet<Path>())) 
     { 
      result.add(javaFile.getPath()); 
     } 
     result.add("-d"); 
     result.add(targetDirectory.getParent().toString()); 
     return result; 
    } 

    @Override 
    public String toString() 
    { 
     return getClass().getName() + "[classPath=" + classPath + "]"; 
    } 

    /** 
    * The type of debugging information that generated files may contain. 
    * <p/> 
    * @author Gili Tzabari 
    */ 
    @SuppressWarnings("PublicInnerClass") 
    public enum DebugType 
    { 
     /** 
     * No debugging information. 
     */ 
     NONE, 
     /** 
     * Line number information. 
     */ 
     LINES, 
     /** 
     * Local variable information. 
     */ 
     VARIABLES, 
     /** 
     * Source file information. 
     */ 
     SOURCE 
    } 
} 
+0

Можете ли вы мне помочь с путём классов: https://stackoverflow.com/questions/32945379/programmatically-compile-java-files-and-include-other-jars-to-classpath – Gobliins