HMCL 2.3.2

This commit is contained in:
huanghongxun
2015-06-22 16:47:05 +08:00
parent 0693d12f6b
commit 0656227183
358 changed files with 35670 additions and 0 deletions

19
HMCLAPI/build.gradle Normal file
View File

@@ -0,0 +1,19 @@
apply plugin: 'me.tatarka.retrolambda'
if (!hasProperty('mainClass')) {
ext.mainClass = ''
}
buildscript {
repositories {
mavenCentral();
dependencies {
classpath 'me.tatarka:gradle-retrolambda:3.1.0'
}
}
}
retrolambda {
javaVersion = JavaVersion.VERSION_1_7
}

View File

@@ -0,0 +1,45 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.util.ResourceBundle;
/**
*
* @author hyh
*/
public final class C {
public static final Gson gsonPrettyPrinting = new GsonBuilder().setPrettyPrinting().create();
public static final Gson gson = new Gson();
public static final ResourceBundle I18N = ResourceBundle.getBundle("org/jackhuang/hellominecraft/launcher/I18N");
//http://repo1.maven.org/maven2
public static final String URL_PUBLISH = "http://www.mcbbs.net/thread-142335-1-1.html";
public static final String URL_TIEBA = "http://tieba.baidu.com/f?kw=hellominecraftlauncher";
public static final String URL_MINECRAFTFORUM = "http://www.minecraftforum.net/forums/mapping-and-modding/minecraft-tools/1265720-hello-minecraft-launcher-1-9-3-mc-1-7-4-auto";
public static final String FILE_MINECRAFT_VERSIONS = "versions";
public static final String LINE_SEPARATOR = System.getProperty("line.separator");
public static final String URL_FORGE_LIST = "http://files.minecraftforge.net/maven/net/minecraftforge/forge/json";
public static final String URL_LITELOADER_LIST = "http://dl.liteloader.com/versions/versions.json";
private C(){}
public static String i18n(String a, Object... format) {
try {
return String.format(C.I18N.getString(a), format);
} catch(Exception e) {
HMCLog.warn("Failed to read localization lang: " + a, e);
return a;
}
}
}

View File

@@ -0,0 +1,40 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft;
import org.jackhuang.hellominecraft.logging.logger.Logger;
/**
*
* @author hyh
*/
public class HMCLog {
public static Logger logger = new Logger("HMC");
public static void log(String message) {
logger.info(message);
}
public static void warn(String message) {
logger.warn(message);
}
public static void warn(String msg, Throwable t) {
logger.warn(msg, t);
}
public static void err(String msg) {
logger.error(msg);
}
public static void err(String msg, Throwable t) {
logger.error(msg, t);
}
}

View File

@@ -0,0 +1,59 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.logging;
import org.jackhuang.hellominecraft.logging.appender.IAppender;
public class AppenderControl {
private final ThreadLocal<AppenderControl> recursive = new ThreadLocal();
private final IAppender appender;
private final Level level;
private final int intLevel;
public AppenderControl(IAppender appender, Level level) {
this.appender = appender;
this.level = level;
this.intLevel = (level == null ? Level.ALL.level : level.level);
}
public IAppender getAppender() {
return this.appender;
}
public void callAppender(LogEvent event) {
if ((this.level != null)
&& (this.intLevel < event.level.level)) {
return;
}
if (this.recursive.get() != null) {
System.err.println("Recursive call to appender " + this.appender.getName());
return;
}
try {
this.recursive.set(this);
try {
this.appender.append(event);
} catch (RuntimeException ex) {
System.err.println("An exception occurred processing Appender " + this.appender.getName());
ex.printStackTrace();
if (!this.appender.ignoreExceptions()) {
throw ex;
}
} catch (Exception ex) {
System.err.println("An exception occurred processing Appender " + this.appender.getName());
ex.printStackTrace();
if (!this.appender.ignoreExceptions()) {
throw new LoggingException(ex);
}
}
} finally {
this.recursive.set(null);
}
}
}

View File

@@ -0,0 +1,30 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.logging;
import java.util.ArrayList;
import org.jackhuang.hellominecraft.logging.appender.ConsoleAppender;
import org.jackhuang.hellominecraft.logging.appender.IAppender;
import org.jackhuang.hellominecraft.logging.layout.DefaultLayout;
/**
*
* @author hyh
*/
public class Configuration {
public ArrayList<IAppender> appenders = new ArrayList<IAppender>();
public static Configuration DEFAULT;
static {
DEFAULT = new Configuration();
DEFAULT.appenders.add(new ConsoleAppender("Console", new DefaultLayout(), true, new ConsoleAppender.SystemOutStream(), true));
}
}

View File

@@ -0,0 +1,37 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.logging;
/**
*
* @author hyh
*/
public enum Level {
OFF(0),
FATAL(1),
ERROR(2),
WARN(3),
INFO(4),
DEBUG(5),
TRACE(6),
ALL(2147483647);
public final int level;
private Level(int i) {
level = i;
}
public boolean lessOrEqual(Level level) {
return this.level <= level.level;
}
public boolean lessOrEqual(int level) {
return this.level <= level;
}
}

View File

@@ -0,0 +1,22 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.logging;
import org.jackhuang.hellominecraft.logging.message.IMessage;
/**
*
* @author hyh
*/
public class LogEvent {
public Level level;
public String threadName;
public Throwable thrown;
public IMessage message;
}

View File

@@ -0,0 +1,19 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.logging;
/**
*
* @author hyh
*/
public class LoggingException extends RuntimeException {
public LoggingException(Exception e) {
super(e);
}
}

View File

@@ -0,0 +1,45 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.logging.appender;
import java.io.Serializable;
import org.jackhuang.hellominecraft.logging.layout.ILayout;
/**
*
* @author hyh
*/
public abstract class AbstractAppender implements IAppender {
String name;
private final ILayout<? extends Serializable> layout;
private final boolean ignoreExceptions;
public AbstractAppender(String name, ILayout<? extends Serializable> layout) {
this(name, layout, true);
}
public AbstractAppender(String name, ILayout<? extends Serializable> layout, boolean ignoreExceptions) {
this.name = name;
this.layout = layout;
this.ignoreExceptions = ignoreExceptions;
}
@Override
public String getName() {
return name;
}
@Override
public boolean ignoreExceptions() {
return ignoreExceptions;
}
@Override
public ILayout<? extends Serializable> getLayout() {
return this.layout;
}
}

View File

@@ -0,0 +1,78 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.logging.appender;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import org.jackhuang.hellominecraft.logging.layout.ILayout;
/**
*
* @author hyh
*/
public class ConsoleAppender extends OutputStreamAppender {
public ConsoleAppender(String name, ILayout<? extends Serializable> layout, boolean ignoreExceptions, OutputStream stream, boolean immediateFlush) {
super(name, layout, ignoreExceptions, stream, true);
}
public static class SystemOutStream extends OutputStream {
@Override
public void close() {
}
@Override
public void flush() {
System.out.flush();
}
@Override
public void write(byte[] b) throws IOException {
System.out.write(b);
}
@Override
public void write(byte[] b, int off, int len)
throws IOException {
System.out.write(b, off, len);
}
@Override
public void write(int b) throws IOException {
System.out.write(b);
}
}
public static class SystemErrStream extends OutputStream {
@Override
public void close() {
}
@Override
public void flush() {
System.err.flush();
}
@Override
public void write(byte[] b) throws IOException {
System.err.write(b);
}
@Override
public void write(byte[] b, int off, int len)
throws IOException {
System.err.write(b, off, len);
}
@Override
public void write(int b) {
System.err.write(b);
}
}
}

View File

@@ -0,0 +1,24 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.logging.appender;
import java.io.Serializable;
import org.jackhuang.hellominecraft.logging.LogEvent;
import org.jackhuang.hellominecraft.logging.layout.ILayout;
/**
*
* @author hyh
*/
public interface IAppender {
void append(LogEvent event);
String getName();
boolean ignoreExceptions();
ILayout<? extends Serializable> getLayout();
}

View File

@@ -0,0 +1,52 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.logging.appender;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.Serializable;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.jackhuang.hellominecraft.logging.LogEvent;
import org.jackhuang.hellominecraft.logging.LoggingException;
import org.jackhuang.hellominecraft.logging.layout.ILayout;
/**
*
* @author hyh
*/
public abstract class OutputStreamAppender extends AbstractAppender {
protected final OutputStream stream;
protected final boolean immediateFlush;
private final Lock readLock = new ReentrantReadWriteLock().readLock();
public OutputStreamAppender(String name, ILayout<? extends Serializable> layout, boolean ignoreExceptions, OutputStream stream, boolean immediateFlush) {
super(name, layout, ignoreExceptions);
this.immediateFlush = immediateFlush;
this.stream = stream;
}
@Override
public void append(LogEvent event) {
this.readLock.lock();
try {
byte[] bytes = getLayout().toByteArray(event);
if (bytes.length > 0) {
stream.write(bytes);
}
if(event.thrown != null)
event.thrown.printStackTrace(new PrintStream(stream));
} catch (IOException ex) {
System.err.println("Unable to write to stream for appender: " + getName());
throw new LoggingException(ex);
} finally {
this.readLock.unlock();
}
}
}

View File

@@ -0,0 +1,22 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.logging.layout;
import org.jackhuang.hellominecraft.logging.LogEvent;
/**
*
* @author hyh
*/
public abstract class AbstractStringLayout implements ILayout<String> {
@Override
public byte[] toByteArray(LogEvent event) {
return toSerializable(event).getBytes();
}
}

View File

@@ -0,0 +1,25 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.logging.layout;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.jackhuang.hellominecraft.logging.LogEvent;
/**
*
* @author hyh
*/
public class DefaultLayout extends AbstractStringLayout {
private static final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
@Override
public String toSerializable(LogEvent event) {
return "[" + sdf.format(new Date()) + "][" + event.threadName + "/" + event.level.name() + "] " + event.message.getFormattedMessage() + "\n";
}
}

View File

@@ -0,0 +1,22 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.logging.layout;
import java.io.Serializable;
import org.jackhuang.hellominecraft.logging.LogEvent;
/**
*
* @author hyh
* @param <T>
*/
public interface ILayout<T extends Serializable> {
byte[] toByteArray(LogEvent event);
T toSerializable(LogEvent event);
}

View File

