/*
* JavaCompiler.java
*
* Copyright (C) 2015 Pixelgaffer
*
* This work is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2 of the License, or any later
* version.
*
* This work is distributed in the hope that it will be useful, but without
* any warranty; without even the implied warranty of merchantability or
* fitness for a particular purpose. See version 2 and version 3 of the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.pixelgaffer.turnierserver.compile;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Properties;
import java.util.regex.Pattern;
import org.apache.commons.io.FileUtils;
import org.pixelgaffer.turnierserver.compile.LibraryDownloader.LibraryDownloaderMode;
import org.pixelgaffer.turnierserver.networking.DatastoreFtpClient;
public class JavaCompiler extends Compiler
{
public JavaCompiler (int ai, int version, int game)
{
super(ai, version, game);
}
@Override
public String getLanguage ()
{
return "Java";
}
@Override
public boolean compile (File srcdir, File bindir, Properties p, PrintWriter output, LibraryDownloader libs)
throws IOException, InterruptedException
{
String classpath = ".";
// die AiLibrary laden
output.print("> Lade Ai Bibliothek herunter ... ");
output.flush();
File libdir = new File(bindir, "AiLibrary");
libdir.mkdir();
try
{
if (libs == null || libs.getMode() == LibraryDownloaderMode.LIBS_ONLY)
DatastoreFtpClient.retrieveAiLibrary(getGame(), "Java", libdir);
else
{
for (File f : libs.getAiLibs("Java"))
FileUtils.copyFile(f, new File(libdir, f.getName()));
}
for (String jar : libdir.list( (dir, name) -> name.endsWith(".jar")))
classpath += File.pathSeparator + "AiLibrary" + File.separator + jar;
output.println("done");
}
catch (Exception e)
{
libdir.delete();
output.println(e);
return false;
}
// die benötigten Libraries lesen
BufferedReader libraries = new BufferedReader(new FileReader(new File(srcdir, "libraries.txt")));
String line;
while ((line = libraries.readLine()) != null)
{
line = line.trim();
if ((line.length() == 0) || line.startsWith("#"))
continue;
String libdirname = line.replace('/', '_');
output.print("> Lade Bibliothek " + line + " herunter ... ");
output.flush();
libdir = new File(bindir, libdirname);
libdir.mkdir();
getLibs().add(new RequiredLibrary(line, libdirname));
try
{
if (libs == null)
DatastoreFtpClient.retrieveLibrary(line, "Java", libdir);
else
{
for (File f : libs.getLib("Java", line))
FileUtils.copyFile(f, new File(libdir, f.getName()));
}
for (String jar : libdir.list( (dir, name) -> name.endsWith(".jar")))
classpath += ":" + libdirname + File.separator + jar;
output.println("done");
}
catch (Exception e)
{
libdir.delete();
output.println(e.getMessage());
}
}
libraries.close();
// die Klassen kompilieren
if (!compileRecursive(srcdir, classpath, srcdir, bindir, output))
return false;
// die argumente für den java befehl speichern
String mainclass = p.getProperty("mainclass");
if (!Pattern.matches("[a-zA-Z0-9_\\.]+", mainclass))
{
output.println(mainclass + " ist keine valide Klasse");
return false;
}
if (mainclass == null)
{
output.println("failed");
output.println("FEHLER: Die Hauptklasse wurde nicht in der settings.prop-Datei angegeben!");
output.println(" Bitte die Zeile");
output.println(" mainclass=com.example.Ai");
output.println(" der settings.prop hinzufügen!");
return false;
}
setCommand("java");
String args[] = { "-classpath", classpath, "-Xmx500M", mainclass };
setArguments(args);
return true;
}
protected boolean compileRecursive (File currentDir, String classpath, File srcdir, File bindir, PrintWriter output)
throws IOException, InterruptedException
{
for (String filename : currentDir.list())
{
File file = new File(currentDir, filename);
if (file.isDirectory())
{
if (!compileRecursive(file, classpath, srcdir, bindir, output))
return false;
continue;
}
// die Datei ins bindir kopieren
String relative = relativePath(file, srcdir);
copy(file, new File(bindir, relative));
// .java-Dateien kompilieren
if (filename.endsWith(".java"))
{
int returncode = execute(bindir, output, "javac", "-classpath", classpath, "-implicit:none", "-encoding", "utf8", relative);
if (returncode != 0)
{
output.println("Process finished with exit code " + returncode + ", aborting");
return false;
}
// ich brauch die source nicht mehr
new File(bindir, relative).delete();
}
}
return true;
}
}