Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
Glavo committed Mar 28, 2024
1 parent 57018be commit bbf186d
Show file tree
Hide file tree
Showing 13 changed files with 260 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@
import org.jackhuang.hmcl.util.i18n.I18n;
import org.jackhuang.hmcl.util.io.CompressingUtils;
import org.jackhuang.hmcl.util.io.FileUtils;
import org.jackhuang.hmcl.util.io.IOUtils;
import org.jackhuang.hmcl.util.io.NetworkUtils;
import org.jetbrains.annotations.NotNull;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
Expand Down Expand Up @@ -294,9 +294,9 @@ class ModInfoDialog extends JFXDialogLayout {
try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(modInfo.getModInfo().getFile())) {
Path iconPath = fs.getPath(modInfo.getModInfo().getLogoPath());
if (Files.exists(iconPath)) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
Files.copy(iconPath, stream);
return new ByteArrayInputStream(stream.toByteArray());
try (InputStream in = Files.newInputStream(iconPath)) {
return IOUtils.readFully(in).toInputStream();
}
}
}
return null;
Expand Down
15 changes: 6 additions & 9 deletions HMCLCore/src/main/java/org/jackhuang/hmcl/auth/offline/Skin.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,10 @@
import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.StringUtils;
import org.jackhuang.hmcl.util.gson.JsonUtils;
import org.jackhuang.hmcl.util.io.ByteArrayOutputBuffer;
import org.jackhuang.hmcl.util.io.FileUtils;
import org.jetbrains.annotations.Nullable;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
Expand Down Expand Up @@ -245,22 +244,20 @@ protected EnumCheckETag shouldCheckETag() {

@Override
protected Context getContext(URLConnection conn, boolean checkETag) throws IOException {
ByteArrayOutputBuffer output = new ByteArrayOutputBuffer(ByteArrayOutputBuffer.getRecommendedSize(conn.getContentLengthLong()));
return new Context() {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();

@Override
public void write(byte[] buffer, int offset, int len) {
baos.write(buffer, offset, len);
public int read(InputStream inputStream) throws IOException {
return output.read(inputStream);
}

@Override
public void close() throws IOException {
if (!isSuccess()) return;

setResult(new ByteArrayInputStream(baos.toByteArray()));

setResult(output.toInputStream());
if (checkETag) {
repository.cacheBytes(baos.toByteArray(), conn);
repository.cacheBytes(output.getBuffer(), output.size(), conn);
}
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@
import org.jackhuang.hmcl.util.MurmurHash2;
import org.jackhuang.hmcl.util.Pair;
import org.jackhuang.hmcl.util.StringUtils;
import org.jackhuang.hmcl.util.io.ByteArrayOutputBuffer;
import org.jackhuang.hmcl.util.io.HttpRequest;
import org.jackhuang.hmcl.util.io.JarUtils;
import org.jetbrains.annotations.Nullable;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
Expand Down Expand Up @@ -140,21 +140,21 @@ public SearchResult search(String gameVersion, @Nullable RemoteModRepository.Cat

@Override
public Optional<RemoteMod.Version> getRemoteVersionByLocalFile(LocalModFile localModFile, Path file) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ByteArrayOutputBuffer buffer = new ByteArrayOutputBuffer();
try (InputStream stream = Files.newInputStream(file)) {
byte[] buf = new byte[1024];
int len;
while ((len = stream.read(buf, 0, buf.length)) != -1) {
for (int i = 0; i < len; i++) {
byte b = buf[i];
if (b != 0x9 && b != 0xa && b != 0xd && b != 0x20) {
baos.write(b);
buffer.write(b);
}
}
}
}

long hash = Integer.toUnsignedLong(MurmurHash2.hash32(baos.toByteArray(), baos.size(), 1));
long hash = Integer.toUnsignedLong(MurmurHash2.hash32(buffer.getBuffer(), buffer.size(), 1));

Response<FingerprintMatchesResult> response = HttpRequest.POST(PREFIX + "/v1/fingerprints")
.json(mapOf(pair("fingerprints", Collections.singletonList(hash))))
Expand Down
8 changes: 2 additions & 6 deletions HMCLCore/src/main/java/org/jackhuang/hmcl/task/FetchTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import org.jackhuang.hmcl.event.EventBus;
import org.jackhuang.hmcl.util.CacheRepository;
import org.jackhuang.hmcl.util.ToStringBuilder;
import org.jackhuang.hmcl.util.io.IOUtils;
import org.jackhuang.hmcl.util.io.NetworkUtils;
import org.jackhuang.hmcl.util.io.ResponseCodeException;

Expand Down Expand Up @@ -132,15 +131,12 @@ public void execute() throws Exception {
long contentLength = conn.getContentLength();
try (Context context = getContext(conn, checkETag); InputStream stream = conn.getInputStream()) {
int lastDownloaded = 0, downloaded = 0;
byte[] buffer = new byte[IOUtils.DEFAULT_BUFFER_SIZE];
while (true) {
if (isCancelled()) break;

int len = stream.read(buffer);
int len = context.read(stream);
if (len == -1) break;

context.write(buffer, 0, len);

downloaded += len;

if (contentLength >= 0) {
Expand Down Expand Up @@ -224,7 +220,7 @@ public String toString() {
protected static abstract class Context implements Closeable {
private boolean success;

public abstract void write(byte[] buffer, int offset, int len) throws IOException;
public abstract int read(InputStream inputStream) throws IOException;

public final void withResult(boolean success) {
this.success = success;
Expand Down
18 changes: 11 additions & 7 deletions HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@
*/
package org.jackhuang.hmcl.task;

import org.jackhuang.hmcl.util.io.ByteArrayOutputBuffer;
import org.jackhuang.hmcl.util.io.FileUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
Expand Down Expand Up @@ -72,23 +73,26 @@ protected void useCachedResult(Path cachedFile) throws IOException {

@Override
protected Context getContext(URLConnection conn, boolean checkETag) {
ByteArrayOutputBuffer output = new ByteArrayOutputBuffer(ByteArrayOutputBuffer.getRecommendedSize(conn.getContentLengthLong()));
return new Context() {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();

@Override
public void write(byte[] buffer, int offset, int len) {
baos.write(buffer, offset, len);
public int read(InputStream inputStream) throws IOException {
return output.read(inputStream);
}

@Override
public void close() throws IOException {
if (!isSuccess()) return;

String result = baos.toString(charset.name());
String result = output.toString(charset);
setResult(result);

if (checkETag) {
repository.cacheText(result, conn);
if (charset == UTF_8) {
repository.cacheBytes(output.getBuffer(), output.size(), conn);
} else {
repository.cacheBytes(result.getBytes(UTF_8), conn);
}
}
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLConnection;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
Expand Down Expand Up @@ -213,20 +214,23 @@ public void cacheRemoteFile(Path downloaded, URLConnection conn) throws IOExcept
}, conn);
}

public void cacheText(String text, URLConnection conn) throws IOException {
cacheBytes(text.getBytes(UTF_8), conn);
public void cacheBytes(byte[] bytes, URLConnection conn) throws IOException {
cacheBytes(bytes, bytes.length, conn);
}

public void cacheBytes(byte[] bytes, URLConnection conn) throws IOException {
public void cacheBytes(byte[] bytes, int length, URLConnection conn) throws IOException {
cacheData(() -> {
String hash = DigestUtils.digestToString(SHA1, bytes);
String hash = DigestUtils.digestToString(SHA1, bytes, length);
Path cached = getFile(SHA1, hash);
FileUtils.writeBytes(cached, bytes);
Files.createDirectories(cached.getParent());
try (OutputStream out = Files.newOutputStream(cached)) {
out.write(bytes, 0, length);
}
return new CacheResult(hash, cached);
}, conn);
}

public synchronized void cacheData(ExceptionalSupplier<CacheResult, IOException> cacheSupplier, URLConnection conn) throws IOException {
private synchronized void cacheData(ExceptionalSupplier<CacheResult, IOException> cacheSupplier, URLConnection conn) throws IOException {
String eTag = conn.getHeaderField("ETag");
if (eTag == null) return;
String url = conn.getURL().toString();
Expand All @@ -243,11 +247,11 @@ public synchronized void cacheData(ExceptionalSupplier<CacheResult, IOException>
}
}

private static class CacheResult {
private static final class CacheResult {
public String hash;
public Path cachedFile;

public CacheResult(String hash, Path cachedFile) {
CacheResult(String hash, Path cachedFile) {
this.hash = hash;
this.cachedFile = cachedFile;
}
Expand Down Expand Up @@ -289,7 +293,7 @@ public void saveETagIndex() throws IOException {
try (FileChannel channel = FileChannel.open(indexFile, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE)) {
FileLock lock = channel.lock();
try {
ETagIndex indexOnDisk = JsonUtils.fromMaybeMalformedJson(new String(IOUtils.readFullyWithoutClosing(Channels.newInputStream(channel)), UTF_8), ETagIndex.class);
ETagIndex indexOnDisk = JsonUtils.fromMaybeMalformedJson(IOUtils.readFullyAsStringWithClosing(Channels.newInputStream(channel)), ETagIndex.class);
Map<String, ETagItem> newIndex = joinETagIndexes(indexOnDisk == null ? null : indexOnDisk.eTag, index.values());
channel.truncate(0);
ByteBuffer writeTo = ByteBuffer.wrap(JsonUtils.GSON.toJson(new ETagIndex(newIndex.values())).getBytes(UTF_8));
Expand Down
10 changes: 10 additions & 0 deletions HMCLCore/src/main/java/org/jackhuang/hmcl/util/DigestUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ public static byte[] digest(String algorithm, byte[] data) {
return getDigest(algorithm).digest(data);
}

public static byte[] digest(String algorithm, byte[] data, int length) {
MessageDigest digest = getDigest(algorithm);
digest.update(data, 0, length);
return digest.digest();
}

public static byte[] digest(String algorithm, Path path) throws IOException {
try (InputStream is = Files.newInputStream(path)) {
return digest(algorithm, is);
Expand All @@ -65,6 +71,10 @@ public static String digestToString(String algorithm, byte[] data) throws IOExce
return Hex.encodeHex(digest(algorithm, data));
}

public static String digestToString(String algorithm, byte[] data, int length) throws IOException {
return Hex.encodeHex(digest(algorithm, data, length));
}

public static String digestToString(String algorithm, Path path) throws IOException {
return Hex.encodeHex(digest(algorithm, path));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package org.jackhuang.hmcl.util.io;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Arrays;

/**
* @author Glavo
*/
public final class ByteArrayOutputBuffer extends ByteArrayOutputStream {

private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

public static int getRecommendedSize(long size) {
if (size < 0)
return IOUtils.DEFAULT_BUFFER_SIZE;
else if (size >= MAX_ARRAY_SIZE)
return MAX_ARRAY_SIZE;
else
return Math.max(32, (int) size);
}

public ByteArrayOutputBuffer() {
this(IOUtils.DEFAULT_BUFFER_SIZE);
}

public ByteArrayOutputBuffer(int size) {
super(size);
}

private void prepare(int next) {
assert next > 0;

int currentCapacity = buf.length;
int currentSize = this.count;
int minCapacity = currentSize + next;
if (minCapacity < 0 || minCapacity > MAX_ARRAY_SIZE) {
throw new OutOfMemoryError();
}

if (currentCapacity >= minCapacity) {
return;
}

int nextCapacity = currentCapacity < MAX_ARRAY_SIZE / 2 ? Math.max(minCapacity, currentSize * 2) : MAX_ARRAY_SIZE;
buf = Arrays.copyOf(buf, nextCapacity);
}

public byte[] getBuffer() {
return this.buf;
}

public int read(InputStream input) throws IOException {
int available = input.available();
if (available > 0) {
prepare(available);
}

int maxRead = buf.length - count;
if (maxRead == 0) {
int b = input.read();
if (b < 0) {
return -1;
} else {
write(b);
return 1;
}
}

int n = input.read(buf, count, maxRead);
if (n > 0) {
count += n;
}
return n;
}

public void copyFrom(InputStream input) throws IOException {
int available = input.available();
if (available > 0) {
prepare(available);
} else if (count == buf.length) {
prepare(1);
}

while (true) {
int n = input.read(buf, count, buf.length - count);
if (n <= 0) {
break;
}

count += n;
if (count == buf.length) {
if (available > 0) {
int b = input.read();
if (b < 0) {
break;
} else {
write(b);
}
} else {
prepare(1);
}
}
}
}

public byte[] toByteArrayWithoutCopy() {
if (buf.length == count) {
return buf;
} else {
return Arrays.copyOf(buf, count);
}
}

public InputStream toInputStream() {
return new ByteArrayInputStream(this.buf, 0, this.count);
}

@SuppressWarnings("Since15")
public String toString(Charset charset) {
return new String(buf, 0, count, charset);
}
}

0 comments on commit bbf186d

Please sign in to comment.