@@ -0,0 +1,523 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.logging.logger;
import org.jackhuang.hellominecraft.logging.Level;
import org.jackhuang.hellominecraft.logging.message.IMessage;
import org.jackhuang.hellominecraft.logging.message.IMessageFactory;
import org.jackhuang.hellominecraft.logging.message.ParameterizedMessageFactory;
import org.jackhuang.hellominecraft.logging.message.StringFormattedMessage;
public abstract class AbstractLogger
implements ILogger {
public static final Class<? extends IMessageFactory> DEFAULT_MESSAGE_FACTORY_CLASS = ParameterizedMessageFactory.class;
private static final String FQCN = AbstractLogger.class.getName();
private static final String THROWING = "throwing";
private static final String CATCHING = "catching";
private final String name;
private final IMessageFactory messageFactory;
public AbstractLogger() {
this.name = getClass().getName();
this.messageFactory = createDefaultMessageFactory();
}
public AbstractLogger(String name) {
this.name = name;
this.messageFactory = createDefaultMessageFactory();
}
public AbstractLogger(String name, IMessageFactory messageFactory) {
this.name = name;
this.messageFactory = (messageFactory == null ? createDefaultMessageFactory() : messageFactory);
}
private IMessageFactory createDefaultMessageFactory() {
try {
return (IMessageFactory) DEFAULT_MESSAGE_FACTORY_CLASS.newInstance();
} catch (InstantiationException e) {
throw new IllegalStateException(e);
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
@Override
public void catching(Level level, Throwable t) {
if (isEnabled(level, (Object) null, null)) {
log(level, this.messageFactory.newMessage(CATCHING), t);
}
}
@Override
public void catching(Throwable t) {
catching(Level.ERROR, t);
}
@Override
public void debug(IMessage msg) {
if (isEnabled(Level.DEBUG, msg, null)) {
log(Level.DEBUG, msg, null);
}
}
@Override
public void debug(IMessage msg, Throwable t) {
if (isEnabled(Level.DEBUG, msg, t)) {
log(Level.DEBUG, msg, t);
}
}
@Override
public void debug(Object message) {
if (isEnabled(Level.DEBUG, message, null)) {
log(Level.DEBUG, this.messageFactory.newMessage(message), null);
}
}
@Override
public void debug(Object message, Throwable t) {
if (isEnabled(Level.DEBUG, message, t)) {
log(Level.DEBUG, this.messageFactory.newMessage(message), t);
}
}
@Override
public void debug(String message) {
if (isEnabled(Level.DEBUG, message)) {
log(Level.DEBUG, this.messageFactory.newMessage(message), null);
}
}
@Override
public void debug(String message, Object[] params) {
if (isEnabled(Level.DEBUG, message, params)) {
IMessage msg = this.messageFactory.newMessage(message, params);
log(Level.DEBUG, msg, msg.getThrowable());
}
}
@Override
public void debug(String message, Throwable t) {
if (isEnabled(Level.DEBUG, message, t)) {
log(Level.DEBUG, this.messageFactory.newMessage(message), t);
}
}
@Override
public void entry() {
entry(new Object[0]);
}
@Override
public void entry(Object[] params) {
if (isEnabled(Level.TRACE, (Object) null, null)) {
log(Level.TRACE, entryMsg(params.length, params), null);
}
}
private IMessage entryMsg(int count, Object[] params) {
if (count == 0) {
return this.messageFactory.newMessage("entry");
}
StringBuilder sb = new StringBuilder("entry params(");
int i = 0;
for (Object parm : params) {
if (parm != null) {
sb.append(parm.toString());
} else {
sb.append("null");
}
i++;
if (i < params.length) {
sb.append(", ");
}
}
sb.append(")");
return this.messageFactory.newMessage(sb.toString());
}
@Override
public void error(IMessage msg) {
if (isEnabled(Level.ERROR, msg, null)) {
log(Level.ERROR, msg, null);
}
}
@Override
public void error(IMessage msg, Throwable t) {
if (isEnabled(Level.ERROR, msg, t)) {
log(Level.ERROR, msg, t);
}
}
@Override
public void error(Object message) {
if (isEnabled(Level.ERROR, message, null)) {
log(Level.ERROR, this.messageFactory.newMessage(message), null);
}
}
@Override
public void error(Object message, Throwable t) {
if (isEnabled(Level.ERROR, message, t)) {
log(Level.ERROR, this.messageFactory.newMessage(message), t);
}
}
@Override
public void error(String message) {
if (isEnabled(Level.ERROR, message)) {
log(Level.ERROR, this.messageFactory.newMessage(message), null);
}
}
@Override
public void error(String message, Object[] params) {
if (isEnabled(Level.ERROR, message, params)) {
IMessage msg = this.messageFactory.newMessage(message, params);
log(Level.ERROR, msg, msg.getThrowable());
}
}
@Override
public void error(String message, Throwable t) {
if (isEnabled(Level.ERROR, message, t)) {
log(Level.ERROR, this.messageFactory.newMessage(message), t);
}
}
@Override
public void fatal(IMessage msg) {
if (isEnabled(Level.FATAL, msg, null)) {
log(Level.FATAL, msg, null);
}
}
@Override
public void fatal(IMessage msg, Throwable t) {
if (isEnabled(Level.FATAL, msg, t)) {
log(Level.FATAL, msg, t);
}
}
@Override
public void fatal(Object message) {
if (isEnabled(Level.FATAL, message, null)) {
log(Level.FATAL, this.messageFactory.newMessage(message), null);
}
}
@Override
public void fatal(Object message, Throwable t) {
if (isEnabled(Level.FATAL, message, t)) {
log(Level.FATAL, this.messageFactory.newMessage(message), t);
}
}
@Override
public void fatal(String message) {
if (isEnabled(Level.FATAL, message)) {
log(Level.FATAL, this.messageFactory.newMessage(message), null);
}
}
@Override
public void fatal(String message, Object[] params) {
if (isEnabled(Level.FATAL, message, params)) {
IMessage msg = this.messageFactory.newMessage(message, params);
log(Level.FATAL, msg, msg.getThrowable());
}
}
@Override
public void fatal(String message, Throwable t) {
if (isEnabled(Level.FATAL, message, t)) {
log(Level.FATAL, this.messageFactory.newMessage(message), t);
}
}
@Override
public String getName() {
return this.name;
}
@Override
public void info(IMessage msg) {
if (isEnabled(Level.INFO, msg, null)) {
log(Level.INFO, msg, null);
}
}
@Override
public void info(IMessage msg, Throwable t) {
if (isEnabled(Level.INFO, msg, t)) {
log(Level.INFO, msg, t);
}
}
@Override
public void info(Object message) {
if (isEnabled(Level.INFO, message, null)) {
log(Level.INFO, this.messageFactory.newMessage(message), null);
}
}
@Override
public void info(Object message, Throwable t) {
if (isEnabled(Level.INFO, message, t)) {
log(Level.INFO, this.messageFactory.newMessage(message), t);
}
}
@Override
public void info(String message) {
if (isEnabled(Level.INFO, message)) {
log(Level.INFO, this.messageFactory.newMessage(message), null);
}
}
@Override
public void info(String message, Object[] params) {
if (isEnabled(Level.INFO, message, params)) {
IMessage msg = this.messageFactory.newMessage(message, params);
log(Level.INFO, msg, msg.getThrowable());
}
}
@Override
public void info(String message, Throwable t) {
if (isEnabled(Level.INFO, message, t)) {
log(Level.INFO, this.messageFactory.newMessage(message), t);
}
}
protected abstract boolean isEnabled(Level paramLevel, IMessage paramIMessage, Throwable paramThrowable);
protected abstract boolean isEnabled(Level paramLevel, Object paramObject, Throwable paramThrowable);
protected abstract boolean isEnabled(Level paramLevel, String paramString);
protected abstract boolean isEnabled(Level paramLevel, String paramString, Object[] paramArrayOfObject);
protected abstract boolean isEnabled(Level paramLevel, String paramString, Throwable paramThrowable);
protected abstract void abstractLog(Level level, IMessage msg, Throwable t);
@Override
public boolean isErrorEnabled() {
return isEnabled(Level.ERROR);
}
@Override
public boolean isFatalEnabled() {
return isEnabled(Level.FATAL);
}
@Override
public boolean isInfoEnabled() {
return isEnabled(Level.INFO);
}
@Override
public boolean isTraceEnabled() {
return isEnabled(Level.TRACE);
}
@Override
public boolean isWarnEnabled() {
return isEnabled(Level.WARN);
}
@Override
public boolean isDebugEnabled() {
return isEnabled(Level.DEBUG);
}
@Override
public boolean isEnabled(Level level) {
return isEnabled(level, (Object) null, null);
}
@Override
public void log(Level level, IMessage msg) {
if (isEnabled(level, msg, null)) {
log(level, msg, null);
}
}
@Override
public void log(Level level, IMessage msg, Throwable t) {
if (isEnabled(level, msg, t)) {
abstractLog(level, msg, t);
}
}
@Override
public void log(Level level, Object message) {
if (isEnabled(level, message, null)) {
log(level, this.messageFactory.newMessage(message), null);
}
}
@Override
public void log(Level level, Object message, Throwable t) {
if (isEnabled(level, message, t)) {
log(level, this.messageFactory.newMessage(message), t);
}
}
@Override
public void log(Level level, String message) {
if (isEnabled(level, message)) {
log(level, this.messageFactory.newMessage(message), null);
}
}
@Override
public void log(Level level, String message, Object[] params) {
if (isEnabled(level, message, params)) {
IMessage msg = this.messageFactory.newMessage(message, params);
log(level, msg, msg.getThrowable());
}
}
@Override
public void log(Level level, String message, Throwable t) {
if (isEnabled(level, message, t)) {
log(level, this.messageFactory.newMessage(message), t);
}
}
@Override
public void printf(Level level, String format, Object[] params) {
if (isEnabled(level, format, params)) {
IMessage msg = new StringFormattedMessage(format, params);
log(level, msg, msg.getThrowable());
}
}
@Override
public <T extends Throwable> T throwing(T t) {
return throwing(Level.ERROR, t);
}
@Override
public <T extends Throwable> T throwing(Level level, T t) {
if (isEnabled(level, (Object) null, null)) {
log(level, this.messageFactory.newMessage(THROWING), t);
}
return t;
}
@Override
public String toString() {
return this.name;
}
@Override
public void trace(IMessage msg) {
if (isEnabled(Level.TRACE, msg, null)) {
log(Level.TRACE, msg, null);
}
}
@Override
public void trace(IMessage msg, Throwable t) {
if (isEnabled(Level.TRACE, msg, t)) {
log(Level.TRACE, msg, t);
}
}
@Override
public void trace(Object message) {
if (isEnabled(Level.TRACE, message, null)) {
log(Level.TRACE, this.messageFactory.newMessage(message), null);
}
}
@Override
public void trace(Object message, Throwable t) {
if (isEnabled(Level.TRACE, message, t)) {
log(Level.TRACE, this.messageFactory.newMessage(message), t);
}
}
@Override
public void trace(String message) {
if (isEnabled(Level.TRACE, message)) {
log(Level.TRACE, this.messageFactory.newMessage(message), null);
}
}
@Override
public void trace(String message, Object[] params) {
if (isEnabled(Level.TRACE, message, params)) {
IMessage msg = this.messageFactory.newMessage(message, params);
log(Level.TRACE, msg, msg.getThrowable());
}
}
@Override
public void trace(String message, Throwable t) {
if (isEnabled(Level.TRACE, message, t)) {
log(Level.TRACE, this.messageFactory.newMessage(message), t);
}
}
@Override
public void warn(IMessage msg) {
if (isEnabled(Level.WARN, msg, null)) {
log(Level.WARN, msg, null);
}
}
@Override
public void warn(IMessage msg, Throwable t) {
if (isEnabled(Level.WARN, msg, t)) {
log(Level.WARN, msg, t);
}
}
@Override
public void warn(Object message) {
if (isEnabled(Level.WARN, message, null)) {
log(Level.WARN, this.messageFactory.newMessage(message), null);
}
}
@Override
public void warn(Object message, Throwable t) {
if (isEnabled(Level.WARN, message, t)) {
log(Level.WARN, this.messageFactory.newMessage(message), t);
}
}
@Override
public void warn(String message) {
if (isEnabled(Level.WARN, message)) {
log(Level.WARN, this.messageFactory.newMessage(message), null);
}
}
@Override
public void warn(String message, Object[] params) {
if (isEnabled(Level.WARN, message, params)) {
IMessage msg = this.messageFactory.newMessage(message, params);
log(Level.WARN, msg, msg.getThrowable());
}
}
@Override
public void warn(String message, Throwable t) {
if (isEnabled(Level.WARN, message, t)) {
log(Level.WARN, this.messageFactory.newMessage(message), t);
}
}
}

View File

@@ -0,0 +1,146 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.logging.logger;
import org.jackhuang.hellominecraft.logging.Level;
import org.jackhuang.hellominecraft.logging.message.IMessage;
/**
*
* @author hyh
*/
public interface ILogger {
void catching(Level paramLevel, Throwable paramThrowable);
void catching(Throwable paramThrowable);
void debug(IMessage paramIMessage);
void debug(IMessage paramIMessage, Throwable paramThrowable);
void debug(Object paramObject);
void debug(Object paramObject, Throwable paramThrowable);
void debug(String paramString);
void debug(String paramString, Object[] paramArrayOfObject);
void debug(String paramString, Throwable paramThrowable);
void entry();
void entry(Object[] paramArrayOfObject);
void error(IMessage paramIMessage);
void error(IMessage paramIMessage, Throwable paramThrowable);
void error(Object paramObject);
void error(Object paramObject, Throwable paramThrowable);
void error(String paramString);
void error(String paramString, Object[] paramArrayOfObject);
void error(String paramString, Throwable paramThrowable);
void fatal(IMessage paramIMessage);
void fatal(IMessage paramIMessage, Throwable paramThrowable);
void fatal(Object paramObject);
void fatal(Object paramObject, Throwable paramThrowable);
void fatal(String paramString);
void fatal(String paramString, Object[] paramArrayOfObject);
void fatal(String paramString, Throwable paramThrowable);
String getName();
void info(IMessage paramIMessage);
void info(IMessage paramIMessage, Throwable paramThrowable);
void info(Object paramObject);
void info(Object paramObject, Throwable paramThrowable);
void info(String paramString);
void info(String paramString, Object[] paramArrayOfObject);
void info(String paramString, Throwable paramThrowable);
boolean isDebugEnabled();
boolean isEnabled(Level paramLevel);
boolean isErrorEnabled();
boolean isFatalEnabled();
boolean isInfoEnabled();
boolean isTraceEnabled();
boolean isWarnEnabled();
void log(Level paramLevel, IMessage paramIMessage);
void log(Level paramLevel, IMessage paramIMessage, Throwable paramThrowable);
void log(Level paramLevel, Object paramObject);
void log(Level paramLevel, Object paramObject, Throwable paramThrowable);
void log(Level paramLevel, String paramString);
void log(Level paramLevel, String paramString, Object[] paramArrayOfObject);
void log(Level paramLevel, String paramString, Throwable paramThrowable);
void printf(Level paramLevel, String paramString, Object[] paramArrayOfObject);
<T extends Throwable> T throwing(Level paramLevel, T paramT);
<T extends Throwable> T throwing(T paramT);
void trace(IMessage paramIMessage);
void trace(IMessage paramIMessage, Throwable paramThrowable);
void trace(Object paramObject);
void trace(Object paramObject, Throwable paramThrowable);
void trace(String paramString);
void trace(String paramString, Object[] paramArrayOfObject);
void trace(String paramString, Throwable paramThrowable);
void warn(IMessage paramIMessage);
void warn(IMessage paramIMessage, Throwable paramThrowable);
void warn(Object paramObject);
void warn(Object paramObject, Throwable paramThrowable);
void warn(String paramString);
void warn(String paramString, Object[] paramArrayOfObject);
void warn(String paramString, Throwable paramThrowable);
}

View File

@@ -0,0 +1,156 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.logging.logger;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.jackhuang.hellominecraft.logging.AppenderControl;
import org.jackhuang.hellominecraft.logging.Configuration;
import org.jackhuang.hellominecraft.logging.Level;
import org.jackhuang.hellominecraft.logging.LogEvent;
import org.jackhuang.hellominecraft.logging.appender.IAppender;
import org.jackhuang.hellominecraft.logging.message.IMessage;
import org.jackhuang.hellominecraft.logging.message.IMessageFactory;
public class Logger extends AbstractLogger {
protected volatile PrivateConfig config;
private final Map<String, AppenderControl> appenders = new ConcurrentHashMap();
public Logger(String name) {
this(name, null, Level.INFO);
}
public Logger(String name, IMessageFactory messageFactory, Level defaultLevel) {
super(name, messageFactory);
this.config = new PrivateConfig(Configuration.DEFAULT, this, defaultLevel);
}
public synchronized void setLevel(Level level) {
if (level != null) {
this.config = new PrivateConfig(this.config, level);
}
}
public Level getLevel() {
return this.config.level;
}
@Override
public void abstractLog(Level level, IMessage data, Throwable t) {
LogEvent event = new LogEvent();
event.level = level;
event.message = data;
event.thrown = t;
event.threadName = Thread.currentThread().getName();
log(event);
}
public void log(LogEvent event) {
callAppenders(event);
}
protected void callAppenders(LogEvent event) {
for (AppenderControl control : this.appenders.values()) {
control.callAppender(event);
}
}
@Override
public boolean isEnabled(Level level, String msg) {
return this.config.filter(level, msg);
}
@Override
public boolean isEnabled(Level level, String msg, Throwable t) {
return this.config.filter(level, msg, t);
}
@Override
public boolean isEnabled(Level level, String msg, Object[] p1) {
return this.config.filter(level, msg, p1);
}
@Override
public boolean isEnabled(Level level, Object msg, Throwable t) {
return this.config.filter(level, msg, t);
}
@Override
public boolean isEnabled(Level level, IMessage msg, Throwable t) {
return this.config.filter(level, msg, t);
}
public void addAppender(IAppender appender) {
this.appenders.put(appender.getName(), new AppenderControl(appender, null));
}
public void removeAppender(IAppender appender) {
this.appenders.remove(appender.getName());
}
public Map<String, IAppender> getAppenders() {
Map map = new HashMap();
for (Map.Entry entry : this.appenders.entrySet()) {
map.put(entry.getKey(), ((AppenderControl) entry.getValue()).getAppender());
}
return map;
}
public String toString() {
String nameLevel = "" + getName() + ":" + getLevel();
return nameLevel;
}
protected class PrivateConfig {
public final Configuration config;
private final Level level;
private final int intLevel;
private final Logger logger;
public PrivateConfig(Configuration c, Logger logger, Level level) {
this.level = level;
this.intLevel = this.level.level;
this.logger = logger;
this.config = c;
for(IAppender appender : config.appenders)
addAppender(appender);
}
public PrivateConfig(PrivateConfig pc, Level level) {
this(pc.config, pc.logger, level);
}
boolean filter(Level level, String msg) {
return this.intLevel >= level.level;
}
boolean filter(Level level, String msg, Throwable t) {
return this.intLevel >= level.level;
}
boolean filter(Level level, String msg, Object[] p1) {
return this.intLevel >= level.level;
}
boolean filter(Level level, Object msg, Throwable t) {
return this.intLevel >= level.level;
}
boolean filter(Level level, IMessage msg, Throwable t) {
return this.intLevel >= level.level;
}
}
}

View File

@@ -0,0 +1,130 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.logging.logger;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.jackhuang.hellominecraft.logging.Level;
import org.jackhuang.hellominecraft.logging.message.IMessage;
import org.jackhuang.hellominecraft.logging.message.IMessageFactory;
public class SimpleLogger extends AbstractLogger {
private static final char SPACE = ' ';
private DateFormat dateFormatter;
private Level level;
private final boolean showDateTime;
private final boolean showContextMap;
private PrintStream stream;
private final String logName;
public SimpleLogger(String name, Level defaultLevel, boolean showLogName, boolean showShortLogName, boolean showDateTime, boolean showContextMap, String dateTimeFormat, IMessageFactory messageFactory, PrintStream stream) {
super(name, messageFactory);
this.level = defaultLevel;
if (showShortLogName) {
int index = name.lastIndexOf(".");
if ((index > 0) && (index < name.length())) {
this.logName = name.substring(index + 1);
} else {
this.logName = name;
}
} else if (showLogName) {
this.logName = name;
} else {
this.logName = null;
}
this.showDateTime = showDateTime;
this.showContextMap = showContextMap;
this.stream = stream;
if (showDateTime) {
try {
this.dateFormatter = new SimpleDateFormat(dateTimeFormat);
} catch (IllegalArgumentException e) {
this.dateFormatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss:SSS zzz");
}
}
}
public void setStream(PrintStream stream) {
this.stream = stream;
}
public Level getLevel() {
return this.level;
}
public void setLevel(Level level) {
if (level != null) {
this.level = level;
}
}
@Override
public void abstractLog(Level level, IMessage msg, Throwable throwable) {
StringBuilder sb = new StringBuilder();
if (this.showDateTime) {
Date now = new Date();
String dateText;
synchronized (this.dateFormatter) {
dateText = this.dateFormatter.format(now);
}
sb.append(dateText);
sb.append(' ');
}
sb.append(level.toString());
sb.append(' ');
if ((this.logName != null) && (this.logName.length() > 0)) {
sb.append(this.logName);
sb.append(' ');
}
sb.append(msg.getFormattedMessage());
Object[] params = msg.getParameters();
Throwable t;
if ((throwable == null) && (params != null) && ((params[(params.length - 1)] instanceof Throwable))) {
t = (Throwable) params[(params.length - 1)];
} else {
t = throwable;
}
if (t != null) {
sb.append(' ');
ByteArrayOutputStream baos = new ByteArrayOutputStream();
t.printStackTrace(new PrintStream(baos));
sb.append(baos.toString());
}
this.stream.println(sb.toString());
}
@Override
protected boolean isEnabled(Level level, String msg) {
return this.level.level >= level.level;
}
@Override
protected boolean isEnabled(Level level, String msg, Throwable t) {
return this.level.level >= level.level;
}
@Override
protected boolean isEnabled(Level level, String msg, Object[] p1) {
return this.level.level >= level.level;
}
@Override
protected boolean isEnabled(Level level, Object msg, Throwable t) {
return this.level.level >= level.level;
}
@Override
protected boolean isEnabled(Level level, IMessage msg, Throwable t) {
return this.level.level >= level.level;
}
}

View File

@@ -0,0 +1,24 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.logging.message;
/**
*
* @author hyh
*/
public abstract class AbstractMessageFactory
implements IMessageFactory {
@Override
public IMessage newMessage(Object message) {
return new ObjectMessage(message);
}
@Override
public IMessage newMessage(String message) {
return new SimpleMessage(message);
}
}

View File

@@ -0,0 +1,20 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.logging.message;
import java.io.Serializable;
/**
*
* @author hyh
*/
public interface IMessage extends Serializable {
String getFormattedMessage();
String getFormat();
Object[] getParameters();
Throwable getThrowable();
}

View File

@@ -0,0 +1,19 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.logging.message;
/**
*
* @author hyh
*/
public abstract interface IMessageFactory {
public abstract IMessage newMessage(Object paramObject);
public abstract IMessage newMessage(String paramString);
public abstract IMessage newMessage(String paramString, Object[] paramArrayOfObject);
}

View File

@@ -0,0 +1,64 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.logging.message;
public class ObjectMessage
implements IMessage {
private static final long serialVersionUID = -5903272448334166185L;
private transient Object obj;
public ObjectMessage(Object obj) {
if (obj == null) {
obj = "null";
}
this.obj = obj;
}
@Override
public String getFormattedMessage() {
return this.obj.toString();
}
@Override
public String getFormat() {
return this.obj.toString();
}
@Override
public Object[] getParameters() {
return new Object[]{this.obj};
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if ((o == null) || (getClass() != o.getClass())) {
return false;
}
ObjectMessage that = (ObjectMessage) o;
return this.obj != null ? this.obj.equals(that.obj) : that.obj == null;
}
@Override
public int hashCode() {
return this.obj != null ? this.obj.hashCode() : 0;
}
@Override
public String toString() {
return "ObjectMessage[obj=" + this.obj.toString() + "]";
}
@Override
public Throwable getThrowable() {
return (this.obj instanceof Throwable) ? (Throwable) this.obj : null;
}
}

View File

@@ -0,0 +1,336 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.logging.message;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
*
* @author hyh
*/
public class ParameterizedMessage
implements IMessage {
public static final String RECURSION_PREFIX = "[...";
public static final String RECURSION_SUFFIX = "...]";
public static final String ERROR_PREFIX = "[!!!";
public static final String ERROR_SEPARATOR = "=>";
public static final String ERROR_MSG_SEPARATOR = ":";
public static final String ERROR_SUFFIX = "!!!]";
private static final long serialVersionUID = -665975803997290697L;
private static final int HASHVAL = 31;
private static final char DELIM_START = '{';
private static final char DELIM_STOP = '}';
private static final char ESCAPE_CHAR = '\\';
private final String messagePattern;
private final String[] stringArgs;
private transient Object[] argArray;
private transient String formattedMessage;
private transient Throwable throwable;
public ParameterizedMessage(String messagePattern, String[] stringArgs, Throwable throwable) {
this.messagePattern = messagePattern;
this.stringArgs = stringArgs;
this.throwable = throwable;
}
public ParameterizedMessage(String messagePattern, Object[] objectArgs, Throwable throwable) {
this.messagePattern = messagePattern;
this.throwable = throwable;
this.stringArgs = parseArguments(objectArgs);
}
public ParameterizedMessage(String messagePattern, Object[] arguments) {
this.messagePattern = messagePattern;
this.stringArgs = parseArguments(arguments);
}
public ParameterizedMessage(String messagePattern, Object arg) {
this(messagePattern, new Object[]{arg});
}
public ParameterizedMessage(String messagePattern, Object arg1, Object arg2) {
this(messagePattern, new Object[]{arg1, arg2});
}
private String[] parseArguments(Object[] arguments) {
if (arguments == null) {
return null;
}
int argsCount = countArgumentPlaceholders(this.messagePattern);
int resultArgCount = arguments.length;
if ((argsCount < arguments.length)
&& (this.throwable == null) && ((arguments[(arguments.length - 1)] instanceof Throwable))) {
this.throwable = ((Throwable) arguments[(arguments.length - 1)]);
resultArgCount--;
}
this.argArray = new Object[resultArgCount];
System.arraycopy(arguments, 0, this.argArray, 0, resultArgCount);
String[] strArgs;
if ((argsCount == 1) && (this.throwable == null) && (arguments.length > 1)) {
strArgs = new String[1];
strArgs[0] = deepToString(arguments);
} else {
strArgs = new String[resultArgCount];
for (int i = 0; i < strArgs.length; i++) {
strArgs[i] = deepToString(arguments[i]);
}
}
return strArgs;
}
@Override
public String getFormattedMessage() {
if (this.formattedMessage == null) {
this.formattedMessage = formatMessage(this.messagePattern, this.stringArgs);
}
return this.formattedMessage;
}
@Override
public String getFormat() {
return this.messagePattern;
}
@Override
public Object[] getParameters() {
if (this.argArray != null) {
return this.argArray;
}
return this.stringArgs;
}
@Override
public Throwable getThrowable() {
return this.throwable;
}
protected String formatMessage(String msgPattern, String[] sArgs) {
return format(msgPattern, sArgs);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ParameterizedMessage that = (ParameterizedMessage) o;
if (this.messagePattern != null ? !this.messagePattern.equals(that.messagePattern) : that.messagePattern != null)
return false;
return Arrays.equals(this.stringArgs, that.stringArgs);
}
@Override
public int hashCode() {
int result = this.messagePattern != null ? this.messagePattern.hashCode() : 0;
result = HASHVAL * result + (this.stringArgs != null ? Arrays.hashCode(this.stringArgs) : 0);
return result;
}
public static String format(String messagePattern, Object[] arguments) {
if ((messagePattern == null) || (arguments == null) || (arguments.length == 0))
return messagePattern;
StringBuilder result = new StringBuilder();
int escapeCounter = 0;
int currentArgument = 0;
for (int i = 0; i < messagePattern.length(); i++) {
char curChar = messagePattern.charAt(i);
if (curChar == ESCAPE_CHAR) {
escapeCounter++;
} else if ((curChar == DELIM_START)
&& (i < messagePattern.length() - 1)
&& (messagePattern.charAt(i + 1) == DELIM_STOP)) {
int escapedEscapes = escapeCounter / 2;
for (int j = 0; j < escapedEscapes; j++)
result.append(ESCAPE_CHAR);
if (escapeCounter % 2 == 1) {
result.append(DELIM_START);
result.append(DELIM_STOP);
} else {
if (currentArgument < arguments.length)
result.append(arguments[currentArgument]);
else
result.append(DELIM_START).append(DELIM_STOP);
currentArgument++;
}
i++;
escapeCounter = 0;
} else {
if (escapeCounter > 0) {
for (int j = 0; j < escapeCounter; j++)
result.append(ESCAPE_CHAR);
escapeCounter = 0;
}
result.append(curChar);
}
}
return result.toString();
}
public static int countArgumentPlaceholders(String messagePattern) {
if (messagePattern == null) return 0;
int delim = messagePattern.indexOf(123);
if (delim == -1) return 0;
int result = 0;
boolean isEscaped = false;
for (int i = 0; i < messagePattern.length(); i++) {
char curChar = messagePattern.charAt(i);
if (curChar == ESCAPE_CHAR) {
isEscaped = !isEscaped;
} else if (curChar == DELIM_START) {
if ((!isEscaped)
&& (i < messagePattern.length() - 1)
&& (messagePattern.charAt(i + 1) == DELIM_STOP)) {
result++;
i++;
}
isEscaped = false;
} else {
isEscaped = false;
}
}
return result;
}
public static String deepToString(Object o) {
if (o == null) return null;
if (o instanceof String) return (String) o;
StringBuilder str = new StringBuilder();
Set dejaVu = new HashSet();
recursiveDeepToString(o, str, dejaVu);
return str.toString();
}
private static void recursiveDeepToString(Object o, StringBuilder str, Set<String> dejaVu) {
if (o == null) {
str.append("null");
return;
}
if ((o instanceof String)) {
str.append(o);
return;
}
Class oClass = o.getClass();
if (oClass.isArray()) {
if (oClass == byte[].class) {
str.append(Arrays.toString((byte[]) (byte[]) o));
} else if (oClass == short[].class) {
str.append(Arrays.toString((short[]) (short[]) o));
} else if (oClass == int[].class) {
str.append(Arrays.toString((int[]) (int[]) o));
} else if (oClass == long[].class) {
str.append(Arrays.toString((long[]) (long[]) o));
} else if (oClass == float[].class) {
str.append(Arrays.toString((float[]) (float[]) o));
} else if (oClass == double[].class) {
str.append(Arrays.toString((double[]) (double[]) o));
} else if (oClass == boolean[].class) {
str.append(Arrays.toString((boolean[]) (boolean[]) o));
} else if (oClass == char[].class) {
str.append(Arrays.toString((char[]) (char[]) o));
} else {
String id = identityToString(o);
if (dejaVu.contains(id)) {
str.append("[...").append(id).append("...]");
} else {
dejaVu.add(id);
Object[] oArray = (Object[]) (Object[]) o;
str.append("[");
boolean first = true;
for (Object current : oArray) {
if (first) first = false;
else str.append(", ");
recursiveDeepToString(current, str, new HashSet(dejaVu));
}
str.append("]");
}
}
} else if ((o instanceof Map)) {
String id = identityToString(o);
if (dejaVu.contains(id)) {
str.append("[...").append(id).append("...]");
} else {
dejaVu.add(id);
Map oMap = (Map) o;
str.append("{");
boolean isFirst = true;
for (Object o1 : oMap.entrySet()) {
Map.Entry current = (Map.Entry) o1;
if (isFirst) isFirst = false;
else str.append(", ");
Object key = current.getKey();
Object value = current.getValue();
recursiveDeepToString(key, str, new HashSet(dejaVu));
str.append("=");
recursiveDeepToString(value, str, new HashSet(dejaVu));
}
str.append("}");
}
} else if ((o instanceof Collection)) {
String id = identityToString(o);
if (dejaVu.contains(id)) {
str.append("[...").append(id).append("...]");
} else {
dejaVu.add(id);
Collection oCol = (Collection) o;
str.append("[");
boolean isFirst = true;
for (Iterator i$ = oCol.iterator(); i$.hasNext();) {
Object anOCol = i$.next();
if (isFirst) isFirst = false;
else str.append(", ");
recursiveDeepToString(anOCol, str, new HashSet(dejaVu));
}
str.append("]");
}
} else if ((o instanceof Date)) {
Date date = (Date) o;
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
str.append(format.format(date));
} else {
try {
str.append(o.toString());
} catch (Throwable t) {
str.append("[!!!");
str.append(identityToString(o));
str.append("=>");
String msg = t.getMessage();
String className = t.getClass().getName();
str.append(className);
if (!className.equals(msg)) {
str.append(":");
str.append(msg);
}
str.append("!!!]");
}
}
}
public static String identityToString(Object obj) {
if (obj == null) return null;
return obj.getClass().getName()+"@"+Integer.toHexString(System.identityHashCode(obj));
}
@Override
public String toString() {
return "ParameterizedMessage[messagePattern="+this.messagePattern+", stringArgs="+Arrays.toString(this.stringArgs)+", throwable="+this.throwable+"]";
}
}

View File

@@ -0,0 +1,20 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.logging.message;
/**
*
* @author hyh
*/
public final class ParameterizedMessageFactory extends AbstractMessageFactory {
public static final ParameterizedMessageFactory INSTANCE = new ParameterizedMessageFactory();
@Override
public IMessage newMessage(String message, Object[] params) {
return new ParameterizedMessage(message, params);
}
}

View File

@@ -0,0 +1,69 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.logging.message;
/**
*
* @author hyh
*/
public class SimpleMessage
implements IMessage {
private static final long serialVersionUID = -8398002534962715992L;
private final String message;
public SimpleMessage() {
this(null);
}
public SimpleMessage(String message) {
this.message = message;
}
@Override
public String getFormattedMessage() {
return this.message;
}
@Override
public String getFormat() {
return this.message;
}
@Override
public Object[] getParameters() {
return null;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if ((o == null) || (getClass() != o.getClass())) {
return false;
}
SimpleMessage that = (SimpleMessage) o;
return this.message != null ? this.message.equals(that.message) : that.message == null;
}
@Override
public int hashCode() {
return this.message != null ? this.message.hashCode() : 0;
}
@Override
public String toString() {
return "SimpleMessage[message=" + this.message + "]";
}
@Override
public Throwable getThrowable() {
return null;
}
}

View File

@@ -0,0 +1,94 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.logging.message;
import java.util.Arrays;
import java.util.IllegalFormatException;
public class StringFormattedMessage
implements IMessage {
private static final long serialVersionUID = -665975803997290697L;
private final String messagePattern;
private final transient Object[] argArray;
private String[] stringArgs;
private transient String formattedMessage;
private transient Throwable throwable;
public StringFormattedMessage(String messagePattern, Object[] arguments) {
this.messagePattern = messagePattern;
this.argArray = arguments;
if ((arguments != null) && (arguments.length > 0) && ((arguments[(arguments.length - 1)] instanceof Throwable))) {
this.throwable = ((Throwable) arguments[(arguments.length - 1)]);
}
}
@Override
public String getFormattedMessage() {
if (this.formattedMessage == null) {
this.formattedMessage = formatMessage(this.messagePattern, this.argArray);
}
return this.formattedMessage;
}
@Override
public String getFormat() {
return this.messagePattern;
}
@Override
public Object[] getParameters() {
if (this.argArray != null) {
return this.argArray;
}
return this.stringArgs;
}
protected String formatMessage(String msgPattern, Object[] args) {
try {
return String.format(msgPattern, args);
} catch (IllegalFormatException ife) {
System.err.println("Unable to format msg: " + msgPattern);
ife.printStackTrace();
}
return msgPattern;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if ((o == null) || (getClass() != o.getClass())) {
return false;
}
StringFormattedMessage that = (StringFormattedMessage) o;
if (this.messagePattern != null ? !this.messagePattern.equals(that.messagePattern) : that.messagePattern != null) {
return false;
}
return Arrays.equals(this.stringArgs, that.stringArgs);
}
@Override
public int hashCode() {
int result = this.messagePattern != null ? this.messagePattern.hashCode() : 0;
result = 31 * result + (this.stringArgs != null ? Arrays.hashCode(this.stringArgs) : 0);
return result;
}
@Override
public String toString() {
return "StringFormatMessage[messagePattern=" + this.messagePattern + ", args=" + Arrays.toString(this.argArray) + "]";
}
@Override
public Throwable getThrowable() {
return this.throwable;
}
}

View File

@@ -0,0 +1,28 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.tasks;
/**
*
* @author hyh
*/
public interface DoingDoneListener<K> {
/**
* Task done.
* @param k
*/
void onDone(K k);
/**
* Before task executing.
* @param k
*/
void onDoing(K k);
/**
* Task failed.
* @param k
*/
void onFailed(K k);
}

View File

@@ -0,0 +1,38 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.tasks;
import java.util.Collection;
import java.util.HashSet;
import org.jackhuang.hellominecraft.tasks.Task;
/**
*
* @author huangyuhui
*/
public class ParallelTask extends Task {
Collection<Task> dependsTask = new HashSet<Task>();
@Override
public boolean executeTask() {
return true;
}
@Override
public String getInfo() {
return "PARALLEL";
}
@Override
public Collection<Task> getDependTasks() {
return dependsTask;
}
public void addDependsTask(Task t) {
dependsTask.add(t);
}
}

View File

@@ -0,0 +1,19 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.tasks;
/**
*
* @author hyh
*/
public abstract class ProgressProvider {
protected ProgressProviderListener ppl;
public ProgressProvider setProgressProviderListener(ProgressProviderListener p) {
ppl = p;
return this;
}
}

View File

@@ -0,0 +1,16 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.tasks;
/**
*
* @author hyh
*/
public interface ProgressProviderListener {
void setProgress(int prog, int max);
void setStatus(String sta);
void onProgressProviderDone();
}

View File

@@ -0,0 +1,54 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.tasks;
import java.util.Collection;
/**
*
* @author hyh
*/
public abstract class Task extends ProgressProvider {
/**
* Run in a new thread(packed in TaskList).
* @return is task finished sucessfully.
*/
public abstract boolean executeTask();
/**
* if this func returns false, TaskList will force abort the thread.
* run in main thread.
* @return is aborted.
*/
public boolean abort() { return false; }
public Throwable getFailReason() { return failReason; }
protected Throwable failReason = null;
protected void setFailReason(Throwable s) {
failReason = s;
}
protected String tag;
protected boolean parallelExecuting;
public Task setTag(String tag) {
this.tag = tag;
return this;
}
public boolean isParallelExecuting() {
return parallelExecuting;
}
public void setParallelExecuting(boolean parallelExecuting) {
this.parallelExecuting = parallelExecuting;
}
public abstract String getInfo();
public Collection<Task> getDependTasks() { return null; }
public Collection<Task> getAfterTasks() { return null; }
}

View File

@@ -0,0 +1,25 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.tasks;
/**
*
* @author hyh
*/
public abstract class TaskInfo extends Task {
String info;
public TaskInfo(String info) {
this.info = info;
}
@Override
public String getInfo() {
return info;
}
}

View File

@@ -0,0 +1,154 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.tasks;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.jackhuang.hellominecraft.utils.functions.DoneListener0;
import org.jackhuang.hellominecraft.HMCLog;
/**
*
* @author hyh
*/
public class TaskList extends Thread {
List<Task> taskQueue = Collections.synchronizedList(new ArrayList());
ArrayList<DoneListener0> allDone = new ArrayList();
ArrayList<DoingDoneListener<Task>> taskListener = new ArrayList();
int totTask = 0;
boolean shouldContinue = true;
public TaskList() {
}
public void clean() {
shouldContinue = true;
totTask = 0;
taskQueue.clear();
}
public void addAllDoneListener(DoneListener0 l) {
allDone.add(l);
}
public void addTaskListener(DoingDoneListener<Task> l) {
taskListener.add(l);
}
public void addTask(Task task) {
taskQueue.add(task);
totTask++;
}
public int taskCount() {
return totTask;
}
private class InvokeThread extends Thread {
Task task;
Set<InvokeThread> s;
public InvokeThread(Task task, Set<InvokeThread> ss) {
this.task = task;
s = ss;
}
@Override
public void run() {
executeTask(task);
s.remove(this);
threadPool.remove(this);
}
}
static final Set<InvokeThread> threadPool = Collections.synchronizedSet(new HashSet<InvokeThread>());
static final Set<Task> taskPool = Collections.synchronizedSet(new HashSet<Task>());
private void processTasks(Collection<Task> c) {
if (c == null) {
return;
}
this.totTask += c.size();
Set<InvokeThread> runningThread = Collections.synchronizedSet(new HashSet<InvokeThread>());
for (Task t2 : c) {
t2.setParallelExecuting(true);
InvokeThread thread = new InvokeThread(t2, runningThread);
threadPool.add(thread);
runningThread.add(thread);
thread.start();
}
while (!runningThread.isEmpty()) {
try {
if(this.isInterrupted()) return;
Thread.sleep(1);
} catch (InterruptedException ex) {
HMCLog.warn("Failed to sleep task thread", ex);
}
}
}
private void executeTask(Task t) {
if (!shouldContinue || t == null) {
return;
}
processTasks(t.getDependTasks());
HMCLog.log("Executing task: " + t.getInfo());
for (DoingDoneListener<Task> d : taskListener) {
d.onDoing(t);
}
if (t.executeTask()) {
HMCLog.log("Task finished: " + t.getInfo());
for (DoingDoneListener<Task> d : taskListener) {
d.onDone(t);
}
processTasks(t.getAfterTasks());
} else {
HMCLog.err("Task failed: " + t.getInfo(), t.getFailReason());
for (DoingDoneListener<Task> d : taskListener) {
d.onFailed(t);
}
}
}
@Override
public void run() {
Thread.currentThread().setName("TaskList");
threadPool.clear();
for (Task taskQueue1 : taskQueue)
executeTask(taskQueue1);
if (shouldContinue)
for (DoneListener0 d : allDone)
d.onDone();
}
public boolean isEmpty() {
return taskQueue.isEmpty();
}
public void abort() {
shouldContinue = false;
while(!threadPool.isEmpty())
synchronized(threadPool) {
InvokeThread it = threadPool.iterator().next();
if(!it.task.abort()) it.interrupt();
threadPool.remove(it);
}
this.interrupt();
}
}

View File

@@ -0,0 +1,30 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.tasks;
/**
*
* @author hyh
*/
public class TaskRunnable extends TaskInfo {
private final Runnable r;
public TaskRunnable(String info, Runnable r) {
super(info);
this.r = r;
}
@Override
public boolean executeTask() {
try {
r.run();
return true;
} catch(Throwable t) {
setFailReason(t);
return false;
}
}
}

View File

@@ -0,0 +1,47 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.tasks;
import java.util.ArrayList;
import org.jackhuang.hellominecraft.tasks.communication.PreviousResult;
import org.jackhuang.hellominecraft.tasks.communication.PreviousResultRegistrator;
import org.jackhuang.hellominecraft.utils.functions.Consumer;
/**
*
* @author hyh
* @param <T> Runnable&lt;T&gt;
*/
public class TaskRunnableArg1<T> extends TaskInfo implements PreviousResultRegistrator<T> {
private final Consumer<T> r;
public TaskRunnableArg1(String info, Consumer<T> r) {
super(info);
this.r = r;
}
@Override
public boolean executeTask() {
if(al.size() != 1) throw new IllegalStateException("the count of args is not one.");
try {
r.accept(al.get(0).getResult());
return true;
} catch(Throwable t) {
setFailReason(t);
return false;
}
}
ArrayList<PreviousResult<T>> al = new ArrayList();
@Override
public Task registerPreviousResult(PreviousResult<T> pr) {
al.add(pr);
return this;
}
}

View File

@@ -0,0 +1,127 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.3" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
<Properties>
<Property name="defaultCloseOperation" type="int" value="2"/>
<Property name="title" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/launcher/I18N.properties" key="taskwindow.title" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
</SyntheticProperties>
<Events>
<EventHandler event="windowClosed" listener="java.awt.event.WindowListener" parameters="java.awt.event.WindowEvent" handler="formWindowClosed"/>
</Events>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="lblSingleProgress" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="349" max="-2" attributes="0"/>
</Group>
<Component id="pgsSingle" alignment="0" pref="434" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="lblTotalProgress" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Component id="pgsTotal" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnCancel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
<Component id="srlDownload" alignment="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="srlDownload" pref="241" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="btnCancel" alignment="1" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="1" attributes="0">
<Component id="lblSingleProgress" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="pgsSingle" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblTotalProgress" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="pgsTotal" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JButton" name="btnCancel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/launcher/I18N.properties" key="taskwindow.cancel" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnCancelActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JProgressBar" name="pgsSingle">
<Properties>
<Property name="stringPainted" type="boolean" value="true"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="lblSingleProgress">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/launcher/I18N.properties" key="taskwindow.single_progress" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="lblTotalProgress">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/launcher/I18N.properties" key="taskwindow.total_progress" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JProgressBar" name="pgsTotal">
<Properties>
<Property name="stringPainted" type="boolean" value="true"/>
</Properties>
</Component>
<Container class="javax.swing.JScrollPane" name="srlDownload">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JList" name="lstDownload">
<Properties>
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor">
<StringArray count="0"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@@ -0,0 +1,242 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.tasks;
import java.awt.EventQueue;
import java.util.ArrayList;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.utils.functions.DoneListener0;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.utils.MessageBox;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.hellominecraft.utils.SwingUtils;
/**
*
* @author hyh
*/
public class TaskWindow extends javax.swing.JDialog
implements ProgressProviderListener, DoneListener0, DoingDoneListener<Task> {
private static final TaskWindow instance = new TaskWindow();
public static TaskWindow getInstance() {
instance.clean();
return instance;
}
boolean suc = false;
private TaskList taskList;
private final ArrayList<String> failReasons = new ArrayList();
/**
* Creates new form DownloadWindow
*/
private TaskWindow() {
initComponents();
setLocationRelativeTo(null);
setModal(true);
}
public TaskWindow addTask(Task task) {
taskList.addTask(task);
return this;
}
public void clean() {
taskList = null;
taskList = new TaskList();
taskList.addTaskListener(this);
taskList.addAllDoneListener(this);
}
public boolean start() {
if (taskList.isAlive()) return false;
pgsSingle.setValue(0);
pgsTotal.setValue(0);
suc = false;
SwingUtils.clear(lstDownload);
failReasons.clear();
try {
taskList.start();
} catch (Exception e) {
HMCLog.warn("Failed to start thread, maybe there're already a taskwindow here.", e);
MessageBox.Show(C.i18n("taskwindow.no_more_instance"));
return false;
}
this.setVisible(true);
return this.areTasksFinished();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
btnCancel = new javax.swing.JButton();
pgsSingle = new javax.swing.JProgressBar();
lblSingleProgress = new javax.swing.JLabel();
lblTotalProgress = new javax.swing.JLabel();
pgsTotal = new javax.swing.JProgressBar();
srlDownload = new javax.swing.JScrollPane();
lstDownload = new javax.swing.JList();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("org/jackhuang/hellominecraft/launcher/I18N"); // NOI18N
setTitle(bundle.getString("taskwindow.title")); // NOI18N
addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosed(java.awt.event.WindowEvent evt) {
formWindowClosed(evt);
}
});
btnCancel.setText(bundle.getString("taskwindow.cancel")); // NOI18N
btnCancel.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnCancelActionPerformed(evt);
}
});
pgsSingle.setStringPainted(true);
lblSingleProgress.setText(bundle.getString("taskwindow.single_progress")); // NOI18N
lblTotalProgress.setText(bundle.getString("taskwindow.total_progress")); // NOI18N
pgsTotal.setStringPainted(true);
srlDownload.setViewportView(lstDownload);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(lblSingleProgress)
.addGap(349, 349, 349))
.addComponent(pgsSingle, javax.swing.GroupLayout.DEFAULT_SIZE, 434, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(lblTotalProgress)
.addGap(0, 0, Short.MAX_VALUE))
.addComponent(pgsTotal, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCancel)
.addContainerGap())
.addComponent(srlDownload)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(srlDownload, javax.swing.GroupLayout.DEFAULT_SIZE, 241, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(btnCancel, javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(lblSingleProgress)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(pgsSingle, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblTotalProgress)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(pgsTotal, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap())
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed
if(MessageBox.Show(C.i18n("operation.confirm_stop"), MessageBox.YES_OPTION) == MessageBox.YES_OPTION)
this.dispose();
}//GEN-LAST:event_btnCancelActionPerformed
private void formWindowClosed(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosed
if (!this.failReasons.isEmpty()) {
MessageBox.Show(StrUtils.parseParams("", failReasons.toArray(), "\n"), C.i18n("message.error"), MessageBox.ERROR_MESSAGE);
failReasons.clear();
}
if (!suc) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
taskList.abort();
}
});
HMCLog.log("Tasks have been canceled by user.");
}
}//GEN-LAST:event_formWindowClosed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnCancel;
private javax.swing.JLabel lblSingleProgress;
private javax.swing.JLabel lblTotalProgress;
private javax.swing.JList lstDownload;
private javax.swing.JProgressBar pgsSingle;
private javax.swing.JProgressBar pgsTotal;
private javax.swing.JScrollPane srlDownload;
// End of variables declaration//GEN-END:variables
@Override
public void setProgress(int progress, int max) {
pgsSingle.setMaximum(max);
pgsSingle.setValue(progress);
}
@Override
public void onDone() {
suc = true;
this.dispose();
HMCLog.log("Tasks are finished.");
}
@Override
public void onDoing(Task task) {
if (!task.isParallelExecuting())
task.setProgressProviderListener(this);
SwingUtils.appendLast(lstDownload, task.getInfo());
SwingUtils.moveEnd(srlDownload);
}
public boolean areTasksFinished() {
return suc;
}
@Override
public void onDone(Task task) {
pgsTotal.setMaximum(taskList.taskCount());
pgsTotal.setValue(pgsTotal.getValue() + 1);
}
@Override
public void onFailed(Task task) {
failReasons.add(task.getInfo() + ": " + (task.getFailReason() == null ? "No exception" : task.getFailReason().getLocalizedMessage()));
pgsTotal.setMaximum(taskList.taskCount());
pgsTotal.setValue(pgsTotal.getValue() + 1);
SwingUtils.replaceLast(lstDownload, task.getFailReason());
SwingUtils.moveEnd(srlDownload);
}
@Override
public void onProgressProviderDone() {
}
@Override
public void setStatus(String sta) {
SwingUtils.replaceLast(lstDownload, sta);
}
}

