[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