0

Ich arbeite an einer Tomcat WebApp für meine Universität, die Studenten ihre Java-Codes kompilieren und die Spur sehen können. Ich installiere es auf einer RHEL7 VM. Aber wenn ich die Kompilation Funktion zu testen (dieses wird von mir nicht implementiert), die Methode, die ich bin Bereitstellung gibt diese:Java Compiler sagt immer "Fehler beim Schreiben className: className.class (Berechtigung verweigert)"

error while writing className: className.class (Permission denied) 
Error on line 1 in className.java 

Ich zeige Ihnen die Methode, die ich denke, generiert dies:

public String compileJavaCode(String javaCode, String javaFileName, File workingDir) throws IOException, TimeoutException{ 

    javax.tools.JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 
    DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>(); 
    StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null); 
    this.createJavaFile(javaCode, javaFileName, workingDir); 
    JavaFileObject file = new JavaSourceFromString(javaFileName, javaCode); 

    Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(file); 
    compiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits).call(); 

    String diagn = ""; 
    for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()){ 
     diagn+=diagnostic.getMessage(null)+"\n";//E.g. cannot find symbol symbol: variable variablename 
     diagn+="Error on line "+Long.toString(diagnostic.getLineNumber())+" in "+diagnostic.getSource().toUri();//E.g. Error on line 22 in ClassName.java 
    } 
     fileManager.close(); 
     compiler.run(null, null, null, workingDir.getAbsolutePath()+File.separator+javaFileName); 
     return diagn; 
} 

Die Schüler sehen den Inhalt dieser diagn Variable als Ergebnis für ihre Code-Einreichung.

Fun Tatsache ist, dass ich es schaffen, die className.class in der workingDir Verzeichnis zu bekommen, aber ich bekomme diesen Fehler aus dem for Zyklus oben. Könnte das Problem compiler.getTask(...).call() sein? Ich meine vielleicht compiler.run ist in der Lage, die .class korrekt zu generieren, aber die compiler.getTask(...).call() versucht, die .class woanders zu schreiben, ich habe keine Berechtigung zum Schreiben.

P.S. Dies ist ein hübscher Legacy-Code, also sei bitte gnädig damit. :)

Wie @Alexander gefragt, dann ist dies der Inhalt der Java-Datei:

public class Sommatore { 

    public int somma(int i, int j) { 
     return i+j; 
    } 

    public int differenza(int i, int j) { 
     return i-j; 
    } 
} 
+0

Zu wenig Informationen zu schreiben. Was ist der Inhalt der Datei 'className.java'? Wenn Sie es in die IDE laden, zeigt es irgendwelche Fehler? Warum liesst du es nicht über 'fileManager.getJavaFileObjectsFromFiles()' zurück und was passiert, wenn du dies anstelle von 'JavaSourceFromString()' probierst? – Alexander

+0

Auch: erhalten Sie irgendeine Ausgabe von 'compiler.run()'? Bitte überprüfen Sie die Protokolle. – Alexander

+0

Soll es nicht ein gültiger Java-Quellcode sein? Ich würde mindestens erwarten 'Klasse Etwas {}' – Alexander

Antwort

0

Scheint, wie der Benutzer, den Sie verwenden, um den Zielordner nicht über die Berechtigungen zu schreiben. Welche Berechtigungen hat das WorkingDir?

Spaß Tatsache ist, dass ich es geschafft habe, die ClassName.class in das Verzeichnis workingDir zu bekommen, aber ich bekomme diesen Fehler von der oben für Zyklus. Könnte das Problem der compiler.getTask (...) sein. Call()? Ich meine, vielleicht ist compiler.run in der Lage, die .class korrekt zu generieren, aber die compiler.getTask (...). Call() versucht, die .class woanders zu schreiben, ich habe keine Berechtigung zum Schreiben.

Um zu überprüfen, ob dies zutrifft, könnten Sie einen Ordner mit offenen Berechtigungen erstellen und versuchen. Zum Beispiel könnten Sie versuchen, als workingDir =/tmp verwenden und überprüfen, was passiert.

EDIT

Ich habe versucht, den Code zu replizieren:

public class JavaCompiler { 
    public static void main(String args[]) throws IOException, TimeoutException { 
     File dir = new File(System.getProperty("user.dir") + "/src/main/java/"); 
     System.out.println(compileJavaCode(dir)); 
    } 
    public static String compileJavaCode(File workingDir) throws IOException,  TimeoutException { 

     javax.tools.JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 
     DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>(); 
     StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null); 
     // this.createJavaFile(javaCode, javaFileName, workingDir); 
     // JavaFileObject file = new JavaSourceFromString(javaFileName, javaCode); 

     Iterable<? extends JavaFileObject> compilationUnits = fileManager 
       .getJavaFileObjectsFromStrings(Arrays.asList(System.getProperty("user.dir") + "/src/main/java/Foo.java")); 
// Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(file); 
     compiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits).call(); 

     String diagn = ""; 
     for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) { 
      diagn += diagnostic.getMessage(null) + "\n";//E.g. cannot find symbol symbol: variable variablename 
      diagn += "Error on line " + Long.toString(diagnostic.getLineNumber()) + " in " + diagnostic.getSource().toUri();//E.g. Error on line 22 in ClassName.java 
     } 
     fileManager.close(); 
     compiler.run(null, null, null, workingDir.getAbsolutePath() + File.separator + "Foo.java"); 
     return diagn; 
    } 
} 

mit Foo.java

public class Foo { 

    public int somma(int i, int j) { 
     return i+j; 
    } 

    public int differenza(int i, int j) { 
     return i-j; 
    } 
} 

Es gibt einige Änderungen, aber das Ergebnis sollte gleich sein . bemerkte ich, dass der "Weg" in

File workingDir 

angegeben ist, dass die Verwendung in

compiler.run(null, null, null, workingDir.getAbsolutePath() + File.separator + "Foo.java"); 

und in

JavaFileObject file = new JavaSourceFromString(javaFileName, javaCode); 
Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(file); 

sein wird, dass in meinem Beispiel:

Iterable<? extends JavaFileObject> compilationUnits = fileManager 
.getJavaFileObjectsFromStrings(Arrays.asList(System.getProperty("user.dir") + "/src/main/java/Foo.java")); 

Was enthält Ihre s

workingDir 

und "Datei"?

JavaFileObject file = new JavaSourceFromString(javaFileName, javaCode); 

In meinem Fall, sind die gleichen.

Ich habe versucht, den Code mit verschiedenen Benutzern ausgeführt werden, und wenn ich einen Benutzer verwenden, die in diesem Ordner nicht in der Lage ist, ich erhalte bisher

/tmp/testSO/src/main/java/Foo.java:5: error: error while writing Foo: /tmp/testSO/src/main/java/Foo.class (Permission denied) 
public class Foo { 
    ^
1 error 
error while writing Foo: /tmp/testSO/src/main/java/Foo.class (Permission denied) 
Error on line 5 in file:/tmp/testSO/src/main/java/Foo.java 
+0

Danke für Ihre Antwort @DurdenP. Ich denke, das ist auch das Problem. Ich habe gelesen, dass compiler.gettask versucht, eine .class-Datei im Quellordner zu erstellen. Könnte das das schuldige Verzeichnis sein? Über das WorkingDir Ich endete mit dem Versuch mit 777 aber scheint nichts passiert ... –

+1

Ich löste die Angabe des Zielverzeichnisses mit dem "-d" -Parameter ti den Compiler. Danke Leute –

Verwandte Themen