View File

@@ -0,0 +1,24 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.tasks.communication;
/**
*
* @author huangyuhui
*/
public class DefaultPreviousResult<T> implements PreviousResult<T>{
T a;
public DefaultPreviousResult(T a) {
this.a = a;
}
@Override
public T getResult() {
return a;
}
}

View File

@@ -0,0 +1,17 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.tasks.communication;
/**
*
* @author hyh
* @param <T> Task result type
*/
public interface PreviousResult<T> {
T getResult();
}

View File

@@ -0,0 +1,23 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.tasks.communication;
import org.jackhuang.hellominecraft.tasks.Task;
/**
*
* @author hyh
* @param <T> Previous task result type
*/
public interface PreviousResultRegistrator<T> {
/**
*
* @param pr previous task handler
* @return task self instance
*/
Task registerPreviousResult(PreviousResult<T> pr);
}

View File

@@ -0,0 +1,43 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.tasks.download;
import org.jackhuang.hellominecraft.utils.functions.Consumer;
import org.jackhuang.hellominecraft.utils.Event;
import org.jackhuang.hellominecraft.views.LogWindow;
/**
*
* @author hyh
*/
public class ContentGetAndShowTask extends HTTPGetTask implements Event<String> {
public ContentGetAndShowTask(String info, String changeLogUrl) {
super(changeLogUrl);
this.info = info;
}
@Override
public boolean executeTask() {
tdtsl.register(this);
return super.executeTask();
}
String info;
@Override
public String getInfo() {
return info;
}
@Override
public boolean call(Object sender, String value) {
LogWindow.instance.clean();
LogWindow.instance.log(value);
LogWindow.instance.setVisible(true);
return true;
}
}

View File

@@ -0,0 +1,17 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.tasks.download;
import org.jackhuang.hellominecraft.tasks.ProgressProviderListener;
/**
*
* @author hyh
*/
public interface DownloadListener extends ProgressProviderListener {
boolean OnFailed();
void OnFailedMoreThan5Times(String url);
}

