/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package modmanager.utility.update; import com.jcraft.jsch.Channel; import com.jcraft.jsch.ChannelSftp; import com.jcraft.jsch.JSch; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; import com.jcraft.jsch.SftpException; import javax.swing.JOptionPane; import modmanager.business.ManagerOptions; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; import java.util.Map.Entry; import java.util.Set; import java.util.StringTokenizer; import java.util.zip.ZipEntry; import java.util.zip.ZipException; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; /** * * @author Shirkit */ public class CalculateJarDifferences { /** * This method should only be run when a new version of the Manager will be released. It tries to make the process more automatic. * Currently: * - Writes in the Version file in LOCAL DISK (Dropbox folder, so Dropbox must be running!) * - Uploads the file to the correct folder tree in the SourceForge project, creating all needed folder on the way. */ public static void main(String[] args) throws ZipException, IOException, JSchException { /* * IMPORTANT * * Before releasing a new version of the Manager, please, follow these instructions: * 0 - Update the Changelog.txt and Version.txt files * 1 - Check if the older version is fully compatible with this one after an update. managerOptions.xml shall not be lost by any reasons. * 2 - Check if the file paths below are correct. * 3 - Clean and build the project, then Package-for-store the Manager.jar * 4 - Goto Sourceforge.net and update the LABEL and the OS supported for the new Manager file. * 5 - Update in the HoN forums page (changelog, topic title and version in first line) */ // First step is to get the version we want to release. String targetVersion = ManagerOptions.getInstance().getVersion(); // Get the old jar File oldJarVersion = new File("C:\\Users\\Shirkit\\Dropbox\\HonModManager\\Dropbox\\Public\\versions\\Manager.jar"); // And the newly generated one File newJarVersion = new File("store\\Manager.jar"); // Target output for where the differences will be generated String verionsFile = "C:\\Users\\Shirkit\\Dropbox\\HonModManager\\Dropbox\\Public\\versions.txt"; File rootVersionsFolder = new File("C:\\Users\\Shirkit\\Dropbox\\HonModManager\\Dropbox\\Public\\versions\\"); File output = new File(rootVersionsFolder, targetVersion + ".jar"); System.out.println("Version to be released=" + targetVersion); System.out.println("Old version file=" + oldJarVersion.getAbsolutePath()); System.out.println("New version file=" + newJarVersion.getAbsolutePath()); System.out.println(); if (calculate(oldJarVersion, newJarVersion, output.getAbsolutePath())) { System.out.println("Output file generated.\nPath=" + output.getAbsolutePath() + "\nSize=" + output.length() / 1024 + "KB"); // Read the current versions file and store it for later FileInputStream fis = new FileInputStream(verionsFile); ByteArrayOutputStream baos = new ByteArrayOutputStream(); copyInputStream(fis, baos); String s = baos.toString(); fis.close(); baos.close(); System.out.println(s); if (!s.trim().isEmpty()) { if (s.contains("\n")) { System.out.println("Older version=" + s.substring(0, s.indexOf("\n"))); } else { System.out.println("Older version=" + s); } s = targetVersion + "\n" + s; } else { System.out.println("First version!"); s = targetVersion; } if (JOptionPane.showConfirmDialog(null, "Confirm upload?", "Confirmation", JOptionPane.YES_NO_OPTION) != 0) { System.exit(0); } // Write new versions file with the new released version FileWriter fw = new FileWriter(verionsFile); fw.write(s); fw.flush(); fw.close(); System.out.println("Versions file written with sucess!"); fis = new FileInputStream(newJarVersion); FileOutputStream fos = new FileOutputStream(rootVersionsFolder + File.separator + "Manager.jar"); copyInputStream(fis, fos); fis.close(); fos.close(); System.out.println("Manager.jar file written!"); System.out.println(); } else { System.err.println("No differences file. Output file not generated."); System.exit(0); } JSch jsch = new JSch(); Session session = null; try { System.out.println("Connecting to SF"); session = jsch.getSession(JOptionPane.showInputDialog("SourceForge Username") + ",all-inhonmodman", "frs.sourceforge.net", 22); session.setConfig("StrictHostKeyChecking", "no"); session.setPassword(JOptionPane.showInputDialog("SourceForge Password")); session.connect(); Channel channel = session.openChannel("sftp"); channel.connect(); ChannelSftp sftpChannel = (ChannelSftp) channel; System.out.println("Connected!"); String root = "/home/frs/project/a/al/all-inhonmodman"; sftpChannel.cd(root); StringTokenizer versionTokens = new StringTokenizer(targetVersion, " "); boolean flag = true; while (versionTokens.hasMoreTokens()) { String s = versionTokens.nextToken(); if (!cdExists(sftpChannel, s)) { sftpChannel.mkdir(s); flag = false; } sftpChannel.cd(s); } if (flag) { System.err.println("Version already exists!"); sftpChannel.exit(); session.disconnect(); System.exit(0); } System.out.println("Uploading file"); OutputStream out = sftpChannel.put("Manager.jar"); FileInputStream fis = new FileInputStream(newJarVersion); copyInputStream(fis, out); out.close(); fis.close(); System.out.println("Upload complete"); sftpChannel.exit(); session.disconnect(); System.out.println("SUCESS!"); } catch (JSchException e) { e.printStackTrace(); } catch (SftpException e) { e.printStackTrace(); } System.exit(0); } public static boolean cdExists(ChannelSftp channel, String path) { try { channel.ls(path); return true; } catch (Exception e) { return false; } } /** * This method calculates the differences between the files inside a Jar file and generates an output file. * The output only contains the files that have difference in their CRC. * @param olderVersionJar - file to be compared to. * @param newerVersionJar - source file of the comparisson. * @param outputDestination - path to the file that will contain the differences in those Jars. * @throws ZipException - if a ZIP error has occurred * @throws IOException - if an I/O error has occurred * @return true if the output file was generated AND has at least one entry inside it, false otherwise. */ private static boolean calculate(File olderVersionJar, File newerVersionJar, String outputDestination) throws ZipException, IOException { ZipFile oldZip = new ZipFile(olderVersionJar); ZipFile newZip = new ZipFile(newerVersionJar); Enumeration oldEntries = oldZip.entries(); Enumeration newEntries = newZip.entries(); HashMap<String, Long> map = new HashMap<String, Long>(); while (newEntries.hasMoreElements()) { ZipEntry entry = (ZipEntry) newEntries.nextElement(); map.put(entry.getName(), entry.getCrc()); } while (oldEntries.hasMoreElements()) { ZipEntry entry = (ZipEntry) oldEntries.nextElement(); Long l = map.get(entry.getName()); if (l != null && l.longValue() == entry.getCrc()) { map.remove(entry.getName()); } } if (!map.isEmpty()) { ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(outputDestination)); Set<Entry<String, Long>> set = map.entrySet(); Iterator<Entry<String, Long>> it = set.iterator(); while (it.hasNext()) { Entry<String, Long> entry = it.next(); ZipEntry zipEntry = newZip.getEntry(entry.getKey()); InputStream is = newZip.getInputStream(zipEntry); zos.putNextEntry(zipEntry); copyInputStream(is, zos); zos.closeEntry(); is.close(); } zos.flush(); zos.close(); } oldZip.close(); newZip.close(); if (map.isEmpty()) { return false; } else { return true; } } /** * 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) 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(); 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()); } copyInputStream(is, zos); is.close(); } zos.close(); zos.flush(); sourceZipFile.close(); diffZipFile.close(); FileOutputStream fos = new FileOutputStream(targetFile); FileInputStream fis = new FileInputStream(temp); copyInputStream(fis, fos); fis.close(); fos.close(); temp.delete(); temp.deleteOnExit(); } private static void copyInputStream(InputStream in, OutputStream out) throws IOException { byte[] buffer = new byte[1024]; int len; while (((len = in.read(buffer)) >= 0)) { out.write(buffer, 0, len); } out.flush(); } }