From f7f58da22029c7a07397856a700760118d30c1aa Mon Sep 17 00:00:00 2001 From: Lyubomir Marinov Date: Sun, 30 Jun 2013 19:48:31 +0300 Subject: [PATCH] Makes it easier to switch to an alaternative Web browser in the 'New version is available' dialog on Windows. --- .../CheckForUpdatesMenuItemComponent.java | 17 +- .../communicator/plugin/update/Update.java | 1084 ----------------- .../plugin/update/UpdateActivator.java | 2 +- .../plugin/update/UpdateServiceImpl.java | 74 +- 4 files changed, 62 insertions(+), 1115 deletions(-) delete mode 100644 src/net/java/sip/communicator/plugin/update/Update.java diff --git a/src/net/java/sip/communicator/plugin/update/CheckForUpdatesMenuItemComponent.java b/src/net/java/sip/communicator/plugin/update/CheckForUpdatesMenuItemComponent.java index 536116527..87b0b8efb 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 JMenuItem getComponent() = 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 5a7e23bd2..000000000 --- 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 Logger used by the Update 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 JDialog, 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 true if the user is to be - * notified if they have the newest version already; otherwise, - * false - */ - 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 FileOutputStream 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 URL of the file to be downloaded - * @param extension the extension of the File to be created or - * null for the default (which may be derived from url) - * @param dryRun true to generate a File in - * tempFile and not open it or false to generate a - * File in tempFile and open it - * @param tempFile a File array of at least one element which is to - * receive the created File instance at index zero (if successful) - * @return the newly created FileOutputStream - * @throws IOException if anything goes wrong while creating the new - * FileOutputStream - */ - 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 File into which url has been - * downloaded or null if there was no response from the - * url - * @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 UpdateCheckActivator that a method is entering the - * "Check for Updates" functionality and it is thus not allowed to enter it - * again. - * - * @param checkForUpdatesDialog the JDialog 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 checkForUpdatesDialog to the front. - */ - private static synchronized void enterCheckForUpdates( - JDialog checkForUpdatesDialog) - { - inCheckForUpdates++; - if (checkForUpdatesDialog != null) - Update.checkForUpdatesDialog = checkForUpdatesDialog; - } - - /** - * Notifies this UpdateCheckActivator that a method is exiting the - * "Check for Updates" functionality and it may thus be allowed to enter it - * again. - * - * @param checkForUpdatesDialog the JDialog 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 true if we are currently running the latest version; - * otherwise, false - */ - 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: - *
    - *
  1. Downloads the setup in a temporary directory.
  2. - *
  3. Warns that the update procedure will shut down the application.
  4. - *
  5. Executes the setup in a separate process and shuts down the - * application.
  6. - *
- */ - 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 command = new ArrayList(); - - /* - * 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 d7b41db7d..67881d6b5 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 void start(Object dependentService) 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 656212819..ae0ef7088 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 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. @@ -83,6 +82,53 @@ public class UpdateServiceImpl private static final String PROP_UPDATE_LINK = "net.java.sip.communicator.UPDATE_LINK"; + /** + * Initializes a new Web browser Component instance and navigates + * it to a specific URL. + * + * @param url the URL to navigate the new Web browser Component + * instance + * @return the new Web browser Component instance which has been + * navigated to the specified url + */ + 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 FileOutputStream for a temporary file into * which the setup is to be downloaded. Because temporary files generally @@ -712,28 +758,12 @@ protected void close(boolean escaped) 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