package forkk.multimc.task; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.util.logging.Logger; import java.util.zip.ZipException; import java.util.zip.ZipFile; import forkk.multimc.data.Instance; import forkk.multimc.gui.SelectionWindow; import forkk.multimc.util.FileUtils; import forkk.multimc.util.ZipUtils; public class JarBuilder extends Task { Instance instance; public JarBuilder(Instance inst) { this.instance = inst; buildLog = Logger.getLogger(SelectionWindow.getMainLogName() + ".JarBuildLogger"); } Logger buildLog; private static final String jarBackupName = "mcbackup.jar"; final int maxSteps = 6; int step = 0; private void setStep(int s) { step = s; setProgress((int) (((float) step / (float) maxSteps) * 100)); } /* * Protocol: * * 1. Create a folder called mctmp that will store all of the files that we're * going to be adding. * 2. Iterate through items in instMods and do the following: * If the item is a directory, recurse into it * * If the item is a zip file, extract it to a temp folder and set the * creation date / time for the extracted files to that of the zip file * they came from. Once they are extracted, perform this step again for * the files that were extracted. * * If the item is a file and is not a zip file, do the following: * If mctmp doesn't already have an item with the same name, simply * copy the item to mctmp. * * If mctmp does have an item with the same name, keep whichever one is * newer. * * 3. If there isn't already a file called mcbackup.jar, copy minecraft.jar to it. * 4. Delete minecraft.jar * 5. Extract mcbackup.jar to a temporary directory called mcjar. * 6. Copy everything from mctmp to mcjar and delete mctmp. * 7. Zip mcjar back into minecraft.jar and delete mcjar. */ @Override public void TaskStart() { OnTaskStart(); try { setStatus("Creating mctmp..."); File mctmp = new File(instance.getRootDir(), "mctmp"); if (mctmp.exists()) FileUtils.recursiveDelete(mctmp); mctmp.mkdir(); setStatus("Adding files to mctmp..."); int pcount = 0; for (File f : instance.getInstMods().listFiles()) { recursiveAdd(f, mctmp); pcount++; setProgress(100 / pcount); } setStep(1); // Backup minecraft.jar and delete it File jarFile = new File(instance.getBinDir(), "minecraft.jar"); File jarBackup = new File(instance.getBinDir(), jarBackupName); if (!jarBackup.exists()) { setStatus("Backing up minecraft.jar"); FileUtils.copyFile(jarFile, jarBackup, false); } jarFile.delete(); setStep(2); // Extract the jar to mcjar and copy everything from mctmp to it. setStatus("Extracting jar file"); File mcjar = new File(instance.getRootDir(), "mcjar"); if (mcjar.exists()) mcjar.delete(); mcjar.mkdir(); ZipFile jarZip = new ZipFile(jarBackup); ZipUtils.ExtractAllFromZip(jarZip, mcjar); File metaInf = new File(mcjar, "META-INF"); if (metaInf.exists()) FileUtils.recursiveDelete(metaInf); setStep(3); // Copy mctmp to mcjar setStatus("Adding mod files"); for (File f : mctmp.listFiles()) { FileUtils.recursiveCopy(f, mcjar, true); } FileUtils.recursiveDelete(mctmp); setStep(4); // Re-zip mcjar to minecraft.jar and delete it. setStatus("Re-zipping jar"); ZipUtils.recursiveAddToZip(mcjar.listFiles(), jarFile, ""); setStep(5); setStatus("Removing temporary files..."); FileUtils.recursiveDelete(mcjar); setStep(6); buildLog.info("Build complete"); } catch (FileNotFoundException e) { e.printStackTrace(); OnErrorMessage(e.getMessage()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); buildLog.fine("Error adding file to mctmp."); OnErrorMessage("Error building jar: " + e.toString()); } OnTaskEnd(); } private void recursiveAdd(File file, File dest) throws IOException { if (file.isDirectory()) { for (File f : file.listFiles()) { buildLog.info("Recursing into directory " + f.toString()); recursiveAdd(f, new File(dest, f.getName())); } } else if (file.isFile()) { // Zip files if (file.getName().lastIndexOf('.') > 0 && file.getName().substring(file.getName().lastIndexOf('.')).equals(".zip")) { buildLog.info("Adding zip file " + file); File zipTmp = new File(instance.getRootDir(), file.getName(). substring(0, file.getName().lastIndexOf('.'))); if (zipTmp.exists()) FileUtils.recursiveDelete(zipTmp); zipTmp.mkdir(); try { ZipUtils.ExtractAllFromZip(new ZipFile(file), zipTmp); } catch (ZipException e) { e.printStackTrace(); buildLog.warning("Failed to open zip file: " + file + "\n" + e.getMessage()); } instance.recursiveSetInstallTime(zipTmp, instance.getInstallTime(file)); for (File f : zipTmp.listFiles()) { recursiveAdd(f, dest); } zipTmp.delete(); } // Other files else { buildLog.info("Adding file " + file); File tcopy = new File(dest, file.getName()); if (!tcopy.exists() || instance.getInstallTime(tcopy) < instance.getInstallTime(file)) { if (!tcopy.getParentFile().exists()) tcopy.getParentFile().mkdirs(); FileUtils.copyFile(file, tcopy, true); } } } } }