Fix syncing TaskWindow.

This commit is contained in:
huanghongxun
2015-09-02 18:57:24 +08:00
parent f9968580af
commit e727ca331f
24 changed files with 83 additions and 474 deletions

View File

@@ -31,6 +31,8 @@ import java.net.URLClassLoader;
import java.security.GeneralSecurityException;
import java.security.cert.X509Certificate;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import java.util.jar.JarFile;
import javax.net.ssl.HostnameVerifier;
@@ -139,7 +141,11 @@ public final class Main implements Runnable {
JarFile jarFile = new JarFile(jar);
String mainClass = jarFile.getManifest().getMainAttributes().getValue("Main-Class");
if (mainClass != null) {
new URLClassLoader(new URL[]{jar.toURI().toURL()}, URLClassLoader.getSystemClassLoader().getParent()).loadClass(mainClass).getMethod("main", String[].class).invoke(null, new Object[]{new String[]{"nofound"}});
ArrayList<String> al = new ArrayList<>(Arrays.asList(args));
al.add("notfound");
new URLClassLoader(new URL[]{jar.toURI().toURL()},
URLClassLoader.getSystemClassLoader().getParent()).loadClass(mainClass)
.getMethod("main", String[].class).invoke(null, new Object[]{al.toArray(new String[0])});
return;
}
}

View File

