|
| 1 | +/* |
| 2 | + * Copyright (C) 2023 Jacob Nabe-Nielsen <jnn@bios.au.dk> |
| 3 | + * |
| 4 | + * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public |
| 5 | + * License version 2 and only version 2 as published by the Free Software Foundation. |
| 6 | + * |
| 7 | + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied |
| 8 | + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
| 9 | + * |
| 10 | + * You should have received a copy of the GNU General Public License along with this program; if not, see |
| 11 | + * <https://www.gnu.org/licenses>. |
| 12 | + * |
| 13 | + * Linking DEPONS statically or dynamically with other modules is making a combined work based on DEPONS. |
| 14 | + * Thus, the terms and conditions of the GNU General Public License cover the whole combination. |
| 15 | + * |
| 16 | + * In addition, as a special exception, the copyright holders of DEPONS give you permission to combine DEPONS |
| 17 | + * with free software programs or libraries that are released under the GNU LGPL and with code included in the |
| 18 | + * standard release of Repast Simphony under the Repast Suite License (or modified versions of such code, with unchanged license). |
| 19 | + * You may copy and distribute such a system following the terms of the GNU GPL for DEPONS and the licenses of the |
| 20 | + * other code concerned. |
| 21 | + * |
| 22 | + * Note that people who make modified versions of DEPONS are not obligated to grant this special exception for |
| 23 | + * their modified versions; it is their choice whether to do so. |
| 24 | + * The GNU General Public License gives permission to release a modified version without this exception; |
| 25 | + * this exception also makes it possible to release a modified version which carries forward this exception. |
| 26 | + */ |
| 27 | + |
| 28 | +package dk.au.bios.porpoise.util; |
| 29 | + |
| 30 | +import java.io.BufferedInputStream; |
| 31 | +import java.io.File; |
| 32 | +import java.io.FileOutputStream; |
| 33 | +import java.io.IOException; |
| 34 | +import java.net.URL; |
| 35 | +import java.nio.file.Paths; |
| 36 | +import java.security.MessageDigest; |
| 37 | +import java.security.NoSuchAlgorithmException; |
| 38 | +import java.util.List; |
| 39 | + |
| 40 | +import com.jgoodies.common.base.Objects; |
| 41 | + |
| 42 | +public class DownloadLandscapes { |
| 43 | + |
| 44 | + private static final List<LandscapeFile> LANDSCAPES = List.of( |
| 45 | + new LandscapeFile("DanTysk", "DanTysk.zip", "https://depons.eu/files/landscapes/DanTysk-2ce68aba.zip", |
| 46 | + 2409804, "2ce68aba7efa1b19358654e150320115dd6b676093e174451dfde3a809d6086e"), |
| 47 | + new LandscapeFile("Gemini", "Gemini.zip", "https://depons.eu/files/landscapes/Gemini-ebd7be0a.zip", 1340405, |
| 48 | + "ebd7be0ab28c898780776f1f48c7652d62b4a56a4a2d87e35c62b775705ccc0f"), |
| 49 | + new LandscapeFile("Homogeneous", "Homogeneous.zip", |
| 50 | + "https://depons.eu/files/landscapes/Homogeneous-fc68407d.zip", 82075, |
| 51 | + "fc68407dd2c7ddd74ad8c9f19ee90fc92f97bb90822eac8473a8fe365f22565d"), |
| 52 | + new LandscapeFile("Kattegat", "Kattegat.zip", "https://depons.eu/files/landscapes/Kattegat-6604cb49.zip", |
| 53 | + 16228688, "6604cb494e5508155f06d882777c7cd9eaeb46fa6992465a67477fe8144c1df1"), |
| 54 | + new LandscapeFile("NorthSea", "NorthSea.zip", "https://depons.eu/files/landscapes/NorthSea-02048b58.zip", |
| 55 | + 84613681, "02048b58aa2ff59107cdfde38e2b073bce1813de049e2f342a981796f0fa97d7")); |
| 56 | + |
| 57 | + public static void main(String[] args) throws Exception { |
| 58 | + for (var landscape : LANDSCAPES) { |
| 59 | + System.out.print(landscape.name + ": "); |
| 60 | + try { |
| 61 | + landscape.downloadAndVerify(false); |
| 62 | + System.out.println("completed"); |
| 63 | + } catch (IOException e) { |
| 64 | + System.out.println("failed: " + e.getMessage()); |
| 65 | + } |
| 66 | + } |
| 67 | + } |
| 68 | + |
| 69 | + private static class LandscapeFile { |
| 70 | + public final String name; |
| 71 | + public final String filename; |
| 72 | + public final String url; |
| 73 | + public final long numBytes; |
| 74 | + public final String sha256; |
| 75 | + |
| 76 | + public LandscapeFile(String name, String filename, String url, long numBytes, String sha256) { |
| 77 | + this.name = name; |
| 78 | + this.filename = filename; |
| 79 | + this.url = url; |
| 80 | + this.numBytes = numBytes; |
| 81 | + this.sha256 = sha256; |
| 82 | + } |
| 83 | + |
| 84 | + void downloadAndVerify(boolean overwriteExisting) throws IOException, NoSuchAlgorithmException { |
| 85 | + MessageDigest digest = MessageDigest.getInstance("SHA-256"); |
| 86 | + File fOut = Paths.get("data", filename).toFile(); |
| 87 | + |
| 88 | + if (fOut.exists() && !overwriteExisting) { |
| 89 | + throw new IOException("File " + filename + " exists and will not be overwritten"); |
| 90 | + } |
| 91 | + |
| 92 | + try (BufferedInputStream in = new BufferedInputStream(new URL(url).openStream()); |
| 93 | + FileOutputStream out = new FileOutputStream(fOut)) { |
| 94 | + |
| 95 | + var buffer = new byte[4096]; |
| 96 | + int actRead; |
| 97 | + while ((actRead = in.read(buffer, 0, 4096)) >= 0) { |
| 98 | + out.write(buffer, 0, actRead); |
| 99 | + digest.update(buffer, 0, actRead); |
| 100 | + } |
| 101 | + |
| 102 | + out.flush(); |
| 103 | + if (fOut.length() != numBytes) { |
| 104 | + throw new IOException( |
| 105 | + "Incorrect size for file " + name + ". Is: " + fOut.length() + ". Expected: " + numBytes); |
| 106 | + } |
| 107 | + |
| 108 | + var readSha256 = digest.digest(); |
| 109 | + var readSha256Str = bytesToHex(readSha256); |
| 110 | + if (!Objects.equals(sha256, readSha256Str)) { |
| 111 | + throw new IOException("Incorrect SHA256 checksum for file " + name); |
| 112 | + } |
| 113 | + } |
| 114 | + } |
| 115 | + |
| 116 | + private static String bytesToHex(byte[] hash) { |
| 117 | + StringBuilder hexString = new StringBuilder(2 * hash.length); |
| 118 | + for (int i = 0; i < hash.length; i++) { |
| 119 | + String hex = Integer.toHexString(0xff & hash[i]); |
| 120 | + if (hex.length() == 1) { |
| 121 | + hexString.append('0'); |
| 122 | + } |
| 123 | + hexString.append(hex); |
| 124 | + } |
| 125 | + return hexString.toString(); |
| 126 | + } |
| 127 | + |
| 128 | + } |
| 129 | + |
| 130 | +} |
0 commit comments