package updater;
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.UIManager;
/**
* This is just a copy of the Updater class for saving it inside our project. You must build this class outside and pack into jar for predicted behavior.
* Get the .jar file, remove it's extension (new name will be "Updater") and when packing the Manager.jar, put it in the root folder.
* You must call it with the 2 string arguments: [1] = Path to the current Manager Jar. [2] = URL to download the new manager.
* @author Shirkit
*/
public class Updater {
public static void main(String[] args) {
/**
* 0 - PATH_TO_MANAGER.JAR
* 1 - CURRENT_MANAGER_VERSION
* 2 - VERIONS.TXT_CONTROL_FILE
* 3 - ROOT_WEBSERVER_FOLDER
* 4 - LOCAL_TEMPORARY_FOLDER
*/
Dialog dialog = new Dialog();
try {
// Validation of arguments
if (args.length != 5) {
throw new InvalidParameterException("\n\nInvalid nunmber of parameters.\n\nCall must be \"java -jar Updater.jar PATH_TO_MANAGER.JAR CURRENT_MANAGER_VERSION VERIONS.TXT_CONTROL_FILE ROOT_WEBSERVER_FOLDER LOCAL_TEMPORARY_FOLDER\"");
}
File managerJar = new File(args[0]);
if (!managerJar.exists()) {
throw new FileNotFoundException(args[0]);
}
dialog.updateLabel("Calculating files");
// Check in versions file how many files we need to download
URL verionsFile = new URL(args[2]);
URLConnection connection = verionsFile.openConnection();
connection.setConnectTimeout(10000);
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
ArrayList<String> versions = new ArrayList<String>();
while (br.ready()) {
versions.add(br.readLine());
}
br.close();
int index = versions.indexOf(args[1]);
// Make sure 'root' will be valid to work with
String root = args[3];
if (!root.endsWith("/")) {
root += "/";
}
if (index != -1) {
// If eveything goes normal
ArrayList<File> filesDownloaded = new ArrayList<File>();
// Need to download from the older to the newer and apply the patchs in this order
int k = 0;
for (int i = index-1; i >= 0; i--) {
dialog.updateLabel("Connecting " + ++k + "/" + index + " files");
URL url = new URL(root + versions.get(i).replaceAll(" ", "%20") + ".jar");
URLConnection con = url.openConnection();
con.setConnectTimeout(10000);
dialog.progressBar.setValue(0);
dialog.progressBar.setMaximum(con.getContentLength());
File f = new File(args[4] + File.separator + versions.get(i) + ".jar");
InputStream in = con.getInputStream();
FileOutputStream out = new FileOutputStream(f,false);
dialog.updateLabel("Downloading " + i + "/" + index + " files");
copyInputStream(in, out, dialog.progressBar);
in.close();
out.close();
filesDownloaded.add(f);
}
// Now the order is already the correct one, just go normal
Iterator<File> it = filesDownloaded.iterator();
k = 0;
while (it.hasNext()) {
dialog.updateLabel("Applying " + ++k + "/" + filesDownloaded.size() + " files");
File file = it.next();
dialog.progressBar.setValue(0);
FileInputStream fis = new FileInputStream(file);
dialog.progressBar.setMaximum(fis.available());
fis.close();
putDifsInJar(managerJar, file, dialog.progressBar);
}
} else {
// If, for some reason, didn't go normal, just download the full Manager.jar
dialog.updateLabel("Connecting");
URL url = new URL(root + "Manager.jar");
URLConnection con = url.openConnection();
con.setConnectTimeout(10000);
dialog.progressBar.setValue(0);
dialog.progressBar.setMaximum(con.getContentLength());
File f = new File(args[4] + File.separator + "Manager.jar");
InputStream in = con.getInputStream();
OutputStream out = new FileOutputStream(f);
dialog.updateLabel("Downloading ");
copyInputStream(in, out, dialog.progressBar);
in.close();
out.close();
// Replace Manager.jar
FileInputStream fis = new FileInputStream(f);
FileOutputStream fos = new FileOutputStream(managerJar);
copyInputStream(in, out, null);
in.close();
out.close();
}
dialog.updateLabel("Finishing");
// Exit
Process runManager = Runtime.getRuntime().exec("java -jar " + managerJar.getAbsolutePath());
System.exit(0);
} catch (Exception e) {
dialog.updateLabel("Closing...");
JOptionPane.showMessageDialog(null, "Failed to update manager\n\n" + e.toString(), "Update failed", JOptionPane.ERROR_MESSAGE);
long t0, t1;
t0 = System.currentTimeMillis();
do {
t1 = System.currentTimeMillis();
} while ((t1 - t0) < (1 * 1500));
System.exit(0);
}
}
public static void copyInputStream(InputStream in, OutputStream out, JProgressBar bar) throws IOException {
byte[] buffer = new byte[1024];
int len;
while (((len = in.read(buffer)) >= 0)) {
if (bar != null) {
bar.setValue(bar.getValue() + 1024);
}
out.write(buffer, 0, len);
}
}
/**
* This method uses puts the new content of the differenceFile into the Jar targetFile, replacing the files as necessary.
* @param targetFile
* @param differenceFile - zip containing the files you want to add into the targetFile.
* This differenceFile must exsit and have at least 1 entry, or a ZipException will be thrown.
* @throws ZipException - if a ZIP error has occurred
* @throws IOException - if an I/O error has occurred
*/
public static void putDifsInJar(File targetFile, File differenceFile, JProgressBar bar) throws ZipException, IOException {
File temp = new File(targetFile.getAbsolutePath() + ".temp");
ZipFile sourceZipFile = new ZipFile(targetFile);
ZipFile diffZipFile = new ZipFile(differenceFile);
HashMap<String, ZipEntry> map = new HashMap<String, ZipEntry>();
Enumeration diffEntries = diffZipFile.entries();
while (diffEntries.hasMoreElements()) {
ZipEntry entry = (ZipEntry) diffEntries.nextElement();
map.put(entry.getName(), entry);
}
Enumeration sourceEntries = sourceZipFile.entries();
while (sourceEntries.hasMoreElements()) {
ZipEntry entry = (ZipEntry) sourceEntries.nextElement();
if (map.get(entry.getName()) == null) {
map.put(entry.getName(), entry);
}
}
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(temp));
Set<Entry<String, ZipEntry>> set = map.entrySet();
bar.setMaximum(set.size());
Iterator<Entry<String, ZipEntry>> it = set.iterator();
while (it.hasNext()) {
Entry<String, ZipEntry> entry = it.next();
zos.putNextEntry(entry.getValue());
InputStream is = null;
if (diffZipFile.getEntry(entry.getKey()) != null) {
is = diffZipFile.getInputStream(entry.getValue());
} else {
is = sourceZipFile.getInputStream(entry.getValue());
}
bar.setValue(bar.getValue() + 1);
copyInputStream(is, zos, null);
is.close();
}
zos.close();
zos.flush();
sourceZipFile.close();
diffZipFile.close();
FileOutputStream fos = new FileOutputStream(targetFile);
FileInputStream fis = new FileInputStream(temp);
copyInputStream(fis, fos, null);
fis.close();
fos.close();
temp.delete();
temp.deleteOnExit();
}
public static class Dialog {
JProgressBar progressBar;
JButton cancel;
JLabel label;
JFrame frame;
public Dialog() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
frame = new JFrame("All-In Hon ModManager Updater");
// Try to center on screen
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
frame.setBounds(((int) dim.getWidth() / 100) * 45, ((int) dim.getHeight() / 10) * 4, 200, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Init values
cancel = new JButton("Cancel");
progressBar = new JProgressBar(0, 100);
progressBar.setStringPainted(true);
label = new JLabel("Starting");
label.setPreferredSize(new Dimension(100, 35));
cancel.addActionListener(new ButtonListener());
JPanel panel = new JPanel(new BorderLayout(0, 5));
panel.add(progressBar, BorderLayout.CENTER);
panel.add(label, BorderLayout.NORTH);
panel.add(cancel, BorderLayout.SOUTH);
panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
frame.setContentPane(panel);
frame.pack();
frame.setVisible(true);
}
public void updateLabel(String text) {
label.setText(text);
frame.paint(frame.getGraphics());
}
}
public static class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
int i = JOptionPane.showConfirmDialog(null, "Do you really want to cancel?", "Confirmation", JOptionPane.YES_NO_OPTION);
if (i == 0) {
System.exit(0);
}
}
}
}