@@ -43,10 +43,9 @@ public class DefaultGameLauncher extends GameLauncher {
private void register() {
downloadLibrariesEvent.register((sender, t) -> {
final TaskWindow dw = TaskWindow.getInstance();
final TaskWindow.TaskWindowFactory dw = TaskWindow.getInstance();
ParallelTask parallelTask = new ParallelTask();
for (DownloadLibraryJob s : t)
//parallelTask.addDependsTask(new FileDownloadTask(s.url, s.path).setTag(s.name));
parallelTask.addDependsTask(new LibraryDownloadTask(s));
dw.addTask(parallelTask);
boolean flag = true;

View File

@@ -3,7 +3,6 @@ package org.jackhuang.mojang.authlib;
public class Agent {
public static final Agent MINECRAFT = new Agent("Minecraft", 1);
public static final Agent SCROLLS = new Agent("Scrolls", 1);
private final String name;
private final int version;

View File

@@ -1,12 +1,6 @@
package org.jackhuang.mojang.authlib;
import org.jackhuang.mojang.authlib.minecraft.MinecraftSessionService;
public abstract interface AuthenticationService {
public abstract UserAuthentication createUserAuthentication(Agent paramAgent);
public abstract MinecraftSessionService createMinecraftSessionService();
public abstract GameProfileRepository createProfileRepository();
}

View File

@@ -1,5 +0,0 @@
package org.jackhuang.mojang.authlib;
public abstract class BaseAuthenticationService
implements AuthenticationService {
}

View File

@@ -1,6 +0,0 @@
package org.jackhuang.mojang.authlib;
public abstract interface GameProfileRepository {
public abstract void findProfilesByNames(String[] paramArrayOfString, Agent paramAgent, ProfileLookupCallback paramProfileLookupCallback);
}

View File

@@ -14,7 +14,7 @@ import org.jackhuang.hellominecraft.utils.system.IOUtils;
import org.jackhuang.hellominecraft.utils.NetUtils;
import org.jackhuang.hellominecraft.utils.Utils;
public abstract class HttpAuthenticationService extends BaseAuthenticationService {
public abstract class HttpAuthenticationService implements AuthenticationService {
private static final Logger LOGGER = new Logger("HttpAuthenticationService");
private final Proxy proxy;

View File

@@ -1,8 +0,0 @@
package org.jackhuang.mojang.authlib;
public abstract interface ProfileLookupCallback {
public abstract void onProfileLookupSucceeded(GameProfile paramGameProfile);
public abstract void onProfileLookupFailed(GameProfile paramGameProfile, Exception paramException);
}

View File

@@ -1,17 +0,0 @@
package org.jackhuang.mojang.authlib.minecraft;
import org.jackhuang.mojang.authlib.AuthenticationService;
public abstract class BaseMinecraftSessionService
implements MinecraftSessionService {
private final AuthenticationService authenticationService;
protected BaseMinecraftSessionService(AuthenticationService authenticationService) {
this.authenticationService = authenticationService;
}
public AuthenticationService getAuthenticationService() {
return this.authenticationService;
}
}

View File

@@ -1,15 +0,0 @@
package org.jackhuang.mojang.authlib.minecraft;
import org.jackhuang.mojang.authlib.HttpAuthenticationService;
public abstract class HttpMinecraftSessionService extends BaseMinecraftSessionService {
protected HttpMinecraftSessionService(HttpAuthenticationService authenticationService) {
super(authenticationService);
}
@Override
public HttpAuthenticationService getAuthenticationService() {
return (HttpAuthenticationService) super.getAuthenticationService();
}
}

View File

@@ -1,16 +0,0 @@
package org.jackhuang.mojang.authlib.minecraft;
import org.jackhuang.mojang.authlib.GameProfile;
import org.jackhuang.mojang.authlib.exceptions.AuthenticationException;
import org.jackhuang.mojang.authlib.exceptions.AuthenticationUnavailableException;
public abstract interface MinecraftSessionService {
public abstract void joinServer(GameProfile paramGameProfile, String paramString1, String paramString2)
throws AuthenticationException;
public abstract GameProfile hasJoinedServer(GameProfile paramGameProfile, String paramString)
throws AuthenticationUnavailableException;
public abstract GameProfile fillProfileProperties(GameProfile paramGameProfile, boolean paramBoolean);
}

View File

@@ -1,19 +0,0 @@
package org.jackhuang.mojang.authlib.yggdrasil;
public class ProfileIncompleteException extends RuntimeException {
public ProfileIncompleteException() {
}
public ProfileIncompleteException(String message) {
super(message);
}
public ProfileIncompleteException(String message, Throwable cause) {
super(message, cause);
}
public ProfileIncompleteException(Throwable cause) {
super(cause);
}
}

View File

@@ -1,19 +0,0 @@
package org.jackhuang.mojang.authlib.yggdrasil;
public class ProfileNotFoundException extends RuntimeException {
public ProfileNotFoundException() {
}
public ProfileNotFoundException(String message) {
super(message);
}
public ProfileNotFoundException(String message, Throwable cause) {
super(message, cause);
}
public ProfileNotFoundException(Throwable cause) {
super(cause);
}
}

View File

@@ -11,14 +11,12 @@ import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import org.jackhuang.mojang.authlib.Agent;
import org.jackhuang.mojang.authlib.GameProfile;
import org.jackhuang.mojang.authlib.GameProfileRepository;
import org.jackhuang.mojang.authlib.HttpAuthenticationService;
import org.jackhuang.mojang.authlib.UserAuthentication;
import org.jackhuang.mojang.authlib.exceptions.AuthenticationException;
import org.jackhuang.mojang.authlib.exceptions.AuthenticationUnavailableException;
import org.jackhuang.mojang.authlib.exceptions.InvalidCredentialsException;
import org.jackhuang.mojang.authlib.exceptions.UserMigratedException;
import org.jackhuang.mojang.authlib.minecraft.MinecraftSessionService;
import org.jackhuang.mojang.authlib.properties.PropertyMap;
import org.jackhuang.mojang.authlib.yggdrasil.response.Response;
import org.jackhuang.mojang.util.UUIDTypeAdapter;
@@ -50,16 +48,6 @@ public class YggdrasilAuthenticationService extends HttpAuthenticationService {
return new YggdrasilUserAuthentication(this, agent);
}
@Override
public MinecraftSessionService createMinecraftSessionService() {
return new YggdrasilMinecraftSessionService(this);
}
@Override
public GameProfileRepository createProfileRepository() {
return new YggdrasilGameProfileRepository(this);
}
protected <T extends Response> T makeRequest(URL url, Object input, Class<T> classOfT) throws AuthenticationException {
try {
String jsonResult = input == null ? performGetRequest(url) : performPostRequest(url, this.gson.toJson(input), "application/json");

View File

@@ -1,134 +0,0 @@
package org.jackhuang.mojang.authlib.yggdrasil;
import java.util.HashSet;
import java.util.Set;
import org.jackhuang.hellominecraft.logging.logger.Logger;
import org.jackhuang.hellominecraft.utils.NetUtils;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.mojang.authlib.Agent;
import org.jackhuang.mojang.authlib.GameProfile;
import org.jackhuang.mojang.authlib.GameProfileRepository;
import org.jackhuang.mojang.authlib.ProfileLookupCallback;
import org.jackhuang.mojang.authlib.exceptions.AuthenticationException;
import org.jackhuang.mojang.authlib.yggdrasil.response.ProfileSearchResultsResponse;
public class YggdrasilGameProfileRepository
implements GameProfileRepository {
private static final Logger LOGGER = new Logger("YggdrasilGameProfileRepository");
private static final String BASE_URL = "https://api.mojang.com/";
private static final String SEARCH_PAGE_URL = BASE_URL + "profiles/page/";
private static final int MAX_FAIL_COUNT = 3;
private static final int DELAY_BETWEEN_PAGES = 100;
private static final int DELAY_BETWEEN_FAILURES = 750;
private final YggdrasilAuthenticationService authenticationService;
public YggdrasilGameProfileRepository(YggdrasilAuthenticationService authenticationService) {
this.authenticationService = authenticationService;
}
@Override
public void findProfilesByNames(String[] names, Agent agent, ProfileLookupCallback callback) {
Set<ProfileCriteria> criteria = new HashSet<ProfileCriteria>();
for (String name : names) {
if (StrUtils.isNotBlank(name)) {
criteria.add(new ProfileCriteria(name, agent));
}
}
Exception exception = null;
Set request = new HashSet<ProfileCriteria>(criteria);
int page = 1;
int failCount = 0;
while (!criteria.isEmpty()) {
try {
ProfileSearchResultsResponse response = (ProfileSearchResultsResponse) this.authenticationService.makeRequest(NetUtils.constantURL("https://api.mojang.com/profiles/page/" + page), request, ProfileSearchResultsResponse.class);
failCount = 0;
exception = null;
if ((response.getSize() == 0) || (response.getProfiles().length == 0)) {
LOGGER.debug("Page {} returned empty, aborting search", new Object[]{page});
} else {
LOGGER.debug("Page {} returned {} results of {}, parsing", new Object[]{page, response.getProfiles().length, response.getSize()});
for (GameProfile profile : response.getProfiles()) {
LOGGER.debug("Successfully looked up profile {}", new Object[]{profile});
criteria.remove(new ProfileCriteria(profile.getName(), agent));
callback.onProfileLookupSucceeded(profile);
}
LOGGER.debug("Page {} successfully parsed", new Object[]{page});
page++;
try {
Thread.sleep(DELAY_BETWEEN_PAGES);
} catch (InterruptedException ignored) {
}
}
} catch (AuthenticationException e) {
exception = e;
failCount++;
if (failCount != 3) {
try {
Thread.sleep(DELAY_BETWEEN_FAILURES);
} catch (InterruptedException ignored) {
}
}
}
}
if (criteria.isEmpty()) {
LOGGER.debug("Successfully found every profile requested");
} else {
LOGGER.debug("{} profiles were missing from search results", new Object[]{criteria.size()});
if (exception == null) {
exception = new ProfileNotFoundException("Server did not find the requested profile");
}
for (ProfileCriteria profileCriteria : criteria) {
callback.onProfileLookupFailed(new GameProfile(null, profileCriteria.getName()), exception);
}
}
}
private class ProfileCriteria {
private final String name;
private final String agent;
private ProfileCriteria(String name, Agent agent) {
this.name = name;
this.agent = agent.getName();
}
public String getName() {
return this.name;
}
public String getAgent() {
return this.agent;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if ((o == null) || (getClass() != o.getClass())) {
return false;
}
ProfileCriteria that = (ProfileCriteria) o;
return (this.agent.equals(that.agent)) && (this.name.toLowerCase().equals(that.name.toLowerCase()));
}
@Override
public int hashCode() {
return 31 * this.name.toLowerCase().hashCode() + this.agent.hashCode();
}
@Override
public String toString() {
return "ProfileCriteria{" + "name=" + name + ", agent=" + agent + '}';
}
}
}

View File

@@ -1,97 +0,0 @@
package org.jackhuang.mojang.authlib.yggdrasil;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import org.jackhuang.hellominecraft.logging.logger.Logger;
import org.jackhuang.hellominecraft.utils.NetUtils;
import org.jackhuang.mojang.authlib.GameProfile;
import org.jackhuang.mojang.authlib.HttpAuthenticationService;
import org.jackhuang.mojang.authlib.exceptions.AuthenticationException;
import org.jackhuang.mojang.authlib.exceptions.AuthenticationUnavailableException;
import org.jackhuang.mojang.authlib.minecraft.HttpMinecraftSessionService;
import org.jackhuang.mojang.authlib.yggdrasil.request.JoinMinecraftServerRequest;
import org.jackhuang.mojang.authlib.yggdrasil.response.HasJoinedMinecraftServerResponse;
import org.jackhuang.mojang.authlib.yggdrasil.response.MinecraftProfilePropertiesResponse;
import org.jackhuang.mojang.authlib.yggdrasil.response.Response;
import org.jackhuang.mojang.util.UUIDTypeAdapter;
public class YggdrasilMinecraftSessionService extends HttpMinecraftSessionService {
private static final Logger LOGGER = new Logger("YggdrasilMinecraftSessionService");
private static final String BASE_URL = "https://sessionserver.mojang.com/session/minecraft/";
private static final URL JOIN_URL = NetUtils.constantURL(BASE_URL + "join");
private static final URL CHECK_URL = NetUtils.constantURL(BASE_URL + "hasJoined");
protected YggdrasilMinecraftSessionService(YggdrasilAuthenticationService authenticationService) {
super(authenticationService);
}
@Override
public void joinServer(GameProfile profile, String authenticationToken, String serverId) throws AuthenticationException {
JoinMinecraftServerRequest request = new JoinMinecraftServerRequest();
request.accessToken = authenticationToken;
request.selectedProfile = profile.getId();
request.serverId = serverId;
getAuthenticationService().makeRequest(JOIN_URL, request, Response.class);
}
@Override
public GameProfile hasJoinedServer(GameProfile user, String serverId) throws AuthenticationUnavailableException {
Map arguments = new HashMap();
arguments.put("username", user.getName());
arguments.put("serverId", serverId);
URL url = NetUtils.concatenateURL(CHECK_URL, HttpAuthenticationService.buildQuery(arguments));
try {
HasJoinedMinecraftServerResponse response = (HasJoinedMinecraftServerResponse) getAuthenticationService().makeRequest(url, null, HasJoinedMinecraftServerResponse.class);
if ((response != null) && (response.getId() != null)) {
GameProfile result = new GameProfile(response.getId(), user.getName());
if (response.getProperties() != null) {
result.getProperties().putAll(response.getProperties());
}
return result;
}
return null;
} catch (AuthenticationUnavailableException e) {
throw e;
} catch (AuthenticationException e) {
}
return null;
}
@Override
public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) {
if (profile.getId() == null) {
return profile;
}
try {
URL url = NetUtils.constantURL(new StringBuilder().append("https://sessionserver.mojang.com/session/minecraft/profile/").append(UUIDTypeAdapter.fromUUID(profile.getId())).toString());
url = NetUtils.concatenateURL(url, new StringBuilder().append("unsigned=").append(!requireSecure).toString());
MinecraftProfilePropertiesResponse response = (MinecraftProfilePropertiesResponse) getAuthenticationService().makeRequest(url, null, MinecraftProfilePropertiesResponse.class);
if (response == null) {
LOGGER.debug(new StringBuilder().append("Couldn't fetch profile properties for ").append(profile).append(" as the profile does not exist").toString());
return profile;
}
GameProfile result = new GameProfile(response.getId(), response.getName());
result.getProperties().putAll(response.getProperties());
profile.getProperties().putAll(response.getProperties());
LOGGER.debug(new StringBuilder().append("Successfully fetched profile properties for ").append(profile).toString());
return result;
} catch (Exception e) {
LOGGER.warn(new StringBuilder().append("Couldn't look up profile properties for ").append(profile).toString(), e);
}
return profile;
}
@Override
public YggdrasilAuthenticationService getAuthenticationService() {
return (YggdrasilAuthenticationService) super.getAuthenticationService();
}
}

View File

@@ -1,10 +0,0 @@
package org.jackhuang.mojang.authlib.yggdrasil.request;
import java.util.UUID;
public class JoinMinecraftServerRequest {
public String accessToken;
public UUID selectedProfile;
public String serverId;
}

View File

@@ -1,18 +0,0 @@
package org.jackhuang.mojang.authlib.yggdrasil.response;
import org.jackhuang.mojang.authlib.properties.PropertyMap;
import java.util.UUID;
public class HasJoinedMinecraftServerResponse extends Response {
private UUID id;
private PropertyMap properties;
public UUID getId() {
return this.id;
}
public PropertyMap getProperties() {
return this.properties;
}
}

View File

@@ -1,23 +0,0 @@
package org.jackhuang.mojang.authlib.yggdrasil.response;
import org.jackhuang.mojang.authlib.properties.PropertyMap;
import java.util.UUID;
public class MinecraftProfilePropertiesResponse extends Response {
private UUID id;
private String name;
private PropertyMap properties;
public UUID getId() {
return this.id;
}
public String getName() {
return this.name;
}
public PropertyMap getProperties() {
return this.properties;
}
}

View File

@@ -1,17 +0,0 @@
package org.jackhuang.mojang.authlib.yggdrasil.response;
import org.jackhuang.mojang.authlib.GameProfile;
public class ProfileSearchResultsResponse extends Response {
private GameProfile[] profiles;
private int size;
public GameProfile[] getProfiles() {
return this.profiles;
}
public int getSize() {
return this.size;
}
}

View File

@@ -20,6 +20,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.jackhuang.hellominecraft.HMCLog;
@@ -30,7 +31,7 @@ import org.jackhuang.hellominecraft.HMCLog;
*/
public class TaskList extends Thread {
List<Task> taskQueue = Collections.synchronizedList(new ArrayList());
List<Task> taskQueue = Collections.synchronizedList(new LinkedList<>());
ArrayList<Runnable> allDone = new ArrayList();
ArrayList<DoingDoneListener<Task>> taskListener = new ArrayList();
@@ -143,8 +144,8 @@ public class TaskList extends Thread {
threadPool.clear();
totTask = taskQueue.size();
for (Task taskQueue1 : taskQueue)
executeTask(taskQueue1);
while(!taskQueue.isEmpty())
executeTask(taskQueue.remove(0));
if (shouldContinue)
for (Runnable d : allDone)
d.run();

View File

@@ -13,6 +13,7 @@
</SyntheticProperties>
<Events>
<EventHandler event="windowClosed" listener="java.awt.event.WindowListener" parameters="java.awt.event.WindowEvent" handler="formWindowClosed"/>
<EventHandler event="windowClosing" listener="java.awt.event.WindowListener" parameters="java.awt.event.WindowEvent" handler="formWindowClosing"/>
</Events>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>

View File

@@ -17,6 +17,7 @@
package org.jackhuang.hellominecraft.tasks;
import java.util.ArrayList;
import java.util.LinkedList;
import javax.swing.SwingUtilities;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.HMCLog;
@@ -33,10 +34,14 @@ public class TaskWindow extends javax.swing.JDialog
private static final TaskWindow instance = new TaskWindow();
public static TaskWindow getInstance() {
private static TaskWindow inst() {
instance.clean();
return instance;
}
public static TaskWindowFactory getInstance() {
return new TaskWindowFactory();
}
boolean suc = false;
@@ -75,7 +80,7 @@ public class TaskWindow extends javax.swing.JDialog
}
public boolean start() {
if (taskList.isAlive()) return false;
if (isVisible() || taskList.isAlive()) return false;
pgsTotal.setValue(0);
suc = false;
SwingUtils.clearDefaultTable(lstDownload);
@@ -113,6 +118,9 @@ public class TaskWindow extends javax.swing.JDialog
public void windowClosed(java.awt.event.WindowEvent evt) {
formWindowClosed(evt);
}
public void windowClosing(java.awt.event.WindowEvent evt) {
formWindowClosing(evt);
}
});
btnCancel.setText(bundle.getString("taskwindow.cancel")); // NOI18N
@@ -174,8 +182,13 @@ public class TaskWindow extends javax.swing.JDialog
SwingUtilities.invokeLater(taskList::abort);
HMCLog.log("Tasks have been canceled by user.");
}
taskList = null;
}//GEN-LAST:event_formWindowClosed
private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
// TODO add your handling code here:
}//GEN-LAST:event_formWindowClosing
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnCancel;
private javax.swing.JTable lstDownload;
@@ -262,4 +275,23 @@ public class TaskWindow extends javax.swing.JDialog
SwingUtils.setValueAt(lstDownload, task.getInfo() + ": " + sta, idx, 0);
});
}
public static class TaskWindowFactory {
public static final Object obj = new Object();
LinkedList<Task> ll = new LinkedList<>();
public TaskWindowFactory addTask(Task t) {
ll.add(t);
return this;
}
public boolean start() {
synchronized(obj) {
TaskWindow tw = inst();
for(Task t : ll) tw.addTask(t);
return tw.start();
}
}
}
}

View File

@@ -78,23 +78,19 @@ public class ForgeInstaller {
//forge.format();
File file = new File(gameDir, profile.install.filePath);
file.getParentFile().mkdirs();
FileOutputStream fos = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int c;
while ((c = is.read()) != -1)
bos.write((byte) c);
bos.close();
fos.close();
try (FileOutputStream fos = new FileOutputStream(file); BufferedOutputStream bos = new BufferedOutputStream(fos)) {
int c;
while ((c = is.read()) != -1)
bos.write((byte) c);
}
File minecraftserver = new File(gameDir, "minecraft_server." + profile.install.minecraft + ".jar");
TaskWindow tw = TaskWindow.getInstance();
if (minecraftserver.exists() && JOptionPane.showConfirmDialog(null, "已发现官方服务端文件,是否要重新下载?") == JOptionPane.YES_OPTION) {
tw.clean();
if (!tw.addTask(new FileDownloadTask("https://s3.amazonaws.com/Minecraft.Download/versions/{MCVER}/minecraft_server.{MCVER}.jar".replace("{MCVER}", profile.install.minecraft),
if (!TaskWindow.getInstance().addTask(new FileDownloadTask("https://s3.amazonaws.com/Minecraft.Download/versions/{MCVER}/minecraft_server.{MCVER}.jar".replace("{MCVER}", profile.install.minecraft),
minecraftserver).setTag("minecraft_server")).start())
MessageBox.Show("Minecraft官方服务端下载失败");
}
tw.clean();
TaskWindow.TaskWindowFactory tw = TaskWindow.getInstance();
for (MinecraftLibrary library : profile.versionInfo.libraries) {
library.init();
File lib = new File(gameDir, "libraries" + File.separator + library.formatted + ".pack.xz");
@@ -103,10 +99,10 @@ public class ForgeInstaller {
libURL = library.url;
tw.addTask(new FileDownloadTask(libURL + library.formatted.replace("\\", "/"), lib).setTag(library.name));
}
tw.start();
if (!tw.areTasksFinished())
if (!tw.start())
MessageBox.Show("压缩库下载失败!");
tw.clean();
tw = TaskWindow.getInstance();
for (MinecraftLibrary library : profile.versionInfo.libraries) {
File packxz = new File(gameDir, "libraries" + File.separator + library.formatted + ".pack.xz");
if (packxz.exists()) return;
@@ -117,11 +113,10 @@ public class ForgeInstaller {
libURL = library.url;
tw.addTask(new FileDownloadTask(libURL + library.formatted.replace("\\", "/"), lib).setTag(library.name));
}
tw.start();
if (!tw.areTasksFinished())
if (!tw.start())
MessageBox.Show("库下载失败!");
tw.clean();
ArrayList<String> badLibs = new ArrayList<String>();
ArrayList<String> badLibs = new ArrayList<>();
for (MinecraftLibrary library : profile.versionInfo.libraries) {
File lib = new File(gameDir, "libraries" + File.separator + library.formatted);
File packFile = new File(gameDir, "libraries" + File.separator + library.formatted + ".pack.xz");
@@ -157,17 +152,15 @@ public class ForgeInstaller {
byte[] checksums = Arrays.copyOfRange(decompressed, decompressed.length - len - 8, decompressed.length - 8);
FileOutputStream jarBytes = new FileOutputStream(output);
JarOutputStream jos = new JarOutputStream(jarBytes);
Pack200.newUnpacker().unpack(new ByteArrayInputStream(decompressed), jos);
jos.putNextEntry(new JarEntry("checksums.sha1"));
jos.write(checksums);
jos.closeEntry();
jos.close();
jarBytes.close();
try (FileOutputStream jarBytes = new FileOutputStream(output); JarOutputStream jos = new JarOutputStream(jarBytes)) {
Pack200.newUnpacker().unpack(new ByteArrayInputStream(decompressed), jos);
jos.putNextEntry(new JarEntry("checksums.sha1"));
jos.write(checksums);
jos.closeEntry();
}
}
private static boolean checksumValid(File libPath, List<String> checksums) {
@@ -186,21 +179,21 @@ public class ForgeInstaller {
private static boolean validateJar(File libPath, byte[] data, List<String> checksums) throws IOException {
System.out.println("Checking \"" + libPath.getAbsolutePath() + "\" internal checksums");
HashMap<String, String> files = new HashMap<String, String>();
HashMap<String, String> files = new HashMap<>();
String[] hashes = null;
JarInputStream jar = new JarInputStream(new ByteArrayInputStream(data));
JarEntry entry = jar.getNextJarEntry();
while (entry != null) {
byte[] eData = IOUtils.readFully(jar);
if (entry.getName().equals("checksums.sha1"))
hashes = new String(eData, Charset.forName("UTF-8")).split("\n");
if (!entry.isDirectory())
files.put(entry.getName(), DigestUtils.sha1Hex(eData));
entry = jar.getNextJarEntry();
try (JarInputStream jar = new JarInputStream(new ByteArrayInputStream(data))) {
JarEntry entry = jar.getNextJarEntry();
while (entry != null) {
byte[] eData = IOUtils.readFully(jar);
if (entry.getName().equals("checksums.sha1"))
hashes = new String(eData, Charset.forName("UTF-8")).split("\n");
if (!entry.isDirectory())
files.put(entry.getName(), DigestUtils.sha1Hex(eData));
entry = jar.getNextJarEntry();
}
}
jar.close();
if (hashes != null) {
boolean failed = !checksums.contains(files.get("checksums.sha1"));