View File

@@ -0,0 +1,247 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.tasks.download;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.X509TrustManager;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.tasks.Task;
import org.jackhuang.hellominecraft.tasks.communication.PreviousResult;
import org.jackhuang.hellominecraft.tasks.communication.PreviousResultRegistrator;
import org.jackhuang.hellominecraft.utils.IOUtils;
/**
*
* @author hyh
*/
// This class downloads a file from a URL.
public class FileDownloadTask extends Task implements PreviousResult<File>, PreviousResultRegistrator<String> {
private static final X509TrustManager xtm = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
private static final HostnameVerifier hnv = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
static {
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("TLS");
X509TrustManager[] xtmArray = new X509TrustManager[]{xtm};
sslContext.init(null, xtmArray, new java.security.SecureRandom());
} catch (GeneralSecurityException gse) {
}
if (sslContext != null) {
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
}
HttpsURLConnection.setDefaultHostnameVerifier(hnv);
}
// Max size of download buffer.
private static final int MAX_BUFFER_SIZE = 2048;
private URL url; // download URL
private int size; // size of download in bytes
private int downloaded; // number of bytes downloaded
private final File filePath;
public FileDownloadTask(File filePath) {
this((URL) null, filePath);
}
public FileDownloadTask(String url, File filePath) {
this(IOUtils.parseURL(url), filePath);
}
// Constructor for Download.
public FileDownloadTask(URL url, File filePath) {
this.url = url;
size = -1;
downloaded = 0;
this.filePath = filePath;
}
// Get this download's URL.
public String getUrl() {
return url.toString();
}
RandomAccessFile file = null;
InputStream stream = null;
boolean shouldContinue = true, aborted = false;
private void closeFiles() {
// Close file.
if (file != null) {
try {
file.close();
file = null;
} catch (IOException e) {
HMCLog.warn("Failed to close file", e);
}
}
// Close connection to server.
if (stream != null) {
try {
stream.close();
stream = null;
} catch (IOException e) {
HMCLog.warn("Failed to close stream", e);
}
}
}
// Download file.
@Override
public boolean executeTask() {
for (PreviousResult<String> p : al) {
this.url = IOUtils.parseURL(p.getResult());
}
for (int repeat = 0; repeat < 6; repeat++) {
if (repeat > 0) {
HMCLog.warn("Failed to download, repeat: " + repeat);
}
try {
// Open connection to URL.
HttpURLConnection connection
= (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(5000);
connection.setRequestProperty("User-Agent", "Hello Minecraft! Launcher");
// Connect to server.
connection.connect();
// Make sure response code is in the 200 range.
if (connection.getResponseCode() / 100 != 2) {
setFailReason(new NetException(C.i18n("download.not_200") + " " + connection.getResponseCode()));
return false;
}
// Check for valid content length.
int contentLength = connection.getContentLength();
if (contentLength < 1) {
setFailReason(new NetException("The content length is invalid."));
return false;
}
// Set the size for this download if it hasn't been already set.
if (size == -1) {
size = contentLength;
}
filePath.getParentFile().mkdirs();
File tempFile = new File(filePath.getAbsolutePath() + ".hmd");
if (!tempFile.exists()) {
tempFile.createNewFile();
}
// Open file and seek to the end of it.
file = new RandomAccessFile(tempFile, "rw");
file.seek(downloaded);
stream = connection.getInputStream();
while (true) {
// Size buffer according to how much of the file is left to download.
if (!shouldContinue) {
closeFiles();
filePath.delete();
break;
}
byte buffer[] = new byte[MAX_BUFFER_SIZE];
// Read from server into buffer.
int read = stream.read(buffer);
if (read == -1) {
break;
}
// Write buffer to file.
file.write(buffer, 0, read);
downloaded += read;
if (ppl != null) {
ppl.setProgress(downloaded, size);
}
}
closeFiles();
tempFile.renameTo(filePath);
if (ppl != null) {
ppl.onProgressProviderDone();
}
return true;
} catch (Exception e) {
setFailReason(new NetException(C.i18n("download.failed") + " " + url, e));
} finally {
closeFiles();
}
}
return false;
}
public static void download(String url, String file, DownloadListener dl) {
((Task) new FileDownloadTask(url, new File(file)).setProgressProviderListener(dl)).executeTask();
}
@Override
public boolean abort() {
shouldContinue = false;
aborted = true;
return true;
}
@Override
public String getInfo() {
return C.i18n("download") + ": " + url + " " + filePath;
}
@Override
public File getResult() {
return filePath;
}
ArrayList<PreviousResult<String>> al = new ArrayList();
@Override
public Task registerPreviousResult(PreviousResult<String> pr) {
al.add(pr);
return this;
}
}

View File

@@ -0,0 +1,85 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.tasks.download;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import org.jackhuang.hellominecraft.HMCLog;
import org.jackhuang.hellominecraft.tasks.TaskInfo;
import org.jackhuang.hellominecraft.tasks.communication.PreviousResult;
import org.jackhuang.hellominecraft.utils.EventHandler;
/**
*
* @author hyh
*/
public class HTTPGetTask extends TaskInfo implements PreviousResult<String> {
String url, encoding, result;
EventHandler<String> tdtsl = new EventHandler<>(this);
boolean shouldContinue = true;
public HTTPGetTask(String url) {
this(null, url);
}
public HTTPGetTask(String info, String url) {
this(info, url, "UTF-8");
}
public HTTPGetTask(String info, String url, String encoding) {
super(info);
this.url = url;
this.encoding = encoding;
}
@Override
public boolean executeTask() {
for (int repeat = 0; repeat < 6; repeat++) {
if (repeat > 0) HMCLog.warn("Failed to download, repeat: " + repeat);
try {
URLConnection conn = new URL(url).openConnection();
InputStream is = conn.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int i;
int size = conn.getContentLength(), read = 0;
while ((i = is.read()) != -1) {
baos.write(i);
if (ppl != null) {
ppl.setProgress(++read, size);
}
if (!shouldContinue) {
return true;
}
}
result = baos.toString();
tdtsl.execute(result);
return true;
} catch (Exception ex) {
setFailReason(new NetException("Failed to get " + url, ex));
}
}
return false;
}
@Override
public boolean abort() {
shouldContinue = false;
return true;
}
@Override
public String getInfo() {
return super.getInfo() != null ? super.getInfo() : "Get: " + url;
}
@Override
public String getResult() {
return result;
}
}

View File

@@ -0,0 +1,22 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.tasks.download;
/**
*
* @author hyh
*/
public class NetException extends RuntimeException {
public NetException(String message) {
super(message);
}
public NetException(String message, Exception e) {
super(message, e);
}
}

View File

@@ -0,0 +1,122 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
*
* @author hyh
*/
public class ArrayUtils {
public static <T> boolean isEmpty(T[] array) {
return array == null || array.length <= 0;
}
public static <T> boolean isNotEmpty(T[] array) {
return !isEmpty(array);
}
public static <T> boolean contains(T[] array, T objectToFind) {
return indexOf(array, objectToFind) != -1;
}
public static <T> int indexOf(T[] array, T valueToFind) {
return indexOf(array, valueToFind, 0);
}
public static <T> int indexOf(T[] array, T valueToFind, int startIndex) {
if (array == null) {
return -1;
}
if (startIndex < 0) {
startIndex = 0;
}
for (int i = startIndex; i < array.length; i++) {
if (valueToFind.equals(array[i])) {
return i;
}
}
return -1;
}
public static <T> int lastIndexOf(T[] array, T valueToFind) {
return lastIndexOf(array, valueToFind, 2147483647);
}
public static <T> int lastIndexOf(T[] array, T valueToFind, int startIndex) {
if (array == null) {
return -1;
}
if (startIndex < 0) {
return -1;
}
if (startIndex >= array.length) {
startIndex = array.length - 1;
}
for (int i = startIndex; i >= 0; i--) {
if (valueToFind.equals(array[i])) {
return i;
}
}
return -1;
}
public static ArrayList merge(List a, List b) {
ArrayList al = new ArrayList(a.size() + b.size());
al.addAll(a); al.addAll(b);
return al;
}
public static <K> K getEnd(K[] k) {
if(k == null) return null;
else return k[k.length-1];
}
public static List tryGetMapWithList(Map map, String key) {
List l = (List)map.get(key);
if(l == null)
map.put(key, l = new ArrayList());
return l;
}
public static <T> int matchArray(T[] a, T[] b) {
for (int i = 0; i < a.length - b.length; i++) {
int j = 1;
for (int k = 0; k < b.length; k++) {
if (b[k].equals(a[(i + k)])) {
continue;
}
j = 0;
break;
}
if (j != 0) {
return i;
}
}
return -1;
}
public static <T> int matchArray(byte[] a, byte[] b) {
for (int i = 0; i < a.length - b.length; i++) {
int j = 1;
for (int k = 0; k < b.length; k++) {
if (b[k] == a[(i + k)]) {
continue;
}
j = 0;
break;
}
if (j != 0) {
return i;
}
}
return -1;
}
}

View File

@@ -0,0 +1,100 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import java.io.UnsupportedEncodingException;
/**
*
* @author hyh
*/
public class Base64 {
public static char[] encode(byte[] data) {
char[] out = new char[((data.length + 2) / 3) * 4];
for (int i = 0, index = 0; i < data.length; i += 3, index += 4) {
boolean quad = false;
boolean trip = false;
int val = (0xFF & (int) data[i]);
val <<= 8;
if ((i + 1) < data.length) {
val |= (0xFF & (int) data[i + 1]);
trip = true;
}
val <<= 8;
if ((i + 2) < data.length) {
val |= (0xFF & (int) data[i + 2]);
quad = true;
}
out[index + 3] = alphabet[(quad ? (val & 0x3F) : 64)];
val >>= 6;
out[index + 2] = alphabet[(trip ? (val & 0x3F) : 64)];
val >>= 6;
out[index + 1] = alphabet[val & 0x3F];
val >>= 6;
out[index + 0] = alphabet[val & 0x3F];
}
return out;
}
public static char[] encode(String s, String charset) throws UnsupportedEncodingException {
return encode(s.getBytes(charset));
}
public static char[] encode(String s) {
return encode(s.getBytes());
}
public static byte[] decode(char[] data) {
int len = ((data.length + 3) / 4) * 3;
if (data.length > 0 && data[data.length - 1] == '=') {
--len;
}
if (data.length > 1 && data[data.length - 2] == '=') {
--len;
}
byte[] out = new byte[len];
int shift = 0;
int accum = 0;
int index = 0;
for (int ix = 0; ix < data.length; ix++) {
int value = codes[data[ix] & 0xFF];
if (value >= 0) {
accum <<= 6;
shift += 6;
accum |= value;
if (shift >= 8) {
shift -= 8;
out[index++] = (byte) ((accum >> shift) & 0xff);
}
}
}
if (index != out.length) {
throw new Error("miscalculated data length!");
}
return out;
}
private static final char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
.toCharArray();
private static final byte[] codes = new byte[256];
static {
for (int i = 0; i < 256; i++) {
codes[i] = -1;
}
for (int i = 'A'; i <= 'Z'; i++) {
codes[i] = (byte) (i - 'A');
}
for (int i = 'a'; i <= 'z'; i++) {
codes[i] = (byte) (26 + i - 'a');
}
for (int i = '0'; i <= '9'; i++) {
codes[i] = (byte) (52 + i - '0');
}
codes['+'] = 62;
codes['/'] = 63;
}
}

View File

@@ -0,0 +1,21 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import java.io.File;
import java.io.IOException;
/**
*
* @author hyh
*/
public class BaseLauncherProfile {
public static String profile = "{\"selectedProfile\": \"(Default)\",\"profiles\": {\"(Default)\": {\"name\": \"(Default)\"}},\"clientToken\": \"88888888-8888-8888-8888-888888888888\"}";
public static void tryWriteProfile(File gameDir) throws IOException {
File file = new File(gameDir, "launcher_profiles.json");
if(!file.exists())
FileUtils.writeStringToFile(file, profile);
}
}

View File

@@ -0,0 +1,21 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
/**
*
* @author hyh
*/
public class Bytes {
public static String substring(String src, int start_idx, int end_idx) {
byte[] b = src.getBytes();
String tgt = "";
for (int i = start_idx; i <= end_idx; i++) {
tgt += (char) b[i];
}
return tgt;
}
}

View File

@@ -0,0 +1,31 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import java.nio.charset.Charset;
public class Charsets {
public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
public static final Charset US_ASCII = Charset.forName("US-ASCII");
public static final Charset UTF_16 = Charset.forName("UTF-16");
public static final Charset UTF_16BE = Charset.forName("UTF-16BE");
public static final Charset UTF_16LE = Charset.forName("UTF-16LE");
public static final Charset UTF_8 = Charset.forName("UTF-8");
public static Charset toCharset(Charset charset) {
return charset == null ? Charset.defaultCharset() : charset;
}
public static Charset toCharset(String charset) {
return charset == null ? Charset.defaultCharset() : Charset.forName(charset);
}
}

View File

@@ -0,0 +1,183 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
/**
* 文件压缩/解压类
*
* @author hyh
*/
public class Compressor {
public static void zip(String sourceDir, String zipFile) throws IOException {
zip(new File(sourceDir), new File(zipFile));
}
/**
* 功能:把 sourceDir 目录下的所有文件进行 zip 格式的压缩,保存为指定 zip 文件
*
* @param sourceDir
* @param zipFile
*/
public static void zip(File sourceDir, File zipFile) throws IOException {
FileOutputStream os;
os = new FileOutputStream(zipFile);
BufferedOutputStream bos = new BufferedOutputStream(os);
try (ZipOutputStream zos = new ZipOutputStream(bos)) {
String basePath;
if (sourceDir.isDirectory()) {
basePath = sourceDir.getPath();
} else {//直接压缩单个文件时,取父目录
basePath = sourceDir.getParent();
}
zipFile(sourceDir, basePath, zos);
zos.closeEntry();
}
}
/**
* 将文件压缩成zip文件
*
* @param source zip文件路径
* @param basePath 待压缩文件根目录
* @param zos
*/
private static void zipFile(File source, String basePath,
ZipOutputStream zos) throws IOException {
File[] files;
if (source.isDirectory()) {
files = source.listFiles();
} else {
files = new File[1];
files[0] = source;
}
String pathName;//存相对路径(相对于待压缩的根目录)
byte[] buf = new byte[1024];
int length;
for (File file : files) {
if (file.isDirectory()) {
pathName = file.getPath().substring(basePath.length() + 1)
+ "/";
if (file.getName().toLowerCase().contains("meta-inf")) {
continue;
}
zos.putNextEntry(new ZipEntry(pathName));
zipFile(file, basePath, zos);
} else {
pathName = file.getPath().substring(basePath.length() + 1);
try (InputStream is = new FileInputStream(file)) {
BufferedInputStream bis = new BufferedInputStream(is);
zos.putNextEntry(new ZipEntry(pathName));
while ((length = bis.read(buf)) > 0) {
zos.write(buf, 0, length);
}
}
}
}
}
public static void unzip(String zipFileName, String extPlace) throws IOException {
unzip(new File(zipFileName), new File(extPlace));
}
public static void unzip(File zipFileName, File extPlace) throws IOException {
unzip(zipFileName, extPlace, new String[0]);
}
/**
* 将文件压缩成zip文件
*
* @param zipFileName zip文件路径
* @param extPlace 待压缩文件根目录
* @param without 带前缀的不解压
*/
public static void unzip(File zipFileName, File extPlace, String[] without) throws IOException {
extPlace.mkdirs();
try (ZipFile zipFile = new ZipFile(zipFileName)) {
if (zipFileName.exists()) {
String strPath, gbkPath, strtemp;
strPath = extPlace.getAbsolutePath();
java.util.Enumeration e = zipFile.entries();
while (e.hasMoreElements()) {
ZipEntry zipEnt = (ZipEntry) e.nextElement();
gbkPath = zipEnt.getName();
if(StrUtils.startsWithOne(without, gbkPath)) continue;
if (zipEnt.isDirectory()) {
strtemp = strPath + File.separator + gbkPath;
File dir = new File(strtemp);
dir.mkdirs();
} else {
//读写文件
InputStream is = zipFile.getInputStream(zipEnt);
BufferedInputStream bis = new BufferedInputStream(is);
gbkPath = zipEnt.getName();
strtemp = strPath + File.separator + gbkPath;
//建目录
String strsubdir = gbkPath;
for (int i = 0; i < strsubdir.length(); i++) {
if (strsubdir.substring(i, i + 1).equalsIgnoreCase("/")) {
String temp = strPath + File.separator + strsubdir.substring(0, i);
File subdir = new File(temp);
if (!subdir.exists()) {
subdir.mkdir();
}
}
}
try (FileOutputStream fos = new FileOutputStream(strtemp); BufferedOutputStream bos = new BufferedOutputStream(fos)) {
int c;
while ((c = bis.read()) != -1)
bos.write((byte) c);
}
}
}
}
}
}
/**
* 将zip1合并到zip2里面即保留zip2
*
* @param destFile zip1
* @param srcFile zip2
*/
public static void merge(File destFile, File srcFile) throws IOException {
try (ZipOutputStream os = new ZipOutputStream(new FileOutputStream(destFile))) {
if (destFile.exists()) {
File extPlace = new File(IOUtils.currentDir(), "HMCL-MERGE-TEMP");
unzip(srcFile, extPlace);
ZipFile zipFile = new ZipFile(srcFile);
if (srcFile.exists()) {
String gbkPath;//, strtemp, strPath;
//strPath = extPlace.getAbsolutePath();
java.util.Enumeration e = zipFile.entries();
while (e.hasMoreElements()) {
ZipEntry zipEnt = (ZipEntry) e.nextElement();
//gbkPath = zipEnt.getName();
if (zipEnt.isDirectory()) {
//strtemp = strPath + File.separator + gbkPath;
} else {
gbkPath = zipEnt.getName();
//strtemp = strPath + File.separator + gbkPath;
os.putNextEntry(zipEnt);
os.write(gbkPath.getBytes("UTF-8"));
}
}
}
}
os.closeEntry();
}
}
}

View File

@@ -0,0 +1,273 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
*
* @author hyh
*/
public class DigestUtils {
private static final int STREAM_BUFFER_LENGTH = 1024;
private static byte[] digest(MessageDigest digest, InputStream data)
throws IOException {
return updateDigest(digest, data).digest();
}
public static MessageDigest getDigest(String algorithm) {
try {
return MessageDigest.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
throw new IllegalArgumentException(e);
}
}
public static MessageDigest getMd2Digest() {
return getDigest("MD2");
}
public static MessageDigest getMd5Digest() {
return getDigest("MD5");
}
public static MessageDigest getSha1Digest() {
return getDigest("SHA-1");
}
public static MessageDigest getSha256Digest() {
return getDigest("SHA-256");
}
public static MessageDigest getSha384Digest() {
return getDigest("SHA-384");
}
public static MessageDigest getSha512Digest() {
return getDigest("SHA-512");
}
@Deprecated
public static MessageDigest getShaDigest() {
return getSha1Digest();
}
public static byte[] md2(byte[] data) {
return getMd2Digest().digest(data);
}
public static byte[] md2(InputStream data)
throws IOException {
return digest(getMd2Digest(), data);
}
public static byte[] md2(String data) {
return md2(data.getBytes(Charsets.UTF_8));
}
public static String md2Hex(byte[] data) {
return Hex.encodeHexString(md2(data));
}
public static String md2Hex(InputStream data)
throws IOException {
return Hex.encodeHexString(md2(data));
}
public static String md2Hex(String data) {
return Hex.encodeHexString(md2(data));
}
public static byte[] md5(byte[] data) {
return getMd5Digest().digest(data);
}
public static byte[] md5(InputStream data)
throws IOException {
return digest(getMd5Digest(), data);
}
public static byte[] md5(String data) {
return md5(data.getBytes(Charsets.UTF_8));
}
public static String md5Hex(byte[] data) {
return Hex.encodeHexString(md5(data));
}
public static String md5Hex(InputStream data)
throws IOException {
return Hex.encodeHexString(md5(data));
}
public static String md5Hex(String data) {
return Hex.encodeHexString(md5(data));
}
@Deprecated
public static byte[] sha(byte[] data) {
return sha1(data);
}
@Deprecated
public static byte[] sha(InputStream data)
throws IOException {
return sha1(data);
}
@Deprecated
public static byte[] sha(String data) {
return sha1(data);
}
public static byte[] sha1(byte[] data) {
return getSha1Digest().digest(data);
}
public static byte[] sha1(InputStream data)
throws IOException {
return digest(getSha1Digest(), data);
}
public static byte[] sha1(String data) {
return sha1(data.getBytes(Charsets.UTF_8));
}
public static String sha1Hex(byte[] data) {
return Hex.encodeHexString(sha1(data));
}
public static String sha1Hex(InputStream data)
throws IOException {
return Hex.encodeHexString(sha1(data));
}
public static String sha1Hex(String data) {
return Hex.encodeHexString(sha1(data));
}
public static byte[] sha256(byte[] data) {
return getSha256Digest().digest(data);
}
public static byte[] sha256(InputStream data)
throws IOException {
return digest(getSha256Digest(), data);
}
public static byte[] sha256(String data) {
return sha256(data.getBytes(Charsets.UTF_8));
}
public static String sha256Hex(byte[] data) {
return Hex.encodeHexString(sha256(data));
}
public static String sha256Hex(InputStream data)
throws IOException {
return Hex.encodeHexString(sha256(data));
}
public static String sha256Hex(String data) {
return Hex.encodeHexString(sha256(data));
}
public static byte[] sha384(byte[] data) {
return getSha384Digest().digest(data);
}
public static byte[] sha384(InputStream data)
throws IOException {
return digest(getSha384Digest(), data);
}
public static byte[] sha384(String data) {
return sha384(data.getBytes(Charsets.UTF_8));
}
public static String sha384Hex(byte[] data) {
return Hex.encodeHexString(sha384(data));
}
public static String sha384Hex(InputStream data)
throws IOException {
return Hex.encodeHexString(sha384(data));
}
public static String sha384Hex(String data) {
return Hex.encodeHexString(sha384(data));
}
public static byte[] sha512(byte[] data) {
return getSha512Digest().digest(data);
}
public static byte[] sha512(InputStream data)
throws IOException {
return digest(getSha512Digest(), data);
}
public static byte[] sha512(String data) {
return sha512(data.getBytes(Charsets.UTF_8));
}
public static String sha512Hex(byte[] data) {
return Hex.encodeHexString(sha512(data));
}
public static String sha512Hex(InputStream data)
throws IOException {
return Hex.encodeHexString(sha512(data));
}
public static String sha512Hex(String data) {
return Hex.encodeHexString(sha512(data));
}
@Deprecated
public static String shaHex(byte[] data) {
return sha1Hex(data);
}
@Deprecated
public static String shaHex(InputStream data)
throws IOException {
return sha1Hex(data);
}
@Deprecated
public static String shaHex(String data) {
return sha1Hex(data);
}
public static MessageDigest updateDigest(MessageDigest messageDigest, byte[] valueToDigest) {
messageDigest.update(valueToDigest);
return messageDigest;
}
public static MessageDigest updateDigest(MessageDigest digest, InputStream data)
throws IOException {
byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
int read = data.read(buffer, 0, STREAM_BUFFER_LENGTH);
while (read > -1) {
digest.update(buffer, 0, read);
read = data.read(buffer, 0, STREAM_BUFFER_LENGTH);
}
return digest;
}
public static MessageDigest updateDigest(MessageDigest messageDigest, String valueToDigest) {
messageDigest.update(valueToDigest.getBytes(Charsets.UTF_8));
return messageDigest;
}
}

