package org.pokenet.updater; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.MalformedURLException; import java.net.URL; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.SwingWorker; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory; import org.tmatesoft.svn.core.wc.ISVNOptions; import org.tmatesoft.svn.core.wc.SVNClientManager; import org.tmatesoft.svn.core.wc.SVNEvent; import org.tmatesoft.svn.core.wc.SVNEventAction; import org.tmatesoft.svn.core.wc.SVNEventAdapter; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc.SVNUpdateClient; import org.tmatesoft.svn.core.wc.SVNWCUtil; public class PokenetUpdater extends JPanel implements ActionListener, PropertyChangeListener { private static final long serialVersionUID = 5427544579927859151L; public static final String SVN_URL = "pokenet-release.svn.sourceforge.net/svnroot/pokenet-release"; public static final String FOLDER_NAME = "pokenet-release"; private String HEADER_IMAGE_URL = "http://pokedev.org/header.png"; private static final String OS = System.getProperty("os.name"); public static final String SAD_INSTALL_MESSAGE = "Hmm. Game installed, but we couldn't save the location.\nThis means that next time you run, you'll have to select the same installation directory."; public static final String TITLE = "Pokenet Installer and Updater"; private static final int WIDTH = 740; private static final int HEIGHT = 470; private static final int OUTPUT_HEIGHT = 120; private static JFrame m_masterFrame = new JFrame("Pokenet: Valiant Venonat"); private JProgressBar m_progressBar; private JButton m_hideButton; private JTextArea m_taskOutput; private Task m_task; private Component m_output; private boolean m_showOutput = true; private JButton m_resetLocation; static boolean m_isWindows = OS.contains("Windows"); static boolean m_isLinux = OS.contains("Linux"); static boolean m_isMac = OS.contains("Mac"); private static float m_progressSize = 0; private static String m_installpath = ""; private static String path; class Task extends SwingWorker<Void, Void> { /* * Main task. Executed in background thread. */ @Override public Void doInBackground() { // Initialize progress property. setProgress(0); DAVRepositoryFactory.setup(); ISVNOptions options = SVNWCUtil.createDefaultOptions(true); /* * Creates an instance of SVNClientManager providing authentication * information (name, password) and an options driver */ SVNClientManager ourClientManager = SVNClientManager .newInstance(options); SVNUpdateClient updateClient = ourClientManager.getUpdateClient(); /* * Creates the event handler to display information */ ourClientManager.setEventHandler(new SVNEventAdapter() { public void handleEvent(SVNEvent event, double progress) { SVNEventAction action = event.getAction(); File curFile = event.getFile(); String path = curFile.getAbsolutePath(); path = path.substring(path.indexOf(FOLDER_NAME)); if (action == SVNEventAction.ADD || action == SVNEventAction.UPDATE_ADD) { m_taskOutput.append("Downloading " + path + " \n"); m_taskOutput.setCaretPosition(m_taskOutput .getDocument().getLength()); System.out.println("Downloading " + curFile.getName()); } if (action == SVNEventAction.STATUS_COMPLETED || action == SVNEventAction.UPDATE_COMPLETED) { setProgress(100); m_taskOutput.append("Download completed. "); m_taskOutput.setCaretPosition(m_taskOutput .getDocument().getLength()); System.out.println("Download completed. "); } } }); /* * sets externals not to be ignored during the checkout */ updateClient.setIgnoreExternals(false); /* * A url of a repository to check out */ SVNURL url = null; try { url = SVNURL.parseURIDecoded("http://" + SVN_URL); } catch (SVNException e2) { e2.printStackTrace(); } /* * A revision to check out */ SVNRevision revision = SVNRevision.HEAD; /* * A revision for which you're sure that the url you specify is * exactly what you need */ SVNRevision pegRevision = SVNRevision.HEAD; /* * A local path where a Working Copy will be ckecked out */ File destPath = new File(m_installpath); /* * returns the number of the revision at which the working copy is */ try { System.out.println(m_installpath); m_taskOutput.append("Game folder: " + m_installpath + "\n"); boolean exists = destPath.exists(); if (!exists) { m_taskOutput .append("Installing...\nPlease be patient while PokeNet is downloaded...\n"); System.out.println("Installing..."); updateClient.doCheckout(url, destPath, pegRevision, revision, SVNDepth.INFINITY, true); } else { ourClientManager.getWCClient().doCleanup(destPath); m_taskOutput.append("Updating...\n"); System.out.println("Updating...\n"); updateClient.doUpdate(destPath, revision, SVNDepth.INFINITY, true, true); } } catch (SVNException e1) { // It's probably locked, lets cleanup and resume. e1.printStackTrace(); try { ourClientManager.getWCClient().doCleanup(destPath); m_taskOutput.append("Resuming Download...\n"); System.out.println("Resuming Download...\n"); updateClient.doUpdate(destPath, revision, SVNDepth.INFINITY, true, true); } catch (SVNException e) { e.printStackTrace(); } } return null; } /* * Executed in event dispatching thread */ @Override public void done() { if (getProgress() < 100) { setProgress(100); m_taskOutput.append("Download complete!"); m_taskOutput.setCaretPosition(m_taskOutput.getDocument() .getLength()); } try { if (!m_installpath.equals("")) { m_taskOutput.append("Setting up the install directory..."); m_taskOutput.setCaretPosition(m_taskOutput.getDocument() .getLength()); File f = new File(path); if (m_isLinux || m_isMac || m_isWindows) { if (f.exists()) f.delete(); PrintWriter pw = new PrintWriter(f); pw.write(m_installpath); pw.flush(); pw.close(); } else { JOptionPane.showInternalMessageDialog(m_masterFrame, SAD_INSTALL_MESSAGE, TITLE, JOptionPane.WARNING_MESSAGE); } } } catch (Exception e) { e.printStackTrace(); JOptionPane .showInternalMessageDialog(m_masterFrame, SAD_INSTALL_MESSAGE, TITLE, JOptionPane.WARNING_MESSAGE); } setCursor(null); // turn off the wait cursor /* * Launch Jar */ LaunchPokenet(); } } public static void LaunchPokenet() { m_masterFrame.setVisible(false); String[] args = new String[4]; try { //String s; String m_launchCommand = ""; String sep = File.separator; if(m_isWindows) { // added " to path m_launchCommand = "\"" + m_installpath + "\\pokenet.bat\""; File dir = new File(m_installpath); Process p = Runtime.getRuntime().exec("cmd /c" + m_launchCommand, null, dir); } else { args[0] = "java "; args[1] = "-Dres.path=" + m_installpath + sep; args[2] = "-Djava.library.path=" + m_installpath + sep + "lib" + sep + "native"; args[3] = "-jar " + m_installpath + sep + "Pokenet.jar"; Process p = Runtime.getRuntime().exec(args); } for(String s: args) System.out.print(s + " "); // // BufferedReader stdInput = new BufferedReader(new InputStreamReader( // p.getInputStream())); // BufferedReader stdError = new BufferedReader(new InputStreamReader( // p.getErrorStream())); // // Read the output from the command // // String s; // while ((s = stdInput.readLine()) != null) { // System.out.println(s); // } // while ((s = stdError.readLine()) != null) { // System.out.println("Error: " + s); // } } catch (IOException e) { e.printStackTrace(); JOptionPane .showInternalMessageDialog( m_masterFrame, "Ouch! Something happened and we couldn't run the game. \nMaybe it didn't install properly?\nError: " + e.getLocalizedMessage(), TITLE, JOptionPane.WARNING_MESSAGE); } System.exit(0); } public PokenetUpdater() { super(new BorderLayout()); JPanel panel = new JPanel(); JPanel container = new JPanel(); panel.setSize(m_masterFrame.getWidth(), 40); container.setSize(m_masterFrame.getWidth(), OUTPUT_HEIGHT + panel.getHeight()); container.setLayout(new BorderLayout()); panel.setLayout(new BorderLayout()); updatePokenet(); // // m_resetLocation = new JButton("Reset Game Location"); // m_hideButton.setActionCommand("reset"); // m_hideButton.addActionListener(this); // m_hideButton.setEnabled(true); // panel.add(m_resetLocation, BorderLayout.LINE_START); m_hideButton = new JButton("Hide Details..."); m_hideButton.setActionCommand("hide"); m_hideButton.addActionListener(this); m_hideButton.setEnabled(true); panel.add(m_hideButton, BorderLayout.LINE_END); m_progressBar = new JProgressBar(); m_progressBar.setIndeterminate(true); m_progressBar.setStringPainted(false); m_progressBar.setToolTipText("Click on Show Details to see the progress"); m_progressBar.setSize(WIDTH, m_hideButton.getHeight()); m_taskOutput = new JTextArea(); m_taskOutput.setSize(m_masterFrame.getWidth(), OUTPUT_HEIGHT); m_taskOutput.setEditable(false); m_taskOutput.setAutoscrolls(true); m_output = new JScrollPane(m_taskOutput); container.add(m_progressBar, BorderLayout.PAGE_END); container.add(m_output, BorderLayout.CENTER); ImageIcon m_logo; JLabel l = null; l = new JLabel(); l.setSize(WIDTH, 190); try { m_logo = new ImageIcon(new URL(HEADER_IMAGE_URL)); l = new JLabel(m_logo); } catch (MalformedURLException e) { e.printStackTrace(); } add(l, BorderLayout.PAGE_START); add(container, BorderLayout.CENTER); add(panel, BorderLayout.PAGE_END); } /** * Invoked when the user presses the start button. */ public void actionPerformed(ActionEvent evt) { if (evt.getActionCommand().equals("hide")) { if (!m_showOutput) { // m_output.setVisible(true); m_hideButton.setText("Hide Details..."); m_masterFrame.setSize(WIDTH, HEIGHT); m_showOutput = true; } else { // m_output.setVisible(false); m_hideButton.setText("Show Details..."); m_masterFrame.setSize(WIDTH, HEIGHT - m_output.getHeight()); m_showOutput = false; } } else if (evt.getActionCommand().equals("reset")) { File f = new File(path); f.delete(); runApp(); } } private void updatePokenet() { setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); // Instances of javax.swing.SwingWorker are not reusuable, so // we create new instances as needed. m_task = new Task(); m_task.addPropertyChangeListener(this); m_task.execute(); } /** * Invoked when task's progress property changes. */ public void propertyChange(PropertyChangeEvent evt) { if ("progress" == evt.getPropertyName()) { int progress = (Integer) evt.getNewValue(); m_progressBar.setValue(progress); } } /** * Create the GUI and show it. As with all GUI code, this must run on the * event-dispatching thread. * * @param mProgressSize */ private static void createAndShowGUI() { // Create and set up the window. m_masterFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); m_masterFrame.setSize(new Dimension(WIDTH, HEIGHT)); // Create and set up the content pane. JComponent newContentPane = new PokenetUpdater(); newContentPane.setOpaque(true); // content panes must be opaque m_masterFrame.setContentPane(newContentPane); // Display the window. centerTheGUIFrame(m_masterFrame); m_masterFrame.setVisible(true); } public static void main(String[] args) { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (UnsupportedLookAndFeelException e) { e.printStackTrace(); } setPathForOS(); runApp(); } public static void runApp() { javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { System.out.println("Path path : " + path); if (!path.equals("")) { BufferedReader br = null; try { br = new BufferedReader(new FileReader(path)); m_installpath = br.readLine(); createAndShowGUI(); } catch (Exception e) { JFileChooser fc = new JFileChooser(); fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); int returnVal = fc.showDialog(m_masterFrame, "Choose Install Location..."); if (returnVal == JFileChooser.APPROVE_OPTION) { File file = fc.getSelectedFile(); try { m_installpath = file.getCanonicalPath() + (m_isWindows ? "\\" : "/") + FOLDER_NAME; createAndShowGUI(); } catch (IOException e1) { e1.printStackTrace(); } } else { JOptionPane.showMessageDialog(m_masterFrame, "Thanks for choosing us!", TITLE, JOptionPane.INFORMATION_MESSAGE); System.exit(0); } } } else { /** * Check Updates */ createAndShowGUI(); } } }); } protected static void setPathForOS() { if (m_isWindows) { path = System.getenv("APPDATA") + "\\.pokenet"; } else if (m_isLinux) { path = System.getenv("HOME") + "/.pokenet"; } else if (m_isMac) { // Probably? path = System.getProperty("user.home") + "/Library/Preferences/org.pokenet.updaterPrefs"; // Maybe. } } /** * This method is used to center the GUI * * @param frame * - Frame that needs to be centered. */ public static void centerTheGUIFrame(JFrame frame) { int widthWindow = frame.getWidth(); int heightWindow = frame.getHeight(); Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); int X = (screen.width / 2) - (widthWindow / 2); // Center horizontally. int Y = (screen.height / 2) - (heightWindow / 2); // Center vertically. frame.setBounds(X, Y, widthWindow, heightWindow); } public static float getProgressSize() { return m_progressSize; } public static void setProgressSize(float f) { m_progressSize = f; } public String getInstallpath() { return m_installpath; } public void setInstallpath(String mInstallpath) { m_installpath = mInstallpath; } }