package org.freeplane.main.application; import java.awt.Component; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.net.MalformedURLException; import java.net.URL; import java.util.Date; import java.util.Locale; import java.util.Set; import javax.swing.Box; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.Timer; import org.freeplane.core.resources.ResourceController; import org.freeplane.core.ui.AFreeplaneAction; import org.freeplane.core.ui.MenuBuilder; import org.freeplane.core.ui.components.UITools; import org.freeplane.core.util.FreeplaneVersion; import org.freeplane.core.util.TextUtils; import org.freeplane.features.mode.Controller; import org.freeplane.features.ui.IMapViewChangeListener; /** * Checks for updates. * * @author robert ladstaetter */ class UpdateCheckAction extends AFreeplaneAction { private static boolean autorunEnabled = true; private static Timer autorunTimer = null; private static final int CHECK_TIME = 30 * 1000; private static final String CHECK_UPDATES_AUTOMATICALLY = "check_updates_automatically"; private static final String LAST_UPDATE_CHECK_TIME = "last_update_check_time"; private static final String LAST_UPDATE_VERSION = "last_update_verson"; /** * the sid. */ private static final long serialVersionUID = 1L; private static final int TWO_DAYS = 1 * 24 * 60 * 60 * 1000; private static final String UPDATE_BUTTON_LOCATION = "main_toolbar_update"; private static final String UPDATE_BUTTON_PATH = UPDATE_BUTTON_LOCATION + "/checkUpdate"; /** * the url where to download the newest version */ private static final String WEB_DOWNLOAD_LOCATION_KEY = "webDownloadLocation"; /** * the url to check the local version against */ private static final String WEB_UPDATE_LOCATION_KEY = "webUpdateLocation"; /** * the client which asks a remote repository for the current version of the program. */ public UpdateCheckAction() { super("UpdateCheckAction"); final Controller controller = Controller.getCurrentController(); controller.getMapViewManager().addMapViewChangeListener(new IMapViewChangeListener() { public void afterViewChange(final Component oldView, final Component newView) { if (newView == null) { return; } EventQueue.invokeLater(new Runnable() { public void run() { removeMe(); } }); setTimer(); } public void afterViewClose(final Component oldView) { } public void afterViewCreated(final Component mapView) { } public void beforeViewChange(final Component oldView, final Component newView) { } private void removeMe() { controller.getMapViewManager().removeMapViewChangeListener(this); } }); //FIXME DOCEAR setEnabled(false); ResourceController.getResourceController().setProperty(CHECK_UPDATES_AUTOMATICALLY, false); } //FIXME: DOCEAR public void setEnabled() { this.setEnabled(false); } public void setEnabled(boolean enabled) { super.setEnabled(false); } public void actionPerformed(final ActionEvent e) { final boolean autoRun = e.getSource().equals(autorunTimer); if (autorunTimer != null) { autorunTimer.stop(); autorunTimer = null; } new Thread(new Runnable() { public void run() { checkForUpdates(autoRun); } }, "checkForUpdates").start(); } private void addUpdateButton(final FreeplaneVersion lastVersion) { Controller controller = Controller.getCurrentController(); final Set<String> modes = controller.getModes(); for (final String mode : modes) { final MenuBuilder menuBuilder = controller.getModeController(mode).getUserInputListenerFactory() .getMenuBuilder(); if (lastVersion == null || lastVersion.compareTo(FreeplaneVersion.getVersion()) <= 0) { ResourceController.getResourceController().setProperty(LAST_UPDATE_VERSION, ""); if (menuBuilder.get(UPDATE_BUTTON_PATH) != null) { menuBuilder.removeElement(UPDATE_BUTTON_PATH); } continue; } ResourceController.getResourceController().setProperty(LAST_UPDATE_VERSION, lastVersion.toString()); final String updateAvailable = TextUtils.format("new_version_available", lastVersion.toString()); controller.getViewController().out(updateAvailable); putValue(SHORT_DESCRIPTION, updateAvailable); putValue(LONG_DESCRIPTION, updateAvailable); if (menuBuilder.get(UPDATE_BUTTON_PATH) == null) { menuBuilder.addAction(UPDATE_BUTTON_LOCATION, UPDATE_BUTTON_PATH, UpdateCheckAction.this, MenuBuilder.AS_CHILD); } } } private void checkForUpdates(final boolean autoRun) { final Date now = new Date(); ResourceController.getResourceController().setProperty(LAST_UPDATE_CHECK_TIME, Long.toString(now.getTime())); final Locale defaultLocale = Locale.getDefault(); final String language = defaultLocale.getLanguage(); final String DEFAULT_LANGUAGE = "en"; final String translatedWebUpdate = getWebUpdateUrl(language); final FreeplaneVersion localVersion = FreeplaneVersion.getVersion(); final HttpVersionClient translatedVersionClient = new HttpVersionClient(translatedWebUpdate, localVersion); FreeplaneVersion lastTranslatedVersion = translatedVersionClient.getRemoteVersion(); if (lastTranslatedVersion == null) { lastTranslatedVersion = localVersion; } final String history; final FreeplaneVersion lastVersion; final boolean connectSuccesfull; if (!language.equals(DEFAULT_LANGUAGE)) { final String defaultWebUpdate = getWebUpdateUrl(DEFAULT_LANGUAGE); final HttpVersionClient defaultVersionClient = new HttpVersionClient(defaultWebUpdate, lastTranslatedVersion); lastVersion = defaultVersionClient.getRemoteVersion(); history = defaultVersionClient.getHistory() + translatedVersionClient.getHistory(); connectSuccesfull = defaultVersionClient.isSuccessful(); } else { lastVersion = lastTranslatedVersion; history = translatedVersionClient.getHistory(); connectSuccesfull = translatedVersionClient.isSuccessful(); } EventQueue.invokeLater(new Runnable() { public void run() { addUpdateButton(lastVersion); if (autoRun) { return; } showUpdateDialog(connectSuccesfull, localVersion, lastVersion, history); } }); } private String getWebUpdateUrl(final String language) { { final String webUpdateUrl = ResourceController.getResourceController().getProperty(WEB_UPDATE_LOCATION_KEY); final FreeplaneVersion localVersion = FreeplaneVersion.getVersion(); final StringBuilder sb = new StringBuilder(webUpdateUrl); final String type = localVersion.getType(); if(! type.equals("")){ sb.append(type); sb.append('/'); } sb.append("history_"); sb.append(language); sb.append(".txt"); return sb.toString(); } } private FreeplaneVersion getKnownNewVersion() { final FreeplaneVersion localVersion = FreeplaneVersion.getVersion(); final String property = ResourceController.getResourceController().getProperty(LAST_UPDATE_VERSION); if (property.equals("")) { return null; } FreeplaneVersion lastVersion = FreeplaneVersion.getVersion(property); if (lastVersion.compareTo(localVersion) <= 0) { lastVersion = null; } return lastVersion; } private void setTimer() { if (autorunEnabled == false) { return; } autorunEnabled = ResourceController.getResourceController().getBooleanProperty(CHECK_UPDATES_AUTOMATICALLY); if (autorunEnabled == false) { return; } autorunEnabled = false; final Date now = new Date(); final long nextCheckMillis = ResourceController.getResourceController().getLongProperty(LAST_UPDATE_CHECK_TIME, 0) + TWO_DAYS; final Date nextCheckDate = new Date(nextCheckMillis); if (now.before(nextCheckDate)) { final FreeplaneVersion knownNewVersion = getKnownNewVersion(); addUpdateButton(knownNewVersion); return; } autorunTimer = new Timer(CHECK_TIME, this); autorunTimer.setRepeats(false); autorunTimer.start(); } private void showUpdateDialog(final boolean connectSuccesfull, final FreeplaneVersion localVersion, final FreeplaneVersion newVersion, final String history) { final int choice; if (connectSuccesfull == false) { choice = showUpdateDialog("can_not_connect_to_info_server", "", ""); } else if (localVersion.compareTo(newVersion) < 0) { choice = showUpdateDialog("new_version_available", newVersion.toString(), history); } else { showUpdateDialog("version_up_to_date", null, null); choice = -1; } if (0 != choice) { return; } // go to download page try { Controller.getCurrentController().getViewController().openDocument( new URL(ResourceController.getResourceController().getProperty(WEB_DOWNLOAD_LOCATION_KEY))); } catch (final MalformedURLException ex) { UITools.errorMessage(TextUtils.getText("url_error") + "\n" + ex); } catch (final Exception ex) { UITools.errorMessage(ex); } } private int showUpdateDialog(final String info, final String newVersion, final String history) { final Box messagePane = Box.createVerticalBox(); final JLabel messageLabel; if (newVersion != null) { messageLabel = new JLabel(TextUtils.format(info, newVersion.toString())); } else { messageLabel = new JLabel(TextUtils.getText(info)); } messageLabel.setAlignmentX(JLabel.LEFT_ALIGNMENT); messagePane.add(messageLabel); final JTextArea historyArea = new JTextArea(history); historyArea.setEditable(false); final JScrollPane historyPane = new JScrollPane(historyArea); historyPane.setPreferredSize(new Dimension(500, 300)); historyPane.setAlignmentX(JLabel.LEFT_ALIGNMENT); messagePane.add(historyPane); final JCheckBox updateAutomatically = new JCheckBox(TextUtils .getText("OptionPanel.check_updates_automatically"), ResourceController.getResourceController() .getBooleanProperty(CHECK_UPDATES_AUTOMATICALLY)); updateAutomatically.setAlignmentX(JLabel.LEFT_ALIGNMENT); messagePane.add(updateAutomatically); final Object[] options; if (newVersion != null) { options = new Object[] { TextUtils.getText("download"), TextUtils.getText("cancel") }; } else { options = new Object[] { TextUtils.getText("simplyhtml.closeBtnName") }; } final int choice = JOptionPane.showOptionDialog(Controller.getCurrentController().getViewController().getFrame(), messagePane, TextUtils.getText("updatecheckdialog"), JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null, options, options[0]); ResourceController.getResourceController().setProperty(CHECK_UPDATES_AUTOMATICALLY, Boolean.toString(updateAutomatically.isSelected())); return choice; } }