View File

@@ -0,0 +1,91 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import java.io.IOException;
import java.io.OutputStream;
/**
*
* @author hyh
*/
public class DoubleOutputStream extends OutputStream {
private OutputStream a = null;
private OutputStream b = null;
private boolean c = true;
public DoubleOutputStream(OutputStream paramOutputStream1, OutputStream paramOutputStream2) {
this(paramOutputStream1, paramOutputStream2, true);
}
private DoubleOutputStream(OutputStream paramOutputStream1, OutputStream paramOutputStream2, boolean paramBoolean) {
this.a = paramOutputStream1;
this.b = paramOutputStream2;
this.c = true;
}
@Override
public final void write(byte[] arr, int off, int len) throws IOException {
if (this.a != null) {
this.a.write(arr, off, len);
}
if (this.b != null) {
this.b.write(arr, off, len);
}
if (this.c) {
flush();
}
}
@Override
public final void write(byte[] paramArrayOfByte) throws IOException {
if (this.a != null) {
this.a.write(paramArrayOfByte);
}
if (this.b != null) {
this.b.write(paramArrayOfByte);
}
if (this.c) {
flush();
}
}
@Override
public final void write(int paramInt) throws IOException {
if (this.a != null) {
this.a.write(paramInt);
}
if (this.b != null) {
this.b.write(paramInt);
}
if (this.c) {
flush();
}
}
@Override
public final void close() throws IOException {
flush();
if (this.a != null) {
this.a.close();
}
if (this.b != null) {
this.b.close();
}
}
@Override
public final void flush() throws IOException {
if (this.a != null) {
this.a.flush();
}
if (this.b != null) {
this.b.flush();
}
}
}

View File

@@ -0,0 +1,15 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
/**
*
* @author huangyuhui
* @param <T> EventArgs
*/
public interface Event<T> {
boolean call(Object sender, T t);
}

View File

@@ -0,0 +1,39 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import java.util.HashSet;
/**
*
* @author huangyuhui
* @param <T> EventArgs
*/
public class EventHandler<T> {
HashSet<Event<T>> handlers;
Object sender;
public EventHandler(Object sender) {
handlers = new HashSet<>();
this.sender = sender;
}
public void register(Event<T> t) {
handlers.add(t);
}
public void unregister(Event<T> t) {
handlers.remove(t);
}
public boolean execute(T x) {
boolean flag = true;
for(Event<T> t : handlers)
if(!t.call(sender, x)) flag = false;
return flag;
}
}

View File

@@ -0,0 +1,463 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.List;
import org.jackhuang.hellominecraft.HMCLog;
/**
*
* @author hyh
*/
public class FileUtils {
public static void deleteDirectory(File directory)
throws IOException {
if (!directory.exists()) {
return;
}
if (!isSymlink(directory)) {
cleanDirectory(directory);
}
if (!directory.delete()) {
String message = "Unable to delete directory " + directory + ".";
throw new IOException(message);
}
}
public static boolean deleteDirectoryQuietly(File directory) {
try {
deleteDirectory(directory);
return true;
} catch(Exception e) {
HMCLog.err("Failed to delete directory " + directory, e);
return false;
}
}
public static boolean cleanDirectoryQuietly(File directory) {
try {
cleanDirectory(directory);
return true;
} catch(Exception e) {
HMCLog.err("Failed to clean directory " + directory, e);
return false;
}
}
public static void cleanDirectory(File directory)
throws IOException {
if (!directory.exists()) {
//String message = directory + " does not exist";
//throw new IllegalArgumentException(message);
directory.mkdirs();
return;
}
if (!directory.isDirectory()) {
String message = directory + " is not a directory";
throw new IllegalArgumentException(message);
}
File[] files = directory.listFiles();
if (files == null) {
throw new IOException("Failed to list contents of " + directory);
}
IOException exception = null;
for (File file : files) {
try {
forceDelete(file);
} catch (IOException ioe) {
exception = ioe;
}
}
if (null != exception) {
throw exception;
}
}
public static void forceDelete(File file)
throws IOException {
if (file.isDirectory()) {
deleteDirectory(file);
} else {
boolean filePresent = file.exists();
if (!file.delete()) {
if (!filePresent) {
throw new FileNotFoundException("File does not exist: " + file);
}
String message = "Unable to delete file: " + file;
throw new IOException(message);
}
}
}
public static boolean isSymlink(File file)
throws IOException {
if (file == null) {
throw new NullPointerException("File must not be null");
}
if (File.separatorChar == '\\') {
return false;
}
File fileInCanonicalDir;
if (file.getParent() == null) {
fileInCanonicalDir = file;
} else {
File canonicalDir = file.getParentFile().getCanonicalFile();
fileInCanonicalDir = new File(canonicalDir, file.getName());
}
return !fileInCanonicalDir.getCanonicalFile().equals(fileInCanonicalDir.getAbsoluteFile());
}
public static void copyDirectory(File srcDir, File destDir)
throws IOException {
copyDirectory(srcDir, destDir, true);
}
public static void copyDirectory(File srcDir, File destDir, boolean preserveFileDate)
throws IOException {
copyDirectory(srcDir, destDir, null, preserveFileDate);
}
public static void copyDirectory(File srcDir, File destDir, FileFilter filter)
throws IOException {
copyDirectory(srcDir, destDir, filter, true);
}
public static void copyDirectory(File srcDir, File destDir, FileFilter filter, boolean preserveFileDate)
throws IOException {
if (srcDir == null) {
throw new NullPointerException("Source must not be null");
}
if (destDir == null) {
throw new NullPointerException("Destination must not be null");
}
if (!srcDir.exists()) {
throw new FileNotFoundException("Source '" + srcDir + "' does not exist");
}
if (!srcDir.isDirectory()) {
throw new IOException("Source '" + srcDir + "' exists but is not a directory");
}
if (srcDir.getCanonicalPath().equals(destDir.getCanonicalPath())) {
throw new IOException("Source '" + srcDir + "' and destination '" + destDir + "' are the same");
}
List exclusionList = null;
if (destDir.getCanonicalPath().startsWith(srcDir.getCanonicalPath())) {
File[] srcFiles = filter == null ? srcDir.listFiles() : srcDir.listFiles(filter);
if ((srcFiles != null) && (srcFiles.length > 0)) {
exclusionList = new ArrayList(srcFiles.length);
for (File srcFile : srcFiles) {
File copiedFile = new File(destDir, srcFile.getName());
exclusionList.add(copiedFile.getCanonicalPath());
}
}
}
doCopyDirectory(srcDir, destDir, filter, preserveFileDate, exclusionList);
}
private static void doCopyDirectory(File srcDir, File destDir, FileFilter filter, boolean preserveFileDate, List<String> exclusionList)
throws IOException {
File[] srcFiles = filter == null ? srcDir.listFiles() : srcDir.listFiles(filter);
if (srcFiles == null) {
throw new IOException("Failed to list contents of " + srcDir);
}
if (destDir.exists()) {
if (!destDir.isDirectory()) {
throw new IOException("Destination '" + destDir + "' exists but is not a directory");
}
} else if ((!destDir.mkdirs()) && (!destDir.isDirectory())) {
throw new IOException("Destination '" + destDir + "' directory cannot be created");
}
if (!destDir.canWrite()) {
throw new IOException("Destination '" + destDir + "' cannot be written to");
}
for (File srcFile : srcFiles) {
File dstFile = new File(destDir, srcFile.getName());
if ((exclusionList == null) || (!exclusionList.contains(srcFile.getCanonicalPath()))) {
if (srcFile.isDirectory()) {
doCopyDirectory(srcFile, dstFile, filter, preserveFileDate, exclusionList);
} else {
doCopyFile(srcFile, dstFile, preserveFileDate);
}
}
}
if (preserveFileDate) {
destDir.setLastModified(srcDir.lastModified());
}
}
public static String readFileToString(File file)
throws IOException {
return NetUtils.getStreamContent(IOUtils.openInputStream(file));
}
public static String readFileToStringQuietly(File file) {
try {
return NetUtils.getStreamContent(IOUtils.openInputStream(file));
} catch (IOException ex) {
HMCLog.err("Failed to read file: " + file, ex);
return null;
}
}
public static String readFileToString(File file, String charset)
throws IOException {
return NetUtils.getStreamContent(IOUtils.openInputStream(file), charset);
}
public static String readFileToStringIgnoreFileNotFound(File file) throws IOException {
try {
return NetUtils.getStreamContent(IOUtils.openInputStream(file));
} catch (FileNotFoundException ex) {
return "";
}
}
public static void copyFile(File srcFile, File destFile)
throws IOException {
copyFile(srcFile, destFile, true);
}
public static void copyFile(File srcFile, File destFile, boolean preserveFileDate)
throws IOException {
if (srcFile == null) {
throw new NullPointerException("Source must not be null");
}
if (destFile == null) {
throw new NullPointerException("Destination must not be null");
}
if (!srcFile.exists()) {
throw new FileNotFoundException("Source '" + srcFile + "' does not exist");
}
if (srcFile.isDirectory()) {
throw new IOException("Source '" + srcFile + "' exists but is a directory");
}
if (srcFile.getCanonicalPath().equals(destFile.getCanonicalPath())) {
throw new IOException("Source '" + srcFile + "' and destination '" + destFile + "' are the same");
}
File parentFile = destFile.getParentFile();
if ((parentFile != null)
&& (!parentFile.mkdirs()) && (!parentFile.isDirectory())) {
throw new IOException("Destination '" + parentFile + "' directory cannot be created");
}
if ((destFile.exists()) && (!destFile.canWrite())) {
throw new IOException("Destination '" + destFile + "' exists but is read-only");
}
doCopyFile(srcFile, destFile, preserveFileDate);
}
private static void doCopyFile(File srcFile, File destFile, boolean preserveFileDate)
throws IOException {
if ((destFile.exists()) && (destFile.isDirectory())) {
throw new IOException("Destination '" + destFile + "' exists but is a directory");
}
FileInputStream fis = null;
FileOutputStream fos = null;
FileChannel input = null;
FileChannel output = null;
try {
fis = new FileInputStream(srcFile);
fos = new FileOutputStream(destFile);
input = fis.getChannel();
output = fos.getChannel();
long size = input.size();
long pos = 0L;
long count;
while (pos < size) {
count = size - pos > 31457280L ? 31457280L : size - pos;
pos += output.transferFrom(input, pos, count);
}
} finally {
IOUtils.closeQuietly(output);
IOUtils.closeQuietly(fos);
IOUtils.closeQuietly(input);
IOUtils.closeQuietly(fis);
}
if (srcFile.length() != destFile.length()) {
throw new IOException("Failed to copy full contents from '" + srcFile + "' to '" + destFile + "'");
}
if (preserveFileDate) {
destFile.setLastModified(srcFile.lastModified());
}
}
public static int indexOfLastSeparator(String filename) {
if (filename == null) {
return -1;
}
int lastUnixPos = filename.lastIndexOf(47);
int lastWindowsPos = filename.lastIndexOf(92);
return Math.max(lastUnixPos, lastWindowsPos);
}
public static int indexOfExtension(String filename) {
if (filename == null) {
return -1;
}
int extensionPos = filename.lastIndexOf(46);
int lastSeparator = indexOfLastSeparator(filename);
return lastSeparator > extensionPos ? -1 : extensionPos;
}
public static String getName(String filename) {
if (filename == null) {
return null;
}
int index = indexOfLastSeparator(filename);
return filename.substring(index + 1);
}
public static String getBaseName(String filename) {
return removeExtension(getName(filename));
}
public static String getExtension(String filename) {
if (filename == null) {
return null;
}
int index = indexOfExtension(filename);
if (index == -1) {
return "";
}
return filename.substring(index + 1);
}
public static String removeExtension(String filename) {
if (filename == null) {
return null;
}
int index = indexOfExtension(filename);
if (index == -1) {
return filename;
}
return filename.substring(0, index);
}
public static void writeQuietly(File file, CharSequence data) {
try {
write(file, data);
} catch(IOException e) {
HMCLog.warn("Failed to write data to file: " + file, e);
}
}
public static void write(File file, CharSequence data)
throws IOException {
write(file, data, "UTF-8", false);
}
public static void write(File file, CharSequence data, boolean append)
throws IOException {
write(file, data, "UTF-8", append);
}
public static void write(File file, CharSequence data, String encoding)
throws IOException {
write(file, data, encoding, false);
}
public static void write(File file, CharSequence data, String encoding, boolean append)
throws IOException {
String str = data == null ? null : data.toString();
writeStringToFile(file, str, encoding, append);
}
public static void writeStringToFile(File file, String data)
throws IOException {
writeStringToFile(file, data, "UTF-8", false);
}
public static void writeStringToFile(File file, String data, String encoding)
throws IOException {
writeStringToFile(file, data, encoding, false);
}
public static void writeStringToFile(File file, String data, String encoding, boolean append)
throws IOException {
OutputStream out = null;
try {
out = openOutputStream(file, append);
IOUtils.write(data, out, encoding);
out.close();
} finally {
IOUtils.closeQuietly(out);
}
}
public static FileInputStream openInputStream(File file)
throws IOException {
if (file.exists()) {
if (file.isDirectory()) {
throw new IOException("File '" + file + "' exists but is a directory");
}
if (!file.canRead()) {
throw new IOException("File '" + file + "' cannot be read");
}
} else {
throw new FileNotFoundException("File '" + file + "' does not exist");
}
return new FileInputStream(file);
}
public static FileOutputStream openOutputStream(File file)
throws IOException {
return openOutputStream(file, false);
}
public static FileOutputStream openOutputStream(File file, boolean append)
throws IOException {
if (file.exists()) {
if (file.isDirectory()) {
throw new IOException("File '" + file + "' exists but is a directory");
}
if (!file.canWrite()) {
throw new IOException("File '" + file + "' cannot be written to");
}
} else {
File parent = file.getParentFile();
if ((parent != null)
&& (!parent.mkdirs()) && (!parent.isDirectory())) {
throw new IOException("Directory '" + parent + "' could not be created");
}
file.createNewFile();
}
return new FileOutputStream(file, append);
}
public static File[] searchSuffix(File dir, String suffix) {
ArrayList<File> al = new ArrayList();
File[] files = dir.listFiles();
for(File f : files)
if(f.getName().endsWith(suffix)) al.add(f);
return al.toArray(new File[0]);
}
}

View File

@@ -0,0 +1,124 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import java.nio.charset.Charset;
public class Hex {
public static final Charset DEFAULT_CHARSET = Charsets.UTF_8;
public static final String DEFAULT_CHARSET_NAME = "UTF-8";
private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
private static final char[] DIGITS_UPPER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
private final Charset charset;
public static byte[] decodeHex(char[] data) throws Exception {
int len = data.length;
if ((len & 0x1) != 0) {
throw new Exception("Odd number of characters.");
}
byte[] out = new byte[len >> 1];
int i = 0;
for (int j = 0; j < len; i++) {
int f = toDigit(data[j], j) << 4;
j++;
f |= toDigit(data[j], j);
j++;
out[i] = (byte) (f & 0xFF);
}
return out;
}
public static char[] encodeHex(byte[] data) {
return encodeHex(data, true);
}
public static char[] encodeHex(byte[] data, boolean toLowerCase) {
return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
}
protected static char[] encodeHex(byte[] data, char[] toDigits) {
int l = data.length;
char[] out = new char[l << 1];
int i = 0;
for (int j = 0; i < l; i++) {
out[(j++)] = toDigits[((0xF0 & data[i]) >>> 4)];
out[(j++)] = toDigits[(0xF & data[i])];
}
return out;
}
public static String encodeHexString(byte[] data) {
return new String(encodeHex(data));
}
protected static int toDigit(char ch, int index) throws Exception {
int digit = Character.digit(ch, 16);
if (digit == -1) {
throw new Exception("Illegal hexadecimal character " + ch + " at index " + index);
}
return digit;
}
public Hex() {
this.charset = DEFAULT_CHARSET;
}
public Hex(Charset charset) {
this.charset = charset;
}
public Hex(String charsetName) {
this(Charset.forName(charsetName));
}
public byte[] decode(byte[] array) throws Exception {
return decodeHex(new String(array, getCharset()).toCharArray());
}
public Object decode(Object object) throws Exception {
try {
char[] charArray = (object instanceof String) ? ((String) object).toCharArray() : (char[]) (char[]) object;
return decodeHex(charArray);
} catch (ClassCastException e) {
throw new Exception(e.getMessage(), e);
}
}
public byte[] encode(byte[] array) {
return encodeHexString(array).getBytes(getCharset());
}
public Object encode(Object object)
throws Exception {
try {
byte[] byteArray = (object instanceof String) ? ((String) object).getBytes(getCharset()) : (byte[]) (byte[]) object;
return encodeHex(byteArray);
} catch (ClassCastException e) {
throw new Exception(e.getMessage(), e);
}
}
public Charset getCharset() {
return this.charset;
}
public String getCharsetName() {
return this.charset.name();
}
@Override
public String toString() {
return super.toString() + "[charsetName=" + this.charset + "]";
}
}

View File

