package au.edu.mq.comp.junitGrading.webUI;
import static spark.Spark.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.UUID;
import com.oreilly.servlet.MultipartRequest;
import au.edu.mq.comp.common.*;
import au.edu.mq.comp.junitGrading.*;
import au.edu.mq.comp.junitGrading.commandLineUI.AutomarkCommandLineEntryPoint;
import au.edu.mq.comp.junitGrading.commandLineUI.JavaGraderDriver;
import spark.*;
import java.lang.StringBuilder;
import org.apache.commons.lang3.StringUtils;
public class AutomarkWebApplication extends Object
{
private int port;
private String workingDirPrefix;
public AutomarkWebApplication(int port, String workingDirPrefix)
{
this.port = port;
this.workingDirPrefix = new String(workingDirPrefix);
}
private String makeConfigFileForJavaGrader(MultipartRequest req, File workingDir)
{
StringBuilder configString = new StringBuilder();
//key setting value
String JUnitTestClassName = req.getParameter("JUnitTestClassName");
if(null != JUnitTestClassName)
{
configString.append("[" + JUnitTestClassName + "]\n");
}
else
{
System.out.println("There is no JUnitTestClassName provided");
}
Enumeration keys = req.getParameterNames();
while(keys.hasMoreElements())
{
String key = (String)keys.nextElement();
String value = req.getParameter(key);
if(null != value)
{
if(true == value.equalsIgnoreCase("on"))
value = "Yes";
configString.append(key + " = " + value + "\n");
}
}
// input files to process
Enumeration files = req.getFileNames();
while (files.hasMoreElements())
{
String name = (String)files.nextElement();
String filename = req.getFilesystemName(name);
//String type = req.getContentType(name);
if(null != filename)
configString.append(name + " = " + workingDir.getAbsolutePath() + File.separator + filename + "\n");
}
//output directory
File outputDir = new File(workingDir.getAbsolutePath() + File.separator + "output");
outputDir.mkdirs();
configString.append("outputDirectory = " + outputDir.getAbsolutePath() + "\n");
//timeout
configString.append("testProcessTimeOut = 15\n");
//Feedback directory
File feedbackDir = new File(workingDir.getAbsolutePath() + File.separator + "FeedBack");
feedbackDir.mkdirs();
return configString.toString();
}
private String createLinkToSubmissionFiles(java.util.List<Assignment> listOfAssignment, String CSVHTMLString, String jobID)
{
String[] key = new String[listOfAssignment.size()];
String[] value = new String[listOfAssignment.size()];
int idx = 0;
for(Assignment assignment : listOfAssignment)
{
String ownerName = assignment.ownerIdentification().name();
String linkString = HTMLUtils.HTMLLinkFromString(String.format("/ViewSubmission/:%s?name=%s", jobID, ownerName.replace(' ', '_')),
ownerName);
key[idx] = ownerName;
value[idx] = linkString;
idx++;
}
return StringUtils.replaceEach(CSVHTMLString, key, value);
}
public void run()
{
//org.apache.log4j.BasicConfigurator.configure();
Spark.setPort(this.port);
get(new Route("/Automark")
{
@Override
public Object handle(Request request, Response response)
{
try
{
String mainHTML = SimpleFileIO.readTextFromSelfJarBundleFile(this, GlobalSetting.programResourcePath() + "/WebUIHTML/main.html");
//String mainHTML = SimpleFileIO.readTextFromFile("/Users/psksvp/MyCode/junitGrading/Automark/src/Resources/WebUIHTML/main.html");
response.header("content-type", "text/html");
return StringUtils.replace(mainHTML, "/**VERSION**/", AutomarkCommandLineEntryPoint.version());
}
catch (IOException e)
{
return "Fail to open file";
}
}
});
get(new Route("/CSVFile/:id")
{
@Override
public Object handle(Request request, Response response)
{
response.header("content-type", "text/plain");
String id = request.params(":id").substring(1);
File theCSVFile = new File(workingDirPrefix +
File.separator +"jobs" +
File.separator + id.toString() +
File.separator + "result.csv");
try
{
String csvString = SimpleFileIO.readTextFromFile(theCSVFile.getAbsolutePath());
return csvString;
}
catch(Exception e)
{
return "id -->" + id + "\n" + e.toString();
}
}
});
get(new Route("/FeedBackZip/:id")
{
@Override
public Object handle(Request request, Response response)
{
String id = request.params(":id").substring(1);
File theFeedbackZipFile = new File(workingDirPrefix +
File.separator +"jobs" +
File.separator + id.toString() +
File.separator + "FeedBack.zip");
try
{
response.header("Content-Disposition", "attachment; filename=\"FeedBack-" + id + ".zip\"");
response.header("content-type", "application/x-zip-compressed");
OutputStream os = response.raw().getOutputStream();
InputStream is = new FileInputStream(theFeedbackZipFile);
SimpleFileIO.copy(is, os);
return "";
}
catch(Exception e)
{
response.header("content-type", "text/plain");
return "id -->" + id + "\n" + e.toString();
}
}
});
get(new Route("/ViewSubmission/:id")
{
@Override
public Object handle(Request request, Response response)
{
String id = request.params(":id").substring(1);
try
{
String ownerName = request.queryParams("name");
File jobDir = new File(workingDirPrefix +
File.separator +"jobs" +
File.separator + id.toString() +
File.separator + "output");
File ownerFolder = SimpleFileIO.findADirecotryInDirectory(jobDir, ownerName);
String runResultTxt = SimpleFileIO.readTextFromFile(ownerFolder.getAbsolutePath() + File.separator + "runResult.txt");
java.util.List<File> listOfJavaFiles = SimpleFileIO.readListOfFileFromFile(ownerFolder.getAbsolutePath() + File.separator + "listOfJavaFiles.txt");
String HTMLOutput = SimpleFileIO.readTextFromSelfJarBundleFile(this, GlobalSetting.programResourcePath() + "/WebUIHTML/SubmissionView.html");
String[] sourceHTMLPair = HTMLUtils.HTMLFromListOfJavaSourceFile(listOfJavaFiles);
String[] keys = {"/**NAME**/", "/**RUNRESULT**/", "/**SOURCECODE**/", "/**SOURCEINDEX**/"};
String[] values = {ownerName.replace('_', ' '),
HTMLUtils.HTMLFromText(runResultTxt),
sourceHTMLPair[1],
sourceHTMLPair[0]};
response.header("content-type", "text/html");
return StringUtils.replaceEachRepeatedly(HTMLOutput, keys, values);
}
catch(Exception e)
{
response.header("content-type", "text/plain");
return "Job id ==>" + id + "is not exist\n" + "exception detail ==>" + e.toString();
}
}
});
get(new Route("/Recall/:id")
{
@Override
public Object handle(Request request, Response response)
{
String id = request.params(":id").substring(1);
try
{
File recallFile = new File(workingDirPrefix +
File.separator +"jobs" +
File.separator + id.toString() +
File.separator + "recall.html");
return SimpleFileIO.readTextFromFile(recallFile.getAbsolutePath());
}
catch(Exception e)
{
response.header("content-type", "text/plain");
return "Job id ==>" + id + "is not exist\n" + "exception detail ==>" + e.toString();
}
}
});
post(new Route("/run")
{
@Override
public Object handle(Request request, Response response)
{
UUID id = UUID.randomUUID();
File workingDir = new File(workingDirPrefix + File.separator +"jobs" + File.separator + id.toString());
if (!workingDir.exists() && !workingDir.mkdirs())
{
throw new RuntimeException("Failed to create directory " + workingDir.getAbsolutePath());
}
try
{
MultipartRequest req = new MultipartRequest(request.raw(), workingDir.getAbsolutePath(), Integer.MAX_VALUE);
String configString = makeConfigFileForJavaGrader(req, workingDir);
SimpleFileIO.writeStringToTextFile(configString, workingDir.getAbsolutePath() + File.separator + "config.txt");
//run automark
JavaGraderDriver agm = new JavaGraderDriver();
//javaGraderDriverMap.put(id.toString(), agm);
String CSVString = agm.run(new File(workingDir.getAbsolutePath() + File.separator + "config.txt"));
//writing output
//csv
SimpleFileIO.writeStringToTextFile(CSVString, workingDir.getAbsolutePath() + File.separator + "result.csv");
//zip feedback
File feedbackDir = new File(workingDir.getAbsolutePath() + File.separator + "FeedBack");
File feedbackZIP = new File(workingDir.getAbsolutePath() + File.separator + "FeedBack.zip");
SimpleFileIO.zipDirectory(feedbackDir, feedbackZIP);
// make html output
String CSVHTMLString = createLinkToSubmissionFiles(agm.listOfAssignment(),
HTMLUtils.HTMLFromCSVString(CSVString),
id.toString());
//String HTMLOutputString = SimpleFileIO.readTextFromFile("/Users/psksvp/MyCode/junitGrading/Automark/src/Resources/WebUIHTML/result.html");
String HTMLOutputString = SimpleFileIO.readTextFromSelfJarBundleFile(this, GlobalSetting.programResourcePath() + "/WebUIHTML/result.html");
String[] keyList = {"/**JOBID**/", "/**BODY**/", "/**CSVURL**/", "/**FEEDBACKZIPURL**/"};
String[] valueList = new String[4];
valueList[0] = id.toString();
valueList[1] = CSVHTMLString;
valueList[2] = "/CSVFile/:" + id.toString();
valueList[3] = "/FeedBackZip/:" + id.toString();
response.header("content-type", "text/html");
String recall = StringUtils.replaceEachRepeatedly(HTMLOutputString, keyList, valueList);
SimpleFileIO.writeStringToTextFile(recall, workingDir.getAbsolutePath() + File.separator + "recall.html");
return recall;
}
catch (Exception e)
{
response.header("content-type", "text/plain");
return "Fail with exception" + e.toString();
}
}
});
}
}