02/26: ajout du module de lancement
This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository tutti. See http://git.codelutin.com/tutti.git commit 2d95c75698a260aa35e818b56796ff3b092116e6 Author: Tony CHEMIT <chemit@codelutin.com> Date: Sat Jan 3 13:39:20 2015 +0100 ajout du module de lancement --- tutti-ui-swing-launcher/LICENSE.txt | 0 tutti-ui-swing-launcher/README.txt | 0 tutti-ui-swing-launcher/pom.xml | 179 ++++++++++++++++ .../src/main/assembly/launcher.xml | 24 +++ .../tutti/ui/swing/launcher/JavaCommand.java | 163 ++++++++++++++ .../ifremer/tutti/ui/swing/launcher/Launcher.java | 236 +++++++++++++++++++++ .../ui/swing/launcher/LauncherProperties.java | 93 ++++++++ .../src/main/resources/splash.bmp | Bin 0 -> 539082 bytes .../src/main/resources/tutti.ico | Bin 0 -> 32038 bytes 9 files changed, 695 insertions(+) diff --git a/tutti-ui-swing-launcher/LICENSE.txt b/tutti-ui-swing-launcher/LICENSE.txt new file mode 100644 index 0000000..e69de29 diff --git a/tutti-ui-swing-launcher/README.txt b/tutti-ui-swing-launcher/README.txt new file mode 100644 index 0000000..e69de29 diff --git a/tutti-ui-swing-launcher/pom.xml b/tutti-ui-swing-launcher/pom.xml new file mode 100644 index 0000000..b9195e9 --- /dev/null +++ b/tutti-ui-swing-launcher/pom.xml @@ -0,0 +1,179 @@ +<!-- + #%L + Tutti :: UI Launcher + %% + Copyright (C) 2015 Ifremer + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 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 Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses />. + #L% +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>fr.ifremer</groupId> + <artifactId>tutti</artifactId> + <version>3.12-SNAPSHOT</version> + </parent> + + <groupId>fr.ifremer.tutti</groupId> + <artifactId>tutti-ui-swing-launcher</artifactId> + + <name>Tutti :: UI Launcher</name> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + + <target.fileName>tutti.exe</target.fileName> + + <!-- generate license bundled files --> + <license.generateBundle>true</license.generateBundle> + <license.bundleThirdPartyPath>META-INF/tutti-THIRD-PARTY.txt</license.bundleThirdPartyPath> + <license.bundleLicensePath>META-INF/tutti-LICENSE.txt</license.bundleLicensePath> + + </properties> + + <dependencies> + <!-- please, no dependency --> + </dependencies> + + <build> + + <plugins> + + <plugin> + <artifactId>maven-jar-plugin</artifactId> + <configuration> + <archive> + <manifest> + <addClasspath>true</addClasspath> + <mainClass>fr.ifremer.tutti.ui.swing.launcher.Launcher</mainClass> + </manifest> + </archive> + </configuration> + </plugin> + + <plugin> + <groupId>com.akathist.maven.plugins.launch4j</groupId> + <artifactId>launch4j-maven-plugin</artifactId> + <executions> + <execution> + <id>create-launcher</id> + <phase>package</phase> + <goals> + <goal>launch4j</goal> + </goals> + <configuration> + <headerType>gui</headerType> + <jar>${project.build.directory}/${project.artifactId}-${project.version}.jar</jar> + <outfile>${project.build.directory}/${target.fileName}</outfile> + <downloadUrl>http://java.com/download</downloadUrl> + <chdir>.</chdir> + <classPath> + <mainClass>fr.ifremer.tutti.ui.swing.launcher.Launcher</mainClass> + <preCp>anything</preCp> + </classPath> + <splash> + <file>src/main/resources/splash.bmp</file> + <timeout>3</timeout> + <waitForWindow>false</waitForWindow> + </splash> + <icon>src/main/resources/tutti.ico</icon> + <customProcName>true</customProcName> + <jre> + <path>jre</path> + <jdkPreference>preferJre</jdkPreference> + <maxHeapSize>20</maxHeapSize> + </jre> + <versionInfo> + <fileVersion>0.0.0.0</fileVersion> + <txtFileVersion>${project.version}</txtFileVersion> + <fileDescription>${project.name}</fileDescription> + <copyright>${project.inceptionYear} - ${project.organization.name}</copyright> + <productVersion>0.0.0.0</productVersion> + <txtProductVersion>${project.version}</txtProductVersion> + <productName>${project.parent.name}</productName> + <companyName>${project.organization.name}</companyName> + <internalName>Tutti Launcher</internalName> + <originalFilename>${target.fileName}</originalFilename> + </versionInfo> + </configuration> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>attach-artifact</goal> + </goals> + <configuration> + <artifacts> + <artifact> + <file>${project.build.directory}/${target.fileName}</file> + <type>zip</type> + <classifier>bin</classifier> + </artifact> + </artifacts> + </configuration> + </execution> + </executions> + </plugin> + + </plugins> + + </build> + + <profiles> + <profile> + <id>assembly-profile</id> + <activation> + <property> + <name>performRelease</name> + <value>true</value> + </property> + </activation> + <build> + <defaultGoal>package</defaultGoal> + <plugins> + + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>single</goal> + </goals> + <configuration> + <attach>true</attach> + <descriptors> + <descriptor>src/main/assembly/launcher.xml</descriptor> + </descriptors> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + </profiles> +</project> + diff --git a/tutti-ui-swing-launcher/src/main/assembly/launcher.xml b/tutti-ui-swing-launcher/src/main/assembly/launcher.xml new file mode 100644 index 0000000..acfabc7 --- /dev/null +++ b/tutti-ui-swing-launcher/src/main/assembly/launcher.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<assembly + xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd"> + <id>bin</id> + + <formats> + <format>zip</format> + </formats> + + <fileSets> + + <fileSet> + <directory>target</directory> + <outputDirectory/> + <includes> + <include>${target.fileName}</include> + </includes> + </fileSet> + + </fileSets> +</assembly> diff --git a/tutti-ui-swing-launcher/src/main/java/fr/ifremer/tutti/ui/swing/launcher/JavaCommand.java b/tutti-ui-swing-launcher/src/main/java/fr/ifremer/tutti/ui/swing/launcher/JavaCommand.java new file mode 100644 index 0000000..267ba3d --- /dev/null +++ b/tutti-ui-swing-launcher/src/main/java/fr/ifremer/tutti/ui/swing/launcher/JavaCommand.java @@ -0,0 +1,163 @@ +package fr.ifremer.tutti.ui.swing.launcher; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * Created on 1/3/15. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 3.12 + */ +public class JavaCommand { + + private static final String DEBUG_JAVA_OPTS = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=%s"; + + static JavaCommand create(Path basedir, int debugPort) { + return new JavaCommand(basedir, debugPort); + } + + static JavaCommand create(Path basedir) { + return new JavaCommand(basedir, 8000); + } + + protected JavaCommand(Path javaCommand, int debugPort) { + this.javaCommand = javaCommand; + this.debugPort = debugPort; + this.preJarArguments = new ArrayList<>(); + this.postJarArguments = new ArrayList<>(); + } + + private final int debugPort; + + private final Path javaCommand; + + private final List<String> preJarArguments; + + private final List<String> postJarArguments; + + private Path jarPath; + + private boolean inheritIO; + + private boolean debug; + + private Path logFile; + + public JavaCommand setInheritIO(boolean inheritIO) { + this.inheritIO = inheritIO; + return this; + } + + public JavaCommand setDebug(boolean debug) { + this.debug = debug; + return this; + } + + public JavaCommand setJarPath(Path jarPath) { + this.jarPath = jarPath; + return this; + } + + public JavaCommand setLogFile(Path logFile) { + this.logFile = logFile; + return this; + } + + public JavaCommand addArgument(Object argument) { + + List<String> whereToAdd; + if (jarPath == null) { + whereToAdd = preJarArguments; + + } else { + whereToAdd = postJarArguments; + } + + whereToAdd.add(argument.toString()); + + return this; + } + + public JavaCommand addArguments(Object argument, Object... arguments) { + + List<String> whereToAdd; + if (jarPath == null) { + whereToAdd = preJarArguments; + + } else { + whereToAdd = postJarArguments; + } + + whereToAdd.add(argument.toString()); + + for (Object argument1 : arguments) { + whereToAdd.add(argument1.toString()); + } + + return this; + } + + public JavaCommand addArguments(Collection<?> arguments) { + + List<String> whereToAdd; + if (jarPath == null) { + whereToAdd = preJarArguments; + + } else { + whereToAdd = postJarArguments; + } + + for (Object argument : arguments) { + whereToAdd.add(argument.toString()); + } + + return this; + } + + public Launcher.ExitCode execute() throws IOException, InterruptedException { + + if (jarPath == null) { + + throw new IllegalStateException("No jarPath given, can't execute."); + + } + + List<String> command = new ArrayList<>(); + + command.add(javaCommand.toString()); + command.addAll(preJarArguments); + if (debug) { + command.add(String.format(DEBUG_JAVA_OPTS, debugPort)); + } + command.add("-jar"); + command.add(jarPath.toString()); + command.addAll(postJarArguments); + + ProcessBuilder pb = new ProcessBuilder(command); + + if (inheritIO) { + + pb.inheritIO(); + + } + + if (logFile != null) { + + File updaterLogFile = logFile.toFile(); + pb.redirectOutput(ProcessBuilder.Redirect.to(updaterLogFile)); + pb.redirectError(ProcessBuilder.Redirect.appendTo(updaterLogFile)); + + } + + System.out.println("Starts java command: " + command); + + int exitCode = pb.start().waitFor(); + return Launcher.ExitCode.valueOf(exitCode); + + } +} diff --git a/tutti-ui-swing-launcher/src/main/java/fr/ifremer/tutti/ui/swing/launcher/Launcher.java b/tutti-ui-swing-launcher/src/main/java/fr/ifremer/tutti/ui/swing/launcher/Launcher.java new file mode 100644 index 0000000..7d57934 --- /dev/null +++ b/tutti-ui-swing-launcher/src/main/java/fr/ifremer/tutti/ui/swing/launcher/Launcher.java @@ -0,0 +1,236 @@ +package fr.ifremer.tutti.ui.swing.launcher; + +import javax.swing.JOptionPane; +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.StandardCopyOption; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * Launcher application that do post-update logic, launch application and listen to exit code. + * + * @author Tony Chemit (chemit@codelutin.com) + * @since 3.12 + */ +public class Launcher { + + public static final String APPLICATION_LANCHER_TITLE = "Tutti UI Launcher"; + + public static final String APPLICATION_DIR = "tutti"; + + public static final String DATA_DIR = "data"; + + public static final String UPDATER_JAR = "updater.jar"; + + public static final String UPDATER_LOGFILE = "updater.log"; + + public static final String FULL_LAUNCH_MODE = "full"; + + public static final String DEBUG_ARG = "--debug"; + + private final Path basedir; + + private final List<String> arguments; + + private final Path javaCommand; + + private final boolean debugMode; + + public static void main(String... args) { + + boolean windowsOs = System.getProperty("os.name").startsWith("Windows"); + + String javaCommandFilename = windowsOs ? "java.exe" : "java"; + + Launcher launcher = new Launcher(javaCommandFilename, args); + launcher.execute(); + + } + + public Launcher(String javaCommandFilename, String... args) { + + this.basedir = Paths.get(System.getProperty("user.dir")); + + this.javaCommand = basedir.resolve("jre").resolve("bin").resolve(javaCommandFilename); + + List<String> fullArguments = Arrays.asList(args); + + this.debugMode = fullArguments.remove(DEBUG_ARG); + + this.arguments = Collections.unmodifiableList(fullArguments); + + } + + public void execute() { + + try { + + ExitCode exitCode; + + do { + + // call update process + exitCode = executeUpdate(); + + if (exitCode == ExitCode.RUNTIME_UPDATE) { + + // if updater has detected runtime update, stop now + System.exit(exitCode.getExitCode()); + + } + + if (exitCode != ExitCode.NORMAL) { + + // update fails + throw new RuntimeException("Tutti Updater has encountered a problem, program stopped.\nPlease check " + UPDATER_LOGFILE); + + } + + // launch application + exitCode = executeApplication(); + + if (exitCode == ExitCode.DELETE_DB) { + deleteDb(); + } + + } while (exitCode.isRelaunch()); + + if (exitCode != ExitCode.NORMAL) { + + // show exit code + throw new RuntimeException("exit code = " + exitCode); + + } + + } catch (Exception ex) { + JOptionPane.showMessageDialog(null, ex.toString(), APPLICATION_LANCHER_TITLE, JOptionPane.ERROR_MESSAGE); + } + + } + + protected ExitCode executeUpdate() throws Exception { + + Path updatePath = basedir.resolve(APPLICATION_DIR).resolve(UPDATER_JAR); + Path updateExecPath = basedir.resolve(UPDATER_JAR); + Files.copy(updatePath, updateExecPath, StandardCopyOption.REPLACE_EXISTING); + + Path logfile = basedir.resolve(UPDATER_LOGFILE); + + try { + + JavaCommand program = JavaCommand + .create(javaCommand) + .setJarPath(updateExecPath) + .setLogFile(logfile); + + ExitCode exitCode = program.execute(); + return exitCode; + + } finally { + + Files.delete(updateExecPath); + + } + + } + + protected ExitCode executeApplication() throws Exception { + + LauncherProperties launcherProperties = new LauncherProperties(basedir); + launcherProperties.load(); + + JavaCommand program = JavaCommand + .create(javaCommand) + .setDebug(debugMode) + .setInheritIO(true) + .addArguments(launcherProperties.getJavaOptions()) + .addArgument("-Dtutti.log.file=" + launcherProperties.getLogFile().toString()) + .setJarPath(launcherProperties.getJarFile()) + .addArguments("--launch-mode", FULL_LAUNCH_MODE) + .addArguments("--basedir", basedir.toString()) +// .addArgument("--config.path", basedir.toString()) + .addArgument(arguments); + + ExitCode exitCode = program.execute(); + return exitCode; + + } + + protected void deleteDb() throws Exception { + + Path dataPath = basedir.resolve(DATA_DIR); + Files.walkFileTree(dataPath.resolve("db"), new RecursiveDeleteFileVisitor()); + Files.walkFileTree(dataPath.resolve("dbcache"), new RecursiveDeleteFileVisitor()); + Files.walkFileTree(dataPath.resolve("dbconf"), new RecursiveDeleteFileVisitor()); + + } + + private class RecursiveDeleteFileVisitor extends SimpleFileVisitor<Path> { + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + Files.deleteIfExists(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + Files.deleteIfExists(dir); + return FileVisitResult.CONTINUE; + } + + } + + /** + * Created on 1/3/15. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 3.12 + */ + public static enum ExitCode { + + NORMAL(0, false), // Normal exist code, always quit program + UPDATE(88, true), // When an update was found, will relaunch application + DELETE_DB(89, true), // When a db deletion is required, will relaunch application + RUNTIME_UPDATE(90, false), // When a runtime update found, quit program to update runtime + UNKNOWN(-1, false); // For any other exit code, will always quit program + + private final int exitCode; + + private final boolean relaunch; + + ExitCode(int exitCode, boolean relaunch) { + this.exitCode = exitCode; + this.relaunch = relaunch; + } + + public int getExitCode() { + return exitCode; + } + + public boolean isRelaunch() { + return relaunch; + } + + public static ExitCode valueOf(int code) { + + ExitCode result = UNKNOWN; + + for (ExitCode exitCode : ExitCode.values()) { + if (code == exitCode.getExitCode()) { + result = exitCode; + } + } + + return result; + + } + } +} diff --git a/tutti-ui-swing-launcher/src/main/java/fr/ifremer/tutti/ui/swing/launcher/LauncherProperties.java b/tutti-ui-swing-launcher/src/main/java/fr/ifremer/tutti/ui/swing/launcher/LauncherProperties.java new file mode 100644 index 0000000..e0a3a88 --- /dev/null +++ b/tutti-ui-swing-launcher/src/main/java/fr/ifremer/tutti/ui/swing/launcher/LauncherProperties.java @@ -0,0 +1,93 @@ +package fr.ifremer.tutti.ui.swing.launcher; + +import java.io.FileReader; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +/** + * Created on 1/3/15. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 3.12 + */ +public class LauncherProperties { + + public static final String LAUNCHER_PROPERTIES = "launcher.properties"; + + public static final String LAUNCHER_PROPERTIES_JAR = "JAR"; + + public static final String LAUNCHER_PROPERTIES_LOGFILE = "LOGFILE"; + + public static final String LAUNCHER_PROPERTIES_JAVA_OPTS = "JAVA_OPTS"; + + private final Path basedir; + + Properties launcherProperties; + + public LauncherProperties(Path basedir) { + this.basedir = basedir; + } + + public void load() throws IOException { + + // application launcher properties + Path applicationFile = basedir.resolve(Launcher.APPLICATION_DIR).resolve(LAUNCHER_PROPERTIES); + // local launcher properties + Path localFile = basedir.resolve(LAUNCHER_PROPERTIES); + + if (!(Files.exists(localFile) || Files.exists(applicationFile))) { + + throw new IOException("Could not find " + LAUNCHER_PROPERTIES); + + } + + Properties p1 = new Properties(); + if (Files.isReadable(applicationFile)) { + p1.load(new FileReader(applicationFile.toFile())); + } + + launcherProperties = new Properties(p1); + if (Files.isReadable(localFile)) { + launcherProperties.load(new FileReader(localFile.toFile())); + } + } + + public Path getJarFile() { + + String jarFileName = launcherProperties.getProperty(LAUNCHER_PROPERTIES_JAR); + Path jarFile = basedir.resolve(jarFileName); + return jarFile; + + } + + public Path getLogFile() { + + String logFileName = launcherProperties.getProperty(LAUNCHER_PROPERTIES_LOGFILE); + Path logFile = basedir.resolve(logFileName); + return logFile; + + } + + public List<String> getJavaOptions() { + + List<String> javaOptions = new ArrayList<>(); + String javaOpts = launcherProperties.getProperty(LAUNCHER_PROPERTIES_JAVA_OPTS); + if (!(javaOpts == null || javaOpts.trim().isEmpty())) { + String[] javaOptsArray = javaOpts.replaceAll("\"", "").split(" "); + for (String opt : javaOptsArray) { + if (!(opt == null || opt.trim().isEmpty())) { + javaOptions.add(opt); + } + } + } + + return javaOptions; + + } + + +} diff --git a/tutti-ui-swing-launcher/src/main/resources/splash.bmp b/tutti-ui-swing-launcher/src/main/resources/splash.bmp new file mode 100644 index 0000000..3d197f4 Binary files /dev/null and b/tutti-ui-swing-launcher/src/main/resources/splash.bmp differ diff --git a/tutti-ui-swing-launcher/src/main/resources/tutti.ico b/tutti-ui-swing-launcher/src/main/resources/tutti.ico new file mode 100644 index 0000000..3b36647 Binary files /dev/null and b/tutti-ui-swing-launcher/src/main/resources/tutti.ico differ -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.
participants (1)
-
codelutin.com scm