@@ -0,0 +1,282 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
import org.jackhuang.hellominecraft.HMCLog;
/**
*
* @author huang
*/
public class IOUtils {
public static String addSeparator(String path) {
if (path == null || path.trim().length() == 0) {
return "";
}
if (isSeparator(path.charAt(path.length() - 1))) {
return path;
} else {
return path + File.separatorChar;
}
}
public static boolean isSeparator(char ch) {
return ch == File.separatorChar || ch == '/' || ch == '\\';
}
public static String removeLastSeparator(String dir) {
String t = dir.trim();
char ch = t.charAt(t.length() - 1);
if (isSeparator(ch)) {
return t.substring(0, t.length() - 1);
}
return t;
}
public static String extractLastDirectory(String dir) {
String t = removeLastSeparator(dir);
int i = t.length() - 1;
while (i >= 0 && !isSeparator(dir.charAt(i))) {
i--;
}
if (i < 0) {
return t;
}
return t.substring(i + 1, (t.length() - i) + (i + 1) - 1);
}
public static ArrayList<String> findAllFile(File f) {
ArrayList<String> arr = new ArrayList<>();
if (f.isDirectory()) {
File[] f1 = f.listFiles();
int len = f1.length;
for (int i = 0; i < len; i++) {
if (f1[i].isFile()) {
arr.add(f1[i].getName());
}
}
}
return arr;
}
public static ArrayList<String> findAllFileWithFullName(File f) {
ArrayList<String> arr = new ArrayList<>();
if (f.isDirectory()) {
File[] f1 = f.listFiles();
int len = f1.length;
for (int i = 0; i < len; i++) {
if (f1[i].isFile()) {
arr.add(addSeparator(f.getAbsolutePath()) + f1[i].getName());
}
}
}
return arr;
}
public static ArrayList<String> findAllDir(File f) {
ArrayList<String> arr = new ArrayList<>();
if (f.isDirectory()) {
File[] f1 = f.listFiles();
int len = f1.length;
for (int i = 0; i < len; i++) {
if (f1[i].isDirectory()) {
arr.add(f1[i].getName());
}
}
}
return arr;
}
public static File currentDir() {
return new File(".");
}
public static String currentDirWithSeparator() {
return addSeparator(currentDir().getAbsolutePath());
}
public static String getLocalMAC() {
InetAddress addr;
try {
addr = InetAddress.getLocalHost();
String ip = addr.getHostAddress();
return getMacAddress(ip);
} catch (UnknownHostException e) {
HMCLog.warn("Failed to get local mac address because of the unknown host.", e);
}
return "ERROR";
}
public static String getMacAddress(String host) {
String mac;
StringBuilder sb = new StringBuilder();
try {
NetworkInterface ni = NetworkInterface.getByInetAddress(InetAddress.getByName(host));
byte[] macs = ni.getHardwareAddress();
for (int i = 0; i < macs.length; i++) {
mac = Integer.toHexString(macs[i] & 0xFF);
if (mac.length() == 1) {
mac = '0' + mac;
}
sb.append(mac).append("-");
}
} catch (SocketException e) {
HMCLog.warn("Failed to get mac address because the socket has thrown an exception.", e);
} catch (UnknownHostException e) {
HMCLog.warn("Failed to get mac address because of the unknown host.", e);
}
mac = sb.toString();
mac = mac.substring(0, mac.length() - 1);
return mac;
}
public static String extractFileName(String fileName) {
File file = new File(fileName);
return file.getName();
}
public static String getJavaDir() {
String path = System.getProperty("java.home") + File.separatorChar + "bin" + File.separatorChar;
path = addSeparator(path);
if (OS.os() == OS.WINDOWS && new File(path + "javaw.exe").isFile()) {
return path + "javaw.exe";
} else {
return path + "java";
}
}
public static byte[] readFully(InputStream stream) throws IOException {
byte[] data = new byte[4096];
ByteArrayOutputStream entryBuffer = new ByteArrayOutputStream();
int len;
do {
len = stream.read(data);
if (len <= 0) {
continue;
}
entryBuffer.write(data, 0, len);
} while (len != -1);
return entryBuffer.toByteArray();
}
public static void closeQuietly(Reader input) {
closeQuietly((Closeable) input);
}
public static void closeQuietly(Writer output) {
closeQuietly((Closeable) output);
}
public static void closeQuietly(InputStream input) {
closeQuietly((Closeable) input);
}
public static void closeQuietly(OutputStream output) {
closeQuietly((Closeable) output);
}
public static void closeQuietly(Closeable closeable) {
try {
if (closeable != null) {
closeable.close();
}
} catch (IOException ioe) {
}
}
public static void write(byte[] data, OutputStream output)
throws IOException {
if (data != null) {
output.write(data);
}
}
public static void write(String data, OutputStream output, String encoding)
throws IOException {
if (data != null) {
output.write(data.getBytes(encoding));
}
}
public static FileInputStream openInputStream(File file)
throws IOException {
if (file.exists()) {
if (file.isDirectory()) {
throw new IOException("File '" + file + "' exists but is a directory");
}
if (!file.canRead()) {
throw new IOException("File '" + file + "' cannot be read");
}
} else {
throw new FileNotFoundException("File '" + file + "' does not exist");
}
return new FileInputStream(file);
}
public static String tryGetCanonicalFolderPath(File file) {
try {
return IOUtils.addSeparator(file.getCanonicalPath());
} catch (IOException ex) {
return IOUtils.addSeparator(file.getAbsolutePath());
}
}
public static File tryGetCanonicalFile(File file) {
try {
return file.getCanonicalFile();
} catch (IOException ex) {
return file.getAbsoluteFile();
}
}
public static File tryGetCanonicalFile(String file) {
return tryGetCanonicalFile(new File(file));
}
public static String tryGetCanonicalFilePath(File file) {
try {
return file.getCanonicalPath();
} catch (IOException ex) {
return file.getAbsolutePath();
}
}
public static URL parseURL(String str) {
try {
return new URL(str);
} catch (MalformedURLException ex) {
HMCLog.warn("Failed to parse URL:" + str);
return null;
}
}
}

View File

@@ -0,0 +1,79 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
*
* @author hyh
*/
public class JavaProcess {
private final List<String> commands;
private final Process process;
private final ArrayList<String> stdOutLines = new ArrayList<>();
private final ArrayList<String> stdErrLines = new ArrayList<>();
public JavaProcess(List<String> commands, Process process, ProcessManager pm) {
this.commands = commands;
this.process = process;
if(pm != null) pm.registerProcess(this);
}
public JavaProcess(String[] commands, Process process, ProcessManager pm) {
this(Arrays.asList(commands), process, pm);
}
public Process getRawProcess() {
return this.process;
}
public List<String> getStartupCommands() {
return this.commands;
}
public String getStartupCommand() {
return this.process.toString();
}
public ArrayList<String> getStdOutLines() {
return this.stdOutLines;
}
public ArrayList<String> getStdErrLines() {
return this.stdErrLines;
}
public boolean isRunning() {
try {
this.process.exitValue();
} catch (IllegalThreadStateException ex) {
return true;
}
return false;
}
public int getExitCode() {
try {
return this.process.exitValue();
} catch (IllegalThreadStateException ex) {
ex.fillInStackTrace();
throw ex;
}
}
@Override
public String toString() {
return "JavaProcess[commands=" + this.commands + ", isRunning=" + isRunning() + "]";
}
public void stop() {
this.process.destroy();
}
}

View File

@@ -0,0 +1,180 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jackhuang.hellominecraft.HMCLog;
/**
*
* @author hyh
*/
public final class JdkVersion {
public String ver;
/**
* -1 - unkown 0 - 32Bit 1 - 64Bit
*/
public int is64Bit;
public JdkVersion(String ver, int is64Bit) {
this.ver = ver;
this.is64Bit = is64Bit;
}
/**
* Constant identifying the 1.5 JVM (Java 5).
*/
public static final int UNKOWN = 2;
/**
* Constant identifying the 1.5 JVM (Java 5).
*/
public static final int JAVA_15 = 2;
/**
* Constant identifying the 1.6 JVM (Java 6).
*/
public static final int JAVA_16 = 3;
/**
* Constant identifying the 1.7 JVM (Java 7).
*/
public static final int JAVA_17 = 4;
/**
* Constant identifying the 1.8 JVM (Java 8).
*/
public static final int JAVA_18 = 5;
/**
* Constant identifying the 1.9 JVM (Java 9).
*/
public static final int JAVA_19 = 6;
private static final String javaVersion;
private static final int majorJavaVersion;
static {
javaVersion = System.getProperty("java.version");
// version String should look like "1.4.2_10"
if (javaVersion.contains("1.9.")) {
majorJavaVersion = JAVA_18;
} else if (javaVersion.contains("1.8.")) {
majorJavaVersion = JAVA_18;
} else if (javaVersion.contains("1.7.")) {
majorJavaVersion = JAVA_17;
} else if (javaVersion.contains("1.6.")) {
majorJavaVersion = JAVA_16;
} else {
// else leave 1.5 as default (it's either 1.5 or unknown)
majorJavaVersion = JAVA_15;
}
}
/**
* Return the full Java version string, as returned by
* <code>System.getProperty("java.version")</code>.
*
* @return the full Java version string
* @see System#getProperty(String)
*/
public static String getJavaVersion() {
return javaVersion;
}
/**
* Get the major version code. This means we can do things like
* <code>if (getMajorJavaVersion() < JAVA_14)</code>. @retu
*
*
* rn a code comparable to the JAVA_XX codes in this class
* @return
* @see #JAVA_13
* @see #JAVA_14
* @see #JAVA_15
* @see #JAVA_16
* @see #JAVA_17
*/
public static int getMajorJavaVersion() {
return majorJavaVersion;
}
/**
* Convenience method to determine if the current JVM is at least Java 1.6
* (Java 6).
*
* @return <code>true</code> if the current JVM is at least Java 1.6
* @deprecated as of Spring 3.0, in favor of reflective checks for the
* specific Java 1.6 classes of interest
* @see #getMajorJavaVersion()
* @see #JAVA_16
* @see #JAVA_17
*/
@Deprecated
public static boolean isAtLeastJava16() {
return (majorJavaVersion >= JAVA_16);
}
public static boolean isJava64Bit() {
String jdkBit = System.getProperty("sun.arch.data.model");
return jdkBit.contains("64");
}
static Pattern p = Pattern.compile("java version \"[1-9]*\\.[1-9]*\\.[0-9]*(.*?)\"");
public static JdkVersion getJavaVersionFromExecutable(String file) throws IOException {
String[] str = new String[]{file, "-version"};
ProcessBuilder pb = new ProcessBuilder(str);
JavaProcess jp = new JavaProcess(str, pb.start(), null);
InputStream is = jp.getRawProcess().getErrorStream();
BufferedReader br = null;
int lineNumber = 0;
String ver = null;
int is64Bit = -1;
try {
br = new BufferedReader(new InputStreamReader(is));
String line;
jp.getRawProcess().waitFor();
while ((line = br.readLine()) != null) {
lineNumber++;
switch (lineNumber) {
case 1:
Matcher m = p.matcher(line);
if (m.find()) {
ver = m.group();
ver = ver.substring("java version \"".length(), ver.length() - 1);
}
break;
case 3:
if (line.contains("64-Bit")) {
is64Bit = 1;
} else {
is64Bit = 0;
}
break;
}
}
} catch (InterruptedException | IOException e) {
HMCLog.warn("Failed to get java version", e);
} finally {
if (br != null) {
br.close();
}
}
return new JdkVersion(ver, is64Bit);
}
public void write(File f) throws IOException {
if (ver != null && is64Bit != -1) {
FileUtils.write(f, ver + "\n" + is64Bit);
}
}
public boolean isEarlyAccess() {
return ver != null && ver.endsWith("-ea");
}
}

View File

@@ -0,0 +1,37 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import org.jackhuang.hellominecraft.utils.functions.Consumer;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
/**
*
* @author hyh
*/
public class LauncherPrintStream extends PrintStream {
private final ArrayList<Consumer<String>> printListeners = new ArrayList<>();
public LauncherPrintStream(OutputStream paramOutputStream) {
super(paramOutputStream);
}
@Override
public final void println(String paramString) {
super.println(paramString);
for (Consumer<String> a1 : printListeners) {
a1.accept(paramString);
}
}
public final void addPrintListener(Consumer<String> paraml) {
this.printListeners.add(paraml);
}
}

View File

@@ -0,0 +1,43 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.jackhuang.hellominecraft.HMCLog;
/**
*
* @author huang
*/
public class MD5Utils {
private static final char e[] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f'
};
public static String hash(String type, String source) {
try {
StringBuilder stringbuilder;
MessageDigest md = MessageDigest.getInstance(type);
md.update(source.getBytes());
byte[] bytes = md.digest();
int s2 = bytes.length;
stringbuilder = new StringBuilder(s2 << 1);
for (int i1 = 0; i1 < s2; i1++) {
stringbuilder.append(e[bytes[i1] >> 4 & 0xf]);
stringbuilder.append(e[bytes[i1] & 0xf]);
}
return stringbuilder.toString();
} catch (NoSuchAlgorithmException e) {
HMCLog.err("Failed to get md5", e);
return "";
}
}
}

View File

@@ -0,0 +1,43 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
/**
*
* @author huang
*/
public class MathUtils {
public static int parseInt(String s, int def) {
try {
return Integer.parseInt(s);
} catch (Exception e) {
return def;
}
}
public static boolean canParseInt(String s) {
try {
Integer.parseInt(s);
return true;
} catch (Exception e) {
return false;
}
}
public static int parseMemory(String s, int def) {
try {
return Integer.parseInt(s);
} catch (Exception e) {
int a = parseInt(s.substring(0, s.length() - 1), def);
if(s.endsWith("g")) return a * 1024;
else if(s.endsWith("k")) return a / 1024;
else return a;
}
}
}

View File

@@ -0,0 +1,114 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import javax.swing.JOptionPane;
import org.jackhuang.hellominecraft.C;
/**
* @author hyh
*/
public class MessageBox
{
private static String Title = C.i18n("message.info");
/**
* Buttons: OK
*/
public static final int DEFAULT_OPTION = -1;
/**
* Buttons: Yes No
*/
public static final int YES_NO_OPTION = 10;
/**
* Buttons: Yes No Cancel
*/
public static final int YES_NO_CANCEL_OPTION =11;
/**
* Buttons: OK Cancel
*/
public static final int OK_CANCEL_OPTION = 12;
/**
* User Operation: Yes
*/
public static final int YES_OPTION = 0;
/**
* User Operation: No
*/
public static final int NO_OPTION = 1;
/**
* User Operation: Cancel
*/
public static final int CANCEL_OPTION = 2;
/**
* User Operation: OK
*/
public static final int OK_OPTION = 0;
/**
* User Operation: Closed Message Box
*/
public static final int CLOSED_OPTION = -1;
/**
* Message Box Type: Error
*/
public static final int ERROR_MESSAGE = 0;
/**
* Message Box Type: Info
*/
public static final int INFORMATION_MESSAGE = 1;
/**
* Message Box Type: Warning
*/
public static final int WARNING_MESSAGE = 2;
/**
* Message Box Type: Question
*/
public static final int QUESTION_MESSAGE = 3;
/**
* Message Box Type: Plain
*/
public static final int PLAIN_MESSAGE = -1;
/**
* Show MsgBox with title and options
* @param Msg The Message
* @param Title The title of MsgBox.
* @param Option The type of MsgBox.
* @return user operation.
*/
public static int Show(String Msg, String Title, int Option)
{
switch(Option)
{
case YES_NO_OPTION:
case YES_NO_CANCEL_OPTION:
case OK_CANCEL_OPTION:
return JOptionPane.showConfirmDialog(null, Msg, Title, Option - 10);
default:
JOptionPane.showMessageDialog(null, Msg, Title, Option);
}
return 0;
}
/**
* Show MsgBox with options
* @param Msg The Message
* @param Option The type of MsgBox.
* @return User Operation
*/
public static int Show(String Msg, int Option)
{
return Show(Msg, Title, Option);
}
/**
* Show Default MsgBox
* @param Msg The Message
* @return User Operation
*/
public static int Show(String Msg)
{
return Show(Msg, Title, INFORMATION_MESSAGE);
}
}

View File

@@ -0,0 +1,48 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import org.jackhuang.hellominecraft.C;
/**
* @author hyh
*/
public class MinecraftVersionRequest {
public static final int Unkown = 0, Invaild = 1, InvaildJar = 2,
Modified = 3, OK = 4, NotFound = 5, NotReadable = 6, NotAFile = 7;
public int type;
public String version;
public static String getResponse(MinecraftVersionRequest minecraftVersion) {
String text = "";
switch (minecraftVersion.type) {
case MinecraftVersionRequest.Invaild:
text = C.i18n("minecraft.invalid");
break;
case MinecraftVersionRequest.InvaildJar:
text = C.i18n("minecraft.invalid_jar");
break;
case MinecraftVersionRequest.NotAFile:
text = C.i18n("minecraft.not_a_file");
break;
case MinecraftVersionRequest.NotFound:
text = C.i18n("minecraft.not_found");
break;
case MinecraftVersionRequest.NotReadable:
text = C.i18n("minecraft.not_readable");
break;
case MinecraftVersionRequest.Modified:
text = C.i18n("minecraft.modified") + " ";
case MinecraftVersionRequest.OK:
text += minecraftVersion.version;
break;
case MinecraftVersionRequest.Unkown:
default:
text = "???";
break;
}
return text;
}
}

View File

@@ -0,0 +1,175 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map;
import org.jackhuang.hellominecraft.HMCLog;
/**
*
* @author huang
*/
public final class NetUtils {
public static byte[] getBytesFromStream(InputStream is) throws IOException {
ByteArrayOutputStream localByteArrayOutputStream = new ByteArrayOutputStream();
byte[] arrayOfByte1 = new byte[1024];
int i;
while ((i = is.read(arrayOfByte1)) >= 0) {
localByteArrayOutputStream.write(arrayOfByte1, 0, i);
}
is.close();
return localByteArrayOutputStream.toByteArray();
}
public static String getStreamContent(InputStream is) throws IOException {
return getStreamContent(is, DEFAULT_CHARSET);
}
public static String getStreamContent(InputStream is, String encoding)
throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(is, encoding));
String result = "";
String line;
while ((line = br.readLine()) != null) {
result += line + "\n";
}
br.close();
if(result.length() < 1) return "";
else return result.substring(0, result.length() - 1);
}
public static String doGet(String url, String encoding) throws IOException {
return getStreamContent(new URL(url).openConnection().getInputStream());
}
public static String doGet(String url) throws IOException {
return doGet(url, DEFAULT_CHARSET);
}
/**
* Sends an HTTP GET request to a url
*
* @param endpoint - The URL of the server. (Example: "
* http://www.yahoo.com/search")
* @param requestParameters - all the request parameters (Example:
* "param1=val1&param2=val2"). Note: This method will add the question mark
* (?) to the request - DO NOT add it yourself
* @return - The response from the end point
*/
public static String sendGetRequest(String endpoint,
String requestParameters) {
String result = null;
if (endpoint.startsWith("http://")) {
// Send a GET request to the servlet
try {
// Construct data
StringBuilder data = new StringBuilder();
// Send data
String urlStr = endpoint;
if (requestParameters != null && requestParameters.length() > 0) {
urlStr += "?" + requestParameters;
}
URL url = new URL(urlStr);
URLConnection conn = url.openConnection();
// Get the response
InputStreamReader r = new InputStreamReader(conn.getInputStream());
StringBuffer sb;
BufferedReader rd = new BufferedReader(r);
sb = new StringBuffer();
String line;
while ((line = rd.readLine()) != null)
sb.append(line);
result = sb.toString();
} catch (Exception e) {
HMCLog.warn("Failed to send get request.", e);
}
}
return result;
}
public static String post(String url, Map<String, String> params) {
URL u = null;
HttpURLConnection con = null;
StringBuilder sb = new StringBuilder();
if (params != null) {
for (Map.Entry<String, String> e : params.entrySet()) {
sb.append(e.getKey());
sb.append("=");
sb.append(e.getValue());
sb.append("&");
}
sb = new StringBuilder(sb.substring(0, sb.length() - 1));
}
System.out.println("send_url:" + url);
System.out.println("send_data:" + sb.toString());
try {
u = new URL(url);
con = (HttpURLConnection) u.openConnection();
con.setRequestMethod(METHOD_POST);
con.setDoOutput(true);
con.setDoInput(true);
con.setUseCaches(false);
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream(), DEFAULT_CHARSET);
osw.write(sb.toString());
osw.flush();
osw.close();
} catch (Exception e) {
HMCLog.warn("Failed to post.", e);
}
StringBuilder buffer = new StringBuilder();
try {
BufferedReader br = new BufferedReader(new InputStreamReader(con
.getInputStream(), DEFAULT_CHARSET));
String temp;
while ((temp = br.readLine()) != null) {
buffer.append(temp);
buffer.append("\n");
}
} catch (Exception e) {
e.printStackTrace();
}
con.disconnect();
return buffer.toString();
}
private static final String METHOD_POST = "POST";
private static final String DEFAULT_CHARSET = "UTF-8";
public static URL constantURL(String url) {
try {
return new URL(url);
} catch (MalformedURLException ex) {
HMCLog.err("Failed to get url instance: " + url, ex);
return null;
}
}
public static URL concatenateURL(URL url, String query) {
try {
if ((url.getQuery() != null) && (url.getQuery().length() > 0)) {
return new URL(url.getProtocol(), url.getHost(), url.getPort(), new StringBuilder().append(url.getFile()).append("&").append(query).toString());
}
return new URL(url.getProtocol(), url.getHost(), url.getPort(), new StringBuilder().append(url.getFile()).append("?").append(query).toString());
} catch (MalformedURLException ex) {
throw new IllegalArgumentException("Could not concatenate given URL with GET arguments!", ex);
}
}
}

View File

