PageRenderTime 69ms CodeModel.GetById 35ms RepoModel.GetById 1ms app.codeStats 0ms

/beam-3dveglab-vlab/src/main/scripts/Install.java

https://github.com/anarisris/esa-beam
Java | 500 lines | 402 code | 32 blank | 66 comment | 79 complexity | 8b77cdc5e655bc5b52c23485df50af4b MD5 | raw file
  1. /*
  2. * Copyright (C) 2010-2014 Netcetera Switzerland (info@netcetera.com)
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU General Public License as published by the Free
  6. * Software Foundation; either version 3 of the License, or (at your option)
  7. * any later version.
  8. * This program is distributed in the hope that it will be useful, but WITHOUT
  9. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  11. * more details.
  12. *
  13. * You should have received a copy of the GNU General Public License along
  14. * with this program; if not, see http://www.gnu.org/licenses/
  15. *
  16. * @(#) $Id: $
  17. */
  18. import java.io.BufferedOutputStream;
  19. import java.io.BufferedReader;
  20. import java.io.BufferedWriter;
  21. import java.io.PrintWriter;
  22. import java.io.File;
  23. import java.io.FileInputStream;
  24. import java.io.FilenameFilter;
  25. import java.io.FileOutputStream;
  26. import java.io.FileWriter;
  27. import java.io.InputStream;
  28. import java.io.InputStreamReader;
  29. import java.io.IOException;
  30. import java.io.OutputStream;
  31. import java.io.OutputStreamWriter;
  32. import java.lang.reflect.Method;
  33. import java.lang.reflect.Modifier;
  34. import java.lang.Thread;
  35. import java.math.BigInteger;
  36. import java.net.JarURLConnection;
  37. import java.net.MalformedURLException;
  38. import java.net.URL;
  39. import java.net.URLClassLoader;
  40. import java.nio.channels.Channels;
  41. import java.nio.channels.ReadableByteChannel;
  42. import java.security.DigestInputStream;
  43. import java.security.MessageDigest;
  44. import java.util.Enumeration;
  45. import java.util.jar.Attributes;
  46. import java.util.regex.Matcher;
  47. import java.util.regex.Pattern;
  48. import java.util.Scanner;
  49. import java.util.zip.ZipEntry;
  50. import java.util.zip.ZipFile;
  51. public class Install {
  52. private static final String TYPE_BIN = "bin";
  53. private static final String TYPE_MODULES = "modules";
  54. private static final String TYPE_AUX = "aux";
  55. private static final String TYPE_LIB = "lib";
  56. private static final String DEFAULT_REPO = "http://www.geo.uzh.ch/microsite/3dveglab/software";
  57. private static final String DEFAULT_MANIFEST = DEFAULT_REPO + "/3DVegLab.manifest";
  58. public static void die(String msg) {System.err.println(msg); System.exit(1);}
  59. public static void fetch(String urlName, String targetName) throws Exception {
  60. System.out.println("fetch " + urlName + " " + targetName);
  61. URL url = null;
  62. ReadableByteChannel rbc = null;
  63. while (rbc == null) {
  64. try {
  65. url = new URL(urlName);
  66. rbc = Channels.newChannel(url.openStream());
  67. } catch (Exception e) {
  68. // might be trying to fetch from a busy server - sleep and retry
  69. System.out.println("got " + e.getMessage() + "\ngc, sleep, and retry...");
  70. url = null;
  71. rbc = null;
  72. // without calling gc(), this seems to loop forever
  73. System.gc();
  74. Thread.sleep(4000);
  75. }
  76. }
  77. FileOutputStream fos = new FileOutputStream(targetName);
  78. long nbytes = fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
  79. fos.close();
  80. System.out.println(nbytes + " bytes downloaded");
  81. }
  82. public static String md5sum(String fName) throws Exception {
  83. System.out.println("md5sum " + fName);
  84. MessageDigest md = MessageDigest.getInstance("MD5");
  85. InputStream is = new FileInputStream(fName);
  86. try {
  87. byte[] buf = new byte[64 * 1024];
  88. is = new DigestInputStream(is, md); while (is.read(buf) != -1);
  89. }
  90. finally {is.close();}
  91. return String.format("%1$032x", new BigInteger(1,md.digest()));
  92. }
  93. public static void unzip(String baseDir, String zipPath) throws Exception {
  94. System.out.println("unzip " + baseDir + " " + zipPath);
  95. Enumeration<?> entries; ZipFile zipFile;
  96. zipFile = new ZipFile(zipPath); entries = zipFile.entries();
  97. while (entries.hasMoreElements()) {
  98. ZipEntry ent = (ZipEntry) entries.nextElement();
  99. if (ent.isDirectory()) {
  100. (new File(baseDir, ent.getName())).mkdirs();
  101. } else {
  102. File newFile = new File(baseDir, ent.getName());
  103. InputStream in = zipFile.getInputStream(ent);
  104. OutputStream out = new BufferedOutputStream(new FileOutputStream(newFile));
  105. byte[] buffer = new byte[1024]; int len;
  106. while ((len = in.read(buffer)) >= 0) out.write(buffer, 0, len);
  107. in.close(); out.close();
  108. }
  109. }
  110. zipFile.close();
  111. }
  112. private static File createDummyInput() throws Exception {
  113. File dummyInput = new File(System.getProperty("java.io.tmpdir"), "dummy.xml");
  114. BufferedWriter out = new BufferedWriter(new FileWriter(dummyInput));
  115. for (String line : new String[] {
  116. "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>",
  117. "<RequestList>",
  118. " <Request type=\"VLAB\">",
  119. " <Parameter name=\"3dScene\" value=\"Default RAMI\"/>",
  120. " <OutputProduct file=\"vlab_out.dim\" format=\"BEAM-DIMAP\"/>",
  121. " </Request>",
  122. "</RequestList>"}) {
  123. out.write(line + "\n");
  124. }
  125. out.close();
  126. return dummyInput;
  127. }
  128. private static File createRunScript(String bindir) throws Exception {
  129. System.out.println("Creating 3DVegLabProcessor script...");
  130. String fileName = null;
  131. String[] lines = null;
  132. if (System.getProperty("os.name").startsWith("Windows")) {
  133. fileName = "3DVegLab.bat";
  134. lines = new String[] {
  135. "@echo off",
  136. "",
  137. "set BEAM4_HOME=" + new File(bindir, "..").getCanonicalPath(),
  138. "",
  139. "\"%BEAM4_HOME%\\jre\\bin\\java.exe\" ^",
  140. " -Xmx1024M ^",
  141. " -Dceres.context=beam ^",
  142. " \"-Dbeam.mainClass=org.esa.beam.framework.processor.ProcessorRunner\" ^",
  143. " \"-Dbeam.processorClass=com.netcetera.vlab.VLabProcessor\" ^",
  144. " \"-Dbeam.home=%BEAM4_HOME%\" ^",
  145. " \"-Dncsa.hdf.hdflib.HDFLibrary.hdflib=%BEAM4_HOME%\\modules\\lib-hdf-2.7\\lib\\jhdf.dll\" ^",
  146. " \"-Dncsa.hdf.hdf5lib.H5.hdf5lib=%BEAM4_HOME%\\modules\\lib-hdf-2.7\\lib\\jhdf5.dll\" ^",
  147. " -jar \"%BEAM4_HOME%\\bin\\ceres-launcher.jar\" %*",
  148. "",
  149. "exit /B %ERRORLEVEL%"
  150. };
  151. } else {
  152. fileName = "3DVegLab.sh";
  153. lines = new String[] {
  154. "#! /bin/sh",
  155. "",
  156. "export BEAM4_HOME=" + new File(bindir, "..").getCanonicalPath(),
  157. "",
  158. ". \"$BEAM4_HOME/bin/detect_java.sh\"",
  159. "",
  160. "\"$app_java_home/bin/java\" \\",
  161. " -Xmx1024M \\",
  162. " -Dceres.context=beam \\",
  163. " \"-Dbeam.mainClass=org.esa.beam.framework.processor.ProcessorRunner\" \\",
  164. " \"-Dbeam.processorClass=com.netcetera.vlab.VLabProcessor\" \\",
  165. " \"-Dbeam.home=$BEAM4_HOME\" \\",
  166. " \"-Dncsa.hdf.hdflib.HDFLibrary.hdflib=$BEAM4_HOME/modules/lib-hdf-2.7/lib/libjhdf.so\" \\",
  167. " \"-Dncsa.hdf.hdf5lib.H5.hdf5lib=$BEAM4_HOME/modules/lib-hdf-2.7/lib/libjhdf5.so\" \\",
  168. " -jar \"$BEAM4_HOME/bin/ceres-launcher.jar\" \"$@\"",
  169. "",
  170. "exit $?"
  171. };
  172. }
  173. File runScript = new File(bindir, fileName);
  174. BufferedWriter out = new BufferedWriter(new FileWriter(runScript));
  175. for (String line : lines) {
  176. out.write(line + "\n");
  177. }
  178. out.close();
  179. runScript.setExecutable(true);
  180. return runScript;
  181. }
  182. private static String join(String[] args, String jstr) {
  183. String result = "";
  184. for (String s: args) {
  185. if (result == "") {
  186. result = s;
  187. } else {
  188. result = result + jstr + s;
  189. }
  190. }
  191. return result;
  192. }
  193. private static int run3DVegLabProcessor(File inputFile, File scriptFile) throws Exception {
  194. System.out.println("Running 3DVegLabProcessor...");
  195. String[] cmd;
  196. if (System.getProperty("os.name").startsWith("Windows")) {
  197. cmd = new String[] {"cmd", "/c", "\" \"" + scriptFile.getCanonicalPath() + "\" \"" + inputFile.getCanonicalPath() + "\" 2>&1 \""};
  198. } else {
  199. cmd = new String[] {"sh", "-c", scriptFile.getCanonicalPath() + " " + inputFile.getCanonicalPath() + " 2>&1"};
  200. }
  201. System.out.println("Executing: " + join(cmd, " "));
  202. ProcessBuilder pb = new ProcessBuilder(cmd);
  203. Process proc = pb.start();
  204. // hack - collect but ignore output
  205. new Scanner( proc.getInputStream() ).useDelimiter("\\Z").next();
  206. return proc.waitFor();
  207. }
  208. private static boolean recursiveDelete(File path) {
  209. if (path.exists()) {
  210. File[] files = path.listFiles();
  211. for (int i = 0; i < files.length; i++) {
  212. if (files[i].isDirectory()) {
  213. recursiveDelete(files[i]);
  214. } else {
  215. files[i].delete();
  216. }
  217. }
  218. }
  219. return (path.delete());
  220. }
  221. /**
  222. * This method should be call to correctly install DART in the 3DVegLab plugin
  223. *
  224. * @param DARTfor3DVegLab: Path to the DARTfor3DVegLab.jar file that should be
  225. * run to install correctly DART in the 3DVegLab plugin.
  226. * @param args: A list of String arguments that should be passed to DARTfor3DVegLab.jar.
  227. * This JAR needs two arguments:
  228. * - DART_FOLDER: The DART folder where was extracted the archive (hopefully
  229. * this is the same where the DARTfor3DVegLab.jar file is located).
  230. * - DART_LOCAL: The location where the DART_LOCAL variable should point out.
  231. * In DART this variable should point out the folder that contains the
  232. * simulation folder.
  233. */
  234. private static void runDARTinstaller(String DARTfor3DVegLab, String[] args)
  235. throws MalformedURLException, IOException {
  236. // Load URL from String argument
  237. URL url = new URL("file:" + DARTfor3DVegLab);
  238. // Init the URLClassLoader
  239. URLClassLoader URLcl = new URLClassLoader(new URL[] {url});
  240. // Get MainClass name
  241. URL JARurl = new URL("jar", "", url + "!/");
  242. JarURLConnection JARuc = (JarURLConnection)JARurl.openConnection();
  243. Attributes attribut = JARuc.getMainAttributes();
  244. String mainClassName = attribut != null ? attribut.getValue(Attributes.Name.MAIN_CLASS) : null;
  245. // Invokes class
  246. try {
  247. // Instanciate the class and get the method
  248. Class<?> klass = URLcl.loadClass(mainClassName);
  249. Method mainMethod = klass.getMethod("main", new Class[] {args.getClass()});
  250. mainMethod.setAccessible(true);
  251. int modifiers = mainMethod.getModifiers();
  252. // Check the 'main'
  253. if (mainMethod.getReturnType() != void.class || ! Modifier.isStatic(modifiers) ||
  254. ! Modifier.isPublic(modifiers)) {
  255. throw new NoSuchMethodException("main");
  256. }
  257. try {
  258. // Launch the main method from DARTfor3DVegLab
  259. mainMethod.invoke(null, new Object[] { args });
  260. } catch (IllegalAccessException e) {
  261. }
  262. } catch (Exception e) {
  263. e.printStackTrace();
  264. System.exit(-1);
  265. }
  266. }
  267. private static void makePathsInLibratSceneFilesAbsolute(File dir) throws IOException {
  268. for (File fileOrDir : dir.listFiles())
  269. if (fileOrDir.isDirectory())
  270. makePathsInLibratSceneFilesAbsolute(fileOrDir);
  271. else if (fileOrDir.getName().matches("^[a-zA-Z0-9\\-_\\.]+(.obj|.obj.crown|.dem)$"))
  272. makePathsInFileAbsolute(fileOrDir);
  273. }
  274. private static void makePathsInFileAbsolute(File destination) throws IOException {
  275. File source = makeBackupFile(destination);
  276. destination.createNewFile();
  277. BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(source), "UTF-8"));
  278. PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(destination), "UTF-8"));
  279. String lineBuffer = null;
  280. while ((lineBuffer = reader.readLine()) != null)
  281. writer.println(makePathInStringAbsolute(lineBuffer, destination.getParentFile()));
  282. reader.close();
  283. writer.close();
  284. }
  285. private static String makePathInStringAbsolute(String string, File dir) {
  286. return string.replaceAll("\\./", (dir.getAbsolutePath() + File.separator).replaceAll("\\\\", "\\\\\\\\"));
  287. }
  288. private static File makeBackupFile(File source) {
  289. File destination = new File(source.getPath() + ".bak");
  290. source.renameTo(destination);
  291. return destination;
  292. }
  293. private static void install(String repoURL, String manifestUrl) throws Exception {
  294. // Get current working directory
  295. String cwd = new File(".").getCanonicalPath();
  296. // Test if we are inside beam-*/bin directory
  297. String endPath = "beam-4.11:bin".replaceAll(":", Matcher.quoteReplacement(File.separator));
  298. if (!cwd.endsWith(endPath)) {
  299. die("Run me from inside a directory ending with: " + endPath + " (not: " + cwd + ")");
  300. }
  301. // Set directories path
  302. String bindir = cwd;
  303. String moddir = new File(cwd, ".." + File.separator + TYPE_MODULES).getAbsolutePath();
  304. String libdir = new File(cwd, ".." + File.separator + TYPE_LIB).getAbsolutePath();
  305. String auxsuffix = ".beam:beam-vlab:auxdata".replaceAll(":", Matcher.quoteReplacement(File.separator));
  306. String auxdir = null;
  307. if (System.getProperty("os.name").startsWith("Windows")) {
  308. auxdir = new File(System.getenv("HOMEDRIVE")+System.getenv("HOMEPATH"), auxsuffix).getCanonicalPath();
  309. } else {
  310. auxdir = new File(System.getenv("HOME"), auxsuffix).getCanonicalPath();
  311. }
  312. File vlabaux = new File(auxdir, "..").getCanonicalFile();
  313. System.out.println("Clearing existing 3DVegLab auxdata: " + vlabaux);
  314. System.out.println("Succeeded? -> " + recursiveDelete(vlabaux));
  315. System.out.println("Fetching " + manifestUrl);
  316. // Get 3DVegLab.manifest file from manifestURL
  317. Scanner sc = new Scanner(new URL(manifestUrl).openStream());
  318. String text = sc.useDelimiter("\\Z").next(); sc.close();
  319. // Process manifest
  320. System.out.println("Processing " + manifestUrl);
  321. for (String line : text.split("\n")) {
  322. // Set up tuple, targetName and newBaseName
  323. String[] tuple = line.split(":");
  324. String targetName = null;
  325. String newBaseName = "";
  326. if (tuple.length > 3) {
  327. newBaseName = tuple[3];
  328. }
  329. if (TYPE_BIN.equals(tuple[1])) {
  330. targetName = bindir + File.separator + tuple[2];
  331. } else if (TYPE_AUX.equals(tuple[1])) {
  332. targetName = auxdir + File.separator + tuple[2];
  333. } else if (TYPE_LIB.equals(tuple[1])) {
  334. targetName = libdir + File.separator + tuple[2];
  335. } else if (TYPE_MODULES.equals(tuple[1])) {
  336. for (File toDelete : new File(moddir).listFiles(new FilenameFilter() {
  337. public boolean accept(File directory, String fileName) {
  338. return fileName.startsWith("beam-3dveglab-vlab");
  339. }})) {
  340. System.out.println("Deleting " + toDelete.getCanonicalPath());
  341. toDelete.delete();
  342. }
  343. targetName = moddir + File.separator + tuple[2];
  344. } else {
  345. die("unknown file locator: " + tuple[1]);
  346. }
  347. // Fetch targetName from repoURL
  348. fetch(repoURL + "/" + tuple[2], targetName);
  349. // Get md5sum and compare it to one from manifest
  350. String cksum = md5sum(targetName);
  351. if (!cksum.equals(tuple[0])) {
  352. die("md5sum mismatch: expected=" + tuple[0] + " actual=" + cksum);
  353. }
  354. // Get oldPath and newPath to rename if necessary
  355. String oldPath = null;
  356. String newPath = null;
  357. for ( String ext : new String[] {".zip", ".tar.gz"} ) {
  358. if (targetName.endsWith(ext)) {
  359. oldPath = targetName.substring(0, targetName.length()-ext.length());
  360. newPath = deriveName(oldPath, newBaseName);
  361. }
  362. }
  363. // Test type (modules, zip and tar.gz)
  364. if (TYPE_MODULES.equals(tuple[1])) {
  365. // modules
  366. File script = createRunScript(bindir);
  367. File dummy = createDummyInput();
  368. run3DVegLabProcessor(dummy, script);
  369. if (! new File(auxdir).isDirectory()) {
  370. die("no auxdir - running 3DVegLab must have failed");
  371. }
  372. } else if (targetName.endsWith(".zip")) {
  373. // ZIP archive
  374. // Unzip and delete fetched targetName file
  375. unzip(new File(targetName, "..").getCanonicalPath(), targetName);
  376. System.out.println("Deleting " + targetName);
  377. new File(targetName).delete();
  378. // If manifest point out a new base, move targetName to newBaseName
  379. if (!newBaseName.equals("")) {
  380. System.out.println("Renaming " + oldPath + " to " + newPath);
  381. new File(oldPath).renameTo(new File(newPath));
  382. }
  383. } else if (targetName.endsWith(".tar.gz")) {
  384. // tar.gz archive
  385. // Check the running OS is not Windows
  386. if (! System.getProperty("os.name").startsWith("Windows")) {
  387. // Create and run command line to extract .tar.gz archive
  388. String [] cmd = new String[] {"sh", "-c", "tar -C " + new File(targetName, "..").getCanonicalPath() + " -xzvf " + targetName};
  389. System.out.println("Running " + join(cmd, " "));
  390. ProcessBuilder pb = new ProcessBuilder(cmd);
  391. Process proc = pb.start();
  392. // hack - collect but ignore output
  393. new Scanner( proc.getInputStream() ).useDelimiter("\\Z").next();
  394. proc.waitFor();
  395. // Delete targetName
  396. System.out.println("Deleting " + targetName);
  397. new File(targetName).delete();
  398. // If manifest point out a new base, move targetName to newBaseName
  399. if (!newBaseName.equals("")) {
  400. System.out.println("Renaming " + oldPath + " to " + newPath);
  401. new File(oldPath).renameTo(new File(newPath));
  402. }
  403. }
  404. }
  405. File target = new File(targetName);
  406. String targetFilename = target.getName();
  407. if (targetFilename.startsWith("librat_scenes")) makePathsInLibratSceneFilesAbsolute(target.getParentFile());
  408. // Test if targetName is a DART archive
  409. if (targetFilename.startsWith("DART")
  410. && !(System.getProperty("os.name").startsWith("Windows") ^ targetName.endsWith(".zip"))) {
  411. // Get DART directory
  412. String DARTfolder = newPath;
  413. // Get DARTfor3DVegLab.jar path
  414. String DARTfor3DVegLab = newPath + File.separator + "DARTfor3DVegLab.jar";
  415. // Create arguments array that will be passed to DARTfor3DVegLab.jar
  416. String[] args = new String[2];
  417. args[0] = DARTfolder;
  418. // /!\ WARNING /!\ Keep this variable up to date and consistent with the dart_scene*.zip
  419. args[1] = new File(DARTfolder).getParent() + File.separator + "dart_local";
  420. // run DART installer
  421. System.out.println("Running DART installer");
  422. runDARTinstaller(DARTfor3DVegLab, args);
  423. }
  424. }
  425. System.out.println("Successfully completed.");
  426. }
  427. private static String deriveName(String oldName, String newBaseName) throws Exception {
  428. String newName = "";
  429. String[] comps = oldName.split(Matcher.quoteReplacement(File.separator));
  430. String basename = comps[comps.length-1];
  431. if (newBaseName.length() > 0) {
  432. newName = new File(oldName, "..").getCanonicalPath() + File.separator + newBaseName;
  433. } else {
  434. newName = new File(oldName, "..").getCanonicalPath() + File.separator + basename;
  435. }
  436. return newName;
  437. }
  438. public static void main(String[] args) throws Exception {
  439. switch (args.length){
  440. case 0:
  441. install(DEFAULT_REPO, DEFAULT_MANIFEST);
  442. break;
  443. case 2:
  444. case 3:
  445. if ("fetch".compareTo(args[0]) == 0) {
  446. String urlName = args[1];
  447. String targetName = null;
  448. String[] parts = urlName.split(";type=");
  449. String[] components = parts[0].split("/");
  450. targetName = components[components.length - 1];
  451. if (args.length == 3) { targetName = args[2]; }
  452. fetch(urlName, targetName);
  453. } else if ("unzip".compareTo(args[0]) == 0) {
  454. if(args.length != 2) { die("unzip expects unzipPath"); }
  455. unzip(new File(".").getCanonicalPath(), args[1]);
  456. } else if ("repo".compareTo(args[0]) == 0) {
  457. if(args.length != 3) { die("repo expects repoURL manifestURL"); }
  458. install(args[1], args[2]);
  459. } else {
  460. die("unknown subcommand: " + args[0]);
  461. }
  462. break;
  463. default:
  464. die("Invalid arguments");
  465. break;
  466. }
  467. }
  468. }