Class UpdateManager

java.lang.Object
ca.corbett.updates.UpdateManager

public class UpdateManager extends Object
Applications built with swing-extras have a way of detecting if they are out of date, or if any of their currently-installed extensions are out of date. Further, applications have a way to discover new extensions, download them, and install them. This UpdateManager class helps manage this feature.

How do I use this? - Start by creating a VersionManifest for your application and all of its extensions. There is an application to help you do this! See ExtPackager on GitHub. Once your VersionManifest is ready, you can upload it to your web server. Then, you create an UpdateSources json which points to your VersionManifest, and you then bundle this UpdateSources with your application. Then, after your application is released, you can update the published VersionManifest on your web host whenever you have a new extension, or a new version of an existing extension. Your application can dynamically discover the new extension or version, and offer the ability to download and install it!

Digital signing - you can optionally digitally sign your extension jars so that your application can verify that they come from a known good source. The ExtPackager application can walk you through the process of generating a key pair, signing your extensions with the private key, and uploading the public key to your web host. This is all entirely optional - if you are hosting on a trusted internal server (like on a local network), you can skip this step entirely. If a signature and a public key are provided, this class will provide you with the signature file for each jar, and the public key that you can use for signature verification.

How do I set all this up? - There's a helper application called ExtPackager that can walk you through the process of setting up your UpdateSources json and your VersionManifest, and can also help you with things like digitally signing your extension jars, providing screenshots for each version, and uploading to your web host via FTP. You don't have to write this json by hand!

