aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLyubomir Marinov <lyubomir.marinov@jitsi.org>2013-06-30 19:48:31 +0300
committerLyubomir Marinov <lyubomir.marinov@jitsi.org>2013-06-30 19:48:31 +0300
commitf7f58da22029c7a07397856a700760118d30c1aa (patch)
treef5a6ea0872a0915b0d5e228c81f64f1bc5db54e5
parent6b8ee2fa6fc742755fdf449d73d7bb0a4627de0e (diff)
downloadjitsi-f7f58da22029c7a07397856a700760118d30c1aa.zip
jitsi-f7f58da22029c7a07397856a700760118d30c1aa.tar.gz
jitsi-f7f58da22029c7a07397856a700760118d30c1aa.tar.bz2
Makes it easier to switch to an alaternative Web browser in the 'New version is available' dialog on Windows.
-rw-r--r--src/net/java/sip/communicator/plugin/update/CheckForUpdatesMenuItemComponent.java17
-rw-r--r--src/net/java/sip/communicator/plugin/update/Update.java1084
-rw-r--r--src/net/java/sip/communicator/plugin/update/UpdateActivator.java2
-rw-r--r--src/net/java/sip/communicator/plugin/update/UpdateServiceImpl.java74
4 files changed, 62 insertions, 1115 deletions
diff --git a/src/net/java/sip/communicator/plugin/update/CheckForUpdatesMenuItemComponent.java b/src/net/java/sip/communicator/plugin/update/CheckForUpdatesMenuItemComponent.java
index 5361165..87b0b8e 100644
--- a/src/net/java/sip/communicator/plugin/update/CheckForUpdatesMenuItemComponent.java
+++ b/src/net/java/sip/communicator/plugin/update/CheckForUpdatesMenuItemComponent.java
@@ -51,15 +51,16 @@ public class CheckForUpdatesMenuItemComponent
= new JMenuItem(
Resources.getResources().getI18NString(
"plugin.updatechecker.UPDATE_MENU_ENTRY"));
- checkForUpdatesMenuItem.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- UpdateActivator.getUpdateService().checkForUpdates(true);
- }
- });
+ checkForUpdatesMenuItem.addActionListener(
+ new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ UpdateActivator.getUpdateService().checkForUpdates(
+ true);
+ }
+ });
}
-
return checkForUpdatesMenuItem;
}
diff --git a/src/net/java/sip/communicator/plugin/update/Update.java b/src/net/java/sip/communicator/plugin/update/Update.java
deleted file mode 100644
index 5a7e23b..0000000
--- a/src/net/java/sip/communicator/plugin/update/Update.java
+++ /dev/null
@@ -1,1084 +0,0 @@
-/*
- * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package net.java.sip.communicator.plugin.update;
-
-import java.awt.*;
-import java.awt.event.*;
-import java.io.*;
-import java.net.*;
-import java.util.*;
-import java.util.List;
-
-import javax.swing.*;
-import javax.swing.text.*;
-
-import net.java.sip.communicator.service.gui.*;
-import net.java.sip.communicator.service.httputil.*;
-import net.java.sip.communicator.service.update.*;
-import net.java.sip.communicator.util.*;
-import net.java.sip.communicator.util.Logger;
-import net.java.sip.communicator.plugin.desktoputil.*;
-
-import org.jitsi.service.resources.*;
-import org.jitsi.service.version.*;
-import org.jitsi.util.*;
-// disambiguation
-
-/**
- * Implements checking for software updates, downloading and applying them i.e.
- * the very logic of the update plug-in.
- *
- * @author Damian Minkov
- * @author Lyubomir Marinov
- */
-public class Update
- implements UpdateService
-{
- /**
- * The <tt>Logger</tt> used by the <tt>Update</tt> class for logging output.
- */
- private static final Logger logger = Logger.getLogger(Update.class);
-
- /**
- * The name of the property which specifies the update link in the
- * configuration file.
- */
- private static final String PROP_UPDATE_LINK
- = "net.java.sip.communicator.UPDATE_LINK";
-
- /**
- * The link pointing to the ChangeLog of the update.
- */
- private static String changesLink;
-
- /**
- * The <tt>JDialog</tt>, if any, which is associated with the currently
- * executing "Check for Updates". While the "Check for Updates"
- * functionality cannot be entered, clicking the "Check for Updates" menu
- * item will bring it to the front.
- */
- private static JDialog checkForUpdatesDialog;
-
- /**
- * The link pointing at the download of the update.
- */
- private static String downloadLink;
-
- /**
- * The indicator/counter which determines how many methods are currently
- * executing the "Check for Updates" functionality so that it is known
- * whether it can be entered.
- */
- private static int inCheckForUpdates = 0;
-
- /**
- * The latest version of the software found at the configured update
- * location.
- */
- private static String latestVersion;
-
- /**
- * Invokes "Check for Updates".
- *
- * @param notifyAboutNewestVersion <tt>true</tt> if the user is to be
- * notified if they have the newest version already; otherwise,
- * <tt>false</tt>
- */
- public synchronized void checkForUpdates(
- final boolean notifyAboutNewestVersion)
- {
- if (inCheckForUpdates > 0)
- {
- if (checkForUpdatesDialog != null)
- checkForUpdatesDialog.toFront();
- return;
- }
-
- Thread checkForUpdatesThread = new Thread()
- {
- @Override
- public void run()
- {
- try
- {
- if(isLatestVersion())
- {
- if(notifyAboutNewestVersion)
- {
- ResourceManagementService resources
- = Resources.getResources();
-
- UpdateActivator.getUIService().getPopupDialog()
- .showMessagePopupDialog(resources.getI18NString(
- "plugin.updatechecker.DIALOG_NOUPDATE"),
- resources.getI18NString(
- "plugin.updatechecker.DIALOG_NOUPDATE_TITLE"),
- PopupDialog.INFORMATION_MESSAGE);
- }
- }
- else if (OSUtils.IS_WINDOWS)
- showWindowsNewVersionAvailableDialog();
- else
- showGenericNewVersionAvailableDialog();
- }
- finally
- {
- exitCheckForUpdates(null);
- }
- }
- };
-
- checkForUpdatesThread.setDaemon(true);
-
- enterCheckForUpdates(null);
- try
- {
- checkForUpdatesThread.start();
- checkForUpdatesThread = null;
- }
- finally
- {
- if (checkForUpdatesThread != null)
- exitCheckForUpdates(null);
- }
- }
-
- /**
- * Tries to create a new <tt>FileOutputStream</tt> for a temporary file into
- * which the setup is to be downloaded. Because temporary files generally
- * have random characters in their names and the name of the setup may be
- * shown to the user, first tries to use the name of the URL to be
- * downloaded because it likely is prettier.
- *
- * @param url the <tt>URL</tt> of the file to be downloaded
- * @param extension the extension of the <tt>File</tt> to be created or
- * <tt>null</tt> for the default (which may be derived from <tt>url</tt>)
- * @param dryRun <tt>true</tt> to generate a <tt>File</tt> in
- * <tt>tempFile</tt> and not open it or <tt>false</tt> to generate a
- * <tt>File</tt> in <tt>tempFile</tt> and open it
- * @param tempFile a <tt>File</tt> array of at least one element which is to
- * receive the created <tt>File</tt> instance at index zero (if successful)
- * @return the newly created <tt>FileOutputStream</tt>
- * @throws IOException if anything goes wrong while creating the new
- * <tt>FileOutputStream</tt>
- */
- private static FileOutputStream createTempFileOutputStream(
- URL url,
- String extension,
- boolean dryRun,
- File[] tempFile)
- throws IOException
- {
- /*
- * Try to use the name from the URL because it isn't a "randomly"
- * generated one.
- */
- String path = url.getPath();
-
- File tf = null;
- FileOutputStream tfos = null;
-
- if ((path != null) && (path.length() != 0))
- {
- int nameBeginIndex =path.lastIndexOf('/');
- String name;
-
- if (nameBeginIndex > 0)
- {
- name = path.substring(nameBeginIndex + 1);
- nameBeginIndex = name.lastIndexOf('\\');
- if (nameBeginIndex > 0)
- name = name.substring(nameBeginIndex + 1);
- }
- else
- name = path;
-
- /*
- * Make sure the extension of the name is EXE so that we're able to
- * execute it later on.
- */
- int nameLength = name.length();
-
- if (nameLength != 0)
- {
- int baseNameEnd = name.lastIndexOf('.');
-
- if (extension == null)
- extension = ".exe";
- if (baseNameEnd == -1)
- name += extension;
- else if (baseNameEnd == 0)
- {
- if (!extension.equalsIgnoreCase(name))
- name += extension;
- }
- else
- name = name.substring(0, baseNameEnd) + extension;
-
- try
- {
- String tempDir = System.getProperty("java.io.tmpdir");
-
- if ((tempDir != null) && (tempDir.length() != 0))
- {
- tf = new File(tempDir, name);
- if (!dryRun)
- tfos = new FileOutputStream(tf);
- }
- }
- catch (FileNotFoundException fnfe)
- {
- // Ignore it because we'll try File#createTempFile().
- }
- catch (SecurityException se)
- {
- // Ignore it because we'll try File#createTempFile().
- }
- }
- }
-
- // Well, we couldn't use a pretty name so try File#createTempFile().
- if ((tfos == null) && !dryRun)
- {
- tf = File.createTempFile("setup", ".exe");
- tfos = new FileOutputStream(tf);
- }
-
- tempFile[0] = tf;
- return tfos;
- }
-
- /**
- * Downloads a remote file specified by its URL into a local file.
- *
- * @param url the URL of the remote file to download
- * @return the local <tt>File</tt> into which <tt>url</tt> has been
- * downloaded or <tt>null</tt> if there was no response from the
- * <tt>url</tt>
- * @throws IOException if an I/O error occurs during the download
- */
- private static File download(String url)
- throws IOException
- {
- final File[] tempFile = new File[1];
- FileOutputStream tempFileOutputStream = null;
- boolean deleteTempFile = true;
-
- tempFileOutputStream
- = createTempFileOutputStream(
- new URL(url),
- /*
- * The default extension, possibly derived from url, is
- * fine. Besides, we do not really have information about
- * any preference.
- */
- null,
- /* Do create a FileOutputStream. */
- false,
- tempFile);
- try
- {
- HttpUtils.HTTPResponseResult res
- = HttpUtils.openURLConnection(url);
-
- if (res != null)
- {
- InputStream content = res.getContent();
- // Track the progress of the download.
- ProgressMonitorInputStream input
- = new ProgressMonitorInputStream(null, url, content);
-
- /*
- * Set the maximum value of the ProgressMonitor to the size of
- * the file to download.
- */
- input.getProgressMonitor().setMaximum(
- (int) res.getContentLength());
-
- try
- {
- final BufferedOutputStream output
- = new BufferedOutputStream(tempFileOutputStream);
-
- try
- {
- int read = -1;
- byte[] buff = new byte[1024];
-
- while((read = input.read(buff)) != -1)
- output.write(buff, 0, read);
- }
- finally
- {
- output.close();
- tempFileOutputStream = null;
- }
- deleteTempFile = false;
- }
- finally
- {
- try
- {
- input.close();
- }
- catch (IOException ioe)
- {
- /*
- * Ignore it because we've already downloaded the setup
- * and that's what matters most.
- */
- }
- }
- }
- }
- finally
- {
- try
- {
- if (tempFileOutputStream != null)
- tempFileOutputStream.close();
- }
- finally
- {
- if (deleteTempFile && (tempFile[0] != null))
- {
- tempFile[0].delete();
- tempFile[0] = null;
- }
- }
- }
- return tempFile[0];
- }
-
- /**
- * Notifies this <tt>UpdateCheckActivator</tt> that a method is entering the
- * "Check for Updates" functionality and it is thus not allowed to enter it
- * again.
- *
- * @param checkForUpdatesDialog the <tt>JDialog</tt> associated with the
- * entry in the "Check for Updates" functionality if any. While "Check for
- * Updates" cannot be entered again, clicking the "Check for Updates" menu
- * item will bring the <tt>checkForUpdatesDialog</tt> to the front.
- */
- private static synchronized void enterCheckForUpdates(
- JDialog checkForUpdatesDialog)
- {
- inCheckForUpdates++;
- if (checkForUpdatesDialog != null)
- Update.checkForUpdatesDialog = checkForUpdatesDialog;
- }
-
- /**
- * Notifies this <tt>UpdateCheckActivator</tt> that a method is exiting the
- * "Check for Updates" functionality and it may thus be allowed to enter it
- * again.
- *
- * @param checkForUpdatesDialog the <tt>JDialog</tt> which was associated
- * with the matching call to {@link #enterCheckForUpdates(JDialog)} if any
- */
- private static synchronized void exitCheckForUpdates(
- JDialog checkForUpdatesDialog)
- {
- if (inCheckForUpdates == 0)
- throw new IllegalStateException("inCheckForUpdates");
- else
- {
- inCheckForUpdates--;
- if ((checkForUpdatesDialog != null)
- && (Update.checkForUpdatesDialog == checkForUpdatesDialog))
- Update.checkForUpdatesDialog = null;
- }
- }
-
- /**
- * Gets the current (software) version.
- *
- * @return the current (software) version
- */
- private static Version getCurrentVersion()
- {
- return getVersionService().getCurrentVersion();
- }
-
- /**
- * Returns the currently registered instance of version service.
- * @return the current version service.
- */
- private static VersionService getVersionService()
- {
- return ServiceUtils.getService(
- UpdateActivator.bundleContext,
- VersionService.class);
- }
-
- /**
- * Determines whether we are currently running the latest version.
- *
- * @return <tt>true</tt> if we are currently running the latest version;
- * otherwise, <tt>false</tt>
- */
- private static boolean isLatestVersion()
- {
- try
- {
- String updateLink
- = UpdateActivator.getConfiguration().getString(
- PROP_UPDATE_LINK);
-
- if(updateLink == null)
- {
- updateLink
- = Resources.getUpdateConfigurationString("update_link");
- }
- if(updateLink == null)
- {
- if (logger.isDebugEnabled())
- logger.debug(
- "Updates are disabled, faking latest version.");
- }
- else
- {
- HttpUtils.HTTPResponseResult res
- = HttpUtils.openURLConnection(updateLink);
-
- if (res != null)
- {
- InputStream in = null;
- Properties props = new Properties();
-
- try
- {
- in = res.getContent();
- props.load(in);
- }
- finally
- {
- in.close();
- }
-
- latestVersion = props.getProperty("last_version");
- downloadLink = props.getProperty("download_link");
-
- changesLink
- = updateLink.substring(
- 0,
- updateLink.lastIndexOf("/") + 1)
- + props.getProperty("changes_html");
-
- try
- {
- VersionService versionService = getVersionService();
-
- Version latestVersionObj =
- versionService.parseVersionString(latestVersion);
-
- if(latestVersionObj != null)
- return latestVersionObj.compareTo(
- getCurrentVersion()) <= 0;
- else
- logger.error("Version obj not parsed("
- + latestVersion + ")");
- }
- catch(Throwable t)
- {
- logger.error("Error parsing version string", t);
- }
-
- // fallback to lexicographically compare
- // of version strings in case of an error
- return latestVersion.compareTo(
- getCurrentVersion().toString()) <= 0;
- }
- }
- }
- catch (Exception e)
- {
- logger.warn(
- "Could not retrieve latest version or compare it to current"
- + " version",
- e);
- /*
- * If we get an exception, then we will return that the current
- * version is the newest one in order to prevent opening the dialog
- * notifying about the availability of a new version.
- */
- }
- return true;
- }
-
- /**
- * Shows dialog informing about the availability of a new version with a
- * Download button which launches the system Web browser.
- */
- private static void showGenericNewVersionAvailableDialog()
- {
- if(!SwingUtilities.isEventDispatchThread())
- {
- SwingUtilities.invokeLater(new Runnable()
- {
- public void run()
- {
- showGenericNewVersionAvailableDialog();
- }
- });
-
- return;
- }
-
- /*
- * Before showing the dialog, we'll enterCheckForUpdates() in order to
- * notify that it is not safe to enter "Check for Updates" again. If we
- * don't manage to show the dialog, we'll have to exitCheckForUpdates().
- * If we manage though, we'll have to exitCheckForUpdates() but only
- * once depending on its modality.
- */
- final boolean[] exitCheckForUpdates = new boolean[] { false };
- final JDialog dialog = new SIPCommDialog()
- {
- private static final long serialVersionUID = 0L;
-
- @Override
- protected void close(boolean escaped)
- {
- synchronized (exitCheckForUpdates)
- {
- if (exitCheckForUpdates[0])
- exitCheckForUpdates(this);
- }
- }
- };
- ResourceManagementService resources = Resources.getResources();
- dialog.setTitle(
- resources.getI18NString("plugin.updatechecker.DIALOG_TITLE"));
-
- JEditorPane contentMessage = new JEditorPane();
- contentMessage.setContentType("text/html");
- contentMessage.setOpaque(false);
- contentMessage.setEditable(false);
-
- String dialogMsg
- = resources.getI18NString(
- "plugin.updatechecker.DIALOG_MESSAGE",
- new String[]
- {
- resources.getSettingsString(
- "service.gui.APPLICATION_NAME")
- });
- if(latestVersion != null)
- dialogMsg
- += resources.getI18NString(
- "plugin.updatechecker.DIALOG_MESSAGE_2",
- new String[]
- {
- resources.getSettingsString(
- "service.gui.APPLICATION_NAME"),
- latestVersion
- });
- contentMessage.setText(dialogMsg);
-
- JPanel contentPane = new TransparentPanel(new BorderLayout(5,5));
- contentPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
- contentPane.add(contentMessage, BorderLayout.CENTER);
-
- JPanel buttonPanel
- = new TransparentPanel(new FlowLayout(FlowLayout.CENTER, 10, 10));
- final JButton closeButton
- = new JButton(
- resources.getI18NString(
- "plugin.updatechecker.BUTTON_CLOSE"));
-
- closeButton.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- dialog.dispose();
- if (exitCheckForUpdates[0])
- exitCheckForUpdates(dialog);
- }
- });
-
- if(downloadLink != null)
- {
- JButton downloadButton
- = new JButton(
- resources.getI18NString(
- "plugin.updatechecker.BUTTON_DOWNLOAD"));
-
- downloadButton.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- if(OSUtils.IS_LINUX64)
- downloadLink
- = downloadLink.replace("i386", "amd64");
-
- UpdateActivator.getBrowserLauncher().openURL(downloadLink);
-
- /*
- * Do the same as the Close button in order to not duplicate
- * the code.
- */
- closeButton.doClick();
- }
- });
-
- buttonPanel.add(downloadButton);
- }
-
- buttonPanel.add(closeButton);
-
- contentPane.add(buttonPanel, BorderLayout.SOUTH);
-
- dialog.setContentPane(contentPane);
-
- dialog.pack();
-
- Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
- dialog.setLocation(
- screenSize.width/2 - dialog.getWidth()/2,
- screenSize.height/2 - dialog.getHeight()/2);
-
- synchronized (exitCheckForUpdates)
- {
- enterCheckForUpdates(dialog);
- exitCheckForUpdates[0] = true;
- }
- try
- {
- dialog.setVisible(true);
- }
- finally
- {
- synchronized (exitCheckForUpdates)
- {
- if (exitCheckForUpdates[0] && dialog.isModal())
- exitCheckForUpdates(dialog);
- }
- }
- }
-
- /**
- * Shows dialog informing about new version with button Install
- * which triggers the update process.
- */
- private static void showWindowsNewVersionAvailableDialog()
- {
- if(!SwingUtilities.isEventDispatchThread())
- {
- SwingUtilities.invokeLater(new Runnable()
- {
- public void run()
- {
- showWindowsNewVersionAvailableDialog();
- }
- });
-
- return;
- }
-
- /*
- * Before showing the dialog, we'll enterCheckForUpdates() in order to
- * notify that it is not safe to enter "Check for Updates" again. If we
- * don't manage to show the dialog, we'll have to exitCheckForUpdates().
- * If we manage though, we'll have to exitCheckForUpdates() but only
- * once depending on its modality.
- */
- final boolean[] exitCheckForUpdates = new boolean[] { false };
- final JDialog dialog = new SIPCommDialog()
- {
- private static final long serialVersionUID = 0L;
-
- @Override
- protected void close(boolean escaped)
- {
- synchronized (exitCheckForUpdates)
- {
- if (exitCheckForUpdates[0])
- exitCheckForUpdates(this);
- }
- }
- };
- ResourceManagementService resources = Resources.getResources();
-
- dialog.setTitle(
- resources.getI18NString("plugin.updatechecker.DIALOG_TITLE"));
-
- JEditorPane contentMessage = new JEditorPane();
- contentMessage.setContentType("text/html");
- contentMessage.setOpaque(false);
- contentMessage.setEditable(false);
-
- /*
- * Use the font of the dialog because contentMessage is just like a
- * label.
- */
- contentMessage.putClientProperty(
- JEditorPane.HONOR_DISPLAY_PROPERTIES,
- Boolean.TRUE);
-
- String dialogMsg
- = resources.getI18NString(
- "plugin.updatechecker.DIALOG_MESSAGE",
- new String[]
- {
- resources.getSettingsString(
- "service.gui.APPLICATION_NAME")
- });
-
- if(latestVersion != null)
- {
- dialogMsg
- += resources.getI18NString(
- "plugin.updatechecker.DIALOG_MESSAGE_2",
- new String[]
- {
- resources.getSettingsString(
- "service.gui.APPLICATION_NAME"),
- latestVersion
- });
- }
-
- contentMessage.setText(dialogMsg);
-
- JPanel contentPane = new SIPCommFrame.MainContentPane();
- contentMessage.setBorder(BorderFactory.createEmptyBorder(10, 0, 20, 0));
- contentPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10));
- contentPane.add(contentMessage, BorderLayout.NORTH);
-
- JScrollPane scrollChanges = new JScrollPane();
- scrollChanges.setPreferredSize(new Dimension(550, 200));
- JEditorPane changesHtml = new JEditorPane();
- changesHtml.setContentType("text/html");
- changesHtml.setEditable(false);
- changesHtml.setBorder(BorderFactory.createLoweredBevelBorder());
- scrollChanges.setViewportView(changesHtml);
- contentPane.add(scrollChanges, BorderLayout.CENTER);
- try
- {
- Document changesHtmlDocument = changesHtml.getDocument();
-
- if (changesHtmlDocument instanceof AbstractDocument)
- {
- ((AbstractDocument) changesHtmlDocument)
- .setAsynchronousLoadPriority(0);
- }
- changesHtml.setPage(new URL(changesLink));
- }
- catch (Exception e)
- {
- logger.error("Cannot set changes Page", e);
- }
-
- JPanel buttonPanel
- = new TransparentPanel(new FlowLayout(FlowLayout.CENTER, 10, 10));
- final JButton closeButton
- = new JButton(
- resources.getI18NString(
- "plugin.updatechecker.BUTTON_CLOSE"));
-
- closeButton.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- dialog.dispose();
- if (exitCheckForUpdates[0])
- exitCheckForUpdates(dialog);
- }
- });
-
- if(downloadLink != null)
- {
- JButton installButton
- = new JButton(
- resources.getI18NString(
- "plugin.updatechecker.BUTTON_INSTALL"));
-
- installButton.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- if(OSUtils.IS_WINDOWS64)
- downloadLink = downloadLink.replace("x86", "x64");
-
- enterCheckForUpdates(null);
- try
- {
- /*
- * Do the same as the Close button in order to not
- * duplicate the code.
- */
- closeButton.doClick();
- }
- finally
- {
- boolean windowsUpdateThreadHasStarted = false;
-
- try
- {
- new Thread()
- {
- @Override
- public void run()
- {
- try
- {
- windowsUpdate();
- }
- finally
- {
- exitCheckForUpdates(null);
- }
- }
- }.start();
- windowsUpdateThreadHasStarted = true;
- }
- finally
- {
- if (!windowsUpdateThreadHasStarted)
- exitCheckForUpdates(null);
- }
- }
- }
- });
-
- buttonPanel.add(installButton);
- }
-
- buttonPanel.add(closeButton);
-
- contentPane.add(buttonPanel, BorderLayout.SOUTH);
-
- dialog.setContentPane(contentPane);
-
- dialog.pack();
-
- Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
- dialog.setLocation(
- screenSize.width/2 - dialog.getWidth()/2,
- screenSize.height/2 - dialog.getHeight()/2);
-
- synchronized (exitCheckForUpdates)
- {
- enterCheckForUpdates(dialog);
- exitCheckForUpdates[0] = true;
- }
- try
- {
- dialog.setVisible(true);
- }
- finally
- {
- synchronized (exitCheckForUpdates)
- {
- if (exitCheckForUpdates[0] && dialog.isModal())
- exitCheckForUpdates(dialog);
- }
- }
- }
-
- /**
- * Implements the very update procedure on Windows which includes without
- * being limited to:
- * <ol>
- * <li>Downloads the setup in a temporary directory.</li>
- * <li>Warns that the update procedure will shut down the application.</li>
- * <li>Executes the setup in a separate process and shuts down the
- * application.</li>
- * </ol>
- */
- private static void windowsUpdate()
- {
- /*
- * Firstly, try a delta update which contains a bspatch file to be used
- * to reconstruct the latest MSI from the locally-cached one. If it
- * fails, fall back to a full update.
- */
- File delta = null;
- boolean deleteDelta = true;
- File msi = null;
-
- try
- {
- String deltaTarget = null;
-
- Version ver = getCurrentVersion();
-
- if(ver.isNightly())
- deltaTarget = ver.getNightlyBuildID();
- else
- deltaTarget = String.valueOf(ver.toString());
-
- String deltaLink
- = downloadLink.replace(
- latestVersion,
- latestVersion + "-delta-" + deltaTarget);
-
- /*
- * TODO Download the delta update regardless of the logging level
- * once the generation of delta updates is implemented and the whole
- * functionality performs satisfactory.
- */
- if (!deltaLink.equalsIgnoreCase(downloadLink))
- delta = download(deltaLink);
-
- if (delta != null)
- {
- File[] deltaMsi = new File[1];
-
- createTempFileOutputStream(
- delta.toURI().toURL(),
- ".msi",
- /*
- * Do not actually create a FileOutputStream, we just
- * want the File (name).
- */
- true,
- deltaMsi);
-
- Process process
- = new ProcessBuilder(
- delta.getCanonicalPath(),
- "--quiet",
- deltaMsi[0].getCanonicalPath())
- .start();
-
- int exitCode = 1;
-
- while (true)
- {
- try
- {
- exitCode = process.waitFor();
- break;
- }
- catch (InterruptedException ie)
- {
- /*
- * Ignore it, we're interested in the exit code of the
- * process.
- */
- }
- }
- if (0 == exitCode)
- {
- deleteDelta = false;
- msi = deltaMsi[0];
- }
- }
- }
- catch (Exception e)
- {
- /* Ignore it, we'll try the full update. */
- }
- finally
- {
- if (deleteDelta && (delta != null))
- {
- delta.delete();
- delta = null;
- }
- }
-
- /*
- * Secondly, either apply the delta update or download and apply a full
- * update.
- */
- boolean deleteMsi = true;
- deleteDelta = true;
-
- try
- {
- if (msi == null)
- msi = download(downloadLink);
- if (msi != null)
- {
- ResourceManagementService resources = Resources.getResources();
-
- if(UpdateActivator.getUIService()
- .getPopupDialog().showConfirmPopupDialog(
- resources.getI18NString(
- "plugin.updatechecker.DIALOG_WARN",
- new String[]{
- resources.getSettingsString(
- "service.gui.APPLICATION_NAME")
- }),
- resources.getI18NString(
- "plugin.updatechecker.DIALOG_TITLE"),
- PopupDialog.YES_NO_OPTION,
- PopupDialog.QUESTION_MESSAGE)
- == PopupDialog.YES_OPTION)
- {
- List<String> command = new ArrayList<String>();
-
- /*
- * If a delta update is in effect, the delta will execute
- * the latest MSI it has previously recreated from the
- * locally-cached MSI. Otherwise, a full update is in effect
- * and it will just execute itself.
- */
- command.add(
- ((delta == null) ? msi : delta).getCanonicalPath());
- command.add("--wait-parent");
- if (delta != null)
- {
- command.add("--msiexec");
- command.add(msi.getCanonicalPath());
- }
- command.add(
- "SIP_COMMUNICATOR_AUTOUPDATE_INSTALLDIR=\""
- + System.getProperty("user.dir")
- + "\"");
-
- deleteMsi = false;
- deleteDelta = false;
-
- /*
- * The setup has been downloaded. Now start it and shut
- * down.
- */
- new ProcessBuilder(command).start();
-
- UpdateActivator.getShutdownService().beginShutdown();
- }
- }
- }
- catch(FileNotFoundException fnfe)
- {
- ResourceManagementService resources = Resources.getResources();
-
- UpdateActivator.getUIService()
- .getPopupDialog().showMessagePopupDialog(
- resources.getI18NString(
- "plugin.updatechecker.DIALOG_MISSING_UPDATE"),
- resources.getI18NString(
- "plugin.updatechecker.DIALOG_NOUPDATE_TITLE"),
- PopupDialog.INFORMATION_MESSAGE);
- }
- catch (Exception e)
- {
- if (logger.isInfoEnabled())
- logger.info("Could not update", e);
- }
- finally
- {
- /*
- * If we've failed, delete the temporary file into which the setup
- * was supposed to be or has already been downloaded.
- */
- if (deleteMsi && (msi != null))
- {
- msi.delete();
- msi = null;
- }
- if (deleteDelta && (delta != null))
- {
- delta.delete();
- delta = null;
- }
- }
- }
-}
diff --git a/src/net/java/sip/communicator/plugin/update/UpdateActivator.java b/src/net/java/sip/communicator/plugin/update/UpdateActivator.java
index d7b41db..67881d6 100644
--- a/src/net/java/sip/communicator/plugin/update/UpdateActivator.java
+++ b/src/net/java/sip/communicator/plugin/update/UpdateActivator.java
@@ -178,7 +178,7 @@ public class UpdateActivator
if (OSUtils.IS_WINDOWS)
{
- updateService = new Update();
+ updateService = new UpdateServiceImpl();
bundleContext.registerService(
UpdateService.class.getName(),
diff --git a/src/net/java/sip/communicator/plugin/update/UpdateServiceImpl.java b/src/net/java/sip/communicator/plugin/update/UpdateServiceImpl.java
index 6562128..ae0ef70 100644
--- a/src/net/java/sip/communicator/plugin/update/UpdateServiceImpl.java
+++ b/src/net/java/sip/communicator/plugin/update/UpdateServiceImpl.java
@@ -16,17 +16,16 @@ import java.util.List;
import javax.swing.*;
import javax.swing.text.*;
+import net.java.sip.communicator.plugin.desktoputil.*;
import net.java.sip.communicator.service.gui.*;
import net.java.sip.communicator.service.httputil.*;
import net.java.sip.communicator.service.update.*;
import net.java.sip.communicator.util.*;
import net.java.sip.communicator.util.Logger;
-import net.java.sip.communicator.plugin.desktoputil.*;
import org.jitsi.service.resources.*;
import org.jitsi.service.version.*;
import org.jitsi.util.*;
-// disambiguation
/**
* Implements checking for software updates, downloading and applying them i.e.
@@ -84,6 +83,53 @@ public class UpdateServiceImpl
= "net.java.sip.communicator.UPDATE_LINK";
/**
+ * Initializes a new Web browser <tt>Component</tt> instance and navigates
+ * it to a specific URL.
+ *
+ * @param url the URL to navigate the new Web browser <tt>Component</tt>
+ * instance
+ * @return the new Web browser <tt>Component</tt> instance which has been
+ * navigated to the specified <tt>url</tt>
+ */
+ private static Component createBrowser(String url)
+ {
+ // Initialize the user interface.
+ JEditorPane editorPane = new JEditorPane();
+
+ editorPane.setBorder(BorderFactory.createLoweredBevelBorder());
+ editorPane.setContentType("text/html");
+ editorPane.setEditable(false);
+
+ JScrollPane scrollPane = new JScrollPane();
+
+ scrollPane.setViewportView(editorPane);
+
+ // Navigate the user interface to the specified URL.
+ try
+ {
+ Document document = editorPane.getDocument();
+
+ if (document instanceof AbstractDocument)
+ ((AbstractDocument) document).setAsynchronousLoadPriority(0);
+
+ editorPane.setPage(new URL(url));
+ }
+ catch (Throwable t)
+ {
+ if (t instanceof ThreadDeath)
+ throw (ThreadDeath) t;
+ else
+ {
+ logger.error(
+ "Failed to navigate the Web browser to: " + url,
+ t);
+ }
+ }
+
+ return editorPane;
+ }
+
+ /**
* Tries to create a new <tt>FileOutputStream</tt> for a temporary file into
* which the setup is to be downloaded. Because temporary files generally
* have random characters in their names and the name of the setup may be
@@ -712,28 +758,12 @@ public class UpdateServiceImpl
contentPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10));
contentPane.add(contentMessage, BorderLayout.NORTH);
- JScrollPane scrollChanges = new JScrollPane();
- scrollChanges.setPreferredSize(new Dimension(550, 200));
- JEditorPane changesHtml = new JEditorPane();
- changesHtml.setContentType("text/html");
- changesHtml.setEditable(false);
- changesHtml.setBorder(BorderFactory.createLoweredBevelBorder());
- scrollChanges.setViewportView(changesHtml);
- contentPane.add(scrollChanges, BorderLayout.CENTER);
- try
- {
- Document changesHtmlDocument = changesHtml.getDocument();
+ Component browser = createBrowser(changesLink);
- if (changesHtmlDocument instanceof AbstractDocument)
- {
- ((AbstractDocument) changesHtmlDocument)
- .setAsynchronousLoadPriority(0);
- }
- changesHtml.setPage(new URL(changesLink));
- }
- catch (Exception e)
+ if (browser != null)
{
- logger.error("Cannot set changes Page", e);
+ browser.setPreferredSize(new Dimension(550, 200));
+ contentPane.add(browser, BorderLayout.CENTER);
}
JPanel buttonPanel