[Schmitzm-commits] r2338 - in trunk/schmitzm-core/src/main: java/de/schmitzm/io java/de/schmitzm/versionnumber resources/de/schmitzm/io/resource/locales

scm-commit at wald.intevation.org scm-commit at wald.intevation.org
Sun Jun 9 21:20:27 CEST 2013


Author: mojays
Date: 2013-06-09 21:20:27 +0200 (Sun, 09 Jun 2013)
New Revision: 2338

Added:
   trunk/schmitzm-core/src/main/java/de/schmitzm/versionnumber/ApplicationUpdater.java
Modified:
   trunk/schmitzm-core/src/main/java/de/schmitzm/io/IOUtil.java
   trunk/schmitzm-core/src/main/java/de/schmitzm/versionnumber/ReleaseUpdater.java
   trunk/schmitzm-core/src/main/resources/de/schmitzm/io/resource/locales/IOResourceBundle.properties
   trunk/schmitzm-core/src/main/resources/de/schmitzm/io/resource/locales/IOResourceBundle_de.properties
Log:
ReleaseUpdater: internationalization
ApplicationUpdater: new utility class to perform automatic update

Modified: trunk/schmitzm-core/src/main/java/de/schmitzm/io/IOUtil.java
===================================================================
--- trunk/schmitzm-core/src/main/java/de/schmitzm/io/IOUtil.java	2013-06-09 17:14:36 UTC (rev 2337)
+++ trunk/schmitzm-core/src/main/java/de/schmitzm/io/IOUtil.java	2013-06-09 19:20:27 UTC (rev 2338)
@@ -2738,6 +2738,7 @@
       }
       // no main method (anymore) for no running thread
       // -> starting class can not be determined anymore :-(
+      LOGGER.warn("Application main class can not be determined! Maybe method was called before main class was instantiated completely.");
       return null;
     }
 

