/* Copyright (C) 2010 Copyright 2010 Google Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package com.googlecode.gwtquake.tools; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.Enumeration; import java.util.Locale; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import com.googlecode.gwtquake.server.CompatibilityImpl; import com.googlecode.gwtquake.shared.common.Compatibility; public class Downloader implements Runnable { static final String[] MIRRORS = { "ftp://ftp.fu-berlin.de/pc/msdos/games/idgames/idstuff/quake2/q2-314-demo-x86.exe", "ftp://ftp.cs.tu-berlin.de/pub/msdos/mirrors/ftp.idsoftware.com/quake2/q2-314-demo-x86.exe", "ftp://ftp.demon.co.uk/pub/mirrors/idsoftware/quake2/q2-314-demo-x86.exe", "ftp://ftp.fragzone.se/pub/spel/quake2/q2-314-demo-x86.exe", "ftp://ftp.idsoftware.com/idstuff/quake2/q2-314-demo-x86.exe", "ftp://ftp.gamers.org/pub/games/idgames2/idstuff/quake2/q2-314-demo-x86.exe", "http://ftp.iinet.net.au/games/idstuff/quake2/q2-314-demo-x86.exe" }; static final int FILE_SIZE = 39015499; private boolean hiresPak; public static void main(String[] args) throws MalformedURLException, InterruptedException { Compatibility.impl = new CompatibilityImpl(); if (new File("raw", "baseq2").exists()) { System.out.println("raw/baseq2 already exists; no need to download"); return; } int m0 = selectInitialMirror(); for (int i = 0; i < MIRRORS.length * 2; i++) { Downloader download = new Downloader(MIRRORS[(i + m0) % MIRRORS.length]); Thread t = new Thread(download); t.start(); t.join(); if (download.ok) { return; } } throw new RuntimeException("Too many retries. Download failed."); } public static int selectInitialMirror() { String domain = Locale.getDefault().getCountry(); if (domain != null) { domain = "." + domain.toLowerCase() + "/"; if (domain.equals(".us/")) { domain = ".com/"; } else if (domain.equals(".gb/")) { domain = ".uk/"; } for (int i = 0; i < MIRRORS.length; i++) { if (MIRRORS[i].indexOf(domain) != -1) { return i; } } } return ((int) (Math.random() * 1000)); } private final URL url; private byte[] buf = new byte[65536]; boolean ok; public Downloader(String url) throws MalformedURLException { this.url = new URL(url); System.out.println("Trying mirror: " + url); } void copyStream(InputStream is, OutputStream os, int expected_size) throws IOException { int total = 0; int dots = 0; while (true) { int count = is.read(buf, 0, buf.length); if (count <= 0) { break; } total += count; if (expected_size != -1) { if (total / 1000000 > dots) { System.out.print("."); dots++; } } os.write(buf, 0, count); } if (expected_size != -1 && total != expected_size) { throw new IOException("Download errot: expected file size: " + expected_size + "; received: " + total); } os.close(); is.close(); } public void run() { try { InputStream is = url.openStream(); File tempFile = File.createTempFile("q2-temp", null); tempFile.deleteOnExit(); System.out.print("Downloading"); copyStream(is, new FileOutputStream(tempFile), FILE_SIZE); System.out.println("Download finished; uncompressing"); ZipFile zipFile = new ZipFile(tempFile); Enumeration<?> e = zipFile.entries(); while (e.hasMoreElements()) { ZipEntry entry = (ZipEntry)e.nextElement(); String name = entry.getName(); int i = 0; if (hiresPak || (i = name.indexOf("/baseq2")) > -1 && name.indexOf(".dll") == -1) { // hiresPak is rooted beneath baseq2 if (hiresPak) { name = "/baseq2/" + name; } File outFile = new File("raw", name.substring(i)); if (entry.isDirectory()) { outFile.mkdirs(); } else { System.out.println("installing " + name.substring(i)); outFile.getParentFile().mkdirs(); copyStream(zipFile.getInputStream(entry), new FileOutputStream(outFile), -1); } } } ok = true; } catch (IOException e) { System.out.println("Donwload Failed"); } } public void setHiresPak(boolean hiresPak) { this.hiresPak = hiresPak; } }