Java tutorial
/* * Copyright (c) 2009-2014, ZawodyWeb Team * All rights reserved. * * This file is distributable under the Simplified BSD license. See the terms * of the Simplified BSD license in the documentation provided with this file. */ package pl.umk.mat.zawodyweb.compiler.classes; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import org.apache.commons.httpclient.*; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.multipart.*; import org.apache.commons.httpclient.params.HttpClientParams; import org.apache.log4j.Logger; import pl.umk.mat.zawodyweb.judge.commons.TestInput; import pl.umk.mat.zawodyweb.judge.commons.TestOutput; import pl.umk.mat.zawodyweb.judge.commons.CompilerInterface; import pl.umk.mat.zawodyweb.database.ResultsStatusEnum; /** * * @author Marek Nowicki */ public class LanguageMAIN implements CompilerInterface { public static final org.apache.log4j.Logger logger = Logger.getLogger(LanguageMAIN.class); private Properties properties; @Override public void setProperties(Properties properties) { this.properties = properties; } /** * Calculate gained points from MAIN to points in ZawodyWeb * @param _points string representing MAIN points * @param task_points points for test in ZawodyWeb * @param max_points max points for problem in MAIN * @return */ private Integer calculatePoints(String _points, int task_points, Integer max_points) { try { int points = Integer.parseInt(_points); if (max_points == null) { if (points > task_points) { points = task_points; } return points; } else { return points * task_points / max_points; } } catch (NumberFormatException ex) { logger.info("Failed to calculate gained points (" + _points + ").", ex); } return null; } /** * Sprawdza rozwizanie na input * @param path kod rdowy * @param input w formacie: * <pre>c=NUMER_KONKURSU<br/>t=NUMER_ZADANIA<br/>m=MAX_POINTS</pre> * @return */ @Override public TestOutput runTest(String path, TestInput input) { TestOutput result = new TestOutput(null); Integer contest_id = null; Integer task_id = null; Integer max_points = null; try { try { Matcher matcher = null; matcher = Pattern.compile("c=([0-9]+)").matcher(input.getInputText()); if (matcher.find()) { contest_id = Integer.valueOf(matcher.group(1)); } matcher = Pattern.compile("t=([0-9]+)").matcher(input.getInputText()); if (matcher.find()) { task_id = Integer.valueOf(matcher.group(1)); } matcher = Pattern.compile("m=([0-9]+)").matcher(input.getInputText()); if (matcher.find()) { max_points = Integer.valueOf(matcher.group(1)); } if (contest_id == null) { throw new IllegalArgumentException("task_id == null"); } if (task_id == null) { throw new IllegalArgumentException("task_id == null"); } } catch (PatternSyntaxException ex) { throw new IllegalArgumentException(ex); } catch (NumberFormatException ex) { throw new IllegalArgumentException(ex); } catch (IllegalStateException ex) { throw new IllegalArgumentException(ex); } } catch (IllegalArgumentException e) { logger.error("Exception when parsing input", e); result.setStatus(ResultsStatusEnum.UNDEF.getCode()); result.setNotes(e.getMessage()); result.setOutputText("MAIN IllegalArgumentException"); return result; } logger.debug("Contest id = " + contest_id); logger.debug("Task id = " + task_id); logger.debug("Max points = " + max_points); String loginUrl = "http://main.edu.pl/pl/login"; String login = properties.getProperty("main_edu_pl.login"); String password = properties.getProperty("main_edu_pl.password"); HttpClient client = new HttpClient(); HttpClientParams params = client.getParams(); params.setParameter("http.useragent", "Opera/9.64 (Windows NT 6.0; U; pl) Presto/2.1.1"); //params.setParameter("http.protocol.handle-redirects", true); client.setParams(params); /* logowanie */ logger.debug("Logging in"); PostMethod postMethod = new PostMethod(loginUrl); NameValuePair[] dataLogging = { new NameValuePair("auth", "1"), new NameValuePair("login", login), new NameValuePair("pass", password) }; postMethod.setRequestBody(dataLogging); try { client.executeMethod(postMethod); if (Pattern.compile("Logowanie udane").matcher(postMethod.getResponseBodyAsString(1024 * 1024)) .find() == false) { logger.error("Unable to login (" + login + ":" + password + ")"); result.setStatus(ResultsStatusEnum.UNDEF.getCode()); result.setOutputText("Logging in failed"); postMethod.releaseConnection(); return result; } } catch (HttpException e) { logger.error("Exception when logging in", e); result.setStatus(ResultsStatusEnum.UNDEF.getCode()); result.setNotes(e.getMessage()); result.setOutputText("HttpException"); postMethod.releaseConnection(); return result; } catch (IOException e) { logger.error("Exception when logging in", e); result.setStatus(ResultsStatusEnum.UNDEF.getCode()); result.setNotes(e.getMessage()); result.setOutputText("IOException"); postMethod.releaseConnection(); return result; } postMethod.releaseConnection(); /* wchodzenie na stron z wysyaniem zada i pobieranie pl z hidden */ logger.debug("Getting submit page"); ArrayList<Part> values = new ArrayList<Part>(); try { GetMethod getMethod = new GetMethod("http://main.edu.pl/user.phtml?op=submit&m=insert&c=" + contest_id); client.executeMethod(getMethod); String response = getMethod.getResponseBodyAsString(1024 * 1024); getMethod.releaseConnection(); Matcher tagMatcher = Pattern.compile("<input[^>]*>").matcher(response); Pattern namePattern = Pattern.compile("name\\s*=\"([^\"]*)\""); Pattern valuePattern = Pattern.compile("value\\s*=\"([^\"]*)\""); while (tagMatcher.find()) { Matcher matcher = null; String name = null; String value = null; String inputTag = tagMatcher.group(); matcher = namePattern.matcher(inputTag); if (matcher.find()) { name = matcher.group(1); } matcher = valuePattern.matcher(inputTag); if (matcher.find()) { value = matcher.group(1); } if (name != null && value != null && name.equals("solution") == false) { values.add(new StringPart(name, value)); } } } catch (HttpException ex) { logger.error("Exception when getting submit page", ex); result.setStatus(ResultsStatusEnum.UNDEF.getCode()); result.setNotes(ex.getMessage()); result.setOutputText("IOException"); return result; } catch (IOException ex) { logger.error("Exception when getting submit page", ex); result.setStatus(ResultsStatusEnum.UNDEF.getCode()); result.setNotes(ex.getMessage()); result.setOutputText("IOException"); return result; } values.add(new StringPart("task", task_id.toString())); String filename = properties.getProperty("CODE_FILENAME"); filename = filename.replaceAll("\\." + properties.getProperty("CODEFILE_EXTENSION") + "$", ""); filename = filename + "." + properties.getProperty("CODEFILE_EXTENSION"); FilePart filePart = new FilePart("solution", new ByteArrayPartSource(filename, path.getBytes())); values.add(filePart); /* wysyanie rozwizania */ logger.debug("Submiting solution"); Integer solution_id = null; postMethod = new PostMethod("http://main.edu.pl/user.phtml?op=submit&m=db_insert&c=" + contest_id); postMethod.setRequestEntity(new MultipartRequestEntity(values.toArray(new Part[0]), client.getParams())); try { try { client.executeMethod(postMethod); HttpMethod method = postMethod; /* check if redirect */ Header locationHeader = postMethod.getResponseHeader("location"); if (locationHeader != null) { String redirectLocation = locationHeader.getValue(); GetMethod getMethod = new GetMethod( new URI(postMethod.getURI(), new URI(redirectLocation, false)).getURI()); client.executeMethod(getMethod); method = getMethod; } BufferedReader br = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream())); StringBuilder sb = new StringBuilder(); String line; while ((line = br.readLine()) != null) { sb.append(line).append("\n"); } Matcher matcher = Pattern.compile("<tr id=\"rptr\">.*?</tr>", Pattern.DOTALL) .matcher(sb.toString()); if (matcher.find()) { Matcher idMatcher = Pattern.compile("id=([0-9]+)").matcher(matcher.group()); if (idMatcher.find()) { solution_id = Integer.parseInt(idMatcher.group(1)); } } if (solution_id == null) { throw new IllegalArgumentException("solution_id == null"); } } catch (HttpException e) { new IllegalArgumentException(e); } catch (IOException e) { new IllegalArgumentException(e); } catch (NumberFormatException e) { new IllegalArgumentException(e); } catch (IllegalStateException e) { new IllegalArgumentException(e); } } catch (IllegalArgumentException e) { logger.error("Exception when submiting solution", e); result.setStatus(ResultsStatusEnum.UNDEF.getCode()); result.setNotes(e.getMessage()); result.setOutputText("IllegalArgumentException"); postMethod.releaseConnection(); return result; } postMethod.releaseConnection(); /* sprawdzanie statusu */ logger.debug("Checking result for main.id=" + solution_id); Pattern resultRowPattern = Pattern.compile("id=" + solution_id + ".*?</tr>", Pattern.DOTALL); Pattern resultPattern = Pattern.compile( "</td>.*?<td.*?>.*?</td>.*?<td.*?>(.*?)</td>.*?<td.*?>.*?</td>.*?<td.*?>(.*?)</td>", Pattern.DOTALL); result_loop: while (true) { try { Thread.sleep(7000); } catch (InterruptedException e) { result.setStatus(ResultsStatusEnum.UNDEF.getCode()); result.setNotes(e.getMessage()); result.setOutputText("InterruptedException"); return result; } GetMethod getMethod = new GetMethod("http://main.edu.pl/user.phtml?op=zgloszenia&c=" + contest_id); try { client.executeMethod(getMethod); String response = getMethod.getResponseBodyAsString(1024 * 1024); getMethod.releaseConnection(); Matcher matcher = resultRowPattern.matcher(response); // "</td>.*?<td.*?>.*?[NAZWA_ZADANIA]</td>.*?<td.*?>(.*?[STATUS])</td>.*?<td.*?>.*?</td>.*?<td.*?>(.*?[PUNKTY])</td>" while (matcher.find()) { Matcher resultMatcher = resultPattern.matcher(matcher.group()); if (resultMatcher.find() && resultMatcher.groupCount() == 2) { String resultType = resultMatcher.group(1); if (resultType.equals("?")) { continue; } else if (resultType.matches("B..d kompilacji")) { // CE result.setStatus(ResultsStatusEnum.CE.getCode()); result.setPoints( calculatePoints(resultMatcher.group(2), input.getMaxPoints(), max_points)); } else if (resultType.matches("Program wyw.aszczony")) { // TLE result.setStatus(ResultsStatusEnum.TLE.getCode()); result.setPoints( calculatePoints(resultMatcher.group(2), input.getMaxPoints(), max_points)); } else if (resultType.matches("B..d wykonania")) { // RTE result.setStatus(ResultsStatusEnum.RE.getCode()); result.setPoints( calculatePoints(resultMatcher.group(2), input.getMaxPoints(), max_points)); } else if (resultType.matches("Z.a odpowied.")) { // WA result.setStatus(ResultsStatusEnum.WA.getCode()); result.setPoints( calculatePoints(resultMatcher.group(2), input.getMaxPoints(), max_points)); } else if (resultType.equals("OK")) { // AC result.setStatus(ResultsStatusEnum.ACC.getCode()); result.setPoints( calculatePoints(resultMatcher.group(2), input.getMaxPoints(), max_points)); } else { result.setStatus(ResultsStatusEnum.UNDEF.getCode()); result.setNotes("Unknown status: \"" + resultType + "\""); } break result_loop; } } } catch (HttpException ex) { result.setStatus(ResultsStatusEnum.UNDEF.getCode()); result.setNotes(ex.getMessage()); result.setOutputText("HttpException"); return result; } catch (IOException ex) { result.setStatus(ResultsStatusEnum.UNDEF.getCode()); result.setNotes(ex.getMessage()); result.setOutputText("IOException"); return result; } } return result; } @Override public byte[] precompile(byte[] code) { return code; } @Override public String compile(byte[] code) { return new String(code); } @Override public String postcompile(String path) { return path; } @Override public void closeProgram(String path) { } }