/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package murban.exerciser.api.controllers;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.Produces;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.xml.parsers.ParserConfigurationException;
import murban.exerciser.api.dao.TokenFacade;
import murban.exerciser.api.models.Token;
import murban.exerciser.helpers.FileHelper;
import murban.exerciser.parser.model.StudentResults;
import murban.exerciser.parser.xml.AntXmlParser;
import murban.exerciser.runner.AntRunner;
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.xml.sax.SAXException;
/**
* REST Web Service
*
* @author PSYcho
*/
@Path("solutions")
@Produces("application/json")
public class SolutionsController {
@Context
private UriInfo context;
@EJB
private TokenFacade tokenFacade;
public SolutionsController() {
}
@GET
@Path("/antversion")
public Response getAntVersion() throws IOException, InterruptedException {
return Response.status(Response.Status.OK).entity(AntRunner.antVersion()).build();
}
@GET
@Path("/reports/{exercise}")
public Response getReports(@PathParam("exercise") String exercise, @HeaderParam("Authorization") String token) {
if (token == null) {
return Response.status(Response.Status.UNAUTHORIZED).build();
}
Token userToken = tokenFacade.validateToken(token);
if (userToken == null) {
return Response.status(Response.Status.FORBIDDEN).build();
}
String userid = userToken.getUserid();
List<File> reports = AntRunner.getTestsReports(exercise, userid);
File buildXml = AntRunner.getBuildXml(exercise, userid);
if (reports.isEmpty() && !buildXml.exists() ) {
return Response.status(Response.Status.NOT_FOUND).entity("Reports not found").build();
}
try {
AntXmlParser antXmlParser = new AntXmlParser();
StudentResults studentResults = antXmlParser.parseStudentResults(buildXml, reports);
return Response.status(Response.Status.OK).entity(studentResults).build();
} catch (IOException | ParserConfigurationException | SAXException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
}
@POST
@Path("/upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(FormDataMultiPart formData, @HeaderParam("Authorization") String token) {
if (token == null) {
return Response.status(Response.Status.UNAUTHORIZED).build();
}
Token userToken = tokenFacade.validateToken(token);
if (userToken == null) {
return Response.status(Response.Status.FORBIDDEN).build();
}
String studentName = userToken.getUserid();
if (formData == null) {
return Response.status(Response.Status.BAD_REQUEST).entity("Form data [file, exercise] required").build();
}
if (formData.getFields("file") == null) {
return Response.status(Response.Status.BAD_REQUEST).entity("Files required").build();
}
if (formData.getFields("exercise") == null) {
return Response.status(Response.Status.BAD_REQUEST).entity("Exercise name required").build();
}
String exerciseName = formData.getField("exercise").getValue();
if (!AntRunner.isExercise(exerciseName)) {
return Response.status(Response.Status.BAD_REQUEST).entity("Exercise not found").build();
}
List<String> savedFiles = saveSolution(formData.getFields("file"), exerciseName, studentName);
if (savedFiles.isEmpty()) {
return Response.status(Response.Status.BAD_REQUEST).entity("No files uploaded").build();
}
try {
AntRunner.antStudent(exerciseName, studentName);
List<File> reports = AntRunner.getTestsReports(exerciseName, studentName);
File buildXml = AntRunner.getBuildXml(exerciseName, studentName);
AntXmlParser antXmlParser = new AntXmlParser();
StudentResults studentResults = antXmlParser.parseStudentResults(buildXml, reports);
return Response.status(200).entity(studentResults).build();
} catch (IOException | ParserConfigurationException | SAXException | InterruptedException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
}
private List<String> saveSolution(List<FormDataBodyPart> files, String exercise, String student) {
DeleteStudentSolutionFolder(exercise,student);
List<String> result = new ArrayList();
for (FormDataBodyPart part : files) {
String fileName = part.getFormDataContentDisposition().getFileName();
if (fileName == null || !isJavaFile(fileName)) {
continue;
}
String destinationFolder = AntRunner.getExercisesFolder() + exercise + "/" + AntRunner.SOLUTIONS_SRC_FOLDER + student + "/";
try {
File savedfile = writeToFile(part.getEntityAs(InputStream.class), fileName, destinationFolder);
result.add(savedfile.getName());
} catch (IOException ex) {
Logger.getLogger(SolutionsController.class.getName()).log(Level.SEVERE, null, ex);
}
}
return result;
}
private void DeleteStudentSolutionFolder(String exercise, String student){
String destinationFolder = AntRunner.getExercisesFolder() + exercise + "/" + AntRunner.SOLUTIONS_SRC_FOLDER + student + "/";
try {
File folder = new File(destinationFolder);
FileHelper.delete(folder);
folder.mkdirs();
} catch (IOException ex) {
Logger.getLogger(SolutionsController.class.getName()).log(Level.SEVERE, null, ex);
}
}
private File writeToFile(InputStream uploadedInputStream,
String fileName,
String destinationFolder) throws FileNotFoundException, IOException {
File folder = new File(destinationFolder);
folder.mkdirs();
File file = new File(destinationFolder + fileName);
OutputStream out = new FileOutputStream(file);
int read = 0;
byte[] bytes = new byte[1024];
out = new FileOutputStream(file);
while ((read = uploadedInputStream.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
out.close();
file.setExecutable(true, false);
file.setWritable(true, false);
file.setReadable(true, false);
return file;
}
private boolean isJavaFile(String fileName) {
return FileHelper.getFileType(fileName).equals("java");
}
}