/* * Eoulsan development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public License version 2.1 or * later and CeCILL-C. This should be distributed with the code. * If you do not have a copy, see: * * http://www.gnu.org/licenses/lgpl-2.1.txt * http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.txt * * Copyright for this code is held jointly by the Genomic platform * of the Institut de Biologie de l'École normale supérieure and * the individual authors. These should be listed in @author doc * comments. * * For more information on the Eoulsan project and its aims, * or to join the Eoulsan Google group, visit the home page * at: * * http://outils.genomique.biologie.ens.fr/eoulsan * */ package fr.ens.biologie.genomique.eoulsan.util; import static fr.ens.biologie.genomique.eoulsan.EoulsanLogger.getLogger; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import fr.ens.biologie.genomique.eoulsan.EoulsanRuntime; import fr.ens.biologie.genomique.eoulsan.Globals; /** * This class is used to install binaries bundled in the jar. * @since 1.0 * @author Laurent Jourdren */ public class BinariesInstaller { private static final int BUFFER_SIZE = 32 * 1024; private static void install(final String inputPath, final String file, final String outputPath) throws FileNotFoundException, IOException { if (new File(outputPath, file).isFile()) { getLogger().fine(file + " is already installed."); return; } final File outputDir = new File(outputPath); if (!outputDir.isDirectory()) { if (!outputDir.mkdirs()) { throw new IOException( "Can't create directory for binaries installation: " + outputDir.getAbsolutePath()); } outputDir.setWritable(true, false); } final String resourcePath = inputPath.toLowerCase() + "/" + file; final InputStream is = BinariesInstaller.class.getResourceAsStream(resourcePath); if (is == null) { throw new FileNotFoundException( "Unable to find the correct resource (" + resourcePath + ")"); } final File outputFile = new File(outputDir, file); OutputStream fos = FileUtils.createOutputStream(outputFile); byte[] buf = new byte[BUFFER_SIZE]; int i = 0; while ((i = is.read(buf)) != -1) { fos.write(buf, 0, i); } is.close(); fos.close(); outputFile.setExecutable(true, false); outputFile.setReadable(true, false); } /** * Install a binary bundled in the jar in a temporary directory. If no * temporary directory is defined, use the "java.io.tmpdir" property. * @param binaryFilename program to install * @param tempDir temporary directory where to install the binary * @return a string with the path of the installed binary * @throws IOException if an error occurs while installing binary */ public static String install(final String softwarePackage, final String packageVersion, final String binaryFilename, final String tempDir) throws IOException { final File tempDirFile = new File(tempDir == null ? System.getProperty("java.io.tmpdir") : tempDir.trim()); if (!tempDirFile.exists()) { throw new IOException( "Temporary directory does not exits: " + tempDirFile); } if (!tempDirFile.isDirectory()) { throw new IOException( "Temporary directory is not a directory: " + tempDirFile); } final String outputPath = tempDirFile.getAbsolutePath() + "/" + Globals.APP_NAME_LOWER_CASE + "/" + Globals.APP_VERSION_STRING + "/" + softwarePackage + "/" + packageVersion; // Test if the file is already installed if (new File(outputPath, binaryFilename).isFile()) { getLogger().info(binaryFilename + " is already installed."); return outputPath + "/" + binaryFilename; } final String os = System.getProperty("os.name").toLowerCase(); final String arch = System.getProperty("os.arch").toLowerCase(); getLogger().fine("Try to install \"" + binaryFilename + "\" of " + softwarePackage + " package for " + os + " (" + arch + ")"); // Get inputPath final String inputPath = getInputPath(softwarePackage, packageVersion); // install the file install(inputPath, binaryFilename, outputPath); getLogger().fine( "Successful installation of " + binaryFilename + " in " + outputPath); return outputPath + "/" + binaryFilename; } /** * Check if a software is available. * @param softwarePackage software name * @param packageVersion software version * @param binaryFilename software binary * @return true if the software is available */ public static boolean check(final String softwarePackage, final String packageVersion, final String binaryFilename) { try { final String inputPath = getInputPath(softwarePackage, packageVersion); final String resourcePath = inputPath.toLowerCase() + "/" + binaryFilename; final InputStream is = BinariesInstaller.class.getResourceAsStream(resourcePath); if (is == null) { return false; } is.close(); } catch (IOException e) { return false; } return true; } /** * Get the directory path of a binary. * @param softwarePackage the software package * @param packageVersion the package version * @return the directory path as a String * @throws IOException if the software is not available */ private static String getInputPath(final String softwarePackage, final String packageVersion) throws IOException { if (!SystemUtils.isUnix()) { throw new IOException("Can only install binaries on *nix systems."); } final String os = System.getProperty("os.name").toLowerCase(); final String arch = System.getProperty("os.arch").toLowerCase(); String osArchKey = os + "\t" + arch; // Bypass platform checking if necessary if (!EoulsanRuntime.getSettings().isBypassPlatformChecking()) { // Check if platform is allowed if (!Globals.AVAILABLE_BINARY_ARCH.contains(osArchKey)) { throw new FileNotFoundException( "There is no executable for your platform (" + os + ") included in " + Globals.APP_NAME); } // Change the os and arch if alias if (Globals.AVAILABLE_BINARY_ARCH_ALIAS.containsKey(osArchKey)) { osArchKey = Globals.AVAILABLE_BINARY_ARCH_ALIAS.get(osArchKey); } } return '/' + osArchKey.replace(" ", "").replace('\t', '/') + (softwarePackage == null ? "" : '/' + softwarePackage.trim()) + (packageVersion == null ? "" : '/' + packageVersion); } }