Added: trunk/schmitzm-core/src/main/java/de/schmitzm/versionnumber/ApplicationUpdater.java
===================================================================
--- trunk/schmitzm-core/src/main/java/de/schmitzm/versionnumber/ApplicationUpdater.java	                        (rev 0)
+++ trunk/schmitzm-core/src/main/java/de/schmitzm/versionnumber/ApplicationUpdater.java	2013-06-09 19:20:27 UTC (rev 2338)
@@ -0,0 +1,204 @@
+/**
+ * Copyright (c) 2009 Martin O. J. Schmitz.
+ * 
+ * This file is part of the SCHMITZM library - a collection of utility 
+ * classes based on Java 1.6, focusing (not only) on Java Swing 
+ * and the Geotools library.
+ * 
+ * The SCHMITZM project is hosted at:
+ * http://wald.intevation.org/projects/schmitzm/
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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 Lesser General Public License (license.txt)
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ * or try this link: http://www.gnu.org/licenses/lgpl.html
+ * 
+ * Contributors:
+ *     Martin O. J. Schmitz - initial API and implementation
+ *     Stefan A. Tzeggai - additional utility classes
+ */
+package de.schmitzm.versionnumber;
+
+import java.awt.Frame;
+import java.io.File;
+import java.io.IOException;
+
+import javax.swing.JOptionPane;
+
+import org.apache.log4j.Logger;
+
+import de.schmitzm.io.IOUtil;
+import de.schmitzm.io.IOUtilBasic;
+import de.schmitzm.lang.LangUtil;
+import de.schmitzm.swing.Disposable;
+import de.schmitzm.swing.ExceptionDialog;
+import de.schmitzm.swing.SwingUtil;
+
+/**
+ * While the {@link ReleaseUpdater} only checks for updates and downloads the files,
+ * the {@link ApplicationUpdater} performs the complete update process, including the
+ * copy/override of the local application file(s).<br>
+ * For this purpose an additional JAR file ({@code updater.jar}) has to be available
+ * on the update server in the same directory as the application file, which is used to
+ * perform the copy/move and application restart commands on the file system.
+ * The {@code updater.jar} especially has to include the class {@link IOUtilBasic} (e.g.
+ * simple JAR of schmitzm-core project).
+ * 
+ * @author Martin O.J. Schmitz
+ */
+public class ApplicationUpdater {
+  protected Logger LOGGER = LangUtil.createLogger(ApplicationUpdater.class);
+  
+  /** Local application file of the running application. {@code null} if application was
+   *  started from class path (and not from JAR or EXE)! */
+  public static final File    APPL_FILE = IOUtil.getApplicationFile();
+  /** Complete command to (re)start the application. */
+  public static final String  APPL_RESTART_COMMAND = IOUtil.createApplicationStartCommand(true);
+
+  /** Holds the release updater to check for updates and download the file. */
+  protected ReleaseUpdater releaseUpdater;
+  /** Name of {@code updater.jar} file on the server (has to be located in the same server
+   *  directory as the application file). */
+  protected String applUpdaterFilename;
+
+
+  /**
+   * Creates application updater.
+   * @param releaseUpdater {@link ReleaseUpdater} used to check for application updates
+   * @param applUpdaterFilename name of {@code updater.jar} file on the server (has to be
+   *                            located in the same server directory as the application file)
+   */
+  public ApplicationUpdater(ReleaseUpdater releaseUpdater, String applUpdaterFilename) {
+    this.releaseUpdater = releaseUpdater;
+    this.applUpdaterFilename = applUpdaterFilename;
+  }
+
+
+  /**
+   * Checks for application update on server and (if necessary) performs the update.
+   * During this process several user interaction dialogs may pop up.
+   * @param dialogParent parent frame for messages and dialogs
+   * @param showNoUpdateMess indicates whether message is shown if no update is available
+   * @param ignoreCheckExceptions indicates whether exceptions on initial update check are
+   *                              ignored (this may be useful on automatic update check when
+   *                              application starts)
+   * @param applToExit {@link Disposable} (this application) to exit during update process (if {@code null}
+   *                   a {@link System#exit(int)} is performed!)
+   */
+  public void performApplicationUpdate(final Frame dialogParent, boolean showNoUpdateMess, boolean ignoreCheckExceptions, Disposable applToExit) {
+    try {
+//    JOptionPane.showMessageDialog(dialogParent, "1) APPL_STARTED_FROM_EXE = "+HibernateSessionFactory.APPL_STARTED_FROM_EXE);
+//    JOptionPane.showMessageDialog(dialogParent, "2) REMOTE_APPL_FILENAME = "+HibernateSessionFactory.REMOTE_APPL_FILENAME);
+//    JOptionPane.showMessageDialog(dialogParent, "3) APPL_FILE = "+HibernateSessionFactory.APPL_FILE);
+//    JOptionPane.showMessageDialog(dialogParent, "9) APPL_RESTART_COMMAND = "+HibernateSessionFactory.APPL_RESTART_COMMAND);
+//    JOptionPane.showMessageDialog(dialogParent, "6) getApplicationFile() = "+IOUtil.getApplicationFile());
+//    JOptionPane.showMessageDialog(dialogParent, "7) getApplicationFilename() = "+IOUtil.getApplicationFilename());
+//    JOptionPane.showMessageDialog(dialogParent, "8) getApplicationFilepath() = "+IOUtil.getApplicationFilepath());
+//    JOptionPane.showMessageDialog(dialogParent, "9) getApplicationCommand(false) = "+IOUtil.getApplicationCommand(false));
+
+    // If application is running from classpath (e.g. Eclipse) HibernateSessionFactory.APPL_FILE
+    // is NULL, because there is none.
+    // Normally the update procedure should be rejected! BUT for development cases (running from Eclipse)
+    // we pretend that application was started from JAR.
+    File applFile = APPL_FILE;
+    if ( applFile == null ) {
+      if ( !ignoreCheckExceptions )
+        JOptionPane.showMessageDialog(dialogParent,
+                                      IOUtil.R("ApplicationUpdater.err.update.not.available"),
+                                      IOUtil.R("ApplicationUpdater.appl.update.title"), 
+                                      JOptionPane.ERROR_MESSAGE);
+      return;
+//      applFile = new File(IOUtil.getApplicationDirectory(), HibernateSessionFactory.REMOTE_APPL_FILENAME);
+    }
+    
+    // DOWNLOAD FILES TO TEMP DIRECTORY
+    // application file as ".update" to application directory (renamed later)
+    // updater file to temporary folder
+    File downloadFile = null;
+    File updaterFile  = null;
+    try { 
+      downloadFile = IOUtil.createTemporaryFile(applFile.getParentFile(),
+                                                releaseUpdater.getApplicationFileName()+".update-",
+                                                null,
+                                                true);
+      downloadFile.delete(); // avoid that file remains in application directory if update is rejected by user!
+      updaterFile  = IOUtil.createTemporaryFile(applUpdaterFilename+"-",null,true);
+    } catch (IOException err) {
+      if ( ignoreCheckExceptions )
+        return;
+      throw new IOException(IOUtil.R("ApplicationUpdater.err.download.tempfile",
+                                     err.getMessage(),
+                                     applFile.getParentFile()),
+                            err);
+    }
+    File retFile = SwingUtil.performReleaseUpdateWithProgressBar(dialogParent,
+                                                                 releaseUpdater,
+                                                                 downloadFile,
+                                                                 true,
+                                                                 showNoUpdateMess,
+                                                                 applUpdaterFilename,
+                                                                 updaterFile);
+    if ( retFile == null )
+      return;
+    
+    // USE UPDATER TO MOVE/RENAME APPLICATION FILE AND RESTART WIMECRM
+    if ( !updaterFile.exists() || updaterFile.length() < 10000 )
+      throw new UnsupportedOperationException(IOUtil.R("ApplicationUpdater.err.updater.not.exist", applUpdaterFilename));
+    int ret = JOptionPane.showConfirmDialog(dialogParent,
+                                            IOUtil.R("ApplicationUpdater.restart.request.mess"),
+                                            IOUtil.R("ApplicationUpdater.restart.request.title"),
+                                            JOptionPane.OK_CANCEL_OPTION,
+                                            JOptionPane.QUESTION_MESSAGE);
+    if ( ret != JOptionPane.OK_OPTION ) {
+      JOptionPane.showMessageDialog(dialogParent,
+                                    IOUtil.R("ApplicationUpdater.restart.canceled.mess"),
+                                    IOUtil.R("ApplicationUpdater.restart.canceled.title"),
+                                    JOptionPane.QUESTION_MESSAGE);
+      return;
+    }
+    
+    // Rename temporary files to permanent
+    String downloadFilenamePermanent = releaseUpdater.getApplicationFileName()
+                                     + ".update"
+                                     + ".r"+releaseUpdater.getLastestBuild();
+    downloadFile = IOUtil.renameFile(downloadFile, downloadFilenamePermanent, true);
+    updaterFile  = IOUtil.renameFile(updaterFile, applUpdaterFilename, true);
+    
+    // Updater-Command um wimecrem.exe ins Zielverzeichnis zu kopieren
+    File destFile = applFile;
+    String moveCmd = LangUtil.replaceParameters("java -cp ${0} ${1} MOVE ${2} ${3} 2000",
+                                            "\""+updaterFile.getAbsolutePath()+"\"",
+                                            IOUtilBasic.class.getName(),
+                                            "\""+downloadFile.getAbsoluteFile()+"\"",
+                                            "\""+destFile.getAbsoluteFile()+"\"");
+    // Updater-Command um wimecrem.exe neu zu starten
+    String restartCommand = APPL_RESTART_COMMAND;
+    String restartCmd = LangUtil.replaceParameters("java -cp ${0} ${1} EXEC 4000 ${2}",
+                                                   "\""+updaterFile.getAbsolutePath()+"\"",
+                                                   IOUtilBasic.class.getName(),
+                                                   restartCommand);
+    // Execute commands (with delay) and terminate WIME crm
+    LOGGER.debug("exec: "+moveCmd);
+    LOGGER.debug("exec: "+restartCmd);
+    Runtime.getRuntime().exec( moveCmd );
+    Runtime.getRuntime().exec( restartCmd );
+    if ( applToExit != null )
+      applToExit.dispose();
+    else
+      System.exit(0);
+  } catch (Exception err) {
+    ExceptionDialog.show(dialogParent, err, IOUtil.R("ApplicationUpdater.err.title"), null);
+  }
+
+  }
+}