@@ -0,0 +1,63 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import com.sun.management.OperatingSystemMXBean;
import java.lang.management.ManagementFactory;
import org.jackhuang.hellominecraft.HMCLog;
/**
* @author hyh
*/
public enum OS {
LINUX,
WINDOWS,
OSX,
UNKOWN;
public static OS os() {
String str;
if ((str = System.getProperty("os.name").toLowerCase())
.contains("win")) {
return OS.WINDOWS;
}
if (str.contains("mac")) {
return OS.OSX;
}
if (str.contains("solaris")) {
return OS.LINUX;
}
if (str.contains("sunos")) {
return OS.LINUX;
}
if (str.contains("linux")) {
return OS.LINUX;
}
if (str.contains("unix")) {
return OS.LINUX;
}
return OS.UNKOWN;
}
public static boolean is64Bit() {
String arch = System.getProperty("os.arch");
return arch.contains("64");
}
/**
* @return Free Physical Memory Size (Byte)
*/
public static long getTotalPhysicalMemory() {
try {
OperatingSystemMXBean o = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
return o.getTotalPhysicalMemorySize();
} catch(Throwable t) {
HMCLog.warn("Failed to get total physical memory size", t);
return -1;
}
}
}

View File

@@ -0,0 +1,20 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
/**
*
* @author hyh
*/
public class Pair<K, V> {
public K key;
public V value;
public Pair(K k, V v) {
key = k;
value = v;
}
}

View File

@@ -0,0 +1,32 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import java.util.HashSet;
/**
*
* @author huangyuhui
*/
public class ProcessManager {
private static final HashSet<JavaProcess> gameProcesses = new HashSet();
public void registerProcess(JavaProcess jp) {
gameProcesses.add(jp);
}
public void stopAllProcesses() {
for(JavaProcess jp : gameProcesses) {
jp.stop();
}
gameProcesses.clear();
}
public void onProcessStopped(JavaProcess p) {
gameProcesses.remove(p);
}
}

View File

@@ -0,0 +1,92 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import org.jackhuang.hellominecraft.HMCLog;
/**
*
* @author hyh
*/
public class ProcessThread extends Thread {
JavaProcess p;
boolean readError = false, enableReading = true;
public final EventHandler<String> printlnEvent = new EventHandler<String>(this);
public final EventHandler<JavaProcess> stopEvent = new EventHandler<JavaProcess>(this);
public ProcessThread(JavaProcess process, boolean readError, boolean enableReading) {
p = process;
this.readError = readError;
this.enableReading = enableReading;
}
public JavaProcess getProcess() {
return p;
}
@Override
public void run() {
InputStream in = null;
BufferedReader br = null;
if (enableReading) {
in = readError ? p.getRawProcess().getErrorStream() : p.getRawProcess().getInputStream();
}
try {
if (enableReading) {
try {
br = new BufferedReader(new InputStreamReader(in, System.getProperty("sun.jnu.encoding", "UTF-8")));
} catch (UnsupportedEncodingException ex) {
HMCLog.warn("Unsupported encoding: " + System.getProperty("sun.jnu.encoding", "UTF-8"), ex);
br = new BufferedReader(new InputStreamReader(in));
}
}
String line;
while (p.isRunning()) {
if (enableReading) {
while ((line = br.readLine()) != null) {
printlnEvent.execute(line);
if (readError) {
System.err.println(line);
p.getStdErrLines().add(line);
} else {
System.out.println(line);
p.getStdOutLines().add(line);
}
}
} else {
try {
Thread.sleep(1);
} catch (Exception e) {
}
}
}
if (enableReading) {
while ((line = br.readLine()) != null) {
printlnEvent.execute(line);
if (readError) {
System.err.println(line);
p.getStdErrLines().add(line);
} else {
System.out.println(line);
p.getStdOutLines().add(line);
}
}
}
stopEvent.execute(p);
} catch (Exception e) {
e.printStackTrace();
}
}
private void stopped() {
}
}

View File

@@ -0,0 +1,29 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
*
* @author hyh
*/
public class ReflectUtils {
public static Set<? extends Class<?>> getClasses(Class c) {
HashSet set = new HashSet();
set.addAll(Arrays.asList(c.getInterfaces()));
while(c != Object.class) {
set.add(c);
c = c.getSuperclass();
}
return set;
}
}

View File

@@ -0,0 +1,214 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import java.awt.Dimension;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.StringTokenizer;
/**
*
* @author huang
*/
public final class StrUtils {
public static String makeCommand(List<String> cmd) {
StringBuilder cmdbuf = new StringBuilder(120);
for (int i = 0; i < cmd.size(); i++) {
if (i > 0) {
cmdbuf.append(' ');
}
String s = cmd.get(i);
if (s.indexOf(' ') >= 0 || s.indexOf('\t') >= 0) {
if (s.charAt(0) != '"') {
cmdbuf.append('"');
cmdbuf.append(s);
if (s.endsWith("\\")) {
cmdbuf.append("\\");
}
cmdbuf.append('"');
} else if (s.endsWith("\"")) {
/* The argument has already been quoted. */
cmdbuf.append(s);
} else {
/* Unmatched quote for the argument. */
throw new IllegalArgumentException();
}
} else {
cmdbuf.append(s);
}
}
String str = cmdbuf.toString();
return str;
}
public static boolean startsWith(String base, String match) {
return base != null && base.startsWith(match);
}
public static boolean startsWithOne(String[] a, String match) {
if (a == null) {
return false;
}
for (String b : a) {
if (startsWith(match, b)) {
return true;
}
}
return false;
}
public static boolean equalsOne(String base, String... a) {
for (String s : a) {
if (base.equals(s)) {
return true;
}
}
return false;
}
public static boolean containsOne(List<String> base, List<String> match) {
for (String a : base) {
for (String b : match) {
if (a.toLowerCase().contains(b.toLowerCase())) {
return true;
}
}
}
return false;
}
public static int getCharShowTime(String s, char c) {
int res = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == c) {
res++;
}
}
return res;
}
public static String formatVersion(String ver) {
if (isBlank(ver)) {
return null;
} else {
for(char ch : ver.toCharArray()) {
if((ch < '0' || ch > '9') && ch != '.') return null;
}
}
int i = getCharShowTime(ver, '.');
if (i == 1) {
return ver + ".0";
} else {
return ver;
}
}
public static String parseParams(String addBefore, Collection paramArrayOfObject, String paramString) {
return parseParams(addBefore, paramArrayOfObject.toArray(), paramString);
}
public static String parseParams(String addBefore, Object[] paramArrayOfObject, String paramString) {
if (paramArrayOfObject == null) {
return "";
}
StringBuilder localStringBuffer = new StringBuilder();
for (int i = 0; i < paramArrayOfObject.length; i++) {
Object localObject = paramArrayOfObject[i];
if (i > 0) {
localStringBuffer.append(addBefore).append(paramString);
}
if (localObject == null) {
localStringBuffer.append("null");
} else if (localObject.getClass().isArray()) {
localStringBuffer.append("[");
if ((localObject instanceof Object[])) {
Object[] arrayOfObject = (Object[]) localObject;
localStringBuffer.append(parseParams(addBefore, arrayOfObject, paramString));
} else {
for (int j = 0; j < Array.getLength(localObject); j++) {
if (j > 0) {
localStringBuffer.append(paramString);
}
localStringBuffer.append(addBefore).append(Array.get(localObject, j));
}
}
localStringBuffer.append("]");
} else {
localStringBuffer.append(addBefore).append(paramArrayOfObject[i]);
}
}
return localStringBuffer.toString();
}
public static boolean isEquals(String base, String to) {
if (base == null) {
return (to == null);
} else {
return base.equals(to);
}
}
public static Dimension parseDimension(String str) {
String[] tokenized = tokenize(str, "x,");
if (tokenized.length != 2) {
return null;
}
int i = MathUtils.parseInt(tokenized[0], -1);
int j = MathUtils.parseInt(tokenized[1], -1);
if ((i < 0) || (j < 0)) {
return null;
}
return new Dimension(i, j);
}
public static String[] tokenize(String paramString1) {
return tokenize(paramString1, " \t\n\r\f");
}
public static String[] tokenize(String paramString1, String paramString2) {
ArrayList localArrayList = new ArrayList();
StringTokenizer tokenizer = new StringTokenizer(paramString1, paramString2);
while (tokenizer.hasMoreTokens()) {
paramString2 = tokenizer.nextToken();
localArrayList.add(paramString2);
}
return (String[]) localArrayList.toArray(new String[localArrayList.size()]);
}
public static String trimExtension(String filename) {
if ((filename != null) && (filename.length() > 0)) {
int i = filename.lastIndexOf('.');
if ((i > -1) && (i < (filename.length()))) {
return filename.substring(0, i);
}
}
return filename;
}
public static boolean isBlank(String s) {
return s == null || s.trim().length() <= 0;
}
public static boolean isNotBlank(String s) {
return !isBlank(s);
}
public static String getStackTrace(Throwable t) {
StringWriter trace = new StringWriter();
PrintWriter writer = new PrintWriter(trace);
t.printStackTrace(writer);
return trace.toString();
}
}

View File

@@ -0,0 +1,90 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.Window;
import java.net.URI;
import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.table.DefaultTableModel;
import org.jackhuang.hellominecraft.HMCLog;
/**
*
* @author huang
*/
public class SwingUtils {
public static DefaultTableModel makeDefaultTableModel(String[] titleA, final Class[] typesA, final boolean[] canEditA) {
return new javax.swing.table.DefaultTableModel(
new Object[][]{},
titleA) {
Class[] types = typesA;
boolean[] canEdit = canEditA;
@Override
public Class getColumnClass(int columnIndex) {
return types[columnIndex];
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return canEdit[columnIndex];
}
};
}
public static void openLink(URI link) {
try {
java.awt.Desktop.getDesktop().browse(link);
} catch (Throwable e) {
HMCLog.warn("Failed to open link: " + link, e);
}
}
public static void moveEnd(JTextArea tf) {
int position = tf.getText().length();
tf.setCaretPosition(position);
}
public static void moveEnd(JScrollPane pane) {
JScrollBar bar = pane.getVerticalScrollBar();
bar.setValue(bar.getMaximum());
}
public static DefaultListModel getDefaultListModel(JList list) {
return (DefaultListModel)list.getModel();
}
public static void appendLast(JList list, Object element) {
getDefaultListModel(list).addElement(element);
}
public static void replaceLast(JList list, Object element) {
DefaultListModel model = getDefaultListModel(list);
model.set(model.getSize()-1, element);
}
public static void clear(JList list) {
list.setModel(new DefaultListModel());
}
public static void clearDefaultTable(JTable table) {
DefaultTableModel model = (DefaultTableModel)table.getModel();
while(model.getRowCount() > 0) {
model.removeRow(0);
}
table.updateUI();
}
}

View File

@@ -0,0 +1,54 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import java.io.OutputStream;
import javax.swing.SwingUtilities;
import javax.swing.text.JTextComponent;
import org.jackhuang.hellominecraft.HMCLog;
/**
*
* @author hyh
*/
public class TextComponentOutputStream extends OutputStream {
private JTextComponent txt;
public TextComponentOutputStream(JTextComponent paramJTextComponent) {
txt = paramJTextComponent;
}
@Override
public final void write(byte[] paramArrayOfByte) {
write(paramArrayOfByte, 0, paramArrayOfByte.length);
}
@Override
public final void write(byte[] paramArrayOfByte, int off, int len) {
append(new String(paramArrayOfByte, off, len));
}
private void append(final String newString) {
try {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
String t = txt.getText() + newString.replace("\t", " ");
txt.setText(t);
txt.setCaretPosition(t.length());
}
});
} catch (Throwable e) {
e.printStackTrace();
}
}
@Override
public final void write(int paramInt) {
append(new String(new byte[]{(byte) paramInt}));
}
}

View File

@@ -0,0 +1,68 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.utils.functions.DoneListener0;
import org.jackhuang.hellominecraft.HMCLog;
/**
*
* @author hyh
*/
public final class UpdateChecker extends Thread {
public static boolean OUT_DATED = false;
public VersionNumber base;
public String type;
public boolean continueUpdate;
public DoneListener0 dl;
public UpdateChecker(VersionNumber base, String type, boolean continueUpdate, DoneListener0 dl) {
super("UpdateChecker");
this.base = base;
this.type = type;
this.continueUpdate = continueUpdate;
this.dl = dl;
}
VersionNumber value;
@Override
public void run() {
String url = "http://huangyuhui.duapp.com/info.php?type=" + type, version;
try {
version = NetUtils.doGet(url);
} catch (Exception e) {
HMCLog.warn("Failed to get update url.", e);
return;
}
value = VersionNumber.check(version);
if (!continueUpdate) {
return;
}
process(false);
}
public void process(boolean showMessage) {
if (value == null) {
HMCLog.warn("Failed to check update...");
if(showMessage) {
MessageBox.Show(C.i18n("update.failed"));
}
} else {
if (VersionNumber.isOlder(base, value)) {
OUT_DATED = true;
dl.onDone();
}
}
}
public VersionNumber getNewVersion() {
return value;
}
}

View File

@@ -0,0 +1,179 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import com.google.gson.GsonBuilder;
import com.sun.management.OperatingSystemMXBean;
import java.awt.Desktop;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.datatransfer.StringSelection;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLDecoder;
import java.util.Random;
import javax.swing.ImageIcon;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.HMCLog;
/**
* @author hyh
*/
public final class Utils {
private static final GsonBuilder gsonBuilder = new GsonBuilder().setPrettyPrinting();
public static GsonBuilder getDefaultGsonBuilder() {
return gsonBuilder;
}
public static String[] getURL() {
URL[] urls = ((URLClassLoader) Utils.class.getClassLoader()).getURLs();
String[] urlStrings = new String[urls.length];
for (int i = 0; i < urlStrings.length; i++) {
try {
urlStrings[i] = URLDecoder.decode(urls[i].getPath(), "UTF-8");
} catch (UnsupportedEncodingException ex) {
HMCLog.warn("Unsupported UTF-8 encoding", ex);
}
}
return urlStrings;
}
public static void addDir(String s) throws IOException {
try {
Field field = ClassLoader.class.getDeclaredField("usr_paths");
field.setAccessible(true);
String[] paths = (String[]) field.get(null);
for (int i = 0; i < paths.length; i++) {
if (s.equals(paths[i])) {
return;
}
}
String[] tmp = new String[paths.length + 1];
System.arraycopy(paths, 0, tmp, 0, paths.length);
tmp[paths.length] = s;
field.set(null, tmp);
} catch (IllegalAccessException e) {
throw new IOException("Failed to get permissions to set library path");
} catch (NoSuchFieldException e) {
throw new IOException("Failed to get field handle to set library path");
}
}
public static int getSuggestedMemorySize() {
try {
OperatingSystemMXBean osmb = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
int memory = (int)(osmb.getTotalPhysicalMemorySize() / 1024 / 1024) / 4;
memory = Math.round((float)memory/128.0f)*128;
return memory;
} catch(Throwable t) {
HMCLog.warn("Failed to get total memory size, use 1024MB.", t);
return 1024;
}
}
public static void setClipborad(String text) {
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(text), null);
}
public static boolean openLink(String url) {
try {
Desktop.getDesktop().browse(new URI(url));
return true;
} catch (Exception ex) {
HMCLog.warn("Failed to open link:" + url, ex);
return false;
}
}
public static void openFolder(File f) {
try {
f.mkdirs();
java.awt.Desktop.getDesktop().open(f);
} catch (Exception ex) {
MessageBox.Show(C.i18n("message.cannot_open_explorer") + ex.getMessage());
HMCLog.warn("Failed to open folder:" + f, ex);
}
}
public static ImageIcon scaleImage(ImageIcon i, int x, int y) {
return new ImageIcon(i.getImage().getScaledInstance(x, y, Image.SCALE_SMOOTH));
}
public static ImageIcon searchBackgroundImage(ImageIcon background, String bgpath, int width, int height) {
Random r = new Random();
boolean loaded = false;
// bgpath
if (StrUtils.isNotBlank(bgpath) && !loaded) {
String[] backgroundPath = bgpath.split(";");
if(backgroundPath.length > 0) {
int index = r.nextInt(backgroundPath.length);
background = new ImageIcon(Toolkit.getDefaultToolkit().getImage(backgroundPath[index]).getScaledInstance(width, height, Image.SCALE_DEFAULT));
HMCLog.log("Prepared background image in bgpath.");
loaded = true;
}
}
// bgskin
if (!loaded) {
File backgroundImageFile = new File("bg");
if (backgroundImageFile.exists() && backgroundImageFile.isDirectory()) {
String[] backgroundPath = backgroundImageFile.list();
if(backgroundPath.length > 0) {
int index = r.nextInt(backgroundPath.length);
background = new ImageIcon(Toolkit.getDefaultToolkit().getImage("bg" + File.separator + backgroundPath[index]).getScaledInstance(width, height, Image.SCALE_DEFAULT));
HMCLog.log("Prepared background image in bgskin folder.");
loaded = true;
}
}
}
// background.png
if (!loaded) {
File backgroundImageFile = new File("background.png");
if (backgroundImageFile.exists()) {
loaded = true;
background = new ImageIcon(Toolkit.getDefaultToolkit().getImage(backgroundImageFile.getAbsolutePath()).getScaledInstance(width, height, Image.SCALE_DEFAULT));
HMCLog.log("Prepared background image in background.png.");
}
}
// background.jpg
if (!loaded) {
File backgroundImageFile = new File("background.jpg");
if (backgroundImageFile.exists()) {
loaded = true;
background = new ImageIcon(Toolkit.getDefaultToolkit().getImage(backgroundImageFile.getAbsolutePath()).getScaledInstance(width, height, Image.SCALE_DEFAULT));
HMCLog.log("Prepared background image in background.jpg.");
}
}
return background;
}
/**
* In order to fight against the permission manager.
*/
public static void shutdownForcely() {
try {
Class z = Class.forName("java.lang.Shutdown");
Method exit = z.getDeclaredMethod("exit", int.class);
exit.setAccessible(true);
exit.invoke(z, 0);
} catch(Exception e) {
MessageBox.Show(C.i18n("launcher.exit_failed"));
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,22 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
/**
*
* @author hyh
*/
public final class Validate {
public static <T> T notNull(T o) {
if(o == null) {
throw new IllegalArgumentException("The validated object is null");
}
return o;
}
}

View File

@@ -0,0 +1,67 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils;
import org.jackhuang.hellominecraft.HMCLog;
/**
*
* @author hyh
*/
public final class VersionNumber implements Comparable<VersionNumber> {
public byte firstVer, secondVer, thirdVer;
public VersionNumber(byte a, byte b, byte c) {
firstVer = a; secondVer = b; thirdVer = c;
}
public static VersionNumber check(String data) {
while (!data.isEmpty() && ((data.charAt(0) < '0' || data.charAt(0) > '9') && data.charAt(0) != '.')) {
data = data.substring(1);
}
if (data.isEmpty()) {
return null;
}
VersionNumber ur = null;
String[] ver = data.split("\\.");
if (ver.length == 3) {
byte v1, v2, v3;
try {
v1 = Byte.parseByte(ver[0]);
v2 = Byte.parseByte(ver[1]);
v3 = Byte.parseByte(ver[2]);
ur = new VersionNumber(v1, v2, v3);
return ur;
} catch (Exception e) {
HMCLog.warn("Failed to parse the version", e);
}
}
return null;
}
public static boolean isOlder(VersionNumber a, VersionNumber b) {
if (a.firstVer < b.firstVer) {
return true;
} else if (a.firstVer == b.firstVer) {
if (a.secondVer < b.secondVer) {
return true;
} else if (a.secondVer == b.secondVer) {
if (a.thirdVer < b.thirdVer) {
return true;
}
}
}
return false;
}
@Override
public int compareTo(VersionNumber o) {
if(isOlder(this, o)) return -1;
else if(isOlder(o, this)) return 1;
else return 0;
}
}

View File

@@ -0,0 +1,14 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils.functions;
/**
*
* @author huangyuhui
*/
public interface BiFunction<A, B, C> {
C apply(A a, B b);
}

View File

@@ -0,0 +1,14 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils.functions;
/**
*
* @author huangyuhui
*/
public interface Consumer<T> {
void accept(T t);
}

View File

@@ -0,0 +1,15 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils.functions;
/**
*
* @author hyh
*/
public interface DoneListener0 {
void onDone();
}

View File

@@ -0,0 +1,14 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils.functions;
/**
*
* @author hyh
*/
public interface DoneListener0Return<T> {
T onDone();
}

View File

@@ -0,0 +1,12 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils.functions;
/**
* @author hyh
*/
public interface DoneListener2<V, V2> {
void onDone(V value, V2 value2);
}

View File

@@ -0,0 +1,15 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils.functions;
/**
*
* @author hyh
*/
public interface DoneListener3<V1, V2, V3> {
void onDone(V1 v1, V2 v2, V3 v3);
}

View File

@@ -0,0 +1,19 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils.functions;
/**
*
* @author hyh
*/
public class FalseDoneListener implements DoneListener0Return<Boolean> {
@Override
public Boolean onDone() {
return Boolean.FALSE;
}
}

View File

@@ -0,0 +1,14 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils.functions;
/**
*
* @author huangyuhui
*/
public interface Function<T, R> {
R apply(T t);
}

View File

@@ -0,0 +1,14 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils.functions;
/**
*
* @author hyh
*/
public interface Predicate<T> {
boolean apply(T t);
}

View File

@@ -0,0 +1,23 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils.functions;
/**
*
* @author hyh
*/
public class TrueDoneListener implements DoneListener0Return<Boolean> {
public static final TrueDoneListener instance = new TrueDoneListener();
private TrueDoneListener(){}
@Override
public Boolean onDone() {
return Boolean.TRUE;
}
}

View File

@@ -0,0 +1,39 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils.tinystream;
import org.jackhuang.hellominecraft.utils.functions.Consumer;
import org.jackhuang.hellominecraft.utils.functions.Predicate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
*
* @author hyh
*/
public final class CollectionUtils {
public static <T> void forEach(Collection<T> coll, Consumer<T> p) {
for(T t : coll) p.accept(t);
}
public static <T> Collection<T> sortOut(Collection<T> coll, Predicate<T> p) {
ArrayList<T> newColl = new ArrayList<>();
forEach(coll, t -> { if(p.apply(t)) newColl.add(t); });
return newColl;
}
public static <T> boolean removeIf(Collection<T> coll, Predicate<T> p) {
boolean removed = false;
final Iterator<T> each = coll.iterator();
while (each.hasNext())
if (p.apply(each.next())) {
each.remove();
removed = true;
}
return removed;
}
}

View File

@@ -0,0 +1,91 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.utils.tinystream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import org.jackhuang.hellominecraft.utils.functions.BiFunction;
import org.jackhuang.hellominecraft.utils.functions.Consumer;
import org.jackhuang.hellominecraft.utils.functions.Function;
import org.jackhuang.hellominecraft.utils.functions.Predicate;
/**
*
* @author huangyuhui
*/
public class Stream<T> {
List<T> internal;
public Stream(Collection<T> internal) {
this.internal = new ArrayList<>(internal);
}
protected Stream() {
}
protected static <T> Stream<T> of(List<T> a) {
Stream<T> b = new Stream<>();
b.internal = a;
return b;
}
public Stream<T> forEach(Consumer<? super T> p) {
for (T t : internal) p.accept(t);
return this;
}
public Stream<T> filter(Predicate<? super T> p) {
ArrayList<T> newList = new ArrayList<>();
forEach(a -> {
if (p.apply(a)) newList.add(a);
});
internal = newList;
return this;
}
public int count() {
return internal.size();
}
public Stream<T> distinct() {
internal = new ArrayList<>(new HashSet<>(internal));
return this;
}
public <R> Stream<R> map(Function<? super T, ? extends R> func) {
List<R> newList = new ArrayList<>(internal.size());
forEach(a -> newList.add(func.apply(a)));
return of(newList);
}
public Stream<T> sorted(Comparator<? super T> c) {
Collections.sort(internal, c);
return this;
}
public <U> U reduce(U identity, BiFunction<U, T, U> accumulator) {
for (T t : internal) identity = accumulator.apply(identity, t);
return identity;
}
public boolean anyMatch(Predicate<? super T> p) {
return map(t -> p.apply(t)).reduce(false, (accumulator, _item) -> accumulator | _item);
}
public boolean allMatch(Predicate<? super T> p) {
return map(t -> p.apply(t)).reduce(true, (accumulator, _item) -> accumulator & _item);
}
public T findFirst() {
return internal.isEmpty() ? null : internal.get(0);
}
}

View File

@@ -0,0 +1,15 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.version;
/**
*
* @author hyh
*/
public class MinecraftRemoteLatestVersion {
public String snapshot, release;
}

View File

@@ -0,0 +1,15 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.version;
/**
*
* @author hyh
*/
public class MinecraftRemoteVersion {
public String id, time, releaseTime, type;
}

View File

@@ -0,0 +1,23 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.version;
import java.util.ArrayList;
import org.jackhuang.hellominecraft.C;
/**
*
* @author hyh
*/
public class MinecraftRemoteVersions {
public ArrayList<MinecraftRemoteVersion> versions;
public MinecraftRemoteLatestVersion latest;
public static MinecraftRemoteVersions fromJson(String s) {
return C.gson.fromJson(s, MinecraftRemoteVersions.class);
}
}

View File

@@ -0,0 +1,87 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.views;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
public abstract class AbstractFilter
implements BufferedImageOp
{
public abstract BufferedImage filter(BufferedImage paramBufferedImage1, BufferedImage paramBufferedImage2);
public Rectangle2D getBounds2D(BufferedImage src)
{
return new Rectangle(0, 0, src.getWidth(), src.getHeight());
}
public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM)
{
if (destCM == null) {
destCM = src.getColorModel();
}
return new BufferedImage(destCM, destCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight()), destCM.isAlphaPremultiplied(), null);
}
public Point2D getPoint2D(Point2D srcPt, Point2D dstPt)
{
return (Point2D)srcPt.clone();
}
public RenderingHints getRenderingHints()
{
return null;
}
protected int[] getPixels(BufferedImage img, int x, int y, int w, int h, int[] pixels)
{
if ((w == 0) || (h == 0)) {
return new int[0];
}
if (pixels == null)
pixels = new int[w * h];
else if (pixels.length < w * h) {
throw new IllegalArgumentException("pixels array must have a length >= w*h");
}
int imageType = img.getType();
if ((imageType == 2) || (imageType == 1))
{
Raster raster = img.getRaster();
return (int[])(int[])raster.getDataElements(x, y, w, h, pixels);
}
return img.getRGB(x, y, w, h, pixels, 0, w);
}
protected void setPixels(BufferedImage img, int x, int y, int w, int h, int[] pixels)
{
if ((pixels == null) || (w == 0) || (h == 0))
return;
if (pixels.length < w * h) {
throw new IllegalArgumentException("pixels array must have a length >= w*h");
}
int imageType = img.getType();
if ((imageType == 2) || (imageType == 1))
{
WritableRaster raster = img.getRaster();
raster.setDataElements(x, y, w, h, pixels);
}
else {
img.setRGB(x, y, w, h, pixels, 0, w);
}
}
}

