/** * Unpacks a pack file. * * @param file the pack file meta-data * @param packInputStream the pack input stream * @param target the target * @throws IOException for any I/O error * @throws InstallerException for any installer exception */ @Override public void unpack(PackFile file, ObjectInputStream packInputStream, File target) throws IOException, InstallerException { // Old way of doing the job by using the (absolute) sourcepath. // Since this is very likely to fail and does not conform to the documentation prefer using // relative // path's // pis = new FileInputStream(pf.sourcePath); File resolvedFile = new File(sourceDir, file.getRelativeSourcePath()); if (!resolvedFile.exists()) { // try alternative destination - the current working directory // user.dir is likely (depends on launcher type) the current directory of the executable or // jar-file... final File userDir = new File(System.getProperty("user.dir")); resolvedFile = new File(userDir, file.getRelativeSourcePath()); } if (resolvedFile.exists()) { InputStream stream = new FileInputStream(resolvedFile); // may have a different length & last modified than we had at compile time, therefore we have // to // build a new PackFile for the copy process... file = new PackFile( resolvedFile.getParentFile(), resolvedFile, file.getTargetPath(), file.osConstraints(), file.override(), file.overrideRenameTo(), file.blockable(), file.getAdditionals()); copy(file, stream, target); } else { // file not found. Since this file was loosely bundled, continue with the installation. logger.warning("Could not find loosely bundled file: " + file.getRelativeSourcePath()); if (prompt.confirm( Prompt.Type.WARNING, "File not found", "Could not find loosely bundled file: " + file.getRelativeSourcePath(), Prompt.Options.OK_CANCEL) == Prompt.Option.OK) { throw new InstallerException("Installation cancelled"); } } }
/** Write Packs to primary jar or each to a separate jar. */ protected void writePacks() throws Exception { final int num = packsList.size(); sendMsg("Writing " + num + " Pack" + (num > 1 ? "s" : "") + " into installer"); // Map to remember pack number and bytes offsets of back references Map<File, Object[]> storedFiles = new HashMap<File, Object[]>(); // Pack200 files map Map<Integer, File> pack200Map = new HashMap<Integer, File>(); int pack200Counter = 0; // Force UTF-8 encoding in order to have proper ZipEntry names. primaryJarStream.setEncoding("utf-8"); // First write the serialized files and file metadata data for each pack // while counting bytes. int packNumber = 0; IXMLElement root = new XMLElementImpl("packs"); for (PackInfo packInfo : packsList) { Pack pack = packInfo.getPack(); pack.nbytes = 0; if ((pack.id == null) || (pack.id.length() == 0)) { pack.id = pack.name; } // create a pack specific jar if required // REFACTOR : Repare web installer // REFACTOR : Use a mergeManager for each packages that will be added to the main merger // if (packJarsSeparate) { // See installer.Unpacker#getPackAsStream for the counterpart // String name = baseFile.getName() + ".pack-" + pack.id + ".jar"; // packStream = IoHelper.getJarOutputStream(name, baseFile.getParentFile()); // } sendMsg("Writing Pack " + packNumber + ": " + pack.name, PackagerListener.MSG_VERBOSE); // Retrieve the correct output stream org.apache.tools.zip.ZipEntry entry = new org.apache.tools.zip.ZipEntry(RESOURCES_PATH + "packs/pack-" + pack.id); primaryJarStream.putNextEntry(entry); primaryJarStream.flush(); // flush before we start counting ByteCountingOutputStream dos = new ByteCountingOutputStream(outputStream); ObjectOutputStream objOut = new ObjectOutputStream(dos); // We write the actual pack files objOut.writeInt(packInfo.getPackFiles().size()); for (PackFile packFile : packInfo.getPackFiles()) { boolean addFile = !pack.loose; boolean pack200 = false; File file = packInfo.getFile(packFile); if (file.getName().toLowerCase().endsWith(".jar") && info.isPack200Compression() && isNotSignedJar(file)) { packFile.setPack200Jar(true); pack200 = true; } // use a back reference if file was in previous pack, and in // same jar Object[] info = storedFiles.get(file); if (info != null && !packJarsSeparate) { packFile.setPreviousPackFileRef((String) info[0], (Long) info[1]); addFile = false; } objOut.writeObject(packFile); // base info if (addFile && !packFile.isDirectory()) { long pos = dos.getByteCount(); // get the position if (pack200) { /* * Warning! * * Pack200 archives must be stored in separated streams, as the Pack200 unpacker * reads the entire stream... * * See http://java.sun.com/javase/6/docs/api/java/util/jar/Pack200.Unpacker.html */ pack200Map.put(pack200Counter, file); objOut.writeInt(pack200Counter); pack200Counter = pack200Counter + 1; } else { FileInputStream inStream = new FileInputStream(file); long bytesWritten = IoHelper.copyStream(inStream, objOut); inStream.close(); if (bytesWritten != packFile.length()) { throw new IOException("File size mismatch when reading " + file); } } storedFiles.put(file, new Object[] {pack.id, pos}); } // even if not written, it counts towards pack size pack.nbytes += packFile.size(); } // Write out information about parsable files objOut.writeInt(packInfo.getParsables().size()); for (ParsableFile parsableFile : packInfo.getParsables()) { objOut.writeObject(parsableFile); } // Write out information about executable files objOut.writeInt(packInfo.getExecutables().size()); for (ExecutableFile executableFile : packInfo.getExecutables()) { objOut.writeObject(executableFile); } // Write out information about updatecheck files objOut.writeInt(packInfo.getUpdateChecks().size()); for (UpdateCheck updateCheck : packInfo.getUpdateChecks()) { objOut.writeObject(updateCheck); } // Cleanup objOut.flush(); if (!compressor.useStandardCompression()) { outputStream.close(); } primaryJarStream.closeEntry(); // close pack specific jar if required if (packJarsSeparate) { primaryJarStream.closeAlways(); } IXMLElement child = new XMLElementImpl("pack", root); child.setAttribute("nbytes", Long.toString(pack.nbytes)); child.setAttribute("name", pack.name); if (pack.id != null) { child.setAttribute("id", pack.id); } root.addChild(child); packNumber++; } // Now that we know sizes, write pack metadata to primary jar. primaryJarStream.putNextEntry(new org.apache.tools.zip.ZipEntry(RESOURCES_PATH + "packs.info")); ObjectOutputStream out = new ObjectOutputStream(primaryJarStream); out.writeInt(packsList.size()); for (PackInfo packInfo : packsList) { out.writeObject(packInfo.getPack()); } out.flush(); primaryJarStream.closeEntry(); // Pack200 files Pack200.Packer packer = createAgressivePack200Packer(); for (Integer key : pack200Map.keySet()) { File file = pack200Map.get(key); primaryJarStream.putNextEntry( new org.apache.tools.zip.ZipEntry(RESOURCES_PATH + "packs/pack200-" + key)); JarFile jar = new JarFile(file); packer.pack(jar, primaryJarStream); jar.close(); primaryJarStream.closeEntry(); } }