Modified: trunk/schmitzm-core/src/main/java/de/schmitzm/versionnumber/ReleaseUpdater.java
===================================================================
--- trunk/schmitzm-core/src/main/java/de/schmitzm/versionnumber/ReleaseUpdater.java	2013-06-09 17:14:36 UTC (rev 2337)
+++ trunk/schmitzm-core/src/main/java/de/schmitzm/versionnumber/ReleaseUpdater.java	2013-06-09 19:20:27 UTC (rev 2338)
@@ -188,7 +188,7 @@
       String latestApplBuildStr = getLastestBuild();
       long latestApplBuild = parseLong(latestApplBuildStr);
       if ( latestApplBuild <= 0 )
-        throw new IOException("No release build can be determined. Can not check for release update!");
+        throw new IOException(IOUtil.R("ReleaseUpdater.err.latest.release"));
       String baseFileName = IOUtil.getBaseFileName(fileName);
       String fileExt = IOUtil.getFileExt(fileName, true);
       fileName = baseFileName + "-" + latestApplBuild + fileExt;
@@ -263,12 +263,12 @@
     String currApplBuildStr = ReleaseUtil.getVersionBuild(releaseClass);
     long currApplBuild = parseLong(currApplBuildStr);
     if ( currApplBuild <= 0 )
