public AsciiBytes substring(int beginIndex, int endIndex) { int length = endIndex - beginIndex; if (this.offset + length > this.bytes.length) { throw new IndexOutOfBoundsException(); } return new AsciiBytes(this.bytes, this.offset + beginIndex, length); }
@Override public void visitFileHeader(CentralDirectoryFileHeader fileHeader, int dataOffset) { AsciiBytes name = fileHeader.getName(); if (name.startsWith(META_INF) && name.endsWith(SIGNATURE_FILE_EXTENSION)) { JarFile.this.signed = true; } }
private JarFile createJarFileFromDirectoryEntry(JarEntry entry) throws IOException { AsciiBytes name = entry.getAsciiBytesName(); JarEntryFilter filter = (candidate) -> { if (candidate.startsWith(name) && !candidate.equals(name)) { return candidate.substring(name.length()); } return null; }; return new JarFile(this.rootFile, this.pathFromRoot + "!/" + entry.getName().substring(0, name.length() - 1), this.data, filter, JarFileType.NESTED_DIRECTORY, this.manifestSupplier); }
public boolean matches(CharSequence name, char suffix) { int charIndex = 0; int nameLen = name.length(); int totalLen = nameLen + ((suffix != 0) ? 1 : 0); for (int i = this.offset; i < this.offset + this.length; i++) { int b = this.bytes[i]; int remainingUtfBytes = getNumberOfUtfBytes(b) - 1; b &= INITIAL_BYTE_BITMASK[remainingUtfBytes]; for (int j = 0; j < remainingUtfBytes; j++) { b = (b << 6) + (this.bytes[++i] & SUBSEQUENT_BYTE_BITMASK); } char c = getChar(name, suffix, charIndex++); if (b <= 0xFFFF) { if (c != b) { return false; } } else { if (c != ((b >> 0xA) + 0xD7C0)) { return false; } c = getChar(name, suffix, charIndex++); if (c != ((b & 0x3FF) + 0xDC00)) { return false; } } } return charIndex == totalLen; }
... import org.springframework.boot.loader.jar.JarEntryData; import org.springframework.boot.loader.jar.JarEntryFilter; import org.springframework.boot.loader.jar.JarFile; import org.springframework.boot.loader.tools.JarWriter; import org.springframework.boot.loader.util.AsciiBytes; ... JarWriter writer = new JarWriter(destination); try { JarFile filteredJarFile = sourceJar.getFilteredJarFile(new JarEntryFilter() { @Override public AsciiBytes apply(AsciiBytes name, JarEntryData entryData) { String string = name.toString(); String exp = "^a.*"; if (string.matches(exp)) { string = string.replaceFirst(exp, "replaced"); return new AsciiBytes(string); } return name; } }); writer.writeEntries(filteredJarFile); } finally { try { writer.close(); } catch (Exception ex) { ex.printStackTrace(); } }
private <T extends FileHeader> T getEntry(int hashCode, CharSequence name, char suffix, Class<T> type, boolean cacheEntry, AsciiBytes nameAlias) { int index = getFirstIndex(hashCode); while (index >= 0 && index < this.size && this.hashCodes[index] == hashCode) { T entry = getEntry(index, type, cacheEntry, nameAlias); if (entry.hasName((nameAlias != null) ? nameAlias.toString() : name, suffix)) { return entry; } index++; } return null; }
private void add(AsciiBytes name, int dataOffset) { this.hashCodes[this.size] = name.hashCode(); this.centralDirectoryOffsets[this.size] = dataOffset; this.positions[this.size] = this.size; this.size++; }
@Override public boolean hasName(CharSequence name, char suffix) { return this.name.matches(name, suffix); }
public boolean isDirectory() { return this.name.endsWith(SLASH); }
@Override public int hashCode() { int hash = this.hash; if (hash == 0 && this.bytes.length > 0) { for (int i = this.offset; i < this.offset + this.length; i++) { int b = this.bytes[i]; int remainingUtfBytes = getNumberOfUtfBytes(b) - 1; b &= INITIAL_BYTE_BITMASK[remainingUtfBytes]; for (int j = 0; j < remainingUtfBytes; j++) { b = (b << 6) + (this.bytes[++i] & SUBSEQUENT_BYTE_BITMASK); } if (b <= 0xFFFF) { hash = 31 * hash + b; } else { hash = 31 * hash + ((b >> 0xA) + 0xD7C0); hash = 31 * hash + ((b & 0x3FF) + 0xDC00); } } this.hash = hash; } return hash; }
private void parseEntries(CentralDirectoryEndRecord endRecord, RandomAccessData centralDirectoryData) throws IOException { byte[] bytes = centralDirectoryData.read(0, centralDirectoryData.getSize()); CentralDirectoryFileHeader fileHeader = new CentralDirectoryFileHeader(); int dataOffset = 0; for (int i = 0; i < endRecord.getNumberOfRecords(); i++) { fileHeader.load(bytes, dataOffset, null, 0, null); visitFileHeader(dataOffset, fileHeader); dataOffset += CENTRAL_DIRECTORY_HEADER_BASE_SIZE + fileHeader.getName().length() + fileHeader.getComment().length() + fileHeader.getExtra().length; } }
private StringSequence decode(StringSequence source) { if (source.isEmpty() || (source.indexOf('%') < 0)) { return source; } ByteArrayOutputStream bos = new ByteArrayOutputStream(source.length()); write(source.toString(), bos); // AsciiBytes is what is used to store the JarEntries so make it symmetric return new StringSequence(AsciiBytes.toString(bos.toByteArray())); }
private <T extends FileHeader> T doGetEntry(CharSequence name, Class<T> type, boolean cacheEntry, AsciiBytes nameAlias) { int hashCode = AsciiBytes.hashCode(name); T entry = getEntry(hashCode, name, NO_SUFFIX, type, cacheEntry, nameAlias); if (entry == null) { hashCode = AsciiBytes.hashCode(hashCode, SLASH); entry = getEntry(hashCode, name, SLASH, type, cacheEntry, nameAlias); } return entry; }
@Override public boolean hasName(CharSequence name, char suffix) { return this.name.matches(name, suffix); }
JarEntry(JarFile jarFile, CentralDirectoryFileHeader header, AsciiBytes nameAlias) { super((nameAlias != null) ? nameAlias.toString() : header.getName().toString()); this.name = (nameAlias != null) ? nameAlias : header.getName(); this.jarFile = jarFile; this.localHeaderOffset = header.getLocalHeaderOffset(); setCompressedSize(header.getCompressedSize()); setMethod(header.getMethod()); setCrc(header.getCrc()); setComment(header.getComment().toString()); setSize(header.getSize()); setTime(header.getTime()); setExtra(header.getExtra()); }
dataOffset = 0; this.name = new AsciiBytes(data, dataOffset, (int) nameLength); if (filter != null) { this.name = filter.apply(this.name); this.comment = new AsciiBytes(data, (int) (dataOffset + nameLength + extraLength), (int) commentLength);
private <T extends FileHeader> T getEntry(CharSequence name, Class<T> type, boolean cacheEntry) { T entry = doGetEntry(name, type, cacheEntry, null); if (!isMetaInfEntry(name) && isMultiReleaseJar()) { int version = RUNTIME_VERSION; AsciiBytes nameAlias = (entry instanceof JarEntry) ? ((JarEntry) entry).getAsciiBytesName() : new AsciiBytes(name.toString()); while (version > BASE_VERSION) { T versionedEntry = doGetEntry("META-INF/versions/" + version + "/" + name, type, cacheEntry, nameAlias); if (versionedEntry != null) { return versionedEntry; } version--; } } return entry; }