@NotNull protected Map<String, EntryInfo> initEntries() { synchronized (lock) { Map<String, EntryInfo> map = myRelPathsToEntries.get(); if (map == null) { final ZipInputStream zip = getZip(); map = new HashMap<String, EntryInfo>(); if (zip != null) { map.put("", new EntryInfo("", null, true, new byte[0])); try { ZipEntry entry = zip.getNextEntry(); while (entry != null) { final String name = entry.getName(); final boolean isDirectory = name.endsWith("/"); if (entry.getExtra() == null) { byte[] cont = new byte[(int) entry.getSize()]; ByteArrayOutputStream byteArray = new ByteArrayOutputStream(); InputStream stream = getZip(); if (stream != null) { int tmp; if ((tmp = stream.read(cont)) == entry.getSize()) { byteArray.write(cont, 0, tmp); entry.setExtra(byteArray.toByteArray()); } else { int readFromIS = tmp; if (tmp < entry.getSize()) { byteArray.write(cont, 0, tmp); while (((tmp = stream.read(cont)) != -1) && (tmp + readFromIS <= entry.getSize())) { byteArray.write(cont, 0, tmp); readFromIS += tmp; } entry.setExtra(byteArray.toByteArray()); } } } } getOrCreate( isDirectory ? name.substring(0, name.length() - 1) : name, isDirectory, map, entry.getExtra()); entry = zip.getNextEntry(); } } catch (IOException e) { e.printStackTrace(); } myRelPathsToEntries = new SoftReference<Map<String, EntryInfo>>(map); } } return map; } }
/** * Open the next entry from the zip archive, and return its description. If the previous entry * wasn't closed, this method will close it. */ public ZipEntry getNextEntry() throws IOException { if (crc == null) throw new IOException("Stream closed."); if (entry != null) closeEntry(); int header = readLeInt(); if (header == CENSIG) { /* Central Header reached. */ close(); return null; } if (header != LOCSIG) throw new ZipException("Wrong Local header signature: " + Integer.toHexString(header)); /* skip version */ readLeShort(); flags = readLeShort(); method = readLeShort(); int dostime = readLeInt(); int crc = readLeInt(); csize = readLeInt(); size = readLeInt(); int nameLen = readLeShort(); int extraLen = readLeShort(); if (method == ZipOutputStream.STORED && csize != size) throw new ZipException("Stored, but compressed != uncompressed"); byte[] buffer = new byte[nameLen]; readFully(buffer); String name; try { name = new String(buffer, "UTF-8"); } catch (UnsupportedEncodingException uee) { throw new AssertionError(uee); } entry = createZipEntry(name); entryAtEOF = false; entry.setMethod(method); if ((flags & 8) == 0) { entry.setCrc(crc & 0xffffffffL); entry.setSize(size & 0xffffffffL); entry.setCompressedSize(csize & 0xffffffffL); } entry.setDOSTime(dostime); if (extraLen > 0) { byte[] extra = new byte[extraLen]; readFully(extra); entry.setExtra(extra); } if (method == ZipOutputStream.DEFLATED && avail > 0) { System.arraycopy(buf, len - avail, buf, 0, avail); len = avail; avail = 0; inf.setInput(buf, 0, len); } return entry; }
protected void writeDocument(String path, ExportedDocument doc) throws IOException { if (path.equals("/") || path.length() == 0) { path = ""; } else { // avoid adding a root entry path += '/'; ZipEntry entry = new ZipEntry(path); // store the number of child as an extra info on the entry entry.setExtra(new DWord(doc.getFilesCount()).getBytes()); out.putNextEntry(entry); out.closeEntry(); // System.out.println(">> add entry: "+entry.getName()); } // write metadata ZipEntry entry = new ZipEntry(path + ExportConstants.DOCUMENT_FILE); out.putNextEntry(entry); try { writeXML(doc.getDocument(), out); } finally { out.closeEntry(); // System.out.println(">> add entry: "+entry.getName()); } // write external documents for (Map.Entry<String, Document> ext : doc.getDocuments().entrySet()) { String fileName = ext.getKey() + ".xml"; entry = new ZipEntry(path + fileName); out.putNextEntry(entry); try { writeXML(ext.getValue(), out); } finally { out.closeEntry(); } } // write blobs Map<String, Blob> blobs = doc.getBlobs(); for (Map.Entry<String, Blob> blobEntry : blobs.entrySet()) { String fileName = blobEntry.getKey(); entry = new ZipEntry(path + fileName); out.putNextEntry(entry); try (InputStream in = blobEntry.getValue().getStream()) { IOUtils.copy(in, out); } // DO NOT CALL out.close(), we want to keep writing to it out.closeEntry(); } }
/** * Unfortunately {@link java.util.zip.ZipOutputStream java.util.zip.ZipOutputStream} seems to * access the extra data directly, so overriding getExtra doesn't help - we need to modify super's * data directly. */ protected void setExtra() { super.setExtra(ExtraFieldUtils.mergeLocalFileDataData(getAllExtraFieldsNoCopy())); }
/** * Unfortunately {@link java.util.zip.ZipOutputStream java.util.zip.ZipOutputStream} seems to * access the extra data directly, so overriding getExtra doesn't help - we need to modify super's * data directly. * * @since 1.1 */ protected void setExtra() { super.setExtra(ExtraFieldUtils.mergeLocalFileDataData(getExtraFields(true))); }
/** Updates an existing jar file. */ boolean update(InputStream in, OutputStream out, InputStream newManifest, JarIndex jarIndex) throws IOException { ZipInputStream zis = new ZipInputStream(in); ZipOutputStream zos = new JarOutputStream(out); ZipEntry e = null; boolean foundManifest = false; boolean updateOk = true; if (jarIndex != null) { addIndex(jarIndex, zos); } // put the old entries first, replace if necessary while ((e = zis.getNextEntry()) != null) { String name = e.getName(); boolean isManifestEntry = equalsIgnoreCase(name, MANIFEST_NAME); if ((jarIndex != null && equalsIgnoreCase(name, INDEX_NAME)) || (Mflag && isManifestEntry)) { continue; } else if (isManifestEntry && ((newManifest != null) || (ename != null) || (pname != null))) { foundManifest = true; if (newManifest != null) { // Don't read from the newManifest InputStream, as we // might need it below, and we can't re-read the same data // twice. FileInputStream fis = new FileInputStream(mname); boolean ambiguous = isAmbiguousMainClass(new Manifest(fis)); fis.close(); if (ambiguous) { return false; } } // Update the manifest. Manifest old = new Manifest(zis); if (newManifest != null) { old.read(newManifest); } if (!updateManifest(old, zos)) { return false; } } else { if (!entryMap.containsKey(name)) { // copy the old stuff // do our own compression ZipEntry e2 = new ZipEntry(name); e2.setMethod(e.getMethod()); e2.setTime(e.getTime()); e2.setComment(e.getComment()); e2.setExtra(e.getExtra()); if (e.getMethod() == ZipEntry.STORED) { e2.setSize(e.getSize()); e2.setCrc(e.getCrc()); } zos.putNextEntry(e2); copy(zis, zos); } else { // replace with the new files File f = entryMap.get(name); addFile(zos, f); entryMap.remove(name); entries.remove(f); } } } // add the remaining new files for (File f : entries) { addFile(zos, f); } if (!foundManifest) { if (newManifest != null) { Manifest m = new Manifest(newManifest); updateOk = !isAmbiguousMainClass(m); if (updateOk) { if (!updateManifest(m, zos)) { updateOk = false; } } } else if (ename != null || pname != null) { if (!updateManifest(new Manifest(), zos)) { updateOk = false; } } } zis.close(); zos.close(); return updateOk; }