-      throw new IOException("No release build set for running application. Can not check for release update!");
+      throw new IOException(IOUtil.R("ReleaseUpdater.err.no.release.local"));
     // determine build of latest version
     String latestApplBuildStr = determineLastestBuild();
     long latestApplBuild = parseLong(latestApplBuildStr);
     if ( latestApplBuild <= 0 )
-      throw new IOException("No release build can be determined. Can not check for release update!");
+      throw new IOException(IOUtil.R("ReleaseUpdater.err.no.release.remote"));
     // check whether latest build is newer than build of running application
     return latestApplBuild > currApplBuild;
   }

Modified: trunk/schmitzm-core/src/main/resources/de/schmitzm/io/resource/locales/IOResourceBundle.properties
===================================================================
--- trunk/schmitzm-core/src/main/resources/de/schmitzm/io/resource/locales/IOResourceBundle.properties	2013-06-09 17:14:36 UTC (rev 2337)
+++ trunk/schmitzm-core/src/main/resources/de/schmitzm/io/resource/locales/IOResourceBundle.properties	2013-06-09 19:20:27 UTC (rev 2338)
@@ -38,3 +38,17 @@
 IOUtil.downloadUrlToFile.err.local.file=Download file can not be saved (locally): ${0}
 IOUtil.downloadUrlToFile.err.remote.file=Download file can not be accessed on server: ${0}
 IOUtil.downloadUrlToFile.err.unknown.host=Download server is not available: ${0}
