/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ro.nextreports.designer.action.help; import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JEditorPane; import javax.swing.JScrollPane; import javax.swing.SwingUtilities; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; import javax.swing.text.Document; import javax.swing.text.html.HTMLEditorKit; import ro.nextreports.designer.Globals; import ro.nextreports.designer.ReleaseInfo; import ro.nextreports.designer.util.FileUtil; import ro.nextreports.designer.util.I18NSupport; import ro.nextreports.designer.util.ImageUtil; import ro.nextreports.designer.util.Show; import ro.nextreports.designer.util.UIActivator; import ro.nextreports.engine.util.ReportUtil; /** * Checks if a new version of NextReports Designer was released on github * * @author Mihai Dinca-Panaitescu * @date 26.09.2013 */ public class CheckForUpdateAction extends AbstractAction { // a request to this url will be saved in database by nemo application private String nextSiteUpdatesUrl = "http://www.asf.ro/next_reports_releases/updates.xml"; private String url = "https://github.com/nextreports/nextreports-designer/releases"; private String releaseRegex = "release-([\\d\\.]+)\\.zip"; private String versionNotFound = "NA"; private String SNAPSHOT_SUFFIX = "-SNAPSHOT"; private String indent = "    "; private JDialog dlg; public CheckForUpdateAction() { putValue(Action.NAME, I18NSupport.getString("update.check")); putValue(Action.SMALL_ICON, ImageUtil.getImageIcon("update")); putValue(Action.SHORT_DESCRIPTION, I18NSupport.getString("update.check")); putValue(Action.LONG_DESCRIPTION, I18NSupport.getString("update.check")); } public void actionPerformed(ActionEvent event) { Thread executorThread = new Thread(new Runnable() { public void run() { UIActivator activator = new UIActivator(Globals.getMainFrame(), I18NSupport.getString("update.check")); activator.start(); final StringBuilder sb = new StringBuilder(); try { System.setProperty("java.net.useSystemProxies", "true"); String currentVersion = ReleaseInfo.getVersion(); int snapshotIndex = currentVersion.indexOf(SNAPSHOT_SUFFIX); if (snapshotIndex > 0) { currentVersion = currentVersion.substring(0, snapshotIndex); } // to save the update info in database String updatesXml = getContent(nextSiteUpdatesUrl); String lastVersion = getLastVersion(url); sb.append("<HTML><b><br>").append(indent) .append(I18NSupport.getString("update.check.current", currentVersion)).append("<br><br>"); if (versionNotFound.equals(lastVersion)) { sb.append(indent).append(I18NSupport.getString("update.check.uptodate")); } else { int status = ReportUtil.compareVersions(currentVersion, lastVersion); if (status < 0) { sb.append(indent) .append(I18NSupport.getString("update.check.newversion", lastVersion)) .append("<br><br>") .append(indent) .append("<font color=\"#0000A0\"><a href=\"http://www.next-reports.com/index.php/download.html\">") .append(I18NSupport.getString("download.name")).append("</a></font>"); } else { sb.append(indent).append(I18NSupport.getString("update.check.uptodate")); } } } finally { sb.append("</b></HTML>"); activator.stop(); } SwingUtilities.invokeLater(new Runnable() { public void run() { JComponent component = createPanel(sb.toString()); dlg = new JDialog(Globals.getMainFrame(), I18NSupport.getString("update.check"), true); dlg.setResizable(false); dlg.setBackground(new Color(234, 241, 248)); dlg.setLayout(new GridBagLayout()); dlg.add(component, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(10, 10, 10, 10), 0, 0)); dlg.pack(); Show.centrateComponent(Globals.getMainFrame(), dlg); dlg.setVisible(true); } }); } }, "NEXT : " + getClass().getSimpleName()); executorThread.start(); } private String getContent(String url) { try { URL u = new URL(url); URLConnection uc = u.openConnection(); uc.setDoOutput(true); StringBuffer sbuf = new StringBuffer(); BufferedReader in = new BufferedReader(new InputStreamReader(uc.getInputStream())); try { String res = in.readLine(); while ((res = in.readLine()) != null) { sbuf.append(res); } } finally { in.close(); } return sbuf.toString(); } catch (IOException ex) { return ""; } } private String getLastVersion(String url) { String html = getContent(url); Pattern p = Pattern.compile(releaseRegex); Matcher m = p.matcher(html); // first found is last release if (m.find()) { String release = m.group(1); return release; } return versionNotFound; } protected MouseListener mouseListener = new MouseAdapter() { public void mouseClicked(MouseEvent me) { dlg.dispose(); } }; private JComponent createPanel(String html) { System.setProperty("awt.useSystemAAFontSettings", "on"); final JEditorPane editorPane = new JEditorPane(); HTMLEditorKit kit = new HTMLEditorKit(); editorPane.setEditorKit(kit); editorPane.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE); editorPane.setFont(new Font("Arial", Font.PLAIN, 12)); editorPane.setPreferredSize(new Dimension(350, 120)); editorPane.setEditable(false); editorPane.setContentType("text/html"); editorPane.setBackground(new Color(234, 241, 248)); Document doc = kit.createDefaultDocument(); editorPane.setDocument(doc); editorPane.setText(html); // Add Hyperlink listener to process hyperlinks editorPane.addHyperlinkListener(new HyperlinkListener() { public void hyperlinkUpdate(final HyperlinkEvent e) { if (e.getEventType() == HyperlinkEvent.EventType.ENTERED) { EventQueue.invokeLater(new Runnable() { public void run() { SwingUtilities.getWindowAncestor(editorPane).setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); editorPane.setToolTipText(e.getURL().toExternalForm()); } }); } else if (e.getEventType() == HyperlinkEvent.EventType.EXITED) { EventQueue.invokeLater(new Runnable() { public void run() { SwingUtilities.getWindowAncestor(editorPane).setCursor(Cursor.getDefaultCursor()); editorPane.setToolTipText(null); } }); } else if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { FileUtil.openUrl(e.getURL().toString(), AboutAction.class); } } }); editorPane.addMouseListener(mouseListener); JScrollPane sp = new JScrollPane(editorPane); return sp; } }