Exemplo n.º 1
0
 /**
  * Runs plugin with supplied arguments.
  *
  * @li First element in @c $args must be a path to ZIP archive with input data.
  * @li Plugin execution is stopped on all triggered errors or uncaught exceptions
  *		and plugin error is returned.
  * @li setUp() and execute() methods are run respectively after input is
  *		unpacked and output folder is created.
  * @li Plugin creates and later removes two temporary folders. It can also create
  *		one ZIP archive with plugin output (path is returned in plugin results).
  * 
  * @param array $args simple array with plugin arguments
  * @return PluginResponse plugin results or error
  */
 public final function run(array $args)
 {
     set_error_handler(array('asm\\utils\\Utils', 'turnErrorToException'));
     $cwd = getcwd();
     try {
         if ($args == null || count($args) < 1) {
             throw new PluginUseException('Data file argument missing');
         }
         $this->dataFolder = Filesystem::tempDir();
         $dataFile = array_shift($args);
         if (!Compression::unzip($dataFile, $this->dataFolder, $unzipMessage)) {
             $response = PluginResponse::createError("ZIP extraction failed (" . $unzipMessage . ").\n\nPerhaps you did not submit a ZIP file " . "or that file was corrupted during upload. You may try again. Extraction was attempted to folder " . str_replace("\\", "/", $this->dataFolder));
         } else {
             $this->outputFolder = Filesystem::tempDir();
             chdir($this->dataFolder);
             $this->setUp($args);
             $this->execute();
             chdir($cwd);
             $outputFile = $this->packOutput();
             $outputPath = $outputFile != null ? realpath($outputFile) : null;
             $response = PluginResponse::create($this->results, $outputPath);
         }
     } catch (PluginException $e) {
         $response = PluginResponse::createError($e->getMessage());
     } catch (Exception $e) {
         $response = PluginResponse::createError('Runtime error: ' . $e->getMessage() . " (file " . $e->getFile() . ", line " . $e->getLine());
     }
     // If an exception occurred during $this->setUp or $this->execute, we must still change the current directory back,
     // in case more plugins are to be run (in a test case battery)
     chdir($cwd);
     restore_error_handler();
     if ($this->dataFolder != null) {
         Filesystem::removeDir($this->dataFolder);
     }
     if ($this->outputFolder != null) {
         Filesystem::removeDir($this->outputFolder);
     }
     return $response;
 }
Exemplo n.º 2
0
 function run($array)
 {
     $zipFile = $array[0];
     if (count($array) !== 2) {
         throw new InvalidArgumentException("This must receive 2 parameters in the array exactly.");
     }
     $launcher = new \asm\core\JavaLauncher();
     $pluginResults = "";
     $response = null;
     $error = $launcher->launch(Filesystem::combinePaths(CheckerRunner::$xmlCheckRoot, "/files/plugins/XML XQuery/XQueryPlugin.jar"), array($zipFile, $array[1]), $responseString);
     if (!$error) {
         if (isset($responseString)) {
             try {
                 $response = \asm\plugin\PluginResponse::fromXmlString($responseString);
             } catch (Exception $ex) {
                 $response = \asm\plugin\PluginResponse::createError('Internal error. Plugin did not supply valid response XML and this error occured: ' . $ex->getMessage() . '. Plugin instead supplied this response string: ' . $responseString);
             }
         }
     } else {
         $response = \asm\plugin\PluginResponse::createError('Plugin cannot be launched (' . $error . ').');
     }
     return $response;
 }