Since:
swing-extras 2.5
Author:
scorbo2
  • Field Details

    • APPLICATION_RESTART

      public static final int APPLICATION_RESTART
      The process exit code that signals to our launcher script that we want to restart the application (like after a new extension is installed). Don't change this value without also updating the launcher script! If they're not in sync, the application will simply exit without restarting.
      See Also:
    • isAutoManifestDownloadEnabled

      public static boolean isAutoManifestDownloadEnabled
      Disable this to prevent the constructor from attempting to automatically download the version manifest.
    • updateSources

      protected final UpdateSources updateSources
    • listeners

      protected final List<UpdateManagerListener> listeners
    • shutdownHooks

      protected final List<ShutdownHook> shutdownHooks
    • downloadManager

      protected final DownloadManager downloadManager
    • versionManifest

      protected VersionManifest versionManifest
  • Constructor Details

    • UpdateManager

      public UpdateManager(File sourceFile) throws com.google.gson.JsonSyntaxException, IOException
      Creates a new UpdateManager using the given update sources json file. If the file fails to parse, an exception is thrown. Otherwise, you can begin making retrieval requests with the new UpdateManager instance. Be sure to register yourself as an UpdateManagerListener before you invoke any of the retrieve methods!
      Throws:
      com.google.gson.JsonSyntaxException
      IOException
    • UpdateManager

      public UpdateManager(UpdateSources sources)
      If you have already parsed the UpdateSources instance, you can supply it to this constructor.
  • Method Details

    • getVersionManifest

      public VersionManifest getVersionManifest()
      UpdateManager will make an attempt to retrieve the VersionManifest when it is instantiated. If it succeeds, the manifest can be retrieved with this method. May return null.
    • getApplicationName

      public String getApplicationName()
      Returns the application name as defined in the update sources json that was used to instantiate this UpdateManager.
    • getUpdateSources

      public List<UpdateSources.UpdateSource> getUpdateSources()
      Returns the UpdateSources that are available in this UpdateManager. Each one can either specify a remote, web-based source, or a local filesystem-based source. The type of source is transparent to the caller, but you must specify the update source to be queried when you invoke any retrieval method.
    • isAllowSnapshots

      public boolean isAllowSnapshots()
      Reports whether SNAPSHOT versions should be shown to the user and allowed for download and installation. The default value is false, unless explicitly enabled in the UpdateSources json or via setAllowSnapshots() in this class.
    • setAllowSnapshots

      public void setAllowSnapshots(boolean allow)
      Decides whether SNAPSHOT versions should be shown to the user and allowed for download and installation. The default value is false, unless explicitly enabled in the UpdateSources json or via setAllowSnapshots() in this class.
    • addUpdateManagerListener

      public void addUpdateManagerListener(UpdateManagerListener listener)
      Register to receive notifications from this UpdateManager as various remote resources are downloaded.
    • removeUpdateManagerListener

      public void removeUpdateManagerListener(UpdateManagerListener listener)
      Stop listening to this UpdateManager for notifications.
    • retrieveVersionManifest

      public void retrieveVersionManifest(UpdateSources.UpdateSource updateSource)
      Requests the VersionManifest for the given UpdateSource (use getUpdateSources to enumerate the available UpdateSources in this UpdateManager). Make sure you have added yourself as a listener via addUpdateManagerListener() before invoking this request.
    • retrievePublicKey

      public void retrievePublicKey(UpdateSources.UpdateSource updateSource)
      Requests the public key for the given UpdateSource (use getUpdateSources to enumerate the available UpdateSources in this UpdateManager). Make sure you have added yourself as a listener via addUpdateManagerListener() before invoking this request.

      NOTE: Not all update sources will define a public key, as jar signing is optional. So, the result may be null!

    • retrieveExtensionJar

      public void retrieveExtensionJar(UpdateSources.UpdateSource updateSource, VersionManifest.ExtensionVersion extVersion)
      Requests the given extension jar from the given UpdateSource (use getUpdateSources to enumerate the available UpdateSources in this UpdateManager). Make sure you have added yourself as a listener via addUpdateManagerListener() before invoking this request.

      NOTE: Retrieving the signature file for the jar is a separate request. Note that jar signing is optional, so the signature file may or may not exist.

    • retrieveSignatureFile

      public void retrieveSignatureFile(URL signatureUrl)
      Requests the given signature file. Make sure you have added yourself as a listener via addUpdateManagerListener() before invoking this request.
    • retrieveScreenshot

      public void retrieveScreenshot(URL screenshotUrl)
      Requests the given screenshot. Make sure you have added yourself as a listener via addUpdateManagerListener() before invoking this request.
    • registerShutdownHook

      public void registerShutdownHook(ShutdownHook hook)
      Register to receive notification before the application is restarted to pick up changes caused by extensions being installed or uninstalled.
    • unregisterShutdownHook

      public void unregisterShutdownHook(ShutdownHook hook)
      You can unregister a previously registered shutdown hook.
    • restartApplication

      public void restartApplication()
      This is invoked as needed by ExtensionManager when extensions have been installed or uninstalled, and the application needs to restart to pick up the changes. If you have cleanup that needs to be done before a restart (closing open db connections, saving unsaved changes, etc), you should use registerShutdownHook so that your cleanup code can be executed before a restart!
    • executeShutdownHooks

      protected void executeShutdownHooks()
      Invoked internally by restartApplication() to execute all shutdown hooks. This is separated out from that method so that it can be unit tested.
    • showApplicationRestartPrompt

      public void showApplicationRestartPrompt(Component parent)
      Prompts the user to suggest an application restart. If the user accepts the prompt, then restartApplication() is invoked. Callers must provide the window or dialog or frame that should own the popup window.
    • showApplicationRestartPrompt

      public void showApplicationRestartPrompt(Component parent, String promptText)
      Prompts the user to suggest an application restart using the given prompt text. If the user accepts the prompt, then restartApplication() is invoked. Callers must provide the window or dialog or frame that should own the popup window.
    • fireVersionManifestDownloaded

      protected void fireVersionManifestDownloaded(URL sourceUrl, VersionManifest manifest)
    • firePublicKeyDownloaded

      protected void firePublicKeyDownloaded(URL sourceUrl, PublicKey publicKey)
    • fireJarFileDownloaded

      protected void fireJarFileDownloaded(URL sourceUrl, File jarFile)
    • fireSignatureFileDownloaded

      protected void fireSignatureFileDownloaded(URL sourceUrl, File signatureFile)
    • fireScreenshotFileDownloaded

      protected void fireScreenshotFileDownloaded(URL sourceUrl, BufferedImage screenshot)
    • fireDownloadFailed

      protected void fireDownloadFailed(URL requestedUrl, String errorMessage)
    • resolveUrl

      public static URL resolveUrl(URL base, String path)
      Given a hopefully sane base URL and some string path component, make an honest attempt to put them together into one URL. Examples:
      • resolveUrl(http://test.example, "hello"); // returns http://test.example/hello
      • resolveUrl(http://test.example/a/, "b/c.txt"); // returns http://test/example/a/b/c.txt
    • unresolveUrl

      public static String unresolveUrl(URL base, URL fullUrl)
      Provides the reverse of the resolveUrl method - that is, given a full URL and the base URl that it was created from, will return the path and file that was appended to the base URL. Examples:
      • unresolveUrl(http://test.example, http://test.example/hello); // returns "hello"
      • unresolveUrl(http://test.example/a/, http://test.example/a/b/c.txt); // returns "b/c.txt"

      Will return null if the fullUrl was not derived from the given base, or if either input is null.