package com.dabomstew.pkrandom.gui; import java.awt.Desktop; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URI; import java.util.Scanner; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import javax.swing.JOptionPane; import com.dabomstew.pkrandom.SysConstants; import com.dabomstew.pkrandom.FileFunctions; import com.dabomstew.pkrandom.Utils; /** * * @author Stewart */ public class UpdateFoundDialog extends javax.swing.JDialog { /** * */ private static final long serialVersionUID = -1641494584047215623L; private int targetVersion; /** * Creates new form UpdateFoundDialog */ public UpdateFoundDialog(RandomizerGUI parent, int newVersion, String changelog) { super(parent, true); initComponents(); targetVersion = newVersion; Scanner sc = new Scanner(changelog); String firstLine = htmlspecialchars(sc.nextLine()); sc.close(); updateFoundLabel.setText("<html>An update to the Randomizer has been found: <b>" + firstLine + ".</b><br />You can see the changes made since your last update below."); while (changelog.trim().toLowerCase().startsWith("<html>")) { changelog = changelog.trim().substring(6); } updateChangelogArea.setText(changelog); updateChangelogArea.setCaretPosition(0); this.setLocationRelativeTo(parent); this.setVisible(true); } /* @formatter:off */ /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always * regenerated by the Form Editor. */ // <editor-fold defaultstate="collapsed" // desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { updateFoundLabel = new javax.swing.JLabel(); clScroller = new javax.swing.JScrollPane(); updateChangelogArea = new javax.swing.JTextArea(); downloadUpdateBtn = new javax.swing.JButton(); closeBtn = new javax.swing.JButton(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); updateFoundLabel .setText("<html>An update to the Randomizer has been found: <b>x.x.x</b>, released <b>blah.</b><br /> You can see the changes made below."); clScroller .setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); updateChangelogArea.setEditable(false); updateChangelogArea.setColumns(40); updateChangelogArea.setLineWrap(true); updateChangelogArea.setRows(5); updateChangelogArea.setWrapStyleWord(true); updateChangelogArea.setEnabled(false); clScroller.setViewportView(updateChangelogArea); downloadUpdateBtn.setText("Download Update Now"); downloadUpdateBtn .addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { downloadUpdateBtnActionPerformed(evt); } }); closeBtn.setText("Close Without Updating"); closeBtn.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { closeBtnActionPerformed(evt); } }); javax.swing.GroupLayout layout = new javax.swing.GroupLayout( getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup(layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup( layout.createSequentialGroup() .addContainerGap() .addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.LEADING) .addComponent(clScroller) .addGroup( layout.createSequentialGroup() .addComponent( updateFoundLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(0, 161, Short.MAX_VALUE)) .addGroup( layout.createSequentialGroup() .addComponent( downloadUpdateBtn) .addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent( closeBtn))) .addContainerGap())); layout.setVerticalGroup(layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup( layout.createSequentialGroup() .addContainerGap() .addComponent(updateFoundLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(clScroller, javax.swing.GroupLayout.PREFERRED_SIZE, 209, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(downloadUpdateBtn) .addComponent(closeBtn)) .addContainerGap())); pack(); }// </editor-fold>//GEN-END:initComponents private void downloadUpdateBtnActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_downloadUpdateBtnActionPerformed // External: download delta file String randomizerBinary; try { randomizerBinary = Utils.getExecutionLocation().getName(); } catch (UnsupportedEncodingException e) { JOptionPane .showMessageDialog( this, "Automatic update not available.\n" + "You will now be taken to the website to download it manually."); attemptOpenBrowser(); return; } String deltaFile = "delta_" + SysConstants.UPDATE_VERSION + "_" + targetVersion + (randomizerBinary.toLowerCase().endsWith(".exe") ? "_win" : "") + ".zip"; try { byte[] zip = FileFunctions.downloadFile(SysConstants.AUTOUPDATE_URL + deltaFile); extract(zip, new File(SysConstants.ROOT_PATH), randomizerBinary); JOptionPane .showMessageDialog( this, "Update complete - the randomizer will now close.\n" + "You should now re-open the program and begin using the new version."); System.exit(0); } catch (IOException ex) { JOptionPane .showMessageDialog( this, "Automatic update not available.\n" + "You will now be taken to the website to download it manually."); attemptOpenBrowser(); } }// GEN-LAST:event_downloadUpdateBtnActionPerformed private void attemptOpenBrowser() { String targetURL = SysConstants.WEBSITE_URL; Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null; if (desktop == null || !desktop.isSupported(Desktop.Action.BROWSE)) { JOptionPane .showMessageDialog( this, "The downloads page could not be opened automatically.\n" + "Open a browser and navigate to the below link to download the update:\n" + targetURL); } else { try { desktop.browse(new URI(targetURL)); } catch (Exception e) { JOptionPane .showMessageDialog( this, "The downloads page could not be opened automatically.\n" + "Open a browser and navigate to the below link to download the update:\n" + targetURL); } } this.setVisible(false); } private void extractFile(ZipInputStream in, File outdir, String name) throws IOException { byte[] buffer = new byte[4096]; BufferedOutputStream out = new BufferedOutputStream( new FileOutputStream(new File(outdir, name))); int count = -1; while ((count = in.read(buffer)) != -1) out.write(buffer, 0, count); out.close(); } private void mkdirs(File outdir, String path) { File d = new File(outdir, path); if (!d.exists()) d.mkdirs(); } private String dirpart(String name) { int s = name.lastIndexOf(File.separatorChar); return s == -1 ? null : name.substring(0, s); } private String htmlspecialchars(String original) { return original.replace("&", "&").replace("<", "<") .replace(">", ">"); } public void extract(byte[] zipfile, File outdir, String randomizerBinary) throws IOException { ZipInputStream zin = new ZipInputStream(new ByteArrayInputStream( zipfile)); ZipEntry entry; String name, dir; while ((entry = zin.getNextEntry()) != null) { name = entry.getName(); if (entry.isDirectory()) { mkdirs(outdir, name); continue; } /* * this part is necessary because file entry can come before * directory entry where is file located i.e.: /foo/foo.txt /foo/ */ dir = dirpart(name); if (dir != null) mkdirs(outdir, dir); if (name.endsWith("randomizer.jar") || name.endsWith("randomizer.exe")) { name = name.substring(0, name.length() - 14) + randomizerBinary; } extractFile(zin, outdir, name); } zin.close(); } private void closeBtnActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_closeBtnActionPerformed this.setVisible(false); }// GEN-LAST:event_closeBtnActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JScrollPane clScroller; private javax.swing.JButton closeBtn; private javax.swing.JButton downloadUpdateBtn; private javax.swing.JTextArea updateChangelogArea; private javax.swing.JLabel updateFoundLabel; // End of variables declaration//GEN-END:variables /* @formatter:on */ }