Exemplo n.º 3
0
 /**
  * Launches plugin and updates database with results.
  * @param string $pluginType one of 'php', 'java', or 'exe'
  * @param string $pluginFile plugin file path
  * @param string $inputFile input file path
  * @param boolean $isTest is this a plugin test or a submission? true if plugin test
  * @param int $rowId ID of row to be updated
  * @param array $arguments plugin arguments
  * @return bool true if no error occurred
  */
 public static function launchPlugin($pluginType, $pluginFile, $inputFile, $isTest, $rowId, $arguments = array())
 {
     try {
         $response = null;
         if (!is_file($pluginFile) || !is_file($inputFile)) {
             $error = "plugin file and/or input file don't exist";
         } else {
             array_unshift($arguments, $inputFile);
             $cwd = getcwd();
             chdir(dirname($pluginFile));
             switch ($pluginType) {
                 case 'php':
                     $launcher = new PhpLauncher();
                     ob_start();
                     $error = $launcher->launch($pluginFile, $arguments, $response);
                     ob_end_clean();
                     break;
                 case 'java':
                     $launcher = new JavaLauncher();
                     $error = $launcher->launch($pluginFile, $arguments, $responseString);
                     break;
                 case 'exe':
                     $launcher = new ExeLauncher();
                     $error = $launcher->launch($pluginFile, $arguments, $responseString);
                     break;
                 default:
                     $error = "unsupported plugin type '{$pluginType}'";
             }
             chdir($cwd);
         }
         if (!$error) {
             if (isset($responseString)) {
                 try {
                     $response = PluginResponse::fromXmlString($responseString);
                 } catch (Exception $ex) {
                     $response = PluginResponse::createError('Internal error. Plugin did not supply valid response XML and this error occurred: ' . $ex->getMessage() . '. Plugin instead supplied this response string: ' . $responseString);
                 }
             }
         } else {
             $response = PluginResponse::createError('Plugin cannot be launched (' . $error . ').');
         }
         $outputFile = $response->getOutput();
         if ($outputFile) {
             $outputFolder = Config::get('paths', 'output');
             $newFile = $outputFolder . date('Y-m-d_H-i-s_') . StringUtils::randomString(10) . '.zip';
             if (rename($outputFile, $newFile)) {
                 $outputFile = $newFile;
             } else {
                 $outputFile = 'tmp-file-rename-failed';
             }
         }
         /**
          * @var $pluginTest \PluginTest
          * @var $submission \Submission
          * @var $previousSubmissions \Submission[]
          */
         if ($isTest) {
             $pluginTest = Repositories::findEntity(Repositories::PluginTest, $rowId);
             $pluginTest->setStatus(\PluginTest::STATUS_COMPLETED);
             $pluginTest->setSuccess($response->getFulfillment());
             $pluginTest->setInfo($response->getDetails());
             $pluginTest->setOutput($outputFile);
             Repositories::persistAndFlush($pluginTest);
         } else {
             $submission = Repositories::findEntity(Repositories::Submission, $rowId);
             // There is a sort of a race condition in here.
             // It is, in theory, possible, that there will be two submissions with the "latest" status after all is done
             // This should not happen in practice, though, and even if it does, it will have negligible negative effects.
             $previousSubmissions = Repositories::makeDqlQuery("SELECT s FROM \\Submission s WHERE s.user = :sameUser AND s.assignment = :sameAssignment AND s.status != 'graded' AND s.status != 'deleted'")->setParameter('sameUser', $submission->getUser()->getId())->setParameter('sameAssignment', $submission->getAssignment()->getId())->getResult();
             foreach ($previousSubmissions as $previousSubmission) {
                 $previousSubmission->setStatus(\Submission::STATUS_NORMAL);
                 Repositories::getEntityManager()->persist($previousSubmission);
             }
             $submission->setStatus(\Submission::STATUS_LATEST);
             $submission->setInfo($response->getDetails());
             $submission->setSuccess($response->getFulfillment());
             $submission->setOutputfile($outputFile);
             Repositories::getEntityManager()->persist($submission);
             Repositories::flushAll();
         }
         return !$error;
     } catch (Exception $exception) {
         $errorInformation = "Internal error. Plugin launcher or plugin failed with an internal error. Exception information: " . $exception->getMessage() . " in " . $exception->getFile() . " at " . $exception->getLine();
         if ($isTest) {
             $pluginTest = Repositories::findEntity(Repositories::PluginTest, $rowId);
             $pluginTest->setStatus(\PluginTest::STATUS_COMPLETED);
             $pluginTest->setSuccess(0);
             $pluginTest->setInfo($errorInformation);
             Repositories::persistAndFlush($pluginTest);
         } else {
             $submission = Repositories::findEntity(Repositories::Submission, $rowId);
             $submission->setStatus(\Submission::STATUS_NORMAL);
             $submission->setInfo($errorInformation);
             Repositories::persistAndFlush($submission);
         }
         return false;
     }
 }