/******************************************************************************* * Copyright (c) 2003, 2010 Albert Pérez and RoboRumble contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/epl-v10.html * * Contributors: * Albert P�rez * - Initial API and implementation * Flemming N. Larsen * - Ported to Java 5 * - Removed dead code * - Minor optimizations * - Replaced the robocode.util.Utils.copy() method with FileTransfer.copy() * - Bugfix: Solved ZipException by creating a session to the Robocode * Repository site * - Properties are now read using PropertiesUtil.getProperties() * - Renamed CheckCompetitorsForSize() into checkCompetitorsForSize() * - Added missing close() to streams * - Added new EXCLUDE property, which is used for excluding participants * - Added the isExcluded() method *******************************************************************************/ package net.sf.robocode.roborumble.netengine; import net.sf.robocode.io.Logger; import net.sf.robocode.roborumble.battlesengine.CompetitionsSelector; import static net.sf.robocode.roborumble.netengine.FileTransfer.DownloadStatus; import static net.sf.robocode.roborumble.util.ExcludesUtil.*; import static net.sf.robocode.roborumble.util.PropertiesUtil.getProperties; import java.io.*; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.util.Enumeration; import java.util.Hashtable; import java.util.Properties; import java.util.Vector; import java.util.jar.JarFile; import java.util.zip.ZipEntry; /** * Class used for downloading participating robots from the Internet. * Manages the download operations (participants and JAR files). * Controlled by properties files. * * @author Albert P�rez (original) * @author Flemming N. Larsen (contributor) */ public class BotsDownload { // private String internetrepository; private final String botsrepository; private final String participantsfile; private final String participantsurl; private final String tempdir; private final String tag; private final String isteams; private final String sizesfile; private final CompetitionsSelector size; private final String ratingsurl; private String generalbots; private final String minibots; private final String microbots; private final String nanobots; private final String generalbotsfile; private final String minibotsfile; private final String microbotsfile; private final String nanobotsfile; private final String removeboturl; public BotsDownload(String propertiesfile) { // Read parameters Properties parameters = getProperties(propertiesfile); botsrepository = parameters.getProperty("BOTSREP", ""); isteams = parameters.getProperty("TEAMS", "NOT"); participantsurl = parameters.getProperty("PARTICIPANTSURL", ""); participantsfile = parameters.getProperty("PARTICIPANTSFILE", ""); tag = parameters.getProperty("STARTAG", "pre"); tempdir = parameters.getProperty("TEMP", ""); // Code size sizesfile = parameters.getProperty("CODESIZEFILE", ""); size = new CompetitionsSelector(sizesfile, botsrepository); // Ratings files ratingsurl = parameters.getProperty("RATINGS.URL", ""); generalbots = propertiesfile; while (generalbots.indexOf("/") != -1) { generalbots = generalbots.substring(generalbots.indexOf("/") + 1); } generalbots = generalbots.substring(0, generalbots.indexOf(".")); minibots = parameters.getProperty("MINIBOTS", ""); microbots = parameters.getProperty("MICROBOTS", ""); nanobots = parameters.getProperty("NANOBOTS", ""); generalbotsfile = parameters.getProperty("RATINGS.GENERAL", ""); minibotsfile = parameters.getProperty("RATINGS.MINIBOTS", ""); microbotsfile = parameters.getProperty("RATINGS.MICROBOTS", ""); nanobotsfile = parameters.getProperty("RATINGS.NANOBOTS", ""); // remove old bots removeboturl = parameters.getProperty("UPDATEBOTSURL", ""); // Read and prepare exclude filters setExcludes(parameters); } public boolean downloadRatings() { File file; // delete previous files if (generalbotsfile.length() != 0) { file = new File(generalbotsfile); if (file.exists() && !file.delete()) { Logger.logError("Can't delete file"); } } if (minibotsfile.length() != 0) { file = new File(minibotsfile); if (file.exists() && !file.delete()) { Logger.logError("Can't delete file"); } } if (microbotsfile.length() != 0) { file = new File(microbotsfile); if (file.exists() && !file.delete()) { Logger.logError("Can't delete file"); } } if (nanobotsfile.length() != 0) { file = new File(nanobotsfile); if (file.exists() && !file.delete()) { Logger.logError("Can't delete file"); } } // download new ones if (ratingsurl.length() == 0) { return false; } boolean downloaded = true; if (generalbots.length() != 0 && generalbotsfile.length() != 0) { downloaded = downloadRatingsFile(generalbots, generalbotsfile) & downloaded; } if (minibots.length() != 0 && minibotsfile.length() != 0) { downloaded = downloadRatingsFile(minibots, minibotsfile) & downloaded; } if (microbots.length() != 0 && microbotsfile.length() != 0) { downloaded = downloadRatingsFile(microbots, microbotsfile) & downloaded; } if (nanobots.length() != 0 && nanobotsfile.length() != 0) { downloaded = downloadRatingsFile(nanobots, nanobotsfile) & downloaded; } return downloaded; } public boolean downloadParticipantsList() { String begin = "<" + tag + ">"; String end = "</" + tag + ">"; Vector<String> bots = new Vector<String>(); BufferedReader in = null; HttpURLConnection urlc = null; try { URL url = new URL(participantsurl); urlc = (HttpURLConnection) url.openConnection(); urlc.setRequestMethod("GET"); urlc.setDoInput(true); urlc.connect(); // Check that we received a HTTP_OK response code. // Bugfix [2779557] - Client tries to remove all participants. if (urlc.getResponseCode() != HttpURLConnection.HTTP_OK) { System.out.print("Unable to retrieve participants list. Response is " + urlc.getResponseCode()); if (urlc.getResponseMessage() != null) { System.out.print(": " + urlc.getResponseMessage()); } System.out.println(); return false; // Error } boolean arebots = false; in = new BufferedReader(new InputStreamReader(urlc.getInputStream())); for (String participant; (participant = in.readLine()) != null;) { if (participant.indexOf(begin) >= 0) { arebots = true; } else if (participant.indexOf(end) >= 0) { arebots = false; } else if (arebots) { String bot = participant.split("[,]")[0]; if (!isExcluded(bot)) { if (!verifyParticipantFormat(participant)) { if (participant.trim().length() > 0) { System.out.println("Participant ignored due to invalid line: " + bot); } } else { bots.add(participant); } } else { System.out.println("Ignored excluded: " + bot); } } } // Prevent our local participants file to be overwritten, if the downloaded list is empty. // Bugfix [2779557] - Client tries to remove all participants. if (bots.size() == 0) { System.out.println("The participants list is empty"); return false; // Error } final File dir = new File(participantsfile).getParentFile(); if (!dir.exists() && !dir.mkdirs()) { Logger.logError("Can't create " + dir); } PrintStream outtxt = new PrintStream(new BufferedOutputStream(new FileOutputStream(participantsfile)), false); for (String bot : bots) { outtxt.println(bot); } outtxt.close(); } catch (IOException e) { System.out.println("Unable to retrieve participants list:"); System.out.println(e); return false; // Error } finally { if (in != null) { try { in.close(); } catch (IOException ignored) {} } if (urlc != null) { urlc.disconnect(); } } return true; // Success } public void downloadMissingBots() { Vector<String> jars = new Vector<String>(); Vector<String> ids = new Vector<String>(); Vector<String> names = new Vector<String>(); // Read participants BufferedReader br = null; try { FileReader fr = new FileReader(participantsfile); br = new BufferedReader(fr); for (String record; (record = br.readLine()) != null;) { if (record.indexOf(",") >= 0) { String id = record.substring(record.indexOf(",") + 1).trim(); String name = record.substring(0, record.indexOf(",")).trim(); String jar = name.replace(' ', '_') + ".jar"; jars.add(jar); ids.add(id); names.add(name); } } } catch (IOException e) { System.out.println("Participants file not found ... Aborting"); System.out.println(e); return; } finally { if (br != null) { try { br.close(); } catch (IOException ignored) {} } } // check if the file exists in the repository and download if not present for (int i = 0; i < jars.size(); i++) { String botjar = jars.get(i); String botid = ids.get(i); String botname = names.get(i); String botpath = botsrepository + botjar; boolean exists = (new File(botpath)).exists(); if (!exists) { boolean downloaded = downloadBot(botname, botjar, botid, botsrepository, tempdir); if (!downloaded) { System.out.println("Could not download " + botjar); } } } } public void updateCodeSize() { if (sizesfile.length() != 0) { BufferedReader br = null; try { FileReader fr = new FileReader(participantsfile); br = new BufferedReader(fr); for (String record; (record = br.readLine()) != null;) { String name = record.substring(0, record.indexOf(",")); name = name.replace(' ', '_'); size.checkCompetitorsForSize(name, name, 1500); } } catch (IOException e) { System.out.println("Battles input file not found ... Aborting"); System.out.println(e); } finally { if (br != null) { try { br.close(); } catch (IOException ignored) {} } } } } private boolean downloadBot(String botname, String file, String id, String destination, String tempdir) { String filed = tempdir + file; String finald = destination + file; // check if the bot exists in the repository boolean exists = (new File(finald)).exists(); if (exists) { System.out.println("The bot already exists in the repository."); return false; } // Download the bot String url; String sessionId = null; if (id.indexOf("://") == -1) { url = "http://robocoderepository.com/Controller.jsp?submitAction=downloadClass&id=" + id; sessionId = FileTransfer.getSessionId( "http://robocoderepository.com/BotSearch.jsp?botName=''&authorName=''&uploadDate="); } else { url = id; } DownloadStatus downloadStatus = FileTransfer.download(url, filed, sessionId); if (downloadStatus == DownloadStatus.FILE_NOT_FOUND) { System.out.println("Could not find " + botname + " from " + url); return false; } else if (downloadStatus == DownloadStatus.COULD_NOT_CONNECT) { System.out.println("Could not connect to " + url); return false; } // Check the bot and save it into the repository if (checkJarFile(filed, botname)) { if (!FileTransfer.copy(filed, finald)) { System.out.println("Unable to copy " + filed + " into the repository"); return false; } } else { System.out.println("Downloaded file is wrong or corrupted:" + file); return false; } System.out.println("Downloaded " + botname + " into " + finald); return true; } private boolean checkJarFile(String file, String botname) { if (botname.indexOf(" ") == -1) { System.out.println("Are you sure " + botname + " is a bot/team? Can't download it."); return false; } String bot = botname.substring(0, botname.indexOf(" ")); bot = bot.replace('.', '/'); if (isteams.equals("YES")) { bot += ".team"; } else { bot += ".properties"; } try { JarFile jarf = new JarFile(file); ZipEntry zipe = jarf.getJarEntry(bot); if (zipe == null) { System.out.println("Not able to read properties"); return false; } InputStream properties = jarf.getInputStream(zipe); Properties parameters = getProperties(properties); if (!isteams.equals("YES")) { String classname = parameters.getProperty("robot.classname", ""); String version = parameters.getProperty("robot.version", ""); return (botname.equals(classname + " " + version)); } String version = parameters.getProperty("team.version", ""); return (botname.equals(botname.substring(0, botname.indexOf(" ")) + " " + version)); } catch (Exception e) { System.out.println(e); return false; } } // ---------------------------------------------------------------------------------- // download ratings file // ---------------------------------------------------------------------------------- private boolean downloadRatingsFile(String competition, String file) { BufferedReader in = null; PrintStream outtxt = null; try { URL url = new URL(ratingsurl + "?version=1&game=" + competition); HttpURLConnection urlc = (HttpURLConnection) url.openConnection(); urlc.setRequestMethod("GET"); urlc.setDoInput(true); urlc.connect(); final File dir = new File(file).getParentFile(); if (!dir.exists() && !dir.mkdirs()) { Logger.logError("Can't create " + dir); } outtxt = new PrintStream(new BufferedOutputStream(new FileOutputStream(file)), false); in = new BufferedReader(new InputStreamReader(urlc.getInputStream())); for (String str; (str = in.readLine()) != null;) { outtxt.println(str); } urlc.disconnect(); } catch (IOException e) { System.out.println("Unable to ratings for " + competition); System.out.println(e); return false; } finally { if (in != null) { try { in.close(); } catch (IOException ignored) {} } if (outtxt != null) { outtxt.close(); } } return true; } // ---------------------------------------------------------------------------------- // download ratings file // ---------------------------------------------------------------------------------- public void notifyServerForOldParticipants() { // Load participants names Hashtable<String, String> namesall = new Hashtable<String, String>(); BufferedReader br = null; try { FileReader fr = new FileReader(participantsfile); br = new BufferedReader(fr); for (String record; (record = br.readLine()) != null;) { if (record.indexOf(",") != -1) { String name = record.substring(0, record.indexOf(",")).replace(' ', '_'); namesall.put(name, name); } } } catch (IOException e) { System.out.println("Participants file not found when removing old participants ... Aborting"); System.out.println(e); return; } finally { if (br != null) { try { br.close(); } catch (IOException ignored) {} } } // Load ratings files Properties generalratings = getProperties(generalbotsfile); Properties miniratings = getProperties(minibotsfile); Properties microratings = getProperties(microbotsfile); Properties nanoratings = getProperties(nanobotsfile); // Check general ratings for (Enumeration<?> e = generalratings.propertyNames(); e.hasMoreElements();) { String bot = (String) e.nextElement(); if (!(isExcluded(bot) || namesall.containsKey(bot))) { // Remove the bot from the ratings file System.out.println("Removing entry ... " + bot + " from " + generalbots); removebot(generalbots, bot); } } // Check mini ratings for (Enumeration<?> e = miniratings.propertyNames(); e.hasMoreElements();) { String bot = (String) e.nextElement(); if (!(isExcluded(bot) || namesall.containsKey(bot))) { // Remove the bot from the ratings file System.out.println("Removing entry ... " + bot + " from " + minibots); removebot(minibots, bot); } } // Check micro ratings for (Enumeration<?> e = microratings.propertyNames(); e.hasMoreElements();) { String bot = (String) e.nextElement(); if (!(isExcluded(bot) || namesall.containsKey(bot))) { // Remove the bot from the ratings file System.out.println("Removing entry ... " + bot + " from " + microbots); removebot(microbots, bot); } } // Check nano ratings for (Enumeration<?> e = nanoratings.propertyNames(); e.hasMoreElements();) { String bot = (String) e.nextElement(); if (!(isExcluded(bot) || namesall.containsKey(bot))) { // Remove the bot from the ratings file System.out.println("Removing entry ... " + bot + " from " + nanobots); removebot(nanobots, bot); } } } private void removebot(String game, String bot) { if (removeboturl.length() == 0) { System.out.println("UPDATEBOTS URL not defined!"); return; } String data = "version=1&game=" + game + "&name=" + bot.trim() + "&dummy=NA"; PrintWriter wr = null; BufferedReader rd = null; try { // Send data URL url = new URL(removeboturl); URLConnection conn = url.openConnection(); conn.setDoOutput(true); wr = new PrintWriter(new OutputStreamWriter(conn.getOutputStream())); wr.println(data); wr.flush(); // Get the response rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); for (String line; (line = rd.readLine()) != null;) { System.out.println(line); } } catch (IOException e) { System.out.println(e); } finally { if (wr != null) { wr.close(); } if (rd != null) { try { rd.close(); } catch (IOException ignored) {} } } } // Checks if a participant format from the participant list is valid private boolean verifyParticipantFormat(String participant) { String[] split = participant.split("[,]"); boolean matches = false; if (split.length == 2) { String robot = split[0].trim(); String link = split[1].trim(); if (robot.matches("[\\w\\.]+[ ][\\w\\.-]+")) { if (link.startsWith("http")) { try { new URL(link); matches = true; } catch (MalformedURLException e) { matches = false; } } else if (link.matches("[\\d]+")) { matches = true; } } } return matches; } }