+
+ReleaseUpdater.err.latest.release=No release build can be determined. Can not check for release update!
+ReleaseUpdater.err.no.release.local=No release build set for running application. Can not check for release update!
+ReleaseUpdater.err.no.release.remote=No release build can be determined on server. Can not check for release update!
+
+ApplicationUpdater.appl.update.title=Application update
+ApplicationUpdater.err.title=Error during application update
+ApplicationUpdater.err.update.not.available=Application was not started locally (JAR or EXE), but via WebStart or Classpath.\nAutomatical application update is not availabe!
+ApplicationUpdater.err.download.tempfile=The temporary download file can not be created locally: ${0}\nMaybe because of missing write access in application directory ${1} 
+ApplicationUpdater.err.updater.not.exist=The necessary utility program ${0} can not be found on update server!
+ApplicationUpdater.restart.request.mess=The update was downloaded successfully. The application has to be terminated NOW to complete the update.\nThe application should restart automatically within some seconds...
+ApplicationUpdater.restart.request.title=Finish application update
+ApplicationUpdater.restart.canceled.mess=The application update was not completed. It has to be proceeded completely again to apply the update!
+ApplicationUpdater.restart.canceled.title=Application update canceled

Modified: trunk/schmitzm-core/src/main/resources/de/schmitzm/io/resource/locales/IOResourceBundle_de.properties
===================================================================
--- trunk/schmitzm-core/src/main/resources/de/schmitzm/io/resource/locales/IOResourceBundle_de.properties	2013-06-09 17:14:36 UTC (rev 2337)
+++ trunk/schmitzm-core/src/main/resources/de/schmitzm/io/resource/locales/IOResourceBundle_de.properties	2013-06-09 19:20:27 UTC (rev 2338)
@@ -38,3 +38,17 @@
 IOUtil.downloadUrlToFile.err.local.file=Die Download-Datei kann (lokal) nicht gespeichert werden ${0}
 IOUtil.downloadUrlToFile.err.remote.file=Die Datei kann nicht vom Server geladen werden: ${0}
 IOUtil.downloadUrlToFile.err.unknown.host=Der Download-Server ist nicht erreichbar: ${0}
+
+ReleaseUpdater.err.latest.release=Neuste Programm-Version kann (auf dem Server) nicht ermittelt werden. Update-Check kann nicht vorgenommen werden!
+ReleaseUpdater.err.no.release.local=F\ufffdr das laufende Programm ist keine Versionsnummer hinterlegt. Update-Check kann nicht vorgenommen werden!
+ReleaseUpdater.err.no.release.remote=Neuste Programm-Version kann (auf dem Server) nicht ermittelt werden. Update-Check kann nicht vorgenommen werden!
+
+ApplicationUpdater.appl.update.title=Programm-Update
+ApplicationUpdater.err.title=Fehler beim Programm-Update
+ApplicationUpdater.err.update.not.available=Das Programm wurde nicht lokal gestartet (JAR oder EXE), sondern \ufffdber WebStart oder Classpath.\nEin automatisches Update kann nicht vorgenommen werden!
+ApplicationUpdater.err.download.tempfile=Die tempor\ufffdre Datei f\ufffdr den Download kann nicht angelegt werden: ${0}\nUnter Umst\ufffdnden besteht kein Schreibrecht auf dem Programmverzeichnis ${1} 
+ApplicationUpdater.err.updater.not.exist=Das erforderliche Hilfs-Programm ${0} kann auf dem Server nicht gefunden werden!
+ApplicationUpdater.restart.request.mess=Das Update wurde erfolgreich herunter geladen. Die Anwendung muss JETZT geschlossen werden, um das Update abzuschliessen.\nDas Programm sollte in wenigen Sekunden automatisch neu starten...
+ApplicationUpdater.restart.request.title=Programm-Update abschliessen
+ApplicationUpdater.restart.canceled.mess=Das Update wurde nicht abgeschlossen. Es muss ggf. nochmals komplett durchgef\ufffdhrt werden!
+ApplicationUpdater.restart.canceled.title=Programm-Update abgebrochen



More information about the Schmitzm-commits mailing list