package games.strategy.engine.framework; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.io.IOException; import java.net.URL; import java.util.Properties; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import javax.swing.BorderFactory; import javax.swing.JEditorPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; import games.strategy.debug.ClientLogger; import games.strategy.engine.ClientContext; import games.strategy.net.OpenFileUtility; import games.strategy.util.Version; public class EngineVersionProperties { private final Version latestVersionOut; private final String link; private final String linkAlt; private final String changelogLink; private static final String TRIPLEA_VERSION_LINK = "https://raw.githubusercontent.com/triplea-game/triplea/master/latest_version.properties"; private EngineVersionProperties() { this(getProperties()); } private EngineVersionProperties(final Properties props) { latestVersionOut = new Version(props.getProperty("LATEST", ClientContext.engineVersion().getVersion().toStringFull("."))); link = props.getProperty("LINK", "http://triplea-game.github.io/"); linkAlt = props.getProperty("LINK_ALT", "http://triplea-game.github.io/download/"); changelogLink = props.getProperty("CHANGELOG", "http://triplea-game.github.io/release_notes/"); } public static EngineVersionProperties contactServerForEngineVersionProperties() { // sourceforge sometimes takes a long while to return results // so run a couple requests in parallel, starting with delays to try and get a response quickly final AtomicReference<EngineVersionProperties> ref = new AtomicReference<>(); final CountDownLatch latch = new CountDownLatch(1); for (int i = 0; i < 5; i++) { new Thread(() -> { ref.set(new EngineVersionProperties()); latch.countDown(); }).start(); try { latch.await(2, TimeUnit.SECONDS); } catch (final InterruptedException e) { Thread.currentThread().interrupt(); } if (ref.get() != null) { break; } } // we have spawned a bunch of requests try { latch.await(15, TimeUnit.SECONDS); } catch (final InterruptedException e) { Thread.currentThread().interrupt(); } return ref.get(); } private static Properties getProperties() { final Properties props = new Properties(); try { props.load(new URL(TRIPLEA_VERSION_LINK).openStream()); } catch (final IOException e) { ClientLogger.logQuietly("Failed while attempting to check for a new Version", e); } return props; } public Version getLatestVersionOut() { return latestVersionOut; } public String getLinkToDownloadLatestVersion() { return link; } public String getLinkAltToDownloadLatestVersion() { return linkAlt; } public String getChangeLogLink() { return changelogLink; } private String getOutOfDateMessage() { final StringBuilder text = new StringBuilder("<html>"); text.append("<h2>A new version of TripleA is out. Please Update TripleA!</h2>"); text.append("<br />Your current version: ").append(ClientContext.engineVersion().getFullVersion()); text.append("<br />Latest version available for download: ").append(getLatestVersionOut()); text.append("<br /><br />Click to download: <a class=\"external\" href=\"").append(getLinkToDownloadLatestVersion()) .append("\">").append(getLinkToDownloadLatestVersion()).append("</a>"); text.append("<br />Backup Mirror: <a class=\"external\" href=\"").append(getLinkAltToDownloadLatestVersion()) .append("\">").append(getLinkAltToDownloadLatestVersion()).append("</a>"); text.append("<br /><br />Please note that installing a new version of TripleA will not remove any old copies of ") .append("TripleA."); text.append("<br />So be sure to either manually uninstall all older versions of TripleA, or change your ") .append("shortcuts to the new TripleA."); text.append("<br /><br />What is new:<br />"); text.append("</html>"); return text.toString(); } private String getOutOfDateReleaseUpdates() { final StringBuilder text = new StringBuilder("<html><body>"); text.append("Link to full Change Log:<br /><a class=\"external\" href=\"").append(getChangeLogLink()).append("\">") .append(getChangeLogLink()).append("</a><br />"); text.append("</body></html>"); return text.toString(); } public Component getOutOfDateComponent() { final JPanel panel = new JPanel(new BorderLayout()); final JEditorPane intro = new JEditorPane("text/html", getOutOfDateMessage()); intro.setEditable(false); intro.setOpaque(false); intro.setBorder(BorderFactory.createEmptyBorder()); final HyperlinkListener hyperlinkListener = e -> { if (HyperlinkEvent.EventType.ACTIVATED.equals(e.getEventType())) { OpenFileUtility.openURL(e.getDescription()); } }; intro.addHyperlinkListener(hyperlinkListener); panel.add(intro, BorderLayout.NORTH); final JEditorPane updates = new JEditorPane("text/html", getOutOfDateReleaseUpdates()); updates.setEditable(false); updates.setOpaque(false); updates.setBorder(BorderFactory.createEmptyBorder()); updates.addHyperlinkListener(hyperlinkListener); updates.setCaretPosition(0); final JScrollPane scroll = new JScrollPane(updates); // scroll.setBorder(BorderFactory.createEmptyBorder()); panel.add(scroll, BorderLayout.CENTER); final Dimension maxDimension = panel.getPreferredSize(); maxDimension.width = Math.min(maxDimension.width, 700); maxDimension.height = Math.min(maxDimension.height, 480); panel.setMaximumSize(maxDimension); panel.setPreferredSize(maxDimension); return panel; } }