package de.hftstuttgart.rest.v1.task; import de.hftstuttgart.models.LegacyMoodleResult; import de.hftstuttgart.models.ModocotResultSummary; import de.hftstuttgart.utils.*; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.tika.Tika; import org.springframework.core.env.Environment; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import javax.servlet.annotation.MultipartConfig; import java.io.*; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.regex.Matcher; /** * Rest controller for everything related to the TASK files */ @RestController @RequestMapping("/v1/task") @MultipartConfig public class TaskUpload { private static final Logger LOG = LogManager.getLogger(TaskUpload.class); private final JGitUtil jGitUtil; private final Path testTmpPathModocot; private final ExecuteTestUtil executeTestUtil; public TaskUpload( Environment env, JGitUtil jGitUtil, ExecuteTestUtil executeTestUtil ) { this.jGitUtil = jGitUtil; this.executeTestUtil = executeTestUtil; // set path of temporary directory on host and inside our container this.testTmpPathModocot = Paths.get(env.getProperty("modocot.tests.tmp.dir")); } @RequestMapping(method = RequestMethod.POST) public LegacyMoodleResult uploadAndTestFile(@RequestParam("taskFile") MultipartFile taskFileRef, @RequestParam("assignmentId") String assignmentId ) throws IOException, InterruptedException { LOG.info("submission for testing received"); LOG.debug("creating new temporary directory"); Path workDirectory = Files.createTempDirectory(testTmpPathModocot, "modocot"); LOG.debug(String.format("working dir for test is: %s", workDirectory.toAbsolutePath().toString())); // define paths for the test, the submission and where the result is to be expected afterwards Path srcPath = Paths.get(workDirectory.toAbsolutePath().toString(), "src"); String mimeInfo = new Tika().detect(taskFileRef.getInputStream()); switch (mimeInfo) { case "text/plain": LOG.debug("textfile uploaded, searching for modocot config"); // find modocot URI in config file Matcher config = RegexUtil.findModocotStudentConfig(taskFileRef.getInputStream()); LOG.debug("calling repo clone"); jGitUtil.cloneRepository(config, srcPath.toAbsolutePath().toString()); break; case "application/zip": LOG.debug("zip archive uploaded, extracting content as student submission"); ArchiveUtil.extractProjectFromZip(taskFileRef.getInputStream(), srcPath.toAbsolutePath()); break; default: String msg = String.format("couldn't process uploaded file with mime type %s", mimeInfo); LOG.error(msg); throw new RuntimeException(msg); } // run test LOG.debug("calling test execution"); ModocotResultSummary resultSummary = executeTestUtil.runTests(assignmentId, workDirectory); // convert to moddle plugin readable format and return to moodle LOG.debug("convert to moodle understandable format"); LegacyMoodleResult moodleResult = LegacyMoodleResult.convertToModdleResult(resultSummary); if (mimeInfo.equals("text/plain")) { LOG.info("check for provided Ticketsystem information"); UnifiedTicketingUtil.reportResults(taskFileRef.getInputStream(), resultSummary); } LOG.info("submission tested successfully"); return moodleResult; } }