View File

@@ -0,0 +1,48 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.views;
import java.awt.Color;
/**
*
* @author hyh
*/
public class BasicColors {
private static Color getWebColor(String c){
return new Color(
Integer.parseInt(c.substring(0,2),16),
Integer.parseInt(c.substring(2,4),16),
Integer.parseInt(c.substring(4,6),16)
);
}
public static final Color COLOR_RED = new Color(229, 0, 0);
public static final Color COLOR_RED_DARKER = new Color(157, 41, 51);
public static final Color COLOR_GREEN = new Color(90, 184, 96);
public static final Color COLOR_BLUE = new Color(16, 108, 163);
public static final Color COLOR_BLUE_DARKER = new Color(12, 94, 145);
public static final Color COLOR_WHITE_TEXT = new Color(254, 254, 254);
public static final Color COLOR_CENTRAL_BACK = new Color(25, 30, 34, 160);
public static final Color bgcolors[] = new Color[] {
COLOR_BLUE,
getWebColor("1ABC9C"),
getWebColor("9B59B6"),
getWebColor("34495E"),
getWebColor("E67E22"),
getWebColor("E74C3C")
};
public static final Color bgcolors_darker[] = new Color[] {
COLOR_BLUE_DARKER,
getWebColor("16A085"),
getWebColor("8E44AD"),
getWebColor("2C3E50"),
getWebColor("D35400"),
getWebColor("C0392B")
};
}

View File

@@ -0,0 +1,75 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.views;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Component;
import java.awt.Composite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import javax.swing.border.AbstractBorder;
public class DropShadowBorder extends AbstractBorder {
private Color color;
private int thickness = 1;
private Insets insets = null;
RenderingHints hints;
public DropShadowBorder(Color color) {
this(color, 3);
}
public DropShadowBorder(Color color, int thickness) {
this.thickness = thickness;
this.color = color;
this.hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
this.insets = new Insets(thickness * 4, thickness * 4, thickness * 4, thickness * 4);
}
public void setColor(Color c) {
color = c;
}
public Insets getBorderInsets(Component c) {
return this.insets;
}
@Override
public Insets getBorderInsets(Component c, Insets insets) {
return getBorderInsets(c);
}
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
BufferedImage shadow = new BufferedImage(width, height, 2);
Graphics2D g2 = shadow.createGraphics();
g2.setRenderingHints(this.hints);
Composite oldComposite = g2.getComposite();
AlphaComposite composite = AlphaComposite.getInstance(1, 0.0F);
g2.setComposite(composite);
g2.setColor(new Color(0, 0, 0, 0));
g2.fillRect(0, 0, width, height);
g2.setComposite(oldComposite);
g2.setColor(this.color);
int border = (int) (this.thickness * 4);
g2.fillRect(border, border + border / 6, width - border * 2, height - border * 2);
g2.dispose();
FastBlurFilter blur = new FastBlurFilter(this.thickness);
shadow = blur.filter(shadow, null);
shadow = blur.filter(shadow, null);
shadow = blur.filter(shadow, null);
shadow = blur.filter(shadow, null);
g.drawImage(shadow, x, y, width, height, null);
}
}

View File

@@ -0,0 +1,132 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.views;
import java.awt.image.BufferedImage;
public class FastBlurFilter extends AbstractFilter {
private final int radius;
public FastBlurFilter() {
this(3);
}
public FastBlurFilter(int radius) {
if (radius < 1) {
radius = 1;
}
this.radius = radius;
}
public int getRadius() {
return this.radius;
}
public BufferedImage filter(BufferedImage src, BufferedImage dst) {
int width = src.getWidth();
int height = src.getHeight();
if (dst == null) {
dst = createCompatibleDestImage(src, null);
}
int[] srcPixels = new int[width * height];
int[] dstPixels = new int[width * height];
getPixels(src, 0, 0, width, height, srcPixels);
blur(srcPixels, dstPixels, width, height, this.radius);
blur(dstPixels, srcPixels, height, width, this.radius);
setPixels(dst, 0, 0, width, height, srcPixels);
return dst;
}
static void blur(int[] srcPixels, int[] dstPixels, int width, int height, int radius) {
int windowSize = radius * 2 + 1;
int radiusPlusOne = radius + 1;
int srcIndex = 0;
int[] sumLookupTable = new int[256 * windowSize];
for (int i = 0; i < sumLookupTable.length; i++) {
sumLookupTable[i] = (i / windowSize);
}
int[] indexLookupTable = new int[radiusPlusOne];
if (radius < width) {
for (int i = 0; i < indexLookupTable.length; i++) {
indexLookupTable[i] = i;
}
} else {
for (int i = 0; i < width; i++) {
indexLookupTable[i] = i;
}
for (int i = width; i < indexLookupTable.length; i++) {
indexLookupTable[i] = (width - 1);
}
}
for (int y = 0; y < height; y++) {
int sumBlue;
int sumGreen;
int sumRed;
int sumAlpha = sumRed = sumGreen = sumBlue = 0;
int dstIndex = y;
int pixel = srcPixels[srcIndex];
sumAlpha += radiusPlusOne * (pixel >> 24 & 0xFF);
sumRed += radiusPlusOne * (pixel >> 16 & 0xFF);
sumGreen += radiusPlusOne * (pixel >> 8 & 0xFF);
sumBlue += radiusPlusOne * (pixel & 0xFF);
for (int i = 1; i <= radius; i++) {
pixel = srcPixels[(srcIndex + indexLookupTable[i])];
sumAlpha += (pixel >> 24 & 0xFF);
sumRed += (pixel >> 16 & 0xFF);
sumGreen += (pixel >> 8 & 0xFF);
sumBlue += (pixel & 0xFF);
}
for (int x = 0; x < width; x++) {
dstPixels[dstIndex] = (sumLookupTable[sumAlpha] << 24 | sumLookupTable[sumRed] << 16 | sumLookupTable[sumGreen] << 8 | sumLookupTable[sumBlue]);
dstIndex += height;
int nextPixelIndex = x + radiusPlusOne;
if (nextPixelIndex >= width) {
nextPixelIndex = width - 1;
}
int previousPixelIndex = x - radius;
if (previousPixelIndex < 0) {
previousPixelIndex = 0;
}
int nextPixel = srcPixels[(srcIndex + nextPixelIndex)];
int previousPixel = srcPixels[(srcIndex + previousPixelIndex)];
sumAlpha += (nextPixel >> 24 & 0xFF);
sumAlpha -= (previousPixel >> 24 & 0xFF);
sumRed += (nextPixel >> 16 & 0xFF);
sumRed -= (previousPixel >> 16 & 0xFF);
sumGreen += (nextPixel >> 8 & 0xFF);
sumGreen -= (previousPixel >> 8 & 0xFF);
sumBlue += (nextPixel & 0xFF);
sumBlue -= (previousPixel & 0xFF);
}
srcIndex += width;
}
}
}

View File

@@ -0,0 +1,168 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.3" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
<Properties>
<Property name="defaultCloseOperation" type="int" value="2"/>
<Property name="title" type="java.lang.String" value="Log"/>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
</SyntheticProperties>
<Events>
<EventHandler event="windowClosed" listener="java.awt.event.WindowListener" parameters="java.awt.event.WindowEvent" handler="formWindowClosed"/>
</Events>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane1" max="32767" attributes="0"/>
<Group type="102" alignment="1" attributes="0">
<Component id="btnTieBa" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnMCBBS" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnMCF" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="btnTerminateGame" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnCopy" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnClear" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnClose" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="lblCrash" alignment="0" pref="639" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="lblCrash" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="375" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="btnClear" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnClose" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnCopy" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnMCBBS" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnTieBa" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnMCF" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnTerminateGame" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextArea" name="txtLog">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="columns" type="int" value="20"/>
<Property name="rows" type="int" value="5"/>
</Properties>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JButton" name="btnClear">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/launcher/I18N.properties" key="ui.button.clear" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnClearActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnClose">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/launcher/I18N.properties" key="ui.button.close" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnCloseActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnCopy">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/launcher/I18N.properties" key="ui.button.copy" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnCopyActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="lblCrash">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/launcher/I18N.properties" key="ui.label.crashing" replaceFormat="C.I18N.getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="btnMCBBS">
<Properties>
<Property name="text" type="java.lang.String" value="MCBBS"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnMCBBSActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnTieBa">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/launcher/I18N.properties" key="logwindow.tieba" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnTieBaActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnMCF">
<Properties>
<Property name="text" type="java.lang.String" value="Minecraft Forum"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnMCFActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnTerminateGame">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/jackhuang/hellominecraft/launcher/I18N.properties" key="logwindow.terminate_game" replaceFormat="java.util.ResourceBundle.getBundle(&quot;{bundleNameSlashes}&quot;).getString(&quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnTerminateGameActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Form>

View File

@@ -0,0 +1,286 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.jackhuang.hellominecraft.views;
import org.jackhuang.hellominecraft.C;
import org.jackhuang.hellominecraft.utils.functions.DoneListener0;
import org.jackhuang.hellominecraft.utils.functions.DoneListener0Return;
import org.jackhuang.hellominecraft.utils.DoubleOutputStream;
import org.jackhuang.hellominecraft.utils.LauncherPrintStream;
import org.jackhuang.hellominecraft.utils.StrUtils;
import org.jackhuang.hellominecraft.utils.SwingUtils;
import org.jackhuang.hellominecraft.utils.TextComponentOutputStream;
import org.jackhuang.hellominecraft.utils.Utils;
/**
*
* @author hyh
*/
public class LogWindow extends javax.swing.JFrame {
boolean movingEnd;
DoneListener0Return<Boolean> listener;
DoneListener0 terminateGameListener;
/**
* Creates new form LogWindow
*/
public LogWindow() {
initComponents();
movingEnd = true;
setLocationRelativeTo(null);
TextComponentOutputStream tc = new TextComponentOutputStream(txtLog);
DoubleOutputStream out = new DoubleOutputStream(tc, System.out);
System.setOut(new LauncherPrintStream(out));
DoubleOutputStream err = new DoubleOutputStream(tc, System.err);
System.setErr(new LauncherPrintStream(err));
}
public static LogWindow instance = new LogWindow();
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
txtLog = new javax.swing.JTextArea();
btnClear = new javax.swing.JButton();
btnClose = new javax.swing.JButton();
btnCopy = new javax.swing.JButton();
lblCrash = new javax.swing.JLabel();
btnMCBBS = new javax.swing.JButton();
btnTieBa = new javax.swing.JButton();
btnMCF = new javax.swing.JButton();
btnTerminateGame = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setTitle("Log");
addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosed(java.awt.event.WindowEvent evt) {
formWindowClosed(evt);
}
});
txtLog.setEditable(false);
txtLog.setColumns(20);
txtLog.setRows(5);
jScrollPane1.setViewportView(txtLog);
java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("org/jackhuang/hellominecraft/launcher/I18N"); // NOI18N
btnClear.setText(bundle.getString("ui.button.clear")); // NOI18N
btnClear.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnClearActionPerformed(evt);
}
});
btnClose.setText(bundle.getString("ui.button.close")); // NOI18N
btnClose.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnCloseActionPerformed(evt);
}
});
btnCopy.setText(bundle.getString("ui.button.copy")); // NOI18N
btnCopy.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnCopyActionPerformed(evt);
}
});
lblCrash.setText(C.I18N.getString("ui.label.crashing")); // NOI18N
btnMCBBS.setText("MCBBS");
btnMCBBS.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnMCBBSActionPerformed(evt);
}
});
btnTieBa.setText(bundle.getString("logwindow.tieba")); // NOI18N
btnTieBa.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnTieBaActionPerformed(evt);
}
});
btnMCF.setText("Minecraft Forum");
btnMCF.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnMCFActionPerformed(evt);
}
});
btnTerminateGame.setText(bundle.getString("logwindow.terminate_game")); // NOI18N
btnTerminateGame.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnTerminateGameActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(btnTieBa)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnMCBBS)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnMCF)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(btnTerminateGame)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCopy)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnClear)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnClose))
.addComponent(lblCrash, javax.swing.GroupLayout.DEFAULT_SIZE, 639, Short.MAX_VALUE))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(lblCrash, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 375, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnClear)
.addComponent(btnClose)
.addComponent(btnCopy)
.addComponent(btnMCBBS)
.addComponent(btnTieBa)
.addComponent(btnMCF)
.addComponent(btnTerminateGame))
.addContainerGap())
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void btnCloseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCloseActionPerformed
this.dispose();
}//GEN-LAST:event_btnCloseActionPerformed
private void btnClearActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnClearActionPerformed
this.txtLog.setText("");
}//GEN-LAST:event_btnClearActionPerformed
private void formWindowClosed(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosed
if(listener != null && listener.onDone()) Utils.shutdownForcely();
}//GEN-LAST:event_formWindowClosed
private void btnCopyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCopyActionPerformed
Utils.setClipborad(this.txtLog.getText());
}//GEN-LAST:event_btnCopyActionPerformed
private void btnMCBBSActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnMCBBSActionPerformed
Utils.openLink(C.URL_PUBLISH);
}//GEN-LAST:event_btnMCBBSActionPerformed
private void btnTieBaActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnTieBaActionPerformed
Utils.openLink(C.URL_TIEBA);
}//GEN-LAST:event_btnTieBaActionPerformed
private void btnMCFActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnMCFActionPerformed
Utils.openLink(C.URL_MINECRAFTFORUM);
}//GEN-LAST:event_btnMCFActionPerformed
private void btnTerminateGameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnTerminateGameActionPerformed
if(terminateGameListener != null)
terminateGameListener.onDone();
}//GEN-LAST:event_btnTerminateGameActionPerformed
public void log(String status) {
String text = txtLog.getText();
text += status + System.getProperty("line.separator");
txtLog.setText(text);
if(movingEnd) {
int position = text.length();
txtLog.setCaretPosition(position);
}
}
public void log(String status, Throwable t) {
log(status);
log(StrUtils.getStackTrace(t));
}
public void setExit(DoneListener0Return<Boolean> exit) {
this.listener = exit;
}
public void setTerminateGame(DoneListener0 l) {
this.terminateGameListener = l;
}
public void clean() {
txtLog.setText("");
}
public boolean getMovingEnd() {
return movingEnd;
}
public void setMovingEnd(boolean b) {
movingEnd = b;
}
@Override
public void setVisible(boolean b) {
lblCrash.setVisible(false);
btnMCBBS.setVisible(false);
btnTieBa.setVisible(false);
btnMCF.setVisible(false);
super.setVisible(b);
}
public void showAsCrashWindow(boolean out_date) {
if(out_date) {
lblCrash.setVisible(false);
btnMCBBS.setVisible(false);
btnTieBa.setVisible(false);
btnMCF.setVisible(false);
lblCrash.setText(C.i18n("ui.label.crashing_out_dated"));
} else {
lblCrash.setVisible(true);
btnMCBBS.setVisible(true);
btnTieBa.setVisible(true);
btnMCF.setVisible(true);
lblCrash.setText(C.i18n("ui.label.crashing"));
}
super.setVisible(true);
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnClear;
private javax.swing.JButton btnClose;
private javax.swing.JButton btnCopy;
private javax.swing.JButton btnMCBBS;
private javax.swing.JButton btnMCF;
private javax.swing.JButton btnTerminateGame;
private javax.swing.JButton btnTieBa;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JLabel lblCrash;
private javax.swing.JTextArea txtLog;
// End of variables declaration//GEN-END:variables
}

Some files were not shown because too many files have changed in this diff Show More