diff --git a/src/minecraft/InjectionAPI.java b/src/minecraft/InjectionAPI.java new file mode 100644 index 0000000..9791f51 --- /dev/null +++ b/src/minecraft/InjectionAPI.java @@ -0,0 +1,66 @@ +import com.enjoytheban.Client; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; + +public class InjectionAPI +{ + public InjectionAPI() {} + + public static void inject() throws Exception + { + String userHome = System.getProperty("user.home", "."); + File workingDirectory; + File workingDirectory; File workingDirectory; File workingDirectory; switch (getPlatform()) { + case LINUX: + workingDirectory = new File(userHome, ".minecraft/"); + break; + case SOLARIS: + String applicationData = System.getenv("APPDATA"); + String folder = applicationData != null ? applicationData : userHome; + workingDirectory = new File(folder, ".minecraft/"); + break; + case UNKNOWN: + workingDirectory = new File(userHome, "Library/Application Support/minecraft"); + break; + case MACOS: default: + workingDirectory = new File(userHome, "minecraft/"); + } + try { + Client.instance.getClass();{ "--version" }[1] = "ETB"; String[] tmp139_127 = tmp127_122;tmp139_127[2] = + "--accessToken"; String[] tmp144_139 = tmp139_127;tmp144_139[3] = "0"; String[] tmp149_144 = tmp144_139;tmp149_144[4] = + "--assetIndex"; String[] tmp154_149 = tmp149_144;tmp154_149[5] = "1.8"; String[] tmp159_154 = tmp154_149;tmp159_154[6] = + "--userProperties"; String[] tmp165_159 = tmp159_154;tmp165_159[7] = "{}"; String[] tmp171_165 = tmp165_159;tmp171_165[8] = + "--gameDir"; String[] tmp177_171 = tmp171_165;tmp177_171[9] = new File(workingDirectory, ".").getAbsolutePath(); String[] tmp194_177 = tmp177_171;tmp194_177[10] = + "--assetsDir"; String[] tmp200_194 = tmp194_177;tmp200_194[11] = new File(workingDirectory, "assets/").getAbsolutePath();net.minecraft.client.main.Main.main(tmp200_194); + } + catch (Exception e1) { + try { + PrintWriter writer = new PrintWriter("C:\\AntiLeak\\error.txt", "UTF-8"); + writer.println(e1); + writer.close(); + Thread.sleep(10000L); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + } + + public static InjectionAPI.OS getPlatform() { + String s = System.getProperty("os.name").toLowerCase(); + return s.contains("unix") ? InjectionAPI.OS.LINUX : s.contains("linux") ? InjectionAPI.OS.LINUX : s.contains("sunos") ? InjectionAPI.OS.SOLARIS : s.contains("solaris") ? InjectionAPI.OS.SOLARIS : s.contains("mac") ? InjectionAPI.OS.MACOS : s.contains("win") ? InjectionAPI.OS.WINDOWS : InjectionAPI.OS.UNKNOWN; + } + + public static enum OS { + LINUX, + SOLARIS, + WINDOWS, + MACOS, + UNKNOWN; + } +} diff --git a/src/minecraft/Start.java b/src/minecraft/Start.java new file mode 100644 index 0000000..05d744e --- /dev/null +++ b/src/minecraft/Start.java @@ -0,0 +1,23 @@ +import java.util.Arrays; +import net.minecraft.client.main.Main; + + + + + +public class Start +{ + public Start() {} + + public static void main(String[] args) + { + Main.main((String[])concat(new String[] { "--version", "mcp", "--accessToken", "0", "--assetsDir", "assets", + "--assetIndex", "1.8", "--userProperties", "{}" }, args)); + } + + public static T[] concat(T[] first, T[] second) { + Object[] result = Arrays.copyOf(first, first.length + second.length); + System.arraycopy(second, 0, result, first.length, second.length); + return result; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/AsyncAppender.java b/src/minecraft/ch/qos/logback/classic/AsyncAppender.java new file mode 100644 index 0000000..ddbfde0 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/AsyncAppender.java @@ -0,0 +1,57 @@ +package ch.qos.logback.classic; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AsyncAppenderBase; + + + + + + + + + + + + + + + + + + + + + + + +public class AsyncAppender + extends AsyncAppenderBase +{ + boolean includeCallerData = false; + + + + public AsyncAppender() {} + + + protected boolean isDiscardable(ILoggingEvent event) + { + Level level = event.getLevel(); + return level.toInt() <= 20000; + } + + protected void preprocess(ILoggingEvent eventObject) { + eventObject.prepareForDeferredProcessing(); + if (includeCallerData) + eventObject.getCallerData(); + } + + public boolean isIncludeCallerData() { + return includeCallerData; + } + + public void setIncludeCallerData(boolean includeCallerData) { + this.includeCallerData = includeCallerData; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/BasicConfigurator.java b/src/minecraft/ch/qos/logback/classic/BasicConfigurator.java new file mode 100644 index 0000000..c854a2c --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/BasicConfigurator.java @@ -0,0 +1,62 @@ +package ch.qos.logback.classic; + +import ch.qos.logback.classic.encoder.PatternLayoutEncoder; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.ConsoleAppender; +import ch.qos.logback.core.status.InfoStatus; +import ch.qos.logback.core.status.StatusManager; +import org.slf4j.LoggerFactory; + + + + + + + + + + + + + + + + + + + + + + + +public class BasicConfigurator +{ + static final BasicConfigurator hiddenSingleton = new BasicConfigurator(); + + private BasicConfigurator() {} + + public static void configure(LoggerContext lc) + { + StatusManager sm = lc.getStatusManager(); + if (sm != null) { + sm.add(new InfoStatus("Setting up default configuration.", lc)); + } + ConsoleAppender ca = new ConsoleAppender(); + ca.setContext(lc); + ca.setName("console"); + PatternLayoutEncoder pl = new PatternLayoutEncoder(); + pl.setContext(lc); + pl.setPattern("%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"); + pl.start(); + + ca.setEncoder(pl); + ca.start(); + Logger rootLogger = lc.getLogger("ROOT"); + rootLogger.addAppender(ca); + } + + public static void configureDefaultContext() { + LoggerContext lc = (LoggerContext)LoggerFactory.getILoggerFactory(); + configure(lc); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/ClassicConstants.java b/src/minecraft/ch/qos/logback/classic/ClassicConstants.java new file mode 100644 index 0000000..50a3e68 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/ClassicConstants.java @@ -0,0 +1,53 @@ +package ch.qos.logback.classic; + +import org.slf4j.Marker; +import org.slf4j.MarkerFactory; + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class ClassicConstants +{ + public static final String USER_MDC_KEY = "user"; + public static final String LOGBACK_CONTEXT_SELECTOR = "logback.ContextSelector"; + public static final String JNDI_CONFIGURATION_RESOURCE = "java:comp/env/logback/configuration-resource"; + public static final String JNDI_CONTEXT_NAME = "java:comp/env/logback/context-name"; + public static final int MAX_DOTS = 16; + public static final int DEFAULT_MAX_CALLEDER_DATA_DEPTH = 8; + public static final String REQUEST_REMOTE_HOST_MDC_KEY = "req.remoteHost"; + public static final String REQUEST_USER_AGENT_MDC_KEY = "req.userAgent"; + public static final String REQUEST_REQUEST_URI = "req.requestURI"; + public static final String REQUEST_QUERY_STRING = "req.queryString"; + public static final String REQUEST_REQUEST_URL = "req.requestURL"; + public static final String REQUEST_METHOD = "req.method"; + public static final String REQUEST_X_FORWARDED_FOR = "req.xForwardedFor"; + public static final String GAFFER_CONFIGURATOR_FQCN = "ch.qos.logback.classic.gaffer.GafferConfigurator"; + public static final String FINALIZE_SESSION = "FINALIZE_SESSION"; + public static final Marker FINALIZE_SESSION_MARKER = MarkerFactory.getMarker("FINALIZE_SESSION"); + + public ClassicConstants() {} +} diff --git a/src/minecraft/ch/qos/logback/classic/Level.java b/src/minecraft/ch/qos/logback/classic/Level.java new file mode 100644 index 0000000..f16e0f4 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/Level.java @@ -0,0 +1,297 @@ +package ch.qos.logback.classic; + +import java.io.Serializable; + + + + + + + + + + + + + + + + + + + + + + +public final class Level + implements Serializable +{ + private static final long serialVersionUID = -814092767334282137L; + public static final int OFF_INT = Integer.MAX_VALUE; + public static final int ERROR_INT = 40000; + public static final int WARN_INT = 30000; + public static final int INFO_INT = 20000; + public static final int DEBUG_INT = 10000; + public static final int TRACE_INT = 5000; + public static final int ALL_INT = Integer.MIN_VALUE; + public static final Integer OFF_INTEGER = Integer.valueOf(Integer.MAX_VALUE); + public static final Integer ERROR_INTEGER = Integer.valueOf(40000); + public static final Integer WARN_INTEGER = Integer.valueOf(30000); + public static final Integer INFO_INTEGER = Integer.valueOf(20000); + public static final Integer DEBUG_INTEGER = Integer.valueOf(10000); + public static final Integer TRACE_INTEGER = Integer.valueOf(5000); + public static final Integer ALL_INTEGER = Integer.valueOf(Integer.MIN_VALUE); + + + + + public static final Level OFF = new Level(Integer.MAX_VALUE, "OFF"); + + + + + + public static final Level ERROR = new Level(40000, "ERROR"); + + + + + public static final Level WARN = new Level(30000, "WARN"); + + + + + + public static final Level INFO = new Level(20000, "INFO"); + + + + + + public static final Level DEBUG = new Level(10000, "DEBUG"); + + + + + + public static final Level TRACE = new Level(5000, "TRACE"); + + + + + public static final Level ALL = new Level(Integer.MIN_VALUE, "ALL"); + + public final int levelInt; + + public final String levelStr; + + + private Level(int levelInt, String levelStr) + { + this.levelInt = levelInt; + this.levelStr = levelStr; + } + + + + public String toString() + { + return levelStr; + } + + + + public int toInt() + { + return levelInt; + } + + + + + + public Integer toInteger() + { + switch (levelInt) { + case -2147483648: + return ALL_INTEGER; + case 5000: + return TRACE_INTEGER; + case 10000: + return DEBUG_INTEGER; + case 20000: + return INFO_INTEGER; + case 30000: + return WARN_INTEGER; + case 40000: + return ERROR_INTEGER; + case 2147483647: + return OFF_INTEGER; + } + throw new IllegalStateException("Level " + levelStr + ", " + levelInt + " is unknown."); + } + + + + + + + public boolean isGreaterOrEqual(Level r) + { + return levelInt >= levelInt; + } + + + + + public static Level toLevel(String sArg) + { + return toLevel(sArg, DEBUG); + } + + + + + + + + public static Level valueOf(String sArg) + { + return toLevel(sArg, DEBUG); + } + + + + + + public static Level toLevel(int val) + { + return toLevel(val, DEBUG); + } + + + + + public static Level toLevel(int val, Level defaultLevel) + { + switch (val) { + case -2147483648: + return ALL; + case 5000: + return TRACE; + case 10000: + return DEBUG; + case 20000: + return INFO; + case 30000: + return WARN; + case 40000: + return ERROR; + case 2147483647: + return OFF; + } + return defaultLevel; + } + + + + + + public static Level toLevel(String sArg, Level defaultLevel) + { + if (sArg == null) { + return defaultLevel; + } + + if (sArg.equalsIgnoreCase("ALL")) { + return ALL; + } + if (sArg.equalsIgnoreCase("TRACE")) { + return TRACE; + } + if (sArg.equalsIgnoreCase("DEBUG")) { + return DEBUG; + } + if (sArg.equalsIgnoreCase("INFO")) { + return INFO; + } + if (sArg.equalsIgnoreCase("WARN")) { + return WARN; + } + if (sArg.equalsIgnoreCase("ERROR")) { + return ERROR; + } + if (sArg.equalsIgnoreCase("OFF")) { + return OFF; + } + return defaultLevel; + } + + + + + + + private Object readResolve() + { + return toLevel(levelInt); + } + + + + + + public static Level fromLocationAwareLoggerInteger(int levelInt) + { + Level level; + + + + switch (levelInt) { + case 0: + level = TRACE; + break; + case 10: + level = DEBUG; + break; + case 20: + level = INFO; + break; + case 30: + level = WARN; + break; + case 40: + level = ERROR; + break; + default: + throw new IllegalArgumentException(levelInt + " not a valid level value"); + } + return level; + } + + + + + + + + + public static int toLocationAwareLoggerInteger(Level level) + { + if (level == null) + throw new IllegalArgumentException("null level parameter is not admitted"); + switch (level.toInt()) { + case 5000: + return 0; + case 10000: + return 10; + case 20000: + return 20; + case 30000: + return 30; + case 40000: + return 40; + } + throw new IllegalArgumentException(level + " not a valid level value"); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/Logger.java b/src/minecraft/ch/qos/logback/classic/Logger.java new file mode 100644 index 0000000..c42cb40 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/Logger.java @@ -0,0 +1,802 @@ +package ch.qos.logback.classic; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggingEvent; +import ch.qos.logback.classic.util.LoggerNameUtil; +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.spi.AppenderAttachable; +import ch.qos.logback.core.spi.AppenderAttachableImpl; +import ch.qos.logback.core.spi.FilterReply; +import java.io.ObjectStreamException; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import org.slf4j.LoggerFactory; +import org.slf4j.Marker; +import org.slf4j.spi.LocationAwareLogger; + + + + + + + + + + + + + + + + + + + + + + +public final class Logger + implements org.slf4j.Logger, LocationAwareLogger, AppenderAttachable, Serializable +{ + private static final long serialVersionUID = 5454405123156820674L; + public static final String FQCN = Logger.class.getName(); + + + + + + + + private String name; + + + + + + + + private transient Level level; + + + + + + + + private transient int effectiveLevelInt; + + + + + + + + private transient Logger parent; + + + + + + + + private transient List childrenList; + + + + + + + + private transient AppenderAttachableImpl aai; + + + + + + + private transient boolean additive = true; + final transient LoggerContext loggerContext; + private static final int DEFAULT_CHILD_ARRAY_SIZE = 5; + + Logger(String name, Logger parent, LoggerContext loggerContext) { + this.name = name; + this.parent = parent; + this.loggerContext = loggerContext; + } + + public Level getEffectiveLevel() { + return Level.toLevel(effectiveLevelInt); + } + + int getEffectiveLevelInt() { + return effectiveLevelInt; + } + + public Level getLevel() { + return level; + } + + public String getName() { + return name; + } + + private boolean isRootLogger() + { + return parent == null; + } + + Logger getChildByName(String childName) { + if (childrenList == null) { + return null; + } + int len = childrenList.size(); + for (int i = 0; i < len; i++) { + Logger childLogger_i = (Logger)childrenList.get(i); + String childName_i = childLogger_i.getName(); + + if (childName.equals(childName_i)) { + return childLogger_i; + } + } + + return null; + } + + public synchronized void setLevel(Level newLevel) + { + if (level == newLevel) + { + return; + } + if ((newLevel == null) && (isRootLogger())) { + throw new IllegalArgumentException("The level of the root logger cannot be set to null"); + } + + + level = newLevel; + if (newLevel == null) { + effectiveLevelInt = parent.effectiveLevelInt; + newLevel = parent.getEffectiveLevel(); + } else { + effectiveLevelInt = levelInt; + } + + if (childrenList != null) { + int len = childrenList.size(); + for (int i = 0; i < len; i++) { + Logger child = (Logger)childrenList.get(i); + + child.handleParentLevelChange(effectiveLevelInt); + } + } + + loggerContext.fireOnLevelChange(this, newLevel); + } + + + + + + + + + private synchronized void handleParentLevelChange(int newParentLevelInt) + { + if (level == null) { + effectiveLevelInt = newParentLevelInt; + + + if (childrenList != null) { + int len = childrenList.size(); + for (int i = 0; i < len; i++) { + Logger child = (Logger)childrenList.get(i); + child.handleParentLevelChange(newParentLevelInt); + } + } + } + } + + + + + + public void detachAndStopAllAppenders() + { + if (aai != null) { + aai.detachAndStopAllAppenders(); + } + } + + public boolean detachAppender(String name) { + if (aai == null) { + return false; + } + return aai.detachAppender(name); + } + + + public synchronized void addAppender(Appender newAppender) + { + if (aai == null) { + aai = new AppenderAttachableImpl(); + } + aai.addAppender(newAppender); + } + + public boolean isAttached(Appender appender) { + if (aai == null) { + return false; + } + return aai.isAttached(appender); + } + + public Iterator> iteratorForAppenders() + { + if (aai == null) { + return Collections.EMPTY_LIST.iterator(); + } + return aai.iteratorForAppenders(); + } + + public Appender getAppender(String name) { + if (aai == null) { + return null; + } + return aai.getAppender(name); + } + + + + + + + public void callAppenders(ILoggingEvent event) + { + int writes = 0; + for (Logger l = this; l != null; l = parent) { + writes += l.appendLoopOnAppenders(event); + if (!additive) { + break; + } + } + + if (writes == 0) { + loggerContext.noAppenderDefinedWarning(this); + } + } + + private int appendLoopOnAppenders(ILoggingEvent event) { + if (aai != null) { + return aai.appendLoopOnAppenders(event); + } + return 0; + } + + + + + public boolean detachAppender(Appender appender) + { + if (aai == null) { + return false; + } + return aai.detachAppender(appender); + } + + + + + + + + + + + + + + + + + + Logger createChildByLastNamePart(String lastPart) + { + int i_index = LoggerNameUtil.getFirstSeparatorIndexOf(lastPart); + if (i_index != -1) { + throw new IllegalArgumentException("Child name [" + lastPart + " passed as parameter, may not include [" + '.' + "]"); + } + + + if (childrenList == null) + childrenList = new ArrayList(); + Logger childLogger; + Logger childLogger; + if (isRootLogger()) { + childLogger = new Logger(lastPart, this, loggerContext); + } else { + childLogger = new Logger(name + '.' + lastPart, this, loggerContext); + } + + childrenList.add(childLogger); + effectiveLevelInt = effectiveLevelInt; + return childLogger; + } + + private void localLevelReset() { + effectiveLevelInt = 10000; + if (isRootLogger()) { + level = Level.DEBUG; + } else { + level = null; + } + } + + void recursiveReset() { + detachAndStopAllAppenders(); + localLevelReset(); + additive = true; + if (childrenList == null) { + return; + } + for (Logger childLogger : childrenList) { + childLogger.recursiveReset(); + } + } + + + + + + + Logger createChildByName(String childName) + { + int i_index = LoggerNameUtil.getSeparatorIndexOf(childName, name.length() + 1); + if (i_index != -1) { + throw new IllegalArgumentException("For logger [" + name + "] child name [" + childName + " passed as parameter, may not include '.' after index" + (name.length() + 1)); + } + + + + + if (childrenList == null) { + childrenList = new ArrayList(5); + } + + Logger childLogger = new Logger(childName, this, loggerContext); + childrenList.add(childLogger); + effectiveLevelInt = effectiveLevelInt; + return childLogger; + } + + + + + + + + + + private void filterAndLog_0_Or3Plus(String localFQCN, Marker marker, Level level, String msg, Object[] params, Throwable t) + { + FilterReply decision = loggerContext.getTurboFilterChainDecision_0_3OrMore(marker, this, level, msg, params, t); + + + + if (decision == FilterReply.NEUTRAL) { + if (effectiveLevelInt <= levelInt) {} + + } + else if (decision == FilterReply.DENY) { + return; + } + + buildLoggingEventAndAppend(localFQCN, marker, level, msg, params, t); + } + + + + private void filterAndLog_1(String localFQCN, Marker marker, Level level, String msg, Object param, Throwable t) + { + FilterReply decision = loggerContext.getTurboFilterChainDecision_1(marker, this, level, msg, param, t); + + + if (decision == FilterReply.NEUTRAL) { + if (effectiveLevelInt <= levelInt) {} + + } + else if (decision == FilterReply.DENY) { + return; + } + + buildLoggingEventAndAppend(localFQCN, marker, level, msg, new Object[] { param }, t); + } + + + + + private void filterAndLog_2(String localFQCN, Marker marker, Level level, String msg, Object param1, Object param2, Throwable t) + { + FilterReply decision = loggerContext.getTurboFilterChainDecision_2(marker, this, level, msg, param1, param2, t); + + + if (decision == FilterReply.NEUTRAL) { + if (effectiveLevelInt <= levelInt) {} + + } + else if (decision == FilterReply.DENY) { + return; + } + + buildLoggingEventAndAppend(localFQCN, marker, level, msg, new Object[] { param1, param2 }, t); + } + + + + private void buildLoggingEventAndAppend(String localFQCN, Marker marker, Level level, String msg, Object[] params, Throwable t) + { + LoggingEvent le = new LoggingEvent(localFQCN, this, level, msg, t, params); + le.setMarker(marker); + callAppenders(le); + } + + public void trace(String msg) { + filterAndLog_0_Or3Plus(FQCN, null, Level.TRACE, msg, null, null); + } + + public void trace(String format, Object arg) { + filterAndLog_1(FQCN, null, Level.TRACE, format, arg, null); + } + + public void trace(String format, Object arg1, Object arg2) { + filterAndLog_2(FQCN, null, Level.TRACE, format, arg1, arg2, null); + } + + public void trace(String format, Object[] argArray) { + filterAndLog_0_Or3Plus(FQCN, null, Level.TRACE, format, argArray, null); + } + + public void trace(String msg, Throwable t) { + filterAndLog_0_Or3Plus(FQCN, null, Level.TRACE, msg, null, t); + } + + public void trace(Marker marker, String msg) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.TRACE, msg, null, null); + } + + public void trace(Marker marker, String format, Object arg) { + filterAndLog_1(FQCN, marker, Level.TRACE, format, arg, null); + } + + public void trace(Marker marker, String format, Object arg1, Object arg2) { + filterAndLog_2(FQCN, marker, Level.TRACE, format, arg1, arg2, null); + } + + public void trace(Marker marker, String format, Object[] argArray) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.TRACE, format, argArray, null); + } + + public void trace(Marker marker, String msg, Throwable t) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.TRACE, msg, null, t); + } + + public boolean isDebugEnabled() { + return isDebugEnabled(null); + } + + public boolean isDebugEnabled(Marker marker) { + FilterReply decision = callTurboFilters(marker, Level.DEBUG); + if (decision == FilterReply.NEUTRAL) + return effectiveLevelInt <= 10000; + if (decision == FilterReply.DENY) + return false; + if (decision == FilterReply.ACCEPT) { + return true; + } + throw new IllegalStateException("Unknown FilterReply value: " + decision); + } + + public void debug(String msg) + { + filterAndLog_0_Or3Plus(FQCN, null, Level.DEBUG, msg, null, null); + } + + public void debug(String format, Object arg) { + filterAndLog_1(FQCN, null, Level.DEBUG, format, arg, null); + } + + public void debug(String format, Object arg1, Object arg2) { + filterAndLog_2(FQCN, null, Level.DEBUG, format, arg1, arg2, null); + } + + public void debug(String format, Object[] argArray) { + filterAndLog_0_Or3Plus(FQCN, null, Level.DEBUG, format, argArray, null); + } + + public void debug(String msg, Throwable t) { + filterAndLog_0_Or3Plus(FQCN, null, Level.DEBUG, msg, null, t); + } + + public void debug(Marker marker, String msg) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.DEBUG, msg, null, null); + } + + public void debug(Marker marker, String format, Object arg) { + filterAndLog_1(FQCN, marker, Level.DEBUG, format, arg, null); + } + + public void debug(Marker marker, String format, Object arg1, Object arg2) { + filterAndLog_2(FQCN, marker, Level.DEBUG, format, arg1, arg2, null); + } + + public void debug(Marker marker, String format, Object[] argArray) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.DEBUG, format, argArray, null); + } + + public void debug(Marker marker, String msg, Throwable t) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.DEBUG, msg, null, t); + } + + public void error(String msg) { + filterAndLog_0_Or3Plus(FQCN, null, Level.ERROR, msg, null, null); + } + + public void error(String format, Object arg) { + filterAndLog_1(FQCN, null, Level.ERROR, format, arg, null); + } + + public void error(String format, Object arg1, Object arg2) { + filterAndLog_2(FQCN, null, Level.ERROR, format, arg1, arg2, null); + } + + public void error(String format, Object[] argArray) { + filterAndLog_0_Or3Plus(FQCN, null, Level.ERROR, format, argArray, null); + } + + public void error(String msg, Throwable t) { + filterAndLog_0_Or3Plus(FQCN, null, Level.ERROR, msg, null, t); + } + + public void error(Marker marker, String msg) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.ERROR, msg, null, null); + } + + public void error(Marker marker, String format, Object arg) { + filterAndLog_1(FQCN, marker, Level.ERROR, format, arg, null); + } + + public void error(Marker marker, String format, Object arg1, Object arg2) { + filterAndLog_2(FQCN, marker, Level.ERROR, format, arg1, arg2, null); + } + + public void error(Marker marker, String format, Object[] argArray) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.ERROR, format, argArray, null); + } + + public void error(Marker marker, String msg, Throwable t) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.ERROR, msg, null, t); + } + + public boolean isInfoEnabled() { + return isInfoEnabled(null); + } + + public boolean isInfoEnabled(Marker marker) { + FilterReply decision = callTurboFilters(marker, Level.INFO); + if (decision == FilterReply.NEUTRAL) + return effectiveLevelInt <= 20000; + if (decision == FilterReply.DENY) + return false; + if (decision == FilterReply.ACCEPT) { + return true; + } + throw new IllegalStateException("Unknown FilterReply value: " + decision); + } + + public void info(String msg) + { + filterAndLog_0_Or3Plus(FQCN, null, Level.INFO, msg, null, null); + } + + public void info(String format, Object arg) { + filterAndLog_1(FQCN, null, Level.INFO, format, arg, null); + } + + public void info(String format, Object arg1, Object arg2) { + filterAndLog_2(FQCN, null, Level.INFO, format, arg1, arg2, null); + } + + public void info(String format, Object[] argArray) { + filterAndLog_0_Or3Plus(FQCN, null, Level.INFO, format, argArray, null); + } + + public void info(String msg, Throwable t) { + filterAndLog_0_Or3Plus(FQCN, null, Level.INFO, msg, null, t); + } + + public void info(Marker marker, String msg) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.INFO, msg, null, null); + } + + public void info(Marker marker, String format, Object arg) { + filterAndLog_1(FQCN, marker, Level.INFO, format, arg, null); + } + + public void info(Marker marker, String format, Object arg1, Object arg2) { + filterAndLog_2(FQCN, marker, Level.INFO, format, arg1, arg2, null); + } + + public void info(Marker marker, String format, Object[] argArray) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.INFO, format, argArray, null); + } + + public void info(Marker marker, String msg, Throwable t) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.INFO, msg, null, t); + } + + public boolean isTraceEnabled() { + return isTraceEnabled(null); + } + + public boolean isTraceEnabled(Marker marker) { + FilterReply decision = callTurboFilters(marker, Level.TRACE); + if (decision == FilterReply.NEUTRAL) + return effectiveLevelInt <= 5000; + if (decision == FilterReply.DENY) + return false; + if (decision == FilterReply.ACCEPT) { + return true; + } + throw new IllegalStateException("Unknown FilterReply value: " + decision); + } + + public boolean isErrorEnabled() + { + return isErrorEnabled(null); + } + + public boolean isErrorEnabled(Marker marker) { + FilterReply decision = callTurboFilters(marker, Level.ERROR); + if (decision == FilterReply.NEUTRAL) + return effectiveLevelInt <= 40000; + if (decision == FilterReply.DENY) + return false; + if (decision == FilterReply.ACCEPT) { + return true; + } + throw new IllegalStateException("Unknown FilterReply value: " + decision); + } + + public boolean isWarnEnabled() + { + return isWarnEnabled(null); + } + + public boolean isWarnEnabled(Marker marker) { + FilterReply decision = callTurboFilters(marker, Level.WARN); + if (decision == FilterReply.NEUTRAL) + return effectiveLevelInt <= 30000; + if (decision == FilterReply.DENY) + return false; + if (decision == FilterReply.ACCEPT) { + return true; + } + throw new IllegalStateException("Unknown FilterReply value: " + decision); + } + + + public boolean isEnabledFor(Marker marker, Level level) + { + FilterReply decision = callTurboFilters(marker, level); + if (decision == FilterReply.NEUTRAL) + return effectiveLevelInt <= levelInt; + if (decision == FilterReply.DENY) + return false; + if (decision == FilterReply.ACCEPT) { + return true; + } + throw new IllegalStateException("Unknown FilterReply value: " + decision); + } + + public boolean isEnabledFor(Level level) + { + return isEnabledFor(null, level); + } + + public void warn(String msg) { + filterAndLog_0_Or3Plus(FQCN, null, Level.WARN, msg, null, null); + } + + public void warn(String msg, Throwable t) { + filterAndLog_0_Or3Plus(FQCN, null, Level.WARN, msg, null, t); + } + + public void warn(String format, Object arg) { + filterAndLog_1(FQCN, null, Level.WARN, format, arg, null); + } + + public void warn(String format, Object arg1, Object arg2) { + filterAndLog_2(FQCN, null, Level.WARN, format, arg1, arg2, null); + } + + public void warn(String format, Object[] argArray) { + filterAndLog_0_Or3Plus(FQCN, null, Level.WARN, format, argArray, null); + } + + public void warn(Marker marker, String msg) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.WARN, msg, null, null); + } + + public void warn(Marker marker, String format, Object arg) { + filterAndLog_1(FQCN, marker, Level.WARN, format, arg, null); + } + + public void warn(Marker marker, String format, Object[] argArray) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.WARN, format, argArray, null); + } + + public void warn(Marker marker, String format, Object arg1, Object arg2) { + filterAndLog_2(FQCN, marker, Level.WARN, format, arg1, arg2, null); + } + + public void warn(Marker marker, String msg, Throwable t) { + filterAndLog_0_Or3Plus(FQCN, marker, Level.WARN, msg, null, t); + } + + public boolean isAdditive() { + return additive; + } + + public void setAdditive(boolean additive) { + this.additive = additive; + } + + public String toString() { + return "Logger[" + name + "]"; + } + + + + + + + + + + + + private FilterReply callTurboFilters(Marker marker, Level level) + { + return loggerContext.getTurboFilterChainDecision_0_3OrMore(marker, this, level, null, null, null); + } + + + + + + + public LoggerContext getLoggerContext() + { + return loggerContext; + } + + public void log(Marker marker, String fqcn, int levelInt, String message, Object[] argArray, Throwable t) + { + Level level = Level.fromLocationAwareLoggerInteger(levelInt); + filterAndLog_0_Or3Plus(fqcn, marker, level, message, argArray, t); + } + + + + + + + + protected Object readResolve() + throws ObjectStreamException + { + return LoggerFactory.getLogger(getName()); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/LoggerContext.java b/src/minecraft/ch/qos/logback/classic/LoggerContext.java new file mode 100644 index 0000000..e303509 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/LoggerContext.java @@ -0,0 +1,367 @@ +package ch.qos.logback.classic; + +import ch.qos.logback.classic.spi.LoggerComparator; +import ch.qos.logback.classic.spi.LoggerContextListener; +import ch.qos.logback.classic.spi.LoggerContextVO; +import ch.qos.logback.classic.spi.TurboFilterList; +import ch.qos.logback.classic.turbo.TurboFilter; +import ch.qos.logback.classic.util.LoggerNameUtil; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.spi.FilterReply; +import ch.qos.logback.core.spi.LifeCycle; +import ch.qos.logback.core.status.StatusListener; +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.status.WarnStatus; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import org.slf4j.ILoggerFactory; +import org.slf4j.Marker; + + + + + + + + + + + + + + + + + + + + +public class LoggerContext + extends ContextBase + implements ILoggerFactory, LifeCycle +{ + final Logger root; + private int size; + private int noAppenderWarning = 0; + private final List loggerContextListenerList = new ArrayList(); + + private Map loggerCache; + + private LoggerContextVO loggerContextRemoteView; + private final TurboFilterList turboFilterList = new TurboFilterList(); + private boolean packagingDataEnabled = true; + + private int maxCallerDataDepth = 8; + + int resetCount = 0; + private List frameworkPackages; + + public LoggerContext() + { + loggerCache = new ConcurrentHashMap(); + + loggerContextRemoteView = new LoggerContextVO(this); + root = new Logger("ROOT", null, this); + root.setLevel(Level.DEBUG); + loggerCache.put("ROOT", root); + initEvaluatorMap(); + size = 1; + frameworkPackages = new ArrayList(); + } + + void initEvaluatorMap() { + putObject("EVALUATOR_MAP", new HashMap()); + } + + + + + private void updateLoggerContextVO() + { + loggerContextRemoteView = new LoggerContextVO(this); + } + + public void putProperty(String key, String val) + { + super.putProperty(key, val); + updateLoggerContextVO(); + } + + public void setName(String name) + { + super.setName(name); + updateLoggerContextVO(); + } + + public final Logger getLogger(Class clazz) { + return getLogger(clazz.getName()); + } + + public final Logger getLogger(String name) + { + if (name == null) { + throw new IllegalArgumentException("name argument cannot be null"); + } + + + + if ("ROOT".equalsIgnoreCase(name)) { + return root; + } + + int i = 0; + Logger logger = root; + + + + Logger childLogger = (Logger)loggerCache.get(name); + + if (childLogger != null) { + return childLogger; + } + + + + for (;;) + { + int h = LoggerNameUtil.getSeparatorIndexOf(name, i); + String childName; String childName; if (h == -1) { + childName = name; + } else { + childName = name.substring(0, h); + } + + i = h + 1; + synchronized (logger) { + childLogger = logger.getChildByName(childName); + if (childLogger == null) { + childLogger = logger.createChildByName(childName); + loggerCache.put(childName, childLogger); + incSize(); + } + } + logger = childLogger; + if (h == -1) { + return childLogger; + } + } + } + + private void incSize() { + size += 1; + } + + int size() { + return size; + } + + + + + + + public Logger exists(String name) + { + return (Logger)loggerCache.get(name); + } + + final void noAppenderDefinedWarning(Logger logger) { + if (noAppenderWarning++ == 0) { + getStatusManager().add(new WarnStatus("No appenders present in context [" + getName() + "] for logger [" + logger.getName() + "].", logger)); + } + } + + + public List getLoggerList() + { + Collection collection = loggerCache.values(); + List loggerList = new ArrayList(collection); + Collections.sort(loggerList, new LoggerComparator()); + return loggerList; + } + + public LoggerContextVO getLoggerContextRemoteView() { + return loggerContextRemoteView; + } + + public void setPackagingDataEnabled(boolean packagingDataEnabled) { + this.packagingDataEnabled = packagingDataEnabled; + } + + public boolean isPackagingDataEnabled() { + return packagingDataEnabled; + } + + + + + + + + + + public void reset() + { + resetCount += 1; + super.reset(); + initEvaluatorMap(); + root.recursiveReset(); + resetTurboFilterList(); + fireOnReset(); + resetListenersExceptResetResistant(); + resetStatusListeners(); + } + + private void resetStatusListeners() { + StatusManager sm = getStatusManager(); + for (StatusListener sl : sm.getCopyOfStatusListenerList()) { + sm.remove(sl); + } + } + + public TurboFilterList getTurboFilterList() { + return turboFilterList; + } + + public void addTurboFilter(TurboFilter newFilter) { + turboFilterList.add(newFilter); + } + + + + + public void resetTurboFilterList() + { + for (TurboFilter tf : turboFilterList) { + tf.stop(); + } + turboFilterList.clear(); + } + + + final FilterReply getTurboFilterChainDecision_0_3OrMore(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) + { + if (turboFilterList.size() == 0) { + return FilterReply.NEUTRAL; + } + return turboFilterList.getTurboFilterChainDecision(marker, logger, level, format, params, t); + } + + + + final FilterReply getTurboFilterChainDecision_1(Marker marker, Logger logger, Level level, String format, Object param, Throwable t) + { + if (turboFilterList.size() == 0) { + return FilterReply.NEUTRAL; + } + return turboFilterList.getTurboFilterChainDecision(marker, logger, level, format, new Object[] { param }, t); + } + + + + final FilterReply getTurboFilterChainDecision_2(Marker marker, Logger logger, Level level, String format, Object param1, Object param2, Throwable t) + { + if (turboFilterList.size() == 0) { + return FilterReply.NEUTRAL; + } + return turboFilterList.getTurboFilterChainDecision(marker, logger, level, format, new Object[] { param1, param2 }, t); + } + + + public void addListener(LoggerContextListener listener) + { + loggerContextListenerList.add(listener); + } + + public void removeListener(LoggerContextListener listener) { + loggerContextListenerList.remove(listener); + } + + private void resetListenersExceptResetResistant() { + List toRetain = new ArrayList(); + + for (LoggerContextListener lcl : loggerContextListenerList) { + if (lcl.isResetResistant()) { + toRetain.add(lcl); + } + } + loggerContextListenerList.retainAll(toRetain); + } + + private void resetAllListeners() { + loggerContextListenerList.clear(); + } + + public List getCopyOfListenerList() { + return new ArrayList(loggerContextListenerList); + } + + void fireOnLevelChange(Logger logger, Level level) { + for (LoggerContextListener listener : loggerContextListenerList) { + listener.onLevelChange(logger, level); + } + } + + private void fireOnReset() { + for (LoggerContextListener listener : loggerContextListenerList) { + listener.onReset(this); + } + } + + private void fireOnStart() { + for (LoggerContextListener listener : loggerContextListenerList) { + listener.onStart(this); + } + } + + private void fireOnStop() { + for (LoggerContextListener listener : loggerContextListenerList) { + listener.onStop(this); + } + } + + + public void start() + { + super.start(); + fireOnStart(); + } + + public void stop() { + reset(); + fireOnStop(); + resetAllListeners(); + super.stop(); + } + + public String toString() + { + return getClass().getName() + "[" + getName() + "]"; + } + + public int getMaxCallerDataDepth() { + return maxCallerDataDepth; + } + + public void setMaxCallerDataDepth(int maxCallerDataDepth) { + this.maxCallerDataDepth = maxCallerDataDepth; + } + + + + + + + + + + public List getFrameworkPackages() + { + return frameworkPackages; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/PatternLayout.java b/src/minecraft/ch/qos/logback/classic/PatternLayout.java new file mode 100644 index 0000000..033c848 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/PatternLayout.java @@ -0,0 +1,156 @@ +package ch.qos.logback.classic; + +import ch.qos.logback.classic.pattern.CallerDataConverter; +import ch.qos.logback.classic.pattern.ClassOfCallerConverter; +import ch.qos.logback.classic.pattern.ContextNameConverter; +import ch.qos.logback.classic.pattern.DateConverter; +import ch.qos.logback.classic.pattern.EnsureExceptionHandling; +import ch.qos.logback.classic.pattern.ExtendedThrowableProxyConverter; +import ch.qos.logback.classic.pattern.FileOfCallerConverter; +import ch.qos.logback.classic.pattern.LevelConverter; +import ch.qos.logback.classic.pattern.LineOfCallerConverter; +import ch.qos.logback.classic.pattern.LineSeparatorConverter; +import ch.qos.logback.classic.pattern.LocalSequenceNumberConverter; +import ch.qos.logback.classic.pattern.LoggerConverter; +import ch.qos.logback.classic.pattern.MDCConverter; +import ch.qos.logback.classic.pattern.MarkerConverter; +import ch.qos.logback.classic.pattern.MessageConverter; +import ch.qos.logback.classic.pattern.MethodOfCallerConverter; +import ch.qos.logback.classic.pattern.NopThrowableInformationConverter; +import ch.qos.logback.classic.pattern.PropertyConverter; +import ch.qos.logback.classic.pattern.RelativeTimeConverter; +import ch.qos.logback.classic.pattern.RootCauseFirstThrowableProxyConverter; +import ch.qos.logback.classic.pattern.ThreadConverter; +import ch.qos.logback.classic.pattern.ThrowableProxyConverter; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.pattern.color.BlackCompositeConverter; +import ch.qos.logback.core.pattern.color.BoldBlueCompositeConverter; +import ch.qos.logback.core.pattern.color.BoldMagentaCompositeConverter; +import ch.qos.logback.core.pattern.color.BoldWhiteCompositeConverter; +import ch.qos.logback.core.pattern.color.BoldYellowCompositeConverter; +import ch.qos.logback.core.pattern.color.CyanCompositeConverter; +import ch.qos.logback.core.pattern.color.GreenCompositeConverter; +import ch.qos.logback.core.pattern.color.MagentaCompositeConverter; +import ch.qos.logback.core.pattern.color.RedCompositeConverter; +import ch.qos.logback.core.pattern.color.YellowCompositeConverter; +import java.util.HashMap; +import java.util.Map; + +public class PatternLayout extends ch.qos.logback.core.pattern.PatternLayoutBase +{ + public static final Map defaultConverterMap = new HashMap(); + public static final String HEADER_PREFIX = "#logback.classic pattern: "; + + static { + defaultConverterMap.putAll(ch.qos.logback.core.pattern.parser.Parser.DEFAULT_COMPOSITE_CONVERTER_MAP); + + defaultConverterMap.put("d", DateConverter.class.getName()); + defaultConverterMap.put("date", DateConverter.class.getName()); + + defaultConverterMap.put("r", RelativeTimeConverter.class.getName()); + defaultConverterMap.put("relative", RelativeTimeConverter.class.getName()); + + defaultConverterMap.put("level", LevelConverter.class.getName()); + defaultConverterMap.put("le", LevelConverter.class.getName()); + defaultConverterMap.put("p", LevelConverter.class.getName()); + + defaultConverterMap.put("t", ThreadConverter.class.getName()); + defaultConverterMap.put("thread", ThreadConverter.class.getName()); + + defaultConverterMap.put("lo", LoggerConverter.class.getName()); + defaultConverterMap.put("logger", LoggerConverter.class.getName()); + defaultConverterMap.put("c", LoggerConverter.class.getName()); + + defaultConverterMap.put("m", MessageConverter.class.getName()); + defaultConverterMap.put("msg", MessageConverter.class.getName()); + defaultConverterMap.put("message", MessageConverter.class.getName()); + + defaultConverterMap.put("C", ClassOfCallerConverter.class.getName()); + defaultConverterMap.put("class", ClassOfCallerConverter.class.getName()); + + defaultConverterMap.put("M", MethodOfCallerConverter.class.getName()); + defaultConverterMap.put("method", MethodOfCallerConverter.class.getName()); + + defaultConverterMap.put("L", LineOfCallerConverter.class.getName()); + defaultConverterMap.put("line", LineOfCallerConverter.class.getName()); + + defaultConverterMap.put("F", FileOfCallerConverter.class.getName()); + defaultConverterMap.put("file", FileOfCallerConverter.class.getName()); + + defaultConverterMap.put("X", MDCConverter.class.getName()); + defaultConverterMap.put("mdc", MDCConverter.class.getName()); + + defaultConverterMap.put("ex", ThrowableProxyConverter.class.getName()); + defaultConverterMap.put("exception", ThrowableProxyConverter.class.getName()); + + defaultConverterMap.put("rEx", RootCauseFirstThrowableProxyConverter.class.getName()); + defaultConverterMap.put("rootException", RootCauseFirstThrowableProxyConverter.class.getName()); + + defaultConverterMap.put("throwable", ThrowableProxyConverter.class.getName()); + + + defaultConverterMap.put("xEx", ExtendedThrowableProxyConverter.class.getName()); + defaultConverterMap.put("xException", ExtendedThrowableProxyConverter.class.getName()); + + defaultConverterMap.put("xThrowable", ExtendedThrowableProxyConverter.class.getName()); + + + defaultConverterMap.put("nopex", NopThrowableInformationConverter.class.getName()); + + defaultConverterMap.put("nopexception", NopThrowableInformationConverter.class.getName()); + + + defaultConverterMap.put("cn", ContextNameConverter.class.getName()); + defaultConverterMap.put("contextName", ContextNameConverter.class.getName()); + + defaultConverterMap.put("caller", CallerDataConverter.class.getName()); + + defaultConverterMap.put("marker", MarkerConverter.class.getName()); + + defaultConverterMap.put("property", PropertyConverter.class.getName()); + + defaultConverterMap.put("n", LineSeparatorConverter.class.getName()); + + defaultConverterMap.put("black", BlackCompositeConverter.class.getName()); + defaultConverterMap.put("red", RedCompositeConverter.class.getName()); + defaultConverterMap.put("green", GreenCompositeConverter.class.getName()); + defaultConverterMap.put("yellow", YellowCompositeConverter.class.getName()); + defaultConverterMap.put("blue", ch.qos.logback.core.pattern.color.BlueCompositeConverter.class.getName()); + defaultConverterMap.put("magenta", MagentaCompositeConverter.class.getName()); + defaultConverterMap.put("cyan", CyanCompositeConverter.class.getName()); + defaultConverterMap.put("white", ch.qos.logback.core.pattern.color.WhiteCompositeConverter.class.getName()); + defaultConverterMap.put("gray", ch.qos.logback.core.pattern.color.GrayCompositeConverter.class.getName()); + defaultConverterMap.put("boldRed", ch.qos.logback.core.pattern.color.BoldRedCompositeConverter.class.getName()); + defaultConverterMap.put("boldGreen", ch.qos.logback.core.pattern.color.BoldGreenCompositeConverter.class.getName()); + defaultConverterMap.put("boldYellow", BoldYellowCompositeConverter.class.getName()); + defaultConverterMap.put("boldBlue", BoldBlueCompositeConverter.class.getName()); + defaultConverterMap.put("boldMagenta", BoldMagentaCompositeConverter.class.getName()); + defaultConverterMap.put("boldCyan", ch.qos.logback.core.pattern.color.BoldCyanCompositeConverter.class.getName()); + defaultConverterMap.put("boldWhite", BoldWhiteCompositeConverter.class.getName()); + defaultConverterMap.put("highlight", ch.qos.logback.classic.pattern.color.HighlightingCompositeConverter.class.getName()); + + defaultConverterMap.put("lsn", LocalSequenceNumberConverter.class.getName()); + } + + + public PatternLayout() + { + postCompileProcessor = new EnsureExceptionHandling(); + } + + public Map getDefaultConverterMap() { + return defaultConverterMap; + } + + public String doLayout(ILoggingEvent event) { + if (!isStarted()) { + return ""; + } + return writeLoopOnConverters(event); + } + + protected String getPresentationHeaderPrefix() + { + return "#logback.classic pattern: "; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/ViewStatusMessagesServlet.java b/src/minecraft/ch/qos/logback/classic/ViewStatusMessagesServlet.java new file mode 100644 index 0000000..aac3814 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/ViewStatusMessagesServlet.java @@ -0,0 +1,40 @@ +package ch.qos.logback.classic; + +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.status.ViewStatusMessagesServletBase; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.slf4j.LoggerFactory; + + + + + + + + + + + + + + +public class ViewStatusMessagesServlet + extends ViewStatusMessagesServletBase +{ + private static final long serialVersionUID = 443878494348593337L; + + public ViewStatusMessagesServlet() {} + + protected StatusManager getStatusManager(HttpServletRequest req, HttpServletResponse resp) + { + LoggerContext lc = (LoggerContext)LoggerFactory.getILoggerFactory(); + return lc.getStatusManager(); + } + + protected String getPageTitle(HttpServletRequest req, HttpServletResponse resp) + { + LoggerContext lc = (LoggerContext)LoggerFactory.getILoggerFactory(); + return "

Status messages for LoggerContext named [" + lc.getName() + "]

\r\n"; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/boolex/EvaluatorTemplate.java b/src/minecraft/ch/qos/logback/classic/boolex/EvaluatorTemplate.java new file mode 100644 index 0000000..85ad2b8 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/boolex/EvaluatorTemplate.java @@ -0,0 +1,38 @@ +package ch.qos.logback.classic.boolex; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import groovy.lang.GroovyObject; +import groovy.lang.MetaClass; +import org.codehaus.groovy.runtime.callsite.CallSite; +import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation; + + + + + + + + + + + + + + + +public class EvaluatorTemplate + implements IEvaluator, GroovyObject +{ + public EvaluatorTemplate() + { + EvaluatorTemplate this; + CallSite[] arrayOfCallSite = $getCallSiteArray(); + MetaClass localMetaClass = $getStaticMetaClass(); + metaClass = localMetaClass; + } + + public boolean doEvaluate(ILoggingEvent event) + { + CallSite[] arrayOfCallSite = $getCallSiteArray();ILoggingEvent e = event;return DefaultTypeTransformation.booleanUnbox(e);return DefaultTypeTransformation.booleanUnbox(Integer.valueOf(0)); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/boolex/GEventEvaluator.java b/src/minecraft/ch/qos/logback/classic/boolex/GEventEvaluator.java new file mode 100644 index 0000000..138927f --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/boolex/GEventEvaluator.java @@ -0,0 +1,88 @@ +package ch.qos.logback.classic.boolex; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.boolex.EvaluationException; +import ch.qos.logback.core.boolex.EventEvaluatorBase; +import ch.qos.logback.core.util.FileUtil; +import groovy.lang.GroovyClassLoader; +import groovy.lang.GroovyObject; +import groovy.lang.Script; +import org.codehaus.groovy.control.CompilationFailedException; + + + + + + + + + + + + +public class GEventEvaluator + extends EventEvaluatorBase +{ + String expression; + IEvaluator delegateEvaluator; + Script script; + + public GEventEvaluator() {} + + public String getExpression() + { + return expression; + } + + public void setExpression(String expression) { + this.expression = expression; + } + + public void start() { + int errors = 0; + if ((expression == null) || (expression.length() == 0)) { + addError("Empty expression"); + return; + } + addInfo("Expression to evaluate [" + expression + "]"); + + + + ClassLoader classLoader = getClass().getClassLoader(); + String currentPackageName = getClass().getPackage().getName(); + currentPackageName = currentPackageName.replace('.', '/'); + + FileUtil fileUtil = new FileUtil(getContext()); + String scriptText = fileUtil.resourceAsString(classLoader, currentPackageName + "/EvaluatorTemplate.groovy"); + if (scriptText == null) { + return; + } + + + scriptText = scriptText.replace("//EXPRESSION", expression); + + GroovyClassLoader gLoader = new GroovyClassLoader(classLoader); + try { + Class scriptClass = gLoader.parseClass(scriptText); + + GroovyObject goo = (GroovyObject)scriptClass.newInstance(); + delegateEvaluator = ((IEvaluator)goo); + } + catch (CompilationFailedException cfe) { + addError("Failed to compile expression [" + expression + "]", cfe); + errors++; + } catch (Exception e) { + addError("Failed to compile expression [" + expression + "]", e); + errors++; + } + if (errors == 0) + super.start(); + } + + public boolean evaluate(ILoggingEvent event) throws NullPointerException, EvaluationException { + if (delegateEvaluator == null) { + return false; + } + return delegateEvaluator.doEvaluate(event); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/boolex/IEvaluator.java b/src/minecraft/ch/qos/logback/classic/boolex/IEvaluator.java new file mode 100644 index 0000000..00823b1 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/boolex/IEvaluator.java @@ -0,0 +1,8 @@ +package ch.qos.logback.classic.boolex; + +import ch.qos.logback.classic.spi.ILoggingEvent; + +public abstract interface IEvaluator +{ + public abstract boolean doEvaluate(ILoggingEvent paramILoggingEvent); +} diff --git a/src/minecraft/ch/qos/logback/classic/boolex/JaninoEventEvaluator.java b/src/minecraft/ch/qos/logback/classic/boolex/JaninoEventEvaluator.java new file mode 100644 index 0000000..a1393f4 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/boolex/JaninoEventEvaluator.java @@ -0,0 +1,155 @@ +package ch.qos.logback.classic.boolex; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.IThrowableProxy; +import ch.qos.logback.classic.spi.LoggerContextVO; +import ch.qos.logback.classic.spi.ThrowableProxy; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.boolex.JaninoEventEvaluatorBase; +import ch.qos.logback.core.boolex.Matcher; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.slf4j.Marker; + + + + + + + + + + + + + + + + + +public class JaninoEventEvaluator + extends JaninoEventEvaluatorBase +{ + public static final String IMPORT_LEVEL = "import ch.qos.logback.classic.Level;\r\n"; + public static final List DEFAULT_PARAM_NAME_LIST = new ArrayList(); + public static final List DEFAULT_PARAM_TYPE_LIST = new ArrayList(); + + static { + DEFAULT_PARAM_NAME_LIST.add("DEBUG"); + DEFAULT_PARAM_NAME_LIST.add("INFO"); + DEFAULT_PARAM_NAME_LIST.add("WARN"); + DEFAULT_PARAM_NAME_LIST.add("ERROR"); + + DEFAULT_PARAM_NAME_LIST.add("event"); + DEFAULT_PARAM_NAME_LIST.add("message"); + + DEFAULT_PARAM_NAME_LIST.add("formattedMessage"); + DEFAULT_PARAM_NAME_LIST.add("logger"); + DEFAULT_PARAM_NAME_LIST.add("loggerContext"); + DEFAULT_PARAM_NAME_LIST.add("level"); + DEFAULT_PARAM_NAME_LIST.add("timeStamp"); + DEFAULT_PARAM_NAME_LIST.add("marker"); + DEFAULT_PARAM_NAME_LIST.add("mdc"); + DEFAULT_PARAM_NAME_LIST.add("throwableProxy"); + DEFAULT_PARAM_NAME_LIST.add("throwable"); + + DEFAULT_PARAM_TYPE_LIST.add(Integer.TYPE); + DEFAULT_PARAM_TYPE_LIST.add(Integer.TYPE); + DEFAULT_PARAM_TYPE_LIST.add(Integer.TYPE); + DEFAULT_PARAM_TYPE_LIST.add(Integer.TYPE); + + DEFAULT_PARAM_TYPE_LIST.add(ILoggingEvent.class); + DEFAULT_PARAM_TYPE_LIST.add(String.class); + DEFAULT_PARAM_TYPE_LIST.add(String.class); + DEFAULT_PARAM_TYPE_LIST.add(String.class); + DEFAULT_PARAM_TYPE_LIST.add(LoggerContextVO.class); + DEFAULT_PARAM_TYPE_LIST.add(Integer.TYPE); + DEFAULT_PARAM_TYPE_LIST.add(Long.TYPE); + DEFAULT_PARAM_TYPE_LIST.add(Marker.class); + DEFAULT_PARAM_TYPE_LIST.add(Map.class); + DEFAULT_PARAM_TYPE_LIST.add(IThrowableProxy.class); + DEFAULT_PARAM_TYPE_LIST.add(Throwable.class); + } + + protected String getDecoratedExpression() { + String expression = getExpression(); + if (!expression.contains("return")) { + expression = "return " + expression + ";"; + addInfo("Adding [return] prefix and a semicolon suffix. Expression becomes [" + expression + "]"); + addInfo("See also http://logback.qos.ch/codes.html#block"); + } + + return "import ch.qos.logback.classic.Level;\r\n" + expression; + } + + protected String[] getParameterNames() { + List fullNameList = new ArrayList(); + fullNameList.addAll(DEFAULT_PARAM_NAME_LIST); + + for (int i = 0; i < matcherList.size(); i++) { + Matcher m = (Matcher)matcherList.get(i); + fullNameList.add(m.getName()); + } + + return (String[])fullNameList.toArray(CoreConstants.EMPTY_STRING_ARRAY); + } + + protected Class[] getParameterTypes() { + List fullTypeList = new ArrayList(); + fullTypeList.addAll(DEFAULT_PARAM_TYPE_LIST); + for (int i = 0; i < matcherList.size(); i++) { + fullTypeList.add(Matcher.class); + } + return (Class[])fullTypeList.toArray(CoreConstants.EMPTY_CLASS_ARRAY); + } + + protected Object[] getParameterValues(ILoggingEvent loggingEvent) { + int matcherListSize = matcherList.size(); + + int i = 0; + Object[] values = new Object[DEFAULT_PARAM_NAME_LIST.size() + matcherListSize]; + + + values[(i++)] = Level.DEBUG_INTEGER; + values[(i++)] = Level.INFO_INTEGER; + values[(i++)] = Level.WARN_INTEGER; + values[(i++)] = Level.ERROR_INTEGER; + + values[(i++)] = loggingEvent; + values[(i++)] = loggingEvent.getMessage(); + values[(i++)] = loggingEvent.getFormattedMessage(); + values[(i++)] = loggingEvent.getLoggerName(); + values[(i++)] = loggingEvent.getLoggerContextVO(); + values[(i++)] = loggingEvent.getLevel().toInteger(); + values[(i++)] = Long.valueOf(loggingEvent.getTimeStamp()); + + + + values[(i++)] = loggingEvent.getMarker(); + values[(i++)] = loggingEvent.getMDCPropertyMap(); + + IThrowableProxy iThrowableProxy = loggingEvent.getThrowableProxy(); + + if (iThrowableProxy != null) { + values[(i++)] = iThrowableProxy; + if ((iThrowableProxy instanceof ThrowableProxy)) { + values[(i++)] = ((ThrowableProxy)iThrowableProxy).getThrowable(); + } else { + values[(i++)] = null; + } + } else { + values[(i++)] = null; + values[(i++)] = null; + } + + for (int j = 0; j < matcherListSize; j++) { + values[(i++)] = ((Matcher)matcherList.get(j)); + } + + return values; + } + + public JaninoEventEvaluator() {} +} diff --git a/src/minecraft/ch/qos/logback/classic/boolex/OnErrorEvaluator.java b/src/minecraft/ch/qos/logback/classic/boolex/OnErrorEvaluator.java new file mode 100644 index 0000000..458ddde --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/boolex/OnErrorEvaluator.java @@ -0,0 +1,38 @@ +package ch.qos.logback.classic.boolex; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.boolex.EvaluationException; +import ch.qos.logback.core.boolex.EventEvaluatorBase; + + + + + + + + + + + + + + + + + + + + + +public class OnErrorEvaluator + extends EventEvaluatorBase +{ + public OnErrorEvaluator() {} + + public boolean evaluate(ILoggingEvent event) + throws NullPointerException, EvaluationException + { + return getLevellevelInt >= 40000; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/boolex/OnMarkerEvaluator.java b/src/minecraft/ch/qos/logback/classic/boolex/OnMarkerEvaluator.java new file mode 100644 index 0000000..9c90967 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/boolex/OnMarkerEvaluator.java @@ -0,0 +1,58 @@ +package ch.qos.logback.classic.boolex; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.boolex.EvaluationException; +import ch.qos.logback.core.boolex.EventEvaluatorBase; +import java.util.ArrayList; +import java.util.List; +import org.slf4j.Marker; + + + + + + + + + + + + + + + + + + + +public class OnMarkerEvaluator + extends EventEvaluatorBase +{ + public OnMarkerEvaluator() {} + + List markerList = new ArrayList(); + + public void addMarker(String markerStr) { + markerList.add(markerStr); + } + + + + + + public boolean evaluate(ILoggingEvent event) + throws NullPointerException, EvaluationException + { + Marker eventsMarker = event.getMarker(); + if (eventsMarker == null) { + return false; + } + + for (String markerStr : markerList) { + if (eventsMarker.contains(markerStr)) { + return true; + } + } + return false; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/db/DBAppender.java b/src/minecraft/ch/qos/logback/classic/db/DBAppender.java new file mode 100644 index 0000000..faef11d --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/db/DBAppender.java @@ -0,0 +1,314 @@ +package ch.qos.logback.classic.db; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.db.names.DBNameResolver; +import ch.qos.logback.classic.db.names.DefaultDBNameResolver; +import ch.qos.logback.classic.spi.CallerData; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.IThrowableProxy; +import ch.qos.logback.classic.spi.LoggerContextVO; +import ch.qos.logback.classic.spi.StackTraceElementProxy; +import ch.qos.logback.classic.spi.ThrowableProxyUtil; +import ch.qos.logback.core.db.DBAppenderBase; +import java.lang.reflect.Method; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + + + + + + + + + + + + + + + + + + + + + + + + +public class DBAppender + extends DBAppenderBase +{ + protected String insertPropertiesSQL; + protected String insertExceptionSQL; + protected String insertSQL; + protected static final Method GET_GENERATED_KEYS_METHOD; + private DBNameResolver dbNameResolver; + static final int TIMESTMP_INDEX = 1; + static final int FORMATTED_MESSAGE_INDEX = 2; + static final int LOGGER_NAME_INDEX = 3; + static final int LEVEL_STRING_INDEX = 4; + static final int THREAD_NAME_INDEX = 5; + static final int REFERENCE_FLAG_INDEX = 6; + static final int ARG0_INDEX = 7; + static final int ARG1_INDEX = 8; + static final int ARG2_INDEX = 9; + static final int ARG3_INDEX = 10; + static final int CALLER_FILENAME_INDEX = 11; + static final int CALLER_CLASS_INDEX = 12; + static final int CALLER_METHOD_INDEX = 13; + static final int CALLER_LINE_INDEX = 14; + static final int EVENT_ID_INDEX = 15; + static final StackTraceElement EMPTY_CALLER_DATA = ; + + static + { + Method getGeneratedKeysMethod; + try + { + getGeneratedKeysMethod = PreparedStatement.class.getMethod("getGeneratedKeys", (Class[])null); + } + catch (Exception ex) { + getGeneratedKeysMethod = null; + } + GET_GENERATED_KEYS_METHOD = getGeneratedKeysMethod; + } + + public void setDbNameResolver(DBNameResolver dbNameResolver) { + this.dbNameResolver = dbNameResolver; + } + + public void start() + { + if (dbNameResolver == null) + dbNameResolver = new DefaultDBNameResolver(); + insertExceptionSQL = SQLBuilder.buildInsertExceptionSQL(dbNameResolver); + insertPropertiesSQL = SQLBuilder.buildInsertPropertiesSQL(dbNameResolver); + insertSQL = SQLBuilder.buildInsertSQL(dbNameResolver); + super.start(); + } + + + protected void subAppend(ILoggingEvent event, Connection connection, PreparedStatement insertStatement) + throws Throwable + { + bindLoggingEventWithInsertStatement(insertStatement, event); + bindLoggingEventArgumentsWithPreparedStatement(insertStatement, event.getArgumentArray()); + + + bindCallerDataWithPreparedStatement(insertStatement, event.getCallerData()); + + int updateCount = insertStatement.executeUpdate(); + if (updateCount != 1) { + addWarn("Failed to insert loggingEvent"); + } + } + + protected void secondarySubAppend(ILoggingEvent event, Connection connection, long eventId) throws Throwable + { + Map mergedMap = mergePropertyMaps(event); + insertProperties(mergedMap, connection, eventId); + + if (event.getThrowableProxy() != null) { + insertThrowable(event.getThrowableProxy(), connection, eventId); + } + } + + void bindLoggingEventWithInsertStatement(PreparedStatement stmt, ILoggingEvent event) throws SQLException + { + stmt.setLong(1, event.getTimeStamp()); + stmt.setString(2, event.getFormattedMessage()); + stmt.setString(3, event.getLoggerName()); + stmt.setString(4, event.getLevel().toString()); + stmt.setString(5, event.getThreadName()); + stmt.setShort(6, DBHelper.computeReferenceMask(event)); + } + + void bindLoggingEventArgumentsWithPreparedStatement(PreparedStatement stmt, Object[] argArray) + throws SQLException + { + int arrayLen = argArray != null ? argArray.length : 0; + + for (int i = 0; (i < arrayLen) && (i < 4); i++) { + stmt.setString(7 + i, asStringTruncatedTo254(argArray[i])); + } + if (arrayLen < 4) { + for (int i = arrayLen; i < 4; i++) { + stmt.setString(7 + i, null); + } + } + } + + String asStringTruncatedTo254(Object o) { + String s = null; + if (o != null) { + s = o.toString(); + } + + if (s == null) { + return null; + } + if (s.length() <= 254) { + return s; + } + return s.substring(0, 254); + } + + + void bindCallerDataWithPreparedStatement(PreparedStatement stmt, StackTraceElement[] callerDataArray) + throws SQLException + { + StackTraceElement caller = extractFirstCaller(callerDataArray); + + stmt.setString(11, caller.getFileName()); + stmt.setString(12, caller.getClassName()); + stmt.setString(13, caller.getMethodName()); + stmt.setString(14, Integer.toString(caller.getLineNumber())); + } + + private StackTraceElement extractFirstCaller(StackTraceElement[] callerDataArray) { + StackTraceElement caller = EMPTY_CALLER_DATA; + if (hasAtLeastOneNonNullElement(callerDataArray)) + caller = callerDataArray[0]; + return caller; + } + + private boolean hasAtLeastOneNonNullElement(StackTraceElement[] callerDataArray) { + return (callerDataArray != null) && (callerDataArray.length > 0) && (callerDataArray[0] != null); + } + + Map mergePropertyMaps(ILoggingEvent event) { + Map mergedMap = new HashMap(); + + + + Map loggerContextMap = event.getLoggerContextVO().getPropertyMap(); + + Map mdcMap = event.getMDCPropertyMap(); + if (loggerContextMap != null) { + mergedMap.putAll(loggerContextMap); + } + if (mdcMap != null) { + mergedMap.putAll(mdcMap); + } + + return mergedMap; + } + + protected Method getGeneratedKeysMethod() + { + return GET_GENERATED_KEYS_METHOD; + } + + protected String getInsertSQL() + { + return insertSQL; + } + + protected void insertProperties(Map mergedMap, Connection connection, long eventId) throws SQLException + { + Set propertiesKeys = mergedMap.keySet(); + if (propertiesKeys.size() > 0) { + PreparedStatement insertPropertiesStatement = null; + try { + insertPropertiesStatement = connection.prepareStatement(insertPropertiesSQL); + + + for (String key : propertiesKeys) { + String value = (String)mergedMap.get(key); + + insertPropertiesStatement.setLong(1, eventId); + insertPropertiesStatement.setString(2, key); + insertPropertiesStatement.setString(3, value); + + if (cnxSupportsBatchUpdates) { + insertPropertiesStatement.addBatch(); + } else { + insertPropertiesStatement.execute(); + } + } + + if (cnxSupportsBatchUpdates) { + insertPropertiesStatement.executeBatch(); + } + } finally { + ch.qos.logback.core.db.DBHelper.closeStatement(insertPropertiesStatement); + } + } + } + + + + + void updateExceptionStatement(PreparedStatement exceptionStatement, String txt, short i, long eventId) + throws SQLException + { + exceptionStatement.setLong(1, eventId); + exceptionStatement.setShort(2, i); + exceptionStatement.setString(3, txt); + if (cnxSupportsBatchUpdates) { + exceptionStatement.addBatch(); + } else { + exceptionStatement.execute(); + } + } + + + short buildExceptionStatement(IThrowableProxy tp, short baseIndex, PreparedStatement insertExceptionStatement, long eventId) + throws SQLException + { + StringBuilder buf = new StringBuilder(); + ThrowableProxyUtil.subjoinFirstLine(buf, tp); + baseIndex = (short)(baseIndex + 1);updateExceptionStatement(insertExceptionStatement, buf.toString(), baseIndex, eventId); + + + int commonFrames = tp.getCommonFrames(); + StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray(); + for (int i = 0; i < stepArray.length - commonFrames; i++) { + StringBuilder sb = new StringBuilder(); + sb.append('\t'); + ThrowableProxyUtil.subjoinSTEP(sb, stepArray[i]); + baseIndex = (short)(baseIndex + 1);updateExceptionStatement(insertExceptionStatement, sb.toString(), baseIndex, eventId); + } + + + if (commonFrames > 0) { + StringBuilder sb = new StringBuilder(); + sb.append('\t').append("... ").append(commonFrames).append(" common frames omitted"); + + baseIndex = (short)(baseIndex + 1);updateExceptionStatement(insertExceptionStatement, sb.toString(), baseIndex, eventId); + } + + + return baseIndex; + } + + protected void insertThrowable(IThrowableProxy tp, Connection connection, long eventId) + throws SQLException + { + PreparedStatement exceptionStatement = null; + try { + exceptionStatement = connection.prepareStatement(insertExceptionSQL); + + short baseIndex = 0; + while (tp != null) { + baseIndex = buildExceptionStatement(tp, baseIndex, exceptionStatement, eventId); + + tp = tp.getCause(); + } + + if (cnxSupportsBatchUpdates) { + exceptionStatement.executeBatch(); + } + } finally { + ch.qos.logback.core.db.DBHelper.closeStatement(exceptionStatement); + } + } + + public DBAppender() {} +} diff --git a/src/minecraft/ch/qos/logback/classic/db/DBHelper.java b/src/minecraft/ch/qos/logback/classic/db/DBHelper.java new file mode 100644 index 0000000..8f06f14 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/db/DBHelper.java @@ -0,0 +1,47 @@ +package ch.qos.logback.classic.db; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggerContextVO; +import java.util.Map; +import java.util.Set; + + + + + + + + + + + + +public class DBHelper +{ + public static final short PROPERTIES_EXIST = 1; + public static final short EXCEPTION_EXISTS = 2; + + public DBHelper() {} + + public static short computeReferenceMask(ILoggingEvent event) + { + short mask = 0; + + int mdcPropSize = 0; + if (event.getMDCPropertyMap() != null) { + mdcPropSize = event.getMDCPropertyMap().keySet().size(); + } + int contextPropSize = 0; + if (event.getLoggerContextVO().getPropertyMap() != null) { + contextPropSize = event.getLoggerContextVO().getPropertyMap().size(); + } + + if ((mdcPropSize > 0) || (contextPropSize > 0)) { + mask = 1; + } + if (event.getThrowableProxy() != null) { + mask = (short)(mask | 0x2); + } + return mask; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/db/SQLBuilder.java b/src/minecraft/ch/qos/logback/classic/db/SQLBuilder.java new file mode 100644 index 0000000..dd691f5 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/db/SQLBuilder.java @@ -0,0 +1,64 @@ +package ch.qos.logback.classic.db; + +import ch.qos.logback.classic.db.names.ColumnName; +import ch.qos.logback.classic.db.names.DBNameResolver; +import ch.qos.logback.classic.db.names.TableName; + + + + + + + + + + + + + +public class SQLBuilder +{ + public SQLBuilder() {} + + static String buildInsertPropertiesSQL(DBNameResolver dbNameResolver) + { + StringBuilder sqlBuilder = new StringBuilder("INSERT INTO "); + sqlBuilder.append(dbNameResolver.getTableName(TableName.LOGGING_EVENT_PROPERTY)).append(" ("); + sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.EVENT_ID)).append(", "); + sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.MAPPED_KEY)).append(", "); + sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.MAPPED_VALUE)).append(") "); + sqlBuilder.append("VALUES (?, ?, ?)"); + return sqlBuilder.toString(); + } + + static String buildInsertExceptionSQL(DBNameResolver dbNameResolver) { + StringBuilder sqlBuilder = new StringBuilder("INSERT INTO "); + sqlBuilder.append(dbNameResolver.getTableName(TableName.LOGGING_EVENT_EXCEPTION)).append(" ("); + sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.EVENT_ID)).append(", "); + sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.I)).append(", "); + sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.TRACE_LINE)).append(") "); + sqlBuilder.append("VALUES (?, ?, ?)"); + return sqlBuilder.toString(); + } + + static String buildInsertSQL(DBNameResolver dbNameResolver) { + StringBuilder sqlBuilder = new StringBuilder("INSERT INTO "); + sqlBuilder.append(dbNameResolver.getTableName(TableName.LOGGING_EVENT)).append(" ("); + sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.TIMESTMP)).append(", "); + sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.FORMATTED_MESSAGE)).append(", "); + sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.LOGGER_NAME)).append(", "); + sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.LEVEL_STRING)).append(", "); + sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.THREAD_NAME)).append(", "); + sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.REFERENCE_FLAG)).append(", "); + sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.ARG0)).append(", "); + sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.ARG1)).append(", "); + sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.ARG2)).append(", "); + sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.ARG3)).append(", "); + sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.CALLER_FILENAME)).append(", "); + sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.CALLER_CLASS)).append(", "); + sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.CALLER_METHOD)).append(", "); + sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.CALLER_LINE)).append(") "); + sqlBuilder.append("VALUES (?, ?, ? ,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + return sqlBuilder.toString(); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/db/names/ColumnName.java b/src/minecraft/ch/qos/logback/classic/db/names/ColumnName.java new file mode 100644 index 0000000..445433d --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/db/names/ColumnName.java @@ -0,0 +1,8 @@ +package ch.qos.logback.classic.db.names; + +public enum ColumnName +{ + EVENT_ID, TIMESTMP, FORMATTED_MESSAGE, LOGGER_NAME, LEVEL_STRING, THREAD_NAME, REFERENCE_FLAG, ARG0, ARG1, ARG2, ARG3, CALLER_FILENAME, CALLER_CLASS, CALLER_METHOD, CALLER_LINE, MAPPED_KEY, MAPPED_VALUE, I, TRACE_LINE; + + private ColumnName() {} +} diff --git a/src/minecraft/ch/qos/logback/classic/db/names/DBNameResolver.java b/src/minecraft/ch/qos/logback/classic/db/names/DBNameResolver.java new file mode 100644 index 0000000..2cf719d --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/db/names/DBNameResolver.java @@ -0,0 +1,8 @@ +package ch.qos.logback.classic.db.names; + +public abstract interface DBNameResolver +{ + public abstract > String getTableName(N paramN); + + public abstract > String getColumnName(N paramN); +} diff --git a/src/minecraft/ch/qos/logback/classic/db/names/DefaultDBNameResolver.java b/src/minecraft/ch/qos/logback/classic/db/names/DefaultDBNameResolver.java new file mode 100644 index 0000000..dd56fdc --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/db/names/DefaultDBNameResolver.java @@ -0,0 +1,33 @@ +package ch.qos.logback.classic.db.names; + + + + + + + + + + +public class DefaultDBNameResolver + implements DBNameResolver +{ + public DefaultDBNameResolver() {} + + + + + + + + + + public > String getTableName(N tableName) + { + return tableName.toString().toLowerCase(); + } + + public > String getColumnName(N columnName) { + return columnName.toString().toLowerCase(); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/db/names/SimpleDBNameResolver.java b/src/minecraft/ch/qos/logback/classic/db/names/SimpleDBNameResolver.java new file mode 100644 index 0000000..19977f0 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/db/names/SimpleDBNameResolver.java @@ -0,0 +1,55 @@ +package ch.qos.logback.classic.db.names; + + + + + + + + + +public class SimpleDBNameResolver + implements DBNameResolver +{ + public SimpleDBNameResolver() {} + + + + + + + + + + private String tableNamePrefix = ""; + + private String tableNameSuffix = ""; + + private String columnNamePrefix = ""; + + private String columnNameSuffix = ""; + + public > String getTableName(N tableName) { + return tableNamePrefix + tableName.name().toLowerCase() + tableNameSuffix; + } + + public > String getColumnName(N columnName) { + return columnNamePrefix + columnName.name().toLowerCase() + columnNameSuffix; + } + + public void setTableNamePrefix(String tableNamePrefix) { + this.tableNamePrefix = (tableNamePrefix != null ? tableNamePrefix : ""); + } + + public void setTableNameSuffix(String tableNameSuffix) { + this.tableNameSuffix = (tableNameSuffix != null ? tableNameSuffix : ""); + } + + public void setColumnNamePrefix(String columnNamePrefix) { + this.columnNamePrefix = (columnNamePrefix != null ? columnNamePrefix : ""); + } + + public void setColumnNameSuffix(String columnNameSuffix) { + this.columnNameSuffix = (columnNameSuffix != null ? columnNameSuffix : ""); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/db/names/TableName.java b/src/minecraft/ch/qos/logback/classic/db/names/TableName.java new file mode 100644 index 0000000..b89ee1d --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/db/names/TableName.java @@ -0,0 +1,8 @@ +package ch.qos.logback.classic.db.names; + +public enum TableName +{ + LOGGING_EVENT, LOGGING_EVENT_PROPERTY, LOGGING_EVENT_EXCEPTION; + + private TableName() {} +} diff --git a/src/minecraft/ch/qos/logback/classic/encoder/PatternLayoutEncoder.java b/src/minecraft/ch/qos/logback/classic/encoder/PatternLayoutEncoder.java new file mode 100644 index 0000000..2bfc389 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/encoder/PatternLayoutEncoder.java @@ -0,0 +1,32 @@ +package ch.qos.logback.classic.encoder; + +import ch.qos.logback.classic.PatternLayout; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.pattern.PatternLayoutEncoderBase; + + + + + + + + + + + +public class PatternLayoutEncoder + extends PatternLayoutEncoderBase +{ + public PatternLayoutEncoder() {} + + public void start() + { + PatternLayout patternLayout = new PatternLayout(); + patternLayout.setContext(context); + patternLayout.setPattern(getPattern()); + patternLayout.setOutputPatternAsHeader(outputPatternAsHeader); + patternLayout.start(); + layout = patternLayout; + super.start(); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/filter/LevelFilter.java b/src/minecraft/ch/qos/logback/classic/filter/LevelFilter.java new file mode 100644 index 0000000..1f92dde --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/filter/LevelFilter.java @@ -0,0 +1,57 @@ +package ch.qos.logback.classic.filter; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.filter.AbstractMatcherFilter; +import ch.qos.logback.core.spi.FilterReply; + + + + + + + + + + + + + + + + + + + + + +public class LevelFilter + extends AbstractMatcherFilter +{ + Level level; + + public LevelFilter() {} + + public FilterReply decide(ILoggingEvent event) + { + if (!isStarted()) { + return FilterReply.NEUTRAL; + } + + if (event.getLevel().equals(level)) { + return onMatch; + } + return onMismatch; + } + + public void setLevel(Level level) + { + this.level = level; + } + + public void start() { + if (level != null) { + super.start(); + } + } +} diff --git a/src/minecraft/ch/qos/logback/classic/filter/ThresholdFilter.java b/src/minecraft/ch/qos/logback/classic/filter/ThresholdFilter.java new file mode 100644 index 0000000..3bec53a --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/filter/ThresholdFilter.java @@ -0,0 +1,61 @@ +package ch.qos.logback.classic.filter; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.filter.Filter; +import ch.qos.logback.core.spi.FilterReply; + + + + + + + + + + + + + + + + + + + + + + + + + +public class ThresholdFilter + extends Filter +{ + Level level; + + public ThresholdFilter() {} + + public FilterReply decide(ILoggingEvent event) + { + if (!isStarted()) { + return FilterReply.NEUTRAL; + } + + if (event.getLevel().isGreaterOrEqual(level)) { + return FilterReply.NEUTRAL; + } + return FilterReply.DENY; + } + + public void setLevel(String level) + { + this.level = Level.toLevel(level); + } + + public void start() { + if (level != null) { + super.start(); + } + } +} diff --git a/src/minecraft/ch/qos/logback/classic/gaffer/AppenderDelegate.java b/src/minecraft/ch/qos/logback/classic/gaffer/AppenderDelegate.java new file mode 100644 index 0000000..781c4aa --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/gaffer/AppenderDelegate.java @@ -0,0 +1,72 @@ +package ch.qos.logback.classic.gaffer; + +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.spi.AppenderAttachable; +import groovy.lang.Closure; +import java.util.List; +import java.util.Map; +import org.codehaus.groovy.runtime.GeneratedClosure; +import org.codehaus.groovy.runtime.ScriptBytecodeAdapter; +import org.codehaus.groovy.runtime.callsite.CallSite; +import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation; + + + + + + + + + + +public class AppenderDelegate + extends ComponentDelegate +{ + private Map> appendersByName; + + public AppenderDelegate(Appender appender) + { + super(appender);Map localMap = ScriptBytecodeAdapter.createMap(new Object[0]);appendersByName = localMap; + } + + class _closure1 extends Closure implements GeneratedClosure { public _closure1(Object _thisObject) { super(_thisObject); } + + public Object doCall(Object it) { CallSite[] arrayOfCallSite = $getCallSiteArray();return ScriptBytecodeAdapter.createMap(new Object[] { arrayOfCallSite[0].callGetProperty(it), it });return null; + } + + public Object doCall() + { + CallSite[] arrayOfCallSite = $getCallSiteArray(); + return doCall(null); + return null; + } + } + + public AppenderDelegate(Appender appender, List> appenders) + { + super(appender);Map localMap = ScriptBytecodeAdapter.createMap(new Object[0]);appendersByName = localMap; + Object localObject = arrayOfCallSite[0].call(appenders, new _closure1(this));appendersByName = ((Map)ScriptBytecodeAdapter.castToType(localObject, Map.class)); + } + + public String getLabel() { + CallSite[] arrayOfCallSite = $getCallSiteArray();return "appender";return null; + } + + public void appenderRef(String name) { + CallSite[] arrayOfCallSite = $getCallSiteArray(); if ((!DefaultTypeTransformation.booleanUnbox(arrayOfCallSite[1].call(AppenderAttachable.class, arrayOfCallSite[2].callGetProperty(arrayOfCallSite[3].callGroovyObjectGetProperty(this)))) ? 1 : 0) != 0) { + Object errorMessage = arrayOfCallSite[4].call(arrayOfCallSite[5].call(arrayOfCallSite[6].call(arrayOfCallSite[7].callGetProperty(arrayOfCallSite[8].callGetProperty(arrayOfCallSite[9].callGroovyObjectGetProperty(this))), " does not implement "), arrayOfCallSite[10].callGetProperty(AppenderAttachable.class)), "."); + throw ((Throwable)arrayOfCallSite[11].callConstructor(IllegalArgumentException.class, errorMessage)); + } + arrayOfCallSite[12].call(arrayOfCallSite[13].callGroovyObjectGetProperty(this), arrayOfCallSite[14].call(appendersByName, name)); + } + + public Map> getAppendersByName() + { + return appendersByName; + } + + public void setAppendersByName(Map> paramMap) + { + appendersByName = paramMap; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/gaffer/ComponentDelegate.java b/src/minecraft/ch/qos/logback/classic/gaffer/ComponentDelegate.java new file mode 100644 index 0000000..f0f1159 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/gaffer/ComponentDelegate.java @@ -0,0 +1,204 @@ +package ch.qos.logback.classic.gaffer; + +import ch.qos.logback.core.joran.spi.NoAutoStartUtil; +import ch.qos.logback.core.spi.ContextAware; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.spi.LifeCycle; +import groovy.lang.Closure; +import groovy.lang.GroovyObject; +import groovy.lang.MetaClass; +import java.util.Iterator; +import java.util.List; +import org.codehaus.groovy.runtime.BytecodeInterface8; +import org.codehaus.groovy.runtime.GStringImpl; +import org.codehaus.groovy.runtime.ScriptBytecodeAdapter; +import org.codehaus.groovy.runtime.callsite.CallSite; +import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation; +import org.codehaus.groovy.runtime.typehandling.ShortTypeHandling; + +public class ComponentDelegate + extends ContextAwareBase implements GroovyObject +{ + private final Object component; + private final List fieldsToCascade; + + public ComponentDelegate(Object arg1) + { + Object component; + CallSite[] arrayOfCallSite = $getCallSiteArray();List localList = ScriptBytecodeAdapter.createList(new Object[0]);fieldsToCascade = localList;MetaClass localMetaClass = $getStaticMetaClass();metaClass = localMetaClass; + + + Object localObject1 = component;this.component = localObject1; + } + + public String getLabel() { CallSite[] arrayOfCallSite = $getCallSiteArray();return "component";return null; } + + public String getLabelFistLetterInUpperCase() { CallSite[] arrayOfCallSite = $getCallSiteArray(); if ((__$stMC) || (BytecodeInterface8.disabledStandardMetaClass())) return (String)ShortTypeHandling.castToString(arrayOfCallSite[0].call(arrayOfCallSite[1].call(arrayOfCallSite[2].call(arrayOfCallSite[3].callCurrent(this), Integer.valueOf(0))), arrayOfCallSite[4].call(arrayOfCallSite[5].callCurrent(this), Integer.valueOf(1)))); else return (String)ShortTypeHandling.castToString(arrayOfCallSite[6].call(arrayOfCallSite[7].call(arrayOfCallSite[8].call(getLabel(), Integer.valueOf(0))), arrayOfCallSite[9].call(getLabel(), Integer.valueOf(1)))); return null; + } + + public void methodMissing(String name, Object args) { CallSite[] arrayOfCallSite = $getCallSiteArray();NestingType nestingType = (NestingType)ShortTypeHandling.castToEnum(arrayOfCallSite[10].call(PropertyUtil.class, component, name), NestingType.class); + if (ScriptBytecodeAdapter.compareEqual(nestingType, arrayOfCallSite[11].callGetProperty(NestingType.class))) { + arrayOfCallSite[12].callCurrent(this, new GStringImpl(new Object[] { arrayOfCallSite[13].callCurrent(this), arrayOfCallSite[14].callCurrent(this), arrayOfCallSite[15].callGetProperty(arrayOfCallSite[16].call(component)), name }, new String[] { "", " ", " of type [", "] has no appplicable [", "] property " })); + return; + } + + String subComponentName = null; + Class clazz = null; + Closure closure = null; + Object localObject1 = arrayOfCallSite[17].callCurrent(this, args);subComponentName = (String)ShortTypeHandling.castToString(arrayOfCallSite[18].call(localObject1, Integer.valueOf(0)));clazz = (Class)ShortTypeHandling.castToClass(arrayOfCallSite[19].call(localObject1, Integer.valueOf(1)));closure = (Closure)ScriptBytecodeAdapter.castToType(arrayOfCallSite[20].call(localObject1, Integer.valueOf(2)), Closure.class); + if ((!BytecodeInterface8.isOrigZ()) || (__$stMC) || (BytecodeInterface8.disabledStandardMetaClass())) { if (ScriptBytecodeAdapter.compareNotEqual(clazz, null)) { + Object subComponent = arrayOfCallSite[21].call(clazz); + String str1; if (((DefaultTypeTransformation.booleanUnbox(subComponentName)) && (DefaultTypeTransformation.booleanUnbox(arrayOfCallSite[22].call(subComponent, name))) ? 1 : 0) != 0) { + str1 = subComponentName;ScriptBytecodeAdapter.setProperty(str1, null, subComponent, "name"); } + Object localObject2; + if ((subComponent instanceof ContextAware)) { + localObject2 = arrayOfCallSite[23].callGroovyObjectGetProperty(this);ScriptBytecodeAdapter.setProperty(localObject2, null, subComponent, "context"); + } + if (DefaultTypeTransformation.booleanUnbox(closure)) { + ComponentDelegate subDelegate = (ComponentDelegate)ScriptBytecodeAdapter.castToType(arrayOfCallSite[24].callConstructor(ComponentDelegate.class, subComponent), ComponentDelegate.class); + + arrayOfCallSite[25].callCurrent(this, subDelegate); + Object localObject3 = arrayOfCallSite[26].callGroovyObjectGetProperty(this);ScriptBytecodeAdapter.setGroovyObjectProperty(localObject3, ComponentDelegate.class, subDelegate, "context"); + arrayOfCallSite[27].callCurrent(this, subComponent); + ComponentDelegate localComponentDelegate1 = subDelegate;ScriptBytecodeAdapter.setGroovyObjectProperty(localComponentDelegate1, ComponentDelegate.class, closure, "delegate"); + Object localObject4 = arrayOfCallSite[28].callGetProperty(Closure.class);ScriptBytecodeAdapter.setGroovyObjectProperty(localObject4, ComponentDelegate.class, closure, "resolveStrategy"); + arrayOfCallSite[29].call(closure); + } + if ((((subComponent instanceof LifeCycle)) && (DefaultTypeTransformation.booleanUnbox(arrayOfCallSite[30].call(NoAutoStartUtil.class, subComponent))) ? 1 : 0) != 0) { + arrayOfCallSite[31].call(subComponent); + } + arrayOfCallSite[32].call(PropertyUtil.class, nestingType, component, subComponent, name); + } else { + arrayOfCallSite[33].callCurrent(this, new GStringImpl(new Object[] { name, arrayOfCallSite[34].callCurrent(this), arrayOfCallSite[35].callCurrent(this), arrayOfCallSite[36].callGetProperty(arrayOfCallSite[37].call(component)) }, new String[] { "No 'class' argument specified for [", "] in ", " ", " of type [", "]" })); + } + } + else if (ScriptBytecodeAdapter.compareNotEqual(clazz, null)) { + Object subComponent = arrayOfCallSite[38].call(clazz); + String str2; if (((DefaultTypeTransformation.booleanUnbox(subComponentName)) && (DefaultTypeTransformation.booleanUnbox(arrayOfCallSite[39].call(subComponent, name))) ? 1 : 0) != 0) { + str2 = subComponentName;ScriptBytecodeAdapter.setProperty(str2, null, subComponent, "name"); } + Object localObject5; + if ((subComponent instanceof ContextAware)) { + localObject5 = arrayOfCallSite[40].callGroovyObjectGetProperty(this);ScriptBytecodeAdapter.setProperty(localObject5, null, subComponent, "context"); + } + if (DefaultTypeTransformation.booleanUnbox(closure)) { + ComponentDelegate subDelegate = (ComponentDelegate)ScriptBytecodeAdapter.castToType(arrayOfCallSite[41].callConstructor(ComponentDelegate.class, subComponent), ComponentDelegate.class); + + arrayOfCallSite[42].callCurrent(this, subDelegate); + Object localObject6 = arrayOfCallSite[43].callGroovyObjectGetProperty(this);ScriptBytecodeAdapter.setGroovyObjectProperty(localObject6, ComponentDelegate.class, subDelegate, "context"); + arrayOfCallSite[44].callCurrent(this, subComponent); + ComponentDelegate localComponentDelegate2 = subDelegate;ScriptBytecodeAdapter.setGroovyObjectProperty(localComponentDelegate2, ComponentDelegate.class, closure, "delegate"); + Object localObject7 = arrayOfCallSite[45].callGetProperty(Closure.class);ScriptBytecodeAdapter.setGroovyObjectProperty(localObject7, ComponentDelegate.class, closure, "resolveStrategy"); + arrayOfCallSite[46].call(closure); + } + if ((((subComponent instanceof LifeCycle)) && (DefaultTypeTransformation.booleanUnbox(arrayOfCallSite[47].call(NoAutoStartUtil.class, subComponent))) ? 1 : 0) != 0) { + arrayOfCallSite[48].call(subComponent); + } + arrayOfCallSite[49].call(PropertyUtil.class, nestingType, component, subComponent, name); + } else { + arrayOfCallSite[50].callCurrent(this, new GStringImpl(new Object[] { name, getLabel(), getComponentName(), arrayOfCallSite[51].callGetProperty(arrayOfCallSite[52].call(component)) }, new String[] { "No 'class' argument specified for [", "] in ", " ", " of type [", "]" })); + } + } + + public void cascadeFields(ComponentDelegate subDelegate) { + CallSite[] arrayOfCallSite = $getCallSiteArray();String k = null; Object localObject; for (Iterator localIterator = (Iterator)ScriptBytecodeAdapter.castToType(arrayOfCallSite[53].call(fieldsToCascade), Iterator.class); localIterator.hasNext(); + ScriptBytecodeAdapter.setProperty(localObject, null, arrayOfCallSite[54].callGroovyObjectGetProperty(subDelegate), (String)ShortTypeHandling.castToString(new GStringImpl(new Object[] { k }, new String[] { "", "" })))) + { + k = (String)ShortTypeHandling.castToString(localIterator.next()); + localObject = ScriptBytecodeAdapter.getGroovyObjectProperty(ComponentDelegate.class, this, (String)ShortTypeHandling.castToString(new GStringImpl(new Object[] { k }, new String[] { "", "" }))); + } + } + + public void injectParent(Object subComponent) { + CallSite[] arrayOfCallSite = $getCallSiteArray(); Object localObject; if (DefaultTypeTransformation.booleanUnbox(arrayOfCallSite[55].call(subComponent, "parent"))) { + localObject = component;ScriptBytecodeAdapter.setProperty(localObject, null, subComponent, "parent"); + } + } + + public void propertyMissing(String name, Object value) { + CallSite[] arrayOfCallSite = $getCallSiteArray();NestingType nestingType = (NestingType)ShortTypeHandling.castToEnum(arrayOfCallSite[56].call(PropertyUtil.class, component, name), NestingType.class); + if (ScriptBytecodeAdapter.compareEqual(nestingType, arrayOfCallSite[57].callGetProperty(NestingType.class))) { + arrayOfCallSite[58].callCurrent(this, new GStringImpl(new Object[] { arrayOfCallSite[59].callCurrent(this), arrayOfCallSite[60].callCurrent(this), arrayOfCallSite[61].callGetProperty(arrayOfCallSite[62].call(component)), name }, new String[] { "", " ", " of type [", "] has no appplicable [", "] property " })); + return; + } + arrayOfCallSite[63].call(PropertyUtil.class, nestingType, component, value, name); + } + + public Object analyzeArgs(Object... args) + { + CallSite[] arrayOfCallSite = $getCallSiteArray();String name = null; + Class clazz = null; + Closure closure = null; + + if (ScriptBytecodeAdapter.compareGreaterThan(arrayOfCallSite[64].call(args), Integer.valueOf(3))) { + arrayOfCallSite[65].callCurrent(this, new GStringImpl(new Object[] { args }, new String[] { "At most 3 arguments allowed but you passed ", "" })); + return ScriptBytecodeAdapter.createList(new Object[] { name, clazz, closure }); + } + + if ((__$stMC) || (BytecodeInterface8.disabledStandardMetaClass())) { if ((arrayOfCallSite[66].call(args, Integer.valueOf(-1)) instanceof Closure)) { + Object localObject1 = arrayOfCallSite[67].call(args, Integer.valueOf(-1));closure = (Closure)ScriptBytecodeAdapter.castToType(localObject1, Closure.class); Object + tmp202_197 = arrayOfCallSite[68].call(args, arrayOfCallSite[69].call(args, Integer.valueOf(-1)));args = (Object[])ScriptBytecodeAdapter.castToType(tmp202_197, [Ljava.lang.Object.class);tmp202_197; + } + } + else if ((BytecodeInterface8.objectArrayGet(args, Integer.valueOf(-1).intValue()) instanceof Closure)) { + Object localObject2 = BytecodeInterface8.objectArrayGet(args, Integer.valueOf(-1).intValue());closure = (Closure)ScriptBytecodeAdapter.castToType(localObject2, Closure.class); Object + tmp287_282 = arrayOfCallSite[70].call(args, BytecodeInterface8.objectArrayGet(args, Integer.valueOf(-1).intValue()));args = (Object[])ScriptBytecodeAdapter.castToType(tmp287_282, [Ljava.lang.Object.class);tmp287_282; } + Object localObject3; + Object localObject4; + if ((!BytecodeInterface8.isOrigInt()) || (!BytecodeInterface8.isOrigZ()) || (__$stMC) || (BytecodeInterface8.disabledStandardMetaClass())) { if (ScriptBytecodeAdapter.compareEqual(arrayOfCallSite[71].call(args), Integer.valueOf(1))) { + localObject3 = arrayOfCallSite[72].callCurrent(this, arrayOfCallSite[73].call(args, Integer.valueOf(0)));clazz = (Class)ShortTypeHandling.castToClass(localObject3); + } + } + else if (ScriptBytecodeAdapter.compareEqual(arrayOfCallSite[74].call(args), Integer.valueOf(1))) { + localObject4 = arrayOfCallSite[75].callCurrent(this, BytecodeInterface8.objectArrayGet(args, 0));clazz = (Class)ShortTypeHandling.castToClass(localObject4); } + Object localObject6; + Object localObject8; + if ((!BytecodeInterface8.isOrigInt()) || (!BytecodeInterface8.isOrigZ()) || (__$stMC) || (BytecodeInterface8.disabledStandardMetaClass())) { if (ScriptBytecodeAdapter.compareEqual(arrayOfCallSite[76].call(args), Integer.valueOf(2))) { + Object localObject5 = arrayOfCallSite[77].callCurrent(this, arrayOfCallSite[78].call(args, Integer.valueOf(0)));name = (String)ShortTypeHandling.castToString(localObject5); + localObject6 = arrayOfCallSite[79].callCurrent(this, arrayOfCallSite[80].call(args, Integer.valueOf(1)));clazz = (Class)ShortTypeHandling.castToClass(localObject6); + } + } + else if (ScriptBytecodeAdapter.compareEqual(arrayOfCallSite[81].call(args), Integer.valueOf(2))) { + Object localObject7 = arrayOfCallSite[82].callCurrent(this, BytecodeInterface8.objectArrayGet(args, 0));name = (String)ShortTypeHandling.castToString(localObject7); + localObject8 = arrayOfCallSite[83].callCurrent(this, BytecodeInterface8.objectArrayGet(args, 1));clazz = (Class)ShortTypeHandling.castToClass(localObject8); + } + + return ScriptBytecodeAdapter.createList(new Object[] { name, clazz, closure });return null; + } + + public Class parseClassArgument(Object arg) { + CallSite[] arrayOfCallSite = $getCallSiteArray(); if ((arg instanceof Class)) { + return (Class)ShortTypeHandling.castToClass(arg); + } else if ((arg instanceof String)) { + return Class.forName((String)ShortTypeHandling.castToString(arg)); + } else { + arrayOfCallSite[84].callCurrent(this, new GStringImpl(new Object[] { arrayOfCallSite[85].callGetProperty(arrayOfCallSite[86].call(arg)) }, new String[] { "Unexpected argument type ", "" })); + return (Class)ShortTypeHandling.castToClass(null); } return null; + } + + public String parseNameArgument(Object arg) + { + CallSite[] arrayOfCallSite = $getCallSiteArray(); if ((arg instanceof String)) { + return (String)ShortTypeHandling.castToString(arg); + } else { + arrayOfCallSite[87].callCurrent(this, "With 2 or 3 arguments, the first argument must be the component name, i.e of type string"); + return (String)ShortTypeHandling.castToString(null); } return null; + } + + public String getComponentName() + { + CallSite[] arrayOfCallSite = $getCallSiteArray(); if (DefaultTypeTransformation.booleanUnbox(arrayOfCallSite[88].call(component, "name"))) { + return (String)ShortTypeHandling.castToString(new GStringImpl(new Object[] { arrayOfCallSite[89].callGetProperty(component) }, new String[] { "[", "]" })); + } else + return ""; return null; + } + + public final Object getComponent() + { + return component; + } + + public final List getFieldsToCascade() + { + return fieldsToCascade; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/gaffer/ConfigurationContributor.java b/src/minecraft/ch/qos/logback/classic/gaffer/ConfigurationContributor.java new file mode 100644 index 0000000..d1140a1 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/gaffer/ConfigurationContributor.java @@ -0,0 +1,8 @@ +package ch.qos.logback.classic.gaffer; + +import java.util.Map; + +public abstract interface ConfigurationContributor +{ + public abstract Map getMappings(); +} diff --git a/src/minecraft/ch/qos/logback/classic/gaffer/ConfigurationDelegate.java b/src/minecraft/ch/qos/logback/classic/gaffer/ConfigurationDelegate.java new file mode 100644 index 0000000..4a369b9 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/gaffer/ConfigurationDelegate.java @@ -0,0 +1,357 @@ +package ch.qos.logback.classic.gaffer; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.jmx.JMXConfigurator; +import ch.qos.logback.classic.jmx.MBeanUtil; +import ch.qos.logback.classic.net.ReceiverBase; +import ch.qos.logback.classic.turbo.ReconfigureOnChangeFilter; +import ch.qos.logback.classic.turbo.TurboFilter; +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.spi.ContextAware; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.spi.LifeCycle; +import ch.qos.logback.core.status.StatusListener; +import ch.qos.logback.core.util.CachingDateFormatter; +import ch.qos.logback.core.util.Duration; +import groovy.lang.Closure; +import groovy.lang.GroovyObject; +import groovy.lang.MetaClass; +import groovy.lang.Reference; +import java.lang.management.ManagementFactory; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import javax.management.MalformedObjectNameException; +import javax.management.ObjectName; +import org.codehaus.groovy.runtime.BytecodeInterface8; +import org.codehaus.groovy.runtime.GStringImpl; +import org.codehaus.groovy.runtime.GeneratedClosure; +import org.codehaus.groovy.runtime.ScriptBytecodeAdapter; +import org.codehaus.groovy.runtime.callsite.CallSite; +import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation; +import org.codehaus.groovy.runtime.typehandling.ShortTypeHandling; + +public class ConfigurationDelegate extends ContextAwareBase implements GroovyObject +{ + private List appenderList; + + public ConfigurationDelegate() + { + ConfigurationDelegate this; + CallSite[] arrayOfCallSite = $getCallSiteArray();List localList = ScriptBytecodeAdapter.createList(new Object[0]);appenderList = localList;MetaClass localMetaClass = $getStaticMetaClass();metaClass = localMetaClass; + } + + public Object getDeclaredOrigin() { CallSite[] arrayOfCallSite = $getCallSiteArray();return this;return null; + } + + + + public void scan(String scanPeriodStr) + { + CallSite[] arrayOfCallSite = $getCallSiteArray();ReconfigureOnChangeFilter rocf = (ReconfigureOnChangeFilter)ScriptBytecodeAdapter.castToType(arrayOfCallSite[0].callConstructor(ReconfigureOnChangeFilter.class), ReconfigureOnChangeFilter.class); + arrayOfCallSite[1].call(rocf, arrayOfCallSite[2].callGroovyObjectGetProperty(this)); + if (DefaultTypeTransformation.booleanUnbox(scanPeriodStr)) + try { + try { Duration duration = (Duration)ScriptBytecodeAdapter.castToType(arrayOfCallSite[3].call(Duration.class, scanPeriodStr), Duration.class); + arrayOfCallSite[4].call(rocf, arrayOfCallSite[5].call(duration)); + arrayOfCallSite[6].callCurrent(this, arrayOfCallSite[7].call("Setting ReconfigureOnChangeFilter scanning period to ", duration)); + } + catch (NumberFormatException nfe) { + arrayOfCallSite[8].callCurrent(this, arrayOfCallSite[9].call(arrayOfCallSite[10].call("Error while converting [", arrayOfCallSite[11].callGroovyObjectGetProperty(this)), "] to long"), nfe); + } + } finally {} + arrayOfCallSite[12].call(rocf); + arrayOfCallSite[13].callCurrent(this, "Adding ReconfigureOnChangeFilter as a turbo filter"); + arrayOfCallSite[14].call(arrayOfCallSite[15].callGroovyObjectGetProperty(this), rocf); + } + + public void statusListener(Class listenerClass) { + CallSite[] arrayOfCallSite = $getCallSiteArray();StatusListener statusListener = (StatusListener)ScriptBytecodeAdapter.castToType(arrayOfCallSite[16].call(listenerClass), StatusListener.class); + arrayOfCallSite[17].call(arrayOfCallSite[18].callGetProperty(arrayOfCallSite[19].callGroovyObjectGetProperty(this)), statusListener); + if ((statusListener instanceof ContextAware)) { + arrayOfCallSite[20].call((ContextAware)ScriptBytecodeAdapter.castToType(statusListener, ContextAware.class), arrayOfCallSite[21].callGroovyObjectGetProperty(this)); + } + if ((statusListener instanceof LifeCycle)) { + arrayOfCallSite[22].call((LifeCycle)ScriptBytecodeAdapter.castToType(statusListener, LifeCycle.class)); + } + arrayOfCallSite[23].callCurrent(this, new GStringImpl(new Object[] { arrayOfCallSite[24].callGetProperty(listenerClass) }, new String[] { "Added status listener of type [", "]" })); + } + + public void conversionRule(String conversionWord, Class converterClass) { + CallSite[] arrayOfCallSite = $getCallSiteArray();String converterClassName = (String)ShortTypeHandling.castToString(arrayOfCallSite[25].call(converterClass)); + + Map ruleRegistry = (Map)ScriptBytecodeAdapter.castToType(arrayOfCallSite[26].call(arrayOfCallSite[27].callGroovyObjectGetProperty(this), arrayOfCallSite[28].callGetProperty(CoreConstants.class)), Map.class); + if (ScriptBytecodeAdapter.compareEqual(ruleRegistry, null)) { + Object localObject = arrayOfCallSite[29].callConstructor(HashMap.class);ruleRegistry = (Map)ScriptBytecodeAdapter.castToType(localObject, Map.class); + arrayOfCallSite[30].call(arrayOfCallSite[31].callGroovyObjectGetProperty(this), arrayOfCallSite[32].callGetProperty(CoreConstants.class), ruleRegistry); + } + + arrayOfCallSite[33].callCurrent(this, arrayOfCallSite[34].call(arrayOfCallSite[35].call(arrayOfCallSite[36].call(arrayOfCallSite[37].call("registering conversion word ", conversionWord), " with class ["), converterClassName), "]")); + arrayOfCallSite[38].call(ruleRegistry, conversionWord, converterClassName); + } + + public void root(Level level) { CallSite[] arrayOfCallSite = $getCallSiteArray();root(level, ScriptBytecodeAdapter.createList(new Object[0]));null; } + public void root(Level level, List appenderNames) { CallSite[] arrayOfCallSite = $getCallSiteArray(); if (ScriptBytecodeAdapter.compareEqual(level, null)) { + arrayOfCallSite[39].callCurrent(this, "Root logger cannot be set to level null"); + } else + arrayOfCallSite[40].callCurrent(this, arrayOfCallSite[41].callGetProperty(org.slf4j.Logger.class), level, appenderNames); + } + + public void logger(String name, Level level) { + CallSite[] arrayOfCallSite = $getCallSiteArray();logger(name, level, ScriptBytecodeAdapter.createList(new Object[0]), null);null; + } + + class _logger_closure1 extends Closure implements GeneratedClosure { + public _logger_closure1(Object _thisObject, Reference aName) { super(_thisObject); + Reference localReference = aName; + this.aName = localReference; + } + + public Object doCall(Object it) { CallSite[] arrayOfCallSite = $getCallSiteArray();return Boolean.valueOf(ScriptBytecodeAdapter.compareEqual(arrayOfCallSite[0].callGetProperty(it), aName.get()));return null; + } + + public Object getaName() + { + CallSite[] arrayOfCallSite = $getCallSiteArray(); + return aName.get(); + return null; + } + } + + public void logger(String name, Level level, List appenderNames, Boolean additivity) + { + CallSite[] arrayOfCallSite = $getCallSiteArray(); Boolean localBoolean; if (DefaultTypeTransformation.booleanUnbox(name)) { + ch.qos.logback.classic.Logger logger = (ch.qos.logback.classic.Logger)ScriptBytecodeAdapter.castToType(arrayOfCallSite[42].call((LoggerContext)ScriptBytecodeAdapter.castToType(arrayOfCallSite[43].callGroovyObjectGetProperty(this), LoggerContext.class), name), ch.qos.logback.classic.Logger.class); + arrayOfCallSite[44].callCurrent(this, arrayOfCallSite[45].call(new GStringImpl(new Object[] { name }, new String[] { "Setting level of logger [", "] to " }), level)); + Level localLevel = level;ScriptBytecodeAdapter.setProperty(localLevel, null, logger, "level"); + + Reference aName = new Reference(null); for (Iterator localIterator = (Iterator)ScriptBytecodeAdapter.castToType(arrayOfCallSite[46].call(appenderNames), Iterator.class); localIterator.hasNext();) { ((Reference)aName).set(localIterator.next()); + Appender appender = (Appender)ScriptBytecodeAdapter.castToType(arrayOfCallSite[47].call(appenderList, new _logger_closure1(this, aName)), Appender.class); + if (ScriptBytecodeAdapter.compareNotEqual(appender, null)) { + arrayOfCallSite[48].callCurrent(this, arrayOfCallSite[49].call(new GStringImpl(new Object[] { aName.get() }, new String[] { "Attaching appender named [", "] to " }), logger)); + arrayOfCallSite[50].call(logger, appender); + } else { + arrayOfCallSite[51].callCurrent(this, new GStringImpl(new Object[] { aName.get() }, new String[] { "Failed to find appender named [", "]" })); + } + } + + if (ScriptBytecodeAdapter.compareNotEqual(additivity, null)) { + localBoolean = additivity;ScriptBytecodeAdapter.setProperty(localBoolean, null, logger, "additive"); + } + } else { + arrayOfCallSite[52].callCurrent(this, "No name attribute for logger"); + } + } + + public void appender(String name, Class clazz, Closure closure) { + CallSite[] arrayOfCallSite = $getCallSiteArray();arrayOfCallSite[53].callCurrent(this, arrayOfCallSite[54].call(arrayOfCallSite[55].call("About to instantiate appender of type [", arrayOfCallSite[56].callGetProperty(clazz)), "]")); + Appender appender = (Appender)ScriptBytecodeAdapter.castToType(arrayOfCallSite[57].call(clazz), Appender.class); + arrayOfCallSite[58].callCurrent(this, arrayOfCallSite[59].call(arrayOfCallSite[60].call("Naming appender as [", name), "]")); + String str = name;ScriptBytecodeAdapter.setProperty(str, null, appender, "name"); + Object localObject1 = arrayOfCallSite[61].callGroovyObjectGetProperty(this);ScriptBytecodeAdapter.setProperty(localObject1, null, appender, "context"); + arrayOfCallSite[62].call(appenderList, appender); + if (ScriptBytecodeAdapter.compareNotEqual(closure, null)) { + AppenderDelegate ad = (AppenderDelegate)ScriptBytecodeAdapter.castToType(arrayOfCallSite[63].callConstructor(AppenderDelegate.class, appender, appenderList), AppenderDelegate.class); + arrayOfCallSite[64].callCurrent(this, ad, appender); + Object localObject2 = arrayOfCallSite[65].callGroovyObjectGetProperty(this);ScriptBytecodeAdapter.setGroovyObjectProperty(localObject2, ConfigurationDelegate.class, ad, "context"); + AppenderDelegate localAppenderDelegate1 = ad;ScriptBytecodeAdapter.setGroovyObjectProperty(localAppenderDelegate1, ConfigurationDelegate.class, closure, "delegate"); + Object localObject3 = arrayOfCallSite[66].callGetProperty(Closure.class);ScriptBytecodeAdapter.setGroovyObjectProperty(localObject3, ConfigurationDelegate.class, closure, "resolveStrategy"); + arrayOfCallSite[67].call(closure); + } + try { + try { arrayOfCallSite[68].call(appender); + } catch (RuntimeException e) { + arrayOfCallSite[69].callCurrent(this, arrayOfCallSite[70].call(arrayOfCallSite[71].call("Failed to start apppender named [", name), "]"), e); + } + } finally {} + } + + public void receiver(String name, Class aClass, Closure closure) { CallSite[] arrayOfCallSite = $getCallSiteArray();arrayOfCallSite[72].callCurrent(this, arrayOfCallSite[73].call(arrayOfCallSite[74].call("About to instantiate receiver of type [", arrayOfCallSite[75].callGetProperty(arrayOfCallSite[76].callGroovyObjectGetProperty(this))), "]")); + ReceiverBase receiver = (ReceiverBase)ScriptBytecodeAdapter.castToType(arrayOfCallSite[77].call(aClass), ReceiverBase.class); + Object localObject1 = arrayOfCallSite[78].callGroovyObjectGetProperty(this);ScriptBytecodeAdapter.setProperty(localObject1, null, receiver, "context"); + if (ScriptBytecodeAdapter.compareNotEqual(closure, null)) { + ComponentDelegate componentDelegate = (ComponentDelegate)ScriptBytecodeAdapter.castToType(arrayOfCallSite[79].callConstructor(ComponentDelegate.class, receiver), ComponentDelegate.class); + Object localObject2 = arrayOfCallSite[80].callGroovyObjectGetProperty(this);ScriptBytecodeAdapter.setGroovyObjectProperty(localObject2, ConfigurationDelegate.class, componentDelegate, "context"); + ComponentDelegate localComponentDelegate1 = componentDelegate;ScriptBytecodeAdapter.setGroovyObjectProperty(localComponentDelegate1, ConfigurationDelegate.class, closure, "delegate"); + Object localObject3 = arrayOfCallSite[81].callGetProperty(Closure.class);ScriptBytecodeAdapter.setGroovyObjectProperty(localObject3, ConfigurationDelegate.class, closure, "resolveStrategy"); + arrayOfCallSite[82].call(closure); + } + try { + try { arrayOfCallSite[83].call(receiver); + } catch (RuntimeException e) { + arrayOfCallSite[84].callCurrent(this, arrayOfCallSite[85].call(arrayOfCallSite[86].call("Failed to start receiver of type [", arrayOfCallSite[87].call(aClass)), "]"), e); + } + } finally {} + } + + private void copyContributions(AppenderDelegate appenderDelegate, Appender appender) { Reference appenderDelegate = new Reference(appenderDelegate);Reference appender = new Reference(appender);CallSite[] arrayOfCallSite = $getCallSiteArray(); if (((Appender)appender.get() instanceof ConfigurationContributor)) { + ConfigurationContributor cc = (ConfigurationContributor)ScriptBytecodeAdapter.castToType((Appender)appender.get(), ConfigurationContributor.class); + arrayOfCallSite[88].call(arrayOfCallSite[89].call(cc), new _copyContributions_closure2(this, appenderDelegate, appender)); } } + class _copyContributions_closure2 extends Closure implements GeneratedClosure { public _copyContributions_closure2(Object _thisObject, Reference appenderDelegate, Reference appender) { super(_thisObject); + Reference localReference1 = appenderDelegate; + this.appenderDelegate = localReference1; + Reference localReference2 = appender; + this.appender = localReference2; } public Object doCall(Object oldName, Object newName) { CallSite[] arrayOfCallSite = $getCallSiteArray();Closure localClosure = ScriptBytecodeAdapter.getMethodPointer(appender.get(), (String)ShortTypeHandling.castToString(new GStringImpl(new Object[] { oldName }, new String[] { "", "" })));ScriptBytecodeAdapter.setProperty(localClosure, null, arrayOfCallSite[0].callGroovyObjectGetProperty(appenderDelegate.get()), (String)ShortTypeHandling.castToString(new GStringImpl(new Object[] { newName }, new String[] { "", "" })));return localClosure;return null; } + + public Object call(Object oldName, Object newName) { CallSite[] arrayOfCallSite = $getCallSiteArray(); + return arrayOfCallSite[1].callCurrent(this, oldName, newName); + return null; } + + public AppenderDelegate getAppenderDelegate() { CallSite[] arrayOfCallSite = $getCallSiteArray(); + return (AppenderDelegate)ScriptBytecodeAdapter.castToType(appenderDelegate.get(), AppenderDelegate.class); + return null; } + public Appender getAppender() { CallSite[] arrayOfCallSite = $getCallSiteArray(); + return (Appender)ScriptBytecodeAdapter.castToType(appender.get(), Appender.class); + return null; } } + public void turboFilter(Class clazz, Closure closure) { CallSite[] arrayOfCallSite = $getCallSiteArray();arrayOfCallSite[90].callCurrent(this, arrayOfCallSite[91].call(arrayOfCallSite[92].call("About to instantiate turboFilter of type [", arrayOfCallSite[93].callGetProperty(clazz)), "]")); + TurboFilter turboFilter = (TurboFilter)ScriptBytecodeAdapter.castToType(arrayOfCallSite[94].call(clazz), TurboFilter.class); + Object localObject1 = arrayOfCallSite[95].callGroovyObjectGetProperty(this);ScriptBytecodeAdapter.setProperty(localObject1, null, turboFilter, "context"); + + if (ScriptBytecodeAdapter.compareNotEqual(closure, null)) { + ComponentDelegate componentDelegate = (ComponentDelegate)ScriptBytecodeAdapter.castToType(arrayOfCallSite[96].callConstructor(ComponentDelegate.class, turboFilter), ComponentDelegate.class); + Object localObject2 = arrayOfCallSite[97].callGroovyObjectGetProperty(this);ScriptBytecodeAdapter.setGroovyObjectProperty(localObject2, ConfigurationDelegate.class, componentDelegate, "context"); + ComponentDelegate localComponentDelegate1 = componentDelegate;ScriptBytecodeAdapter.setGroovyObjectProperty(localComponentDelegate1, ConfigurationDelegate.class, closure, "delegate"); + Object localObject3 = arrayOfCallSite[98].callGetProperty(Closure.class);ScriptBytecodeAdapter.setGroovyObjectProperty(localObject3, ConfigurationDelegate.class, closure, "resolveStrategy"); + arrayOfCallSite[99].call(closure); + } + arrayOfCallSite[100].call(turboFilter); + arrayOfCallSite[101].callCurrent(this, "Adding aforementioned turbo filter to context"); + arrayOfCallSite[102].call(arrayOfCallSite[103].callGroovyObjectGetProperty(this), turboFilter); + } + + public String timestamp(String datePattern, long timeReference) { + CallSite[] arrayOfCallSite = $getCallSiteArray();long now = DefaultTypeTransformation.longUnbox(Integer.valueOf(-1)); + Object localObject; + if (ScriptBytecodeAdapter.compareEqual(Long.valueOf(timeReference), Integer.valueOf(-1))) { + arrayOfCallSite[104].callCurrent(this, "Using current interpretation time, i.e. now, as time reference."); + localObject = arrayOfCallSite[105].call(System.class);now = DefaultTypeTransformation.longUnbox(localObject); + } else { + long l1 = timeReference;now = l1; + arrayOfCallSite[106].callCurrent(this, arrayOfCallSite[107].call(arrayOfCallSite[108].call("Using ", Long.valueOf(now)), " as time reference.")); + } + CachingDateFormatter sdf = (CachingDateFormatter)ScriptBytecodeAdapter.castToType(arrayOfCallSite[109].callConstructor(CachingDateFormatter.class, datePattern), CachingDateFormatter.class); + return (String)ShortTypeHandling.castToString(arrayOfCallSite[110].call(sdf, Long.valueOf(now)));return null; + } + + + + + + + + public void jmxConfigurator(String name) + { + CallSite[] arrayOfCallSite = $getCallSiteArray();Object objectName = null; + Object contextName = arrayOfCallSite[111].callGetProperty(arrayOfCallSite[112].callGroovyObjectGetProperty(this)); + if (ScriptBytecodeAdapter.compareNotEqual(name, null)) + try { + String str; + try { localObject1 = arrayOfCallSite[113].callConstructor(ObjectName.class, name);objectName = localObject1; + } catch (MalformedObjectNameException e) { Object localObject1; + str = name;contextName = str; + } + } finally {} + if (ScriptBytecodeAdapter.compareEqual(objectName, null)) { + Object objectNameAsStr = arrayOfCallSite[114].call(MBeanUtil.class, contextName, JMXConfigurator.class); + Object localObject3 = arrayOfCallSite[115].call(MBeanUtil.class, arrayOfCallSite[116].callGroovyObjectGetProperty(this), this, objectNameAsStr);objectName = localObject3; + if (ScriptBytecodeAdapter.compareEqual(objectName, null)) { + arrayOfCallSite[117].callCurrent(this, new GStringImpl(new Object[] { objectNameAsStr }, new String[] { "Failed to construct ObjectName for [", "]" })); + return; + } + } + + Object platformMBeanServer = arrayOfCallSite[118].callGetProperty(ManagementFactory.class); + if ((!DefaultTypeTransformation.booleanUnbox(arrayOfCallSite[119].call(MBeanUtil.class, platformMBeanServer, objectName)) ? 1 : 0) != 0) { + JMXConfigurator jmxConfigurator = (JMXConfigurator)ScriptBytecodeAdapter.castToType(arrayOfCallSite[120].callConstructor(JMXConfigurator.class, ScriptBytecodeAdapter.createPojoWrapper((LoggerContext)ScriptBytecodeAdapter.castToType(arrayOfCallSite[121].callGroovyObjectGetProperty(this), LoggerContext.class), LoggerContext.class), platformMBeanServer, objectName), JMXConfigurator.class); + try { + try { arrayOfCallSite[122].call(platformMBeanServer, jmxConfigurator, objectName); + } catch (Exception all) { + arrayOfCallSite[123].callCurrent(this, "Failed to create mbean", all); + } + } + finally {} + } + } + + public void scan() + { + CallSite[] arrayOfCallSite = $getCallSiteArray(); + if ((__$stMC) || (BytecodeInterface8.disabledStandardMetaClass())) + { + scan(null); + null; + } + else + { + scan(null); + null; + } + } + + public void logger(String name, Level level, List appenderNames) + { + CallSite[] arrayOfCallSite = $getCallSiteArray(); + logger(name, level, appenderNames, null); + null; + } + + public void appender(String name, Class clazz) + { + CallSite[] arrayOfCallSite = $getCallSiteArray(); + appender(name, clazz, null); + null; + } + + public void receiver(String name, Class aClass) + { + CallSite[] arrayOfCallSite = $getCallSiteArray(); + receiver(name, aClass, null); + null; + } + + public void turboFilter(Class clazz) + { + CallSite[] arrayOfCallSite = $getCallSiteArray(); + turboFilter(clazz, null); + null; + } + + public String timestamp(String datePattern) + { + CallSite[] arrayOfCallSite = $getCallSiteArray(); + if ((__$stMC) || (BytecodeInterface8.disabledStandardMetaClass())) { + return timestamp(datePattern, DefaultTypeTransformation.longUnbox(Integer.valueOf(-1))); + } else { + return timestamp(datePattern, DefaultTypeTransformation.longUnbox(Integer.valueOf(-1))); + } + return null; + } + + public void jmxConfigurator() + { + CallSite[] arrayOfCallSite = $getCallSiteArray(); + if ((__$stMC) || (BytecodeInterface8.disabledStandardMetaClass())) + { + jmxConfigurator(null); + null; + } + else + { + jmxConfigurator(null); + null; + } + } + + public List getAppenderList() + { + return appenderList; + } + + public void setAppenderList(List paramList) + { + appenderList = paramList; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/gaffer/GafferConfigurator.java b/src/minecraft/ch/qos/logback/classic/gaffer/GafferConfigurator.java new file mode 100644 index 0000000..68aaec1 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/gaffer/GafferConfigurator.java @@ -0,0 +1,161 @@ +package ch.qos.logback.classic.gaffer; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.encoder.PatternLayoutEncoder; +import ch.qos.logback.core.joran.util.ConfigurationWatchListUtil; +import ch.qos.logback.core.status.OnConsoleStatusListener; +import ch.qos.logback.core.util.ContextUtil; +import groovy.lang.Binding; +import groovy.lang.Closure; +import groovy.lang.GroovyObject; +import groovy.lang.MetaClass; +import groovy.lang.Reference; +import groovy.lang.Script; +import java.io.File; +import java.net.URL; +import org.codehaus.groovy.control.CompilerConfiguration; +import org.codehaus.groovy.control.customizers.ImportCustomizer; +import org.codehaus.groovy.runtime.ArrayUtil; +import org.codehaus.groovy.runtime.BytecodeInterface8; +import org.codehaus.groovy.runtime.GStringImpl; +import org.codehaus.groovy.runtime.GeneratedClosure; +import org.codehaus.groovy.runtime.ScriptBytecodeAdapter; +import org.codehaus.groovy.runtime.callsite.CallSite; +import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation; + +public class GafferConfigurator implements GroovyObject +{ + private LoggerContext context; + private static final String DEBUG_SYSTEM_PROPERTY_KEY = "logback.debug"; + + public GafferConfigurator(LoggerContext arg1) + { + LoggerContext context; + CallSite[] arrayOfCallSite = $getCallSiteArray();MetaClass localMetaClass = $getStaticMetaClass();metaClass = localMetaClass;LoggerContext localLoggerContext1 = context;this.context = ((LoggerContext)ScriptBytecodeAdapter.castToType(localLoggerContext1, LoggerContext.class)); + } + + protected void informContextOfURLUsedForConfiguration(URL url) { + CallSite[] arrayOfCallSite = $getCallSiteArray();arrayOfCallSite[0].call(ConfigurationWatchListUtil.class, context, url); + } + + public void run(URL url) { + CallSite[] arrayOfCallSite = $getCallSiteArray(); if ((__$stMC) || (BytecodeInterface8.disabledStandardMetaClass())) { arrayOfCallSite[1].callCurrent(this, url); } else { informContextOfURLUsedForConfiguration(url);null; } + arrayOfCallSite[2].callCurrent(this, arrayOfCallSite[3].callGetProperty(url)); + } + + public void run(File file) { + CallSite[] arrayOfCallSite = $getCallSiteArray();arrayOfCallSite[4].callCurrent(this, arrayOfCallSite[5].call(arrayOfCallSite[6].call(file))); + arrayOfCallSite[7].callCurrent(this, arrayOfCallSite[8].callGetProperty(file)); + } + + + + + + + + class _run_closure1 + extends Closure + implements GeneratedClosure + { + public _run_closure1(Object _thisObject, Reference dslScript) + { + super(_thisObject); + Reference localReference = dslScript; + this.dslScript = localReference; + } + + + + + + + + public Object doCall(Object it) + { + CallSite[] arrayOfCallSite = $getCallSiteArray();return dslScript.get();return null; + } + + public Script getDslScript() + { + CallSite[] arrayOfCallSite = $getCallSiteArray(); + return (Script)ScriptBytecodeAdapter.castToType(dslScript.get(), Script.class); + return null; + } + + public Object doCall() + { + CallSite[] arrayOfCallSite = $getCallSiteArray(); + return doCall(null); + return null; + } + } + + public void run(String dslText) + { + CallSite[] arrayOfCallSite = $getCallSiteArray();Binding binding = (Binding)ScriptBytecodeAdapter.castToType(arrayOfCallSite[9].callConstructor(Binding.class), Binding.class); + arrayOfCallSite[10].call(binding, "hostname", arrayOfCallSite[11].callGetProperty(ContextUtil.class)); + + Object configuration = arrayOfCallSite[12].callConstructor(CompilerConfiguration.class); + if ((__$stMC) || (BytecodeInterface8.disabledStandardMetaClass())) arrayOfCallSite[13].call(configuration, arrayOfCallSite[14].callCurrent(this)); else { arrayOfCallSite[15].call(configuration, importCustomizer()); + } + String debugAttrib = (String)org.codehaus.groovy.runtime.typehandling.ShortTypeHandling.castToString(arrayOfCallSite[16].call(System.class, DEBUG_SYSTEM_PROPERTY_KEY)); + if (((DefaultTypeTransformation.booleanUnbox(arrayOfCallSite[17].call(ch.qos.logback.core.util.OptionHelper.class, debugAttrib))) || (DefaultTypeTransformation.booleanUnbox(arrayOfCallSite[18].call(debugAttrib, "false"))) ? 1 : 0) == 0) {} + if ((DefaultTypeTransformation.booleanUnbox(arrayOfCallSite[19].call(debugAttrib, "null")) ? 1 : 0) == 0) + { + + + arrayOfCallSite[20].call(OnConsoleStatusListener.class, context); + } + + + arrayOfCallSite[21].call(arrayOfCallSite[22].callConstructor(ContextUtil.class, context), arrayOfCallSite[23].call(context)); + + Reference dslScript = new Reference((Script)ScriptBytecodeAdapter.castToType(arrayOfCallSite[24].call(arrayOfCallSite[25].callConstructor(groovy.lang.GroovyShell.class, binding, configuration), dslText), Script.class)); + + arrayOfCallSite[26].call(arrayOfCallSite[27].callGroovyObjectGetProperty((Script)dslScript.get()), ConfigurationDelegate.class); + arrayOfCallSite[28].call((Script)dslScript.get(), context); + _run_closure1 local_run_closure1 = new _run_closure1(this, dslScript);ScriptBytecodeAdapter.setProperty(local_run_closure1, null, arrayOfCallSite[29].callGroovyObjectGetProperty((Script)dslScript.get()), "getDeclaredOrigin"); + + arrayOfCallSite[30].call((Script)dslScript.get()); + } + + protected ImportCustomizer importCustomizer() { + CallSite[] arrayOfCallSite = $getCallSiteArray();Object customizer = arrayOfCallSite[31].callConstructor(ImportCustomizer.class); + + + Object core = "ch.qos.logback.core"; + arrayOfCallSite[32].call(customizer, ArrayUtil.createArray(core, new GStringImpl(new Object[] { core }, new String[] { "", ".encoder" }), new GStringImpl(new Object[] { core }, new String[] { "", ".read" }), new GStringImpl(new Object[] { core }, new String[] { "", ".rolling" }), new GStringImpl(new Object[] { core }, new String[] { "", ".status" }), "ch.qos.logback.classic.net")); + + + arrayOfCallSite[33].call(customizer, arrayOfCallSite[34].callGetProperty(PatternLayoutEncoder.class)); + + arrayOfCallSite[35].call(customizer, arrayOfCallSite[36].callGetProperty(Level.class)); + + arrayOfCallSite[37].call(customizer, "off", arrayOfCallSite[38].callGetProperty(Level.class), "OFF"); + arrayOfCallSite[39].call(customizer, "error", arrayOfCallSite[40].callGetProperty(Level.class), "ERROR"); + arrayOfCallSite[41].call(customizer, "warn", arrayOfCallSite[42].callGetProperty(Level.class), "WARN"); + arrayOfCallSite[43].call(customizer, "info", arrayOfCallSite[44].callGetProperty(Level.class), "INFO"); + arrayOfCallSite[45].call(customizer, "debug", arrayOfCallSite[46].callGetProperty(Level.class), "DEBUG"); + arrayOfCallSite[47].call(customizer, "trace", arrayOfCallSite[48].callGetProperty(Level.class), "TRACE"); + arrayOfCallSite[49].call(customizer, "all", arrayOfCallSite[50].callGetProperty(Level.class), "ALL"); + + return (ImportCustomizer)ScriptBytecodeAdapter.castToType(customizer, ImportCustomizer.class);return null; + } + + public LoggerContext getContext() + { + return context; + } + + public void setContext(LoggerContext paramLoggerContext) + { + context = paramLoggerContext; + } + + public static final String getDEBUG_SYSTEM_PROPERTY_KEY() + { + return DEBUG_SYSTEM_PROPERTY_KEY; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/gaffer/GafferUtil.java b/src/minecraft/ch/qos/logback/classic/gaffer/GafferUtil.java new file mode 100644 index 0000000..7d97f8b --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/gaffer/GafferUtil.java @@ -0,0 +1,78 @@ +package ch.qos.logback.classic.gaffer; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.core.status.ErrorStatus; +import ch.qos.logback.core.status.StatusManager; +import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.net.URL; + + + + + + + + + + + + + + + + + +public class GafferUtil +{ + public GafferUtil() {} + + private static String ERROR_MSG = "Failed to instantiate ch.qos.logback.classic.gaffer.GafferConfigurator"; + + public static void runGafferConfiguratorOn(LoggerContext loggerContext, Object origin, File configFile) { + GafferConfigurator gafferConfigurator = newGafferConfiguratorInstance(loggerContext, origin); + if (gafferConfigurator != null) { + gafferConfigurator.run(configFile); + } + } + + public static void runGafferConfiguratorOn(LoggerContext loggerContext, Object origin, URL configFile) { + GafferConfigurator gafferConfigurator = newGafferConfiguratorInstance(loggerContext, origin); + if (gafferConfigurator != null) { + gafferConfigurator.run(configFile); + } + } + + private static GafferConfigurator newGafferConfiguratorInstance(LoggerContext loggerContext, Object origin) + { + try { + Class gcClass = Class.forName("ch.qos.logback.classic.gaffer.GafferConfigurator"); + Constructor c = gcClass.getConstructor(new Class[] { LoggerContext.class }); + return (GafferConfigurator)c.newInstance(new Object[] { loggerContext }); + } catch (ClassNotFoundException e) { + addError(loggerContext, origin, ERROR_MSG, e); + } catch (NoSuchMethodException e) { + addError(loggerContext, origin, ERROR_MSG, e); + } catch (InvocationTargetException e) { + addError(loggerContext, origin, ERROR_MSG, e); + } catch (InstantiationException e) { + addError(loggerContext, origin, ERROR_MSG, e); + } catch (IllegalAccessException e) { + addError(loggerContext, origin, ERROR_MSG, e); + } + return null; + } + + private static void addError(LoggerContext context, Object origin, String msg) { + addError(context, origin, msg, null); + } + + private static void addError(LoggerContext context, Object origin, String msg, Throwable t) { + StatusManager sm = context.getStatusManager(); + if (sm == null) { + return; + } + sm.add(new ErrorStatus(msg, origin, t)); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/gaffer/NestingType.java b/src/minecraft/ch/qos/logback/classic/gaffer/NestingType.java new file mode 100644 index 0000000..6a6eef5 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/gaffer/NestingType.java @@ -0,0 +1,48 @@ +package ch.qos.logback.classic.gaffer; + +import groovy.lang.GroovyObject; +import groovy.lang.MetaClass; +import java.util.LinkedHashMap; +import org.codehaus.groovy.runtime.ScriptBytecodeAdapter; +import org.codehaus.groovy.runtime.callsite.CallSite; +import org.codehaus.groovy.runtime.typehandling.ShortTypeHandling; +import org.codehaus.groovy.transform.ImmutableASTTransformation; + +public enum NestingType + implements GroovyObject +{ + public static final NestingType MIN_VALUE; + public static final NestingType MAX_VALUE; + + public NestingType(LinkedHashMap __namedArgs) + { + MetaClass localMetaClass = $getStaticMetaClass(); + metaClass = localMetaClass; + if (ScriptBytecodeAdapter.compareEqual(__namedArgs, null)) { + throw ((Throwable)arrayOfCallSite[0].callConstructor(IllegalArgumentException.class, "One of the enum constants for enum ch.qos.logback.classic.gaffer.NestingType was initialized with null. Please use a non-null value or define your own constructor.")); + } else { + arrayOfCallSite[1].callStatic(ImmutableASTTransformation.class, this, __namedArgs); + } + } + + public NestingType() + { + this((LinkedHashMap)ScriptBytecodeAdapter.castToType(arrayOfCallSite[2].callConstructor(LinkedHashMap.class), LinkedHashMap.class)); + } + + static + { + Object localObject1 = $getCallSiteArray()[13].callStatic(NestingType.class, "NA", Integer.valueOf(0)); + NA = (NestingType)ShortTypeHandling.castToEnum(localObject1, NestingType.class); + Object localObject2 = $getCallSiteArray()[14].callStatic(NestingType.class, "SINGLE", Integer.valueOf(1)); + SINGLE = (NestingType)ShortTypeHandling.castToEnum(localObject2, NestingType.class); + Object localObject3 = $getCallSiteArray()[15].callStatic(NestingType.class, "AS_COLLECTION", Integer.valueOf(2)); + AS_COLLECTION = (NestingType)ShortTypeHandling.castToEnum(localObject3, NestingType.class); + NestingType localNestingType1 = NA; + MIN_VALUE = localNestingType1; + NestingType localNestingType2 = AS_COLLECTION; + MAX_VALUE = localNestingType2; + NestingType[] arrayOfNestingType = { NA, SINGLE, AS_COLLECTION }; + $VALUES = arrayOfNestingType; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/gaffer/PropertyUtil.java b/src/minecraft/ch/qos/logback/classic/gaffer/PropertyUtil.java new file mode 100644 index 0000000..bedf9fb --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/gaffer/PropertyUtil.java @@ -0,0 +1,77 @@ +package ch.qos.logback.classic.gaffer; + +import groovy.lang.Closure; +import groovy.lang.GroovyObject; +import groovy.lang.MetaClass; +import java.beans.Introspector; +import org.codehaus.groovy.runtime.BytecodeInterface8; +import org.codehaus.groovy.runtime.GStringImpl; +import org.codehaus.groovy.runtime.GeneratedClosure; +import org.codehaus.groovy.runtime.ScriptBytecodeAdapter; +import org.codehaus.groovy.runtime.callsite.CallSite; +import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation; +import org.codehaus.groovy.runtime.typehandling.ShortTypeHandling; + +public class PropertyUtil implements GroovyObject +{ + public PropertyUtil() + { + PropertyUtil this; + CallSite[] arrayOfCallSite = $getCallSiteArray(); + MetaClass localMetaClass = $getStaticMetaClass(); + metaClass = localMetaClass; + } + + public static boolean hasAdderMethod(Object obj, String name) + { + CallSite[] arrayOfCallSite = $getCallSiteArray();String addMethod = null; GStringImpl localGStringImpl1; GStringImpl localGStringImpl2; if ((__$stMC) || (BytecodeInterface8.disabledStandardMetaClass())) { localGStringImpl1 = new GStringImpl(new Object[] { arrayOfCallSite[0].callStatic(PropertyUtil.class, name) }, new String[] { "add", "" });addMethod = (String)ShortTypeHandling.castToString(localGStringImpl1); } else { localGStringImpl2 = new GStringImpl(new Object[] { upperCaseFirstLetter(name) }, new String[] { "add", "" });addMethod = (String)ShortTypeHandling.castToString(localGStringImpl2); } + return DefaultTypeTransformation.booleanUnbox(arrayOfCallSite[1].call(arrayOfCallSite[2].callGetProperty(obj), obj, addMethod));return DefaultTypeTransformation.booleanUnbox(Integer.valueOf(0)); + } + + public static NestingType nestingType(Object obj, String name) { + CallSite[] arrayOfCallSite = $getCallSiteArray();Object decapitalizedName = arrayOfCallSite[3].call(Introspector.class, name); + if (DefaultTypeTransformation.booleanUnbox(arrayOfCallSite[4].call(obj, decapitalizedName))) { + return (NestingType)ShortTypeHandling.castToEnum(arrayOfCallSite[5].callGetProperty(NestingType.class), NestingType.class); + } + if (DefaultTypeTransformation.booleanUnbox(arrayOfCallSite[6].callStatic(PropertyUtil.class, obj, name))) { + return (NestingType)ShortTypeHandling.castToEnum(arrayOfCallSite[7].callGetProperty(NestingType.class), NestingType.class); + } + return (NestingType)ShortTypeHandling.castToEnum(arrayOfCallSite[8].callGetProperty(NestingType.class), NestingType.class);return null; + } + + public static void attach(NestingType nestingType, Object component, Object subComponent, String name) { + CallSite[] arrayOfCallSite = $getCallSiteArray();NestingType localNestingType = nestingType; + if (ScriptBytecodeAdapter.isCase(localNestingType, arrayOfCallSite[9].callGetProperty(NestingType.class))) { + Object localObject1 = arrayOfCallSite[10].call(Introspector.class, name);name = (String)ShortTypeHandling.castToString(localObject1); + Object localObject2 = subComponent;ScriptBytecodeAdapter.setProperty(localObject2, null, component, (String)ShortTypeHandling.castToString(new GStringImpl(new Object[] { name }, new String[] { "", "" }))); + return; + } else if (!ScriptBytecodeAdapter.isCase(localNestingType, arrayOfCallSite[11].callGetProperty(NestingType.class))) { return; } + String firstUpperName = (String)ShortTypeHandling.castToString(arrayOfCallSite[12].call(PropertyUtil.class, name)); + ScriptBytecodeAdapter.invokeMethodN(PropertyUtil.class, component, (String)ShortTypeHandling.castToString(new GStringImpl(new Object[] { firstUpperName }, new String[] { "add", "" })), new Object[] { subComponent }); + } + + + public static String transformFirstLetter(String s, Closure closure) + { + CallSite[] arrayOfCallSite = $getCallSiteArray(); if ((!BytecodeInterface8.isOrigInt()) || (!BytecodeInterface8.isOrigZ()) || (__$stMC) || (BytecodeInterface8.disabledStandardMetaClass())) { if (((ScriptBytecodeAdapter.compareEqual(s, null)) || (ScriptBytecodeAdapter.compareEqual(arrayOfCallSite[13].call(s), Integer.valueOf(0))) ? 1 : 0) != 0) { + return s; + } + } + else if (((ScriptBytecodeAdapter.compareEqual(s, null)) || (ScriptBytecodeAdapter.compareEqual(arrayOfCallSite[14].call(s), Integer.valueOf(0))) ? 1 : 0) != 0) { + return s; + } + String firstLetter = (String)ShortTypeHandling.castToString(arrayOfCallSite[15].callConstructor(String.class, arrayOfCallSite[16].call(s, Integer.valueOf(0)))); + + String modifiedFistLetter = (String)ShortTypeHandling.castToString(arrayOfCallSite[17].call(closure, firstLetter)); + + if (ScriptBytecodeAdapter.compareEqual(arrayOfCallSite[18].call(s), Integer.valueOf(1))) { + return modifiedFistLetter; + } else + return (String)ShortTypeHandling.castToString(arrayOfCallSite[19].call(modifiedFistLetter, arrayOfCallSite[20].call(s, Integer.valueOf(1)))); return null; + } + + class _upperCaseFirstLetter_closure1 extends Closure implements GeneratedClosure { public _upperCaseFirstLetter_closure1(Object _thisObject) { super(_thisObject); } + + public Object doCall(String it) { CallSite[] arrayOfCallSite = $getCallSiteArray();return arrayOfCallSite[0].call(it);return null; } public Object call(String it) { CallSite[] arrayOfCallSite = $getCallSiteArray(); if ((__$stMC) || (BytecodeInterface8.disabledStandardMetaClass())) return arrayOfCallSite[1].callCurrent(this, it); else return doCall(it); return null; } } public static String upperCaseFirstLetter(String s) { CallSite[] arrayOfCallSite = $getCallSiteArray();return (String)ShortTypeHandling.castToString(arrayOfCallSite[21].callStatic(PropertyUtil.class, s, new _upperCaseFirstLetter_closure1(PropertyUtil.class, PropertyUtil.class)));return null; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/helpers/MDCInsertingServletFilter.java b/src/minecraft/ch/qos/logback/classic/helpers/MDCInsertingServletFilter.java new file mode 100644 index 0000000..59ee35c --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/helpers/MDCInsertingServletFilter.java @@ -0,0 +1,94 @@ +package ch.qos.logback.classic.helpers; + +import java.io.IOException; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import org.slf4j.MDC; + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class MDCInsertingServletFilter + implements Filter +{ + public MDCInsertingServletFilter() {} + + public void destroy() {} + + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException + { + insertIntoMDC(request); + try { + chain.doFilter(request, response); + } finally { + clearMDC(); + } + } + + void insertIntoMDC(ServletRequest request) + { + MDC.put("req.remoteHost", request.getRemoteHost()); + + + if ((request instanceof HttpServletRequest)) { + HttpServletRequest httpServletRequest = (HttpServletRequest)request; + MDC.put("req.requestURI", httpServletRequest.getRequestURI()); + + StringBuffer requestURL = httpServletRequest.getRequestURL(); + if (requestURL != null) { + MDC.put("req.requestURL", requestURL.toString()); + } + MDC.put("req.method", httpServletRequest.getMethod()); + MDC.put("req.queryString", httpServletRequest.getQueryString()); + MDC.put("req.userAgent", httpServletRequest.getHeader("User-Agent")); + + MDC.put("req.xForwardedFor", httpServletRequest.getHeader("X-Forwarded-For")); + } + } + + + void clearMDC() + { + MDC.remove("req.remoteHost"); + MDC.remove("req.requestURI"); + MDC.remove("req.queryString"); + + MDC.remove("req.requestURL"); + MDC.remove("req.method"); + MDC.remove("req.userAgent"); + MDC.remove("req.xForwardedFor"); + } + + public void init(FilterConfig arg0) + throws ServletException + {} +} diff --git a/src/minecraft/ch/qos/logback/classic/html/DefaultCssBuilder.java b/src/minecraft/ch/qos/logback/classic/html/DefaultCssBuilder.java new file mode 100644 index 0000000..bc3f30d --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/html/DefaultCssBuilder.java @@ -0,0 +1,75 @@ +package ch.qos.logback.classic.html; + +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.html.CssBuilder; + + + + + + + + + + + + + + + + + + + +public class DefaultCssBuilder + implements CssBuilder +{ + public DefaultCssBuilder() {} + + public void addCss(StringBuilder sbuf) + { + sbuf.append(""); + sbuf.append(CoreConstants.LINE_SEPARATOR); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/html/DefaultThrowableRenderer.java b/src/minecraft/ch/qos/logback/classic/html/DefaultThrowableRenderer.java new file mode 100644 index 0000000..fc24070 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/html/DefaultThrowableRenderer.java @@ -0,0 +1,67 @@ +package ch.qos.logback.classic.html; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.IThrowableProxy; +import ch.qos.logback.classic.spi.StackTraceElementProxy; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.helpers.Transform; +import ch.qos.logback.core.html.IThrowableRenderer; + + + + + + + + + + + +public class DefaultThrowableRenderer + implements IThrowableRenderer +{ + static final String TRACE_PREFIX = "
    "; + + public DefaultThrowableRenderer() {} + + public void render(StringBuilder sbuf, ILoggingEvent event) + { + IThrowableProxy tp = event.getThrowableProxy(); + sbuf.append(""); + while (tp != null) { + render(sbuf, tp); + tp = tp.getCause(); + } + sbuf.append(""); + } + + void render(StringBuilder sbuf, IThrowableProxy tp) { + printFirstLine(sbuf, tp); + + int commonFrames = tp.getCommonFrames(); + StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray(); + + for (int i = 0; i < stepArray.length - commonFrames; i++) { + StackTraceElementProxy step = stepArray[i]; + sbuf.append("
    "); + sbuf.append(Transform.escapeTags(step.toString())); + sbuf.append(CoreConstants.LINE_SEPARATOR); + } + + if (commonFrames > 0) { + sbuf.append("
    "); + sbuf.append("\t... ").append(commonFrames).append(" common frames omitted").append(CoreConstants.LINE_SEPARATOR); + } + } + + public void printFirstLine(StringBuilder sb, IThrowableProxy tp) + { + int commonFrames = tp.getCommonFrames(); + if (commonFrames > 0) { + sb.append("
").append("Caused by: "); + } + sb.append(tp.getClassName()).append(": ").append(Transform.escapeTags(tp.getMessage())); + + sb.append(CoreConstants.LINE_SEPARATOR); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/html/HTMLLayout.java b/src/minecraft/ch/qos/logback/classic/html/HTMLLayout.java new file mode 100644 index 0000000..f052af9 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/html/HTMLLayout.java @@ -0,0 +1,142 @@ +package ch.qos.logback.classic.html; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.PatternLayout; +import ch.qos.logback.classic.pattern.MDCConverter; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.helpers.Transform; +import ch.qos.logback.core.html.HTMLLayoutBase; +import ch.qos.logback.core.html.IThrowableRenderer; +import ch.qos.logback.core.pattern.Converter; +import java.util.Map; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class HTMLLayout + extends HTMLLayoutBase +{ + static final String DEFAULT_CONVERSION_PATTERN = "%date%thread%level%logger%mdc%msg"; + IThrowableRenderer throwableRenderer; + + public HTMLLayout() + { + pattern = "%date%thread%level%logger%mdc%msg"; + throwableRenderer = new DefaultThrowableRenderer(); + cssBuilder = new DefaultCssBuilder(); + } + + public void start() + { + int errorCount = 0; + if (throwableRenderer == null) { + addError("ThrowableRender cannot be null."); + errorCount++; + } + if (errorCount == 0) { + super.start(); + } + } + + protected Map getDefaultConverterMap() { + return PatternLayout.defaultConverterMap; + } + + public String doLayout(ILoggingEvent event) { + StringBuilder buf = new StringBuilder(); + startNewTableIfLimitReached(buf); + + boolean odd = true; + if ((counter++ & 1L) == 0L) { + odd = false; + } + + String level = event.getLevel().toString().toLowerCase(); + + buf.append(CoreConstants.LINE_SEPARATOR); + buf.append(""); + } else { + buf.append(" even\">"); + } + buf.append(CoreConstants.LINE_SEPARATOR); + + Converter c = head; + while (c != null) { + appendEventToBuffer(buf, c, event); + c = c.getNext(); + } + buf.append(""); + buf.append(CoreConstants.LINE_SEPARATOR); + + if (event.getThrowableProxy() != null) { + throwableRenderer.render(buf, event); + } + return buf.toString(); + } + + private void appendEventToBuffer(StringBuilder buf, Converter c, ILoggingEvent event) + { + buf.append(""); + buf.append(Transform.escapeTags(c.convert(event))); + buf.append(""); + buf.append(CoreConstants.LINE_SEPARATOR); + } + + public IThrowableRenderer getThrowableRenderer() { + return throwableRenderer; + } + + public void setThrowableRenderer(IThrowableRenderer throwableRenderer) { + this.throwableRenderer = throwableRenderer; + } + + protected String computeConverterName(Converter c) + { + if ((c instanceof MDCConverter)) { + MDCConverter mc = (MDCConverter)c; + String key = mc.getFirstOption(); + if (key != null) { + return key; + } + return "MDC"; + } + + return super.computeConverterName(c); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/html/UrlCssBuilder.java b/src/minecraft/ch/qos/logback/classic/html/UrlCssBuilder.java new file mode 100644 index 0000000..52e8457 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/html/UrlCssBuilder.java @@ -0,0 +1,43 @@ +package ch.qos.logback.classic.html; + +import ch.qos.logback.core.html.CssBuilder; + + + + + + + + + + + + + + + + + + + +public class UrlCssBuilder + implements CssBuilder +{ + public UrlCssBuilder() {} + + String url = "http://logback.qos.ch/css/classic.css"; + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public void addCss(StringBuilder sbuf) { + sbuf.append(""); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/jmx/JMXConfigurator.java b/src/minecraft/ch/qos/logback/classic/jmx/JMXConfigurator.java new file mode 100644 index 0000000..131d4f1 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/jmx/JMXConfigurator.java @@ -0,0 +1,300 @@ +package ch.qos.logback.classic.jmx; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.classic.spi.LoggerContextListener; +import ch.qos.logback.classic.util.ContextInitializer; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.status.StatusListener; +import ch.qos.logback.core.status.StatusListenerAsList; +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.util.StatusPrinter; +import java.io.File; +import java.io.FileNotFoundException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import javax.management.InstanceNotFoundException; +import javax.management.MBeanRegistrationException; +import javax.management.MBeanServer; +import javax.management.ObjectName; + + + + + + + + + + + + + + + + + + + + + + + + +public class JMXConfigurator + extends ContextAwareBase + implements JMXConfiguratorMBean, LoggerContextListener +{ + private static String EMPTY = ""; + + LoggerContext loggerContext; + + MBeanServer mbs; + + ObjectName objectName; + + String objectNameAsString; + boolean debug = true; + + boolean started; + + public JMXConfigurator(LoggerContext loggerContext, MBeanServer mbs, ObjectName objectName) + { + started = true; + context = loggerContext; + this.loggerContext = loggerContext; + this.mbs = mbs; + this.objectName = objectName; + objectNameAsString = objectName.toString(); + if (previouslyRegisteredListenerWithSameObjectName()) { + addError("Previously registered JMXConfigurator named [" + objectNameAsString + "] in the logger context named [" + loggerContext.getName() + "]"); + + } + else + { + loggerContext.addListener(this); + } + } + + private boolean previouslyRegisteredListenerWithSameObjectName() { + List lcll = loggerContext.getCopyOfListenerList(); + for (LoggerContextListener lcl : lcll) { + if ((lcl instanceof JMXConfigurator)) { + JMXConfigurator jmxConfigurator = (JMXConfigurator)lcl; + if (objectName.equals(objectName)) { + return true; + } + } + } + return false; + } + + public void reloadDefaultConfiguration() throws JoranException { + ContextInitializer ci = new ContextInitializer(loggerContext); + URL url = ci.findURLOfDefaultConfigurationFile(true); + reloadByURL(url); + } + + public void reloadByFileName(String fileName) throws JoranException, FileNotFoundException + { + File f = new File(fileName); + if ((f.exists()) && (f.isFile())) + { + try { + URL url = f.toURI().toURL(); + reloadByURL(url); + } catch (MalformedURLException e) { + throw new RuntimeException("Unexpected MalformedURLException occured. See nexted cause.", e); + } + } + else + { + String errMsg = "Could not find [" + fileName + "]"; + addInfo(errMsg); + throw new FileNotFoundException(errMsg); + } + } + + void addStatusListener(StatusListener statusListener) { + StatusManager sm = loggerContext.getStatusManager(); + sm.add(statusListener); + } + + void removeStatusListener(StatusListener statusListener) { + StatusManager sm = loggerContext.getStatusManager(); + sm.remove(statusListener); + } + + public void reloadByURL(URL url) throws JoranException { + StatusListenerAsList statusListenerAsList = new StatusListenerAsList(); + + addStatusListener(statusListenerAsList); + addInfo("Resetting context: " + loggerContext.getName()); + loggerContext.reset(); + + addStatusListener(statusListenerAsList); + try + { + JoranConfigurator configurator = new JoranConfigurator(); + configurator.setContext(loggerContext); + configurator.doConfigure(url); + addInfo("Context: " + loggerContext.getName() + " reloaded."); + } finally { + removeStatusListener(statusListenerAsList); + if (debug) { + StatusPrinter.print(statusListenerAsList.getStatusList()); + } + } + } + + public void setLoggerLevel(String loggerName, String levelStr) { + if (loggerName == null) { + return; + } + if (levelStr == null) { + return; + } + loggerName = loggerName.trim(); + levelStr = levelStr.trim(); + + addInfo("Trying to set level " + levelStr + " to logger " + loggerName); + LoggerContext lc = (LoggerContext)context; + + Logger logger = lc.getLogger(loggerName); + if ("null".equalsIgnoreCase(levelStr)) { + logger.setLevel(null); + } else { + Level level = Level.toLevel(levelStr, null); + if (level != null) { + logger.setLevel(level); + } + } + } + + public String getLoggerLevel(String loggerName) { + if (loggerName == null) { + return EMPTY; + } + + loggerName = loggerName.trim(); + + LoggerContext lc = (LoggerContext)context; + Logger logger = lc.exists(loggerName); + if ((logger != null) && (logger.getLevel() != null)) { + return logger.getLevel().toString(); + } + return EMPTY; + } + + public String getLoggerEffectiveLevel(String loggerName) + { + if (loggerName == null) { + return EMPTY; + } + + loggerName = loggerName.trim(); + + LoggerContext lc = (LoggerContext)context; + Logger logger = lc.exists(loggerName); + if (logger != null) { + return logger.getEffectiveLevel().toString(); + } + return EMPTY; + } + + public List getLoggerList() + { + LoggerContext lc = (LoggerContext)context; + List strList = new ArrayList(); + Iterator it = lc.getLoggerList().iterator(); + while (it.hasNext()) { + Logger log = (Logger)it.next(); + strList.add(log.getName()); + } + return strList; + } + + public List getStatuses() { + List list = new ArrayList(); + Iterator it = context.getStatusManager().getCopyOfStatusList().iterator(); + + while (it.hasNext()) { + list.add(((Status)it.next()).toString()); + } + return list; + } + + + + + public void onStop(LoggerContext context) + { + if (!started) { + addInfo("onStop() method called on a stopped JMXActivator [" + objectNameAsString + "]"); + + return; + } + if (mbs.isRegistered(objectName)) { + try { + addInfo("Unregistering mbean [" + objectNameAsString + "]"); + mbs.unregisterMBean(objectName); + } + catch (InstanceNotFoundException e) { + addError("Unable to find a verifiably registered mbean [" + objectNameAsString + "]", e); + } + catch (MBeanRegistrationException e) { + addError("Failed to unregister [" + objectNameAsString + "]", e); + } + } else { + addInfo("mbean [" + objectNameAsString + "] was not in the mbean registry. This is OK."); + } + + stop(); + } + + + public void onLevelChange(Logger logger, Level level) {} + + public void onReset(LoggerContext context) + { + addInfo("onReset() method called JMXActivator [" + objectNameAsString + "]"); + } + + + + + + public boolean isResetResistant() + { + return true; + } + + private void clearFields() { + mbs = null; + objectName = null; + loggerContext = null; + } + + private void stop() { + started = false; + clearFields(); + } + + + public void onStart(LoggerContext context) {} + + + public String toString() + { + return getClass().getName() + "(" + context.getName() + ")"; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/jmx/JMXConfiguratorMBean.java b/src/minecraft/ch/qos/logback/classic/jmx/JMXConfiguratorMBean.java new file mode 100644 index 0000000..5f10bb6 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/jmx/JMXConfiguratorMBean.java @@ -0,0 +1,28 @@ +package ch.qos.logback.classic.jmx; + +import ch.qos.logback.core.joran.spi.JoranException; +import java.io.FileNotFoundException; +import java.net.URL; +import java.util.List; + +public abstract interface JMXConfiguratorMBean +{ + public abstract void reloadDefaultConfiguration() + throws JoranException; + + public abstract void reloadByFileName(String paramString) + throws JoranException, FileNotFoundException; + + public abstract void reloadByURL(URL paramURL) + throws JoranException; + + public abstract void setLoggerLevel(String paramString1, String paramString2); + + public abstract String getLoggerLevel(String paramString); + + public abstract String getLoggerEffectiveLevel(String paramString); + + public abstract List getLoggerList(); + + public abstract List getStatuses(); +} diff --git a/src/minecraft/ch/qos/logback/classic/jmx/MBeanUtil.java b/src/minecraft/ch/qos/logback/classic/jmx/MBeanUtil.java new file mode 100644 index 0000000..12d322a --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/jmx/MBeanUtil.java @@ -0,0 +1,88 @@ +package ch.qos.logback.classic.jmx; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.status.StatusUtil; +import javax.management.InstanceNotFoundException; +import javax.management.MBeanRegistrationException; +import javax.management.MBeanServer; +import javax.management.MalformedObjectNameException; +import javax.management.ObjectName; + + + + + + + + + + + + +public class MBeanUtil +{ + static final String DOMAIN = "ch.qos.logback.classic"; + + public MBeanUtil() {} + + public static String getObjectNameFor(String contextName, Class type) + { + return "ch.qos.logback.classic:Name=" + contextName + ",Type=" + type.getName(); + } + + + public static ObjectName string2ObjectName(Context context, Object caller, String objectNameAsStr) + { + String msg = "Failed to convert [" + objectNameAsStr + "] to ObjectName"; + + StatusUtil statusUtil = new StatusUtil(context); + try { + return new ObjectName(objectNameAsStr); + } catch (MalformedObjectNameException e) { + statusUtil.addError(caller, msg, e); + return null; + } catch (NullPointerException e) { + statusUtil.addError(caller, msg, e); } + return null; + } + + public static boolean isRegistered(MBeanServer mbs, ObjectName objectName) + { + return mbs.isRegistered(objectName); + } + + public static void createAndRegisterJMXConfigurator(MBeanServer mbs, LoggerContext loggerContext, JMXConfigurator jmxConfigurator, ObjectName objectName, Object caller) + { + try + { + mbs.registerMBean(jmxConfigurator, objectName); + } catch (Exception e) { + StatusUtil statusUtil = new StatusUtil(loggerContext); + statusUtil.addError(caller, "Failed to create mbean", e); + } + } + + + public static void unregister(LoggerContext loggerContext, MBeanServer mbs, ObjectName objectName, Object caller) + { + StatusUtil statusUtil = new StatusUtil(loggerContext); + if (mbs.isRegistered(objectName)) { + try { + statusUtil.addInfo(caller, "Unregistering mbean [" + objectName + "]"); + + mbs.unregisterMBean(objectName); + } + catch (InstanceNotFoundException e) { + statusUtil.addError(caller, "Failed to unregister mbean" + objectName, e); + } + catch (MBeanRegistrationException e) + { + statusUtil.addError(caller, "Failed to unregister mbean" + objectName, e); + } + + } else { + statusUtil.addInfo(caller, "mbean [" + objectName + "] does not seem to be registered"); + } + } +} diff --git a/src/minecraft/ch/qos/logback/classic/joran/JoranConfigurator.java b/src/minecraft/ch/qos/logback/classic/joran/JoranConfigurator.java new file mode 100644 index 0000000..d8464e6 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/joran/JoranConfigurator.java @@ -0,0 +1,95 @@ +package ch.qos.logback.classic.joran; + +import ch.qos.logback.classic.joran.action.ConfigurationAction; +import ch.qos.logback.classic.joran.action.ConsolePluginAction; +import ch.qos.logback.classic.joran.action.ContextNameAction; +import ch.qos.logback.classic.joran.action.EvaluatorAction; +import ch.qos.logback.classic.joran.action.InsertFromJNDIAction; +import ch.qos.logback.classic.joran.action.JMXConfiguratorAction; +import ch.qos.logback.classic.joran.action.LevelAction; +import ch.qos.logback.classic.joran.action.LoggerAction; +import ch.qos.logback.classic.joran.action.LoggerContextListenerAction; +import ch.qos.logback.classic.joran.action.ReceiverAction; +import ch.qos.logback.classic.joran.action.RootLoggerAction; +import ch.qos.logback.classic.sift.SiftAction; +import ch.qos.logback.classic.spi.PlatformInfo; +import ch.qos.logback.classic.util.DefaultNestedComponentRules; +import ch.qos.logback.core.joran.JoranConfiguratorBase; +import ch.qos.logback.core.joran.action.AppenderRefAction; +import ch.qos.logback.core.joran.action.IncludeAction; +import ch.qos.logback.core.joran.action.NOPAction; +import ch.qos.logback.core.joran.conditional.ElseAction; +import ch.qos.logback.core.joran.conditional.IfAction; +import ch.qos.logback.core.joran.conditional.ThenAction; +import ch.qos.logback.core.joran.spi.DefaultNestedComponentRegistry; +import ch.qos.logback.core.joran.spi.ElementSelector; +import ch.qos.logback.core.joran.spi.RuleStore; + + + + + + + +public class JoranConfigurator + extends JoranConfiguratorBase +{ + public JoranConfigurator() {} + + public void addInstanceRules(RuleStore rs) + { + super.addInstanceRules(rs); + + rs.addRule(new ElementSelector("configuration"), new ConfigurationAction()); + + rs.addRule(new ElementSelector("configuration/contextName"), new ContextNameAction()); + + rs.addRule(new ElementSelector("configuration/contextListener"), new LoggerContextListenerAction()); + + rs.addRule(new ElementSelector("configuration/insertFromJNDI"), new InsertFromJNDIAction()); + + rs.addRule(new ElementSelector("configuration/evaluator"), new EvaluatorAction()); + + rs.addRule(new ElementSelector("configuration/appender/sift"), new SiftAction()); + rs.addRule(new ElementSelector("configuration/appender/sift/*"), new NOPAction()); + + rs.addRule(new ElementSelector("configuration/logger"), new LoggerAction()); + rs.addRule(new ElementSelector("configuration/logger/level"), new LevelAction()); + + rs.addRule(new ElementSelector("configuration/root"), new RootLoggerAction()); + rs.addRule(new ElementSelector("configuration/root/level"), new LevelAction()); + rs.addRule(new ElementSelector("configuration/logger/appender-ref"), new AppenderRefAction()); + + rs.addRule(new ElementSelector("configuration/root/appender-ref"), new AppenderRefAction()); + + + + rs.addRule(new ElementSelector("*/if"), new IfAction()); + rs.addRule(new ElementSelector("*/if/then"), new ThenAction()); + rs.addRule(new ElementSelector("*/if/then/*"), new NOPAction()); + rs.addRule(new ElementSelector("*/if/else"), new ElseAction()); + rs.addRule(new ElementSelector("*/if/else/*"), new NOPAction()); + + + + + if (PlatformInfo.hasJMXObjectName()) { + rs.addRule(new ElementSelector("configuration/jmxConfigurator"), new JMXConfiguratorAction()); + } + + rs.addRule(new ElementSelector("configuration/include"), new IncludeAction()); + + rs.addRule(new ElementSelector("configuration/consolePlugin"), new ConsolePluginAction()); + + + rs.addRule(new ElementSelector("configuration/receiver"), new ReceiverAction()); + } + + + + + protected void addDefaultNestedComponentRegistryRules(DefaultNestedComponentRegistry registry) + { + DefaultNestedComponentRules.addDefaultNestedComponentRegistryRules(registry); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/joran/action/ConfigurationAction.java b/src/minecraft/ch/qos/logback/classic/joran/action/ConfigurationAction.java new file mode 100644 index 0000000..2b3de5e --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/joran/action/ConfigurationAction.java @@ -0,0 +1,109 @@ +package ch.qos.logback.classic.joran.action; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.turbo.ReconfigureOnChangeFilter; +import ch.qos.logback.classic.util.EnvUtil; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.status.OnConsoleStatusListener; +import ch.qos.logback.core.util.ContextUtil; +import ch.qos.logback.core.util.Duration; +import ch.qos.logback.core.util.OptionHelper; +import org.xml.sax.Attributes; + + + + + + + + + + + +public class ConfigurationAction + extends Action +{ + static final String INTERNAL_DEBUG_ATTR = "debug"; + static final String SCAN_ATTR = "scan"; + static final String SCAN_PERIOD_ATTR = "scanPeriod"; + static final String DEBUG_SYSTEM_PROPERTY_KEY = "logback.debug"; + + public ConfigurationAction() {} + + long threshold = 0L; + + public void begin(InterpretationContext ic, String name, Attributes attributes) { + threshold = System.currentTimeMillis(); + + + + + String debugAttrib = getSystemProperty("logback.debug"); + if (debugAttrib == null) { + debugAttrib = ic.subst(attributes.getValue("debug")); + } + + if ((OptionHelper.isEmpty(debugAttrib)) || (debugAttrib.equalsIgnoreCase("false")) || (debugAttrib.equalsIgnoreCase("null"))) + { + addInfo("debug attribute not set"); + } else { + OnConsoleStatusListener.addNewInstanceToContext(context); + } + + processScanAttrib(ic, attributes); + + ContextUtil contextUtil = new ContextUtil(context); + contextUtil.addHostNameAsProperty(); + + if (EnvUtil.isGroovyAvailable()) { + LoggerContext lc = (LoggerContext)context; + contextUtil.addGroovyPackages(lc.getFrameworkPackages()); + } + + + + ic.pushObject(getContext()); + } + + + + String getSystemProperty(String name) + { + try + { + return System.getProperty(name); + } catch (SecurityException ex) {} + return null; + } + + void processScanAttrib(InterpretationContext ic, Attributes attributes) + { + String scanAttrib = ic.subst(attributes.getValue("scan")); + if ((!OptionHelper.isEmpty(scanAttrib)) && (!"false".equalsIgnoreCase(scanAttrib))) + { + ReconfigureOnChangeFilter rocf = new ReconfigureOnChangeFilter(); + rocf.setContext(context); + String scanPeriodAttrib = ic.subst(attributes.getValue("scanPeriod")); + if (!OptionHelper.isEmpty(scanPeriodAttrib)) { + try { + Duration duration = Duration.valueOf(scanPeriodAttrib); + rocf.setRefreshPeriod(duration.getMilliseconds()); + addInfo("Setting ReconfigureOnChangeFilter scanning period to " + duration); + } + catch (NumberFormatException nfe) { + addError("Error while converting [" + scanAttrib + "] to long", nfe); + } + } + rocf.start(); + LoggerContext lc = (LoggerContext)context; + addInfo("Adding ReconfigureOnChangeFilter as a turbo filter"); + lc.addTurboFilter(rocf); + } + } + + public void end(InterpretationContext ec, String name) { + addInfo("End of configuration."); + ec.popObject(); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/joran/action/ConsolePluginAction.java b/src/minecraft/ch/qos/logback/classic/joran/action/ConsolePluginAction.java new file mode 100644 index 0000000..9ca200b --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/joran/action/ConsolePluginAction.java @@ -0,0 +1,63 @@ +package ch.qos.logback.classic.joran.action; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.net.SocketAppender; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import org.xml.sax.Attributes; + + + + + + + + + + + + + + +public class ConsolePluginAction + extends Action +{ + private static final String PORT_ATTR = "port"; + private static final Integer DEFAULT_PORT = Integer.valueOf(4321); + + public ConsolePluginAction() {} + + public void begin(InterpretationContext ec, String name, Attributes attributes) throws ActionException { + String portStr = attributes.getValue("port"); + Integer port = null; + + if (portStr == null) { + port = DEFAULT_PORT; + } else { + try { + port = Integer.valueOf(portStr); + } catch (NumberFormatException ex) { + addError("Port " + portStr + " in ConsolePlugin config is not a correct number"); + } + } + + + LoggerContext lc = (LoggerContext)ec.getContext(); + SocketAppender appender = new SocketAppender(); + appender.setContext(lc); + appender.setIncludeCallerData(true); + appender.setRemoteHost("localhost"); + appender.setPort(port.intValue()); + appender.start(); + Logger root = lc.getLogger("ROOT"); + root.addAppender(appender); + + addInfo("Sending LoggingEvents to the plugin using port " + port); + } + + public void end(InterpretationContext ec, String name) + throws ActionException + {} +} diff --git a/src/minecraft/ch/qos/logback/classic/joran/action/ContextNameAction.java b/src/minecraft/ch/qos/logback/classic/joran/action/ContextNameAction.java new file mode 100644 index 0000000..c6efe59 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/joran/action/ContextNameAction.java @@ -0,0 +1,38 @@ +package ch.qos.logback.classic.joran.action; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import org.xml.sax.Attributes; + + + + + + + + + + + + +public class ContextNameAction + extends Action +{ + public ContextNameAction() {} + + public void begin(InterpretationContext ec, String name, Attributes attributes) {} + + public void body(InterpretationContext ec, String body) + { + String finalBody = ec.subst(body); + addInfo("Setting logger context name as [" + finalBody + "]"); + try { + context.setName(finalBody); + } catch (IllegalStateException e) { + addError("Failed to rename context [" + context.getName() + "] as [" + finalBody + "]", e); + } + } + + public void end(InterpretationContext ec, String name) {} +} diff --git a/src/minecraft/ch/qos/logback/classic/joran/action/EvaluatorAction.java b/src/minecraft/ch/qos/logback/classic/joran/action/EvaluatorAction.java new file mode 100644 index 0000000..175b8a0 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/joran/action/EvaluatorAction.java @@ -0,0 +1,23 @@ +package ch.qos.logback.classic.joran.action; + +import ch.qos.logback.classic.boolex.JaninoEventEvaluator; +import ch.qos.logback.core.joran.action.AbstractEventEvaluatorAction; + + + + + + + + + +public class EvaluatorAction + extends AbstractEventEvaluatorAction +{ + public EvaluatorAction() {} + + protected String defaultClassName() + { + return JaninoEventEvaluator.class.getName(); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/joran/action/InsertFromJNDIAction.java b/src/minecraft/ch/qos/logback/classic/joran/action/InsertFromJNDIAction.java new file mode 100644 index 0000000..f83af0c --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/joran/action/InsertFromJNDIAction.java @@ -0,0 +1,81 @@ +package ch.qos.logback.classic.joran.action; + +import ch.qos.logback.classic.util.JNDIUtil; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.action.ActionUtil; +import ch.qos.logback.core.joran.action.ActionUtil.Scope; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.util.OptionHelper; +import javax.naming.Context; +import javax.naming.NamingException; +import org.xml.sax.Attributes; + + + + + + + + + + + + + + + + + + + +public class InsertFromJNDIAction + extends Action +{ + public static final String ENV_ENTRY_NAME_ATTR = "env-entry-name"; + public static final String AS_ATTR = "as"; + + public InsertFromJNDIAction() {} + + public void begin(InterpretationContext ec, String name, Attributes attributes) + { + int errorCount = 0; + String envEntryName = ec.subst(attributes.getValue("env-entry-name")); + String asKey = ec.subst(attributes.getValue("as")); + + String scopeStr = attributes.getValue("scope"); + ActionUtil.Scope scope = ActionUtil.stringToScope(scopeStr); + + + + if (OptionHelper.isEmpty(envEntryName)) { + String lineColStr = getLineColStr(ec); + addError("[env-entry-name] missing, around " + lineColStr); + errorCount++; + } + + if (OptionHelper.isEmpty(asKey)) { + String lineColStr = getLineColStr(ec); + addError("[as] missing, around " + lineColStr); + errorCount++; + } + + if (errorCount != 0) { + return; + } + try + { + Context ctx = JNDIUtil.getInitialContext(); + String envEntryValue = JNDIUtil.lookup(ctx, envEntryName); + if (OptionHelper.isEmpty(envEntryValue)) { + addError("[" + envEntryName + "] has null or empty value"); + } else { + addInfo("Setting variable [" + asKey + "] to [" + envEntryValue + "] in [" + scope + "] scope"); + ActionUtil.setProperty(ec, asKey, envEntryValue, scope); + } + } catch (NamingException e) { + addError("Failed to lookup JNDI env-entry [" + envEntryName + "]"); + } + } + + public void end(InterpretationContext ec, String name) {} +} diff --git a/src/minecraft/ch/qos/logback/classic/joran/action/JMXConfiguratorAction.java b/src/minecraft/ch/qos/logback/classic/joran/action/JMXConfiguratorAction.java new file mode 100644 index 0000000..81e231d --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/joran/action/JMXConfiguratorAction.java @@ -0,0 +1,86 @@ +package ch.qos.logback.classic.joran.action; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.jmx.JMXConfigurator; +import ch.qos.logback.classic.jmx.MBeanUtil; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.util.OptionHelper; +import java.lang.management.ManagementFactory; +import javax.management.MBeanServer; +import javax.management.ObjectName; +import org.xml.sax.Attributes; + + + + + + + + + + + + + +public class JMXConfiguratorAction + extends Action +{ + static final String OBJECT_NAME_ATTRIBUTE_NAME = "objectName"; + static final String CONTEXT_NAME_ATTRIBUTE_NAME = "contextName"; + static final char JMX_NAME_SEPARATOR = ','; + + public JMXConfiguratorAction() {} + + public void begin(InterpretationContext ec, String name, Attributes attributes) + throws ActionException + { + addInfo("begin"); + + + String contextName = context.getName(); + String contextNameAttributeVal = attributes.getValue("contextName"); + + if (!OptionHelper.isEmpty(contextNameAttributeVal)) { + contextName = contextNameAttributeVal; + } + + + String objectNameAttributeVal = attributes.getValue("objectName"); + String objectNameAsStr; + String objectNameAsStr; if (OptionHelper.isEmpty(objectNameAttributeVal)) { + objectNameAsStr = MBeanUtil.getObjectNameFor(contextName, JMXConfigurator.class); + } + else { + objectNameAsStr = objectNameAttributeVal; + } + + ObjectName objectName = MBeanUtil.string2ObjectName(context, this, objectNameAsStr); + + if (objectName == null) { + addError("Failed construct ObjectName for [" + objectNameAsStr + "]"); + return; + } + + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + if (!MBeanUtil.isRegistered(mbs, objectName)) + { + + + + JMXConfigurator jmxConfigurator = new JMXConfigurator((LoggerContext)context, mbs, objectName); + try + { + mbs.registerMBean(jmxConfigurator, objectName); + } catch (Exception e) { + addError("Failed to create mbean", e); + } + } + } + + public void end(InterpretationContext ec, String name) + throws ActionException + {} +} diff --git a/src/minecraft/ch/qos/logback/classic/joran/action/LevelAction.java b/src/minecraft/ch/qos/logback/classic/joran/action/LevelAction.java new file mode 100644 index 0000000..43c4037 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/joran/action/LevelAction.java @@ -0,0 +1,65 @@ +package ch.qos.logback.classic.joran.action; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import org.xml.sax.Attributes; + + + + + + + + + + + + + + + + + + + + + +public class LevelAction + extends Action +{ + public LevelAction() {} + + boolean inError = false; + + public void begin(InterpretationContext ec, String name, Attributes attributes) { + Object o = ec.peekObject(); + + if (!(o instanceof Logger)) { + inError = true; + addError("For element , could not find a logger at the top of execution stack."); + return; + } + + Logger l = (Logger)o; + + String loggerName = l.getName(); + + String levelStr = ec.subst(attributes.getValue("value")); + + + + if (("INHERITED".equalsIgnoreCase(levelStr)) || ("NULL".equalsIgnoreCase(levelStr))) { + l.setLevel(null); + } else { + l.setLevel(Level.toLevel(levelStr, Level.DEBUG)); + } + + addInfo(loggerName + " level set to " + l.getLevel()); + } + + public void finish(InterpretationContext ec) {} + + public void end(InterpretationContext ec, String e) {} +} diff --git a/src/minecraft/ch/qos/logback/classic/joran/action/LoggerAction.java b/src/minecraft/ch/qos/logback/classic/joran/action/LoggerAction.java new file mode 100644 index 0000000..f81c9a2 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/joran/action/LoggerAction.java @@ -0,0 +1,94 @@ +package ch.qos.logback.classic.joran.action; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.util.OptionHelper; +import org.xml.sax.Attributes; + + + + + + + + + + + + + + + + + + + + +public class LoggerAction + extends Action +{ + public static final String LEVEL_ATTRIBUTE = "level"; + boolean inError = false; + + public LoggerAction() {} + + public void begin(InterpretationContext ec, String name, Attributes attributes) { inError = false; + logger = null; + + LoggerContext loggerContext = (LoggerContext)context; + + String loggerName = ec.subst(attributes.getValue("name")); + + if (OptionHelper.isEmpty(loggerName)) { + inError = true; + String aroundLine = getLineColStr(ec); + String errorMsg = "No 'name' attribute in element " + name + ", around " + aroundLine; + addError(errorMsg); + return; + } + + logger = loggerContext.getLogger(loggerName); + + String levelStr = ec.subst(attributes.getValue("level")); + + if (!OptionHelper.isEmpty(levelStr)) { + if (("INHERITED".equalsIgnoreCase(levelStr)) || ("NULL".equalsIgnoreCase(levelStr))) + { + addInfo("Setting level of logger [" + loggerName + "] to null, i.e. INHERITED"); + + logger.setLevel(null); + } else { + Level level = Level.toLevel(levelStr); + addInfo("Setting level of logger [" + loggerName + "] to " + level); + logger.setLevel(level); + } + } + + String additivityStr = ec.subst(attributes.getValue("additivity")); + if (!OptionHelper.isEmpty(additivityStr)) { + boolean additive = OptionHelper.toBoolean(additivityStr, true); + addInfo("Setting additivity of logger [" + loggerName + "] to " + additive); + + logger.setAdditive(additive); + } + ec.pushObject(logger); + } + + Logger logger; + public void end(InterpretationContext ec, String e) { if (inError) { + return; + } + Object o = ec.peekObject(); + if (o != logger) { + addWarn("The object on the top the of the stack is not " + logger + " pushed earlier"); + addWarn("It is: " + o); + } else { + ec.popObject(); + } + } + + public void finish(InterpretationContext ec) {} +} diff --git a/src/minecraft/ch/qos/logback/classic/joran/action/LoggerContextListenerAction.java b/src/minecraft/ch/qos/logback/classic/joran/action/LoggerContextListenerAction.java new file mode 100644 index 0000000..5d46691 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/joran/action/LoggerContextListenerAction.java @@ -0,0 +1,81 @@ +package ch.qos.logback.classic.joran.action; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.LoggerContextListener; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.spi.ContextAware; +import ch.qos.logback.core.spi.LifeCycle; +import ch.qos.logback.core.util.OptionHelper; +import org.xml.sax.Attributes; + + + + + + + + + + + + + +public class LoggerContextListenerAction + extends Action +{ + boolean inError = false; + LoggerContextListener lcl; + + public LoggerContextListenerAction() {} + + public void begin(InterpretationContext ec, String name, Attributes attributes) throws ActionException + { + inError = false; + + String className = attributes.getValue("class"); + if (OptionHelper.isEmpty(className)) { + addError("Mandatory \"class\" attribute not set for element"); + + inError = true; + return; + } + try + { + lcl = ((LoggerContextListener)OptionHelper.instantiateByClassName(className, LoggerContextListener.class, context)); + + + if ((lcl instanceof ContextAware)) { + ((ContextAware)lcl).setContext(context); + } + + ec.pushObject(lcl); + addInfo("Adding LoggerContextListener of type [" + className + "] to the object stack"); + } + catch (Exception oops) + { + inError = true; + addError("Could not create LoggerContextListener of type " + className + "].", oops); + } + } + + public void end(InterpretationContext ec, String name) throws ActionException + { + if (inError) { + return; + } + Object o = ec.peekObject(); + + if (o != lcl) { + addWarn("The object on the top the of the stack is not the LoggerContextListener pushed earlier."); + } else { + if ((lcl instanceof LifeCycle)) { + ((LifeCycle)lcl).start(); + addInfo("Starting LoggerContextListener"); + } + ((LoggerContext)context).addListener(lcl); + ec.popObject(); + } + } +} diff --git a/src/minecraft/ch/qos/logback/classic/joran/action/ReceiverAction.java b/src/minecraft/ch/qos/logback/classic/joran/action/ReceiverAction.java new file mode 100644 index 0000000..cbc4bdb --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/joran/action/ReceiverAction.java @@ -0,0 +1,80 @@ +package ch.qos.logback.classic.joran.action; + +import ch.qos.logback.classic.net.ReceiverBase; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.util.OptionHelper; +import org.xml.sax.Attributes; + + + + + + + + + + + + + + + + + + +public class ReceiverAction + extends Action +{ + private ReceiverBase receiver; + private boolean inError; + + public ReceiverAction() {} + + public void begin(InterpretationContext ic, String name, Attributes attributes) + throws ActionException + { + String className = attributes.getValue("class"); + if (OptionHelper.isEmpty(className)) { + addError("Missing class name for receiver. Near [" + name + "] line " + getLineNumber(ic)); + + inError = true; + return; + } + try + { + addInfo("About to instantiate receiver of type [" + className + "]"); + + receiver = ((ReceiverBase)OptionHelper.instantiateByClassName(className, ReceiverBase.class, context)); + + receiver.setContext(context); + + ic.pushObject(receiver); + } + catch (Exception ex) { + inError = true; + addError("Could not create a receiver of type [" + className + "].", ex); + throw new ActionException(ex); + } + } + + + public void end(InterpretationContext ic, String name) + throws ActionException + { + if (inError) { return; + } + ic.getContext().register(receiver); + receiver.start(); + + Object o = ic.peekObject(); + if (o != receiver) { + addWarn("The object at the of the stack is not the remote pushed earlier."); + } + else { + ic.popObject(); + } + } +} diff --git a/src/minecraft/ch/qos/logback/classic/joran/action/RootLoggerAction.java b/src/minecraft/ch/qos/logback/classic/joran/action/RootLoggerAction.java new file mode 100644 index 0000000..8d66d1f --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/joran/action/RootLoggerAction.java @@ -0,0 +1,60 @@ +package ch.qos.logback.classic.joran.action; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.util.OptionHelper; +import org.xml.sax.Attributes; + + + + + + + + + + + + +public class RootLoggerAction + extends Action +{ + Logger root; + + public RootLoggerAction() {} + + boolean inError = false; + + public void begin(InterpretationContext ec, String name, Attributes attributes) { + inError = false; + + LoggerContext loggerContext = (LoggerContext)context; + root = loggerContext.getLogger("ROOT"); + + String levelStr = ec.subst(attributes.getValue("level")); + if (!OptionHelper.isEmpty(levelStr)) { + Level level = Level.toLevel(levelStr); + addInfo("Setting level of ROOT logger to " + level); + root.setLevel(level); + } + ec.pushObject(root); + } + + public void end(InterpretationContext ec, String name) { + if (inError) { + return; + } + Object o = ec.peekObject(); + if (o != root) { + addWarn("The object on the top the of the stack is not the root logger"); + addWarn("It is: " + o); + } else { + ec.popObject(); + } + } + + public void finish(InterpretationContext ec) {} +} diff --git a/src/minecraft/ch/qos/logback/classic/jul/JULHelper.java b/src/minecraft/ch/qos/logback/classic/jul/JULHelper.java new file mode 100644 index 0000000..641d524 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/jul/JULHelper.java @@ -0,0 +1,73 @@ +package ch.qos.logback.classic.jul; + + + + + + + + +public class JULHelper +{ + public JULHelper() {} + + + + + + + + + public static final boolean isRegularNonRootLogger(java.util.logging.Logger julLogger) + { + if (julLogger == null) + return false; + return !julLogger.getName().equals(""); + } + + public static final boolean isRoot(java.util.logging.Logger julLogger) { + if (julLogger == null) + return false; + return julLogger.getName().equals(""); + } + + public static java.util.logging.Level asJULLevel(ch.qos.logback.classic.Level lbLevel) { + if (lbLevel == null) { + throw new IllegalArgumentException("Unexpected level [null]"); + } + switch (levelInt) { + case -2147483648: + return java.util.logging.Level.ALL; + case 5000: + return java.util.logging.Level.FINEST; + case 10000: + return java.util.logging.Level.FINE; + case 20000: + return java.util.logging.Level.INFO; + case 30000: + return java.util.logging.Level.WARNING; + case 40000: + return java.util.logging.Level.SEVERE; + case 2147483647: + return java.util.logging.Level.OFF; + } + throw new IllegalArgumentException("Unexpected level [" + lbLevel + "]"); + } + + public static String asJULLoggerName(String loggerName) + { + if ("ROOT".equals(loggerName)) { + return ""; + } + return loggerName; + } + + public static java.util.logging.Logger asJULLogger(String loggerName) { + String julLoggerName = asJULLoggerName(loggerName); + return java.util.logging.Logger.getLogger(julLoggerName); + } + + public static java.util.logging.Logger asJULLogger(ch.qos.logback.classic.Logger logger) { + return asJULLogger(logger.getName()); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/jul/LevelChangePropagator.java b/src/minecraft/ch/qos/logback/classic/jul/LevelChangePropagator.java new file mode 100644 index 0000000..9008153 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/jul/LevelChangePropagator.java @@ -0,0 +1,110 @@ +package ch.qos.logback.classic.jul; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.LoggerContextListener; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.spi.LifeCycle; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.logging.LogManager; + + + + + + + + + + + + + + + + + +public class LevelChangePropagator + extends ContextAwareBase + implements LoggerContextListener, LifeCycle +{ + public LevelChangePropagator() {} + + private Set julLoggerSet = new HashSet(); + boolean isStarted = false; + boolean resetJUL = false; + + public void setResetJUL(boolean resetJUL) { + this.resetJUL = resetJUL; + } + + public boolean isResetResistant() { + return false; + } + + + public void onStart(LoggerContext context) {} + + + public void onReset(LoggerContext context) {} + + public void onStop(LoggerContext context) {} + + public void onLevelChange(ch.qos.logback.classic.Logger logger, ch.qos.logback.classic.Level level) + { + propagate(logger, level); + } + + private void propagate(ch.qos.logback.classic.Logger logger, ch.qos.logback.classic.Level level) { + addInfo("Propagating " + level + " level on " + logger + " onto the JUL framework"); + java.util.logging.Logger julLogger = JULHelper.asJULLogger(logger); + + + julLoggerSet.add(julLogger); + java.util.logging.Level julLevel = JULHelper.asJULLevel(level); + julLogger.setLevel(julLevel); + } + + public void resetJULLevels() { + LogManager lm = LogManager.getLogManager(); + + Enumeration e = lm.getLoggerNames(); + while (e.hasMoreElements()) { + String loggerName = (String)e.nextElement(); + java.util.logging.Logger julLogger = lm.getLogger(loggerName); + if ((JULHelper.isRegularNonRootLogger(julLogger)) && (julLogger.getLevel() != null)) { + addInfo("Setting level of jul logger [" + loggerName + "] to null"); + julLogger.setLevel(null); + } + } + } + + private void propagateExistingLoggerLevels() { + LoggerContext loggerContext = (LoggerContext)context; + List loggerList = loggerContext.getLoggerList(); + for (ch.qos.logback.classic.Logger l : loggerList) { + if (l.getLevel() != null) { + propagate(l, l.getLevel()); + } + } + } + + public void start() { + if (resetJUL) { + resetJULLevels(); + } + propagateExistingLoggerLevels(); + + isStarted = true; + } + + public void stop() { + isStarted = false; + } + + public boolean isStarted() { + return isStarted; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/log4j/XMLLayout.java b/src/minecraft/ch/qos/logback/classic/log4j/XMLLayout.java new file mode 100644 index 0000000..d069c24 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/log4j/XMLLayout.java @@ -0,0 +1,186 @@ +package ch.qos.logback.classic.log4j; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.IThrowableProxy; +import ch.qos.logback.classic.spi.StackTraceElementProxy; +import ch.qos.logback.core.LayoutBase; +import ch.qos.logback.core.helpers.Transform; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + + + + + + + + + + + + + + + + + + + + + + + + + + +public class XMLLayout + extends LayoutBase +{ + private final int DEFAULT_SIZE = 256; + private final int UPPER_LIMIT = 2048; + + private StringBuilder buf = new StringBuilder(256); + private boolean locationInfo = false; + private boolean properties = false; + + public XMLLayout() {} + + public void start() { super.start(); } + + + + + + + + + + + + public void setLocationInfo(boolean flag) + { + locationInfo = flag; + } + + + + public boolean getLocationInfo() + { + return locationInfo; + } + + + + + + + + public void setProperties(boolean flag) + { + properties = flag; + } + + + + + + + public boolean getProperties() + { + return properties; + } + + + + + + + public String doLayout(ILoggingEvent event) + { + if (buf.capacity() > 2048) { + buf = new StringBuilder(256); + } else { + buf.setLength(0); + } + + + + buf.append("\r\n"); + + buf.append(" "); + buf.append(Transform.escapeTags(event.getFormattedMessage())); + buf.append("\r\n"); + + + + + + IThrowableProxy tp = event.getThrowableProxy(); + if (tp != null) { + StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray(); + buf.append(" \r\n"); + } + + if (locationInfo) { + StackTraceElement[] callerDataArray = event.getCallerData(); + if ((callerDataArray != null) && (callerDataArray.length > 0)) { + StackTraceElement immediateCallerData = callerDataArray[0]; + buf.append(" \r\n"); + } + } + + + + + + if (getProperties()) { + Map propertyMap = event.getMDCPropertyMap(); + + if ((propertyMap != null) && (propertyMap.size() != 0)) { + Set> entrySet = propertyMap.entrySet(); + buf.append(" "); + for (Map.Entry entry : entrySet) { + buf.append("\r\n "); + } + buf.append("\r\n "); + } + } + + buf.append("\r\n\r\n\r\n"); + + return buf.toString(); + } + + public String getContentType() + { + return "text/xml"; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/net/JMSQueueAppender.java b/src/minecraft/ch/qos/logback/classic/net/JMSQueueAppender.java new file mode 100644 index 0000000..f787bd9 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/net/JMSQueueAppender.java @@ -0,0 +1,211 @@ +package ch.qos.logback.classic.net; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.net.JMSAppenderBase; +import ch.qos.logback.core.spi.PreSerializationTransformer; +import java.io.Serializable; +import javax.jms.ObjectMessage; +import javax.jms.Queue; +import javax.jms.QueueConnection; +import javax.jms.QueueConnectionFactory; +import javax.jms.QueueSender; +import javax.jms.QueueSession; +import javax.naming.Context; + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class JMSQueueAppender + extends JMSAppenderBase +{ + static int SUCCESSIVE_FAILURE_LIMIT = 3; + + String queueBindingName; + + String qcfBindingName; + QueueConnection queueConnection; + QueueSession queueSession; + QueueSender queueSender; + int successiveFailureCount = 0; + + private PreSerializationTransformer pst = new LoggingEventPreSerializationTransformer(); + + + public JMSQueueAppender() {} + + + public void setQueueConnectionFactoryBindingName(String qcfBindingName) + { + this.qcfBindingName = qcfBindingName; + } + + + + public String getQueueConnectionFactoryBindingName() + { + return qcfBindingName; + } + + + + + public void setQueueBindingName(String queueBindingName) + { + this.queueBindingName = queueBindingName; + } + + + + public String getQueueBindingName() + { + return queueBindingName; + } + + + + + public void start() + { + try + { + Context jndi = buildJNDIContext(); + + + QueueConnectionFactory queueConnectionFactory = (QueueConnectionFactory)lookup(jndi, qcfBindingName); + + + if (userName != null) { + queueConnection = queueConnectionFactory.createQueueConnection(userName, password); + } + else { + queueConnection = queueConnectionFactory.createQueueConnection(); + } + + + + + queueSession = queueConnection.createQueueSession(false, 1); + + + + Queue queue = (Queue)lookup(jndi, queueBindingName); + + + queueSender = queueSession.createSender(queue); + + + queueConnection.start(); + + jndi.close(); + } catch (Exception e) { + addError("Error while activating options for appender named [" + name + "].", e); + } + + + if ((queueConnection != null) && (queueSession != null) && (queueSender != null)) + { + super.start(); + } + } + + + + + + public synchronized void stop() + { + if (!started) { + return; + } + + started = false; + try + { + if (queueSession != null) { + queueSession.close(); + } + if (queueConnection != null) { + queueConnection.close(); + } + } catch (Exception e) { + addError("Error while closing JMSAppender [" + name + "].", e); + } + + + queueSender = null; + queueSession = null; + queueConnection = null; + } + + + + + public void append(ILoggingEvent event) + { + if (!isStarted()) { + return; + } + try + { + ObjectMessage msg = queueSession.createObjectMessage(); + Serializable so = pst.transform(event); + msg.setObject(so); + queueSender.send(msg); + successiveFailureCount = 0; + } catch (Exception e) { + successiveFailureCount += 1; + if (successiveFailureCount > SUCCESSIVE_FAILURE_LIMIT) { + stop(); + } + addError("Could not send message in JMSQueueAppender [" + name + "].", e); + } + } + + + + + + protected QueueConnection getQueueConnection() + { + return queueConnection; + } + + + + + protected QueueSession getQueueSession() + { + return queueSession; + } + + + + + protected QueueSender getQueueSender() + { + return queueSender; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/net/JMSQueueSink.java b/src/minecraft/ch/qos/logback/classic/net/JMSQueueSink.java new file mode 100644 index 0000000..cf2bca2 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/net/JMSQueueSink.java @@ -0,0 +1,152 @@ +package ch.qos.logback.classic.net; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.util.ContextInitializer; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.util.Properties; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageListener; +import javax.jms.ObjectMessage; +import javax.jms.Queue; +import javax.jms.QueueConnection; +import javax.jms.QueueConnectionFactory; +import javax.jms.QueueSession; +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NameNotFoundException; +import javax.naming.NamingException; +import org.slf4j.LoggerFactory; + + + + + + + + + + + + + + + + + + + + +public class JMSQueueSink + implements MessageListener +{ + private Logger logger = (Logger)LoggerFactory.getLogger(JMSTopicSink.class); + + public static void main(String[] args) throws Exception { + if (args.length < 2) { + usage("Wrong number of arguments."); + } + + String qcfBindingName = args[0]; + String queueBindingName = args[1]; + String username = null; + String password = null; + if (args.length == 4) { + username = args[2]; + password = args[3]; + } + + LoggerContext loggerContext = (LoggerContext)LoggerFactory.getILoggerFactory(); + + new ContextInitializer(loggerContext).autoConfig(); + + new JMSQueueSink(qcfBindingName, queueBindingName, username, password); + + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + + System.out.println("Type \"exit\" to quit JMSQueueSink."); + for (;;) { + String s = stdin.readLine(); + if (s.equalsIgnoreCase("exit")) { + System.out.println("Exiting. Kill the application if it does not exit due to daemon threads."); + + return; + } + } + } + + public JMSQueueSink(String qcfBindingName, String queueBindingName, String username, String password) + { + try + { + Properties env = new Properties(); + env.put("java.naming.factory.initial", "org.apache.activemq.jndi.ActiveMQInitialContextFactory"); + env.put("java.naming.provider.url", "tcp://localhost:61616"); + Context ctx = new InitialContext(env); + + QueueConnectionFactory queueConnectionFactory = (QueueConnectionFactory)lookup(ctx, qcfBindingName); + + System.out.println("Queue Cnx Factory found"); + Queue queue = (Queue)ctx.lookup(queueBindingName); + System.out.println("Queue found: " + queue.getQueueName()); + + QueueConnection queueConnection = queueConnectionFactory.createQueueConnection(username, password); + + System.out.println("Queue Connection created"); + + QueueSession queueSession = queueConnection.createQueueSession(false, 1); + + + MessageConsumer queueConsumer = queueSession.createConsumer(queue); + + queueConsumer.setMessageListener(this); + + queueConnection.start(); + System.out.println("Queue Connection started"); + } + catch (Exception e) { + logger.error("Could not read JMS message.", e); + } + } + + public void onMessage(Message message) + { + try { + if ((message instanceof ObjectMessage)) { + ObjectMessage objectMessage = (ObjectMessage)message; + ILoggingEvent event = (ILoggingEvent)objectMessage.getObject(); + Logger log = (Logger)LoggerFactory.getLogger(event.getLoggerName()); + log.callAppenders(event); + } else { + logger.warn("Received message is of type " + message.getJMSType() + ", was expecting ObjectMessage."); + } + } + catch (JMSException jmse) { + logger.error("Exception thrown while processing incoming message.", jmse); + } + } + + protected Object lookup(Context ctx, String name) throws NamingException + { + try { + return ctx.lookup(name); + } catch (NameNotFoundException e) { + logger.error("Could not find name [" + name + "]."); + throw e; + } + } + + static void usage(String msg) { + System.err.println(msg); + System.err.println("Usage: java " + JMSQueueSink.class.getName() + " QueueConnectionFactoryBindingName QueueBindingName Username Password"); + + + + System.exit(1); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/net/JMSTopicAppender.java b/src/minecraft/ch/qos/logback/classic/net/JMSTopicAppender.java new file mode 100644 index 0000000..040f611 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/net/JMSTopicAppender.java @@ -0,0 +1,211 @@ +package ch.qos.logback.classic.net; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.net.JMSAppenderBase; +import ch.qos.logback.core.spi.PreSerializationTransformer; +import java.io.Serializable; +import javax.jms.ObjectMessage; +import javax.jms.Topic; +import javax.jms.TopicConnection; +import javax.jms.TopicConnectionFactory; +import javax.jms.TopicPublisher; +import javax.jms.TopicSession; +import javax.naming.Context; + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class JMSTopicAppender + extends JMSAppenderBase +{ + static int SUCCESSIVE_FAILURE_LIMIT = 3; + + String topicBindingName; + + String tcfBindingName; + TopicConnection topicConnection; + TopicSession topicSession; + TopicPublisher topicPublisher; + int successiveFailureCount = 0; + + private PreSerializationTransformer pst = new LoggingEventPreSerializationTransformer(); + + + public JMSTopicAppender() {} + + + public void setTopicConnectionFactoryBindingName(String tcfBindingName) + { + this.tcfBindingName = tcfBindingName; + } + + + + public String getTopicConnectionFactoryBindingName() + { + return tcfBindingName; + } + + + + + public void setTopicBindingName(String topicBindingName) + { + this.topicBindingName = topicBindingName; + } + + + + public String getTopicBindingName() + { + return topicBindingName; + } + + + + + public void start() + { + try + { + Context jndi = buildJNDIContext(); + + + TopicConnectionFactory topicConnectionFactory = (TopicConnectionFactory)lookup(jndi, tcfBindingName); + + + if (userName != null) { + topicConnection = topicConnectionFactory.createTopicConnection(userName, password); + } + else { + topicConnection = topicConnectionFactory.createTopicConnection(); + } + + + + + topicSession = topicConnection.createTopicSession(false, 1); + + + + Topic topic = (Topic)lookup(jndi, topicBindingName); + + + topicPublisher = topicSession.createPublisher(topic); + + + topicConnection.start(); + + jndi.close(); + } catch (Exception e) { + addError("Error while activating options for appender named [" + name + "].", e); + } + + + if ((topicConnection != null) && (topicSession != null) && (topicPublisher != null)) + { + super.start(); + } + } + + + + + + public synchronized void stop() + { + if (!started) { + return; + } + + started = false; + try + { + if (topicSession != null) { + topicSession.close(); + } + if (topicConnection != null) { + topicConnection.close(); + } + } catch (Exception e) { + addError("Error while closing JMSAppender [" + name + "].", e); + } + + + topicPublisher = null; + topicSession = null; + topicConnection = null; + } + + + + + + public void append(ILoggingEvent event) + { + if (!isStarted()) { + return; + } + try + { + ObjectMessage msg = topicSession.createObjectMessage(); + Serializable so = pst.transform(event); + msg.setObject(so); + topicPublisher.publish(msg); + successiveFailureCount = 0; + } catch (Exception e) { + successiveFailureCount += 1; + if (successiveFailureCount > SUCCESSIVE_FAILURE_LIMIT) { + stop(); + } + addError("Could not publish message in JMSTopicAppender [" + name + "].", e); + } + } + + + + + protected TopicConnection getTopicConnection() + { + return topicConnection; + } + + + + + protected TopicSession getTopicSession() + { + return topicSession; + } + + + + + protected TopicPublisher getTopicPublisher() + { + return topicPublisher; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/net/JMSTopicSink.java b/src/minecraft/ch/qos/logback/classic/net/JMSTopicSink.java new file mode 100644 index 0000000..3690fa7 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/net/JMSTopicSink.java @@ -0,0 +1,152 @@ +package ch.qos.logback.classic.net; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.util.ContextInitializer; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.util.Properties; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageListener; +import javax.jms.ObjectMessage; +import javax.jms.Topic; +import javax.jms.TopicConnection; +import javax.jms.TopicConnectionFactory; +import javax.jms.TopicSession; +import javax.jms.TopicSubscriber; +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NameNotFoundException; +import javax.naming.NamingException; +import org.slf4j.LoggerFactory; + + + + + + + + + + + + + + + + + + + + +public class JMSTopicSink + implements MessageListener +{ + private Logger logger = (Logger)LoggerFactory.getLogger(JMSTopicSink.class); + + public static void main(String[] args) throws Exception { + if (args.length < 2) { + usage("Wrong number of arguments."); + } + + String tcfBindingName = args[0]; + String topicBindingName = args[1]; + String username = null; + String password = null; + if (args.length == 4) { + username = args[2]; + password = args[3]; + } + + LoggerContext loggerContext = (LoggerContext)LoggerFactory.getILoggerFactory(); + + new ContextInitializer(loggerContext).autoConfig(); + + new JMSTopicSink(tcfBindingName, topicBindingName, username, password); + + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + + System.out.println("Type \"exit\" to quit JMSTopicSink."); + for (;;) { + String s = stdin.readLine(); + if (s.equalsIgnoreCase("exit")) { + System.out.println("Exiting. Kill the application if it does not exit due to daemon threads."); + + return; + } + } + } + + public JMSTopicSink(String tcfBindingName, String topicBindingName, String username, String password) + { + try + { + Properties env = new Properties(); + env.put("java.naming.factory.initial", "org.apache.activemq.jndi.ActiveMQInitialContextFactory"); + env.put("java.naming.provider.url", "tcp://localhost:61616"); + Context ctx = new InitialContext(env); + + TopicConnectionFactory topicConnectionFactory = (TopicConnectionFactory)lookup(ctx, tcfBindingName); + + System.out.println("Topic Cnx Factory found"); + Topic topic = (Topic)ctx.lookup(topicBindingName); + System.out.println("Topic found: " + topic.getTopicName()); + + TopicConnection topicConnection = topicConnectionFactory.createTopicConnection(username, password); + + System.out.println("Topic Connection created"); + + TopicSession topicSession = topicConnection.createTopicSession(false, 1); + + + TopicSubscriber topicSubscriber = topicSession.createSubscriber(topic); + + topicSubscriber.setMessageListener(this); + + topicConnection.start(); + System.out.println("Topic Connection started"); + } + catch (Exception e) { + logger.error("Could not read JMS message.", e); + } + } + + public void onMessage(Message message) + { + try { + if ((message instanceof ObjectMessage)) { + ObjectMessage objectMessage = (ObjectMessage)message; + ILoggingEvent event = (ILoggingEvent)objectMessage.getObject(); + Logger log = (Logger)LoggerFactory.getLogger(event.getLoggerName()); + log.callAppenders(event); + } else { + logger.warn("Received message is of type " + message.getJMSType() + ", was expecting ObjectMessage."); + } + } + catch (JMSException jmse) { + logger.error("Exception thrown while processing incoming message.", jmse); + } + } + + protected Object lookup(Context ctx, String name) throws NamingException + { + try { + return ctx.lookup(name); + } catch (NameNotFoundException e) { + logger.error("Could not find name [" + name + "]."); + throw e; + } + } + + static void usage(String msg) { + System.err.println(msg); + System.err.println("Usage: java " + JMSTopicSink.class.getName() + " TopicConnectionFactoryBindingName TopicBindingName Username Password"); + + + + System.exit(1); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/net/LoggingEventPreSerializationTransformer.java b/src/minecraft/ch/qos/logback/classic/net/LoggingEventPreSerializationTransformer.java new file mode 100644 index 0000000..85a14af --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/net/LoggingEventPreSerializationTransformer.java @@ -0,0 +1,37 @@ +package ch.qos.logback.classic.net; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggingEvent; +import ch.qos.logback.classic.spi.LoggingEventVO; +import ch.qos.logback.core.spi.PreSerializationTransformer; +import java.io.Serializable; + + + + + + + + + + + + +public class LoggingEventPreSerializationTransformer + implements PreSerializationTransformer +{ + public LoggingEventPreSerializationTransformer() {} + + public Serializable transform(ILoggingEvent event) + { + if (event == null) { + return null; + } + if ((event instanceof LoggingEvent)) + return LoggingEventVO.build(event); + if ((event instanceof LoggingEventVO)) { + return (LoggingEventVO)event; + } + throw new IllegalArgumentException("Unsupported type " + event.getClass().getName()); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/net/ReceiverBase.java b/src/minecraft/ch/qos/logback/classic/net/ReceiverBase.java new file mode 100644 index 0000000..55fd888 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/net/ReceiverBase.java @@ -0,0 +1,70 @@ +package ch.qos.logback.classic.net; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.spi.LifeCycle; +import java.util.concurrent.ExecutorService; + + + + + + + + + + + + + + + + + +public abstract class ReceiverBase + extends ContextAwareBase + implements LifeCycle +{ + private boolean started; + + public ReceiverBase() {} + + public final void start() + { + if (isStarted()) return; + if (getContext() == null) { + throw new IllegalStateException("context not set"); + } + if (shouldStart()) { + getContext().getExecutorService().execute(getRunnableTask()); + started = true; + } + } + + + + public final void stop() + { + if (!isStarted()) return; + try { + onStop(); + } + catch (RuntimeException ex) { + addError("on stop: " + ex, ex); + } + started = false; + } + + + + public final boolean isStarted() + { + return started; + } + + protected abstract boolean shouldStart(); + + protected abstract void onStop(); + + protected abstract Runnable getRunnableTask(); +} diff --git a/src/minecraft/ch/qos/logback/classic/net/SMTPAppender.java b/src/minecraft/ch/qos/logback/classic/net/SMTPAppender.java new file mode 100644 index 0000000..ab535dc --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/net/SMTPAppender.java @@ -0,0 +1,135 @@ +package ch.qos.logback.classic.net; + +import ch.qos.logback.classic.ClassicConstants; +import ch.qos.logback.classic.PatternLayout; +import ch.qos.logback.classic.boolex.OnErrorEvaluator; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.Layout; +import ch.qos.logback.core.boolex.EventEvaluator; +import ch.qos.logback.core.helpers.CyclicBuffer; +import ch.qos.logback.core.net.SMTPAppenderBase; +import org.slf4j.Marker; + + + + + + + + + + + + + + + + + + + + + + + + + + +public class SMTPAppender + extends SMTPAppenderBase +{ + static final String DEFAULT_SUBJECT_PATTERN = "%logger{20} - %m"; + private int bufferSize = 512; + private boolean includeCallerData = false; + + + + + + public SMTPAppender() {} + + + + + + public void start() + { + if (eventEvaluator == null) { + OnErrorEvaluator onError = new OnErrorEvaluator(); + onError.setContext(getContext()); + onError.setName("onError"); + onError.start(); + eventEvaluator = onError; + } + super.start(); + } + + + + + public SMTPAppender(EventEvaluator eventEvaluator) + { + this.eventEvaluator = eventEvaluator; + } + + + + + protected void subAppend(CyclicBuffer cb, ILoggingEvent event) + { + if (includeCallerData) { + event.getCallerData(); + } + event.prepareForDeferredProcessing(); + cb.add(event); + } + + protected void fillBuffer(CyclicBuffer cb, StringBuffer sbuf) + { + int len = cb.length(); + for (int i = 0; i < len; i++) { + ILoggingEvent event = (ILoggingEvent)cb.get(); + sbuf.append(layout.doLayout(event)); + } + } + + protected boolean eventMarksEndOfLife(ILoggingEvent eventObject) { + Marker marker = eventObject.getMarker(); + if (marker == null) { + return false; + } + return marker.contains(ClassicConstants.FINALIZE_SESSION_MARKER); + } + + + protected Layout makeSubjectLayout(String subjectStr) + { + if (subjectStr == null) { + subjectStr = "%logger{20} - %m"; + } + PatternLayout pl = new PatternLayout(); + pl.setContext(getContext()); + pl.setPattern(subjectStr); + + + + pl.setPostCompileProcessor(null); + pl.start(); + return pl; + } + + protected PatternLayout makeNewToPatternLayout(String toPattern) + { + PatternLayout pl = new PatternLayout(); + pl.setPattern(toPattern + "%nopex"); + return pl; + } + + public boolean isIncludeCallerData() { + return includeCallerData; + } + + public void setIncludeCallerData(boolean includeCallerData) { + this.includeCallerData = includeCallerData; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/net/SSLSocketAppender.java b/src/minecraft/ch/qos/logback/classic/net/SSLSocketAppender.java new file mode 100644 index 0000000..b15c15f --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/net/SSLSocketAppender.java @@ -0,0 +1,54 @@ +package ch.qos.logback.classic.net; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.net.AbstractSSLSocketAppender; +import ch.qos.logback.core.spi.PreSerializationTransformer; + + + + + + + + + + + + + + + + + + + + + + + +public class SSLSocketAppender + extends AbstractSSLSocketAppender +{ + private final PreSerializationTransformer pst = new LoggingEventPreSerializationTransformer(); + + private boolean includeCallerData; + + + public SSLSocketAppender() {} + + + protected void postProcessEvent(ILoggingEvent event) + { + if (includeCallerData) { + event.getCallerData(); + } + } + + public void setIncludeCallerData(boolean includeCallerData) { + this.includeCallerData = includeCallerData; + } + + public PreSerializationTransformer getPST() { + return pst; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/net/SSLSocketReceiver.java b/src/minecraft/ch/qos/logback/classic/net/SSLSocketReceiver.java new file mode 100644 index 0000000..f6093d1 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/net/SSLSocketReceiver.java @@ -0,0 +1,83 @@ +package ch.qos.logback.classic.net; + +import ch.qos.logback.core.net.ssl.ConfigurableSSLSocketFactory; +import ch.qos.logback.core.net.ssl.SSLComponent; +import ch.qos.logback.core.net.ssl.SSLConfiguration; +import ch.qos.logback.core.net.ssl.SSLParametersConfiguration; +import javax.net.SocketFactory; +import javax.net.ssl.SSLContext; + + + + + + + + + + + + + + + + + + + + + + +public class SSLSocketReceiver + extends SocketReceiver + implements SSLComponent +{ + private SSLConfiguration ssl; + private SocketFactory socketFactory; + + public SSLSocketReceiver() {} + + protected SocketFactory getSocketFactory() + { + return socketFactory; + } + + + + protected boolean shouldStart() + { + try + { + SSLContext sslContext = getSsl().createContext(this); + SSLParametersConfiguration parameters = getSsl().getParameters(); + parameters.setContext(getContext()); + socketFactory = new ConfigurableSSLSocketFactory(parameters, sslContext.getSocketFactory()); + + return super.shouldStart(); + } + catch (Exception ex) { + addError(ex.getMessage(), ex); } + return false; + } + + + + + + + public SSLConfiguration getSsl() + { + if (ssl == null) { + ssl = new SSLConfiguration(); + } + return ssl; + } + + + + + public void setSsl(SSLConfiguration ssl) + { + this.ssl = ssl; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/net/SimpleSSLSocketServer.java b/src/minecraft/ch/qos/logback/classic/net/SimpleSSLSocketServer.java new file mode 100644 index 0000000..79d2369 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/net/SimpleSSLSocketServer.java @@ -0,0 +1,100 @@ +package ch.qos.logback.classic.net; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.core.net.ssl.ConfigurableSSLServerSocketFactory; +import ch.qos.logback.core.net.ssl.SSLParametersConfiguration; +import java.security.NoSuchAlgorithmException; +import javax.net.ServerSocketFactory; +import javax.net.ssl.SSLContext; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class SimpleSSLSocketServer + extends SimpleSocketServer +{ + private final ServerSocketFactory socketFactory; + + public static void main(String[] argv) + throws Exception + { + doMain(SimpleSSLSocketServer.class, argv); + } + + + + + + + + public SimpleSSLSocketServer(LoggerContext lc, int port) + throws NoSuchAlgorithmException + { + this(lc, port, SSLContext.getDefault()); + } + + + + + + + + public SimpleSSLSocketServer(LoggerContext lc, int port, SSLContext sslContext) + { + super(lc, port); + if (sslContext == null) { + throw new NullPointerException("SSL context required"); + } + SSLParametersConfiguration parameters = new SSLParametersConfiguration(); + + parameters.setContext(lc); + socketFactory = new ConfigurableSSLServerSocketFactory(parameters, sslContext.getServerSocketFactory()); + } + + + protected ServerSocketFactory getServerSocketFactory() + { + return socketFactory; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/net/SimpleSocketServer.java b/src/minecraft/ch/qos/logback/classic/net/SimpleSocketServer.java new file mode 100644 index 0000000..df5c2b8 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/net/SimpleSocketServer.java @@ -0,0 +1,239 @@ +package ch.qos.logback.classic.net; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.core.joran.spi.JoranException; +import java.io.IOException; +import java.io.PrintStream; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import javax.net.ServerSocketFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class SimpleSocketServer + extends Thread +{ + Logger logger = LoggerFactory.getLogger(SimpleSocketServer.class); + + private final int port; + private final LoggerContext lc; + private boolean closed = false; + private ServerSocket serverSocket; + private List socketNodeList = new ArrayList(); + private CountDownLatch latch; + + public static void main(String[] argv) + throws Exception + { + doMain(SimpleSocketServer.class, argv); + } + + protected static void doMain(Class serverClass, String[] argv) throws Exception + { + int port = -1; + if (argv.length == 2) { + port = parsePortNumber(argv[0]); + } else { + usage("Wrong number of arguments."); + } + + String configFile = argv[1]; + LoggerContext lc = (LoggerContext)LoggerFactory.getILoggerFactory(); + configureLC(lc, configFile); + + SimpleSocketServer sss = new SimpleSocketServer(lc, port); + sss.start(); + } + + public SimpleSocketServer(LoggerContext lc, int port) { + this.lc = lc; + this.port = port; + } + + + public void run() + { + String oldThreadName = Thread.currentThread().getName(); + + try + { + String newThreadName = getServerThreadName(); + Thread.currentThread().setName(newThreadName); + + logger.info("Listening on port " + port); + serverSocket = getServerSocketFactory().createServerSocket(port); + while (!closed) { + logger.info("Waiting to accept a new client."); + signalAlmostReadiness(); + Socket socket = serverSocket.accept(); + logger.info("Connected to client at " + socket.getInetAddress()); + logger.info("Starting new socket node."); + SocketNode newSocketNode = new SocketNode(this, socket, lc); + synchronized (socketNodeList) { + socketNodeList.add(newSocketNode); + } + String clientThreadName = getClientThreadName(socket); + new Thread(newSocketNode, clientThreadName).start(); + } + } catch (Exception e) { + if (closed) { + logger.info("Exception in run method for a closed server. This is normal."); + } else { + logger.error("Unexpected failure in run method", e); + } + } + finally + { + Thread.currentThread().setName(oldThreadName); + } + } + + + + protected String getServerThreadName() + { + return String.format("Logback %s (port %d)", new Object[] { getClass().getSimpleName(), Integer.valueOf(port) }); + } + + + + protected String getClientThreadName(Socket socket) + { + return String.format("Logback SocketNode (client: %s)", new Object[] { socket.getRemoteSocketAddress() }); + } + + + + + + protected ServerSocketFactory getServerSocketFactory() + { + return ServerSocketFactory.getDefault(); + } + + + + + void signalAlmostReadiness() + { + if ((latch != null) && (latch.getCount() != 0L)) + { + latch.countDown(); + } + } + + + + + void setLatch(CountDownLatch latch) + { + this.latch = latch; + } + + + public CountDownLatch getLatch() + { + return latch; + } + + public boolean isClosed() { return closed; } + + public void close() + { + closed = true; + if (serverSocket != null) { + try { + serverSocket.close(); + } catch (IOException e) { + logger.error("Failed to close serverSocket", e); + } finally { + serverSocket = null; + } + } + + logger.info("closing this server"); + synchronized (socketNodeList) { + for (SocketNode sn : socketNodeList) { + sn.close(); + } + } + if (socketNodeList.size() != 0) { + logger.warn("Was expecting a 0-sized socketNodeList after server shutdown"); + } + } + + public void socketNodeClosing(SocketNode sn) + { + logger.debug("Removing {}", sn); + + + + + synchronized (socketNodeList) { + socketNodeList.remove(sn); + } + } + + static void usage(String msg) { + System.err.println(msg); + System.err.println("Usage: java " + SimpleSocketServer.class.getName() + " port configFile"); + + System.exit(1); + } + + static int parsePortNumber(String portStr) { + try { + return Integer.parseInt(portStr); + } catch (NumberFormatException e) { + e.printStackTrace(); + usage("Could not interpret port number [" + portStr + "]."); + } + return -1; + } + + public static void configureLC(LoggerContext lc, String configFile) + throws JoranException + { + JoranConfigurator configurator = new JoranConfigurator(); + lc.reset(); + configurator.setContext(lc); + configurator.doConfigure(configFile); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/net/SocketAcceptor.java b/src/minecraft/ch/qos/logback/classic/net/SocketAcceptor.java new file mode 100644 index 0000000..2dc74c4 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/net/SocketAcceptor.java @@ -0,0 +1,9 @@ +package ch.qos.logback.classic.net; + +class SocketAcceptor + extends Thread +{ + SocketAcceptor() {} + + public void run() {} +} diff --git a/src/minecraft/ch/qos/logback/classic/net/SocketAppender.java b/src/minecraft/ch/qos/logback/classic/net/SocketAppender.java new file mode 100644 index 0000000..7c21a3e --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/net/SocketAppender.java @@ -0,0 +1,59 @@ +package ch.qos.logback.classic.net; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.net.AbstractSocketAppender; +import ch.qos.logback.core.spi.PreSerializationTransformer; + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class SocketAppender + extends AbstractSocketAppender +{ + private static final PreSerializationTransformer pst = new LoggingEventPreSerializationTransformer(); + + + private boolean includeCallerData = false; + + + public SocketAppender() {} + + + protected void postProcessEvent(ILoggingEvent event) + { + if (includeCallerData) { + event.getCallerData(); + } + } + + public void setIncludeCallerData(boolean includeCallerData) { + this.includeCallerData = includeCallerData; + } + + public PreSerializationTransformer getPST() { + return pst; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/net/SocketNode.java b/src/minecraft/ch/qos/logback/classic/net/SocketNode.java new file mode 100644 index 0000000..0aba17d --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/net/SocketNode.java @@ -0,0 +1,129 @@ +package ch.qos.logback.classic.net; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.ILoggingEvent; +import java.io.BufferedInputStream; +import java.io.EOFException; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.SocketException; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class SocketNode + implements Runnable +{ + Socket socket; + LoggerContext context; + ObjectInputStream ois; + SocketAddress remoteSocketAddress; + Logger logger; + boolean closed = false; + SimpleSocketServer socketServer; + + public SocketNode(SimpleSocketServer socketServer, Socket socket, LoggerContext context) { + this.socketServer = socketServer; + this.socket = socket; + remoteSocketAddress = socket.getRemoteSocketAddress(); + this.context = context; + logger = context.getLogger(SocketNode.class); + } + + + + + + + public void run() + { + try + { + ois = new ObjectInputStream(new BufferedInputStream(socket.getInputStream())); + } + catch (Exception e) { + logger.error("Could not open ObjectInputStream to " + socket, e); + closed = true; + } + + + + try + { + while (!closed) + { + ILoggingEvent event = (ILoggingEvent)ois.readObject(); + + + Logger remoteLogger = context.getLogger(event.getLoggerName()); + + if (remoteLogger.isEnabledFor(event.getLevel())) + { + remoteLogger.callAppenders(event); + } + } + } catch (EOFException e) { + logger.info("Caught java.io.EOFException closing connection."); + } catch (SocketException e) { + logger.info("Caught java.net.SocketException closing connection."); + } catch (IOException e) { + logger.info("Caught java.io.IOException: " + e); + logger.info("Closing connection."); + } catch (Exception e) { + logger.error("Unexpected exception. Closing connection.", e); + } + + socketServer.socketNodeClosing(this); + close(); + } + + void close() { + if (closed) { + return; + } + closed = true; + if (ois != null) { + try { + ois.close(); + } catch (IOException e) { + logger.warn("Could not close connection.", e); + } finally { + ois = null; + } + } + } + + public String toString() + { + return getClass().getName() + remoteSocketAddress.toString(); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/net/SocketReceiver.java b/src/minecraft/ch/qos/logback/classic/net/SocketReceiver.java new file mode 100644 index 0000000..a56b023 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/net/SocketReceiver.java @@ -0,0 +1,224 @@ +package ch.qos.logback.classic.net; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.net.DefaultSocketConnector; +import ch.qos.logback.core.net.SocketConnector; +import ch.qos.logback.core.net.SocketConnector.ExceptionHandler; +import ch.qos.logback.core.util.CloseUtil; +import java.io.EOFException; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.net.ConnectException; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.RejectedExecutionException; +import javax.net.SocketFactory; + + + + + + + + + + + + + + + + + + + + +public class SocketReceiver + extends ReceiverBase + implements Runnable, SocketConnector.ExceptionHandler +{ + private static final int DEFAULT_ACCEPT_CONNECTION_DELAY = 5000; + private String remoteHost; + private InetAddress address; + private int port; + private int reconnectionDelay; + private int acceptConnectionTimeout = 5000; + + private String receiverId; + private volatile Socket socket; + private Future connectorTask; + + public SocketReceiver() {} + + protected boolean shouldStart() + { + int errorCount = 0; + if (port == 0) { + errorCount++; + addError("No port was configured for receiver. For more information, please visit http://logback.qos.ch/codes.html#receiver_no_port"); + } + + + if (remoteHost == null) { + errorCount++; + addError("No host name or address was configured for receiver. For more information, please visit http://logback.qos.ch/codes.html#receiver_no_host"); + } + + + if (reconnectionDelay == 0) { + reconnectionDelay = 30000; + } + + if (errorCount == 0) { + try { + address = InetAddress.getByName(remoteHost); + } catch (UnknownHostException ex) { + addError("unknown host: " + remoteHost); + errorCount++; + } + } + + if (errorCount == 0) { + receiverId = ("receiver " + remoteHost + ":" + port + ": "); + } + + return errorCount == 0; + } + + + + protected void onStop() + { + if (socket != null) { + CloseUtil.closeQuietly(socket); + } + } + + protected Runnable getRunnableTask() + { + return this; + } + + + public void run() + { + try + { + LoggerContext lc = (LoggerContext)getContext(); + while (!Thread.currentThread().isInterrupted()) { + SocketConnector connector = createConnector(address, port, 0, reconnectionDelay); + + connectorTask = activateConnector(connector); + if (connectorTask == null) + break; + socket = waitForConnectorToReturnASocket(); + if (socket == null) + break; + dispatchEvents(lc); + } + } + catch (InterruptedException ex) {} + + addInfo("shutting down"); + } + + private SocketConnector createConnector(InetAddress address, int port, int initialDelay, int retryDelay) + { + SocketConnector connector = newConnector(address, port, initialDelay, retryDelay); + + connector.setExceptionHandler(this); + connector.setSocketFactory(getSocketFactory()); + return connector; + } + + private Future activateConnector(SocketConnector connector) + { + try { + return getContext().getExecutorService().submit(connector); + } catch (RejectedExecutionException ex) {} + return null; + } + + private Socket waitForConnectorToReturnASocket() throws InterruptedException + { + try { + Socket s = (Socket)connectorTask.get(); + connectorTask = null; + return s; + } catch (ExecutionException e) {} + return null; + } + + private void dispatchEvents(LoggerContext lc) + { + try { + socket.setSoTimeout(acceptConnectionTimeout); + ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); + socket.setSoTimeout(0); + addInfo(receiverId + "connection established"); + for (;;) { + ILoggingEvent event = (ILoggingEvent)ois.readObject(); + Logger remoteLogger = lc.getLogger(event.getLoggerName()); + if (remoteLogger.isEnabledFor(event.getLevel())) { + remoteLogger.callAppenders(event); + } + } + } catch (EOFException ex) { + addInfo(receiverId + "end-of-stream detected"); + } catch (IOException ex) { + addInfo(receiverId + "connection failed: " + ex); + } catch (ClassNotFoundException ex) { + addInfo(receiverId + "unknown event class: " + ex); + } finally { + CloseUtil.closeQuietly(socket); + socket = null; + addInfo(receiverId + "connection closed"); + } + } + + + + public void connectionFailed(SocketConnector connector, Exception ex) + { + if ((ex instanceof InterruptedException)) { + addInfo("connector interrupted"); + } else if ((ex instanceof ConnectException)) { + addInfo(receiverId + "connection refused"); + } else { + addInfo(receiverId + ex); + } + } + + + protected SocketConnector newConnector(InetAddress address, int port, int initialDelay, int retryDelay) + { + return new DefaultSocketConnector(address, port, initialDelay, retryDelay); + } + + protected SocketFactory getSocketFactory() { + return SocketFactory.getDefault(); + } + + public void setRemoteHost(String remoteHost) { + this.remoteHost = remoteHost; + } + + public void setPort(int port) { + this.port = port; + } + + public void setReconnectionDelay(int reconnectionDelay) { + this.reconnectionDelay = reconnectionDelay; + } + + public void setAcceptConnectionTimeout(int acceptConnectionTimeout) { + this.acceptConnectionTimeout = acceptConnectionTimeout; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/net/SyslogAppender.java b/src/minecraft/ch/qos/logback/classic/net/SyslogAppender.java new file mode 100644 index 0000000..d651b56 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/net/SyslogAppender.java @@ -0,0 +1,183 @@ +package ch.qos.logback.classic.net; + +import ch.qos.logback.classic.PatternLayout; +import ch.qos.logback.classic.pattern.SyslogStartConverter; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.IThrowableProxy; +import ch.qos.logback.classic.spi.StackTraceElementProxy; +import ch.qos.logback.classic.util.LevelToSyslogSeverity; +import ch.qos.logback.core.Layout; +import ch.qos.logback.core.net.SyslogAppenderBase; +import ch.qos.logback.core.net.SyslogOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.Map; + + + + + + + + + + + + + + + + + + + + + + +public class SyslogAppender + extends SyslogAppenderBase +{ + public static final String DEFAULT_SUFFIX_PATTERN = "[%thread] %logger %msg"; + public static final String DEFAULT_STACKTRACE_PATTERN = "\t"; + PatternLayout stackTraceLayout = new PatternLayout(); + String stackTracePattern = "\t"; + + boolean throwableExcluded = false; + + public SyslogAppender() {} + + public void start() { super.start(); + setupStackTraceLayout(); + } + + String getPrefixPattern() { + return "%syslogStart{" + getFacility() + "}%nopex{}"; + } + + public SyslogOutputStream createOutputStream() throws SocketException, UnknownHostException + { + return new SyslogOutputStream(getSyslogHost(), getPort()); + } + + + + + + + + public int getSeverityForEvent(Object eventObject) + { + ILoggingEvent event = (ILoggingEvent)eventObject; + return LevelToSyslogSeverity.convert(event); + } + + protected void postProcess(Object eventObject, OutputStream sw) + { + if (throwableExcluded) { + return; + } + ILoggingEvent event = (ILoggingEvent)eventObject; + IThrowableProxy tp = event.getThrowableProxy(); + + if (tp == null) { + return; + } + String stackTracePrefix = stackTraceLayout.doLayout(event); + boolean isRootException = true; + while (tp != null) { + StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray(); + try { + handleThrowableFirstLine(sw, tp, stackTracePrefix, isRootException); + isRootException = false; + for (StackTraceElementProxy step : stepArray) { + StringBuilder sb = new StringBuilder(); + sb.append(stackTracePrefix).append(step); + sw.write(sb.toString().getBytes()); + sw.flush(); + } + } catch (IOException e) { + break; + } + tp = tp.getCause(); + } + } + + private void handleThrowableFirstLine(OutputStream sw, IThrowableProxy tp, String stackTracePrefix, boolean isRootException) throws IOException + { + StringBuilder sb = new StringBuilder().append(stackTracePrefix); + + if (!isRootException) { + sb.append("Caused by: "); + } + sb.append(tp.getClassName()).append(": ").append(tp.getMessage()); + sw.write(sb.toString().getBytes()); + sw.flush(); + } + + boolean stackTraceHeaderLine(StringBuilder sb, boolean topException) + { + return false; + } + + public Layout buildLayout() { + PatternLayout layout = new PatternLayout(); + layout.getInstanceConverterMap().put("syslogStart", SyslogStartConverter.class.getName()); + + if (suffixPattern == null) { + suffixPattern = "[%thread] %logger %msg"; + } + layout.setPattern(getPrefixPattern() + suffixPattern); + layout.setContext(getContext()); + layout.start(); + return layout; + } + + private void setupStackTraceLayout() { + stackTraceLayout.getInstanceConverterMap().put("syslogStart", SyslogStartConverter.class.getName()); + + + stackTraceLayout.setPattern(getPrefixPattern() + stackTracePattern); + stackTraceLayout.setContext(getContext()); + stackTraceLayout.start(); + } + + public boolean isThrowableExcluded() { + return throwableExcluded; + } + + + + + + + + public void setThrowableExcluded(boolean throwableExcluded) + { + this.throwableExcluded = throwableExcluded; + } + + + + + + + public String getStackTracePattern() + { + return stackTracePattern; + } + + + + + + + + + + public void setStackTracePattern(String stackTracePattern) + { + this.stackTracePattern = stackTracePattern; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/net/server/RemoteAppenderClient.java b/src/minecraft/ch/qos/logback/classic/net/server/RemoteAppenderClient.java new file mode 100644 index 0000000..728adb1 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/net/server/RemoteAppenderClient.java @@ -0,0 +1,10 @@ +package ch.qos.logback.classic.net.server; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.core.net.server.Client; + +abstract interface RemoteAppenderClient + extends Client +{ + public abstract void setLoggerContext(LoggerContext paramLoggerContext); +} diff --git a/src/minecraft/ch/qos/logback/classic/net/server/RemoteAppenderServerListener.java b/src/minecraft/ch/qos/logback/classic/net/server/RemoteAppenderServerListener.java new file mode 100644 index 0000000..cb1c11b --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/net/server/RemoteAppenderServerListener.java @@ -0,0 +1,48 @@ +package ch.qos.logback.classic.net.server; + +import ch.qos.logback.core.net.server.ServerSocketListener; +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; + + + + + + + + + + + + + + + + + + + + + + + + + +class RemoteAppenderServerListener + extends ServerSocketListener +{ + public RemoteAppenderServerListener(ServerSocket serverSocket) + { + super(serverSocket); + } + + + + + protected RemoteAppenderClient createClient(String id, Socket socket) + throws IOException + { + return new RemoteAppenderStreamClient(id, socket); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/net/server/RemoteAppenderServerRunner.java b/src/minecraft/ch/qos/logback/classic/net/server/RemoteAppenderServerRunner.java new file mode 100644 index 0000000..4696ba4 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/net/server/RemoteAppenderServerRunner.java @@ -0,0 +1,52 @@ +package ch.qos.logback.classic.net.server; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.core.net.server.ConcurrentServerRunner; +import ch.qos.logback.core.net.server.ServerListener; +import java.util.concurrent.Executor; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +class RemoteAppenderServerRunner + extends ConcurrentServerRunner +{ + public RemoteAppenderServerRunner(ServerListener listener, Executor executor) + { + super(listener, executor); + } + + + + + protected boolean configureClient(RemoteAppenderClient client) + { + client.setLoggerContext((LoggerContext)getContext()); + return true; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/net/server/RemoteAppenderStreamClient.java b/src/minecraft/ch/qos/logback/classic/net/server/RemoteAppenderStreamClient.java new file mode 100644 index 0000000..507ca8f --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/net/server/RemoteAppenderStreamClient.java @@ -0,0 +1,141 @@ +package ch.qos.logback.classic.net.server; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.util.CloseUtil; +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.net.Socket; + + + + + + + + + + + + + + + + + + + + + + + + + +class RemoteAppenderStreamClient + implements RemoteAppenderClient +{ + private final String id; + private final Socket socket; + private final InputStream inputStream; + private LoggerContext lc; + private Logger logger; + + public RemoteAppenderStreamClient(String id, Socket socket) + { + this.id = id; + this.socket = socket; + inputStream = null; + } + + + + + + + + + + public RemoteAppenderStreamClient(String id, InputStream inputStream) + { + this.id = id; + socket = null; + this.inputStream = inputStream; + } + + + + public void setLoggerContext(LoggerContext lc) + { + this.lc = lc; + logger = lc.getLogger(getClass().getPackage().getName()); + } + + + + public void close() + { + if (socket == null) return; + CloseUtil.closeQuietly(socket); + } + + + + public void run() + { + logger.info(this + ": connected"); + ObjectInputStream ois = null; + try { + ois = createObjectInputStream(); + for (;;) + { + ILoggingEvent event = (ILoggingEvent)ois.readObject(); + + + Logger remoteLogger = lc.getLogger(event.getLoggerName()); + + if (remoteLogger.isEnabledFor(event.getLevel())) + { + remoteLogger.callAppenders(event); + } + + } + + + } + catch (EOFException ex) {}catch (IOException ex) + { + logger.info(this + ": " + ex); + } + catch (ClassNotFoundException ex) { + logger.error(this + ": unknown event class"); + } + catch (RuntimeException ex) { + logger.error(this + ": " + ex); + } + finally { + if (ois != null) { + CloseUtil.closeQuietly(ois); + } + close(); + logger.info(this + ": connection closed"); + } + } + + private ObjectInputStream createObjectInputStream() throws IOException { + if (inputStream != null) { + return new ObjectInputStream(inputStream); + } + return new ObjectInputStream(socket.getInputStream()); + } + + + + + public String toString() + { + return "client " + id; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/net/server/SSLServerSocketAppender.java b/src/minecraft/ch/qos/logback/classic/net/server/SSLServerSocketAppender.java new file mode 100644 index 0000000..5067ff9 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/net/server/SSLServerSocketAppender.java @@ -0,0 +1,53 @@ +package ch.qos.logback.classic.net.server; + +import ch.qos.logback.classic.net.LoggingEventPreSerializationTransformer; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.net.server.SSLServerSocketAppenderBase; +import ch.qos.logback.core.spi.PreSerializationTransformer; + + + + + + + + + + + + + + + + + + + +public class SSLServerSocketAppender + extends SSLServerSocketAppenderBase +{ + private static final PreSerializationTransformer pst = new LoggingEventPreSerializationTransformer(); + private boolean includeCallerData; + + public SSLServerSocketAppender() {} + + protected void postProcessEvent(ILoggingEvent event) + { + if (isIncludeCallerData()) { + event.getCallerData(); + } + } + + protected PreSerializationTransformer getPST() + { + return pst; + } + + public boolean isIncludeCallerData() { + return includeCallerData; + } + + public void setIncludeCallerData(boolean includeCallerData) { + this.includeCallerData = includeCallerData; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/net/server/SSLServerSocketReceiver.java b/src/minecraft/ch/qos/logback/classic/net/server/SSLServerSocketReceiver.java new file mode 100644 index 0000000..088cae2 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/net/server/SSLServerSocketReceiver.java @@ -0,0 +1,69 @@ +package ch.qos.logback.classic.net.server; + +import ch.qos.logback.core.net.ssl.ConfigurableSSLServerSocketFactory; +import ch.qos.logback.core.net.ssl.SSLComponent; +import ch.qos.logback.core.net.ssl.SSLConfiguration; +import ch.qos.logback.core.net.ssl.SSLParametersConfiguration; +import javax.net.ServerSocketFactory; +import javax.net.ssl.SSLContext; + + + + + + + + + + + + + + + + + + + +public class SSLServerSocketReceiver + extends ServerSocketReceiver + implements SSLComponent +{ + private SSLConfiguration ssl; + private ServerSocketFactory socketFactory; + + public SSLServerSocketReceiver() {} + + protected ServerSocketFactory getServerSocketFactory() + throws Exception + { + if (socketFactory == null) { + SSLContext sslContext = getSsl().createContext(this); + SSLParametersConfiguration parameters = getSsl().getParameters(); + parameters.setContext(getContext()); + socketFactory = new ConfigurableSSLServerSocketFactory(parameters, sslContext.getServerSocketFactory()); + } + + return socketFactory; + } + + + + + + public SSLConfiguration getSsl() + { + if (ssl == null) { + ssl = new SSLConfiguration(); + } + return ssl; + } + + + + + public void setSsl(SSLConfiguration ssl) + { + this.ssl = ssl; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/net/server/ServerSocketAppender.java b/src/minecraft/ch/qos/logback/classic/net/server/ServerSocketAppender.java new file mode 100644 index 0000000..b346698 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/net/server/ServerSocketAppender.java @@ -0,0 +1,55 @@ +package ch.qos.logback.classic.net.server; + +import ch.qos.logback.classic.net.LoggingEventPreSerializationTransformer; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.net.server.AbstractServerSocketAppender; +import ch.qos.logback.core.spi.PreSerializationTransformer; + + + + + + + + + + + + + + + + + + + + + +public class ServerSocketAppender + extends AbstractServerSocketAppender +{ + private static final PreSerializationTransformer pst = new LoggingEventPreSerializationTransformer(); + private boolean includeCallerData; + + public ServerSocketAppender() {} + + protected void postProcessEvent(ILoggingEvent event) + { + if (isIncludeCallerData()) { + event.getCallerData(); + } + } + + protected PreSerializationTransformer getPST() + { + return pst; + } + + public boolean isIncludeCallerData() { + return includeCallerData; + } + + public void setIncludeCallerData(boolean includeCallerData) { + this.includeCallerData = includeCallerData; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/net/server/ServerSocketReceiver.java b/src/minecraft/ch/qos/logback/classic/net/server/ServerSocketReceiver.java new file mode 100644 index 0000000..e171017 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/net/server/ServerSocketReceiver.java @@ -0,0 +1,177 @@ +package ch.qos.logback.classic.net.server; + +import ch.qos.logback.classic.net.ReceiverBase; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.net.server.ServerListener; +import ch.qos.logback.core.net.server.ServerRunner; +import ch.qos.logback.core.util.CloseUtil; +import java.io.IOException; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.UnknownHostException; +import java.util.concurrent.Executor; +import javax.net.ServerSocketFactory; + + + + + + + + + + + + + + + + + + + + + + + + +public class ServerSocketReceiver + extends ReceiverBase +{ + public static final int DEFAULT_BACKLOG = 50; + private int port = 4560; + private int backlog = 50; + + private String address; + private ServerSocket serverSocket; + private ServerRunner runner; + + public ServerSocketReceiver() {} + + protected boolean shouldStart() + { + try + { + ServerSocket serverSocket = getServerSocketFactory().createServerSocket(getPort(), getBacklog(), getInetAddress()); + + + ServerListener listener = createServerListener(serverSocket); + + + runner = createServerRunner(listener, getContext().getExecutorService()); + runner.setContext(getContext()); + return true; + } + catch (Exception ex) { + addError("server startup error: " + ex, ex); + CloseUtil.closeQuietly(this.serverSocket); } + return false; + } + + + protected ServerListener createServerListener(ServerSocket socket) + { + return new RemoteAppenderServerListener(socket); + } + + + protected ServerRunner createServerRunner(ServerListener listener, Executor executor) + { + return new RemoteAppenderServerRunner(listener, executor); + } + + protected Runnable getRunnableTask() + { + return runner; + } + + + protected void onStop() + { + try + { + if (runner == null) return; + runner.stop(); + } + catch (IOException ex) { + addError("server shutdown error: " + ex, ex); + } + } + + + + + + + protected ServerSocketFactory getServerSocketFactory() + throws Exception + { + return ServerSocketFactory.getDefault(); + } + + + + + protected InetAddress getInetAddress() + throws UnknownHostException + { + if (getAddress() == null) return null; + return InetAddress.getByName(getAddress()); + } + + + + + public int getPort() + { + return port; + } + + + + + public void setPort(int port) + { + this.port = port; + } + + + + + + + + + public int getBacklog() + { + return backlog; + } + + + + + + + + + public void setBacklog(int backlog) + { + this.backlog = backlog; + } + + + + + public String getAddress() + { + return address; + } + + + + + public void setAddress(String address) + { + this.address = address; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/Abbreviator.java b/src/minecraft/ch/qos/logback/classic/pattern/Abbreviator.java new file mode 100644 index 0000000..93f38bb --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/Abbreviator.java @@ -0,0 +1,6 @@ +package ch.qos.logback.classic.pattern; + +public abstract interface Abbreviator +{ + public abstract String abbreviate(String paramString); +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/CallerDataConverter.java b/src/minecraft/ch/qos/logback/classic/pattern/CallerDataConverter.java new file mode 100644 index 0000000..cb4b0ab --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/CallerDataConverter.java @@ -0,0 +1,174 @@ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.spi.CallerData; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.boolex.EvaluationException; +import ch.qos.logback.core.boolex.EventEvaluator; +import ch.qos.logback.core.status.ErrorStatus; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + + + + + + + + + + + + + + + + + + + + + +public class CallerDataConverter + extends ClassicConverter +{ + public static final String DEFAULT_CALLER_LINE_PREFIX = "Caller+"; + public static final String DEFAULT_RANGE_DELIMITER = ".."; + private int depthStart = 0; + private int depthEnd = 5; + List> evaluatorList = null; + + + final int MAX_ERROR_COUNT = 4; + int errorCount = 0; + + public CallerDataConverter() {} + + public void start() { String depthStr = getFirstOption(); + if (depthStr == null) { + return; + } + try + { + if (isRange(depthStr)) { + String[] numbers = splitRange(depthStr); + if (numbers.length == 2) { + depthStart = Integer.parseInt(numbers[0]); + depthEnd = Integer.parseInt(numbers[1]); + checkRange(); + } else { + addError("Failed to parse depth option as range [" + depthStr + "]"); + } + } else { + depthEnd = Integer.parseInt(depthStr); + } + } catch (NumberFormatException nfe) { + addError("Failed to parse depth option [" + depthStr + "]", nfe); + } + + List optionList = getOptionList(); + + if ((optionList != null) && (optionList.size() > 1)) { + int optionListSize = optionList.size(); + for (int i = 1; i < optionListSize; i++) { + String evaluatorStr = (String)optionList.get(i); + Context context = getContext(); + if (context != null) { + Map evaluatorMap = (Map)context.getObject("EVALUATOR_MAP"); + + EventEvaluator ee = (EventEvaluator)evaluatorMap.get(evaluatorStr); + + if (ee != null) { + addEvaluator(ee); + } + } + } + } + } + + private boolean isRange(String depthStr) { + return depthStr.contains(getDefaultRangeDelimiter()); + } + + private String[] splitRange(String depthStr) { + return depthStr.split(Pattern.quote(getDefaultRangeDelimiter()), 2); + } + + private void checkRange() { + if ((depthStart < 0) || (depthEnd < 0)) { + addError("Invalid depthStart/depthEnd range [" + depthStart + ", " + depthEnd + "] (negative values are not allowed)"); + } else if (depthStart >= depthEnd) { + addError("Invalid depthEnd range [" + depthStart + ", " + depthEnd + "] (start greater or equal to end)"); + } + } + + private void addEvaluator(EventEvaluator ee) { + if (evaluatorList == null) { + evaluatorList = new ArrayList(); + } + evaluatorList.add(ee); + } + + public String convert(ILoggingEvent le) { + StringBuilder buf = new StringBuilder(); + + if (evaluatorList != null) { + boolean printCallerData = false; + for (int i = 0; i < evaluatorList.size(); i++) { + EventEvaluator ee = (EventEvaluator)evaluatorList.get(i); + try { + if (ee.evaluate(le)) { + printCallerData = true; + break; + } + } catch (EvaluationException eex) { + errorCount += 1; + if (errorCount < 4) { + addError("Exception thrown for evaluator named [" + ee.getName() + "]", eex); + } + else if (errorCount == 4) { + ErrorStatus errorStatus = new ErrorStatus("Exception thrown for evaluator named [" + ee.getName() + "].", this, eex); + + + errorStatus.add(new ErrorStatus("This was the last warning about this evaluator's errors.We don't want the StatusManager to get flooded.", this)); + + + addStatus(errorStatus); + } + } + } + + + if (!printCallerData) { + return ""; + } + } + + StackTraceElement[] cda = le.getCallerData(); + if ((cda != null) && (cda.length > depthStart)) { + int limit = depthEnd < cda.length ? depthEnd : cda.length; + + for (int i = depthStart; i < limit; i++) { + buf.append(getCallerLinePrefix()); + buf.append(i); + buf.append("\t at "); + buf.append(cda[i]); + buf.append(CoreConstants.LINE_SEPARATOR); + } + return buf.toString(); + } + return CallerData.CALLER_DATA_NA; + } + + protected String getCallerLinePrefix() + { + return "Caller+"; + } + + protected String getDefaultRangeDelimiter() { + return ".."; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/ClassNameOnlyAbbreviator.java b/src/minecraft/ch/qos/logback/classic/pattern/ClassNameOnlyAbbreviator.java new file mode 100644 index 0000000..8917dcf --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/ClassNameOnlyAbbreviator.java @@ -0,0 +1,36 @@ +package ch.qos.logback.classic.pattern; + + + + + + + + + + + +public class ClassNameOnlyAbbreviator + implements Abbreviator +{ + public ClassNameOnlyAbbreviator() {} + + + + + + + + + + + + public String abbreviate(String fqClassName) + { + int lastIndex = fqClassName.lastIndexOf('.'); + if (lastIndex != -1) { + return fqClassName.substring(lastIndex + 1, fqClassName.length()); + } + return fqClassName; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/ClassOfCallerConverter.java b/src/minecraft/ch/qos/logback/classic/pattern/ClassOfCallerConverter.java new file mode 100644 index 0000000..1f7cf3d --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/ClassOfCallerConverter.java @@ -0,0 +1,29 @@ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; + + + + + + + + + + + + +public class ClassOfCallerConverter + extends NamedConverter +{ + public ClassOfCallerConverter() {} + + protected String getFullyQualifiedName(ILoggingEvent event) + { + StackTraceElement[] cda = event.getCallerData(); + if ((cda != null) && (cda.length > 0)) { + return cda[0].getClassName(); + } + return "?"; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/ClassicConverter.java b/src/minecraft/ch/qos/logback/classic/pattern/ClassicConverter.java new file mode 100644 index 0000000..a2d6ab3 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/ClassicConverter.java @@ -0,0 +1,10 @@ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.pattern.DynamicConverter; + +public abstract class ClassicConverter + extends DynamicConverter +{ + public ClassicConverter() {} +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/ContextNameConverter.java b/src/minecraft/ch/qos/logback/classic/pattern/ContextNameConverter.java new file mode 100644 index 0000000..41d82ce --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/ContextNameConverter.java @@ -0,0 +1,31 @@ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggerContextVO; + + + + + + + + + + + + + + + + + +public class ContextNameConverter + extends ClassicConverter +{ + public ContextNameConverter() {} + + public String convert(ILoggingEvent event) + { + return event.getLoggerContextVO().getName(); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/DateConverter.java b/src/minecraft/ch/qos/logback/classic/pattern/DateConverter.java new file mode 100644 index 0000000..9110ce9 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/DateConverter.java @@ -0,0 +1,65 @@ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.util.CachingDateFormatter; +import java.util.List; +import java.util.TimeZone; + + + + + + + + + + + + + + + +public class DateConverter + extends ClassicConverter +{ + long lastTimestamp = -1L; + String timestampStrCache = null; + CachingDateFormatter cachingDateFormatter = null; + + public DateConverter() {} + + public void start() { + String datePattern = getFirstOption(); + if (datePattern == null) { + datePattern = "yyyy-MM-dd HH:mm:ss,SSS"; + } + + if (datePattern.equals("ISO8601")) { + datePattern = "yyyy-MM-dd HH:mm:ss,SSS"; + } + try + { + cachingDateFormatter = new CachingDateFormatter(datePattern); + } + catch (IllegalArgumentException e) + { + addWarn("Could not instantiate SimpleDateFormat with pattern " + datePattern, e); + + + cachingDateFormatter = new CachingDateFormatter("yyyy-MM-dd HH:mm:ss,SSS"); + } + + List optionList = getOptionList(); + + + if ((optionList != null) && (optionList.size() > 1)) { + TimeZone tz = TimeZone.getTimeZone((String)optionList.get(1)); + cachingDateFormatter.setTimeZone(tz); + } + } + + public String convert(ILoggingEvent le) { + long timestamp = le.getTimeStamp(); + return cachingDateFormatter.format(timestamp); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/EnsureExceptionHandling.java b/src/minecraft/ch/qos/logback/classic/pattern/EnsureExceptionHandling.java new file mode 100644 index 0000000..d0287f8 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/EnsureExceptionHandling.java @@ -0,0 +1,69 @@ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.pattern.Converter; +import ch.qos.logback.core.pattern.ConverterUtil; +import ch.qos.logback.core.pattern.PostCompileProcessor; + + + + + + + + + + + + + + + + + + + + + + + + + + +public class EnsureExceptionHandling + implements PostCompileProcessor +{ + public EnsureExceptionHandling() {} + + public void process(Converter head) + { + if (head == null) + { + throw new IllegalArgumentException("cannot process empty chain"); + } + if (!chainHandlesThrowable(head)) { + Converter tail = ConverterUtil.findTail(head); + Converter exConverter = new ExtendedThrowableProxyConverter(); + tail.setNext(exConverter); + } + } + + + + + + + + + public boolean chainHandlesThrowable(Converter head) + { + Converter c = head; + while (c != null) { + if ((c instanceof ThrowableHandlingConverter)) { + return true; + } + c = c.getNext(); + } + return false; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/ExtendedThrowableProxyConverter.java b/src/minecraft/ch/qos/logback/classic/pattern/ExtendedThrowableProxyConverter.java new file mode 100644 index 0000000..c9f3cec --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/ExtendedThrowableProxyConverter.java @@ -0,0 +1,28 @@ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.StackTraceElementProxy; +import ch.qos.logback.classic.spi.ThrowableProxyUtil; + + + + + + + + + + + +public class ExtendedThrowableProxyConverter + extends ThrowableProxyConverter +{ + public ExtendedThrowableProxyConverter() {} + + protected void extraData(StringBuilder builder, StackTraceElementProxy step) + { + ThrowableProxyUtil.subjoinPackagingData(builder, step); + } + + protected void prepareLoggingEvent(ILoggingEvent event) {} +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/FileOfCallerConverter.java b/src/minecraft/ch/qos/logback/classic/pattern/FileOfCallerConverter.java new file mode 100644 index 0000000..0259798 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/FileOfCallerConverter.java @@ -0,0 +1,28 @@ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; + + + + + + + + + + + +public class FileOfCallerConverter + extends ClassicConverter +{ + public FileOfCallerConverter() {} + + public String convert(ILoggingEvent le) + { + StackTraceElement[] cda = le.getCallerData(); + if ((cda != null) && (cda.length > 0)) { + return cda[0].getFileName(); + } + return "?"; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/LevelConverter.java b/src/minecraft/ch/qos/logback/classic/pattern/LevelConverter.java new file mode 100644 index 0000000..6c67f05 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/LevelConverter.java @@ -0,0 +1,28 @@ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; + + + + + + + + + + + + + + +public class LevelConverter + extends ClassicConverter +{ + public LevelConverter() {} + + public String convert(ILoggingEvent le) + { + return le.getLevel().toString(); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/LineOfCallerConverter.java b/src/minecraft/ch/qos/logback/classic/pattern/LineOfCallerConverter.java new file mode 100644 index 0000000..6dc37c7 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/LineOfCallerConverter.java @@ -0,0 +1,28 @@ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; + + + + + + + + + + + +public class LineOfCallerConverter + extends ClassicConverter +{ + public LineOfCallerConverter() {} + + public String convert(ILoggingEvent le) + { + StackTraceElement[] cda = le.getCallerData(); + if ((cda != null) && (cda.length > 0)) { + return Integer.toString(cda[0].getLineNumber()); + } + return "?"; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/LineSeparatorConverter.java b/src/minecraft/ch/qos/logback/classic/pattern/LineSeparatorConverter.java new file mode 100644 index 0000000..ef77741 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/LineSeparatorConverter.java @@ -0,0 +1,24 @@ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.CoreConstants; + + + + + + + + + + +public class LineSeparatorConverter + extends ClassicConverter +{ + public LineSeparatorConverter() {} + + public String convert(ILoggingEvent event) + { + return CoreConstants.LINE_SEPARATOR; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/LocalSequenceNumberConverter.java b/src/minecraft/ch/qos/logback/classic/pattern/LocalSequenceNumberConverter.java new file mode 100644 index 0000000..d43e544 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/LocalSequenceNumberConverter.java @@ -0,0 +1,35 @@ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import java.util.concurrent.atomic.AtomicLong; + + + + + + + + + + + + + + + + + + + + + + +public class LocalSequenceNumberConverter + extends ClassicConverter +{ + AtomicLong sequenceNumber = new AtomicLong(System.currentTimeMillis()); + + public LocalSequenceNumberConverter() {} + + public String convert(ILoggingEvent event) { return Long.toString(sequenceNumber.getAndIncrement()); } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/LoggerConverter.java b/src/minecraft/ch/qos/logback/classic/pattern/LoggerConverter.java new file mode 100644 index 0000000..bd58c5f --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/LoggerConverter.java @@ -0,0 +1,23 @@ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; + + + + + + + + + + +public class LoggerConverter + extends NamedConverter +{ + public LoggerConverter() {} + + protected String getFullyQualifiedName(ILoggingEvent event) + { + return event.getLoggerName(); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/MDCConverter.java b/src/minecraft/ch/qos/logback/classic/pattern/MDCConverter.java new file mode 100644 index 0000000..46a2846 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/MDCConverter.java @@ -0,0 +1,81 @@ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.util.OptionHelper; +import java.util.Map; +import java.util.Map.Entry; + + + + + + + + + + + + + + +public class MDCConverter + extends ClassicConverter +{ + private String key; + private String defaultValue = ""; + + public MDCConverter() {} + + public void start() { String[] keyInfo = OptionHelper.extractDefaultReplacement(getFirstOption()); + key = keyInfo[0]; + if (keyInfo[1] != null) { + defaultValue = keyInfo[1]; + } + super.start(); + } + + public void stop() + { + key = null; + super.stop(); + } + + public String convert(ILoggingEvent event) + { + Map mdcPropertyMap = event.getMDCPropertyMap(); + + if (mdcPropertyMap == null) { + return defaultValue; + } + + if (key == null) { + return outputMDCForAllKeys(mdcPropertyMap); + } + + String value = (String)event.getMDCPropertyMap().get(key); + if (value != null) { + return value; + } + return defaultValue; + } + + + + + + private String outputMDCForAllKeys(Map mdcPropertyMap) + { + StringBuilder buf = new StringBuilder(); + boolean first = true; + for (Map.Entry entry : mdcPropertyMap.entrySet()) { + if (first) { + first = false; + } else { + buf.append(", "); + } + + buf.append((String)entry.getKey()).append('=').append((String)entry.getValue()); + } + return buf.toString(); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/MarkerConverter.java b/src/minecraft/ch/qos/logback/classic/pattern/MarkerConverter.java new file mode 100644 index 0000000..4582f8a --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/MarkerConverter.java @@ -0,0 +1,36 @@ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import org.slf4j.Marker; + + + + + + + + + + + + + + + + + +public class MarkerConverter + extends ClassicConverter +{ + public MarkerConverter() {} + + private static String EMPTY = ""; + + public String convert(ILoggingEvent le) { + Marker marker = le.getMarker(); + if (marker == null) { + return EMPTY; + } + return marker.toString(); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/MessageConverter.java b/src/minecraft/ch/qos/logback/classic/pattern/MessageConverter.java new file mode 100644 index 0000000..864a541 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/MessageConverter.java @@ -0,0 +1,28 @@ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; + + + + + + + + + + + + + + + +public class MessageConverter + extends ClassicConverter +{ + public MessageConverter() {} + + public String convert(ILoggingEvent event) + { + return event.getFormattedMessage(); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/MethodOfCallerConverter.java b/src/minecraft/ch/qos/logback/classic/pattern/MethodOfCallerConverter.java new file mode 100644 index 0000000..cb0a55e --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/MethodOfCallerConverter.java @@ -0,0 +1,28 @@ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; + + + + + + + + + + + +public class MethodOfCallerConverter + extends ClassicConverter +{ + public MethodOfCallerConverter() {} + + public String convert(ILoggingEvent le) + { + StackTraceElement[] cda = le.getCallerData(); + if ((cda != null) && (cda.length > 0)) { + return cda[0].getMethodName(); + } + return "?"; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/NamedConverter.java b/src/minecraft/ch/qos/logback/classic/pattern/NamedConverter.java new file mode 100644 index 0000000..cfa5dea --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/NamedConverter.java @@ -0,0 +1,55 @@ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; + + + + + + + + + + + + + +public abstract class NamedConverter + extends ClassicConverter +{ + Abbreviator abbreviator = null; + + + + public NamedConverter() {} + + + protected abstract String getFullyQualifiedName(ILoggingEvent paramILoggingEvent); + + + public void start() + { + String optStr = getFirstOption(); + if (optStr != null) { + try { + int targetLen = Integer.parseInt(optStr); + if (targetLen == 0) { + abbreviator = new ClassNameOnlyAbbreviator(); + } else if (targetLen > 0) { + abbreviator = new TargetLengthBasedClassNameAbbreviator(targetLen); + } + } + catch (NumberFormatException nfe) {} + } + } + + public String convert(ILoggingEvent event) + { + String fqn = getFullyQualifiedName(event); + + if (abbreviator == null) { + return fqn; + } + return abbreviator.abbreviate(fqn); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/NopThrowableInformationConverter.java b/src/minecraft/ch/qos/logback/classic/pattern/NopThrowableInformationConverter.java new file mode 100644 index 0000000..3a9a5e5 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/NopThrowableInformationConverter.java @@ -0,0 +1,42 @@ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class NopThrowableInformationConverter + extends ThrowableHandlingConverter +{ + public NopThrowableInformationConverter() {} + + public String convert(ILoggingEvent event) + { + return ""; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/PropertyConverter.java b/src/minecraft/ch/qos/logback/classic/pattern/PropertyConverter.java new file mode 100644 index 0000000..37a6ae6 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/PropertyConverter.java @@ -0,0 +1,45 @@ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggerContextVO; +import java.util.Map; + + + + + + + + + + + +public final class PropertyConverter + extends ClassicConverter +{ + String key; + + public PropertyConverter() {} + + public void start() + { + String optStr = getFirstOption(); + if (optStr != null) { + key = optStr; + super.start(); + } + } + + public String convert(ILoggingEvent event) { + if (key == null) { + return "Property_HAS_NO_KEY"; + } + LoggerContextVO lcvo = event.getLoggerContextVO(); + Map map = lcvo.getPropertyMap(); + String val = (String)map.get(key); + if (val != null) { + return val; + } + return System.getProperty(key); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/RelativeTimeConverter.java b/src/minecraft/ch/qos/logback/classic/pattern/RelativeTimeConverter.java new file mode 100644 index 0000000..5c20b9f --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/RelativeTimeConverter.java @@ -0,0 +1,35 @@ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggerContextVO; + + + + + + + + + + +public class RelativeTimeConverter + extends ClassicConverter +{ + public RelativeTimeConverter() {} + + long lastTimestamp = -1L; + String timesmapCache = null; + + public String convert(ILoggingEvent event) { + long now = event.getTimeStamp(); + + synchronized (this) + { + if (now != lastTimestamp) { + lastTimestamp = now; + timesmapCache = Long.toString(now - event.getLoggerContextVO().getBirthTime()); + } + return timesmapCache; + } + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/RootCauseFirstThrowableProxyConverter.java b/src/minecraft/ch/qos/logback/classic/pattern/RootCauseFirstThrowableProxyConverter.java new file mode 100644 index 0000000..d3da38d --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/RootCauseFirstThrowableProxyConverter.java @@ -0,0 +1,52 @@ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.spi.IThrowableProxy; +import ch.qos.logback.classic.spi.ThrowableProxyUtil; +import ch.qos.logback.core.CoreConstants; + + + + + + + + + + + + + + + +public class RootCauseFirstThrowableProxyConverter + extends ExtendedThrowableProxyConverter +{ + public RootCauseFirstThrowableProxyConverter() {} + + protected String throwableProxyToString(IThrowableProxy tp) + { + StringBuilder buf = new StringBuilder(2048); + recursiveAppendRootCauseFirst(buf, null, 1, tp); + return buf.toString(); + } + + protected void recursiveAppendRootCauseFirst(StringBuilder sb, String prefix, int indent, IThrowableProxy tp) { + if (tp.getCause() != null) { + recursiveAppendRootCauseFirst(sb, prefix, indent, tp.getCause()); + prefix = null; + } + ThrowableProxyUtil.indent(sb, indent - 1); + if (prefix != null) { + sb.append(prefix); + } + ThrowableProxyUtil.subjoinFirstLineRootCauseFirst(sb, tp); + sb.append(CoreConstants.LINE_SEPARATOR); + subjoinSTEPArray(sb, indent, tp); + IThrowableProxy[] suppressed = tp.getSuppressed(); + if (suppressed != null) { + for (IThrowableProxy current : suppressed) { + recursiveAppendRootCauseFirst(sb, "Suppressed: ", indent + 1, current); + } + } + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/SyslogStartConverter.java b/src/minecraft/ch/qos/logback/classic/pattern/SyslogStartConverter.java new file mode 100644 index 0000000..49f8bf3 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/SyslogStartConverter.java @@ -0,0 +1,110 @@ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.util.LevelToSyslogSeverity; +import ch.qos.logback.core.net.SyslogAppenderBase; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.Locale; + + + + + + + + + + + + + + +public class SyslogStartConverter + extends ClassicConverter +{ + long lastTimestamp = -1L; + String timesmapStr = null; + SimpleDateFormat simpleMonthFormat; + SimpleDateFormat simpleTimeFormat; + private final Calendar calendar = Calendar.getInstance(Locale.US); + String localHostName; + int facility; + + public SyslogStartConverter() {} + + public void start() { int errorCount = 0; + + String facilityStr = getFirstOption(); + if (facilityStr == null) { + addError("was expecting a facility string as an option"); + return; + } + + facility = SyslogAppenderBase.facilityStringToint(facilityStr); + + localHostName = getLocalHostname(); + try + { + simpleMonthFormat = new SimpleDateFormat("MMM", Locale.US); + simpleTimeFormat = new SimpleDateFormat("HH:mm:ss", Locale.US); + } catch (IllegalArgumentException e) { + addError("Could not instantiate SimpleDateFormat", e); + errorCount++; + } + + if (errorCount == 0) { + super.start(); + } + } + + public String convert(ILoggingEvent event) { + StringBuilder sb = new StringBuilder(); + + int pri = facility + LevelToSyslogSeverity.convert(event); + + sb.append("<"); + sb.append(pri); + sb.append(">"); + sb.append(computeTimeStampString(event.getTimeStamp())); + sb.append(' '); + sb.append(localHostName); + sb.append(' '); + + return sb.toString(); + } + + + + + + public String getLocalHostname() + { + try + { + InetAddress addr = InetAddress.getLocalHost(); + return addr.getHostName(); + } catch (UnknownHostException uhe) { + addError("Could not determine local host name", uhe); } + return "UNKNOWN_LOCALHOST"; + } + + String computeTimeStampString(long now) + { + synchronized (this) + { + + if (now / 1000L != lastTimestamp) { + lastTimestamp = (now / 1000L); + Date nowDate = new Date(now); + calendar.setTime(nowDate); + timesmapStr = String.format("%s %2d %s", new Object[] { simpleMonthFormat.format(nowDate), Integer.valueOf(calendar.get(5)), simpleTimeFormat.format(nowDate) }); + } + + return timesmapStr; + } + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/TargetLengthBasedClassNameAbbreviator.java b/src/minecraft/ch/qos/logback/classic/pattern/TargetLengthBasedClassNameAbbreviator.java new file mode 100644 index 0000000..65c2abc --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/TargetLengthBasedClassNameAbbreviator.java @@ -0,0 +1,128 @@ +package ch.qos.logback.classic.pattern; + +import java.io.PrintStream; + + + + + + + + + + + + + +public class TargetLengthBasedClassNameAbbreviator + implements Abbreviator +{ + final int targetLength; + + public TargetLengthBasedClassNameAbbreviator(int targetLength) + { + this.targetLength = targetLength; + } + + public String abbreviate(String fqClassName) { + StringBuilder buf = new StringBuilder(targetLength); + if (fqClassName == null) { + throw new IllegalArgumentException("Class name may not be null"); + } + + int inLen = fqClassName.length(); + if (inLen < targetLength) { + return fqClassName; + } + + int[] dotIndexesArray = new int[16]; + + + int[] lengthArray = new int[17]; + + int dotCount = computeDotIndexes(fqClassName, dotIndexesArray); + + + + + if (dotCount == 0) { + return fqClassName; + } + + computeLengthArray(fqClassName, dotIndexesArray, lengthArray, dotCount); + + for (int i = 0; i <= dotCount; i++) { + if (i == 0) { + buf.append(fqClassName.substring(0, lengthArray[i] - 1)); + } else { + buf.append(fqClassName.substring(dotIndexesArray[(i - 1)], dotIndexesArray[(i - 1)] + lengthArray[i])); + } + } + + + + return buf.toString(); + } + + static int computeDotIndexes(String className, int[] dotArray) { + int dotCount = 0; + int k = 0; + + for (;;) + { + k = className.indexOf('.', k); + if ((k == -1) || (dotCount >= 16)) break; + dotArray[dotCount] = k; + dotCount++; + k++; + } + + + + return dotCount; + } + + void computeLengthArray(String className, int[] dotArray, int[] lengthArray, int dotCount) + { + int toTrim = className.length() - targetLength; + + + + + + for (int i = 0; i < dotCount; i++) { + int previousDotPosition = -1; + if (i > 0) { + previousDotPosition = dotArray[(i - 1)]; + } + int available = dotArray[i] - previousDotPosition - 1; + + + int len = available < 1 ? available : 1; + + + if (toTrim > 0) { + len = available < 1 ? available : 1; + } else { + len = available; + } + toTrim -= available - len; + lengthArray[i] = (len + 1); + } + + int lastDotIndex = dotCount - 1; + lengthArray[dotCount] = (className.length() - dotArray[lastDotIndex]); + } + + static void printArray(String msg, int[] ia) { + System.out.print(msg); + for (int i = 0; i < ia.length; i++) { + if (i == 0) { + System.out.print(ia[i]); + } else { + System.out.print(", " + ia[i]); + } + } + System.out.println(); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/ThreadConverter.java b/src/minecraft/ch/qos/logback/classic/pattern/ThreadConverter.java new file mode 100644 index 0000000..cdb3bec --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/ThreadConverter.java @@ -0,0 +1,28 @@ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; + + + + + + + + + + + + + + + +public class ThreadConverter + extends ClassicConverter +{ + public ThreadConverter() {} + + public String convert(ILoggingEvent event) + { + return event.getThreadName(); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/ThrowableHandlingConverter.java b/src/minecraft/ch/qos/logback/classic/pattern/ThrowableHandlingConverter.java new file mode 100644 index 0000000..423f91c --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/ThrowableHandlingConverter.java @@ -0,0 +1,27 @@ +package ch.qos.logback.classic.pattern; + + + + + + + + + +public abstract class ThrowableHandlingConverter + extends ClassicConverter +{ + public ThrowableHandlingConverter() {} + + + + + + + + + boolean handlesThrowable() + { + return true; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/ThrowableProxyConverter.java b/src/minecraft/ch/qos/logback/classic/pattern/ThrowableProxyConverter.java new file mode 100644 index 0000000..aa75fc7 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/ThrowableProxyConverter.java @@ -0,0 +1,249 @@ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.IThrowableProxy; +import ch.qos.logback.classic.spi.StackTraceElementProxy; +import ch.qos.logback.classic.spi.ThrowableProxyUtil; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.boolex.EvaluationException; +import ch.qos.logback.core.boolex.EventEvaluator; +import ch.qos.logback.core.status.ErrorStatus; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + + + + + + + + + + + + + + + + + + + + +public class ThrowableProxyConverter + extends ThrowableHandlingConverter +{ + protected static final int BUILDER_CAPACITY = 2048; + int lengthOption; + List> evaluatorList = null; + List ignoredStackTraceLines = null; + + int errorCount = 0; + + public ThrowableProxyConverter() {} + + public void start() { + String lengthStr = getFirstOption(); + + if (lengthStr == null) { + lengthOption = Integer.MAX_VALUE; + } else { + lengthStr = lengthStr.toLowerCase(); + if ("full".equals(lengthStr)) { + lengthOption = Integer.MAX_VALUE; + } else if ("short".equals(lengthStr)) { + lengthOption = 1; + } else { + try { + lengthOption = Integer.parseInt(lengthStr); + } catch (NumberFormatException nfe) { + addError("Could not parse [" + lengthStr + "] as an integer"); + lengthOption = Integer.MAX_VALUE; + } + } + } + + List optionList = getOptionList(); + + if ((optionList != null) && (optionList.size() > 1)) { + int optionListSize = optionList.size(); + for (int i = 1; i < optionListSize; i++) { + String evaluatorOrIgnoredStackTraceLine = (String)optionList.get(i); + Context context = getContext(); + Map evaluatorMap = (Map)context.getObject("EVALUATOR_MAP"); + EventEvaluator ee = (EventEvaluator)evaluatorMap.get(evaluatorOrIgnoredStackTraceLine); + + if (ee != null) { + addEvaluator(ee); + } else { + addIgnoreStackTraceLine(evaluatorOrIgnoredStackTraceLine); + } + } + } + super.start(); + } + + private void addEvaluator(EventEvaluator ee) { + if (evaluatorList == null) { + evaluatorList = new ArrayList(); + } + evaluatorList.add(ee); + } + + private void addIgnoreStackTraceLine(String ignoredStackTraceLine) { + if (ignoredStackTraceLines == null) { + ignoredStackTraceLines = new ArrayList(); + } + ignoredStackTraceLines.add(ignoredStackTraceLine); + } + + public void stop() { + evaluatorList = null; + super.stop(); + } + + + protected void extraData(StringBuilder builder, StackTraceElementProxy step) {} + + + public String convert(ILoggingEvent event) + { + IThrowableProxy tp = event.getThrowableProxy(); + if (tp == null) { + return ""; + } + + + if (evaluatorList != null) { + boolean printStack = true; + for (int i = 0; i < evaluatorList.size(); i++) { + EventEvaluator ee = (EventEvaluator)evaluatorList.get(i); + try { + if (ee.evaluate(event)) { + printStack = false; + break; + } + } catch (EvaluationException eex) { + errorCount += 1; + if (errorCount < 4) { + addError("Exception thrown for evaluator named [" + ee.getName() + "]", eex); + } + else if (errorCount == 4) { + ErrorStatus errorStatus = new ErrorStatus("Exception thrown for evaluator named [" + ee.getName() + "].", this, eex); + + + errorStatus.add(new ErrorStatus("This was the last warning about this evaluator's errors.We don't want the StatusManager to get flooded.", this)); + + + addStatus(errorStatus); + } + } + } + + if (!printStack) { + return ""; + } + } + + return throwableProxyToString(tp); + } + + protected String throwableProxyToString(IThrowableProxy tp) { + StringBuilder sb = new StringBuilder(2048); + + recursiveAppend(sb, null, 1, tp); + + return sb.toString(); + } + + private void recursiveAppend(StringBuilder sb, String prefix, int indent, IThrowableProxy tp) { + if (tp == null) + return; + subjoinFirstLine(sb, prefix, indent, tp); + sb.append(CoreConstants.LINE_SEPARATOR); + subjoinSTEPArray(sb, indent, tp); + IThrowableProxy[] suppressed = tp.getSuppressed(); + if (suppressed != null) { + for (IThrowableProxy current : suppressed) { + recursiveAppend(sb, "Suppressed: ", indent + 1, current); + } + } + recursiveAppend(sb, "Caused by: ", indent, tp.getCause()); + } + + private void subjoinFirstLine(StringBuilder buf, String prefix, int indent, IThrowableProxy tp) { + ThrowableProxyUtil.indent(buf, indent - 1); + if (prefix != null) { + buf.append(prefix); + } + subjoinExceptionMessage(buf, tp); + } + + private void subjoinExceptionMessage(StringBuilder buf, IThrowableProxy tp) { + buf.append(tp.getClassName()).append(": ").append(tp.getMessage()); + } + + protected void subjoinSTEPArray(StringBuilder buf, int indent, IThrowableProxy tp) { + StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray(); + int commonFrames = tp.getCommonFrames(); + + boolean unrestrictedPrinting = lengthOption > stepArray.length; + + + int maxIndex = unrestrictedPrinting ? stepArray.length : lengthOption; + if ((commonFrames > 0) && (unrestrictedPrinting)) { + maxIndex -= commonFrames; + } + + int ignoredCount = 0; + for (int i = 0; i < maxIndex; i++) { + StackTraceElementProxy element = stepArray[i]; + if (!isIgnoredStackTraceLine(element.toString())) { + ThrowableProxyUtil.indent(buf, indent); + printStackLine(buf, ignoredCount, element); + ignoredCount = 0; + buf.append(CoreConstants.LINE_SEPARATOR); + } else { + ignoredCount++; + if (maxIndex < stepArray.length) { + maxIndex++; + } + } + } + if (ignoredCount > 0) { + printIgnoredCount(buf, ignoredCount); + buf.append(CoreConstants.LINE_SEPARATOR); + } + + if ((commonFrames > 0) && (unrestrictedPrinting)) { + ThrowableProxyUtil.indent(buf, indent); + buf.append("... ").append(tp.getCommonFrames()).append(" common frames omitted").append(CoreConstants.LINE_SEPARATOR); + } + } + + private void printStackLine(StringBuilder buf, int ignoredCount, StackTraceElementProxy element) + { + buf.append(element); + extraData(buf, element); + if (ignoredCount > 0) { + printIgnoredCount(buf, ignoredCount); + } + } + + private void printIgnoredCount(StringBuilder buf, int ignoredCount) { + buf.append(" [").append(ignoredCount).append(" skipped]"); + } + + private boolean isIgnoredStackTraceLine(String line) { + if (ignoredStackTraceLines != null) { + for (String ignoredStackTraceLine : ignoredStackTraceLines) { + if (line.contains(ignoredStackTraceLine)) { + return true; + } + } + } + return false; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/Util.java b/src/minecraft/ch/qos/logback/classic/pattern/Util.java new file mode 100644 index 0000000..ecf41f9 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/Util.java @@ -0,0 +1,48 @@ +package ch.qos.logback.classic.pattern; + +import ch.qos.logback.classic.spi.ClassPackagingData; +import java.util.HashMap; +import java.util.Map; +import org.slf4j.Marker; + + + + + + + + + + + + + + + + + + +public class Util +{ + public Util() {} + + static Map cache = new HashMap(); + + public static boolean match(Marker marker, Marker[] markerArray) { + if (markerArray == null) { + throw new IllegalArgumentException("markerArray should not be null"); + } + + + + int size = markerArray.length; + for (int i = 0; i < size; i++) + { + + if (marker.contains(markerArray[i])) { + return true; + } + } + return false; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/pattern/color/HighlightingCompositeConverter.java b/src/minecraft/ch/qos/logback/classic/pattern/color/HighlightingCompositeConverter.java new file mode 100644 index 0000000..8810e07 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/pattern/color/HighlightingCompositeConverter.java @@ -0,0 +1,37 @@ +package ch.qos.logback.classic.pattern.color; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.pattern.color.ForegroundCompositeConverterBase; + + + + + + + + + + + + + + + + + +public class HighlightingCompositeConverter + extends ForegroundCompositeConverterBase +{ + public HighlightingCompositeConverter() {} + + protected String getForegroundColorCode(ILoggingEvent event) + { + Level level = event.getLevel(); + switch (level.toInt()) { + case 40000: return "1;31"; + case 30000: return "31"; + case 20000: return "34"; } + return "39"; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/selector/ContextJNDISelector.java b/src/minecraft/ch/qos/logback/classic/selector/ContextJNDISelector.java new file mode 100644 index 0000000..23f010b --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/selector/ContextJNDISelector.java @@ -0,0 +1,204 @@ +package ch.qos.logback.classic.selector; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.classic.util.ContextInitializer; +import ch.qos.logback.classic.util.JNDIUtil; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.status.InfoStatus; +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.status.StatusUtil; +import ch.qos.logback.core.status.WarnStatus; +import ch.qos.logback.core.util.Loader; +import ch.qos.logback.core.util.StatusPrinter; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.naming.Context; +import javax.naming.NamingException; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class ContextJNDISelector + implements ContextSelector +{ + private final Map synchronizedContextMap; + private final LoggerContext defaultContext; + private static final ThreadLocal threadLocal = new ThreadLocal(); + + public ContextJNDISelector(LoggerContext context) { + synchronizedContextMap = Collections.synchronizedMap(new HashMap()); + + defaultContext = context; + } + + public LoggerContext getDefaultLoggerContext() { + return defaultContext; + } + + public LoggerContext detachLoggerContext(String loggerContextName) { + return (LoggerContext)synchronizedContextMap.remove(loggerContextName); + } + + public LoggerContext getLoggerContext() { + String contextName = null; + Context ctx = null; + + + LoggerContext lc = (LoggerContext)threadLocal.get(); + if (lc != null) { + return lc; + } + + + try + { + ctx = JNDIUtil.getInitialContext(); + contextName = JNDIUtil.lookup(ctx, "java:comp/env/logback/context-name"); + } + catch (NamingException ne) {} + + + if (contextName == null) + { + return defaultContext; + } + + LoggerContext loggerContext = (LoggerContext)synchronizedContextMap.get(contextName); + + if (loggerContext == null) + { + loggerContext = new LoggerContext(); + loggerContext.setName(contextName); + synchronizedContextMap.put(contextName, loggerContext); + URL url = findConfigFileURL(ctx, loggerContext); + if (url != null) { + configureLoggerContextByURL(loggerContext, url); + } else { + try { + new ContextInitializer(loggerContext).autoConfig(); + } + catch (JoranException je) {} + } + + if (!StatusUtil.contextHasStatusListener(loggerContext)) + StatusPrinter.printInCaseOfErrorsOrWarnings(loggerContext); + } + return loggerContext; + } + + private String conventionalConfigFileName(String contextName) + { + return "logback-" + contextName + ".xml"; + } + + private URL findConfigFileURL(Context ctx, LoggerContext loggerContext) { + StatusManager sm = loggerContext.getStatusManager(); + + String jndiEntryForConfigResource = JNDIUtil.lookup(ctx, "java:comp/env/logback/configuration-resource"); + + + if (jndiEntryForConfigResource != null) { + sm.add(new InfoStatus("Searching for [" + jndiEntryForConfigResource + "]", this)); + + URL url = urlByResourceName(sm, jndiEntryForConfigResource); + if (url == null) { + String msg = "The jndi resource [" + jndiEntryForConfigResource + "] for context [" + loggerContext.getName() + "] does not lead to a valid file"; + + + sm.add(new WarnStatus(msg, this)); + } + return url; + } + String resourceByConvention = conventionalConfigFileName(loggerContext.getName()); + + return urlByResourceName(sm, resourceByConvention); + } + + private URL urlByResourceName(StatusManager sm, String resourceName) + { + sm.add(new InfoStatus("Searching for [" + resourceName + "]", this)); + + URL url = Loader.getResource(resourceName, Loader.getTCL()); + if (url != null) { + return url; + } + return Loader.getResourceBySelfClassLoader(resourceName); + } + + private void configureLoggerContextByURL(LoggerContext context, URL url) { + try { + JoranConfigurator configurator = new JoranConfigurator(); + context.reset(); + configurator.setContext(context); + configurator.doConfigure(url); + } + catch (JoranException e) {} + StatusPrinter.printInCaseOfErrorsOrWarnings(context); + } + + public List getContextNames() { + List list = new ArrayList(); + list.addAll(synchronizedContextMap.keySet()); + return list; + } + + public LoggerContext getLoggerContext(String name) { + return (LoggerContext)synchronizedContextMap.get(name); + } + + + + + + public int getCount() + { + return synchronizedContextMap.size(); + } + + + + + + + + + public void setLocalContext(LoggerContext context) + { + threadLocal.set(context); + } + + public void removeLocalContext() { + threadLocal.remove(); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/selector/ContextSelector.java b/src/minecraft/ch/qos/logback/classic/selector/ContextSelector.java new file mode 100644 index 0000000..659d284 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/selector/ContextSelector.java @@ -0,0 +1,17 @@ +package ch.qos.logback.classic.selector; + +import ch.qos.logback.classic.LoggerContext; +import java.util.List; + +public abstract interface ContextSelector +{ + public abstract LoggerContext getLoggerContext(); + + public abstract LoggerContext getLoggerContext(String paramString); + + public abstract LoggerContext getDefaultLoggerContext(); + + public abstract LoggerContext detachLoggerContext(String paramString); + + public abstract List getContextNames(); +} diff --git a/src/minecraft/ch/qos/logback/classic/selector/DefaultContextSelector.java b/src/minecraft/ch/qos/logback/classic/selector/DefaultContextSelector.java new file mode 100644 index 0000000..5937dc2 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/selector/DefaultContextSelector.java @@ -0,0 +1,51 @@ +package ch.qos.logback.classic.selector; + +import ch.qos.logback.classic.LoggerContext; +import java.util.Arrays; +import java.util.List; + + + + + + + + + + + + + +public class DefaultContextSelector + implements ContextSelector +{ + private LoggerContext defaultLoggerContext; + + public DefaultContextSelector(LoggerContext context) + { + defaultLoggerContext = context; + } + + public LoggerContext getLoggerContext() { + return getDefaultLoggerContext(); + } + + public LoggerContext getDefaultLoggerContext() { + return defaultLoggerContext; + } + + public LoggerContext detachLoggerContext(String loggerContextName) { + return defaultLoggerContext; + } + + public List getContextNames() { + return Arrays.asList(new String[] { defaultLoggerContext.getName() }); + } + + public LoggerContext getLoggerContext(String name) { + if (defaultLoggerContext.getName().equals(name)) { + return defaultLoggerContext; + } + return null; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/selector/servlet/ContextDetachingSCL.java b/src/minecraft/ch/qos/logback/classic/selector/servlet/ContextDetachingSCL.java new file mode 100644 index 0000000..5f840da --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/selector/servlet/ContextDetachingSCL.java @@ -0,0 +1,63 @@ +package ch.qos.logback.classic.selector.servlet; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.selector.ContextSelector; +import ch.qos.logback.classic.util.ContextSelectorStaticBinder; +import ch.qos.logback.classic.util.JNDIUtil; +import java.io.PrintStream; +import javax.naming.Context; +import javax.naming.NamingException; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import org.slf4j.Logger; + + + + + + + + + + + + + +public class ContextDetachingSCL + implements ServletContextListener +{ + public ContextDetachingSCL() {} + + public void contextDestroyed(ServletContextEvent servletContextEvent) + { + String loggerContextName = null; + try + { + Context ctx = JNDIUtil.getInitialContext(); + loggerContextName = JNDIUtil.lookup(ctx, "java:comp/env/logback/context-name"); + } + catch (NamingException ne) {} + + if (loggerContextName != null) { + System.out.println("About to detach context named " + loggerContextName); + + ContextSelector selector = ContextSelectorStaticBinder.getSingleton().getContextSelector(); + if (selector == null) { + System.out.println("Selector is null, cannot detach context. Skipping."); + return; + } + LoggerContext context = selector.getLoggerContext(loggerContextName); + if (context != null) { + Logger logger = context.getLogger("ROOT"); + logger.warn("Stopping logger context " + loggerContextName); + selector.detachLoggerContext(loggerContextName); + + context.stop(); + } else { + System.out.println("No context named " + loggerContextName + " was found."); + } + } + } + + public void contextInitialized(ServletContextEvent arg0) {} +} diff --git a/src/minecraft/ch/qos/logback/classic/selector/servlet/LoggerContextFilter.java b/src/minecraft/ch/qos/logback/classic/selector/servlet/LoggerContextFilter.java new file mode 100644 index 0000000..14e9d50 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/selector/servlet/LoggerContextFilter.java @@ -0,0 +1,81 @@ +package ch.qos.logback.classic.selector.servlet; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.selector.ContextJNDISelector; +import ch.qos.logback.classic.selector.ContextSelector; +import ch.qos.logback.classic.util.ContextSelectorStaticBinder; +import java.io.IOException; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import org.slf4j.LoggerFactory; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class LoggerContextFilter + implements Filter +{ + public LoggerContextFilter() {} + + public void destroy() {} + + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException + { + LoggerContext lc = (LoggerContext)LoggerFactory.getILoggerFactory(); + ContextSelector selector = ContextSelectorStaticBinder.getSingleton().getContextSelector(); + ContextJNDISelector sel = null; + + if ((selector instanceof ContextJNDISelector)) { + sel = (ContextJNDISelector)selector; + sel.setLocalContext(lc); + } + try + { + chain.doFilter(request, response); + } finally { + if (sel != null) { + sel.removeLocalContext(); + } + } + } + + public void init(FilterConfig arg0) + throws ServletException + {} +} diff --git a/src/minecraft/ch/qos/logback/classic/sift/AppenderFactoryUsingJoran.java b/src/minecraft/ch/qos/logback/classic/sift/AppenderFactoryUsingJoran.java new file mode 100644 index 0000000..ddd4255 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/sift/AppenderFactoryUsingJoran.java @@ -0,0 +1,37 @@ +package ch.qos.logback.classic.sift; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.joran.event.SaxEvent; +import ch.qos.logback.core.sift.AbstractAppenderFactoryUsingJoran; +import ch.qos.logback.core.sift.SiftingJoranConfiguratorBase; +import java.util.List; +import java.util.Map; + + + + + + + + + + + + + + + + + +public class AppenderFactoryUsingJoran + extends AbstractAppenderFactoryUsingJoran +{ + AppenderFactoryUsingJoran(List eventList, String key, Map parentPropertyMap) + { + super(eventList, key, parentPropertyMap); + } + + public SiftingJoranConfiguratorBase getSiftingJoranConfigurator(String discriminatingValue) { + return new SiftingJoranConfigurator(key, discriminatingValue, parentPropertyMap); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/sift/ContextBasedDiscriminator.java b/src/minecraft/ch/qos/logback/classic/sift/ContextBasedDiscriminator.java new file mode 100644 index 0000000..e0a1704 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/sift/ContextBasedDiscriminator.java @@ -0,0 +1,73 @@ +package ch.qos.logback.classic.sift; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggerContextVO; +import ch.qos.logback.core.sift.AbstractDiscriminator; + + + + + + + + + + + + + + + + + + + + + + +public class ContextBasedDiscriminator + extends AbstractDiscriminator +{ + private static final String KEY = "contextName"; + private String defaultValue; + + public ContextBasedDiscriminator() {} + + public String getDiscriminatingValue(ILoggingEvent event) + { + String contextName = event.getLoggerContextVO().getName(); + + if (contextName == null) { + return defaultValue; + } + return contextName; + } + + public String getKey() + { + return "contextName"; + } + + public void setKey(String key) { + throw new UnsupportedOperationException("Key cannot be set. Using fixed key contextName"); + } + + + + + + public String getDefaultValue() + { + return defaultValue; + } + + + + + + + public void setDefaultValue(String defaultValue) + { + this.defaultValue = defaultValue; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/sift/JNDIBasedContextDiscriminator.java b/src/minecraft/ch/qos/logback/classic/sift/JNDIBasedContextDiscriminator.java new file mode 100644 index 0000000..e9946d5 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/sift/JNDIBasedContextDiscriminator.java @@ -0,0 +1,82 @@ +package ch.qos.logback.classic.sift; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.selector.ContextSelector; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.util.ContextSelectorStaticBinder; +import ch.qos.logback.core.sift.AbstractDiscriminator; + + + + + + + + + + + + + + + + + + + + + + + +public class JNDIBasedContextDiscriminator + extends AbstractDiscriminator +{ + private static final String KEY = "contextName"; + private String defaultValue; + + public JNDIBasedContextDiscriminator() {} + + public String getDiscriminatingValue(ILoggingEvent event) + { + ContextSelector selector = ContextSelectorStaticBinder.getSingleton().getContextSelector(); + + + if (selector == null) { + return defaultValue; + } + + LoggerContext lc = selector.getLoggerContext(); + if (lc == null) { + return defaultValue; + } + + return lc.getName(); + } + + public String getKey() { + return "contextName"; + } + + public void setKey(String key) { + throw new UnsupportedOperationException("Key cannot be set. Using fixed key contextName"); + } + + + + + + public String getDefaultValue() + { + return defaultValue; + } + + + + + + + public void setDefaultValue(String defaultValue) + { + this.defaultValue = defaultValue; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/sift/MDCBasedDiscriminator.java b/src/minecraft/ch/qos/logback/classic/sift/MDCBasedDiscriminator.java new file mode 100644 index 0000000..6a0a8ff --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/sift/MDCBasedDiscriminator.java @@ -0,0 +1,99 @@ +package ch.qos.logback.classic.sift; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.sift.AbstractDiscriminator; +import ch.qos.logback.core.util.OptionHelper; +import java.util.Map; + + + + + + + + + + + + + + + + + + + + + + + + + +public class MDCBasedDiscriminator + extends AbstractDiscriminator +{ + private String key; + private String defaultValue; + + public MDCBasedDiscriminator() {} + + public String getDiscriminatingValue(ILoggingEvent event) + { + Map mdcMap = event.getMDCPropertyMap(); + if (mdcMap == null) { + return defaultValue; + } + String mdcValue = (String)mdcMap.get(key); + if (mdcValue == null) { + return defaultValue; + } + return mdcValue; + } + + + public void start() + { + int errors = 0; + if (OptionHelper.isEmpty(key)) { + errors++; + addError("The \"Key\" property must be set"); + } + if (OptionHelper.isEmpty(defaultValue)) { + errors++; + addError("The \"DefaultValue\" property must be set"); + } + if (errors == 0) { + started = true; + } + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + + + + public String getDefaultValue() + { + return defaultValue; + } + + + + + + + + + + + public void setDefaultValue(String defaultValue) + { + this.defaultValue = defaultValue; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/sift/SiftAction.java b/src/minecraft/ch/qos/logback/classic/sift/SiftAction.java new file mode 100644 index 0000000..bc3c893 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/sift/SiftAction.java @@ -0,0 +1,58 @@ +package ch.qos.logback.classic.sift; + +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.event.InPlayListener; +import ch.qos.logback.core.joran.event.SaxEvent; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.xml.sax.Attributes; + + + + + + + + + + + +public class SiftAction + extends Action + implements InPlayListener +{ + List seList; + + public SiftAction() {} + + public void begin(InterpretationContext ic, String name, Attributes attributes) + throws ActionException + { + seList = new ArrayList(); + ic.addInPlayListener(this); + } + + public void end(InterpretationContext ic, String name) throws ActionException + { + ic.removeInPlayListener(this); + Object o = ic.peekObject(); + if ((o instanceof SiftingAppender)) { + SiftingAppender sa = (SiftingAppender)o; + Map propertyMap = ic.getCopyOfPropertyMap(); + AppenderFactoryUsingJoran appenderFactory = new AppenderFactoryUsingJoran(seList, sa.getDiscriminatorKey(), propertyMap); + + sa.setAppenderFactory(appenderFactory); + } + } + + public void inPlay(SaxEvent event) { + seList.add(event); + } + + public List getSeList() { + return seList; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/sift/SiftingAppender.java b/src/minecraft/ch/qos/logback/classic/sift/SiftingAppender.java new file mode 100644 index 0000000..d8fb071 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/sift/SiftingAppender.java @@ -0,0 +1,54 @@ +package ch.qos.logback.classic.sift; + +import ch.qos.logback.classic.ClassicConstants; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.joran.spi.DefaultClass; +import ch.qos.logback.core.sift.Discriminator; +import ch.qos.logback.core.sift.SiftingAppenderBase; +import org.slf4j.Marker; + + + + + + + + + + + + + + + + + + + + + +public class SiftingAppender + extends SiftingAppenderBase +{ + public SiftingAppender() {} + + protected long getTimestamp(ILoggingEvent event) + { + return event.getTimeStamp(); + } + + + @DefaultClass(MDCBasedDiscriminator.class) + public void setDiscriminator(Discriminator discriminator) + { + super.setDiscriminator(discriminator); + } + + protected boolean eventMarksEndOfLife(ILoggingEvent event) { + Marker marker = event.getMarker(); + if (marker == null) { + return false; + } + return marker.contains(ClassicConstants.FINALIZE_SESSION_MARKER); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/sift/SiftingJoranConfigurator.java b/src/minecraft/ch/qos/logback/classic/sift/SiftingJoranConfigurator.java new file mode 100644 index 0000000..ae8a180 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/sift/SiftingJoranConfigurator.java @@ -0,0 +1,79 @@ +package ch.qos.logback.classic.sift; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.util.DefaultNestedComponentRules; +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.joran.action.AppenderAction; +import ch.qos.logback.core.joran.spi.DefaultNestedComponentRegistry; +import ch.qos.logback.core.joran.spi.ElementPath; +import ch.qos.logback.core.joran.spi.ElementSelector; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.joran.spi.Interpreter; +import ch.qos.logback.core.joran.spi.RuleStore; +import ch.qos.logback.core.sift.SiftingJoranConfiguratorBase; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + + + + + + + + + + + + +public class SiftingJoranConfigurator + extends SiftingJoranConfiguratorBase +{ + SiftingJoranConfigurator(String key, String value, Map parentPropertyMap) + { + super(key, value, parentPropertyMap); + } + + protected ElementPath initialElementPath() + { + return new ElementPath("configuration"); + } + + protected void addInstanceRules(RuleStore rs) + { + super.addInstanceRules(rs); + rs.addRule(new ElementSelector("configuration/appender"), new AppenderAction()); + } + + + + protected void addDefaultNestedComponentRegistryRules(DefaultNestedComponentRegistry registry) + { + DefaultNestedComponentRules.addDefaultNestedComponentRegistryRules(registry); + } + + protected void buildInterpreter() + { + super.buildInterpreter(); + Map omap = interpreter.getInterpretationContext().getObjectMap(); + omap.put("APPENDER_BAG", new HashMap()); + omap.put("FILTER_CHAIN_BAG", new HashMap()); + Map propertiesMap = new HashMap(); + propertiesMap.putAll(parentPropertyMap); + propertiesMap.put(key, value); + interpreter.setInterpretationContextPropertiesMap(propertiesMap); + } + + public Appender getAppender() + { + Map omap = interpreter.getInterpretationContext().getObjectMap(); + HashMap appenderMap = (HashMap)omap.get("APPENDER_BAG"); + oneAndOnlyOneCheck(appenderMap); + Collection values = appenderMap.values(); + if (values.size() == 0) { + return null; + } + return (Appender)values.iterator().next(); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/spi/CallerData.java b/src/minecraft/ch/qos/logback/classic/spi/CallerData.java new file mode 100644 index 0000000..724ab85 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/spi/CallerData.java @@ -0,0 +1,130 @@ +package ch.qos.logback.classic.spi; + +import ch.qos.logback.core.CoreConstants; +import java.util.List; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class CallerData +{ + public static final String NA = "?"; + private static final String LOG4J_CATEGORY = "org.apache.log4j.Category"; + private static final String SLF4J_BOUNDARY = "org.slf4j.Logger"; + public static final int LINE_NA = -1; + public static final String CALLER_DATA_NA = "?#?:?" + CoreConstants.LINE_SEPARATOR; + + + + + public static final StackTraceElement[] EMPTY_CALLER_DATA_ARRAY = new StackTraceElement[0]; + + + + public CallerData() {} + + + + public static StackTraceElement[] extract(Throwable t, String fqnOfInvokingClass, int maxDepth, List frameworkPackageList) + { + if (t == null) { + return null; + } + + StackTraceElement[] steArray = t.getStackTrace(); + + + int found = -1; + for (int i = 0; i < steArray.length; i++) { + if (isInFrameworkSpace(steArray[i].getClassName(), fqnOfInvokingClass, frameworkPackageList)) + { + + found = i + 1; + } else { + if (found != -1) { + break; + } + } + } + + + if (found == -1) { + return EMPTY_CALLER_DATA_ARRAY; + } + + int availableDepth = steArray.length - found; + int desiredDepth = maxDepth < availableDepth ? maxDepth : availableDepth; + + StackTraceElement[] callerDataArray = new StackTraceElement[desiredDepth]; + for (int i = 0; i < desiredDepth; i++) { + callerDataArray[i] = steArray[(found + i)]; + } + return callerDataArray; + } + + + + static boolean isInFrameworkSpace(String currentClass, String fqnOfInvokingClass, List frameworkPackageList) + { + if ((currentClass.equals(fqnOfInvokingClass)) || (currentClass.equals("org.apache.log4j.Category")) || (currentClass.startsWith("org.slf4j.Logger")) || (isInFrameworkSpaceList(currentClass, frameworkPackageList))) + { + return true; + } + return false; + } + + + + + private static boolean isInFrameworkSpaceList(String currentClass, List frameworkPackageList) + { + if (frameworkPackageList == null) { + return false; + } + for (String s : frameworkPackageList) { + if (currentClass.startsWith(s)) + return true; + } + return false; + } + + + + + + + public static StackTraceElement naInstance() + { + return new StackTraceElement("?", "?", "?", -1); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/spi/ClassPackagingData.java b/src/minecraft/ch/qos/logback/classic/spi/ClassPackagingData.java new file mode 100644 index 0000000..bcf1fd9 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/spi/ClassPackagingData.java @@ -0,0 +1,80 @@ +package ch.qos.logback.classic.spi; + +import java.io.Serializable; + + + + + + + + + + + + +public class ClassPackagingData + implements Serializable +{ + private static final long serialVersionUID = -804643281218337001L; + final String codeLocation; + final String version; + private final boolean exact; + + public ClassPackagingData(String codeLocation, String version) + { + this.codeLocation = codeLocation; + this.version = version; + exact = true; + } + + public ClassPackagingData(String classLocation, String version, boolean exact) { + codeLocation = classLocation; + this.version = version; + this.exact = exact; + } + + public String getCodeLocation() { + return codeLocation; + } + + public String getVersion() { + return version; + } + + public boolean isExact() { + return exact; + } + + public int hashCode() + { + int PRIME = 31; + int result = 1; + result = 31 * result + (codeLocation == null ? 0 : codeLocation.hashCode()); + return result; + } + + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ClassPackagingData other = (ClassPackagingData)obj; + if (codeLocation == null) { + if (codeLocation != null) + return false; + } else if (!codeLocation.equals(codeLocation)) + return false; + if (exact != exact) + return false; + if (version == null) { + if (version != null) + return false; + } else if (!version.equals(version)) + return false; + return true; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/spi/Configurator.java b/src/minecraft/ch/qos/logback/classic/spi/Configurator.java new file mode 100644 index 0000000..d5d4043 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/spi/Configurator.java @@ -0,0 +1,10 @@ +package ch.qos.logback.classic.spi; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.core.spi.ContextAware; + +public abstract interface Configurator + extends ContextAware +{ + public abstract void configure(LoggerContext paramLoggerContext); +} diff --git a/src/minecraft/ch/qos/logback/classic/spi/EventArgUtil.java b/src/minecraft/ch/qos/logback/classic/spi/EventArgUtil.java new file mode 100644 index 0000000..3b2e5b4 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/spi/EventArgUtil.java @@ -0,0 +1,54 @@ +package ch.qos.logback.classic.spi; + + + + + + + +public class EventArgUtil +{ + public EventArgUtil() {} + + + + + + + public static final Throwable extractThrowable(Object[] argArray) + { + if ((argArray == null) || (argArray.length == 0)) { + return null; + } + + Object lastEntry = argArray[(argArray.length - 1)]; + if ((lastEntry instanceof Throwable)) { + return (Throwable)lastEntry; + } + return null; + } + + + + + + + public static Object[] trimmedCopy(Object[] argArray) + { + if ((argArray == null) || (argArray.length == 0)) { + throw new IllegalStateException("non-sensical empty or null argument array"); + } + int trimemdLen = argArray.length - 1; + Object[] trimmed = new Object[trimemdLen]; + System.arraycopy(argArray, 0, trimmed, 0, trimemdLen); + return trimmed; + } + + public static Object[] arrangeArguments(Object[] argArray) { + return argArray; + } + + public static boolean successfulExtraction(Throwable throwable) { + return throwable != null; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/spi/ILoggingEvent.java b/src/minecraft/ch/qos/logback/classic/spi/ILoggingEvent.java new file mode 100644 index 0000000..1bfcc0d --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/spi/ILoggingEvent.java @@ -0,0 +1,43 @@ +package ch.qos.logback.classic.spi; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.core.spi.DeferredProcessingAware; +import java.util.Map; +import org.slf4j.Marker; + +public abstract interface ILoggingEvent + extends DeferredProcessingAware +{ + public abstract String getThreadName(); + + public abstract Level getLevel(); + + public abstract String getMessage(); + + public abstract Object[] getArgumentArray(); + + public abstract String getFormattedMessage(); + + public abstract String getLoggerName(); + + public abstract LoggerContextVO getLoggerContextVO(); + + public abstract IThrowableProxy getThrowableProxy(); + + public abstract StackTraceElement[] getCallerData(); + + public abstract boolean hasCallerData(); + + public abstract Marker getMarker(); + + public abstract Map getMDCPropertyMap(); + + /** + * @deprecated + */ + public abstract Map getMdc(); + + public abstract long getTimeStamp(); + + public abstract void prepareForDeferredProcessing(); +} diff --git a/src/minecraft/ch/qos/logback/classic/spi/IThrowableProxy.java b/src/minecraft/ch/qos/logback/classic/spi/IThrowableProxy.java new file mode 100644 index 0000000..637aea8 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/spi/IThrowableProxy.java @@ -0,0 +1,16 @@ +package ch.qos.logback.classic.spi; + +public abstract interface IThrowableProxy +{ + public abstract String getMessage(); + + public abstract String getClassName(); + + public abstract StackTraceElementProxy[] getStackTraceElementProxyArray(); + + public abstract int getCommonFrames(); + + public abstract IThrowableProxy getCause(); + + public abstract IThrowableProxy[] getSuppressed(); +} diff --git a/src/minecraft/ch/qos/logback/classic/spi/LoggerComparator.java b/src/minecraft/ch/qos/logback/classic/spi/LoggerComparator.java new file mode 100644 index 0000000..08245c5 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/spi/LoggerComparator.java @@ -0,0 +1,34 @@ +package ch.qos.logback.classic.spi; + +import ch.qos.logback.classic.Logger; +import java.util.Comparator; + + + + + + + + + + + +public class LoggerComparator + implements Comparator +{ + public LoggerComparator() {} + + public int compare(Logger l1, Logger l2) + { + if (l1.getName().equals(l2.getName())) { + return 0; + } + if (l1.getName().equals("ROOT")) { + return -1; + } + if (l2.getName().equals("ROOT")) { + return 1; + } + return l1.getName().compareTo(l2.getName()); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/spi/LoggerContextAware.java b/src/minecraft/ch/qos/logback/classic/spi/LoggerContextAware.java new file mode 100644 index 0000000..26756f6 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/spi/LoggerContextAware.java @@ -0,0 +1,10 @@ +package ch.qos.logback.classic.spi; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.core.spi.ContextAware; + +public abstract interface LoggerContextAware + extends ContextAware +{ + public abstract void setLoggerContext(LoggerContext paramLoggerContext); +} diff --git a/src/minecraft/ch/qos/logback/classic/spi/LoggerContextAwareBase.java b/src/minecraft/ch/qos/logback/classic/spi/LoggerContextAwareBase.java new file mode 100644 index 0000000..5a3140b --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/spi/LoggerContextAwareBase.java @@ -0,0 +1,49 @@ +package ch.qos.logback.classic.spi; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.spi.ContextAwareBase; + + + + + + + + + + + + + + +public class LoggerContextAwareBase + extends ContextAwareBase + implements LoggerContextAware +{ + public LoggerContextAwareBase() {} + + public void setLoggerContext(LoggerContext context) + { + super.setContext(context); + } + + + public void setContext(Context context) + { + if (((context instanceof LoggerContext)) || (context == null)) { + super.setContext(context); + } else { + throw new IllegalArgumentException("LoggerContextAwareBase only accepts contexts of type c.l.classic.LoggerContext"); + } + } + + + + + + public LoggerContext getLoggerContext() + { + return (LoggerContext)context; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/spi/LoggerContextListener.java b/src/minecraft/ch/qos/logback/classic/spi/LoggerContextListener.java new file mode 100644 index 0000000..a4acef2 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/spi/LoggerContextListener.java @@ -0,0 +1,18 @@ +package ch.qos.logback.classic.spi; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; + +public abstract interface LoggerContextListener +{ + public abstract boolean isResetResistant(); + + public abstract void onStart(LoggerContext paramLoggerContext); + + public abstract void onReset(LoggerContext paramLoggerContext); + + public abstract void onStop(LoggerContext paramLoggerContext); + + public abstract void onLevelChange(Logger paramLogger, Level paramLevel); +} diff --git a/src/minecraft/ch/qos/logback/classic/spi/LoggerContextVO.java b/src/minecraft/ch/qos/logback/classic/spi/LoggerContextVO.java new file mode 100644 index 0000000..58c5ae2 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/spi/LoggerContextVO.java @@ -0,0 +1,99 @@ +package ch.qos.logback.classic.spi; + +import ch.qos.logback.classic.LoggerContext; +import java.io.Serializable; +import java.util.Map; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class LoggerContextVO + implements Serializable +{ + private static final long serialVersionUID = 5488023392483144387L; + final String name; + final Map propertyMap; + final long birthTime; + + public LoggerContextVO(LoggerContext lc) + { + name = lc.getName(); + propertyMap = lc.getCopyOfPropertyMap(); + birthTime = lc.getBirthTime(); + } + + public LoggerContextVO(String name, Map propertyMap, long birthTime) { + this.name = name; + this.propertyMap = propertyMap; + this.birthTime = birthTime; + } + + public String getName() { + return name; + } + + public Map getPropertyMap() { + return propertyMap; + } + + public long getBirthTime() { + return birthTime; + } + + + public String toString() + { + return "LoggerContextVO{name='" + name + '\'' + ", propertyMap=" + propertyMap + ", birthTime=" + birthTime + '}'; + } + + + + + public boolean equals(Object o) + { + if (this == o) return true; + if (!(o instanceof LoggerContextVO)) { return false; + } + LoggerContextVO that = (LoggerContextVO)o; + + if (birthTime != birthTime) return false; + if (name != null ? !name.equals(name) : name != null) return false; + if (propertyMap != null ? !propertyMap.equals(propertyMap) : propertyMap != null) { return false; + } + return true; + } + + public int hashCode() + { + int result = name != null ? name.hashCode() : 0; + result = 31 * result + (propertyMap != null ? propertyMap.hashCode() : 0); + result = 31 * result + (int)(birthTime ^ birthTime >>> 32); + + return result; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/spi/LoggerRemoteView.java b/src/minecraft/ch/qos/logback/classic/spi/LoggerRemoteView.java new file mode 100644 index 0000000..93ccbf8 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/spi/LoggerRemoteView.java @@ -0,0 +1,49 @@ +package ch.qos.logback.classic.spi; + +import ch.qos.logback.classic.LoggerContext; +import java.io.Serializable; + + + + + + + + + + + + + + + + + + + + + + + +public class LoggerRemoteView + implements Serializable +{ + private static final long serialVersionUID = 5028223666108713696L; + final LoggerContextVO loggerContextView; + final String name; + + public LoggerRemoteView(String name, LoggerContext lc) + { + this.name = name; + assert (lc.getLoggerContextRemoteView() != null); + loggerContextView = lc.getLoggerContextRemoteView(); + } + + public LoggerContextVO getLoggerContextView() { + return loggerContextView; + } + + public String getName() { + return name; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/spi/LoggingEvent.java b/src/minecraft/ch/qos/logback/classic/spi/LoggingEvent.java new file mode 100644 index 0000000..50eb448 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/spi/LoggingEvent.java @@ -0,0 +1,365 @@ +package ch.qos.logback.classic.spi; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.util.LogbackMDCAdapter; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.util.HashMap; +import java.util.Map; +import org.slf4j.MDC; +import org.slf4j.Marker; +import org.slf4j.helpers.FormattingTuple; +import org.slf4j.helpers.MessageFormatter; +import org.slf4j.spi.MDCAdapter; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class LoggingEvent + implements ILoggingEvent +{ + transient String fqnOfLoggerClass; + private String threadName; + private String loggerName; + private LoggerContext loggerContext; + private LoggerContextVO loggerContextVO; + private transient Level level; + private String message; + transient String formattedMessage; + private transient Object[] argumentArray; + private ThrowableProxy throwableProxy; + private StackTraceElement[] callerDataArray; + private Marker marker; + private Map mdcPropertyMap; + private static final Map CACHED_NULL_MAP = new HashMap(); + + + private long timeStamp; + + + + public LoggingEvent() {} + + + + public LoggingEvent(String fqcn, Logger logger, Level level, String message, Throwable throwable, Object[] argArray) + { + fqnOfLoggerClass = fqcn; + loggerName = logger.getName(); + loggerContext = logger.getLoggerContext(); + loggerContextVO = loggerContext.getLoggerContextRemoteView(); + this.level = level; + + this.message = message; + argumentArray = argArray; + + if (throwable == null) { + throwable = extractThrowableAnRearrangeArguments(argArray); + } + + if (throwable != null) { + throwableProxy = new ThrowableProxy(throwable); + LoggerContext lc = logger.getLoggerContext(); + if (lc.isPackagingDataEnabled()) { + throwableProxy.calculatePackagingData(); + } + } + + timeStamp = System.currentTimeMillis(); + } + + private Throwable extractThrowableAnRearrangeArguments(Object[] argArray) { + Throwable extractedThrowable = EventArgUtil.extractThrowable(argArray); + if (EventArgUtil.successfulExtraction(extractedThrowable)) { + argumentArray = EventArgUtil.trimmedCopy(argArray); + } + return extractedThrowable; + } + + public void setArgumentArray(Object[] argArray) { + if (argumentArray != null) { + throw new IllegalStateException("argArray has been already set"); + } + argumentArray = argArray; + } + + public Object[] getArgumentArray() { + return argumentArray; + } + + public Level getLevel() { + return level; + } + + public String getLoggerName() { + return loggerName; + } + + public void setLoggerName(String loggerName) { + this.loggerName = loggerName; + } + + public String getThreadName() { + if (threadName == null) { + threadName = Thread.currentThread().getName(); + } + return threadName; + } + + + + public void setThreadName(String threadName) + throws IllegalStateException + { + if (this.threadName != null) { + throw new IllegalStateException("threadName has been already set"); + } + this.threadName = threadName; + } + + + + + public IThrowableProxy getThrowableProxy() + { + return throwableProxy; + } + + + + public void setThrowableProxy(ThrowableProxy tp) + { + if (throwableProxy != null) { + throw new IllegalStateException("ThrowableProxy has been already set."); + } + throwableProxy = tp; + } + + + + + + + + + + public void prepareForDeferredProcessing() + { + getFormattedMessage(); + getThreadName(); + + getMDCPropertyMap(); + } + + public LoggerContextVO getLoggerContextVO() { + return loggerContextVO; + } + + public void setLoggerContextRemoteView(LoggerContextVO loggerContextVO) { + this.loggerContextVO = loggerContextVO; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + if (this.message != null) { + throw new IllegalStateException("The message for this event has been set already."); + } + + this.message = message; + } + + public long getTimeStamp() { + return timeStamp; + } + + public void setTimeStamp(long timeStamp) { + this.timeStamp = timeStamp; + } + + public void setLevel(Level level) { + if (this.level != null) { + throw new IllegalStateException("The level has been already set for this event."); + } + + this.level = level; + } + + + + + + + + + + + public StackTraceElement[] getCallerData() + { + if (callerDataArray == null) { + callerDataArray = CallerData.extract(new Throwable(), fqnOfLoggerClass, loggerContext.getMaxCallerDataDepth(), loggerContext.getFrameworkPackages()); + } + + return callerDataArray; + } + + public boolean hasCallerData() { + return callerDataArray != null; + } + + public void setCallerData(StackTraceElement[] callerDataArray) { + this.callerDataArray = callerDataArray; + } + + public Marker getMarker() { + return marker; + } + + public void setMarker(Marker marker) { + if (this.marker != null) { + throw new IllegalStateException("The marker has been already set for this event."); + } + + this.marker = marker; + } + + public long getContextBirthTime() { + return loggerContextVO.getBirthTime(); + } + + public String getFormattedMessage() + { + if (formattedMessage != null) { + return formattedMessage; + } + if (argumentArray != null) { + formattedMessage = MessageFormatter.arrayFormat(message, argumentArray).getMessage(); + } + else { + formattedMessage = message; + } + + return formattedMessage; + } + + public Map getMDCPropertyMap() + { + if (mdcPropertyMap == null) { + MDCAdapter mdc = MDC.getMDCAdapter(); + if ((mdc instanceof LogbackMDCAdapter)) { + mdcPropertyMap = ((LogbackMDCAdapter)mdc).getPropertyMap(); + } else { + mdcPropertyMap = mdc.getCopyOfContextMap(); + } + } + if (mdcPropertyMap == null) { + mdcPropertyMap = CACHED_NULL_MAP; + } + return mdcPropertyMap; + } + + + + + + + public void setMDCPropertyMap(Map map) + { + if (mdcPropertyMap != null) { + throw new IllegalStateException("The MDCPropertyMap has been already set for this event."); + } + + mdcPropertyMap = map; + } + + + + /** + * @deprecated + */ + public Map getMdc() + { + return getMDCPropertyMap(); + } + + public String toString() + { + StringBuilder sb = new StringBuilder(); + sb.append('['); + sb.append(level).append("] "); + sb.append(getFormattedMessage()); + return sb.toString(); + } + + + + + + private void writeObject(ObjectOutputStream out) + throws IOException + { + throw new UnsupportedOperationException(getClass() + " does not support serialization. " + "Use LoggerEventVO instance instead. See also LoggerEventVO.build method."); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/spi/LoggingEventVO.java b/src/minecraft/ch/qos/logback/classic/spi/LoggingEventVO.java new file mode 100644 index 0000000..aedc5a8 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/spi/LoggingEventVO.java @@ -0,0 +1,249 @@ +package ch.qos.logback.classic.spi; + +import ch.qos.logback.classic.Level; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Map; +import org.slf4j.Marker; +import org.slf4j.helpers.FormattingTuple; +import org.slf4j.helpers.MessageFormatter; + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class LoggingEventVO + implements ILoggingEvent, Serializable +{ + private static final long serialVersionUID = 6553722650255690312L; + private static final int NULL_ARGUMENT_ARRAY = -1; + private static final String NULL_ARGUMENT_ARRAY_ELEMENT = "NULL_ARGUMENT_ARRAY_ELEMENT"; + private String threadName; + private String loggerName; + private LoggerContextVO loggerContextVO; + private transient Level level; + private String message; + private transient String formattedMessage; + private transient Object[] argumentArray; + private ThrowableProxyVO throwableProxy; + private StackTraceElement[] callerDataArray; + private Marker marker; + private Map mdcPropertyMap; + private long timeStamp; + + public LoggingEventVO() {} + + public static LoggingEventVO build(ILoggingEvent le) + { + LoggingEventVO ledo = new LoggingEventVO(); + loggerName = le.getLoggerName(); + loggerContextVO = le.getLoggerContextVO(); + threadName = le.getThreadName(); + level = le.getLevel(); + message = le.getMessage(); + argumentArray = le.getArgumentArray(); + marker = le.getMarker(); + mdcPropertyMap = le.getMDCPropertyMap(); + timeStamp = le.getTimeStamp(); + throwableProxy = ThrowableProxyVO.build(le.getThrowableProxy()); + + + if (le.hasCallerData()) { + callerDataArray = le.getCallerData(); + } + return ledo; + } + + public String getThreadName() { + return threadName; + } + + public LoggerContextVO getLoggerContextVO() { + return loggerContextVO; + } + + public String getLoggerName() { + return loggerName; + } + + public Level getLevel() { + return level; + } + + public String getMessage() { + return message; + } + + public String getFormattedMessage() { + if (formattedMessage != null) { + return formattedMessage; + } + + if (argumentArray != null) { + formattedMessage = MessageFormatter.arrayFormat(message, argumentArray).getMessage(); + } + else { + formattedMessage = message; + } + + return formattedMessage; + } + + public Object[] getArgumentArray() { + return argumentArray; + } + + public IThrowableProxy getThrowableProxy() { + return throwableProxy; + } + + public StackTraceElement[] getCallerData() { + return callerDataArray; + } + + public boolean hasCallerData() { + return callerDataArray != null; + } + + public Marker getMarker() { + return marker; + } + + public long getTimeStamp() { + return timeStamp; + } + + public long getContextBirthTime() { + return loggerContextVO.getBirthTime(); + } + + public LoggerContextVO getContextLoggerRemoteView() { + return loggerContextVO; + } + + public Map getMDCPropertyMap() { + return mdcPropertyMap; + } + + public Map getMdc() { return mdcPropertyMap; } + + public void prepareForDeferredProcessing() {} + + private void writeObject(ObjectOutputStream out) + throws IOException + { + out.defaultWriteObject(); + out.writeInt(level.levelInt); + if (argumentArray != null) { + int len = argumentArray.length; + out.writeInt(len); + for (int i = 0; i < argumentArray.length; i++) { + if (argumentArray[i] != null) { + out.writeObject(argumentArray[i].toString()); + } else { + out.writeObject("NULL_ARGUMENT_ARRAY_ELEMENT"); + } + } + } else { + out.writeInt(-1); + } + } + + private void readObject(ObjectInputStream in) + throws IOException, ClassNotFoundException + { + in.defaultReadObject(); + int levelInt = in.readInt(); + level = Level.toLevel(levelInt); + + int argArrayLen = in.readInt(); + if (argArrayLen != -1) { + argumentArray = new String[argArrayLen]; + for (int i = 0; i < argArrayLen; i++) { + Object val = in.readObject(); + if (!"NULL_ARGUMENT_ARRAY_ELEMENT".equals(val)) { + argumentArray[i] = val; + } + } + } + } + + public int hashCode() + { + int prime = 31; + int result = 1; + result = 31 * result + (message == null ? 0 : message.hashCode()); + result = 31 * result + (threadName == null ? 0 : threadName.hashCode()); + + result = 31 * result + (int)(timeStamp ^ timeStamp >>> 32); + return result; + } + + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + LoggingEventVO other = (LoggingEventVO)obj; + if (message == null) { + if (message != null) + return false; + } else if (!message.equals(message)) { + return false; + } + if (loggerName == null) { + if (loggerName != null) + return false; + } else if (!loggerName.equals(loggerName)) { + return false; + } + if (threadName == null) { + if (threadName != null) + return false; + } else if (!threadName.equals(threadName)) + return false; + if (timeStamp != timeStamp) { + return false; + } + if (marker == null) { + if (marker != null) + return false; + } else if (!marker.equals(marker)) { + return false; + } + if (mdcPropertyMap == null) { + if (mdcPropertyMap != null) + return false; + } else if (!mdcPropertyMap.equals(mdcPropertyMap)) + return false; + return true; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/spi/PackagingDataCalculator.java b/src/minecraft/ch/qos/logback/classic/spi/PackagingDataCalculator.java new file mode 100644 index 0000000..a403c2b --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/spi/PackagingDataCalculator.java @@ -0,0 +1,250 @@ +package ch.qos.logback.classic.spi; + +import java.io.PrintStream; +import java.net.URL; +import java.security.CodeSource; +import java.security.ProtectionDomain; +import java.util.HashMap; +import sun.reflect.Reflection; + + + + + + + + + + + + + + + + + + + +public class PackagingDataCalculator +{ + static final StackTraceElementProxy[] STEP_ARRAY_TEMPLATE = new StackTraceElementProxy[0]; + + HashMap cache = new HashMap(); + + private static boolean GET_CALLER_CLASS_METHOD_AVAILABLE = false; + + + + + static + { + try + { + Reflection.getCallerClass(2); + GET_CALLER_CLASS_METHOD_AVAILABLE = true; + + } + catch (NoClassDefFoundError e) {}catch (NoSuchMethodError e) {}catch (UnsupportedOperationException e) {}catch (Throwable e) + { + System.err.println("Unexpected exception"); + e.printStackTrace(); + } + } + + public void calculate(IThrowableProxy tp) + { + while (tp != null) { + populateFrames(tp.getStackTraceElementProxyArray()); + IThrowableProxy[] suppressed = tp.getSuppressed(); + if (suppressed != null) { + for (IThrowableProxy current : suppressed) { + populateFrames(current.getStackTraceElementProxyArray()); + } + } + tp = tp.getCause(); + } + } + + + void populateFrames(StackTraceElementProxy[] stepArray) + { + Throwable t = new Throwable("local stack reference"); + StackTraceElement[] localteSTEArray = t.getStackTrace(); + int commonFrames = STEUtil.findNumberOfCommonFrames(localteSTEArray, stepArray); + + int localFirstCommon = localteSTEArray.length - commonFrames; + int stepFirstCommon = stepArray.length - commonFrames; + + ClassLoader lastExactClassLoader = null; + ClassLoader firsExactClassLoader = null; + + int missfireCount = 0; + for (int i = 0; i < commonFrames; i++) { + Class callerClass = null; + if (GET_CALLER_CLASS_METHOD_AVAILABLE) { + callerClass = Reflection.getCallerClass(localFirstCommon + i - missfireCount + 1); + } + + StackTraceElementProxy step = stepArray[(stepFirstCommon + i)]; + String stepClassname = ste.getClassName(); + + if ((callerClass != null) && (stepClassname.equals(callerClass.getName()))) + { + lastExactClassLoader = callerClass.getClassLoader(); + if (firsExactClassLoader == null) { + firsExactClassLoader = lastExactClassLoader; + } + ClassPackagingData pi = calculateByExactType(callerClass); + step.setClassPackagingData(pi); + } else { + missfireCount++; + ClassPackagingData pi = computeBySTEP(step, lastExactClassLoader); + step.setClassPackagingData(pi); + } + } + populateUncommonFrames(commonFrames, stepArray, firsExactClassLoader); + } + + void populateUncommonFrames(int commonFrames, StackTraceElementProxy[] stepArray, ClassLoader firstExactClassLoader) + { + int uncommonFrames = stepArray.length - commonFrames; + for (int i = 0; i < uncommonFrames; i++) { + StackTraceElementProxy step = stepArray[i]; + ClassPackagingData pi = computeBySTEP(step, firstExactClassLoader); + step.setClassPackagingData(pi); + } + } + + private ClassPackagingData calculateByExactType(Class type) { + String className = type.getName(); + ClassPackagingData cpd = (ClassPackagingData)cache.get(className); + if (cpd != null) { + return cpd; + } + String version = getImplementationVersion(type); + String codeLocation = getCodeLocation(type); + cpd = new ClassPackagingData(codeLocation, version); + cache.put(className, cpd); + return cpd; + } + + private ClassPackagingData computeBySTEP(StackTraceElementProxy step, ClassLoader lastExactClassLoader) + { + String className = ste.getClassName(); + ClassPackagingData cpd = (ClassPackagingData)cache.get(className); + if (cpd != null) { + return cpd; + } + Class type = bestEffortLoadClass(lastExactClassLoader, className); + String version = getImplementationVersion(type); + String codeLocation = getCodeLocation(type); + cpd = new ClassPackagingData(codeLocation, version, false); + cache.put(className, cpd); + return cpd; + } + + String getImplementationVersion(Class type) { + if (type == null) { + return "na"; + } + Package aPackage = type.getPackage(); + if (aPackage != null) { + String v = aPackage.getImplementationVersion(); + if (v == null) { + return "na"; + } + return v; + } + + return "na"; + } + + String getCodeLocation(Class type) + { + try { + if (type != null) + { + CodeSource codeSource = type.getProtectionDomain().getCodeSource(); + if (codeSource != null) { + URL resource = codeSource.getLocation(); + if (resource != null) { + String locationStr = resource.toString(); + + String result = getCodeLocation(locationStr, '/'); + if (result != null) { + return result; + } + return getCodeLocation(locationStr, '\\'); + } + } + } + } + catch (Exception e) {} + + return "na"; + } + + private String getCodeLocation(String locationStr, char separator) { + int idx = locationStr.lastIndexOf(separator); + if (isFolder(idx, locationStr)) { + idx = locationStr.lastIndexOf(separator, idx - 1); + return locationStr.substring(idx + 1); } + if (idx > 0) { + return locationStr.substring(idx + 1); + } + return null; + } + + private boolean isFolder(int idx, String text) { + return (idx != -1) && (idx + 1 == text.length()); + } + + private Class loadClass(ClassLoader cl, String className) { + if (cl == null) { + return null; + } + try { + return cl.loadClass(className); + } catch (ClassNotFoundException e1) { + return null; + } catch (NoClassDefFoundError e1) { + return null; + } catch (Exception e) { + e.printStackTrace(); } + return null; + } + + + + + + + + + private Class bestEffortLoadClass(ClassLoader lastGuaranteedClassLoader, String className) + { + Class result = loadClass(lastGuaranteedClassLoader, className); + if (result != null) { + return result; + } + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + if (tccl != lastGuaranteedClassLoader) { + result = loadClass(tccl, className); + } + if (result != null) { + return result; + } + try + { + return Class.forName(className); + } catch (ClassNotFoundException e1) { + return null; + } catch (NoClassDefFoundError e1) { + return null; + } catch (Exception e) { + e.printStackTrace(); } + return null; + } + + public PackagingDataCalculator() {} +} diff --git a/src/minecraft/ch/qos/logback/classic/spi/PlatformInfo.java b/src/minecraft/ch/qos/logback/classic/spi/PlatformInfo.java new file mode 100644 index 0000000..6c46ea9 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/spi/PlatformInfo.java @@ -0,0 +1,38 @@ +package ch.qos.logback.classic.spi; + + + + + + + +public class PlatformInfo +{ + private static final int UNINITIALIZED = -1; + + + + + + + public PlatformInfo() {} + + + + + + + private static int hasJMXObjectName = -1; + + public static boolean hasJMXObjectName() { + if (hasJMXObjectName == -1) { + try { + Class.forName("javax.management.ObjectName"); + hasJMXObjectName = 1; + } catch (Throwable e) { + hasJMXObjectName = 0; + } + } + return hasJMXObjectName == 1; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/spi/STEUtil.java b/src/minecraft/ch/qos/logback/classic/spi/STEUtil.java new file mode 100644 index 0000000..6f03f3e --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/spi/STEUtil.java @@ -0,0 +1,61 @@ +package ch.qos.logback.classic.spi; + + + + + + + +public class STEUtil +{ + public STEUtil() {} + + + + + + + + static int UNUSED_findNumberOfCommonFrames(StackTraceElement[] steArray, StackTraceElement[] otherSTEArray) + { + if (otherSTEArray == null) { + return 0; + } + + int steIndex = steArray.length - 1; + int parentIndex = otherSTEArray.length - 1; + int count = 0; + while ((steIndex >= 0) && (parentIndex >= 0) && + (steArray[steIndex].equals(otherSTEArray[parentIndex]))) { + count++; + + + + steIndex--; + parentIndex--; + } + return count; + } + + + static int findNumberOfCommonFrames(StackTraceElement[] steArray, StackTraceElementProxy[] otherSTEPArray) + { + if (otherSTEPArray == null) { + return 0; + } + + int steIndex = steArray.length - 1; + int parentIndex = otherSTEPArray.length - 1; + int count = 0; + while ((steIndex >= 0) && (parentIndex >= 0) && + (steArray[steIndex].equals(ste))) { + count++; + + + + steIndex--; + parentIndex--; + } + return count; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/spi/StackTraceElementProxy.java b/src/minecraft/ch/qos/logback/classic/spi/StackTraceElementProxy.java new file mode 100644 index 0000000..0431b38 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/spi/StackTraceElementProxy.java @@ -0,0 +1,90 @@ +package ch.qos.logback.classic.spi; + +import java.io.Serializable; + + + + + + + + + + + + + + + +public class StackTraceElementProxy + implements Serializable +{ + private static final long serialVersionUID = -2374374378980555982L; + final StackTraceElement ste; + private transient String steAsString; + private ClassPackagingData cpd; + + public StackTraceElementProxy(StackTraceElement ste) + { + if (ste == null) { + throw new IllegalArgumentException("ste cannot be null"); + } + this.ste = ste; + } + + public String getSTEAsString() + { + if (steAsString == null) { + steAsString = ("at " + ste.toString()); + } + return steAsString; + } + + public StackTraceElement getStackTraceElement() { + return ste; + } + + public void setClassPackagingData(ClassPackagingData cpd) { + if (this.cpd != null) { + throw new IllegalStateException("Packaging data has been already set"); + } + this.cpd = cpd; + } + + public ClassPackagingData getClassPackagingData() { + return cpd; + } + + public int hashCode() + { + return ste.hashCode(); + } + + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + StackTraceElementProxy other = (StackTraceElementProxy)obj; + + if (!ste.equals(ste)) { + return false; + } + if (cpd == null) { + if (cpd != null) { + return false; + } + } else if (!cpd.equals(cpd)) { + return false; + } + return true; + } + + public String toString() + { + return getSTEAsString(); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/spi/ThrowableProxy.java b/src/minecraft/ch/qos/logback/classic/spi/ThrowableProxy.java new file mode 100644 index 0000000..9c55871 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/spi/ThrowableProxy.java @@ -0,0 +1,163 @@ +package ch.qos.logback.classic.spi; + +import ch.qos.logback.core.CoreConstants; +import java.io.PrintStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + + + + + + + + + + + + + + + +public class ThrowableProxy + implements IThrowableProxy +{ + private Throwable throwable; + private String className; + private String message; + StackTraceElementProxy[] stackTraceElementProxyArray; + int commonFrames; + private ThrowableProxy cause; + private ThrowableProxy[] suppressed = NO_SUPPRESSED; + + private transient PackagingDataCalculator packagingDataCalculator; + private boolean calculatedPackageData = false; + private static final Method GET_SUPPRESSED_METHOD; + + static + { + Method method = null; + try { + method = Throwable.class.getMethod("getSuppressed", new Class[0]); + } + catch (NoSuchMethodException e) {} + + GET_SUPPRESSED_METHOD = method; + } + + private static final ThrowableProxy[] NO_SUPPRESSED = new ThrowableProxy[0]; + + public ThrowableProxy(Throwable throwable) + { + this.throwable = throwable; + className = throwable.getClass().getName(); + message = throwable.getMessage(); + stackTraceElementProxyArray = ThrowableProxyUtil.steArrayToStepArray(throwable.getStackTrace()); + + + Throwable nested = throwable.getCause(); + + if (nested != null) { + cause = new ThrowableProxy(nested); + cause.commonFrames = ThrowableProxyUtil.findNumberOfCommonFrames(nested.getStackTrace(), stackTraceElementProxyArray); + } + + + if (GET_SUPPRESSED_METHOD != null) { + try + { + Object obj = GET_SUPPRESSED_METHOD.invoke(throwable, new Object[0]); + if ((obj instanceof Throwable[])) { + Throwable[] throwableSuppressed = (Throwable[])obj; + if (throwableSuppressed.length > 0) { + suppressed = new ThrowableProxy[throwableSuppressed.length]; + for (int i = 0; i < throwableSuppressed.length; i++) { + suppressed[i] = new ThrowableProxy(throwableSuppressed[i]); + suppressed[i].commonFrames = ThrowableProxyUtil.findNumberOfCommonFrames(throwableSuppressed[i].getStackTrace(), stackTraceElementProxyArray); + } + } + } + } + catch (IllegalAccessException e) {}catch (InvocationTargetException e) {} + } + } + + + + + + + + public Throwable getThrowable() + { + return throwable; + } + + public String getMessage() { + return message; + } + + + + + + public String getClassName() + { + return className; + } + + public StackTraceElementProxy[] getStackTraceElementProxyArray() { + return stackTraceElementProxyArray; + } + + public int getCommonFrames() { + return commonFrames; + } + + + + + + public IThrowableProxy getCause() + { + return cause; + } + + public IThrowableProxy[] getSuppressed() { + return suppressed; + } + + + + public PackagingDataCalculator getPackagingDataCalculator() + { + if ((throwable != null) && (packagingDataCalculator == null)) { + packagingDataCalculator = new PackagingDataCalculator(); + } + return packagingDataCalculator; + } + + public void calculatePackagingData() { + if (calculatedPackageData) { + return; + } + PackagingDataCalculator pdc = getPackagingDataCalculator(); + if (pdc != null) { + calculatedPackageData = true; + pdc.calculate(this); + } + } + + + public void fullDump() + { + StringBuilder builder = new StringBuilder(); + for (StackTraceElementProxy step : stackTraceElementProxyArray) { + String string = step.toString(); + builder.append('\t').append(string); + ThrowableProxyUtil.subjoinPackagingData(builder, step); + builder.append(CoreConstants.LINE_SEPARATOR); + } + System.out.println(builder.toString()); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/spi/ThrowableProxyUtil.java b/src/minecraft/ch/qos/logback/classic/spi/ThrowableProxyUtil.java new file mode 100644 index 0000000..937e4ab --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/spi/ThrowableProxyUtil.java @@ -0,0 +1,189 @@ +package ch.qos.logback.classic.spi; + +import ch.qos.logback.core.CoreConstants; + + + + + + + + + + + + + + + + + + + +public class ThrowableProxyUtil +{ + public static final int REGULAR_EXCEPTION_INDENT = 1; + public static final int SUPPRESSED_EXCEPTION_INDENT = 1; + private static final int BUILDER_CAPACITY = 2048; + + public ThrowableProxyUtil() {} + + public static void build(ThrowableProxy nestedTP, Throwable nestedThrowable, ThrowableProxy parentTP) + { + StackTraceElement[] nestedSTE = nestedThrowable.getStackTrace(); + + int commonFramesCount = -1; + if (parentTP != null) { + commonFramesCount = findNumberOfCommonFrames(nestedSTE, parentTP.getStackTraceElementProxyArray()); + } + + + commonFrames = commonFramesCount; + stackTraceElementProxyArray = steArrayToStepArray(nestedSTE); + } + + static StackTraceElementProxy[] steArrayToStepArray(StackTraceElement[] stea) { + if (stea == null) { + return new StackTraceElementProxy[0]; + } + StackTraceElementProxy[] stepa = new StackTraceElementProxy[stea.length]; + for (int i = 0; i < stepa.length; i++) { + stepa[i] = new StackTraceElementProxy(stea[i]); + } + return stepa; + } + + static int findNumberOfCommonFrames(StackTraceElement[] steArray, StackTraceElementProxy[] parentSTEPArray) + { + if ((parentSTEPArray == null) || (steArray == null)) { + return 0; + } + + int steIndex = steArray.length - 1; + int parentIndex = parentSTEPArray.length - 1; + int count = 0; + while ((steIndex >= 0) && (parentIndex >= 0)) { + StackTraceElement ste = steArray[steIndex]; + StackTraceElement otherSte = ste; + if (!ste.equals(otherSte)) break; + count++; + + + + steIndex--; + parentIndex--; + } + return count; + } + + public static String asString(IThrowableProxy tp) { + StringBuilder sb = new StringBuilder(2048); + + recursiveAppend(sb, null, 1, tp); + + return sb.toString(); + } + + private static void recursiveAppend(StringBuilder sb, String prefix, int indent, IThrowableProxy tp) { + if (tp == null) + return; + subjoinFirstLine(sb, prefix, indent, tp); + sb.append(CoreConstants.LINE_SEPARATOR); + subjoinSTEPArray(sb, indent, tp); + IThrowableProxy[] suppressed = tp.getSuppressed(); + if (suppressed != null) { + for (IThrowableProxy current : suppressed) { + recursiveAppend(sb, "Suppressed: ", indent + 1, current); + } + } + recursiveAppend(sb, "Caused by: ", indent, tp.getCause()); + } + + public static void indent(StringBuilder buf, int indent) { + for (int j = 0; j < indent; j++) { + buf.append('\t'); + } + } + + private static void subjoinFirstLine(StringBuilder buf, String prefix, int indent, IThrowableProxy tp) { + indent(buf, indent - 1); + if (prefix != null) { + buf.append(prefix); + } + subjoinExceptionMessage(buf, tp); + } + + public static void subjoinPackagingData(StringBuilder builder, StackTraceElementProxy step) { + if (step != null) { + ClassPackagingData cpd = step.getClassPackagingData(); + if (cpd != null) { + if (!cpd.isExact()) { + builder.append(" ~["); + } else { + builder.append(" ["); + } + + builder.append(cpd.getCodeLocation()).append(':').append(cpd.getVersion()).append(']'); + } + } + } + + public static void subjoinSTEP(StringBuilder sb, StackTraceElementProxy step) + { + sb.append(step.toString()); + subjoinPackagingData(sb, step); + } + + + + /** + * @deprecated + */ + public static void subjoinSTEPArray(StringBuilder sb, IThrowableProxy tp) + { + subjoinSTEPArray(sb, 1, tp); + } + + + + + + public static void subjoinSTEPArray(StringBuilder sb, int indentLevel, IThrowableProxy tp) + { + StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray(); + int commonFrames = tp.getCommonFrames(); + + for (int i = 0; i < stepArray.length - commonFrames; i++) { + StackTraceElementProxy step = stepArray[i]; + indent(sb, indentLevel); + subjoinSTEP(sb, step); + sb.append(CoreConstants.LINE_SEPARATOR); + } + + if (commonFrames > 0) { + indent(sb, indentLevel); + sb.append("... ").append(commonFrames).append(" common frames omitted").append(CoreConstants.LINE_SEPARATOR); + } + } + + + public static void subjoinFirstLine(StringBuilder buf, IThrowableProxy tp) + { + int commonFrames = tp.getCommonFrames(); + if (commonFrames > 0) { + buf.append("Caused by: "); + } + subjoinExceptionMessage(buf, tp); + } + + public static void subjoinFirstLineRootCauseFirst(StringBuilder buf, IThrowableProxy tp) { + if (tp.getCause() != null) { + buf.append("Wrapped by: "); + } + subjoinExceptionMessage(buf, tp); + } + + private static void subjoinExceptionMessage(StringBuilder buf, IThrowableProxy tp) { + buf.append(tp.getClassName()).append(": ").append(tp.getMessage()); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/spi/ThrowableProxyVO.java b/src/minecraft/ch/qos/logback/classic/spi/ThrowableProxyVO.java new file mode 100644 index 0000000..60791e7 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/spi/ThrowableProxyVO.java @@ -0,0 +1,117 @@ +package ch.qos.logback.classic.spi; + +import java.io.Serializable; +import java.util.Arrays; + + + + + + + + + + + + +public class ThrowableProxyVO + implements IThrowableProxy, Serializable +{ + private static final long serialVersionUID = -773438177285807139L; + private String className; + private String message; + private int commonFramesCount; + private StackTraceElementProxy[] stackTraceElementProxyArray; + private IThrowableProxy cause; + private IThrowableProxy[] suppressed; + + public ThrowableProxyVO() {} + + public String getMessage() + { + return message; + } + + public String getClassName() { + return className; + } + + public int getCommonFrames() { + return commonFramesCount; + } + + public IThrowableProxy getCause() { + return cause; + } + + public StackTraceElementProxy[] getStackTraceElementProxyArray() { + return stackTraceElementProxyArray; + } + + public IThrowableProxy[] getSuppressed() { + return suppressed; + } + + public int hashCode() + { + int prime = 31; + int result = 1; + result = 31 * result + (className == null ? 0 : className.hashCode()); + + return result; + } + + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ThrowableProxyVO other = (ThrowableProxyVO)obj; + + if (className == null) { + if (className != null) + return false; + } else if (!className.equals(className)) { + return false; + } + if (!Arrays.equals(stackTraceElementProxyArray, stackTraceElementProxyArray)) { + return false; + } + if (!Arrays.equals(suppressed, suppressed)) { + return false; + } + if (cause == null) { + if (cause != null) + return false; + } else if (!cause.equals(cause)) { + return false; + } + return true; + } + + public static ThrowableProxyVO build(IThrowableProxy throwableProxy) { + if (throwableProxy == null) { + return null; + } + ThrowableProxyVO tpvo = new ThrowableProxyVO(); + className = throwableProxy.getClassName(); + message = throwableProxy.getMessage(); + commonFramesCount = throwableProxy.getCommonFrames(); + stackTraceElementProxyArray = throwableProxy.getStackTraceElementProxyArray(); + IThrowableProxy cause = throwableProxy.getCause(); + if (cause != null) { + cause = build(cause); + } + IThrowableProxy[] suppressed = throwableProxy.getSuppressed(); + if (suppressed != null) { + suppressed = new IThrowableProxy[suppressed.length]; + for (int i = 0; i < suppressed.length; i++) { + suppressed[i] = build(suppressed[i]); + } + } + return tpvo; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/spi/TurboFilterList.java b/src/minecraft/ch/qos/logback/classic/spi/TurboFilterList.java new file mode 100644 index 0000000..9a2114c --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/spi/TurboFilterList.java @@ -0,0 +1,69 @@ +package ch.qos.logback.classic.spi; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.turbo.TurboFilter; +import ch.qos.logback.core.spi.FilterReply; +import java.util.concurrent.CopyOnWriteArrayList; +import org.slf4j.Marker; + + + + + + + + + + + + + + + + + + + + + + + + + + +public final class TurboFilterList + extends CopyOnWriteArrayList +{ + private static final long serialVersionUID = 1L; + + public TurboFilterList() {} + + public FilterReply getTurboFilterChainDecision(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) + { + int size = size(); + + + + if (size == 1) { + try { + TurboFilter tf = (TurboFilter)get(0); + return tf.decide(marker, logger, level, format, params, t); + } catch (IndexOutOfBoundsException iobe) { + return FilterReply.NEUTRAL; + } + } + + Object[] tfa = toArray(); + int len = tfa.length; + for (int i = 0; i < len; i++) + { + TurboFilter tf = (TurboFilter)tfa[i]; + FilterReply r = tf.decide(marker, logger, level, format, params, t); + if ((r == FilterReply.DENY) || (r == FilterReply.ACCEPT)) { + return r; + } + } + return FilterReply.NEUTRAL; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/turbo/DuplicateMessageFilter.java b/src/minecraft/ch/qos/logback/classic/turbo/DuplicateMessageFilter.java new file mode 100644 index 0000000..ac7817e --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/turbo/DuplicateMessageFilter.java @@ -0,0 +1,90 @@ +package ch.qos.logback.classic.turbo; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.core.spi.FilterReply; +import org.slf4j.Marker; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class DuplicateMessageFilter + extends TurboFilter +{ + public static final int DEFAULT_CACHE_SIZE = 100; + public static final int DEFAULT_ALLOWED_REPETITIONS = 5; + public int allowedRepetitions = 5; + public int cacheSize = 100; + private LRUMessageCache msgCache; + + public DuplicateMessageFilter() {} + + public void start() { + msgCache = new LRUMessageCache(cacheSize); + super.start(); + } + + public void stop() + { + msgCache.clear(); + msgCache = null; + super.stop(); + } + + + public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) + { + int count = msgCache.getMessageCountAndThenIncrement(format); + if (count <= allowedRepetitions) { + return FilterReply.NEUTRAL; + } + return FilterReply.DENY; + } + + public int getAllowedRepetitions() + { + return allowedRepetitions; + } + + + + + + public void setAllowedRepetitions(int allowedRepetitions) + { + this.allowedRepetitions = allowedRepetitions; + } + + public int getCacheSize() { + return cacheSize; + } + + public void setCacheSize(int cacheSize) { + this.cacheSize = cacheSize; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/turbo/DynamicThresholdFilter.java b/src/minecraft/ch/qos/logback/classic/turbo/DynamicThresholdFilter.java new file mode 100644 index 0000000..b589b86 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/turbo/DynamicThresholdFilter.java @@ -0,0 +1,256 @@ +package ch.qos.logback.classic.turbo; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.core.spi.FilterReply; +import java.util.HashMap; +import java.util.Map; +import org.slf4j.MDC; +import org.slf4j.Marker; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class DynamicThresholdFilter + extends TurboFilter +{ + private Map valueLevelMap = new HashMap(); + private Level defaultThreshold = Level.ERROR; + + private String key; + private FilterReply onHigherOrEqual = FilterReply.NEUTRAL; + private FilterReply onLower = FilterReply.DENY; + + + public DynamicThresholdFilter() {} + + + public String getKey() + { + return key; + } + + + + public void setKey(String key) + { + this.key = key; + } + + + + + + public Level getDefaultThreshold() + { + return defaultThreshold; + } + + public void setDefaultThreshold(Level defaultThreshold) { + this.defaultThreshold = defaultThreshold; + } + + + + + + + public FilterReply getOnHigherOrEqual() + { + return onHigherOrEqual; + } + + public void setOnHigherOrEqual(FilterReply onHigherOrEqual) { + this.onHigherOrEqual = onHigherOrEqual; + } + + + + + + + public FilterReply getOnLower() + { + return onLower; + } + + public void setOnLower(FilterReply onLower) { + this.onLower = onLower; + } + + + + public void addMDCValueLevelPair(MDCValueLevelPair mdcValueLevelPair) + { + if (valueLevelMap.containsKey(mdcValueLevelPair.getValue())) { + addError(mdcValueLevelPair.getValue() + " has been already set"); + } else { + valueLevelMap.put(mdcValueLevelPair.getValue(), mdcValueLevelPair.getLevel()); + } + } + + + + + + public void start() + { + if (key == null) { + addError("No key name was specified"); + } + super.start(); + } + + + + + + + + + + + + + + + + + + + + + + + + public FilterReply decide(Marker marker, Logger logger, Level level, String s, Object[] objects, Throwable throwable) + { + String mdcValue = MDC.get(key); + if (!isStarted()) { + return FilterReply.NEUTRAL; + } + + Level levelAssociatedWithMDCValue = null; + if (mdcValue != null) { + levelAssociatedWithMDCValue = (Level)valueLevelMap.get(mdcValue); + } + if (levelAssociatedWithMDCValue == null) { + levelAssociatedWithMDCValue = defaultThreshold; + } + if (level.isGreaterOrEqual(levelAssociatedWithMDCValue)) { + return onHigherOrEqual; + } + return onLower; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/turbo/LRUMessageCache.java b/src/minecraft/ch/qos/logback/classic/turbo/LRUMessageCache.java new file mode 100644 index 0000000..ced7fbc --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/turbo/LRUMessageCache.java @@ -0,0 +1,66 @@ +package ch.qos.logback.classic.turbo; + +import java.util.LinkedHashMap; +import java.util.Map.Entry; + + + + + + + + + + + + + + + + +class LRUMessageCache + extends LinkedHashMap +{ + private static final long serialVersionUID = 1L; + final int cacheSize; + + LRUMessageCache(int cacheSize) + { + super((int)(cacheSize * 1.3333334F), 0.75F, true); + if (cacheSize < 1) { + throw new IllegalArgumentException("Cache size cannot be smaller than 1"); + } + this.cacheSize = cacheSize; + } + + int getMessageCountAndThenIncrement(String msg) + { + if (msg == null) { + return 0; + } + + Integer i; + + synchronized (this) { + i = (Integer)super.get(msg); + if (i == null) { + i = Integer.valueOf(0); + } else { + i = Integer.valueOf(i.intValue() + 1); + } + super.put(msg, i); + } + return i.intValue(); + } + + + protected boolean removeEldestEntry(Map.Entry eldest) + { + return size() > cacheSize; + } + + public synchronized void clear() + { + super.clear(); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/turbo/MDCFilter.java b/src/minecraft/ch/qos/logback/classic/turbo/MDCFilter.java new file mode 100644 index 0000000..8cf27ed --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/turbo/MDCFilter.java @@ -0,0 +1,71 @@ +package ch.qos.logback.classic.turbo; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.core.spi.FilterReply; +import org.slf4j.MDC; +import org.slf4j.Marker; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class MDCFilter + extends MatchingFilter +{ + String MDCKey; + String value; + + public MDCFilter() {} + + public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) + { + if (MDCKey == null) { + return FilterReply.NEUTRAL; + } + + String value = MDC.get(MDCKey); + if (this.value.equals(value)) { + return onMatch; + } + return onMismatch; + } + + public void setValue(String value) { + this.value = value; + } + + public void setMDCKey(String MDCKey) { + this.MDCKey = MDCKey; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/turbo/MDCValueLevelPair.java b/src/minecraft/ch/qos/logback/classic/turbo/MDCValueLevelPair.java new file mode 100644 index 0000000..cbfb3bc --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/turbo/MDCValueLevelPair.java @@ -0,0 +1,44 @@ +package ch.qos.logback.classic.turbo; + +import ch.qos.logback.classic.Level; + + + + + + + + + + + + + + + + + +public class MDCValueLevelPair +{ + private String value; + private Level level; + + public MDCValueLevelPair() {} + + public String getValue() + { + return value; + } + + public void setValue(String name) { + value = name; + } + + public Level getLevel() { + return level; + } + + public void setLevel(Level level) { + this.level = level; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/turbo/MarkerFilter.java b/src/minecraft/ch/qos/logback/classic/turbo/MarkerFilter.java new file mode 100644 index 0000000..a84de54 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/turbo/MarkerFilter.java @@ -0,0 +1,67 @@ +package ch.qos.logback.classic.turbo; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.core.spi.FilterReply; +import org.slf4j.Marker; +import org.slf4j.MarkerFactory; + + + + + + + + + + + + + + + + +public class MarkerFilter + extends MatchingFilter +{ + Marker markerToMatch; + + public MarkerFilter() {} + + public void start() + { + if (markerToMatch != null) { + super.start(); + } else { + addError("The marker property must be set for [" + getName() + "]"); + } + } + + public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) + { + if (!isStarted()) { + return FilterReply.NEUTRAL; + } + + if (marker == null) { + return onMismatch; + } + + if (marker.contains(markerToMatch)) { + return onMatch; + } + return onMismatch; + } + + + + + + + public void setMarker(String markerStr) + { + if (markerStr != null) { + markerToMatch = MarkerFactory.getMarker(markerStr); + } + } +} diff --git a/src/minecraft/ch/qos/logback/classic/turbo/MatchingFilter.java b/src/minecraft/ch/qos/logback/classic/turbo/MatchingFilter.java new file mode 100644 index 0000000..7dfa4e3 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/turbo/MatchingFilter.java @@ -0,0 +1,48 @@ +package ch.qos.logback.classic.turbo; + +import ch.qos.logback.core.spi.FilterReply; + + + + + + + + + + + + + + + + + +public abstract class MatchingFilter + extends TurboFilter +{ + public MatchingFilter() {} + + protected FilterReply onMatch = FilterReply.NEUTRAL; + protected FilterReply onMismatch = FilterReply.NEUTRAL; + + public final void setOnMatch(String action) { + if ("NEUTRAL".equals(action)) { + onMatch = FilterReply.NEUTRAL; + } else if ("ACCEPT".equals(action)) { + onMatch = FilterReply.ACCEPT; + } else if ("DENY".equals(action)) { + onMatch = FilterReply.DENY; + } + } + + public final void setOnMismatch(String action) { + if ("NEUTRAL".equals(action)) { + onMismatch = FilterReply.NEUTRAL; + } else if ("ACCEPT".equals(action)) { + onMismatch = FilterReply.ACCEPT; + } else if ("DENY".equals(action)) { + onMismatch = FilterReply.DENY; + } + } +} diff --git a/src/minecraft/ch/qos/logback/classic/turbo/ReconfigureOnChangeFilter.java b/src/minecraft/ch/qos/logback/classic/turbo/ReconfigureOnChangeFilter.java new file mode 100644 index 0000000..2c042e8 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/turbo/ReconfigureOnChangeFilter.java @@ -0,0 +1,279 @@ +package ch.qos.logback.classic.turbo; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.gaffer.GafferUtil; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.classic.util.EnvUtil; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.joran.event.SaxEvent; +import ch.qos.logback.core.joran.spi.ConfigurationWatchList; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.joran.util.ConfigurationWatchListUtil; +import ch.qos.logback.core.spi.FilterReply; +import ch.qos.logback.core.status.StatusUtil; +import java.io.File; +import java.net.URL; +import java.util.List; +import java.util.concurrent.ExecutorService; +import org.slf4j.Marker; + + + + + + + + + + + + + + + + + + + + + +public class ReconfigureOnChangeFilter + extends TurboFilter +{ + public static final long DEFAULT_REFRESH_PERIOD = 60000L; + long refreshPeriod; + URL mainConfigurationURL; + protected volatile long nextCheck; + ConfigurationWatchList configurationWatchList; + private long invocationCounter; + private volatile long mask; + private volatile long lastMaskCheck; + private static final int MAX_MASK = 65535; + private static final long MASK_INCREASE_THRESHOLD = 100L; + private static final long MASK_DECREASE_THRESHOLD = 800L; + + public void start() + { + configurationWatchList = ConfigurationWatchListUtil.getConfigurationWatchList(context); + if (configurationWatchList != null) { + mainConfigurationURL = configurationWatchList.getMainURL(); + if (mainConfigurationURL == null) { + addWarn("Due to missing top level configuration file, automatic reconfiguration is impossible."); + return; + } + List watchList = configurationWatchList.getCopyOfFileWatchList(); + long inSeconds = refreshPeriod / 1000L; + addInfo("Will scan for changes in [" + watchList + "] every " + inSeconds + " seconds. "); + + synchronized (configurationWatchList) { + updateNextCheck(System.currentTimeMillis()); + } + super.start(); + } else { + addWarn("Empty ConfigurationWatchList in context"); + } + } + + public String toString() + { + return "ReconfigureOnChangeFilter{invocationCounter=" + invocationCounter + '}'; + } + + public ReconfigureOnChangeFilter() + { + refreshPeriod = 60000L; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + invocationCounter = 0L; + + mask = 15L; + lastMaskCheck = System.currentTimeMillis(); + } + + + public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) + { + if (!isStarted()) { + return FilterReply.NEUTRAL; + } + + + + + if ((invocationCounter++ & mask) != mask) { + return FilterReply.NEUTRAL; + } + + long now = System.currentTimeMillis(); + + synchronized (configurationWatchList) { + updateMaskIfNecessary(now); + if (changeDetected(now)) + { + + + + disableSubsequentReconfiguration(); + detachReconfigurationToNewThread(); + } + } + + return FilterReply.NEUTRAL; + } + + + + + + + + + + + + + + + private void updateMaskIfNecessary(long now) + { + long timeElapsedSinceLastMaskUpdateCheck = now - lastMaskCheck; + lastMaskCheck = now; + if ((timeElapsedSinceLastMaskUpdateCheck < 100L) && (mask < 65535L)) { + mask = (mask << 1 | 1L); + } else if (timeElapsedSinceLastMaskUpdateCheck > 800L) { + mask >>>= 2; + } + } + + + + void detachReconfigurationToNewThread() + { + addInfo("Detected change in [" + configurationWatchList.getCopyOfFileWatchList() + "]"); + context.getExecutorService().submit(new ReconfiguringThread()); + } + + void updateNextCheck(long now) { + nextCheck = (now + refreshPeriod); + } + + protected boolean changeDetected(long now) { + if (now >= nextCheck) { + updateNextCheck(now); + return configurationWatchList.changeDetected(); + } + return false; + } + + void disableSubsequentReconfiguration() { + nextCheck = Long.MAX_VALUE; + } + + public long getRefreshPeriod() { + return refreshPeriod; + } + + + public void setRefreshPeriod(long refreshPeriod) { this.refreshPeriod = refreshPeriod; } + + class ReconfiguringThread implements Runnable { + ReconfiguringThread() {} + + public void run() { if (mainConfigurationURL == null) { + addInfo("Due to missing top level configuration file, skipping reconfiguration"); + return; + } + LoggerContext lc = (LoggerContext)context; + addInfo("Will reset and reconfigure context named [" + context.getName() + "]"); + if (mainConfigurationURL.toString().endsWith("xml")) { + performXMLConfiguration(lc); + } else if (mainConfigurationURL.toString().endsWith("groovy")) { + if (EnvUtil.isGroovyAvailable()) { + lc.reset(); + + + GafferUtil.runGafferConfiguratorOn(lc, this, mainConfigurationURL); + } else { + addError("Groovy classes are not available on the class path. ABORTING INITIALIZATION."); + } + } + } + + private void performXMLConfiguration(LoggerContext lc) { + JoranConfigurator jc = new JoranConfigurator(); + jc.setContext(context); + StatusUtil statusUtil = new StatusUtil(context); + List eventList = jc.recallSafeConfiguration(); + URL mainURL = ConfigurationWatchListUtil.getMainWatchURL(context); + lc.reset(); + long threshold = System.currentTimeMillis(); + try { + jc.doConfigure(mainConfigurationURL); + if (statusUtil.hasXMLParsingErrors(threshold)) { + fallbackConfiguration(lc, eventList, mainURL); + } + } catch (JoranException e) { + fallbackConfiguration(lc, eventList, mainURL); + } + } + + private void fallbackConfiguration(LoggerContext lc, List eventList, URL mainURL) { + JoranConfigurator joranConfigurator = new JoranConfigurator(); + joranConfigurator.setContext(context); + if (eventList != null) { + addWarn("Falling back to previously registered safe configuration."); + try { + lc.reset(); + JoranConfigurator.informContextOfURLUsedForConfiguration(context, mainURL); + joranConfigurator.doConfigure(eventList); + addInfo("Re-registering previous fallback configuration once more as a fallback configuration point"); + joranConfigurator.registerSafeConfiguration(); + } catch (JoranException e) { + addError("Unexpected exception thrown by a configuration considered safe.", e); + } + } else { + addWarn("No previous configuration to fall back on."); + } + } + } +} diff --git a/src/minecraft/ch/qos/logback/classic/turbo/TurboFilter.java b/src/minecraft/ch/qos/logback/classic/turbo/TurboFilter.java new file mode 100644 index 0000000..3d4f23f --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/turbo/TurboFilter.java @@ -0,0 +1,76 @@ +package ch.qos.logback.classic.turbo; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.spi.FilterReply; +import ch.qos.logback.core.spi.LifeCycle; +import org.slf4j.Marker; + + + + + + + + + + + + + + + + + + + + + + + +public abstract class TurboFilter + extends ContextAwareBase + implements LifeCycle +{ + private String name; + boolean start = false; + + + + + + public TurboFilter() {} + + + + + + public abstract FilterReply decide(Marker paramMarker, Logger paramLogger, Level paramLevel, String paramString, Object[] paramArrayOfObject, Throwable paramThrowable); + + + + + + public void start() + { + start = true; + } + + public boolean isStarted() { + return start; + } + + public void stop() { + start = false; + } + + public String getName() + { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/util/ContextInitializer.java b/src/minecraft/ch/qos/logback/classic/util/ContextInitializer.java new file mode 100644 index 0000000..6fded8f --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/util/ContextInitializer.java @@ -0,0 +1,199 @@ +package ch.qos.logback.classic.util; + +import ch.qos.logback.classic.BasicConfigurator; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.gaffer.GafferUtil; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.classic.spi.Configurator; +import ch.qos.logback.core.LogbackException; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.status.ErrorStatus; +import ch.qos.logback.core.status.InfoStatus; +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.status.WarnStatus; +import ch.qos.logback.core.util.Loader; +import ch.qos.logback.core.util.OptionHelper; +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.util.Set; + + + + + + + + + + + + + + + + + + + + + + +public class ContextInitializer +{ + public static final String GROOVY_AUTOCONFIG_FILE = "logback.groovy"; + public static final String AUTOCONFIG_FILE = "logback.xml"; + public static final String TEST_AUTOCONFIG_FILE = "logback-test.xml"; + public static final String CONFIG_FILE_PROPERTY = "logback.configurationFile"; + public static final String STATUS_LISTENER_CLASS = "logback.statusListenerClass"; + public static final String SYSOUT = "SYSOUT"; + final LoggerContext loggerContext; + + public ContextInitializer(LoggerContext loggerContext) + { + this.loggerContext = loggerContext; + } + + public void configureByResource(URL url) throws JoranException { + if (url == null) { + throw new IllegalArgumentException("URL argument cannot be null"); + } + String urlString = url.toString(); + if (urlString.endsWith("groovy")) { + if (EnvUtil.isGroovyAvailable()) + { + + GafferUtil.runGafferConfiguratorOn(loggerContext, this, url); + } else { + StatusManager sm = loggerContext.getStatusManager(); + sm.add(new ErrorStatus("Groovy classes are not available on the class path. ABORTING INITIALIZATION.", loggerContext)); + } + } + else if (urlString.endsWith("xml")) { + JoranConfigurator configurator = new JoranConfigurator(); + configurator.setContext(loggerContext); + configurator.doConfigure(url); + } else { + throw new LogbackException("Unexpected filename extension of file [" + url.toString() + "]. Should be either .groovy or .xml"); + } + } + + void joranConfigureByResource(URL url) throws JoranException { + JoranConfigurator configurator = new JoranConfigurator(); + configurator.setContext(loggerContext); + configurator.doConfigure(url); + } + + private URL findConfigFileURLFromSystemProperties(ClassLoader classLoader, boolean updateStatus) { + String logbackConfigFile = OptionHelper.getSystemProperty("logback.configurationFile"); + if (logbackConfigFile != null) { + URL result = null; + try { + result = new URL(logbackConfigFile); + return result; + } + catch (MalformedURLException e) + { + result = Loader.getResource(logbackConfigFile, classLoader); + if (result != null) { + return result; + } + File f = new File(logbackConfigFile); + if ((f.exists()) && (f.isFile())) { + try { + result = f.toURI().toURL(); + return result; + } + catch (MalformedURLException e1) {} + } + } finally { + if (updateStatus) { + statusOnResourceSearch(logbackConfigFile, classLoader, result); + } + } + } + return null; + } + + public URL findURLOfDefaultConfigurationFile(boolean updateStatus) { + ClassLoader myClassLoader = Loader.getClassLoaderOfObject(this); + URL url = findConfigFileURLFromSystemProperties(myClassLoader, updateStatus); + if (url != null) { + return url; + } + + url = getResource("logback.groovy", myClassLoader, updateStatus); + if (url != null) { + return url; + } + + url = getResource("logback-test.xml", myClassLoader, updateStatus); + if (url != null) { + return url; + } + + return getResource("logback.xml", myClassLoader, updateStatus); + } + + private URL getResource(String filename, ClassLoader myClassLoader, boolean updateStatus) { + URL url = Loader.getResource(filename, myClassLoader); + if (updateStatus) { + statusOnResourceSearch(filename, myClassLoader, url); + } + return url; + } + + public void autoConfig() throws JoranException { + StatusListenerConfigHelper.installIfAsked(loggerContext); + URL url = findURLOfDefaultConfigurationFile(true); + if (url != null) { + configureByResource(url); + } else { + Configurator c = (Configurator)EnvUtil.loadFromServiceLoader(Configurator.class); + if (c != null) { + try { + c.setContext(loggerContext); + c.configure(loggerContext); + } catch (Exception e) { + throw new LogbackException(String.format("Failed to initialize Configurator: %s using ServiceLoader", new Object[] { c != null ? c.getClass().getCanonicalName() : "null" }), e); + } + + } else { + BasicConfigurator.configure(loggerContext); + } + } + } + + private void multiplicityWarning(String resourceName, ClassLoader classLoader) { + Set urlSet = null; + StatusManager sm = loggerContext.getStatusManager(); + try { + urlSet = Loader.getResourceOccurrenceCount(resourceName, classLoader); + } catch (IOException e) { + sm.add(new ErrorStatus("Failed to get url list for resource [" + resourceName + "]", loggerContext, e)); + } + + if ((urlSet != null) && (urlSet.size() > 1)) { + sm.add(new WarnStatus("Resource [" + resourceName + "] occurs multiple times on the classpath.", loggerContext)); + + for (URL url : urlSet) { + sm.add(new WarnStatus("Resource [" + resourceName + "] occurs at [" + url.toString() + "]", loggerContext)); + } + } + } + + private void statusOnResourceSearch(String resourceName, ClassLoader classLoader, URL url) + { + StatusManager sm = loggerContext.getStatusManager(); + if (url == null) { + sm.add(new InfoStatus("Could NOT find resource [" + resourceName + "]", loggerContext)); + } + else { + sm.add(new InfoStatus("Found resource [" + resourceName + "] at [" + url.toString() + "]", loggerContext)); + + multiplicityWarning(resourceName, classLoader); + } + } +} diff --git a/src/minecraft/ch/qos/logback/classic/util/ContextSelectorStaticBinder.java b/src/minecraft/ch/qos/logback/classic/util/ContextSelectorStaticBinder.java new file mode 100644 index 0000000..fb9b012 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/util/ContextSelectorStaticBinder.java @@ -0,0 +1,106 @@ +package ch.qos.logback.classic.util; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.selector.ContextJNDISelector; +import ch.qos.logback.classic.selector.ContextSelector; +import ch.qos.logback.classic.selector.DefaultContextSelector; +import ch.qos.logback.core.util.Loader; +import ch.qos.logback.core.util.OptionHelper; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + + + + + + + + + + + + + + + + + + + + + + +public class ContextSelectorStaticBinder +{ + static ContextSelectorStaticBinder singleton = new ContextSelectorStaticBinder(); + ContextSelector contextSelector; + Object key; + + public ContextSelectorStaticBinder() {} + + public static ContextSelectorStaticBinder getSingleton() { return singleton; } + + + + + + + + + + + + + public void init(LoggerContext defaultLoggerContext, Object key) + throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException + { + if (this.key == null) { + this.key = key; + } else if (this.key != key) { + throw new IllegalAccessException("Only certain classes can access this method."); + } + + + String contextSelectorStr = OptionHelper.getSystemProperty("logback.ContextSelector"); + + if (contextSelectorStr == null) { + contextSelector = new DefaultContextSelector(defaultLoggerContext); + } else if (contextSelectorStr.equals("JNDI")) + { + contextSelector = new ContextJNDISelector(defaultLoggerContext); + } else { + contextSelector = dynamicalContextSelector(defaultLoggerContext, contextSelectorStr); + } + } + + + + + + + + + + + + + + + + + + + + static ContextSelector dynamicalContextSelector(LoggerContext defaultLoggerContext, String contextSelectorStr) + throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException + { + Class contextSelectorClass = Loader.loadClass(contextSelectorStr); + Constructor cons = contextSelectorClass.getConstructor(new Class[] { LoggerContext.class }); + + return (ContextSelector)cons.newInstance(new Object[] { defaultLoggerContext }); + } + + public ContextSelector getContextSelector() { + return contextSelector; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/util/CopyOnInheritThreadLocal.java b/src/minecraft/ch/qos/logback/classic/util/CopyOnInheritThreadLocal.java new file mode 100644 index 0000000..ef8c11e --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/util/CopyOnInheritThreadLocal.java @@ -0,0 +1,38 @@ +package ch.qos.logback.classic.util; + +import java.util.HashMap; + + + + + + + + + + + + + + + + + + + + + + +public class CopyOnInheritThreadLocal + extends InheritableThreadLocal> +{ + public CopyOnInheritThreadLocal() {} + + protected HashMap childValue(HashMap parentValue) + { + if (parentValue == null) { + return null; + } + return new HashMap(parentValue); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/util/DefaultNestedComponentRules.java b/src/minecraft/ch/qos/logback/classic/util/DefaultNestedComponentRules.java new file mode 100644 index 0000000..2285de2 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/util/DefaultNestedComponentRules.java @@ -0,0 +1,47 @@ +package ch.qos.logback.classic.util; + +import ch.qos.logback.classic.PatternLayout; +import ch.qos.logback.classic.boolex.JaninoEventEvaluator; +import ch.qos.logback.classic.encoder.PatternLayoutEncoder; +import ch.qos.logback.core.AppenderBase; +import ch.qos.logback.core.UnsynchronizedAppenderBase; +import ch.qos.logback.core.filter.EvaluatorFilter; +import ch.qos.logback.core.joran.spi.DefaultNestedComponentRegistry; +import ch.qos.logback.core.net.ssl.SSLNestedComponentRegistryRules; + + + + + + + + + + + + + + + + + + + +public class DefaultNestedComponentRules +{ + public DefaultNestedComponentRules() {} + + public static void addDefaultNestedComponentRegistryRules(DefaultNestedComponentRegistry registry) + { + registry.add(AppenderBase.class, "layout", PatternLayout.class); + registry.add(UnsynchronizedAppenderBase.class, "layout", PatternLayout.class); + + registry.add(AppenderBase.class, "encoder", PatternLayoutEncoder.class); + registry.add(UnsynchronizedAppenderBase.class, "encoder", PatternLayoutEncoder.class); + + registry.add(EvaluatorFilter.class, "evaluator", JaninoEventEvaluator.class); + + + SSLNestedComponentRegistryRules.addDefaultNestedComponentRegistryRules(registry); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/util/EnvUtil.java b/src/minecraft/ch/qos/logback/classic/util/EnvUtil.java new file mode 100644 index 0000000..347fc48 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/util/EnvUtil.java @@ -0,0 +1,99 @@ +package ch.qos.logback.classic.util; + +import ch.qos.logback.core.util.Loader; +import java.lang.reflect.Method; +import java.util.Iterator; + + + + + + + + + + + + + + + + + + + + + + + + + +public class EnvUtil +{ + static ClassLoader testServiceLoaderClassLoader = null; + private static final Method serviceLoaderLoadMethod; + + public static boolean isGroovyAvailable() { ClassLoader classLoader = Loader.getClassLoaderOfClass(EnvUtil.class); + try { + Class bindingClass = classLoader.loadClass("groovy.lang.Binding"); + return bindingClass != null; + } catch (ClassNotFoundException e) {} + return false; + } + + + + + private static final Method serviceLoaderIteratorMethod; + + + + static + { + Method tLoadMethod = null; + Method tIteratorMethod = null; + try { + Class clazz = Class.forName("java.util.ServiceLoader"); + tLoadMethod = clazz.getMethod("load", new Class[] { Class.class, ClassLoader.class }); + tIteratorMethod = clazz.getMethod("iterator", new Class[0]); + } + catch (ClassNotFoundException ce) {}catch (NoSuchMethodException ne) {} + + + + serviceLoaderLoadMethod = tLoadMethod; + serviceLoaderIteratorMethod = tIteratorMethod; + } + + public static boolean isServiceLoaderAvailable() { + return (serviceLoaderLoadMethod != null) && (serviceLoaderIteratorMethod != null); + } + + private static ClassLoader getServiceLoaderClassLoader() { + return testServiceLoaderClassLoader == null ? Loader.getClassLoaderOfClass(EnvUtil.class) : testServiceLoaderClassLoader; + } + + public static T loadFromServiceLoader(Class c) + { + if (isServiceLoaderAvailable()) { + Object loader; + try { + loader = serviceLoaderLoadMethod.invoke(null, new Object[] { c, getServiceLoaderClassLoader() }); + } catch (Exception e) { + throw new IllegalStateException("Cannot invoke java.util.ServiceLoader#load()", e); + } + Iterator it; + try + { + it = (Iterator)serviceLoaderIteratorMethod.invoke(loader, new Object[0]); + } catch (Exception e) { + throw new IllegalStateException("Cannot invoke java.util.ServiceLoader#iterator()", e); + } + if (it.hasNext()) + return it.next(); + } + return null; + } + + public EnvUtil() {} +} diff --git a/src/minecraft/ch/qos/logback/classic/util/JNDIUtil.java b/src/minecraft/ch/qos/logback/classic/util/JNDIUtil.java new file mode 100644 index 0000000..4cd0525 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/util/JNDIUtil.java @@ -0,0 +1,43 @@ +package ch.qos.logback.classic.util; + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; + + + + + + + + + + + + + + + + + +public class JNDIUtil +{ + public JNDIUtil() {} + + public static Context getInitialContext() + throws NamingException + { + return new InitialContext(); + } + + public static String lookup(Context ctx, String name) { + if (ctx == null) { + return null; + } + try { + Object lookup = ctx.lookup(name); + return lookup == null ? null : lookup.toString(); + } catch (NamingException e) {} + return null; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/util/LevelToSyslogSeverity.java b/src/minecraft/ch/qos/logback/classic/util/LevelToSyslogSeverity.java new file mode 100644 index 0000000..e72a31f --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/util/LevelToSyslogSeverity.java @@ -0,0 +1,44 @@ +package ch.qos.logback.classic.util; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; + + + + + + + + + + + + + + + + + + +public class LevelToSyslogSeverity +{ + public LevelToSyslogSeverity() {} + + public static int convert(ILoggingEvent event) + { + Level level = event.getLevel(); + + switch (levelInt) { + case 40000: + return 3; + case 30000: + return 4; + case 20000: + return 6; + case 5000: + case 10000: + return 7; + } + throw new IllegalArgumentException("Level " + level + " is not a valid level for a printing method"); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/util/LogbackMDCAdapter.java b/src/minecraft/ch/qos/logback/classic/util/LogbackMDCAdapter.java new file mode 100644 index 0000000..063be3e --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/util/LogbackMDCAdapter.java @@ -0,0 +1,203 @@ +package ch.qos.logback.classic.util; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import org.slf4j.spi.MDCAdapter; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public final class LogbackMDCAdapter + implements MDCAdapter +{ + final InheritableThreadLocal> copyOnInheritThreadLocal = new InheritableThreadLocal(); + private static final int WRITE_OPERATION = 1; + private static final int READ_OPERATION = 2; + + public LogbackMDCAdapter() {} + + final ThreadLocal lastOperation = new ThreadLocal(); + + private Integer getAndSetLastOperation(int op) { + Integer lastOp = (Integer)lastOperation.get(); + lastOperation.set(Integer.valueOf(op)); + return lastOp; + } + + private boolean wasLastOpReadOrNull(Integer lastOp) { + return (lastOp == null) || (lastOp.intValue() == 2); + } + + private Map duplicateAndInsertNewMap(Map oldMap) { + Map newMap = Collections.synchronizedMap(new HashMap()); + if (oldMap != null) + { + + synchronized (oldMap) { + newMap.putAll(oldMap); + } + } + + copyOnInheritThreadLocal.set(newMap); + return newMap; + } + + + + + + + + + + + public void put(String key, String val) + throws IllegalArgumentException + { + if (key == null) { + throw new IllegalArgumentException("key cannot be null"); + } + + Map oldMap = (Map)copyOnInheritThreadLocal.get(); + Integer lastOp = getAndSetLastOperation(1); + + if ((wasLastOpReadOrNull(lastOp)) || (oldMap == null)) { + Map newMap = duplicateAndInsertNewMap(oldMap); + newMap.put(key, val); + } else { + oldMap.put(key, val); + } + } + + + + + public void remove(String key) + { + if (key == null) { + return; + } + Map oldMap = (Map)copyOnInheritThreadLocal.get(); + if (oldMap == null) { return; + } + Integer lastOp = getAndSetLastOperation(1); + + if (wasLastOpReadOrNull(lastOp)) { + Map newMap = duplicateAndInsertNewMap(oldMap); + newMap.remove(key); + } else { + oldMap.remove(key); + } + } + + + + + public void clear() + { + lastOperation.set(Integer.valueOf(1)); + copyOnInheritThreadLocal.remove(); + } + + + + + public String get(String key) + { + Map map = getPropertyMap(); + if ((map != null) && (key != null)) { + return (String)map.get(key); + } + return null; + } + + + + + + public Map getPropertyMap() + { + lastOperation.set(Integer.valueOf(2)); + return (Map)copyOnInheritThreadLocal.get(); + } + + + + + public Set getKeys() + { + Map map = getPropertyMap(); + + if (map != null) { + return map.keySet(); + } + return null; + } + + + + + + public Map getCopyOfContextMap() + { + lastOperation.set(Integer.valueOf(2)); + Map hashMap = (Map)copyOnInheritThreadLocal.get(); + if (hashMap == null) { + return null; + } + return new HashMap(hashMap); + } + + + public void setContextMap(Map contextMap) + { + lastOperation.set(Integer.valueOf(1)); + + Map newMap = Collections.synchronizedMap(new HashMap()); + newMap.putAll(contextMap); + + + copyOnInheritThreadLocal.set(newMap); + } +} diff --git a/src/minecraft/ch/qos/logback/classic/util/LoggerNameUtil.java b/src/minecraft/ch/qos/logback/classic/util/LoggerNameUtil.java new file mode 100644 index 0000000..09d73fa --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/util/LoggerNameUtil.java @@ -0,0 +1,65 @@ +package ch.qos.logback.classic.util; + +import java.util.ArrayList; +import java.util.List; + + + + + + + + + + + + + + + + + +public class LoggerNameUtil +{ + public LoggerNameUtil() {} + + public static int getFirstSeparatorIndexOf(String name) + { + return getSeparatorIndexOf(name, 0); + } + + + + + + + + + public static int getSeparatorIndexOf(String name, int fromIndex) + { + int dotIndex = name.indexOf('.', fromIndex); + int dollarIndex = name.indexOf('$', fromIndex); + + if ((dotIndex == -1) && (dollarIndex == -1)) return -1; + if (dotIndex == -1) return dollarIndex; + if (dollarIndex == -1) { return dotIndex; + } + return dotIndex < dollarIndex ? dotIndex : dollarIndex; + } + + public static List computeNameParts(String loggerName) { + List partList = new ArrayList(); + + int fromIndex = 0; + for (;;) { + int index = getSeparatorIndexOf(loggerName, fromIndex); + if (index == -1) { + partList.add(loggerName.substring(fromIndex)); + break; + } + partList.add(loggerName.substring(fromIndex, index)); + fromIndex = index + 1; + } + return partList; + } +} diff --git a/src/minecraft/ch/qos/logback/classic/util/StatusListenerConfigHelper.java b/src/minecraft/ch/qos/logback/classic/util/StatusListenerConfigHelper.java new file mode 100644 index 0000000..c3cbee2 --- /dev/null +++ b/src/minecraft/ch/qos/logback/classic/util/StatusListenerConfigHelper.java @@ -0,0 +1,63 @@ +package ch.qos.logback.classic.util; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.core.spi.ContextAware; +import ch.qos.logback.core.spi.LifeCycle; +import ch.qos.logback.core.status.OnConsoleStatusListener; +import ch.qos.logback.core.status.StatusListener; +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.util.OptionHelper; + + + + + + + + + + +public class StatusListenerConfigHelper +{ + public StatusListenerConfigHelper() {} + + static void installIfAsked(LoggerContext loggerContext) + { + String slClass = OptionHelper.getSystemProperty("logback.statusListenerClass"); + + if (!OptionHelper.isEmpty(slClass)) { + addStatusListener(loggerContext, slClass); + } + } + + private static void addStatusListener(LoggerContext loggerContext, String listenerClass) + { + StatusListener listener = null; + if ("SYSOUT".equalsIgnoreCase(listenerClass)) { + listener = new OnConsoleStatusListener(); + } else { + listener = createListenerPerClassName(loggerContext, listenerClass); + } + initAndAddListener(loggerContext, listener); + } + + private static void initAndAddListener(LoggerContext loggerContext, StatusListener listener) { + if (listener != null) { + if ((listener instanceof ContextAware)) + ((ContextAware)listener).setContext(loggerContext); + if ((listener instanceof LifeCycle)) + ((LifeCycle)listener).start(); + loggerContext.getStatusManager().add(listener); + } + } + + private static StatusListener createListenerPerClassName(LoggerContext loggerContext, String listenerClass) { + try { + return (StatusListener)OptionHelper.instantiateByClassName(listenerClass, StatusListener.class, loggerContext); + } + catch (Exception e) + { + e.printStackTrace(); } + return null; + } +} diff --git a/src/minecraft/ch/qos/logback/core/Appender.java b/src/minecraft/ch/qos/logback/core/Appender.java new file mode 100644 index 0000000..fd9b0e7 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/Appender.java @@ -0,0 +1,16 @@ +package ch.qos.logback.core; + +import ch.qos.logback.core.spi.ContextAware; +import ch.qos.logback.core.spi.FilterAttachable; +import ch.qos.logback.core.spi.LifeCycle; + +public abstract interface Appender + extends LifeCycle, ContextAware, FilterAttachable +{ + public abstract String getName(); + + public abstract void doAppend(E paramE) + throws LogbackException; + + public abstract void setName(String paramString); +} diff --git a/src/minecraft/ch/qos/logback/core/AppenderBase.java b/src/minecraft/ch/qos/logback/core/AppenderBase.java new file mode 100644 index 0000000..82339ef --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/AppenderBase.java @@ -0,0 +1,136 @@ +package ch.qos.logback.core; + +import ch.qos.logback.core.filter.Filter; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.spi.FilterAttachableImpl; +import ch.qos.logback.core.spi.FilterReply; +import ch.qos.logback.core.status.WarnStatus; +import java.util.List; + + + + + + + + + + + + + + + + + + + + + + +public abstract class AppenderBase + extends ContextAwareBase + implements Appender +{ + protected volatile boolean started = false; + + + public AppenderBase() {} + + + private boolean guard = false; + + + + protected String name; + + + private FilterAttachableImpl fai = new FilterAttachableImpl(); + + public String getName() { + return name; } + + + private int statusRepeatCount = 0; + private int exceptionCount = 0; + + + static final int ALLOWED_REPEATS = 5; + + + + public synchronized void doAppend(E eventObject) + { + if (guard) { + return; + } + try + { + guard = true; + + if (!started) { + if (statusRepeatCount++ < 5) { + addStatus(new WarnStatus("Attempted to append to non started appender [" + name + "].", this)); + } + + + } + else + { + if (getFilterChainDecision(eventObject) == FilterReply.DENY) { + return; + } + + + append(eventObject); + } + } catch (Exception e) { + if (exceptionCount++ < 5) { + addError("Appender [" + name + "] failed to append.", e); + } + } finally { + guard = false; + } + } + + + protected abstract void append(E paramE); + + + public void setName(String name) + { + this.name = name; + } + + public void start() { + started = true; + } + + public void stop() { + started = false; + } + + public boolean isStarted() { + return started; + } + + public String toString() { + return getClass().getName() + "[" + name + "]"; + } + + public void addFilter(Filter newFilter) { + fai.addFilter(newFilter); + } + + public void clearAllFilters() { + fai.clearAllFilters(); + } + + public List> getCopyOfAttachedFiltersList() { + return fai.getCopyOfAttachedFiltersList(); + } + + public FilterReply getFilterChainDecision(E event) { + return fai.getFilterChainDecision(event); + } +} diff --git a/src/minecraft/ch/qos/logback/core/AsyncAppenderBase.java b/src/minecraft/ch/qos/logback/core/AsyncAppenderBase.java new file mode 100644 index 0000000..b2d0659 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/AsyncAppenderBase.java @@ -0,0 +1,268 @@ +package ch.qos.logback.core; + +import ch.qos.logback.core.spi.AppenderAttachable; +import ch.qos.logback.core.spi.AppenderAttachableImpl; +import java.util.Iterator; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; + + + + + + + + + + + + + + + + +public class AsyncAppenderBase + extends UnsynchronizedAppenderBase + implements AppenderAttachable +{ + AppenderAttachableImpl aai; + BlockingQueue blockingQueue; + public static final int DEFAULT_QUEUE_SIZE = 256; + int queueSize; + int appenderCount; + static final int UNDEFINED = -1; + int discardingThreshold; + AsyncAppenderBase.Worker worker; + public static final int DEFAULT_MAX_FLUSH_TIME = 1000; + int maxFlushTime; + + public AsyncAppenderBase() + { + aai = new AppenderAttachableImpl(); + + + + + + + queueSize = 256; + + appenderCount = 0; + + + discardingThreshold = -1; + + worker = new Worker(); + + + + + + + + maxFlushTime = 1000; + } + + + + + + + + + + protected boolean isDiscardable(E eventObject) + { + return false; + } + + + + + + + protected void preprocess(E eventObject) {} + + + + + + public void start() + { + if (appenderCount == 0) { + addError("No attached appenders found."); + return; + } + if (queueSize < 1) { + addError("Invalid queue size [" + queueSize + "]"); + return; + } + blockingQueue = new ArrayBlockingQueue(queueSize); + + if (discardingThreshold == -1) + discardingThreshold = (queueSize / 5); + addInfo("Setting discardingThreshold to " + discardingThreshold); + worker.setDaemon(true); + worker.setName("AsyncAppender-Worker-" + getName()); + + super.start(); + worker.start(); + } + + public void stop() + { + if (!isStarted()) { + return; + } + + + super.stop(); + + + + worker.interrupt(); + try { + worker.join(maxFlushTime); + + + if (worker.isAlive()) { + addWarn("Max queue flush timeout (" + maxFlushTime + " ms) exceeded. Approximately " + blockingQueue.size() + " queued events were possibly discarded."); + } + else { + addInfo("Queue flush finished successfully within timeout."); + } + } + catch (InterruptedException e) { + addError("Failed to join worker thread. " + blockingQueue.size() + " queued events may be discarded.", e); + } + } + + + protected void append(E eventObject) + { + if ((isQueueBelowDiscardingThreshold()) && (isDiscardable(eventObject))) { + return; + } + preprocess(eventObject); + put(eventObject); + } + + private boolean isQueueBelowDiscardingThreshold() { + return blockingQueue.remainingCapacity() < discardingThreshold; + } + + private void put(E eventObject) { + try { + blockingQueue.put(eventObject); + } + catch (InterruptedException e) {} + } + + public int getQueueSize() { + return queueSize; + } + + public void setQueueSize(int queueSize) { + this.queueSize = queueSize; + } + + public int getDiscardingThreshold() { + return discardingThreshold; + } + + public void setDiscardingThreshold(int discardingThreshold) { + this.discardingThreshold = discardingThreshold; + } + + public int getMaxFlushTime() { + return maxFlushTime; + } + + public void setMaxFlushTime(int maxFlushTime) { + this.maxFlushTime = maxFlushTime; + } + + + + + + public int getNumberOfElementsInQueue() + { + return blockingQueue.size(); + } + + + + + + + public int getRemainingCapacity() + { + return blockingQueue.remainingCapacity(); + } + + + public void addAppender(Appender newAppender) + { + if (appenderCount == 0) { + appenderCount += 1; + addInfo("Attaching appender named [" + newAppender.getName() + "] to AsyncAppender."); + aai.addAppender(newAppender); + } else { + addWarn("One and only one appender may be attached to AsyncAppender."); + addWarn("Ignoring additional appender named [" + newAppender.getName() + "]"); + } + } + + public Iterator> iteratorForAppenders() { + return aai.iteratorForAppenders(); + } + + public Appender getAppender(String name) { + return aai.getAppender(name); + } + + public boolean isAttached(Appender eAppender) { + return aai.isAttached(eAppender); + } + + public void detachAndStopAllAppenders() { + aai.detachAndStopAllAppenders(); + } + + public boolean detachAppender(Appender eAppender) { + return aai.detachAppender(eAppender); + } + + + public boolean detachAppender(String name) { return aai.detachAppender(name); } + + class Worker extends Thread { + Worker() {} + + public void run() { + AsyncAppenderBase parent = AsyncAppenderBase.this; + AppenderAttachableImpl aai = aai; + for (;;) + { + if (parent.isStarted()) { + try { + E e = blockingQueue.take(); + aai.appendLoopOnAppenders(e); + } + catch (InterruptedException ie) {} + } + } + + addInfo("Worker thread will flush remaining events before exiting. "); + + for (E e : blockingQueue) { + aai.appendLoopOnAppenders(e); + blockingQueue.remove(e); + } + + + aai.detachAndStopAllAppenders(); + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/BasicStatusManager.java b/src/minecraft/ch/qos/logback/core/BasicStatusManager.java new file mode 100644 index 0000000..0070ef5 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/BasicStatusManager.java @@ -0,0 +1,144 @@ +package ch.qos.logback.core; + +import ch.qos.logback.core.helpers.CyclicBuffer; +import ch.qos.logback.core.spi.LogbackLock; +import ch.qos.logback.core.status.OnConsoleStatusListener; +import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.status.StatusListener; +import ch.qos.logback.core.status.StatusManager; +import java.util.ArrayList; +import java.util.List; + + + + + + + + + + + + + + + +public class BasicStatusManager + implements StatusManager +{ + public static final int MAX_HEADER_COUNT = 150; + public static final int TAIL_SIZE = 150; + int count = 0; + + + protected final List statusList = new ArrayList(); + protected final CyclicBuffer tailBuffer = new CyclicBuffer(150); + + protected final LogbackLock statusListLock = new LogbackLock(); + + int level = 0; + + + protected final List statusListenerList = new ArrayList(); + protected final LogbackLock statusListenerListLock = new LogbackLock(); + + + + + + + + public BasicStatusManager() {} + + + + + + + public void add(Status newStatus) + { + fireStatusAddEvent(newStatus); + + count += 1; + if (newStatus.getLevel() > level) { + level = newStatus.getLevel(); + } + + synchronized (statusListLock) { + if (statusList.size() < 150) { + statusList.add(newStatus); + } else { + tailBuffer.add(newStatus); + } + } + } + + public List getCopyOfStatusList() + { + synchronized (statusListLock) { + List tList = new ArrayList(statusList); + tList.addAll(tailBuffer.asList()); + return tList; + } + } + + private void fireStatusAddEvent(Status status) { + synchronized (statusListenerListLock) { + for (StatusListener sl : statusListenerList) { + sl.addStatusEvent(status); + } + } + } + + public void clear() { + synchronized (statusListLock) { + count = 0; + statusList.clear(); + tailBuffer.clear(); + } + } + + public int getLevel() { + return level; + } + + public int getCount() { + return count; + } + + + + + public void add(StatusListener listener) + { + synchronized (statusListenerListLock) { + if ((listener instanceof OnConsoleStatusListener)) { + boolean alreadyPresent = checkForPresence(statusListenerList, listener.getClass()); + if (alreadyPresent) + return; + } + statusListenerList.add(listener); + } + } + + private boolean checkForPresence(List statusListenerList, Class aClass) { + for (StatusListener e : statusListenerList) { + if (e.getClass() == aClass) + return true; + } + return false; + } + + public void remove(StatusListener listener) + { + synchronized (statusListenerListLock) { + statusListenerList.remove(listener); + } + } + + public List getCopyOfStatusListenerList() { + synchronized (statusListenerListLock) { + return new ArrayList(statusListenerList); + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/ConsoleAppender.java b/src/minecraft/ch/qos/logback/core/ConsoleAppender.java new file mode 100644 index 0000000..b2704a3 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/ConsoleAppender.java @@ -0,0 +1,119 @@ +package ch.qos.logback.core; + +import ch.qos.logback.core.joran.spi.ConsoleTarget; +import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.status.WarnStatus; +import ch.qos.logback.core.util.EnvUtil; +import ch.qos.logback.core.util.OptionHelper; +import java.io.OutputStream; +import java.util.Arrays; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class ConsoleAppender + extends OutputStreamAppender +{ + protected ConsoleTarget target = ConsoleTarget.SystemOut; + protected boolean withJansi = false; + + private static final String WindowsAnsiOutputStream_CLASS_NAME = "org.fusesource.jansi.WindowsAnsiOutputStream"; + + + public ConsoleAppender() {} + + public void setTarget(String value) + { + ConsoleTarget t = ConsoleTarget.findByName(value.trim()); + if (t == null) { + targetWarn(value); + } else { + target = t; + } + } + + + + + + + public String getTarget() + { + return target.getName(); + } + + private void targetWarn(String val) { + Status status = new WarnStatus("[" + val + "] should be one of " + Arrays.toString(ConsoleTarget.values()), this); + + status.add(new WarnStatus("Using previously set target, System.out by default.", this)); + + addStatus(status); + } + + public void start() + { + OutputStream targetStream = target.getStream(); + + if ((EnvUtil.isWindows()) && (withJansi)) { + targetStream = getTargetStreamForWindows(targetStream); + } + setOutputStream(targetStream); + super.start(); + } + + private OutputStream getTargetStreamForWindows(OutputStream targetStream) { + try { + addInfo("Enabling JANSI WindowsAnsiOutputStream for the console."); + Object windowsAnsiOutputStream = OptionHelper.instantiateByClassNameAndParameter("org.fusesource.jansi.WindowsAnsiOutputStream", Object.class, context, OutputStream.class, targetStream); + + return (OutputStream)windowsAnsiOutputStream; + } catch (Exception e) { + addWarn("Failed to create WindowsAnsiOutputStream. Falling back on the default stream.", e); + } + return targetStream; + } + + + + public boolean isWithJansi() + { + return withJansi; + } + + + + + + + public void setWithJansi(boolean withJansi) + { + this.withJansi = withJansi; + } +} diff --git a/src/minecraft/ch/qos/logback/core/Context.java b/src/minecraft/ch/qos/logback/core/Context.java new file mode 100644 index 0000000..5929fd4 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/Context.java @@ -0,0 +1,35 @@ +package ch.qos.logback.core; + +import ch.qos.logback.core.spi.LifeCycle; +import ch.qos.logback.core.spi.PropertyContainer; +import ch.qos.logback.core.status.StatusManager; +import java.util.Map; +import java.util.concurrent.ExecutorService; + +public abstract interface Context + extends PropertyContainer +{ + public abstract StatusManager getStatusManager(); + + public abstract Object getObject(String paramString); + + public abstract void putObject(String paramString, Object paramObject); + + public abstract String getProperty(String paramString); + + public abstract void putProperty(String paramString1, String paramString2); + + public abstract Map getCopyOfPropertyMap(); + + public abstract String getName(); + + public abstract void setName(String paramString); + + public abstract long getBirthTime(); + + public abstract Object getConfigurationLock(); + + public abstract ExecutorService getExecutorService(); + + public abstract void register(LifeCycle paramLifeCycle); +} diff --git a/src/minecraft/ch/qos/logback/core/ContextBase.java b/src/minecraft/ch/qos/logback/core/ContextBase.java new file mode 100644 index 0000000..514a2f1 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/ContextBase.java @@ -0,0 +1,220 @@ +package ch.qos.logback.core; + +import ch.qos.logback.core.spi.LifeCycle; +import ch.qos.logback.core.spi.LogbackLock; +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.util.ExecutorServiceUtil; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutorService; + + + + + + + + + + + + + + + + +public class ContextBase + implements Context, LifeCycle +{ + private long birthTime = System.currentTimeMillis(); + + private String name; + private StatusManager sm = new BasicStatusManager(); + + + + Map propertyMap = new HashMap(); + Map objectMap = new HashMap(); + + LogbackLock configurationLock = new LogbackLock(); + private volatile ExecutorService executorService; + private LifeCycleManager lifeCycleManager; + private boolean started; + + public ContextBase() {} + + public StatusManager getStatusManager() { return sm; } + + + + + + + + + + + + + public void setStatusManager(StatusManager statusManager) + { + if (statusManager == null) { + throw new IllegalArgumentException("null StatusManager not allowed"); + } + sm = statusManager; + } + + public Map getCopyOfPropertyMap() { + return new HashMap(propertyMap); + } + + public void putProperty(String key, String val) { + propertyMap.put(key, val); + } + + + + + + + + public String getProperty(String key) + { + if ("CONTEXT_NAME".equals(key)) { + return getName(); + } + return (String)propertyMap.get(key); + } + + public Object getObject(String key) { + return objectMap.get(key); + } + + public void putObject(String key, Object value) { + objectMap.put(key, value); + } + + public void removeObject(String key) { + objectMap.remove(key); + } + + public String getName() + { + return name; + } + + + + public void start() + { + started = true; + } + + + public void stop() + { + stopExecutorService(); + started = false; + } + + public boolean isStarted() { + return started; + } + + + + + public void reset() + { + removeShutdownHook(); + getLifeCycleManager().reset(); + propertyMap.clear(); + objectMap.clear(); + } + + + + + + + public void setName(String name) + throws IllegalStateException + { + if ((name != null) && (name.equals(this.name))) { + return; + } + if ((this.name == null) || ("default".equals(this.name))) + { + this.name = name; + } else { + throw new IllegalStateException("Context has been already given a name"); + } + } + + public long getBirthTime() { + return birthTime; + } + + public Object getConfigurationLock() { + return configurationLock; + } + + public ExecutorService getExecutorService() { + if (executorService == null) { + synchronized (this) { + if (executorService == null) { + executorService = ExecutorServiceUtil.newExecutorService(); + } + } + } + return executorService; + } + + private synchronized void stopExecutorService() { + if (executorService != null) { + ExecutorServiceUtil.shutdown(executorService); + executorService = null; + } + } + + private void removeShutdownHook() { + Thread hook = (Thread)getObject("SHUTDOWN_HOOK"); + if (hook != null) { + removeObject("SHUTDOWN_HOOK"); + try { + Runtime.getRuntime().removeShutdownHook(hook); + } + catch (IllegalStateException e) {} + } + } + + + public void register(LifeCycle component) + { + getLifeCycleManager().register(component); + } + + + + + + + + + + + + + synchronized LifeCycleManager getLifeCycleManager() + { + if (lifeCycleManager == null) { + lifeCycleManager = new LifeCycleManager(); + } + return lifeCycleManager; + } + + public String toString() + { + return name; + } +} diff --git a/src/minecraft/ch/qos/logback/core/CoreConstants.java b/src/minecraft/ch/qos/logback/core/CoreConstants.java new file mode 100644 index 0000000..21cdc43 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/CoreConstants.java @@ -0,0 +1,183 @@ +package ch.qos.logback.core; + +import ch.qos.logback.core.util.EnvUtil; + + + + + + + + + + + + + + + + + + + +public class CoreConstants +{ + public static final int CORE_POOL_SIZE = EnvUtil.isJDK5() ? 1 : 0; + + + + + + public static final int MAX_POOL_SIZE = 32; + + + + + public static final String LINE_SEPARATOR = System.getProperty("line.separator"); + public static final int LINE_SEPARATOR_LEN = LINE_SEPARATOR.length(); + + + + public static final String CODES_URL = "http://logback.qos.ch/codes.html"; + + + + public static final String DEFAULT_CONTEXT_NAME = "default"; + + + + public static final String PATTERN_RULE_REGISTRY = "PATTERN_RULE_REGISTRY"; + + + + public static final String ISO8601_STR = "ISO8601"; + + + + public static final String ISO8601_PATTERN = "yyyy-MM-dd HH:mm:ss,SSS"; + + + + public static final String DAILY_DATE_PATTERN = "yyyy-MM-dd"; + + + + public static final String CLF_DATE_PATTERN = "dd/MMM/yyyy:HH:mm:ss Z"; + + + + public static final String EVALUATOR_MAP = "EVALUATOR_MAP"; + + + + public static final String VALUE_OF = "valueOf"; + + + + public static final String EMPTY_STRING = ""; + + + + public static final String[] EMPTY_STRING_ARRAY = new String[0]; + + + + + public static final Class[] EMPTY_CLASS_ARRAY = new Class[0]; + + public static final String CAUSED_BY = "Caused by: "; + + public static final String SUPPRESSED = "Suppressed: "; + + public static final String WRAPPED_BY = "Wrapped by: "; + + public static final char PERCENT_CHAR = '%'; + + public static final char LEFT_PARENTHESIS_CHAR = '('; + + public static final char RIGHT_PARENTHESIS_CHAR = ')'; + + public static final char ESCAPE_CHAR = '\\'; + + public static final char CURLY_LEFT = '{'; + + public static final char CURLY_RIGHT = '}'; + + public static final char COMMA_CHAR = ','; + + public static final char DOUBLE_QUOTE_CHAR = '"'; + + public static final char SINGLE_QUOTE_CHAR = '\''; + + public static final char COLON_CHAR = ':'; + + public static final char DASH_CHAR = '-'; + + public static final String DEFAULT_VALUE_SEPARATOR = ":-"; + + public static final int TABLE_ROW_LIMIT = 10000; + + public static final int OOS_RESET_FREQUENCY = 70; + public static long REFERENCE_BIPS = 9000L; + + + public static final int MAX_ERROR_COUNT = 4; + + + public static final char DOT = '.'; + + + public static final char TAB = '\t'; + + + public static final char DOLLAR = '$'; + + + public static final String SEE_FNP_NOT_SET = "See also http://logback.qos.ch/codes.html#tbr_fnp_not_set"; + + + public static final String CONFIGURATION_WATCH_LIST = "CONFIGURATION_WATCH_LIST"; + + + public static final String CONFIGURATION_WATCH_LIST_RESET = "CONFIGURATION_WATCH_LIST_RESET"; + + + public static final String SAFE_JORAN_CONFIGURATION = "SAFE_JORAN_CONFIGURATION"; + + + public static final String XML_PARSING = "XML_PARSING"; + + + public static final String SHUTDOWN_HOOK_THREAD = "SHUTDOWN_HOOK"; + + public static final String HOSTNAME_KEY = "HOSTNAME"; + + public static final String CONTEXT_NAME_KEY = "CONTEXT_NAME"; + + public static final int BYTES_PER_INT = 4; + + public static final int MILLIS_IN_ONE_SECOND = 1000; + + public static final int MILLIS_IN_ONE_MINUTE = 60000; + + public static final int MILLIS_IN_ONE_HOUR = 3600000; + + public static final int MILLIS_IN_ONE_DAY = 86400000; + + public static final int MILLIS_IN_ONE_WEEK = 604800000; + + public static final int SECONDS_TO_WAIT_FOR_COMPRESSION_JOBS = 30; + + public static final String CONTEXT_SCOPE_VALUE = "context"; + + public static final String RESET_MSG_PREFIX = "Will reset and reconfigure context "; + + public static final String JNDI_COMP_PREFIX = "java:comp/env"; + + public static final String UNDEFINED_PROPERTY_SUFFIX = "_IS_UNDEFINED"; + + public static final String LEFT_ACCOLADE = new String(new char[] { '{' }); + public static final String RIGHT_ACCOLADE = new String(new char[] { '}' }); + + public CoreConstants() {} +} diff --git a/src/minecraft/ch/qos/logback/core/FileAppender.java b/src/minecraft/ch/qos/logback/core/FileAppender.java new file mode 100644 index 0000000..791415f --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/FileAppender.java @@ -0,0 +1,223 @@ +package ch.qos.logback.core; + +import ch.qos.logback.core.recovery.ResilientFileOutputStream; +import ch.qos.logback.core.util.FileUtil; +import java.io.File; +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.util.concurrent.locks.ReentrantLock; + + + + + + + + + + + + + + + + + + + + + + + + + + +public class FileAppender + extends OutputStreamAppender +{ + protected boolean append = true; + + + + + protected String fileName = null; + + private boolean prudent = false; + + + public FileAppender() {} + + public void setFile(String file) + { + if (file == null) { + fileName = file; + } + else + { + fileName = file.trim(); + } + } + + + + public boolean isAppend() + { + return append; + } + + + + + + + public final String rawFileProperty() + { + return fileName; + } + + + + + + + + public String getFile() + { + return fileName; + } + + + + + + public void start() + { + int errors = 0; + if (getFile() != null) { + addInfo("File property is set to [" + fileName + "]"); + + if ((prudent) && + (!isAppend())) { + setAppend(true); + addWarn("Setting \"Append\" property to true on account of \"Prudent\" mode"); + } + + try + { + openFile(getFile()); + } catch (IOException e) { + errors++; + addError("openFile(" + fileName + "," + append + ") call failed.", e); + } + } else { + errors++; + addError("\"File\" property not set for appender named [" + name + "]."); + } + if (errors == 0) { + super.start(); + } + } + + + + + + + + + + + + + + + + public void openFile(String file_name) + throws IOException + { + lock.lock(); + try { + File file = new File(file_name); + boolean result = FileUtil.createMissingParentDirectories(file); + if (!result) { + addError("Failed to create parent directories for [" + file.getAbsolutePath() + "]"); + } + + + ResilientFileOutputStream resilientFos = new ResilientFileOutputStream(file, append); + + resilientFos.setContext(context); + setOutputStream(resilientFos); + } finally { + lock.unlock(); + } + } + + + + + + public boolean isPrudent() + { + return prudent; + } + + + + + + + public void setPrudent(boolean prudent) + { + this.prudent = prudent; + } + + public void setAppend(boolean append) { + this.append = append; + } + + private void safeWrite(E event) throws IOException { + ResilientFileOutputStream resilientFOS = (ResilientFileOutputStream)getOutputStream(); + FileChannel fileChannel = resilientFOS.getChannel(); + if (fileChannel == null) { + return; + } + + + boolean interrupted = Thread.interrupted(); + + FileLock fileLock = null; + try { + fileLock = fileChannel.lock(); + long position = fileChannel.position(); + long size = fileChannel.size(); + if (size != position) { + fileChannel.position(size); + } + super.writeOut(event); + } + catch (IOException e) { + resilientFOS.postIOFailure(e); + } + finally { + if ((fileLock != null) && (fileLock.isValid())) { + fileLock.release(); + } + + + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + + protected void writeOut(E event) throws IOException + { + if (prudent) { + safeWrite(event); + } else { + super.writeOut(event); + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/Layout.java b/src/minecraft/ch/qos/logback/core/Layout.java new file mode 100644 index 0000000..0b09afe --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/Layout.java @@ -0,0 +1,20 @@ +package ch.qos.logback.core; + +import ch.qos.logback.core.spi.ContextAware; +import ch.qos.logback.core.spi.LifeCycle; + +public abstract interface Layout + extends ContextAware, LifeCycle +{ + public abstract String doLayout(E paramE); + + public abstract String getFileHeader(); + + public abstract String getPresentationHeader(); + + public abstract String getPresentationFooter(); + + public abstract String getFileFooter(); + + public abstract String getContentType(); +} diff --git a/src/minecraft/ch/qos/logback/core/LayoutBase.java b/src/minecraft/ch/qos/logback/core/LayoutBase.java new file mode 100644 index 0000000..00eac4b --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/LayoutBase.java @@ -0,0 +1,82 @@ +package ch.qos.logback.core; + +import ch.qos.logback.core.spi.ContextAwareBase; + + + + + + + + + + +public abstract class LayoutBase + extends ContextAwareBase + implements Layout +{ + protected boolean started; + String fileHeader; + String fileFooter; + String presentationHeader; + String presentationFooter; + + public LayoutBase() {} + + public void setContext(Context context) + { + this.context = context; + } + + public Context getContext() { + return context; + } + + public void start() { + started = true; + } + + public void stop() { + started = false; + } + + public boolean isStarted() { + return started; + } + + public String getFileHeader() { + return fileHeader; + } + + public String getPresentationHeader() { + return presentationHeader; + } + + public String getPresentationFooter() { + return presentationFooter; + } + + public String getFileFooter() { + return fileFooter; + } + + public String getContentType() { + return "text/plain"; + } + + public void setFileHeader(String header) { + fileHeader = header; + } + + public void setFileFooter(String footer) { + fileFooter = footer; + } + + public void setPresentationHeader(String header) { + presentationHeader = header; + } + + public void setPresentationFooter(String footer) { + presentationFooter = footer; + } +} diff --git a/src/minecraft/ch/qos/logback/core/LifeCycleManager.java b/src/minecraft/ch/qos/logback/core/LifeCycleManager.java new file mode 100644 index 0000000..f8736be --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/LifeCycleManager.java @@ -0,0 +1,54 @@ +package ch.qos.logback.core; + +import ch.qos.logback.core.spi.LifeCycle; +import java.util.HashSet; +import java.util.Set; + + + + + + + + + + + + + + + + + + + + + + +public class LifeCycleManager +{ + private final Set components = new HashSet(); + + + public LifeCycleManager() {} + + + public void register(LifeCycle component) + { + components.add(component); + } + + + + + + public void reset() + { + for (LifeCycle component : components) { + if (component.isStarted()) { + component.stop(); + } + } + components.clear(); + } +} diff --git a/src/minecraft/ch/qos/logback/core/LogbackException.java b/src/minecraft/ch/qos/logback/core/LogbackException.java new file mode 100644 index 0000000..85a2bb8 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/LogbackException.java @@ -0,0 +1,28 @@ +package ch.qos.logback.core; + + + + + + + +public class LogbackException + extends RuntimeException +{ + private static final long serialVersionUID = -799956346239073266L; + + + + + + + public LogbackException(String msg) + { + super(msg); + } + + public LogbackException(String msg, Throwable nested) + { + super(msg, nested); + } +} diff --git a/src/minecraft/ch/qos/logback/core/OutputStreamAppender.java b/src/minecraft/ch/qos/logback/core/OutputStreamAppender.java new file mode 100644 index 0000000..cdba84c --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/OutputStreamAppender.java @@ -0,0 +1,238 @@ +package ch.qos.logback.core; + +import ch.qos.logback.core.encoder.Encoder; +import ch.qos.logback.core.encoder.LayoutWrappingEncoder; +import ch.qos.logback.core.spi.DeferredProcessingAware; +import ch.qos.logback.core.status.ErrorStatus; +import java.io.IOException; +import java.io.OutputStream; +import java.util.concurrent.locks.ReentrantLock; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class OutputStreamAppender + extends UnsynchronizedAppenderBase +{ + protected Encoder encoder; + protected final ReentrantLock lock = new ReentrantLock(true); + + + private OutputStream outputStream; + + + + public OutputStreamAppender() {} + + + + public OutputStream getOutputStream() + { + return outputStream; + } + + + + + public void start() + { + int errors = 0; + if (encoder == null) { + addStatus(new ErrorStatus("No encoder set for the appender named \"" + name + "\".", this)); + + errors++; + } + + if (outputStream == null) { + addStatus(new ErrorStatus("No output stream set for the appender named \"" + name + "\".", this)); + + errors++; + } + + if (errors == 0) { + super.start(); + } + } + + public void setLayout(Layout layout) { + addWarn("This appender no longer admits a layout as a sub-component, set an encoder instead."); + addWarn("To ensure compatibility, wrapping your layout in LayoutWrappingEncoder."); + addWarn("See also http://logback.qos.ch/codes.html#layoutInsteadOfEncoder for details"); + LayoutWrappingEncoder lwe = new LayoutWrappingEncoder(); + lwe.setLayout(layout); + lwe.setContext(context); + encoder = lwe; + } + + protected void append(E eventObject) + { + if (!isStarted()) { + return; + } + + subAppend(eventObject); + } + + + + + + + + public void stop() + { + lock.lock(); + try { + closeOutputStream(); + super.stop(); + } finally { + lock.unlock(); + } + } + + + + protected void closeOutputStream() + { + if (outputStream != null) { + try + { + encoderClose(); + outputStream.close(); + outputStream = null; + } catch (IOException e) { + addStatus(new ErrorStatus("Could not close output stream for OutputStreamAppender.", this, e)); + } + } + } + + void encoderInit() + { + if ((encoder != null) && (outputStream != null)) { + try { + encoder.init(outputStream); + } catch (IOException ioe) { + started = false; + addStatus(new ErrorStatus("Failed to initialize encoder for appender named [" + name + "].", this, ioe)); + } + } + } + + + void encoderClose() + { + if ((encoder != null) && (outputStream != null)) { + try { + encoder.close(); + } catch (IOException ioe) { + started = false; + addStatus(new ErrorStatus("Failed to write footer for appender named [" + name + "].", this, ioe)); + } + } + } + + + + + + + + + + + + public void setOutputStream(OutputStream outputStream) + { + lock.lock(); + try + { + closeOutputStream(); + + this.outputStream = outputStream; + if (encoder == null) { + addWarn("Encoder has not been set. Cannot invoke its init method."); + } + else + { + encoderInit(); } + } finally { + lock.unlock(); + } + } + + protected void writeOut(E event) throws IOException { + encoder.doEncode(event); + } + + + + + + + + + protected void subAppend(E event) + { + if (!isStarted()) { + return; + } + try + { + if ((event instanceof DeferredProcessingAware)) { + ((DeferredProcessingAware)event).prepareForDeferredProcessing(); + } + + + + lock.lock(); + try { + writeOut(event); + } finally { + lock.unlock(); + } + } + catch (IOException ioe) + { + started = false; + addStatus(new ErrorStatus("IO failure in appender", this, ioe)); + } + } + + public Encoder getEncoder() { + return encoder; + } + + public void setEncoder(Encoder encoder) { + this.encoder = encoder; + } +} diff --git a/src/minecraft/ch/qos/logback/core/PropertyDefinerBase.java b/src/minecraft/ch/qos/logback/core/PropertyDefinerBase.java new file mode 100644 index 0000000..d236751 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/PropertyDefinerBase.java @@ -0,0 +1,29 @@ +package ch.qos.logback.core; + +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.spi.PropertyDefiner; + + + + + + + + + + + + + + +public abstract class PropertyDefinerBase + extends ContextAwareBase + implements PropertyDefiner +{ + public PropertyDefinerBase() {} + + protected static String booleanAsStr(boolean bool) + { + return bool ? Boolean.TRUE.toString() : Boolean.FALSE.toString(); + } +} diff --git a/src/minecraft/ch/qos/logback/core/UnsynchronizedAppenderBase.java b/src/minecraft/ch/qos/logback/core/UnsynchronizedAppenderBase.java new file mode 100644 index 0000000..c3fc1ed --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/UnsynchronizedAppenderBase.java @@ -0,0 +1,139 @@ +package ch.qos.logback.core; + +import ch.qos.logback.core.filter.Filter; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.spi.FilterAttachableImpl; +import ch.qos.logback.core.spi.FilterReply; +import ch.qos.logback.core.status.WarnStatus; +import java.util.List; + + + + + + + + + + + + + + + + + + + + + +public abstract class UnsynchronizedAppenderBase + extends ContextAwareBase + implements Appender +{ + protected boolean started = false; + + + + + public UnsynchronizedAppenderBase() {} + + + + private ThreadLocal guard = new ThreadLocal(); + + + + protected String name; + + + + private FilterAttachableImpl fai = new FilterAttachableImpl(); + + public String getName() { + return name; } + + + private int statusRepeatCount = 0; + private int exceptionCount = 0; + + + static final int ALLOWED_REPEATS = 3; + + + + public void doAppend(E eventObject) + { + if (Boolean.TRUE.equals(guard.get())) { + return; + } + try + { + guard.set(Boolean.TRUE); + + if (!started) { + if (statusRepeatCount++ < 3) { + addStatus(new WarnStatus("Attempted to append to non started appender [" + name + "].", this)); + } + + + } + else + { + if (getFilterChainDecision(eventObject) == FilterReply.DENY) { + return; + } + + + append(eventObject); + } + } catch (Exception e) { + if (exceptionCount++ < 3) { + addError("Appender [" + name + "] failed to append.", e); + } + } finally { + guard.set(Boolean.FALSE); + } + } + + + protected abstract void append(E paramE); + + + public void setName(String name) + { + this.name = name; + } + + public void start() { + started = true; + } + + public void stop() { + started = false; + } + + public boolean isStarted() { + return started; + } + + public String toString() { + return getClass().getName() + "[" + name + "]"; + } + + public void addFilter(Filter newFilter) { + fai.addFilter(newFilter); + } + + public void clearAllFilters() { + fai.clearAllFilters(); + } + + public List> getCopyOfAttachedFiltersList() { + return fai.getCopyOfAttachedFiltersList(); + } + + public FilterReply getFilterChainDecision(E event) { + return fai.getFilterChainDecision(event); + } +} diff --git a/src/minecraft/ch/qos/logback/core/boolex/EvaluationException.java b/src/minecraft/ch/qos/logback/core/boolex/EvaluationException.java new file mode 100644 index 0000000..a1bef11 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/boolex/EvaluationException.java @@ -0,0 +1,36 @@ +package ch.qos.logback.core.boolex; + + + + + + + + + +public class EvaluationException + extends Exception +{ + private static final long serialVersionUID = 1L; + + + + + + + + + + public EvaluationException(String msg) + { + super(msg); + } + + public EvaluationException(String msg, Throwable cause) { + super(msg, cause); + } + + public EvaluationException(Throwable cause) { + super(cause); + } +} diff --git a/src/minecraft/ch/qos/logback/core/boolex/EventEvaluator.java b/src/minecraft/ch/qos/logback/core/boolex/EventEvaluator.java new file mode 100644 index 0000000..303b8e0 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/boolex/EventEvaluator.java @@ -0,0 +1,15 @@ +package ch.qos.logback.core.boolex; + +import ch.qos.logback.core.spi.ContextAware; +import ch.qos.logback.core.spi.LifeCycle; + +public abstract interface EventEvaluator + extends ContextAware, LifeCycle +{ + public abstract boolean evaluate(E paramE) + throws NullPointerException, EvaluationException; + + public abstract String getName(); + + public abstract void setName(String paramString); +} diff --git a/src/minecraft/ch/qos/logback/core/boolex/EventEvaluatorBase.java b/src/minecraft/ch/qos/logback/core/boolex/EventEvaluatorBase.java new file mode 100644 index 0000000..8348118 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/boolex/EventEvaluatorBase.java @@ -0,0 +1,46 @@ +package ch.qos.logback.core.boolex; + +import ch.qos.logback.core.spi.ContextAwareBase; + + + + + + + + + + +public abstract class EventEvaluatorBase + extends ContextAwareBase + implements EventEvaluator +{ + String name; + boolean started; + + public EventEvaluatorBase() {} + + public String getName() + { + return name; + } + + public void setName(String name) { + if (this.name != null) { + throw new IllegalStateException("name has been already set"); + } + this.name = name; + } + + public boolean isStarted() { + return started; + } + + public void start() { + started = true; + } + + public void stop() { + started = false; + } +} diff --git a/src/minecraft/ch/qos/logback/core/boolex/JaninoEventEvaluatorBase.java b/src/minecraft/ch/qos/logback/core/boolex/JaninoEventEvaluatorBase.java new file mode 100644 index 0000000..64bed62 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/boolex/JaninoEventEvaluatorBase.java @@ -0,0 +1,109 @@ +package ch.qos.logback.core.boolex; + +import java.util.ArrayList; +import java.util.List; +import org.codehaus.janino.ScriptEvaluator; + + + + + + + + + + + + + +public abstract class JaninoEventEvaluatorBase + extends EventEvaluatorBase +{ + static Class EXPRESSION_TYPE; + static Class[] THROWN_EXCEPTIONS; + public static final int ERROR_THRESHOLD = 4; + private String expression; + ScriptEvaluator scriptEvaluator; + + static + { + EXPRESSION_TYPE = Boolean.TYPE; + THROWN_EXCEPTIONS = new Class[1]; + + + + THROWN_EXCEPTIONS[0] = EvaluationException.class; + } + + + + + private int errorCount = 0; + + + + + + + + + + protected List matcherList = new ArrayList(); + + public void start() + { + try { + assert (context != null); + scriptEvaluator = new ScriptEvaluator(getDecoratedExpression(), EXPRESSION_TYPE, getParameterNames(), getParameterTypes(), THROWN_EXCEPTIONS); + + super.start(); + } catch (Exception e) { + addError("Could not start evaluator with expression [" + expression + "]", e); + } + } + + public boolean evaluate(E event) throws EvaluationException + { + if (!isStarted()) { + throw new IllegalStateException("Evaluator [" + name + "] was called in stopped state"); + } + try + { + Boolean result = (Boolean)scriptEvaluator.evaluate(getParameterValues(event)); + return result.booleanValue(); + } catch (Exception ex) { + errorCount += 1; + if (errorCount >= 4) { + stop(); + } + throw new EvaluationException("Evaluator [" + name + "] caused an exception", ex); + } + } + + public String getExpression() + { + return expression; + } + + public void setExpression(String expression) { + this.expression = expression; + } + + public void addMatcher(Matcher matcher) { + matcherList.add(matcher); + } + + public List getMatcherList() { + return matcherList; + } + + public JaninoEventEvaluatorBase() {} + + protected abstract String getDecoratedExpression(); + + protected abstract String[] getParameterNames(); + + protected abstract Class[] getParameterTypes(); + + protected abstract Object[] getParameterValues(E paramE); +} diff --git a/src/minecraft/ch/qos/logback/core/boolex/Matcher.java b/src/minecraft/ch/qos/logback/core/boolex/Matcher.java new file mode 100644 index 0000000..a76e6a4 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/boolex/Matcher.java @@ -0,0 +1,125 @@ +package ch.qos.logback.core.boolex; + +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.spi.LifeCycle; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + + + + + + + + + + + + + +public class Matcher + extends ContextAwareBase + implements LifeCycle +{ + private String regex; + private String name; + private boolean caseSensitive = true; + private boolean canonEq = false; + private boolean unicodeCase = false; + + private boolean start = false; + + public Matcher() {} + + public String getRegex() { return regex; } + + public void setRegex(String regex) + { + this.regex = regex; + } + + public void start() { + if (name == null) { + addError("All Matcher objects must be named"); + return; + } + try { + int code = 0; + if (!caseSensitive) { + code |= 0x2; + } + if (canonEq) { + code |= 0x80; + } + if (unicodeCase) { + code |= 0x40; + } + + + + pattern = Pattern.compile(regex, code); + start = true; + } catch (PatternSyntaxException pse) { + addError("Failed to compile regex [" + regex + "]", pse); + } + } + + public void stop() { + start = false; + } + + public boolean isStarted() { + return start; + } + + + + + + private Pattern pattern; + + + + public boolean matches(String input) + throws EvaluationException + { + if (start) { + java.util.regex.Matcher matcher = pattern.matcher(input); + return matcher.find(); + } + throw new EvaluationException("Matcher [" + regex + "] not started"); + } + + public boolean isCanonEq() + { + return canonEq; + } + + public void setCanonEq(boolean canonEq) { + this.canonEq = canonEq; + } + + public boolean isCaseSensitive() { + return caseSensitive; + } + + public void setCaseSensitive(boolean caseSensitive) { + this.caseSensitive = caseSensitive; + } + + public boolean isUnicodeCase() { + return unicodeCase; + } + + public void setUnicodeCase(boolean unicodeCase) { + this.unicodeCase = unicodeCase; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/src/minecraft/ch/qos/logback/core/db/BindDataSourceToJNDIAction.java b/src/minecraft/ch/qos/logback/core/db/BindDataSourceToJNDIAction.java new file mode 100644 index 0000000..990f9a3 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/db/BindDataSourceToJNDIAction.java @@ -0,0 +1,88 @@ +package ch.qos.logback.core.db; + +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.joran.util.PropertySetter; +import ch.qos.logback.core.util.OptionHelper; +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.sql.DataSource; +import org.xml.sax.Attributes; + + + + + + + + + + + + + + + + + + + + + + + +public class BindDataSourceToJNDIAction + extends Action +{ + static final String DATA_SOURCE_CLASS = "dataSourceClass"; + static final String URL = "url"; + static final String USER = "user"; + static final String PASSWORD = "password"; + + public BindDataSourceToJNDIAction() {} + + public void begin(InterpretationContext ec, String localName, Attributes attributes) + { + String dsClassName = ec.getProperty("dataSourceClass"); + + if (OptionHelper.isEmpty(dsClassName)) { + addWarn("dsClassName is a required parameter"); + ec.addError("dsClassName is a required parameter"); + + return; + } + + String urlStr = ec.getProperty("url"); + String userStr = ec.getProperty("user"); + String passwordStr = ec.getProperty("password"); + try + { + DataSource ds = (DataSource)OptionHelper.instantiateByClassName(dsClassName, DataSource.class, context); + + + PropertySetter setter = new PropertySetter(ds); + setter.setContext(context); + + if (!OptionHelper.isEmpty(urlStr)) { + setter.setProperty("url", urlStr); + } + + if (!OptionHelper.isEmpty(userStr)) { + setter.setProperty("user", userStr); + } + + if (!OptionHelper.isEmpty(passwordStr)) { + setter.setProperty("password", passwordStr); + } + + Context ctx = new InitialContext(); + ctx.rebind("dataSource", ds); + } catch (Exception oops) { + addError("Could not bind datasource. Reported error follows.", oops); + + ec.addError("Could not not bind datasource of type [" + dsClassName + "]."); + } + } + + public void end(InterpretationContext ec, String name) {} +} diff --git a/src/minecraft/ch/qos/logback/core/db/ConnectionSource.java b/src/minecraft/ch/qos/logback/core/db/ConnectionSource.java new file mode 100644 index 0000000..bc573ab --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/db/ConnectionSource.java @@ -0,0 +1,19 @@ +package ch.qos.logback.core.db; + +import ch.qos.logback.core.db.dialect.SQLDialectCode; +import ch.qos.logback.core.spi.LifeCycle; +import java.sql.Connection; +import java.sql.SQLException; + +public abstract interface ConnectionSource + extends LifeCycle +{ + public abstract Connection getConnection() + throws SQLException; + + public abstract SQLDialectCode getSQLDialectCode(); + + public abstract boolean supportsGetGeneratedKeys(); + + public abstract boolean supportsBatchUpdates(); +} diff --git a/src/minecraft/ch/qos/logback/core/db/ConnectionSourceBase.java b/src/minecraft/ch/qos/logback/core/db/ConnectionSourceBase.java new file mode 100644 index 0000000..c355494 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/db/ConnectionSourceBase.java @@ -0,0 +1,129 @@ +package ch.qos.logback.core.db; + +import ch.qos.logback.core.db.dialect.DBUtil; +import ch.qos.logback.core.db.dialect.SQLDialectCode; +import ch.qos.logback.core.spi.ContextAwareBase; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.SQLException; + + + + + + + + + + + + + + + + + + +public abstract class ConnectionSourceBase + extends ContextAwareBase + implements ConnectionSource +{ + private boolean started; + private String user = null; + private String password = null; + + + private SQLDialectCode dialectCode = SQLDialectCode.UNKNOWN_DIALECT; + private boolean supportsGetGeneratedKeys = false; + private boolean supportsBatchUpdates = false; + + + public ConnectionSourceBase() {} + + + public void discoverConnectionProperties() + { + Connection connection = null; + try { + connection = getConnection(); + if (connection == null) { + addWarn("Could not get a connection"); + } + else { + DatabaseMetaData meta = connection.getMetaData(); + DBUtil util = new DBUtil(); + util.setContext(getContext()); + supportsGetGeneratedKeys = util.supportsGetGeneratedKeys(meta); + supportsBatchUpdates = util.supportsBatchUpdates(meta); + dialectCode = DBUtil.discoverSQLDialect(meta); + addInfo("Driver name=" + meta.getDriverName()); + addInfo("Driver version=" + meta.getDriverVersion()); + addInfo("supportsGetGeneratedKeys=" + supportsGetGeneratedKeys); + } + } catch (SQLException se) { + addWarn("Could not discover the dialect to use.", se); + } finally { + DBHelper.closeConnection(connection); + } + } + + + + public final boolean supportsGetGeneratedKeys() + { + return supportsGetGeneratedKeys; + } + + public final SQLDialectCode getSQLDialectCode() { + return dialectCode; + } + + + + public final String getPassword() + { + return password; + } + + + + + public final void setPassword(String password) + { + this.password = password; + } + + + + public final String getUser() + { + return user; + } + + + + + public final void setUser(String username) + { + user = username; + } + + + + public final boolean supportsBatchUpdates() + { + return supportsBatchUpdates; + } + + public boolean isStarted() { + return started; + } + + public void start() { + started = true; + } + + public void stop() { + started = false; + } +} diff --git a/src/minecraft/ch/qos/logback/core/db/DBAppenderBase.java b/src/minecraft/ch/qos/logback/core/db/DBAppenderBase.java new file mode 100644 index 0000000..3411b87 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/db/DBAppenderBase.java @@ -0,0 +1,179 @@ +package ch.qos.logback.core.db; + +import ch.qos.logback.core.UnsynchronizedAppenderBase; +import ch.qos.logback.core.db.dialect.DBUtil; +import ch.qos.logback.core.db.dialect.SQLDialect; +import ch.qos.logback.core.db.dialect.SQLDialectCode; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + + + + + + + + + + + + + + + + + + + +public abstract class DBAppenderBase + extends UnsynchronizedAppenderBase +{ + protected ConnectionSource connectionSource; + protected boolean cnxSupportsGetGeneratedKeys = false; + protected boolean cnxSupportsBatchUpdates = false; + protected SQLDialect sqlDialect; + + public DBAppenderBase() {} + + protected abstract Method getGeneratedKeysMethod(); + + protected abstract String getInsertSQL(); + + public void start() { + if (connectionSource == null) { + throw new IllegalStateException("DBAppender cannot function without a connection source"); + } + + + sqlDialect = DBUtil.getDialectFromCode(connectionSource.getSQLDialectCode()); + + if (getGeneratedKeysMethod() != null) { + cnxSupportsGetGeneratedKeys = connectionSource.supportsGetGeneratedKeys(); + } else { + cnxSupportsGetGeneratedKeys = false; + } + cnxSupportsBatchUpdates = connectionSource.supportsBatchUpdates(); + if ((!cnxSupportsGetGeneratedKeys) && (sqlDialect == null)) { + throw new IllegalStateException("DBAppender cannot function if the JDBC driver does not support getGeneratedKeys method *and* without a specific SQL dialect"); + } + + + + super.start(); + } + + + + public ConnectionSource getConnectionSource() + { + return connectionSource; + } + + + + + public void setConnectionSource(ConnectionSource connectionSource) + { + this.connectionSource = connectionSource; + } + + public void append(E eventObject) + { + Connection connection = null; + PreparedStatement insertStatement = null; + try { + connection = connectionSource.getConnection(); + connection.setAutoCommit(false); + + if (cnxSupportsGetGeneratedKeys) { + String EVENT_ID_COL_NAME = "EVENT_ID"; + + if (connectionSource.getSQLDialectCode() == SQLDialectCode.POSTGRES_DIALECT) { + EVENT_ID_COL_NAME = EVENT_ID_COL_NAME.toLowerCase(); + } + insertStatement = connection.prepareStatement(getInsertSQL(), new String[] { EVENT_ID_COL_NAME }); + } + else { + insertStatement = connection.prepareStatement(getInsertSQL()); + } + + long eventId; + + synchronized (this) { + subAppend(eventObject, connection, insertStatement); + eventId = selectEventId(insertStatement, connection); + } + secondarySubAppend(eventObject, connection, eventId); + + connection.commit(); + } catch (Throwable sqle) { + addError("problem appending event", sqle); + } finally { + DBHelper.closeStatement(insertStatement); + DBHelper.closeConnection(connection); + } + } + + protected abstract void subAppend(E paramE, Connection paramConnection, PreparedStatement paramPreparedStatement) + throws Throwable; + + protected abstract void secondarySubAppend(E paramE, Connection paramConnection, long paramLong) + throws Throwable; + + protected long selectEventId(PreparedStatement insertStatement, Connection connection) throws SQLException, InvocationTargetException + { + ResultSet rs = null; + Statement idStatement = null; + try { + boolean gotGeneratedKeys = false; + if (cnxSupportsGetGeneratedKeys) { + try { + rs = (ResultSet)getGeneratedKeysMethod().invoke(insertStatement, (Object[])null); + + gotGeneratedKeys = true; + } catch (InvocationTargetException ex) { + Throwable target = ex.getTargetException(); + if ((target instanceof SQLException)) { + throw ((SQLException)target); + } + throw ex; + } catch (IllegalAccessException ex) { + addWarn("IllegalAccessException invoking PreparedStatement.getGeneratedKeys", ex); + } + } + + + + if (!gotGeneratedKeys) { + idStatement = connection.createStatement(); + idStatement.setMaxRows(1); + String selectInsertIdStr = sqlDialect.getSelectInsertId(); + rs = idStatement.executeQuery(selectInsertIdStr); + } + + + + rs.next(); + long eventId = rs.getLong(1); + return eventId; + } finally { + if (rs != null) { + try { + rs.close(); + } + catch (SQLException e) {} + } + DBHelper.closeStatement(idStatement); + } + } + + public void stop() + { + super.stop(); + } +} diff --git a/src/minecraft/ch/qos/logback/core/db/DBHelper.java b/src/minecraft/ch/qos/logback/core/db/DBHelper.java new file mode 100644 index 0000000..50fbf6b --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/db/DBHelper.java @@ -0,0 +1,45 @@ +package ch.qos.logback.core.db; + +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; + + + + + + + + + + + + + + + +public class DBHelper +{ + public DBHelper() {} + + public static void closeConnection(Connection connection) + { + if (connection != null) { + try { + connection.close(); + } + catch (SQLException sqle) {} + } + } + + + public static void closeStatement(Statement statement) + { + if (statement != null) { + try { + statement.close(); + } + catch (SQLException sqle) {} + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/db/DataSourceConnectionSource.java b/src/minecraft/ch/qos/logback/core/db/DataSourceConnectionSource.java new file mode 100644 index 0000000..6599b03 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/db/DataSourceConnectionSource.java @@ -0,0 +1,76 @@ +package ch.qos.logback.core.db; + +import ch.qos.logback.core.db.dialect.SQLDialectCode; +import java.sql.Connection; +import java.sql.SQLException; +import javax.sql.DataSource; + + + + + + + + + + + + + + + + + + + + + + + + + +public class DataSourceConnectionSource + extends ConnectionSourceBase +{ + private DataSource dataSource; + + public DataSourceConnectionSource() {} + + public void start() + { + if (dataSource == null) { + addWarn("WARNING: No data source specified"); + } else { + discoverConnectionProperties(); + if ((!supportsGetGeneratedKeys()) && (getSQLDialectCode() == SQLDialectCode.UNKNOWN_DIALECT)) + { + addWarn("Connection does not support GetGeneratedKey method and could not discover the dialect."); + } + } + super.start(); + } + + + public Connection getConnection() + throws SQLException + { + if (dataSource == null) { + addError("WARNING: No data source specified"); + return null; + } + + if (getUser() == null) { + return dataSource.getConnection(); + } + return dataSource.getConnection(getUser(), getPassword()); + } + + public DataSource getDataSource() + { + return dataSource; + } + + public void setDataSource(DataSource dataSource) { + this.dataSource = dataSource; + } +} diff --git a/src/minecraft/ch/qos/logback/core/db/DriverManagerConnectionSource.java b/src/minecraft/ch/qos/logback/core/db/DriverManagerConnectionSource.java new file mode 100644 index 0000000..fba52fd --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/db/DriverManagerConnectionSource.java @@ -0,0 +1,95 @@ +package ch.qos.logback.core.db; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; + + + + + + + + + + + + + + + + + + + + + + +public class DriverManagerConnectionSource + extends ConnectionSourceBase +{ + private String driverClass = null; + private String url = null; + + public DriverManagerConnectionSource() {} + + public void start() { try { if (driverClass != null) { + Class.forName(driverClass); + discoverConnectionProperties(); + } else { + addError("WARNING: No JDBC driver specified for logback DriverManagerConnectionSource."); + } + } catch (ClassNotFoundException cnfe) { + addError("Could not load JDBC driver class: " + driverClass, cnfe); + } + } + + + public Connection getConnection() + throws SQLException + { + if (getUser() == null) { + return DriverManager.getConnection(url); + } + return DriverManager.getConnection(url, getUser(), getPassword()); + } + + + + + + + public String getUrl() + { + return url; + } + + + + + + + public void setUrl(String url) + { + this.url = url; + } + + + + + + public String getDriverClass() + { + return driverClass; + } + + + + + + + public void setDriverClass(String driverClass) + { + this.driverClass = driverClass; + } +} diff --git a/src/minecraft/ch/qos/logback/core/db/JNDIConnectionSource.java b/src/minecraft/ch/qos/logback/core/db/JNDIConnectionSource.java new file mode 100644 index 0000000..46a2065 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/db/JNDIConnectionSource.java @@ -0,0 +1,112 @@ +package ch.qos.logback.core.db; + +import java.sql.Connection; +import java.sql.SQLException; +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.sql.DataSource; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class JNDIConnectionSource + extends ConnectionSourceBase +{ + public JNDIConnectionSource() {} + + private String jndiLocation = null; + private DataSource dataSource = null; + + public void start() { + if (jndiLocation == null) { + addError("No JNDI location specified for JNDIConnectionSource."); + } + discoverConnectionProperties(); + } + + public Connection getConnection() throws SQLException + { + Connection conn = null; + try { + if (dataSource == null) { + dataSource = lookupDataSource(); + } + if (getUser() != null) { + addWarn("Ignoring property [user] with value [" + getUser() + "] for obtaining a connection from a DataSource."); + } + conn = dataSource.getConnection(); + } catch (NamingException ne) { + addError("Error while getting data source", ne); + throw new SQLException("NamingException while looking up DataSource: " + ne.getMessage()); + } + catch (ClassCastException cce) { + addError("ClassCastException while looking up DataSource.", cce); + throw new SQLException("ClassCastException while looking up DataSource: " + cce.getMessage()); + } + + + return conn; + } + + + + + + public String getJndiLocation() + { + return jndiLocation; + } + + + + + + + public void setJndiLocation(String jndiLocation) + { + this.jndiLocation = jndiLocation; + } + + private DataSource lookupDataSource() throws NamingException, SQLException { + addInfo("Looking up [" + jndiLocation + "] in JNDI"); + + Context initialContext = new InitialContext(); + Object obj = initialContext.lookup(jndiLocation); + + + + DataSource ds = (DataSource)obj; + + if (ds == null) { + throw new SQLException("Failed to obtain data source from JNDI location " + jndiLocation); + } + + return ds; + } +} diff --git a/src/minecraft/ch/qos/logback/core/db/dialect/DBUtil.java b/src/minecraft/ch/qos/logback/core/db/dialect/DBUtil.java new file mode 100644 index 0000000..6d46e69 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/db/dialect/DBUtil.java @@ -0,0 +1,140 @@ +package ch.qos.logback.core.db.dialect; + +import ch.qos.logback.core.spi.ContextAwareBase; +import java.lang.reflect.Method; +import java.sql.DatabaseMetaData; +import java.sql.SQLException; + + + + + + + + + + + + + + + +public class DBUtil + extends ContextAwareBase +{ + private static final String POSTGRES_PART = "postgresql"; + private static final String MYSQL_PART = "mysql"; + private static final String ORACLE_PART = "oracle"; + private static final String MSSQL_PART = "microsoft"; + private static final String HSQL_PART = "hsql"; + private static final String H2_PART = "h2"; + private static final String SYBASE_SQLANY_PART = "sql anywhere"; + private static final String SQLITE_PART = "sqlite"; + + public DBUtil() {} + + public static SQLDialectCode discoverSQLDialect(DatabaseMetaData meta) + { + SQLDialectCode dialectCode = SQLDialectCode.UNKNOWN_DIALECT; + + try + { + String dbName = meta.getDatabaseProductName().toLowerCase(); + + if (dbName.indexOf("postgresql") != -1) + return SQLDialectCode.POSTGRES_DIALECT; + if (dbName.indexOf("mysql") != -1) + return SQLDialectCode.MYSQL_DIALECT; + if (dbName.indexOf("oracle") != -1) + return SQLDialectCode.ORACLE_DIALECT; + if (dbName.indexOf("microsoft") != -1) + return SQLDialectCode.MSSQL_DIALECT; + if (dbName.indexOf("hsql") != -1) + return SQLDialectCode.HSQL_DIALECT; + if (dbName.indexOf("h2") != -1) + return SQLDialectCode.H2_DIALECT; + if (dbName.indexOf("sql anywhere") != -1) + return SQLDialectCode.SYBASE_SQLANYWHERE_DIALECT; + if (dbName.indexOf("sqlite") != -1) { + return SQLDialectCode.SQLITE_DIALECT; + } + return SQLDialectCode.UNKNOWN_DIALECT; + } + catch (SQLException sqle) {} + + + + return dialectCode; + } + + public static SQLDialect getDialectFromCode(SQLDialectCode sqlDialectType) { + SQLDialect sqlDialect = null; + + switch (1.$SwitchMap$ch$qos$logback$core$db$dialect$SQLDialectCode[sqlDialectType.ordinal()]) { + case 1: + sqlDialect = new PostgreSQLDialect(); + break; + + case 2: + sqlDialect = new MySQLDialect(); + break; + + case 3: + sqlDialect = new OracleDialect(); + break; + + case 4: + sqlDialect = new MsSQLDialect(); + break; + + case 5: + sqlDialect = new HSQLDBDialect(); + break; + + case 6: + sqlDialect = new H2Dialect(); + break; + + case 7: + sqlDialect = new SybaseSqlAnywhereDialect(); + break; + + case 8: + sqlDialect = new SQLiteDialect(); + } + + return sqlDialect; + } + + + + + + + + public boolean supportsGetGeneratedKeys(DatabaseMetaData meta) + { + try + { + return ((Boolean)DatabaseMetaData.class.getMethod("supportsGetGeneratedKeys", (Class[])null).invoke(meta, (Object[])null)).booleanValue(); + } + catch (Throwable e) + { + addInfo("Could not call supportsGetGeneratedKeys method. This may be recoverable"); } + return false; + } + + + + + + public boolean supportsBatchUpdates(DatabaseMetaData meta) + { + try + { + return meta.supportsBatchUpdates(); + } catch (Throwable e) { + addInfo("Missing DatabaseMetaData.supportsBatchUpdates method."); } + return false; + } +} diff --git a/src/minecraft/ch/qos/logback/core/db/dialect/H2Dialect.java b/src/minecraft/ch/qos/logback/core/db/dialect/H2Dialect.java new file mode 100644 index 0000000..30b4158 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/db/dialect/H2Dialect.java @@ -0,0 +1,27 @@ +package ch.qos.logback.core.db.dialect; + + + + + + +public class H2Dialect + implements SQLDialect +{ + public static final String SELECT_CURRVAL = "CALL IDENTITY()"; + + + + + + public H2Dialect() {} + + + + + + public String getSelectInsertId() + { + return "CALL IDENTITY()"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/db/dialect/HSQLDBDialect.java b/src/minecraft/ch/qos/logback/core/db/dialect/HSQLDBDialect.java new file mode 100644 index 0000000..8719c31 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/db/dialect/HSQLDBDialect.java @@ -0,0 +1,27 @@ +package ch.qos.logback.core.db.dialect; + + + + + + +public class HSQLDBDialect + implements SQLDialect +{ + public static final String SELECT_CURRVAL = "CALL IDENTITY()"; + + + + + + public HSQLDBDialect() {} + + + + + + public String getSelectInsertId() + { + return "CALL IDENTITY()"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/db/dialect/MsSQLDialect.java b/src/minecraft/ch/qos/logback/core/db/dialect/MsSQLDialect.java new file mode 100644 index 0000000..9ce67f2 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/db/dialect/MsSQLDialect.java @@ -0,0 +1,30 @@ +package ch.qos.logback.core.db.dialect; + + + + + + + +public class MsSQLDialect + implements SQLDialect +{ + public static final String SELECT_CURRVAL = "SELECT @@identity id"; + + + + + + + public MsSQLDialect() {} + + + + + + + public String getSelectInsertId() + { + return "SELECT @@identity id"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/db/dialect/MySQLDialect.java b/src/minecraft/ch/qos/logback/core/db/dialect/MySQLDialect.java new file mode 100644 index 0000000..4fefa1f --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/db/dialect/MySQLDialect.java @@ -0,0 +1,28 @@ +package ch.qos.logback.core.db.dialect; + + + + + + +public class MySQLDialect + implements SQLDialect +{ + public static final String SELECT_LAST_INSERT_ID = "SELECT LAST_INSERT_ID()"; + + + + + + + public MySQLDialect() {} + + + + + + public String getSelectInsertId() + { + return "SELECT LAST_INSERT_ID()"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/db/dialect/OracleDialect.java b/src/minecraft/ch/qos/logback/core/db/dialect/OracleDialect.java new file mode 100644 index 0000000..535663f --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/db/dialect/OracleDialect.java @@ -0,0 +1,28 @@ +package ch.qos.logback.core.db.dialect; + + + + + + +public class OracleDialect + implements SQLDialect +{ + public static final String SELECT_CURRVAL = "SELECT logging_event_id_seq.currval from dual"; + + + + + + + public OracleDialect() {} + + + + + + public String getSelectInsertId() + { + return "SELECT logging_event_id_seq.currval from dual"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/db/dialect/PostgreSQLDialect.java b/src/minecraft/ch/qos/logback/core/db/dialect/PostgreSQLDialect.java new file mode 100644 index 0000000..4292fd8 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/db/dialect/PostgreSQLDialect.java @@ -0,0 +1,29 @@ +package ch.qos.logback.core.db.dialect; + + + + + + +public class PostgreSQLDialect + implements SQLDialect +{ + public static final String SELECT_CURRVAL = "SELECT currval('logging_event_id_seq')"; + + + + + + + public PostgreSQLDialect() {} + + + + + + + public String getSelectInsertId() + { + return "SELECT currval('logging_event_id_seq')"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/db/dialect/SQLDialect.java b/src/minecraft/ch/qos/logback/core/db/dialect/SQLDialect.java new file mode 100644 index 0000000..8f33849 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/db/dialect/SQLDialect.java @@ -0,0 +1,6 @@ +package ch.qos.logback.core.db.dialect; + +public abstract interface SQLDialect +{ + public abstract String getSelectInsertId(); +} diff --git a/src/minecraft/ch/qos/logback/core/db/dialect/SQLDialectCode.java b/src/minecraft/ch/qos/logback/core/db/dialect/SQLDialectCode.java new file mode 100644 index 0000000..4d2313d --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/db/dialect/SQLDialectCode.java @@ -0,0 +1,8 @@ +package ch.qos.logback.core.db.dialect; + +public enum SQLDialectCode +{ + UNKNOWN_DIALECT, POSTGRES_DIALECT, MYSQL_DIALECT, ORACLE_DIALECT, MSSQL_DIALECT, HSQL_DIALECT, H2_DIALECT, SYBASE_SQLANYWHERE_DIALECT, SQLITE_DIALECT; + + private SQLDialectCode() {} +} diff --git a/src/minecraft/ch/qos/logback/core/db/dialect/SQLiteDialect.java b/src/minecraft/ch/qos/logback/core/db/dialect/SQLiteDialect.java new file mode 100644 index 0000000..ece095a --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/db/dialect/SQLiteDialect.java @@ -0,0 +1,30 @@ +package ch.qos.logback.core.db.dialect; + + + + + + + +public class SQLiteDialect + implements SQLDialect +{ + public static final String SELECT_CURRVAL = "SELECT last_insert_rowid();"; + + + + + + + public SQLiteDialect() {} + + + + + + + public String getSelectInsertId() + { + return "SELECT last_insert_rowid();"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/db/dialect/SybaseSqlAnywhereDialect.java b/src/minecraft/ch/qos/logback/core/db/dialect/SybaseSqlAnywhereDialect.java new file mode 100644 index 0000000..fe31e75 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/db/dialect/SybaseSqlAnywhereDialect.java @@ -0,0 +1,32 @@ +package ch.qos.logback.core.db.dialect; + + + + + + + +public class SybaseSqlAnywhereDialect + implements SQLDialect +{ + public static final String SELECT_CURRVAL = "SELECT @@identity id"; + + + + + + + + public SybaseSqlAnywhereDialect() {} + + + + + + + + public String getSelectInsertId() + { + return "SELECT @@identity id"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/encoder/ByteArrayUtil.java b/src/minecraft/ch/qos/logback/core/encoder/ByteArrayUtil.java new file mode 100644 index 0000000..f68ccdb --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/encoder/ByteArrayUtil.java @@ -0,0 +1,69 @@ +package ch.qos.logback.core.encoder; + +import java.io.ByteArrayOutputStream; + + + + + + + + + + + + +public class ByteArrayUtil +{ + public ByteArrayUtil() {} + + static void writeInt(byte[] byteArray, int offset, int i) + { + for (int j = 0; j < 4; j++) { + int shift = 24 - j * 8; + byteArray[(offset + j)] = ((byte)(i >>> shift)); + } + } + + static void writeInt(ByteArrayOutputStream baos, int i) { + for (int j = 0; j < 4; j++) { + int shift = 24 - j * 8; + baos.write((byte)(i >>> shift)); + } + } + + static int readInt(byte[] byteArray, int offset) + { + int i = 0; + for (int j = 0; j < 4; j++) { + int shift = 24 - j * 8; + i += ((byteArray[(offset + j)] & 0xFF) << shift); + } + return i; + } + + public static String toHexString(byte[] ba) { + StringBuilder sbuf = new StringBuilder(); + for (byte b : ba) { + String s = Integer.toHexString(b & 0xFF); + if (s.length() == 1) { + sbuf.append('0'); + } + sbuf.append(s); + } + return sbuf.toString(); + } + + public static byte[] hexStringToByteArray(String s) { + int len = s.length(); + byte[] ba = new byte[len / 2]; + + for (int i = 0; i < ba.length; i++) { + int j = i * 2; + int t = Integer.parseInt(s.substring(j, j + 2), 16); + byte b = (byte)(t & 0xFF); + ba[i] = b; + } + return ba; + } +} diff --git a/src/minecraft/ch/qos/logback/core/encoder/EchoEncoder.java b/src/minecraft/ch/qos/logback/core/encoder/EchoEncoder.java new file mode 100644 index 0000000..7862cc1 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/encoder/EchoEncoder.java @@ -0,0 +1,47 @@ +package ch.qos.logback.core.encoder; + +import ch.qos.logback.core.CoreConstants; +import java.io.IOException; +import java.io.OutputStream; + + + + + + + + + + +public class EchoEncoder + extends EncoderBase +{ + String fileHeader; + String fileFooter; + + public EchoEncoder() {} + + public void doEncode(E event) + throws IOException + { + String val = event + CoreConstants.LINE_SEPARATOR; + outputStream.write(val.getBytes()); + + outputStream.flush(); + } + + public void close() throws IOException { + if (fileFooter == null) { + return; + } + outputStream.write(fileFooter.getBytes()); + } + + public void init(OutputStream os) throws IOException { + super.init(os); + if (fileHeader == null) { + return; + } + outputStream.write(fileHeader.getBytes()); + } +} diff --git a/src/minecraft/ch/qos/logback/core/encoder/Encoder.java b/src/minecraft/ch/qos/logback/core/encoder/Encoder.java new file mode 100644 index 0000000..3244632 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/encoder/Encoder.java @@ -0,0 +1,19 @@ +package ch.qos.logback.core.encoder; + +import ch.qos.logback.core.spi.ContextAware; +import ch.qos.logback.core.spi.LifeCycle; +import java.io.IOException; +import java.io.OutputStream; + +public abstract interface Encoder + extends ContextAware, LifeCycle +{ + public abstract void init(OutputStream paramOutputStream) + throws IOException; + + public abstract void doEncode(E paramE) + throws IOException; + + public abstract void close() + throws IOException; +} diff --git a/src/minecraft/ch/qos/logback/core/encoder/EncoderBase.java b/src/minecraft/ch/qos/logback/core/encoder/EncoderBase.java new file mode 100644 index 0000000..4e5b15f --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/encoder/EncoderBase.java @@ -0,0 +1,42 @@ +package ch.qos.logback.core.encoder; + +import ch.qos.logback.core.spi.ContextAwareBase; +import java.io.IOException; +import java.io.OutputStream; + + + + + + + + + + +public abstract class EncoderBase + extends ContextAwareBase + implements Encoder +{ + protected boolean started; + protected OutputStream outputStream; + + public EncoderBase() {} + + public void init(OutputStream os) + throws IOException + { + outputStream = os; + } + + public boolean isStarted() { + return started; + } + + public void start() { + started = true; + } + + public void stop() { + started = false; + } +} diff --git a/src/minecraft/ch/qos/logback/core/encoder/EventObjectInputStream.java b/src/minecraft/ch/qos/logback/core/encoder/EventObjectInputStream.java new file mode 100644 index 0000000..d217684 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/encoder/EventObjectInputStream.java @@ -0,0 +1,158 @@ +package ch.qos.logback.core.encoder; + +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.util.ArrayList; +import java.util.List; + + + + + + + + + + + + + + + + + + + + + + + + +public class EventObjectInputStream + extends InputStream +{ + NonClosableInputStream ncis; + List buffer = new ArrayList(); + + int index = 0; + + EventObjectInputStream(InputStream is) throws IOException { + ncis = new NonClosableInputStream(is); + } + + public int read() throws IOException + { + throw new UnsupportedOperationException("Only the readEvent method is supported."); + } + + + + public int available() + throws IOException + { + return ncis.available(); + } + + public E readEvent() throws IOException + { + E event = getFromBuffer(); + if (event != null) { + return event; + } + + internalReset(); + int count = readHeader(); + if (count == -1) { + return null; + } + readPayload(count); + readFooter(count); + return getFromBuffer(); + } + + private void internalReset() { + index = 0; + buffer.clear(); + } + + E getFromBuffer() { + if (index >= buffer.size()) { + return null; + } + return buffer.get(index++); + } + + int readHeader() throws IOException { + byte[] headerBA = new byte[16]; + + int bytesRead = ncis.read(headerBA); + if (bytesRead == -1) { + return -1; + } + + + + + int offset = 0; + int startPebble = ByteArrayUtil.readInt(headerBA, offset); + if (startPebble != 1853421169) { + throw new IllegalStateException("Does not look like data created by ObjectStreamEncoder"); + } + + offset += 4; + int count = ByteArrayUtil.readInt(headerBA, offset); + offset += 4; + int endPointer = ByteArrayUtil.readInt(headerBA, offset); + offset += 4; + int checksum = ByteArrayUtil.readInt(headerBA, offset); + if (checksum != (0x6E78F671 ^ count)) { + throw new IllegalStateException("Invalid checksum"); + } + return count; + } + + E readEvents(ObjectInputStream ois) throws IOException + { + E e = null; + try { + e = ois.readObject(); + buffer.add(e); + } + catch (ClassNotFoundException e1) { + e1.printStackTrace(); + } + return e; + } + + void readFooter(int count) throws IOException { + byte[] headerBA = new byte[8]; + ncis.read(headerBA); + + int offset = 0; + int stopPebble = ByteArrayUtil.readInt(headerBA, offset); + if (stopPebble != 640373619) { + throw new IllegalStateException("Looks like a corrupt stream"); + } + + offset += 4; + int checksum = ByteArrayUtil.readInt(headerBA, offset); + if (checksum != (0x262B5373 ^ count)) { + throw new IllegalStateException("Invalid checksum"); + } + } + + void readPayload(int count) throws IOException { + List eventList = new ArrayList(count); + ObjectInputStream ois = new ObjectInputStream(ncis); + for (int i = 0; i < count; i++) { + E e = readEvents(ois); + eventList.add(e); + } + ois.close(); + } + + public void close() throws IOException { + ncis.realClose(); + } +} diff --git a/src/minecraft/ch/qos/logback/core/encoder/LayoutWrappingEncoder.java b/src/minecraft/ch/qos/logback/core/encoder/LayoutWrappingEncoder.java new file mode 100644 index 0000000..1dee82c --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/encoder/LayoutWrappingEncoder.java @@ -0,0 +1,163 @@ +package ch.qos.logback.core.encoder; + +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.Layout; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; + + + + + + + + + + + + + + + + + + + + + + + +public class LayoutWrappingEncoder + extends EncoderBase +{ + protected Layout layout; + private Charset charset; + private boolean immediateFlush = true; + + + + + public LayoutWrappingEncoder() {} + + + + public void setImmediateFlush(boolean immediateFlush) + { + this.immediateFlush = immediateFlush; + } + + public boolean isImmediateFlush() + { + return immediateFlush; + } + + public Layout getLayout() + { + return layout; + } + + public void setLayout(Layout layout) { + this.layout = layout; + } + + public Charset getCharset() { + return charset; + } + + + + + + + + + + + public void setCharset(Charset charset) + { + this.charset = charset; + } + + public void init(OutputStream os) throws IOException { + super.init(os); + writeHeader(); + } + + void writeHeader() throws IOException { + if ((layout != null) && (outputStream != null)) { + StringBuilder sb = new StringBuilder(); + appendIfNotNull(sb, layout.getFileHeader()); + appendIfNotNull(sb, layout.getPresentationHeader()); + if (sb.length() > 0) { + sb.append(CoreConstants.LINE_SEPARATOR); + + + + outputStream.write(convertToBytes(sb.toString())); + outputStream.flush(); + } + } + } + + public void close() throws IOException { + writeFooter(); + } + + void writeFooter() throws IOException { + if ((layout != null) && (outputStream != null)) { + StringBuilder sb = new StringBuilder(); + appendIfNotNull(sb, layout.getPresentationFooter()); + appendIfNotNull(sb, layout.getFileFooter()); + if (sb.length() > 0) { + outputStream.write(convertToBytes(sb.toString())); + outputStream.flush(); + } + } + } + + private byte[] convertToBytes(String s) { + if (charset == null) { + return s.getBytes(); + } + try { + return s.getBytes(charset.name()); + } catch (UnsupportedEncodingException e) { + throw new IllegalStateException("An existing charset cannot possibly be unsupported."); + } + } + + public void doEncode(E event) + throws IOException + { + String txt = layout.doLayout(event); + outputStream.write(convertToBytes(txt)); + if (immediateFlush) + outputStream.flush(); + } + + public boolean isStarted() { + return false; + } + + public void start() { + started = true; + } + + public void stop() { + started = false; + if (outputStream != null) { + try { + outputStream.flush(); + } + catch (IOException e) {} + } + } + + private void appendIfNotNull(StringBuilder sb, String s) { + if (s != null) { + sb.append(s); + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/encoder/NonClosableInputStream.java b/src/minecraft/ch/qos/logback/core/encoder/NonClosableInputStream.java new file mode 100644 index 0000000..5d620f2 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/encoder/NonClosableInputStream.java @@ -0,0 +1,37 @@ +package ch.qos.logback.core.encoder; + +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; + + + + + + + + + + + + +public class NonClosableInputStream + extends FilterInputStream +{ + NonClosableInputStream(InputStream is) + { + super(is); + } + + + + public void close() {} + + + + public void realClose() + throws IOException + { + super.close(); + } +} diff --git a/src/minecraft/ch/qos/logback/core/encoder/ObjectStreamEncoder.java b/src/minecraft/ch/qos/logback/core/encoder/ObjectStreamEncoder.java new file mode 100644 index 0000000..e6313cf --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/encoder/ObjectStreamEncoder.java @@ -0,0 +1,94 @@ +package ch.qos.logback.core.encoder; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + + + + + + + + + + + + + + + + + + + + +public class ObjectStreamEncoder + extends EncoderBase +{ + public static final int START_PEBBLE = 1853421169; + public static final int STOP_PEBBLE = 640373619; + + public ObjectStreamEncoder() {} + + private int MAX_BUFFER_SIZE = 100; + + List bufferList = new ArrayList(MAX_BUFFER_SIZE); + + public void doEncode(E event) throws IOException { + bufferList.add(event); + if (bufferList.size() == MAX_BUFFER_SIZE) { + writeBuffer(); + } + } + + void writeHeader(ByteArrayOutputStream baos, int bufferSize) { + ByteArrayUtil.writeInt(baos, 1853421169); + ByteArrayUtil.writeInt(baos, bufferSize); + ByteArrayUtil.writeInt(baos, 0); + ByteArrayUtil.writeInt(baos, 0x6E78F671 ^ bufferSize); + } + + void writeFooter(ByteArrayOutputStream baos, int bufferSize) { + ByteArrayUtil.writeInt(baos, 640373619); + ByteArrayUtil.writeInt(baos, 0x262B5373 ^ bufferSize); + } + + void writeBuffer() throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(10000); + + int size = bufferList.size(); + writeHeader(baos, size); + ObjectOutputStream oos = new ObjectOutputStream(baos); + for (E e : bufferList) { + oos.writeObject(e); + } + bufferList.clear(); + oos.flush(); + + writeFooter(baos, size); + + byte[] byteArray = baos.toByteArray(); + oos.close(); + writeEndPosition(byteArray); + outputStream.write(byteArray); + } + + void writeEndPosition(byte[] byteArray) + { + int offset = 8; + ByteArrayUtil.writeInt(byteArray, offset, byteArray.length - offset); + } + + public void init(OutputStream os) throws IOException + { + super.init(os); + bufferList.clear(); + } + + public void close() throws IOException { + writeBuffer(); + } +} diff --git a/src/minecraft/ch/qos/logback/core/filter/AbstractMatcherFilter.java b/src/minecraft/ch/qos/logback/core/filter/AbstractMatcherFilter.java new file mode 100644 index 0000000..8b90ff0 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/filter/AbstractMatcherFilter.java @@ -0,0 +1,38 @@ +package ch.qos.logback.core.filter; + +import ch.qos.logback.core.spi.FilterReply; + + + + + + + + + + + +public abstract class AbstractMatcherFilter + extends Filter +{ + public AbstractMatcherFilter() {} + + protected FilterReply onMatch = FilterReply.NEUTRAL; + protected FilterReply onMismatch = FilterReply.NEUTRAL; + + public final void setOnMatch(FilterReply reply) { + onMatch = reply; + } + + public final void setOnMismatch(FilterReply reply) { + onMismatch = reply; + } + + public final FilterReply getOnMatch() { + return onMatch; + } + + public final FilterReply getOnMismatch() { + return onMismatch; + } +} diff --git a/src/minecraft/ch/qos/logback/core/filter/EvaluatorFilter.java b/src/minecraft/ch/qos/logback/core/filter/EvaluatorFilter.java new file mode 100644 index 0000000..9116b0c --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/filter/EvaluatorFilter.java @@ -0,0 +1,74 @@ +package ch.qos.logback.core.filter; + +import ch.qos.logback.core.boolex.EvaluationException; +import ch.qos.logback.core.boolex.EventEvaluator; +import ch.qos.logback.core.spi.FilterReply; + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class EvaluatorFilter + extends AbstractMatcherFilter +{ + EventEvaluator evaluator; + + public EvaluatorFilter() {} + + public void start() + { + if (evaluator != null) { + super.start(); + } else { + addError("No evaluator set for filter " + getName()); + } + } + + public EventEvaluator getEvaluator() { + return evaluator; + } + + public void setEvaluator(EventEvaluator evaluator) { + this.evaluator = evaluator; + } + + + public FilterReply decide(E event) + { + if ((!isStarted()) || (!evaluator.isStarted())) { + return FilterReply.NEUTRAL; + } + try { + if (evaluator.evaluate(event)) { + return onMatch; + } + return onMismatch; + } + catch (EvaluationException e) { + addError("Evaluator " + evaluator.getName() + " threw an exception", e); } + return FilterReply.NEUTRAL; + } +} diff --git a/src/minecraft/ch/qos/logback/core/filter/Filter.java b/src/minecraft/ch/qos/logback/core/filter/Filter.java new file mode 100644 index 0000000..bbdaa24 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/filter/Filter.java @@ -0,0 +1,68 @@ +package ch.qos.logback.core.filter; + +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.spi.FilterReply; +import ch.qos.logback.core.spi.LifeCycle; + + + + + + + + + + + + + + + + + + + + + +public abstract class Filter + extends ContextAwareBase + implements LifeCycle +{ + private String name; + + public Filter() {} + + boolean start = false; + + public void start() { + start = true; + } + + public boolean isStarted() { + return start; + } + + public void stop() { + start = false; + } + + + + + + + public abstract FilterReply decide(E paramE); + + + + + + public String getName() + { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/src/minecraft/ch/qos/logback/core/helpers/CyclicBuffer.java b/src/minecraft/ch/qos/logback/core/helpers/CyclicBuffer.java new file mode 100644 index 0000000..a08c023 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/helpers/CyclicBuffer.java @@ -0,0 +1,175 @@ +package ch.qos.logback.core.helpers; + +import java.util.ArrayList; +import java.util.List; + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class CyclicBuffer +{ + E[] ea; + int first; + int last; + int numElems; + int maxSize; + + public CyclicBuffer(int maxSize) + throws IllegalArgumentException + { + if (maxSize < 1) { + throw new IllegalArgumentException("The maxSize argument (" + maxSize + ") is not a positive integer."); + } + + init(maxSize); + } + + public CyclicBuffer(CyclicBuffer other) { + maxSize = maxSize; + ea = ((Object[])new Object[maxSize]); + System.arraycopy(ea, 0, ea, 0, maxSize); + last = last; + first = first; + numElems = numElems; + } + + private void init(int maxSize) + { + this.maxSize = maxSize; + ea = ((Object[])new Object[maxSize]); + first = 0; + last = 0; + numElems = 0; + } + + + + public void clear() + { + init(maxSize); + } + + + + + public void add(E event) + { + ea[last] = event; + if (++last == maxSize) { + last = 0; + } + if (numElems < maxSize) { + numElems += 1; + } else if (++first == maxSize) { + first = 0; + } + } + + + + + public E get(int i) + { + if ((i < 0) || (i >= numElems)) { + return null; + } + return ea[((first + i) % maxSize)]; + } + + public int getMaxSize() { + return maxSize; + } + + + + + public E get() + { + E r = null; + if (numElems > 0) { + numElems -= 1; + r = ea[first]; + ea[first] = null; + if (++first == maxSize) + first = 0; + } + return r; + } + + public List asList() { + List tList = new ArrayList(); + for (int i = 0; i < length(); i++) { + tList.add(get(i)); + } + return tList; + } + + + + + public int length() + { + return numElems; + } + + + + + + + + public void resize(int newSize) + { + if (newSize < 0) { + throw new IllegalArgumentException("Negative array size [" + newSize + "] not allowed."); + } + + if (newSize == numElems) { + return; + } + + E[] temp = (Object[])new Object[newSize]; + + int loopLen = newSize < numElems ? newSize : numElems; + + for (int i = 0; i < loopLen; i++) { + temp[i] = ea[first]; + ea[first] = null; + if (++first == numElems) + first = 0; + } + ea = temp; + first = 0; + numElems = loopLen; + maxSize = newSize; + if (loopLen == newSize) { + last = 0; + } else { + last = loopLen; + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/helpers/NOPAppender.java b/src/minecraft/ch/qos/logback/core/helpers/NOPAppender.java new file mode 100644 index 0000000..22f4cd7 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/helpers/NOPAppender.java @@ -0,0 +1,11 @@ +package ch.qos.logback.core.helpers; + +import ch.qos.logback.core.AppenderBase; + +public final class NOPAppender + extends AppenderBase +{ + public NOPAppender() {} + + protected void append(E eventObject) {} +} diff --git a/src/minecraft/ch/qos/logback/core/helpers/ThrowableToStringArray.java b/src/minecraft/ch/qos/logback/core/helpers/ThrowableToStringArray.java new file mode 100644 index 0000000..982b49f --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/helpers/ThrowableToStringArray.java @@ -0,0 +1,85 @@ +package ch.qos.logback.core.helpers; + +import java.util.LinkedList; +import java.util.List; + + + + + + + + + + + + + +public class ThrowableToStringArray +{ + public ThrowableToStringArray() {} + + public static String[] convert(Throwable t) + { + List strList = new LinkedList(); + extract(strList, t, null); + return (String[])strList.toArray(new String[0]); + } + + + + private static void extract(List strList, Throwable t, StackTraceElement[] parentSTE) + { + StackTraceElement[] ste = t.getStackTrace(); + int numberOfcommonFrames = findNumberOfCommonFrames(ste, parentSTE); + + strList.add(formatFirstLine(t, parentSTE)); + for (int i = 0; i < ste.length - numberOfcommonFrames; i++) { + strList.add("\tat " + ste[i].toString()); + } + + if (numberOfcommonFrames != 0) { + strList.add("\t... " + numberOfcommonFrames + " common frames omitted"); + } + + Throwable cause = t.getCause(); + if (cause != null) { + extract(strList, cause, ste); + } + } + + private static String formatFirstLine(Throwable t, StackTraceElement[] parentSTE) + { + String prefix = ""; + if (parentSTE != null) { + prefix = "Caused by: "; + } + + String result = prefix + t.getClass().getName(); + if (t.getMessage() != null) { + result = result + ": " + t.getMessage(); + } + return result; + } + + private static int findNumberOfCommonFrames(StackTraceElement[] ste, StackTraceElement[] parentSTE) + { + if (parentSTE == null) { + return 0; + } + + int steIndex = ste.length - 1; + int parentIndex = parentSTE.length - 1; + int count = 0; + while ((steIndex >= 0) && (parentIndex >= 0) && + (ste[steIndex].equals(parentSTE[parentIndex]))) { + count++; + + + + steIndex--; + parentIndex--; + } + return count; + } +} diff --git a/src/minecraft/ch/qos/logback/core/helpers/Transform.java b/src/minecraft/ch/qos/logback/core/helpers/Transform.java new file mode 100644 index 0000000..5c20dcd --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/helpers/Transform.java @@ -0,0 +1,135 @@ +package ch.qos.logback.core.helpers; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + + + + + + + + + + + + + + + + + + +public class Transform +{ + private static final String CDATA_START = ""; + private static final String CDATA_PSEUDO_END = "]]>"; + private static final String CDATA_EMBEDED_END = "]]>]]>".length(); + private static final Pattern UNSAFE_XML_CHARS = Pattern.compile("[\000-\b\013\f\016-\037<>&'\"]"); + + + + + public Transform() {} + + + + + public static String escapeTags(String input) + { + if ((input == null) || (input.length() == 0) || (!UNSAFE_XML_CHARS.matcher(input).find())) { + return input; + } + StringBuffer buf = new StringBuffer(input); + return escapeTags(buf); + } + + + + + + + + + public static String escapeTags(StringBuffer buf) + { + for (int i = 0; i < buf.length(); i++) { + char ch = buf.charAt(i); + switch (ch) + { + case '\t': + case '\n': + case '\r': + break; + case '&': + buf.replace(i, i + 1, "&"); + break; + case '<': + buf.replace(i, i + 1, "<"); + break; + case '>': + buf.replace(i, i + 1, ">"); + break; + case '"': + buf.replace(i, i + 1, """); + break; + case '\'': + buf.replace(i, i + 1, "'"); + break; + default: + if (ch < ' ') + { + + buf.replace(i, i + 1, "�"); + } + break; + } + } + return buf.toString(); + } + + + + + + + + + + + + + public static void appendEscapingCDATA(StringBuilder output, String str) + { + if (str == null) { + return; + } + + int end = str.indexOf("]]>"); + + if (end < 0) { + output.append(str); + + return; + } + + int start = 0; + + while (end > -1) { + output.append(str.substring(start, end)); + output.append("]]>]]>", start); + } else { + return; + } + } + + output.append(str.substring(start)); + } +} diff --git a/src/minecraft/ch/qos/logback/core/hook/DelayingShutdownHook.java b/src/minecraft/ch/qos/logback/core/hook/DelayingShutdownHook.java new file mode 100644 index 0000000..687d84f --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/hook/DelayingShutdownHook.java @@ -0,0 +1,60 @@ +package ch.qos.logback.core.hook; + +import ch.qos.logback.core.util.Duration; + + + + + + + + + + + + + + + + + + + + + + + +public class DelayingShutdownHook + extends ShutdownHookBase +{ + public static final Duration DEFAULT_DELAY = Duration.buildByMilliseconds(0.0D); + + + + + private Duration delay = DEFAULT_DELAY; + + public DelayingShutdownHook() {} + + public Duration getDelay() + { + return delay; + } + + + + + + public void setDelay(Duration delay) + { + this.delay = delay; + } + + public void run() { + try { + Thread.sleep(delay.getMilliseconds()); + } + catch (InterruptedException e) {} + super.stop(); + } +} diff --git a/src/minecraft/ch/qos/logback/core/hook/ShutdownHook.java b/src/minecraft/ch/qos/logback/core/hook/ShutdownHook.java new file mode 100644 index 0000000..04478be --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/hook/ShutdownHook.java @@ -0,0 +1,7 @@ +package ch.qos.logback.core.hook; + +import ch.qos.logback.core.spi.ContextAware; + +public abstract interface ShutdownHook + extends Runnable, ContextAware +{} diff --git a/src/minecraft/ch/qos/logback/core/hook/ShutdownHookBase.java b/src/minecraft/ch/qos/logback/core/hook/ShutdownHookBase.java new file mode 100644 index 0000000..a37b6c4 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/hook/ShutdownHookBase.java @@ -0,0 +1,42 @@ +package ch.qos.logback.core.hook; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.ContextBase; +import ch.qos.logback.core.spi.ContextAwareBase; + + + + + + + + + + + + + + + + + + + + +public abstract class ShutdownHookBase + extends ContextAwareBase + implements ShutdownHook +{ + public ShutdownHookBase() {} + + protected void stop() + { + addInfo("Logback context being closed via shutdown hook"); + + Context hookContext = getContext(); + if ((hookContext instanceof ContextBase)) { + ContextBase context = (ContextBase)hookContext; + context.stop(); + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/html/CssBuilder.java b/src/minecraft/ch/qos/logback/core/html/CssBuilder.java new file mode 100644 index 0000000..5f876cf --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/html/CssBuilder.java @@ -0,0 +1,6 @@ +package ch.qos.logback.core.html; + +public abstract interface CssBuilder +{ + public abstract void addCss(StringBuilder paramStringBuilder); +} diff --git a/src/minecraft/ch/qos/logback/core/html/HTMLLayoutBase.java b/src/minecraft/ch/qos/logback/core/html/HTMLLayoutBase.java new file mode 100644 index 0000000..c6115fc --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/html/HTMLLayoutBase.java @@ -0,0 +1,260 @@ +package ch.qos.logback.core.html; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.LayoutBase; +import ch.qos.logback.core.pattern.Converter; +import ch.qos.logback.core.pattern.ConverterUtil; +import ch.qos.logback.core.pattern.parser.Node; +import ch.qos.logback.core.pattern.parser.Parser; +import ch.qos.logback.core.spi.ScanException; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + + + + + + + + + + + + + + + + + + + + + + + +public abstract class HTMLLayoutBase + extends LayoutBase +{ + protected String pattern; + protected Converter head; + protected String title = "Logback Log Messages"; + + + + protected CssBuilder cssBuilder; + + + protected long counter = 0L; + + + public HTMLLayoutBase() {} + + + public void setPattern(String conversionPattern) + { + pattern = conversionPattern; + } + + + + public String getPattern() + { + return pattern; + } + + public CssBuilder getCssBuilder() { + return cssBuilder; + } + + public void setCssBuilder(CssBuilder cssBuilder) { + this.cssBuilder = cssBuilder; + } + + + + + public void start() + { + int errorCount = 0; + try + { + Parser p = new Parser(pattern); + p.setContext(getContext()); + Node t = p.parse(); + head = p.compile(t, getEffectiveConverterMap()); + ConverterUtil.startConverters(head); + } catch (ScanException ex) { + addError("Incorrect pattern found", ex); + errorCount++; + } + + if (errorCount == 0) { + started = true; + } + } + + + + protected abstract Map getDefaultConverterMap(); + + + + public Map getEffectiveConverterMap() + { + Map effectiveMap = new HashMap(); + + + Map defaultMap = getDefaultConverterMap(); + if (defaultMap != null) { + effectiveMap.putAll(defaultMap); + } + + + Context context = getContext(); + if (context != null) + { + Map contextMap = (Map)context.getObject("PATTERN_RULE_REGISTRY"); + + if (contextMap != null) { + effectiveMap.putAll(contextMap); + } + } + return effectiveMap; + } + + + + + + + + public void setTitle(String title) + { + this.title = title; + } + + + + public String getTitle() + { + return title; + } + + + + + public String getContentType() + { + return "text/html"; + } + + + + + public String getFileHeader() + { + StringBuilder sbuf = new StringBuilder(); + sbuf.append(""); + sbuf.append(CoreConstants.LINE_SEPARATOR); + sbuf.append(""); + sbuf.append(CoreConstants.LINE_SEPARATOR); + sbuf.append(" "); + sbuf.append(CoreConstants.LINE_SEPARATOR); + sbuf.append(" "); + sbuf.append(title); + sbuf.append(""); + sbuf.append(CoreConstants.LINE_SEPARATOR); + + cssBuilder.addCss(sbuf); + + sbuf.append(CoreConstants.LINE_SEPARATOR); + sbuf.append(" "); + sbuf.append(CoreConstants.LINE_SEPARATOR); + sbuf.append(""); + sbuf.append(CoreConstants.LINE_SEPARATOR); + + return sbuf.toString(); + } + + public String getPresentationHeader() { + StringBuilder sbuf = new StringBuilder(); + sbuf.append("
"); + sbuf.append(CoreConstants.LINE_SEPARATOR); + sbuf.append("

Log session start time "); + sbuf.append(new Date()); + sbuf.append("

"); + sbuf.append(CoreConstants.LINE_SEPARATOR); + sbuf.append(CoreConstants.LINE_SEPARATOR); + sbuf.append(""); + sbuf.append(CoreConstants.LINE_SEPARATOR); + + buildHeaderRowForTable(sbuf); + + return sbuf.toString(); + } + + private void buildHeaderRowForTable(StringBuilder sbuf) + { + Converter c = head; + + sbuf.append(""); + sbuf.append(CoreConstants.LINE_SEPARATOR); + while (c != null) { + String name = computeConverterName(c); + if (name == null) { + c = c.getNext(); + } + else { + sbuf.append(""); + sbuf.append(CoreConstants.LINE_SEPARATOR); + c = c.getNext(); + } } + sbuf.append(""); + sbuf.append(CoreConstants.LINE_SEPARATOR); + } + + public String getPresentationFooter() { + StringBuilder sbuf = new StringBuilder(); + sbuf.append("
"); + sbuf.append(computeConverterName(c)); + sbuf.append("
"); + return sbuf.toString(); + } + + + + + public String getFileFooter() + { + StringBuilder sbuf = new StringBuilder(); + sbuf.append(CoreConstants.LINE_SEPARATOR); + sbuf.append(""); + return sbuf.toString(); + } + + protected void startNewTableIfLimitReached(StringBuilder sbuf) { + if (counter >= 10000L) { + counter = 0L; + sbuf.append(""); + sbuf.append(CoreConstants.LINE_SEPARATOR); + sbuf.append("

"); + sbuf.append(""); + sbuf.append(CoreConstants.LINE_SEPARATOR); + buildHeaderRowForTable(sbuf); + } + } + + protected String computeConverterName(Converter c) { + String className = c.getClass().getSimpleName(); + int index = className.indexOf("Converter"); + if (index == -1) { + return className; + } + return className.substring(0, index); + } +} diff --git a/src/minecraft/ch/qos/logback/core/html/IThrowableRenderer.java b/src/minecraft/ch/qos/logback/core/html/IThrowableRenderer.java new file mode 100644 index 0000000..037603a --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/html/IThrowableRenderer.java @@ -0,0 +1,6 @@ +package ch.qos.logback.core.html; + +public abstract interface IThrowableRenderer +{ + public abstract void render(StringBuilder paramStringBuilder, E paramE); +} diff --git a/src/minecraft/ch/qos/logback/core/html/NOPThrowableRenderer.java b/src/minecraft/ch/qos/logback/core/html/NOPThrowableRenderer.java new file mode 100644 index 0000000..2f1bae7 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/html/NOPThrowableRenderer.java @@ -0,0 +1,9 @@ +package ch.qos.logback.core.html; + +public class NOPThrowableRenderer + implements IThrowableRenderer +{ + public NOPThrowableRenderer() {} + + public void render(StringBuilder sbuf, Object event) {} +} diff --git a/src/minecraft/ch/qos/logback/core/joran/GenericConfigurator.java b/src/minecraft/ch/qos/logback/core/joran/GenericConfigurator.java new file mode 100644 index 0000000..1fee459 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/GenericConfigurator.java @@ -0,0 +1,169 @@ +package ch.qos.logback.core.joran; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.joran.event.SaxEvent; +import ch.qos.logback.core.joran.event.SaxEventRecorder; +import ch.qos.logback.core.joran.spi.DefaultNestedComponentRegistry; +import ch.qos.logback.core.joran.spi.ElementPath; +import ch.qos.logback.core.joran.spi.EventPlayer; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.joran.spi.Interpreter; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.joran.spi.RuleStore; +import ch.qos.logback.core.joran.spi.SimpleRuleStore; +import ch.qos.logback.core.joran.util.ConfigurationWatchListUtil; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.status.StatusUtil; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.net.URLConnection; +import java.util.List; +import org.xml.sax.InputSource; + + + + +public abstract class GenericConfigurator + extends ContextAwareBase +{ + protected Interpreter interpreter; + + public GenericConfigurator() {} + + public final void doConfigure(URL url) + throws JoranException + { + InputStream in = null; + try { + informContextOfURLUsedForConfiguration(getContext(), url); + URLConnection urlConnection = url.openConnection(); + + + urlConnection.setUseCaches(false); + + in = urlConnection.getInputStream(); + doConfigure(in); + String errMsg; + String errMsg; String errMsg; return; } catch (IOException ioe) { errMsg = "Could not open URL [" + url + "]."; + addError(errMsg, ioe); + throw new JoranException(errMsg, ioe); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException ioe) { + errMsg = "Could not close input stream"; + addError(errMsg, ioe); + throw new JoranException(errMsg, ioe); + } + } + } + } + + public final void doConfigure(String filename) throws JoranException { + doConfigure(new File(filename)); + } + + public final void doConfigure(File file) throws JoranException { + FileInputStream fis = null; + try { + informContextOfURLUsedForConfiguration(getContext(), file.toURI().toURL()); + fis = new FileInputStream(file); + doConfigure(fis); + String errMsg; + String errMsg; String errMsg; return; } catch (IOException ioe) { errMsg = "Could not open [" + file.getPath() + "]."; + addError(errMsg, ioe); + throw new JoranException(errMsg, ioe); + } finally { + if (fis != null) { + try { + fis.close(); + } catch (IOException ioe) { + errMsg = "Could not close [" + file.getName() + "]."; + addError(errMsg, ioe); + throw new JoranException(errMsg, ioe); + } + } + } + } + + public static void informContextOfURLUsedForConfiguration(Context context, URL url) { + ConfigurationWatchListUtil.setMainWatchURL(context, url); + } + + public final void doConfigure(InputStream inputStream) throws JoranException { + doConfigure(new InputSource(inputStream)); + } + + + protected abstract void addInstanceRules(RuleStore paramRuleStore); + + protected abstract void addImplicitRules(Interpreter paramInterpreter); + + protected void addDefaultNestedComponentRegistryRules(DefaultNestedComponentRegistry registry) {} + + protected ElementPath initialElementPath() + { + return new ElementPath(); + } + + protected void buildInterpreter() { + RuleStore rs = new SimpleRuleStore(context); + addInstanceRules(rs); + interpreter = new Interpreter(context, rs, initialElementPath()); + InterpretationContext interpretationContext = interpreter.getInterpretationContext(); + interpretationContext.setContext(context); + addImplicitRules(interpreter); + addDefaultNestedComponentRegistryRules(interpretationContext.getDefaultNestedComponentRegistry()); + } + + + + public final void doConfigure(InputSource inputSource) + throws JoranException + { + long threshold = System.currentTimeMillis(); + if (!ConfigurationWatchListUtil.wasConfigurationWatchListReset(context)) { + informContextOfURLUsedForConfiguration(getContext(), null); + } + SaxEventRecorder recorder = new SaxEventRecorder(context); + recorder.recordEvents(inputSource); + doConfigure(saxEventList); + + StatusUtil statusUtil = new StatusUtil(context); + if (statusUtil.noXMLParsingErrorsOccurred(threshold)) { + addInfo("Registering current configuration as safe fallback point"); + registerSafeConfiguration(); + } + } + + public void doConfigure(List eventList) throws JoranException + { + buildInterpreter(); + + synchronized (context.getConfigurationLock()) { + interpreter.getEventPlayer().play(eventList); + } + } + + + + + + + public void registerSafeConfiguration() + { + context.putObject("SAFE_JORAN_CONFIGURATION", interpreter.getEventPlayer().getCopyOfPlayerEventList()); + } + + + + public List recallSafeConfiguration() + { + return (List)context.getObject("SAFE_JORAN_CONFIGURATION"); + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/JoranConfiguratorBase.java b/src/minecraft/ch/qos/logback/core/joran/JoranConfiguratorBase.java new file mode 100644 index 0000000..1bd551d --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/JoranConfiguratorBase.java @@ -0,0 +1,114 @@ +package ch.qos.logback.core.joran; + +import ch.qos.logback.core.joran.action.AppenderAction; +import ch.qos.logback.core.joran.action.AppenderRefAction; +import ch.qos.logback.core.joran.action.ContextPropertyAction; +import ch.qos.logback.core.joran.action.ConversionRuleAction; +import ch.qos.logback.core.joran.action.DefinePropertyAction; +import ch.qos.logback.core.joran.action.NestedBasicPropertyIA; +import ch.qos.logback.core.joran.action.NestedComplexPropertyIA; +import ch.qos.logback.core.joran.action.NewRuleAction; +import ch.qos.logback.core.joran.action.ParamAction; +import ch.qos.logback.core.joran.action.PropertyAction; +import ch.qos.logback.core.joran.action.ShutdownHookAction; +import ch.qos.logback.core.joran.action.StatusListenerAction; +import ch.qos.logback.core.joran.action.TimestampAction; +import ch.qos.logback.core.joran.spi.ElementSelector; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.joran.spi.Interpreter; +import ch.qos.logback.core.joran.spi.RuleStore; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class JoranConfiguratorBase + extends GenericConfigurator +{ + public JoranConfiguratorBase() {} + + public List getErrorList() + { + return null; + } + + + + protected void addInstanceRules(RuleStore rs) + { + rs.addRule(new ElementSelector("configuration/variable"), new PropertyAction()); + rs.addRule(new ElementSelector("configuration/property"), new PropertyAction()); + + rs.addRule(new ElementSelector("configuration/substitutionProperty"), new PropertyAction()); + + + rs.addRule(new ElementSelector("configuration/timestamp"), new TimestampAction()); + rs.addRule(new ElementSelector("configuration/shutdownHook"), new ShutdownHookAction()); + rs.addRule(new ElementSelector("configuration/define"), new DefinePropertyAction()); + + + + rs.addRule(new ElementSelector("configuration/contextProperty"), new ContextPropertyAction()); + + + rs.addRule(new ElementSelector("configuration/conversionRule"), new ConversionRuleAction()); + + + rs.addRule(new ElementSelector("configuration/statusListener"), new StatusListenerAction()); + + + rs.addRule(new ElementSelector("configuration/appender"), new AppenderAction()); + rs.addRule(new ElementSelector("configuration/appender/appender-ref"), new AppenderRefAction()); + + rs.addRule(new ElementSelector("configuration/newRule"), new NewRuleAction()); + rs.addRule(new ElementSelector("*/param"), new ParamAction()); + } + + + protected void addImplicitRules(Interpreter interpreter) + { + NestedComplexPropertyIA nestedComplexPropertyIA = new NestedComplexPropertyIA(); + nestedComplexPropertyIA.setContext(context); + interpreter.addImplicitAction(nestedComplexPropertyIA); + + NestedBasicPropertyIA nestedBasicIA = new NestedBasicPropertyIA(); + nestedBasicIA.setContext(context); + interpreter.addImplicitAction(nestedBasicIA); + } + + protected void buildInterpreter() + { + super.buildInterpreter(); + Map omap = interpreter.getInterpretationContext().getObjectMap(); + + omap.put("APPENDER_BAG", new HashMap()); + omap.put("FILTER_CHAIN_BAG", new HashMap()); + } + + public InterpretationContext getInterpretationContext() { + return interpreter.getInterpretationContext(); + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/action/AbstractEventEvaluatorAction.java b/src/minecraft/ch/qos/logback/core/joran/action/AbstractEventEvaluatorAction.java new file mode 100644 index 0000000..79213dd --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/action/AbstractEventEvaluatorAction.java @@ -0,0 +1,121 @@ +package ch.qos.logback.core.joran.action; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.boolex.EventEvaluator; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.spi.LifeCycle; +import ch.qos.logback.core.util.OptionHelper; +import java.util.Map; +import org.xml.sax.Attributes; + + + + + + + + + + + + + + + +public abstract class AbstractEventEvaluatorAction + extends Action +{ + EventEvaluator evaluator; + boolean inError = false; + + + public AbstractEventEvaluatorAction() {} + + public void begin(InterpretationContext ec, String name, Attributes attributes) + { + inError = false; + evaluator = null; + + String className = attributes.getValue("class"); + if (OptionHelper.isEmpty(className)) { + className = defaultClassName(); + addInfo("Assuming default evaluator class [" + className + "]"); + } + + if (OptionHelper.isEmpty(className)) { + className = defaultClassName(); + inError = true; + addError("Mandatory \"class\" attribute not set for "); + + return; + } + + String evaluatorName = attributes.getValue("name"); + if (OptionHelper.isEmpty(evaluatorName)) { + inError = true; + addError("Mandatory \"name\" attribute not set for "); + + return; + } + try { + evaluator = ((EventEvaluator)OptionHelper.instantiateByClassName(className, EventEvaluator.class, context)); + + + evaluator.setContext(context); + evaluator.setName(evaluatorName); + + ec.pushObject(evaluator); + addInfo("Adding evaluator named [" + evaluatorName + "] to the object stack"); + } + catch (Exception oops) + { + inError = true; + addError("Could not create evaluator of type " + className + "].", oops); + } + } + + + + + + + protected abstract String defaultClassName(); + + + + + + public void end(InterpretationContext ec, String e) + { + if (inError) { + return; + } + + if ((evaluator instanceof LifeCycle)) { + evaluator.start(); + addInfo("Starting evaluator named [" + evaluator.getName() + "]"); + } + + Object o = ec.peekObject(); + + if (o != evaluator) { + addWarn("The object on the top the of the stack is not the evaluator pushed earlier."); + } else { + ec.popObject(); + try + { + Map> evaluatorMap = (Map)context.getObject("EVALUATOR_MAP"); + + if (evaluatorMap == null) { + addError("Could not find EvaluatorMap"); + } else { + evaluatorMap.put(evaluator.getName(), evaluator); + } + } catch (Exception ex) { + addError("Could not set evaluator named [" + evaluator + "].", ex); + } + } + } + + public void finish(InterpretationContext ec) {} +} diff --git a/src/minecraft/ch/qos/logback/core/joran/action/Action.java b/src/minecraft/ch/qos/logback/core/joran/action/Action.java new file mode 100644 index 0000000..8f7aad4 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/action/Action.java @@ -0,0 +1,101 @@ +package ch.qos.logback.core.joran.action; + +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.joran.spi.Interpreter; +import ch.qos.logback.core.spi.ContextAwareBase; +import org.xml.sax.Attributes; +import org.xml.sax.Locator; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class Action + extends ContextAwareBase +{ + public static final String NAME_ATTRIBUTE = "name"; + public static final String KEY_ATTRIBUTE = "key"; + public static final String VALUE_ATTRIBUTE = "value"; + public static final String FILE_ATTRIBUTE = "file"; + public static final String CLASS_ATTRIBUTE = "class"; + public static final String PATTERN_ATTRIBUTE = "pattern"; + public static final String SCOPE_ATTRIBUTE = "scope"; + public static final String ACTION_CLASS_ATTRIBUTE = "actionClass"; + + public Action() {} + + public abstract void begin(InterpretationContext paramInterpretationContext, String paramString, Attributes paramAttributes) + throws ActionException; + + public void body(InterpretationContext ic, String body) + throws ActionException + {} + + public abstract void end(InterpretationContext paramInterpretationContext, String paramString) + throws ActionException; + + public String toString() + { + return getClass().getName(); + } + + protected int getColumnNumber(InterpretationContext ic) { + Interpreter ji = ic.getJoranInterpreter(); + Locator locator = ji.getLocator(); + if (locator != null) { + return locator.getColumnNumber(); + } + return -1; + } + + protected int getLineNumber(InterpretationContext ic) { + Interpreter ji = ic.getJoranInterpreter(); + Locator locator = ji.getLocator(); + if (locator != null) { + return locator.getLineNumber(); + } + return -1; + } + + protected String getLineColStr(InterpretationContext ic) { + return "line: " + getLineNumber(ic) + ", column: " + getColumnNumber(ic); + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/action/ActionConst.java b/src/minecraft/ch/qos/logback/core/joran/action/ActionConst.java new file mode 100644 index 0000000..443f219 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/action/ActionConst.java @@ -0,0 +1,42 @@ +package ch.qos.logback.core.joran.action; + + + +public abstract class ActionConst +{ + public static final String APPENDER_TAG = "appender"; + + + public static final String REF_ATTRIBUTE = "ref"; + + + public static final String ADDITIVITY_ATTRIBUTE = "additivity"; + + + public static final String LEVEL_ATTRIBUTE = "level"; + + + public static final String CONVERTER_CLASS_ATTRIBUTE = "converterClass"; + + + public static final String CONVERSION_WORD_ATTRIBUTE = "conversionWord"; + + + public static final String PATTERN_ATTRIBUTE = "pattern"; + + + public static final String VALUE_ATTR = "value"; + + + public static final String ACTION_CLASS_ATTRIBUTE = "actionClass"; + + public static final String INHERITED = "INHERITED"; + + public static final String NULL = "NULL"; + + static final Class[] ONE_STRING_PARAM = { String.class }; + public static final String APPENDER_BAG = "APPENDER_BAG"; + public static final String FILTER_CHAIN_BAG = "FILTER_CHAIN_BAG"; + + public ActionConst() {} +} diff --git a/src/minecraft/ch/qos/logback/core/joran/action/ActionUtil.java b/src/minecraft/ch/qos/logback/core/joran/action/ActionUtil.java new file mode 100644 index 0000000..f9da15c --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/action/ActionUtil.java @@ -0,0 +1,73 @@ +package ch.qos.logback.core.joran.action; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.util.ContextUtil; +import ch.qos.logback.core.util.OptionHelper; +import java.util.Properties; + + + + + + + + + + + +public class ActionUtil +{ + public ActionUtil() {} + + public static enum Scope + { + LOCAL, CONTEXT, SYSTEM; + + + private Scope() {} + } + + + public static Scope stringToScope(String scopeStr) + { + if (Scope.SYSTEM.toString().equalsIgnoreCase(scopeStr)) + return Scope.SYSTEM; + if (Scope.CONTEXT.toString().equalsIgnoreCase(scopeStr)) { + return Scope.CONTEXT; + } + return Scope.LOCAL; + } + + public static void setProperty(InterpretationContext ic, String key, String value, Scope scope) { + switch (1.$SwitchMap$ch$qos$logback$core$joran$action$ActionUtil$Scope[scope.ordinal()]) { + case 1: + ic.addSubstitutionProperty(key, value); + break; + case 2: + ic.getContext().putProperty(key, value); + break; + case 3: + OptionHelper.setSystemProperty(ic, key, value); + } + + } + + + + + public static void setProperties(InterpretationContext ic, Properties props, Scope scope) + { + switch (1.$SwitchMap$ch$qos$logback$core$joran$action$ActionUtil$Scope[scope.ordinal()]) { + case 1: + ic.addSubstitutionProperties(props); + break; + case 2: + ContextUtil cu = new ContextUtil(ic.getContext()); + cu.addProperties(props); + break; + case 3: + OptionHelper.setSystemProperties(ic, props); + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/action/AppenderAction.java b/src/minecraft/ch/qos/logback/core/joran/action/AppenderAction.java new file mode 100644 index 0000000..e0256ec --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/action/AppenderAction.java @@ -0,0 +1,108 @@ +package ch.qos.logback.core.joran.action; + +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.spi.LifeCycle; +import ch.qos.logback.core.util.OptionHelper; +import java.util.HashMap; +import java.util.Map; +import org.xml.sax.Attributes; + + + + + + + + + + + + + +public class AppenderAction + extends Action +{ + Appender appender; + private boolean inError = false; + + + + + public AppenderAction() {} + + + + public void begin(InterpretationContext ec, String localName, Attributes attributes) + throws ActionException + { + appender = null; + inError = false; + + String className = attributes.getValue("class"); + if (OptionHelper.isEmpty(className)) { + addError("Missing class name for appender. Near [" + localName + "] line " + getLineNumber(ec)); + + inError = true; + return; + } + try + { + addInfo("About to instantiate appender of type [" + className + "]"); + + appender = ((Appender)OptionHelper.instantiateByClassName(className, Appender.class, context)); + + + appender.setContext(context); + + String appenderName = ec.subst(attributes.getValue("name")); + + if (OptionHelper.isEmpty(appenderName)) { + addWarn("No appender name given for appender of type " + className + "]."); + } + else { + appender.setName(appenderName); + addInfo("Naming appender as [" + appenderName + "]"); + } + + + + HashMap> appenderBag = (HashMap)ec.getObjectMap().get("APPENDER_BAG"); + + + + appenderBag.put(appenderName, appender); + + ec.pushObject(appender); + } catch (Exception oops) { + inError = true; + addError("Could not create an Appender of type [" + className + "].", oops); + + throw new ActionException(oops); + } + } + + + + + public void end(InterpretationContext ec, String name) + { + if (inError) { + return; + } + + if ((appender instanceof LifeCycle)) { + appender.start(); + } + + Object o = ec.peekObject(); + + if (o != appender) { + addWarn("The object at the of the stack is not the appender named [" + appender.getName() + "] pushed earlier."); + } + else { + ec.popObject(); + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/action/AppenderRefAction.java b/src/minecraft/ch/qos/logback/core/joran/action/AppenderRefAction.java new file mode 100644 index 0000000..7cf913f --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/action/AppenderRefAction.java @@ -0,0 +1,80 @@ +package ch.qos.logback.core.joran.action; + +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.spi.AppenderAttachable; +import ch.qos.logback.core.util.OptionHelper; +import java.util.HashMap; +import java.util.Map; +import org.xml.sax.Attributes; + + + + + + + + + + + + + + + +public class AppenderRefAction + extends Action +{ + boolean inError = false; + + public AppenderRefAction() {} + + public void begin(InterpretationContext ec, String tagName, Attributes attributes) { + inError = false; + + + + Object o = ec.peekObject(); + + if (!(o instanceof AppenderAttachable)) { + String errMsg = "Could not find an AppenderAttachable at the top of execution stack. Near [" + tagName + "] line " + getLineNumber(ec); + + inError = true; + addError(errMsg); + return; + } + + AppenderAttachable appenderAttachable = (AppenderAttachable)o; + + String appenderName = ec.subst(attributes.getValue("ref")); + + if (OptionHelper.isEmpty(appenderName)) + { + String errMsg = "Missing appender ref attribute in tag."; + inError = true; + addError(errMsg); + + return; + } + + HashMap> appenderBag = (HashMap)ec.getObjectMap().get("APPENDER_BAG"); + + Appender appender = (Appender)appenderBag.get(appenderName); + + if (appender == null) { + String msg = "Could not find an appender named [" + appenderName + "]. Did you define it below instead of above in the configuration file?"; + + inError = true; + addError(msg); + addError("See http://logback.qos.ch/codes.html#appender_order for more details."); + + return; + } + + addInfo("Attaching appender named [" + appenderName + "] to " + appenderAttachable); + + appenderAttachable.addAppender(appender); + } + + public void end(InterpretationContext ec, String n) {} +} diff --git a/src/minecraft/ch/qos/logback/core/joran/action/ContextPropertyAction.java b/src/minecraft/ch/qos/logback/core/joran/action/ContextPropertyAction.java new file mode 100644 index 0000000..70ff0ba --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/action/ContextPropertyAction.java @@ -0,0 +1,35 @@ +package ch.qos.logback.core.joran.action; + +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import org.xml.sax.Attributes; + + + + + + + + + + + + + + + +public class ContextPropertyAction + extends Action +{ + public ContextPropertyAction() {} + + public void begin(InterpretationContext ec, String name, Attributes attributes) + throws ActionException + { + addError("The [contextProperty] element has been removed. Please use [substitutionProperty] element instead"); + } + + public void end(InterpretationContext ec, String name) + throws ActionException + {} +} diff --git a/src/minecraft/ch/qos/logback/core/joran/action/ConversionRuleAction.java b/src/minecraft/ch/qos/logback/core/joran/action/ConversionRuleAction.java new file mode 100644 index 0000000..06dc1b1 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/action/ConversionRuleAction.java @@ -0,0 +1,81 @@ +package ch.qos.logback.core.joran.action; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.util.OptionHelper; +import java.util.HashMap; +import java.util.Map; +import org.xml.sax.Attributes; + + + + + + + + + + + + + + + + + +public class ConversionRuleAction + extends Action +{ + boolean inError = false; + + + + public ConversionRuleAction() {} + + + public void begin(InterpretationContext ec, String localName, Attributes attributes) + { + inError = false; + + + String conversionWord = attributes.getValue("conversionWord"); + + String converterClass = attributes.getValue("converterClass"); + + + if (OptionHelper.isEmpty(conversionWord)) { + inError = true; + String errorMsg = "No 'conversionWord' attribute in "; + addError(errorMsg); + + return; + } + + if (OptionHelper.isEmpty(converterClass)) { + inError = true; + String errorMsg = "No 'converterClass' attribute in "; + ec.addError(errorMsg); + + return; + } + try + { + Map ruleRegistry = (Map)context.getObject("PATTERN_RULE_REGISTRY"); + if (ruleRegistry == null) { + ruleRegistry = new HashMap(); + context.putObject("PATTERN_RULE_REGISTRY", ruleRegistry); + } + + addInfo("registering conversion word " + conversionWord + " with class [" + converterClass + "]"); + ruleRegistry.put(conversionWord, converterClass); + } catch (Exception oops) { + inError = true; + String errorMsg = "Could not add conversion rule to PatternLayout."; + addError(errorMsg); + } + } + + public void end(InterpretationContext ec, String n) {} + + public void finish(InterpretationContext ec) {} +} diff --git a/src/minecraft/ch/qos/logback/core/joran/action/DefinePropertyAction.java b/src/minecraft/ch/qos/logback/core/joran/action/DefinePropertyAction.java new file mode 100644 index 0000000..6a4a6fc --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/action/DefinePropertyAction.java @@ -0,0 +1,114 @@ +package ch.qos.logback.core.joran.action; + +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.spi.LifeCycle; +import ch.qos.logback.core.spi.PropertyDefiner; +import ch.qos.logback.core.util.OptionHelper; +import org.xml.sax.Attributes; + + + + + + + + + + + + + + + + + + + +public class DefinePropertyAction + extends Action +{ + String scopeStr; + ActionUtil.Scope scope; + String propertyName; + PropertyDefiner definer; + boolean inError; + + public DefinePropertyAction() {} + + public void begin(InterpretationContext ec, String localName, Attributes attributes) + throws ActionException + { + scopeStr = null; + scope = null; + propertyName = null; + definer = null; + inError = false; + + + propertyName = attributes.getValue("name"); + scopeStr = attributes.getValue("scope"); + + scope = ActionUtil.stringToScope(scopeStr); + if (OptionHelper.isEmpty(propertyName)) { + addError("Missing property name for property definer. Near [" + localName + "] line " + getLineNumber(ec)); + + inError = true; + return; + } + + + String className = attributes.getValue("class"); + if (OptionHelper.isEmpty(className)) { + addError("Missing class name for property definer. Near [" + localName + "] line " + getLineNumber(ec)); + + inError = true; + return; + } + + try + { + addInfo("About to instantiate property definer of type [" + className + "]"); + + definer = ((PropertyDefiner)OptionHelper.instantiateByClassName(className, PropertyDefiner.class, context)); + + definer.setContext(context); + if ((definer instanceof LifeCycle)) { + ((LifeCycle)definer).start(); + } + ec.pushObject(definer); + } catch (Exception oops) { + inError = true; + addError("Could not create an PropertyDefiner of type [" + className + "].", oops); + + throw new ActionException(oops); + } + } + + + + + public void end(InterpretationContext ec, String name) + { + if (inError) { + return; + } + + Object o = ec.peekObject(); + + if (o != definer) { + addWarn("The object at the of the stack is not the property definer for property named [" + propertyName + "] pushed earlier."); + } + else { + addInfo("Popping property definer for property named [" + propertyName + "] from the object stack"); + + ec.popObject(); + + + String propertyValue = definer.getPropertyValue(); + if (propertyValue != null) { + ActionUtil.setProperty(ec, propertyName, propertyValue, scope); + } + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/action/IADataForBasicProperty.java b/src/minecraft/ch/qos/logback/core/joran/action/IADataForBasicProperty.java new file mode 100644 index 0000000..4c30e2c --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/action/IADataForBasicProperty.java @@ -0,0 +1,35 @@ +package ch.qos.logback.core.joran.action; + +import ch.qos.logback.core.joran.util.PropertySetter; +import ch.qos.logback.core.util.AggregationType; + + + + + + + + + + + + + + + + + +class IADataForBasicProperty +{ + final PropertySetter parentBean; + final AggregationType aggregationType; + final String propertyName; + boolean inError; + + IADataForBasicProperty(PropertySetter parentBean, AggregationType aggregationType, String propertyName) + { + this.parentBean = parentBean; + this.aggregationType = aggregationType; + this.propertyName = propertyName; + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/action/IADataForComplexProperty.java b/src/minecraft/ch/qos/logback/core/joran/action/IADataForComplexProperty.java new file mode 100644 index 0000000..87f27df --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/action/IADataForComplexProperty.java @@ -0,0 +1,52 @@ +package ch.qos.logback.core.joran.action; + +import ch.qos.logback.core.joran.util.PropertySetter; +import ch.qos.logback.core.util.AggregationType; + + + + + + + + + + + + + + + + + +public class IADataForComplexProperty +{ + final PropertySetter parentBean; + final AggregationType aggregationType; + final String complexPropertyName; + private Object nestedComplexProperty; + boolean inError; + + public IADataForComplexProperty(PropertySetter parentBean, AggregationType aggregationType, String complexPropertyName) + { + this.parentBean = parentBean; + this.aggregationType = aggregationType; + this.complexPropertyName = complexPropertyName; + } + + public AggregationType getAggregationType() { + return aggregationType; + } + + public Object getNestedComplexProperty() { + return nestedComplexProperty; + } + + public String getComplexPropertyName() { + return complexPropertyName; + } + + public void setNestedComplexProperty(Object nestedComplexProperty) { + this.nestedComplexProperty = nestedComplexProperty; + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/action/ImplicitAction.java b/src/minecraft/ch/qos/logback/core/joran/action/ImplicitAction.java new file mode 100644 index 0000000..82d567f --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/action/ImplicitAction.java @@ -0,0 +1,13 @@ +package ch.qos.logback.core.joran.action; + +import ch.qos.logback.core.joran.spi.ElementPath; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import org.xml.sax.Attributes; + +public abstract class ImplicitAction + extends Action +{ + public ImplicitAction() {} + + public abstract boolean isApplicable(ElementPath paramElementPath, Attributes paramAttributes, InterpretationContext paramInterpretationContext); +} diff --git a/src/minecraft/ch/qos/logback/core/joran/action/IncludeAction.java b/src/minecraft/ch/qos/logback/core/joran/action/IncludeAction.java new file mode 100644 index 0000000..30e9e6e --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/action/IncludeAction.java @@ -0,0 +1,243 @@ +package ch.qos.logback.core.joran.action; + +import ch.qos.logback.core.joran.event.SaxEvent; +import ch.qos.logback.core.joran.event.SaxEventRecorder; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.EventPlayer; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.joran.spi.Interpreter; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.joran.util.ConfigurationWatchListUtil; +import ch.qos.logback.core.util.Loader; +import ch.qos.logback.core.util.OptionHelper; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.util.List; +import org.xml.sax.Attributes; + + + + + + + + + + + + + +public class IncludeAction + extends Action +{ + private static final String INCLUDED_TAG = "included"; + private static final String FILE_ATTR = "file"; + private static final String URL_ATTR = "url"; + private static final String RESOURCE_ATTR = "resource"; + private static final String OPTIONAL_ATTR = "optional"; + private String attributeInUse; + private boolean optional; + + public IncludeAction() {} + + public void begin(InterpretationContext ec, String name, Attributes attributes) + throws ActionException + { + SaxEventRecorder recorder = new SaxEventRecorder(context); + + attributeInUse = null; + optional = OptionHelper.toBoolean(attributes.getValue("optional"), false); + + if (!checkAttributes(attributes)) { + return; + } + + InputStream in = getInputStream(ec, attributes); + try + { + if (in != null) { + parseAndRecord(in, recorder); + + trimHeadAndTail(recorder); + + + ec.getJoranInterpreter().getEventPlayer().addEventsDynamically(saxEventList, 2); + } + } catch (JoranException e) { + addError("Error while parsing " + attributeInUse, e); + } finally { + close(in); + } + } + + void close(InputStream in) + { + if (in != null) { + try { + in.close(); + } + catch (IOException e) {} + } + } + + private boolean checkAttributes(Attributes attributes) { + String fileAttribute = attributes.getValue("file"); + String urlAttribute = attributes.getValue("url"); + String resourceAttribute = attributes.getValue("resource"); + + int count = 0; + + if (!OptionHelper.isEmpty(fileAttribute)) { + count++; + } + if (!OptionHelper.isEmpty(urlAttribute)) { + count++; + } + if (!OptionHelper.isEmpty(resourceAttribute)) { + count++; + } + + if (count == 0) { + addError("One of \"path\", \"resource\" or \"url\" attributes must be set."); + return false; } + if (count > 1) { + addError("Only one of \"file\", \"url\" or \"resource\" attributes should be set."); + return false; } + if (count == 1) { + return true; + } + throw new IllegalStateException("Count value [" + count + "] is not expected"); + } + + private InputStream getInputStreamByFilePath(String pathToFile) + { + try { + return new FileInputStream(pathToFile); + } catch (IOException ioe) { + optionalWarning("File [" + pathToFile + "] does not exist."); } + return null; + } + + URL attributeToURL(String urlAttribute) + { + try { + return new URL(urlAttribute); + } catch (MalformedURLException mue) { + String errMsg = "URL [" + urlAttribute + "] is not well formed."; + addError(errMsg, mue); } + return null; + } + + private InputStream getInputStreamByUrl(URL url) + { + return openURL(url); + } + + InputStream openURL(URL url) { + try { + return url.openStream(); + } catch (IOException e) { + optionalWarning("Failed to open [" + url.toString() + "]"); } + return null; + } + + URL resourceAsURL(String resourceAttribute) + { + URL url = Loader.getResourceBySelfClassLoader(resourceAttribute); + if (url == null) { + optionalWarning("Could not find resource corresponding to [" + resourceAttribute + "]"); + return null; + } + return url; + } + + private void optionalWarning(String msg) { + if (!optional) { + addWarn(msg); + } + } + + URL filePathAsURL(String path) { + URI uri = new File(path).toURI(); + try { + return uri.toURL(); + } + catch (MalformedURLException e) { + e.printStackTrace(); } + return null; + } + + private InputStream getInputStreamByResource(URL url) + { + return openURL(url); + } + + URL getInputURL(InterpretationContext ec, Attributes attributes) { + String fileAttribute = attributes.getValue("file"); + String urlAttribute = attributes.getValue("url"); + String resourceAttribute = attributes.getValue("resource"); + + if (!OptionHelper.isEmpty(fileAttribute)) { + attributeInUse = ec.subst(fileAttribute); + return filePathAsURL(attributeInUse); + } + + if (!OptionHelper.isEmpty(urlAttribute)) { + attributeInUse = ec.subst(urlAttribute); + return attributeToURL(attributeInUse); + } + + if (!OptionHelper.isEmpty(resourceAttribute)) { + attributeInUse = ec.subst(resourceAttribute); + return resourceAsURL(attributeInUse); + } + + throw new IllegalStateException("A URL stream should have been returned"); + } + + InputStream getInputStream(InterpretationContext ec, Attributes attributes) + { + URL inputURL = getInputURL(ec, attributes); + if (inputURL == null) { + return null; + } + ConfigurationWatchListUtil.addToWatchList(context, inputURL); + return openURL(inputURL); + } + + + + private void trimHeadAndTail(SaxEventRecorder recorder) + { + List saxEventList = saxEventList; + + if (saxEventList.size() == 0) { + return; + } + + SaxEvent first = (SaxEvent)saxEventList.get(0); + if ((first != null) && (qName.equalsIgnoreCase("included"))) { + saxEventList.remove(0); + } + + SaxEvent last = (SaxEvent)saxEventList.get(saxEventList.size() - 1); + if ((last != null) && (qName.equalsIgnoreCase("included"))) { + saxEventList.remove(saxEventList.size() - 1); + } + } + + private void parseAndRecord(InputStream inputSource, SaxEventRecorder recorder) throws JoranException + { + recorder.setContext(context); + recorder.recordEvents(inputSource); + } + + public void end(InterpretationContext ec, String name) + throws ActionException + {} +} diff --git a/src/minecraft/ch/qos/logback/core/joran/action/NOPAction.java b/src/minecraft/ch/qos/logback/core/joran/action/NOPAction.java new file mode 100644 index 0000000..af288c0 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/action/NOPAction.java @@ -0,0 +1,14 @@ +package ch.qos.logback.core.joran.action; + +import ch.qos.logback.core.joran.spi.InterpretationContext; +import org.xml.sax.Attributes; + +public class NOPAction + extends Action +{ + public NOPAction() {} + + public void begin(InterpretationContext ec, String name, Attributes attributes) {} + + public void end(InterpretationContext ec, String name) {} +} diff --git a/src/minecraft/ch/qos/logback/core/joran/action/NestedBasicPropertyIA.java b/src/minecraft/ch/qos/logback/core/joran/action/NestedBasicPropertyIA.java new file mode 100644 index 0000000..ddae580 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/action/NestedBasicPropertyIA.java @@ -0,0 +1,104 @@ +package ch.qos.logback.core.joran.action; + +import ch.qos.logback.core.joran.spi.ElementPath; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.joran.util.PropertySetter; +import ch.qos.logback.core.util.AggregationType; +import java.util.Stack; +import org.xml.sax.Attributes; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class NestedBasicPropertyIA + extends ImplicitAction +{ + Stack actionDataStack = new Stack(); + + public NestedBasicPropertyIA() {} + + public boolean isApplicable(ElementPath elementPath, Attributes attributes, InterpretationContext ec) + { + String nestedElementTagName = elementPath.peekLast(); + + + if (ec.isEmpty()) { + return false; + } + + Object o = ec.peekObject(); + PropertySetter parentBean = new PropertySetter(o); + parentBean.setContext(context); + + AggregationType aggregationType = parentBean.computeAggregationType(nestedElementTagName); + + + switch (1.$SwitchMap$ch$qos$logback$core$util$AggregationType[aggregationType.ordinal()]) { + case 1: + case 2: + case 3: + return false; + + case 4: + case 5: + IADataForBasicProperty ad = new IADataForBasicProperty(parentBean, aggregationType, nestedElementTagName); + + actionDataStack.push(ad); + + return true; + } + addError("PropertySetter.canContainComponent returned " + aggregationType); + return false; + } + + + + public void begin(InterpretationContext ec, String localName, Attributes attributes) {} + + + + public void body(InterpretationContext ec, String body) + { + String finalBody = ec.subst(body); + + IADataForBasicProperty actionData = (IADataForBasicProperty)actionDataStack.peek(); + switch (1.$SwitchMap$ch$qos$logback$core$util$AggregationType[aggregationType.ordinal()]) { + case 4: + parentBean.setProperty(propertyName, finalBody); + break; + case 5: + parentBean.addBasicProperty(propertyName, finalBody); + } + + } + + public void end(InterpretationContext ec, String tagName) + { + actionDataStack.pop(); + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/action/NestedComplexPropertyIA.java b/src/minecraft/ch/qos/logback/core/joran/action/NestedComplexPropertyIA.java new file mode 100644 index 0000000..2a8d00b --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/action/NestedComplexPropertyIA.java @@ -0,0 +1,188 @@ +package ch.qos.logback.core.joran.action; + +import ch.qos.logback.core.joran.spi.ElementPath; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.joran.spi.NoAutoStartUtil; +import ch.qos.logback.core.joran.util.PropertySetter; +import ch.qos.logback.core.spi.ContextAware; +import ch.qos.logback.core.spi.LifeCycle; +import ch.qos.logback.core.util.AggregationType; +import ch.qos.logback.core.util.Loader; +import ch.qos.logback.core.util.OptionHelper; +import java.util.Stack; +import org.xml.sax.Attributes; + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class NestedComplexPropertyIA + extends ImplicitAction +{ + Stack actionDataStack = new Stack(); + + public NestedComplexPropertyIA() {} + + public boolean isApplicable(ElementPath elementPath, Attributes attributes, InterpretationContext ic) { + String nestedElementTagName = elementPath.peekLast(); + + + if (ic.isEmpty()) { + return false; + } + + Object o = ic.peekObject(); + PropertySetter parentBean = new PropertySetter(o); + parentBean.setContext(context); + + AggregationType aggregationType = parentBean.computeAggregationType(nestedElementTagName); + + + switch (1.$SwitchMap$ch$qos$logback$core$util$AggregationType[aggregationType.ordinal()]) { + case 1: + case 2: + case 3: + return false; + + + case 4: + case 5: + IADataForComplexProperty ad = new IADataForComplexProperty(parentBean, aggregationType, nestedElementTagName); + + actionDataStack.push(ad); + + return true; + } + addError("PropertySetter.computeAggregationType returned " + aggregationType); + + return false; + } + + + + + public void begin(InterpretationContext ec, String localName, Attributes attributes) + { + IADataForComplexProperty actionData = (IADataForComplexProperty)actionDataStack.peek(); + + + String className = attributes.getValue("class"); + + className = ec.subst(className); + + Class componentClass = null; + try + { + if (!OptionHelper.isEmpty(className)) { + componentClass = Loader.loadClass(className, context); + } + else { + PropertySetter parentBean = parentBean; + componentClass = parentBean.getClassNameViaImplicitRules(actionData.getComplexPropertyName(), actionData.getAggregationType(), ec.getDefaultNestedComponentRegistry()); + } + + + + if (componentClass == null) { + inError = true; + String errMsg = "Could not find an appropriate class for property [" + localName + "]"; + + addError(errMsg); + return; + } + + if (OptionHelper.isEmpty(className)) { + addInfo("Assuming default type [" + componentClass.getName() + "] for [" + localName + "] property"); + } + + + actionData.setNestedComplexProperty(componentClass.newInstance()); + + + if ((actionData.getNestedComplexProperty() instanceof ContextAware)) { + ((ContextAware)actionData.getNestedComplexProperty()).setContext(context); + } + + + + ec.pushObject(actionData.getNestedComplexProperty()); + } + catch (Exception oops) { + inError = true; + String msg = "Could not create component [" + localName + "] of type [" + className + "]"; + + addError(msg, oops); + } + } + + + + + public void end(InterpretationContext ec, String tagName) + { + IADataForComplexProperty actionData = (IADataForComplexProperty)actionDataStack.pop(); + + + if (inError) { + return; + } + + PropertySetter nestedBean = new PropertySetter(actionData.getNestedComplexProperty()); + + nestedBean.setContext(context); + + + if (nestedBean.computeAggregationType("parent") == AggregationType.AS_COMPLEX_PROPERTY) { + nestedBean.setComplexProperty("parent", parentBean.getObj()); + } + + + + Object nestedComplexProperty = actionData.getNestedComplexProperty(); + if (((nestedComplexProperty instanceof LifeCycle)) && (NoAutoStartUtil.notMarkedWithNoAutoStart(nestedComplexProperty))) + { + ((LifeCycle)nestedComplexProperty).start(); + } + + Object o = ec.peekObject(); + + if (o != actionData.getNestedComplexProperty()) { + addError("The object on the top the of the stack is not the component pushed earlier."); + } else { + ec.popObject(); + + switch (1.$SwitchMap$ch$qos$logback$core$util$AggregationType[aggregationType.ordinal()]) { + case 5: + parentBean.setComplexProperty(tagName, actionData.getNestedComplexProperty()); + + + break; + case 4: + parentBean.addComplexProperty(tagName, actionData.getNestedComplexProperty()); + } + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/action/NewRuleAction.java b/src/minecraft/ch/qos/logback/core/joran/action/NewRuleAction.java new file mode 100644 index 0000000..6571085 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/action/NewRuleAction.java @@ -0,0 +1,66 @@ +package ch.qos.logback.core.joran.action; + +import ch.qos.logback.core.joran.spi.ElementSelector; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.joran.spi.Interpreter; +import ch.qos.logback.core.joran.spi.RuleStore; +import ch.qos.logback.core.util.OptionHelper; +import org.xml.sax.Attributes; + + + + + + + + + + + + +public class NewRuleAction + extends Action +{ + boolean inError = false; + + + public NewRuleAction() {} + + public void begin(InterpretationContext ec, String localName, Attributes attributes) + { + inError = false; + + String pattern = attributes.getValue("pattern"); + String actionClass = attributes.getValue("actionClass"); + + if (OptionHelper.isEmpty(pattern)) { + inError = true; + String errorMsg = "No 'pattern' attribute in "; + addError(errorMsg); + return; + } + + if (OptionHelper.isEmpty(actionClass)) { + inError = true; + String errorMsg = "No 'actionClass' attribute in "; + addError(errorMsg); + return; + } + try + { + addInfo("About to add new Joran parsing rule [" + pattern + "," + actionClass + "]."); + + ec.getJoranInterpreter().getRuleStore().addRule(new ElementSelector(pattern), actionClass); + } + catch (Exception oops) { + inError = true; + String errorMsg = "Could not add new Joran parsing rule [" + pattern + "," + actionClass + "]"; + + addError(errorMsg); + } + } + + public void end(InterpretationContext ec, String n) {} + + public void finish(InterpretationContext ec) {} +} diff --git a/src/minecraft/ch/qos/logback/core/joran/action/ParamAction.java b/src/minecraft/ch/qos/logback/core/joran/action/ParamAction.java new file mode 100644 index 0000000..3a6f312 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/action/ParamAction.java @@ -0,0 +1,65 @@ +package ch.qos.logback.core.joran.action; + +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.joran.util.PropertySetter; +import org.xml.sax.Attributes; + + + + + + + + + + + + + + + + +public class ParamAction + extends Action +{ + static String NO_NAME = "No name attribute in element"; + static String NO_VALUE = "No name attribute in element"; + boolean inError = false; + + public ParamAction() {} + + public void begin(InterpretationContext ec, String localName, Attributes attributes) { String name = attributes.getValue("name"); + String value = attributes.getValue("value"); + + if (name == null) { + inError = true; + addError(NO_NAME); + return; + } + + if (value == null) { + inError = true; + addError(NO_VALUE); + return; + } + + + value = value.trim(); + + Object o = ec.peekObject(); + PropertySetter propSetter = new PropertySetter(o); + propSetter.setContext(context); + value = ec.subst(value); + + + name = ec.subst(name); + + + + propSetter.setProperty(name, value); + } + + public void end(InterpretationContext ec, String localName) {} + + public void finish(InterpretationContext ec) {} +} diff --git a/src/minecraft/ch/qos/logback/core/joran/action/PropertyAction.java b/src/minecraft/ch/qos/logback/core/joran/action/PropertyAction.java new file mode 100644 index 0000000..bed10db --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/action/PropertyAction.java @@ -0,0 +1,147 @@ +package ch.qos.logback.core.joran.action; + +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.pattern.util.RegularEscapeUtil; +import ch.qos.logback.core.util.Loader; +import ch.qos.logback.core.util.OptionHelper; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.Properties; +import org.xml.sax.Attributes; + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class PropertyAction + extends Action +{ + static final String RESOURCE_ATTRIBUTE = "resource"; + static String INVALID_ATTRIBUTES = "In element, either the \"file\" attribute alone, or the \"resource\" element alone, or both the \"name\" and \"value\" attributes must be set."; + + + + + public PropertyAction() {} + + + + + public void begin(InterpretationContext ec, String localName, Attributes attributes) + { + if ("substitutionProperty".equals(localName)) { + addWarn("[substitutionProperty] element has been deprecated. Please use the [property] element instead."); + } + + String name = attributes.getValue("name"); + String value = attributes.getValue("value"); + String scopeStr = attributes.getValue("scope"); + + ActionUtil.Scope scope = ActionUtil.stringToScope(scopeStr); + + if (checkFileAttributeSanity(attributes)) { + String file = attributes.getValue("file"); + file = ec.subst(file); + try { + FileInputStream istream = new FileInputStream(file); + loadAndSetProperties(ec, istream, scope); + } catch (FileNotFoundException e) { + addError("Could not find properties file [" + file + "]."); + } catch (IOException e1) { + addError("Could not read properties file [" + file + "].", e1); + } + } else if (checkResourceAttributeSanity(attributes)) { + String resource = attributes.getValue("resource"); + resource = ec.subst(resource); + URL resourceURL = Loader.getResourceBySelfClassLoader(resource); + if (resourceURL == null) { + addError("Could not find resource [" + resource + "]."); + } else { + try { + InputStream istream = resourceURL.openStream(); + loadAndSetProperties(ec, istream, scope); + } catch (IOException e) { + addError("Could not read resource file [" + resource + "].", e); + } + } + } else if (checkValueNameAttributesSanity(attributes)) { + value = RegularEscapeUtil.basicEscape(value); + + value = value.trim(); + value = ec.subst(value); + ActionUtil.setProperty(ec, name, value, scope); + } + else { + addError(INVALID_ATTRIBUTES); + } + } + + void loadAndSetProperties(InterpretationContext ec, InputStream istream, ActionUtil.Scope scope) throws IOException + { + Properties props = new Properties(); + props.load(istream); + istream.close(); + ActionUtil.setProperties(ec, props, scope); + } + + boolean checkFileAttributeSanity(Attributes attributes) { + String file = attributes.getValue("file"); + String name = attributes.getValue("name"); + String value = attributes.getValue("value"); + String resource = attributes.getValue("resource"); + + return (!OptionHelper.isEmpty(file)) && (OptionHelper.isEmpty(name)) && (OptionHelper.isEmpty(value)) && (OptionHelper.isEmpty(resource)); + } + + + boolean checkResourceAttributeSanity(Attributes attributes) + { + String file = attributes.getValue("file"); + String name = attributes.getValue("name"); + String value = attributes.getValue("value"); + String resource = attributes.getValue("resource"); + + return (!OptionHelper.isEmpty(resource)) && (OptionHelper.isEmpty(name)) && (OptionHelper.isEmpty(value)) && (OptionHelper.isEmpty(file)); + } + + + boolean checkValueNameAttributesSanity(Attributes attributes) + { + String file = attributes.getValue("file"); + String name = attributes.getValue("name"); + String value = attributes.getValue("value"); + String resource = attributes.getValue("resource"); + + return (!OptionHelper.isEmpty(name)) && (!OptionHelper.isEmpty(value)) && (OptionHelper.isEmpty(file)) && (OptionHelper.isEmpty(resource)); + } + + public void end(InterpretationContext ec, String name) {} + + public void finish(InterpretationContext ec) {} +} diff --git a/src/minecraft/ch/qos/logback/core/joran/action/ShutdownHookAction.java b/src/minecraft/ch/qos/logback/core/joran/action/ShutdownHookAction.java new file mode 100644 index 0000000..ad0fecd --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/action/ShutdownHookAction.java @@ -0,0 +1,90 @@ +package ch.qos.logback.core.joran.action; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.hook.ShutdownHookBase; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.util.OptionHelper; +import org.xml.sax.Attributes; + + + + + + + + + + + + + + + + + + + + + + +public class ShutdownHookAction + extends Action +{ + ShutdownHookBase hook; + private boolean inError; + + public ShutdownHookAction() {} + + public void begin(InterpretationContext ic, String name, Attributes attributes) + throws ActionException + { + hook = null; + inError = false; + + String className = attributes.getValue("class"); + if (OptionHelper.isEmpty(className)) { + addError("Missing class name for shutdown hook. Near [" + name + "] line " + getLineNumber(ic)); + + inError = true; + return; + } + try + { + addInfo("About to instantiate shutdown hook of type [" + className + "]"); + + hook = ((ShutdownHookBase)OptionHelper.instantiateByClassName(className, ShutdownHookBase.class, context)); + + hook.setContext(context); + + ic.pushObject(hook); + } catch (Exception e) { + inError = true; + addError("Could not create a shutdown hook of type [" + className + "].", e); + throw new ActionException(e); + } + } + + + + + public void end(InterpretationContext ic, String name) + throws ActionException + { + if (inError) { + return; + } + + Object o = ic.peekObject(); + if (o != hook) { + addWarn("The object at the of the stack is not the hook pushed earlier."); + } else { + ic.popObject(); + + Thread hookThread = new Thread(hook, "Logback shutdown hook [" + context.getName() + "]"); + + context.putObject("SHUTDOWN_HOOK", hookThread); + Runtime.getRuntime().addShutdownHook(hookThread); + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/action/StatusListenerAction.java b/src/minecraft/ch/qos/logback/core/joran/action/StatusListenerAction.java new file mode 100644 index 0000000..5b63676 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/action/StatusListenerAction.java @@ -0,0 +1,77 @@ +package ch.qos.logback.core.joran.action; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.spi.ContextAware; +import ch.qos.logback.core.spi.LifeCycle; +import ch.qos.logback.core.status.StatusListener; +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.util.OptionHelper; +import org.xml.sax.Attributes; + + + + + + + + + + + + +public class StatusListenerAction + extends Action +{ + public StatusListenerAction() {} + + boolean inError = false; + StatusListener statusListener = null; + + public void begin(InterpretationContext ec, String name, Attributes attributes) throws ActionException { + inError = false; + String className = attributes.getValue("class"); + if (OptionHelper.isEmpty(className)) { + addError("Missing class name for statusListener. Near [" + name + "] line " + getLineNumber(ec)); + + inError = true; + return; + } + try + { + statusListener = ((StatusListener)OptionHelper.instantiateByClassName(className, StatusListener.class, context)); + + ec.getContext().getStatusManager().add(statusListener); + if ((statusListener instanceof ContextAware)) { + ((ContextAware)statusListener).setContext(context); + } + addInfo("Added status listener of type [" + className + "]"); + ec.pushObject(statusListener); + } catch (Exception e) { + inError = true; + addError("Could not create an StatusListener of type [" + className + "].", e); + + throw new ActionException(e); + } + } + + + public void finish(InterpretationContext ec) {} + + public void end(InterpretationContext ec, String e) + { + if (inError) { + return; + } + if ((statusListener instanceof LifeCycle)) { + ((LifeCycle)statusListener).start(); + } + Object o = ec.peekObject(); + if (o != statusListener) { + addWarn("The object at the of the stack is not the statusListener pushed earlier."); + } else { + ec.popObject(); + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/action/TimestampAction.java b/src/minecraft/ch/qos/logback/core/joran/action/TimestampAction.java new file mode 100644 index 0000000..752158a --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/action/TimestampAction.java @@ -0,0 +1,82 @@ +package ch.qos.logback.core.joran.action; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.util.CachingDateFormatter; +import ch.qos.logback.core.util.OptionHelper; +import org.xml.sax.Attributes; + + + + + + + + + + + + + + + + + + + + + +public class TimestampAction + extends Action +{ + static String DATE_PATTERN_ATTRIBUTE = "datePattern"; + static String TIME_REFERENCE_ATTRIBUTE = "timeReference"; + static String CONTEXT_BIRTH = "contextBirth"; + + boolean inError = false; + + public TimestampAction() {} + + public void begin(InterpretationContext ec, String name, Attributes attributes) throws ActionException { + String keyStr = attributes.getValue("key"); + if (OptionHelper.isEmpty(keyStr)) { + addError("Attribute named [key] cannot be empty"); + inError = true; + } + String datePatternStr = attributes.getValue(DATE_PATTERN_ATTRIBUTE); + if (OptionHelper.isEmpty(datePatternStr)) { + addError("Attribute named [" + DATE_PATTERN_ATTRIBUTE + "] cannot be empty"); + + inError = true; + } + + String timeReferenceStr = attributes.getValue(TIME_REFERENCE_ATTRIBUTE); + long timeReference; + long timeReference; if (CONTEXT_BIRTH.equalsIgnoreCase(timeReferenceStr)) { + addInfo("Using context birth as time reference."); + timeReference = context.getBirthTime(); + } else { + timeReference = System.currentTimeMillis(); + addInfo("Using current interpretation time, i.e. now, as time reference."); + } + + + if (inError) { + return; + } + String scopeStr = attributes.getValue("scope"); + ActionUtil.Scope scope = ActionUtil.stringToScope(scopeStr); + + CachingDateFormatter sdf = new CachingDateFormatter(datePatternStr); + String val = sdf.format(timeReference); + + addInfo("Adding property to the context with key=\"" + keyStr + "\" and value=\"" + val + "\" to the " + scope + " scope"); + + ActionUtil.setProperty(ec, keyStr, val, scope); + } + + public void end(InterpretationContext ec, String name) + throws ActionException + {} +} diff --git a/src/minecraft/ch/qos/logback/core/joran/conditional/Condition.java b/src/minecraft/ch/qos/logback/core/joran/conditional/Condition.java new file mode 100644 index 0000000..2b712fb --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/conditional/Condition.java @@ -0,0 +1,6 @@ +package ch.qos.logback.core.joran.conditional; + +public abstract interface Condition +{ + public abstract boolean evaluate(); +} diff --git a/src/minecraft/ch/qos/logback/core/joran/conditional/ElseAction.java b/src/minecraft/ch/qos/logback/core/joran/conditional/ElseAction.java new file mode 100644 index 0000000..b68b4f5 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/conditional/ElseAction.java @@ -0,0 +1,26 @@ +package ch.qos.logback.core.joran.conditional; + +import ch.qos.logback.core.joran.event.SaxEvent; +import java.util.List; + + + + + + + + + + + + +public class ElseAction + extends ThenOrElseActionBase +{ + public ElseAction() {} + + void registerEventList(IfAction ifAction, List eventList) + { + ifAction.setElseSaxEventList(eventList); + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/conditional/IfAction.java b/src/minecraft/ch/qos/logback/core/joran/conditional/IfAction.java new file mode 100644 index 0000000..9e535a5 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/conditional/IfAction.java @@ -0,0 +1,148 @@ +package ch.qos.logback.core.joran.conditional; + +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.event.SaxEvent; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.EventPlayer; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import ch.qos.logback.core.joran.spi.Interpreter; +import ch.qos.logback.core.util.EnvUtil; +import ch.qos.logback.core.util.OptionHelper; +import java.util.List; +import java.util.Stack; +import org.xml.sax.Attributes; + + + + + + + + + + + + + + + + +public class IfAction + extends Action +{ + private static final String CONDITION_ATTR = "condition"; + public static final String MISSING_JANINO_MSG = "Could not find Janino library on the class path. Skipping conditional processing."; + public static final String MISSING_JANINO_SEE = "See also http://logback.qos.ch/codes.html#ifJanino"; + Stack stack = new Stack(); + + public IfAction() {} + + public void begin(InterpretationContext ic, String name, Attributes attributes) throws ActionException + { + IfState state = new IfState(); + boolean emptyStack = stack.isEmpty(); + stack.push(state); + + if (!emptyStack) { + return; + } + + ic.pushObject(this); + if (!EnvUtil.isJaninoAvailable()) { + addError("Could not find Janino library on the class path. Skipping conditional processing."); + addError("See also http://logback.qos.ch/codes.html#ifJanino"); + return; + } + + active = true; + Condition condition = null; + String conditionAttribute = attributes.getValue("condition"); + + + if (!OptionHelper.isEmpty(conditionAttribute)) { + conditionAttribute = OptionHelper.substVars(conditionAttribute, ic, context); + PropertyEvalScriptBuilder pesb = new PropertyEvalScriptBuilder(ic); + pesb.setContext(context); + try { + condition = pesb.build(conditionAttribute); + } catch (Exception e) { + addError("Failed to parse condition [" + conditionAttribute + "]", e); + } + + if (condition != null) { + boolResult = Boolean.valueOf(condition.evaluate()); + } + } + } + + + + public void end(InterpretationContext ic, String name) + throws ActionException + { + IfState state = (IfState)stack.pop(); + if (!active) { + return; + } + + + Object o = ic.peekObject(); + if (o == null) { + throw new IllegalStateException("Unexpected null object on stack"); + } + if (!(o instanceof IfAction)) { + throw new IllegalStateException("Unexpected object of type [" + o.getClass() + "] on stack"); + } + + + if (o != this) { + throw new IllegalStateException("IfAction different then current one on stack"); + } + + ic.popObject(); + + if (boolResult == null) { + addError("Failed to determine \"if then else\" result"); + return; + } + + Interpreter interpreter = ic.getJoranInterpreter(); + List listToPlay = thenSaxEventList; + if (!boolResult.booleanValue()) { + listToPlay = elseSaxEventList; + } + + + if (listToPlay != null) + { + interpreter.getEventPlayer().addEventsDynamically(listToPlay, 1); + } + } + + + public void setThenSaxEventList(List thenSaxEventList) + { + IfState state = (IfState)stack.firstElement(); + if (active) { + thenSaxEventList = thenSaxEventList; + } else { + throw new IllegalStateException("setThenSaxEventList() invoked on inactive IfAction"); + } + } + + public void setElseSaxEventList(List elseSaxEventList) { + IfState state = (IfState)stack.firstElement(); + if (active) { + elseSaxEventList = elseSaxEventList; + } else { + throw new IllegalStateException("setElseSaxEventList() invoked on inactive IfAction"); + } + } + + public boolean isActive() + { + if (stack == null) return false; + if (stack.isEmpty()) return false; + return stack.peek()).active; + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/conditional/IfState.java b/src/minecraft/ch/qos/logback/core/joran/conditional/IfState.java new file mode 100644 index 0000000..99e9393 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/conditional/IfState.java @@ -0,0 +1,14 @@ +package ch.qos.logback.core.joran.conditional; + +import ch.qos.logback.core.joran.event.SaxEvent; +import java.util.List; + +class IfState +{ + Boolean boolResult; + List thenSaxEventList; + List elseSaxEventList; + boolean active; + + IfState() {} +} diff --git a/src/minecraft/ch/qos/logback/core/joran/conditional/PropertyEvalScriptBuilder.java b/src/minecraft/ch/qos/logback/core/joran/conditional/PropertyEvalScriptBuilder.java new file mode 100644 index 0000000..75e1ba3 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/conditional/PropertyEvalScriptBuilder.java @@ -0,0 +1,60 @@ +package ch.qos.logback.core.joran.conditional; + +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.spi.PropertyContainer; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; +import org.codehaus.commons.compiler.CompileException; +import org.codehaus.janino.ClassBodyEvaluator; + + + + + + + + + + + + + + + +public class PropertyEvalScriptBuilder + extends ContextAwareBase +{ + private static String SCRIPT_PREFIX = "public boolean evaluate() { return "; + + private static String SCRIPT_SUFFIX = "; }"; + final PropertyContainer localPropContainer; + + PropertyEvalScriptBuilder(PropertyContainer localPropContainer) + { + this.localPropContainer = localPropContainer; + } + + Map map = new HashMap(); + + + + + public Condition build(String script) + throws IllegalAccessException, CompileException, InstantiationException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException + { + ClassBodyEvaluator cbe = new ClassBodyEvaluator(); + cbe.setImplementedInterfaces(new Class[] { Condition.class }); + cbe.setExtendedClass(PropertyWrapperForScripts.class); + cbe.setParentClassLoader(ClassBodyEvaluator.class.getClassLoader()); + cbe.cook(SCRIPT_PREFIX + script + SCRIPT_SUFFIX); + + Class clazz = cbe.getClazz(); + Condition instance = (Condition)clazz.newInstance(); + Method setMapMethod = clazz.getMethod("setPropertyContainers", new Class[] { PropertyContainer.class, PropertyContainer.class }); + setMapMethod.invoke(instance, new Object[] { localPropContainer, context }); + + return instance; + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/conditional/PropertyWrapperForScripts.java b/src/minecraft/ch/qos/logback/core/joran/conditional/PropertyWrapperForScripts.java new file mode 100644 index 0000000..811a030 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/conditional/PropertyWrapperForScripts.java @@ -0,0 +1,51 @@ +package ch.qos.logback.core.joran.conditional; + +import ch.qos.logback.core.spi.PropertyContainer; +import ch.qos.logback.core.util.OptionHelper; + + + + + + + + + + + + +public class PropertyWrapperForScripts +{ + PropertyContainer local; + PropertyContainer context; + + public PropertyWrapperForScripts() {} + + public void setPropertyContainers(PropertyContainer local, PropertyContainer context) + { + this.local = local; + this.context = context; + } + + public boolean isNull(String k) { + String val = OptionHelper.propertyLookup(k, local, context); + return val == null; + } + + public boolean isDefined(String k) { + String val = OptionHelper.propertyLookup(k, local, context); + return val != null; + } + + public String p(String k) { + return property(k); + } + + public String property(String k) { + String val = OptionHelper.propertyLookup(k, local, context); + if (val != null) { + return val; + } + return ""; + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/conditional/ThenAction.java b/src/minecraft/ch/qos/logback/core/joran/conditional/ThenAction.java new file mode 100644 index 0000000..08471e5 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/conditional/ThenAction.java @@ -0,0 +1,26 @@ +package ch.qos.logback.core.joran.conditional; + +import ch.qos.logback.core.joran.event.SaxEvent; +import java.util.List; + + + + + + + + + + + + +public class ThenAction + extends ThenOrElseActionBase +{ + public ThenAction() {} + + void registerEventList(IfAction ifAction, List eventList) + { + ifAction.setThenSaxEventList(eventList); + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/conditional/ThenActionState.java b/src/minecraft/ch/qos/logback/core/joran/conditional/ThenActionState.java new file mode 100644 index 0000000..0964c30 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/conditional/ThenActionState.java @@ -0,0 +1,88 @@ +package ch.qos.logback.core.joran.conditional; + +import ch.qos.logback.core.joran.event.InPlayListener; +import ch.qos.logback.core.joran.event.SaxEvent; +import java.util.ArrayList; +import java.util.List; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +class ThenActionState + implements InPlayListener +{ + ThenActionState() {} + + List eventList = new ArrayList(); + boolean isRegistered = false; + + public void inPlay(SaxEvent event) { + eventList.add(event); + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/conditional/ThenOrElseActionBase.java b/src/minecraft/ch/qos/logback/core/joran/conditional/ThenOrElseActionBase.java new file mode 100644 index 0000000..da4887b --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/conditional/ThenOrElseActionBase.java @@ -0,0 +1,77 @@ +package ch.qos.logback.core.joran.conditional; + +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.event.SaxEvent; +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.InterpretationContext; +import java.util.List; +import java.util.Stack; +import org.xml.sax.Attributes; + + + + + + + + + + + + + + + + + +public abstract class ThenOrElseActionBase + extends Action +{ + Stack stateStack = new Stack(); + + public ThenOrElseActionBase() {} + + public void begin(InterpretationContext ic, String name, Attributes attributes) throws ActionException + { + if (!weAreActive(ic)) { return; + } + ThenActionState state = new ThenActionState(); + if (ic.isListenerListEmpty()) { + ic.addInPlayListener(state); + isRegistered = true; + } + stateStack.push(state); + } + + boolean weAreActive(InterpretationContext ic) { + Object o = ic.peekObject(); + if (!(o instanceof IfAction)) return false; + IfAction ifAction = (IfAction)o; + return ifAction.isActive(); + } + + public void end(InterpretationContext ic, String name) throws ActionException + { + if (!weAreActive(ic)) { return; + } + ThenActionState state = (ThenActionState)stateStack.pop(); + if (isRegistered) { + ic.removeInPlayListener(state); + Object o = ic.peekObject(); + if ((o instanceof IfAction)) { + IfAction ifAction = (IfAction)o; + removeFirstAndLastFromList(eventList); + registerEventList(ifAction, eventList); + } else { + throw new IllegalStateException("Missing IfAction on top of stack"); + } + } + } + + abstract void registerEventList(IfAction paramIfAction, List paramList); + + void removeFirstAndLastFromList(List eventList) { + eventList.remove(0); + eventList.remove(eventList.size() - 1); + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/event/BodyEvent.java b/src/minecraft/ch/qos/logback/core/joran/event/BodyEvent.java new file mode 100644 index 0000000..a640a9d --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/event/BodyEvent.java @@ -0,0 +1,49 @@ +package ch.qos.logback.core.joran.event; + +import org.xml.sax.Locator; + + + + + + + + + + + + + +public class BodyEvent + extends SaxEvent +{ + private String text; + + BodyEvent(String text, Locator locator) + { + super(null, null, null, locator); + this.text = text; + } + + + + + + public String getText() + { + if (text != null) { + return text.trim(); + } + return text; + } + + public String toString() + { + return "BodyEvent(" + getText() + ")" + locator.getLineNumber() + "," + locator.getColumnNumber(); + } + + public void append(String str) + { + text += str; + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/event/EndEvent.java b/src/minecraft/ch/qos/logback/core/joran/event/EndEvent.java new file mode 100644 index 0000000..6ef9da1 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/event/EndEvent.java @@ -0,0 +1,29 @@ +package ch.qos.logback.core.joran.event; + +import org.xml.sax.Locator; + + + + + + + + + + + + + +public class EndEvent + extends SaxEvent +{ + EndEvent(String namespaceURI, String localName, String qName, Locator locator) + { + super(namespaceURI, localName, qName, locator); + } + + public String toString() + { + return " EndEvent(" + getQName() + ") [" + locator.getLineNumber() + "," + locator.getColumnNumber() + "]"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/event/InPlayListener.java b/src/minecraft/ch/qos/logback/core/joran/event/InPlayListener.java new file mode 100644 index 0000000..4762af1 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/event/InPlayListener.java @@ -0,0 +1,6 @@ +package ch.qos.logback.core.joran.event; + +public abstract interface InPlayListener +{ + public abstract void inPlay(SaxEvent paramSaxEvent); +} diff --git a/src/minecraft/ch/qos/logback/core/joran/event/SaxEvent.java b/src/minecraft/ch/qos/logback/core/joran/event/SaxEvent.java new file mode 100644 index 0000000..9e98d6e --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/event/SaxEvent.java @@ -0,0 +1,49 @@ +package ch.qos.logback.core.joran.event; + +import org.xml.sax.Locator; +import org.xml.sax.helpers.LocatorImpl; + + + + + + + + + + + + + +public class SaxEvent +{ + public final String namespaceURI; + public final String localName; + public final String qName; + public final Locator locator; + + SaxEvent(String namespaceURI, String localName, String qName, Locator locator) + { + this.namespaceURI = namespaceURI; + this.localName = localName; + this.qName = qName; + + this.locator = new LocatorImpl(locator); + } + + public String getLocalName() { + return localName; + } + + public Locator getLocator() { + return locator; + } + + public String getNamespaceURI() { + return namespaceURI; + } + + public String getQName() { + return qName; + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/event/SaxEventRecorder.java b/src/minecraft/ch/qos/logback/core/joran/event/SaxEventRecorder.java new file mode 100644 index 0000000..8d91858 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/event/SaxEventRecorder.java @@ -0,0 +1,208 @@ +package ch.qos.logback.core.joran.event; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.joran.spi.ElementPath; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.spi.ContextAware; +import ch.qos.logback.core.spi.ContextAwareImpl; +import ch.qos.logback.core.status.Status; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.helpers.DefaultHandler; + + + + + + + + + + + + + + + + + +public class SaxEventRecorder + extends DefaultHandler + implements ContextAware +{ + final ContextAwareImpl cai; + + public SaxEventRecorder(Context context) + { + cai = new ContextAwareImpl(context, this); + } + + public List saxEventList = new ArrayList(); + Locator locator; + ElementPath globalElementPath = new ElementPath(); + + public final void recordEvents(InputStream inputStream) throws JoranException { + recordEvents(new InputSource(inputStream)); + } + + public List recordEvents(InputSource inputSource) throws JoranException + { + SAXParser saxParser = buildSaxParser(); + try { + saxParser.parse(inputSource, this); + return saxEventList; + } catch (IOException ie) { + handleError("I/O error occurred while parsing xml file", ie); + } + catch (SAXException se) { + throw new JoranException("Problem parsing XML document. See previously reported errors.", se); + } catch (Exception ex) { + handleError("Unexpected exception while parsing XML document.", ex); + } + throw new IllegalStateException("This point can never be reached"); + } + + private void handleError(String errMsg, Throwable t) throws JoranException { + addError(errMsg, t); + throw new JoranException(errMsg, t); + } + + private SAXParser buildSaxParser() throws JoranException { + try { + SAXParserFactory spf = SAXParserFactory.newInstance(); + spf.setValidating(false); + spf.setNamespaceAware(true); + return spf.newSAXParser(); + } catch (Exception pce) { + String errMsg = "Parser configuration error occurred"; + addError(errMsg, pce); + throw new JoranException(errMsg, pce); + } + } + + public void startDocument() {} + + public Locator getLocator() + { + return locator; + } + + public void setDocumentLocator(Locator l) { + locator = l; + } + + + public void startElement(String namespaceURI, String localName, String qName, Attributes atts) + { + String tagName = getTagName(localName, qName); + globalElementPath.push(tagName); + ElementPath current = globalElementPath.duplicate(); + saxEventList.add(new StartEvent(current, namespaceURI, localName, qName, atts, getLocator())); + } + + public void characters(char[] ch, int start, int length) + { + String bodyStr = new String(ch, start, length); + SaxEvent lastEvent = getLastEvent(); + if ((lastEvent instanceof BodyEvent)) { + BodyEvent be = (BodyEvent)lastEvent; + be.append(bodyStr); + + } + else if (!isSpaceOnly(bodyStr)) { + saxEventList.add(new BodyEvent(bodyStr, getLocator())); + } + } + + boolean isSpaceOnly(String bodyStr) + { + String bodyTrimmed = bodyStr.trim(); + return bodyTrimmed.length() == 0; + } + + SaxEvent getLastEvent() { + if (saxEventList.isEmpty()) { + return null; + } + int size = saxEventList.size(); + return (SaxEvent)saxEventList.get(size - 1); + } + + public void endElement(String namespaceURI, String localName, String qName) { + saxEventList.add(new EndEvent(namespaceURI, localName, qName, getLocator())); + + globalElementPath.pop(); + } + + String getTagName(String localName, String qName) { + String tagName = localName; + if ((tagName == null) || (tagName.length() < 1)) { + tagName = qName; + } + return tagName; + } + + public void error(SAXParseException spe) throws SAXException { + addError("XML_PARSING - Parsing error on line " + spe.getLineNumber() + " and column " + spe.getColumnNumber(), spe); + } + + public void fatalError(SAXParseException spe) throws SAXException + { + addError("XML_PARSING - Parsing fatal error on line " + spe.getLineNumber() + " and column " + spe.getColumnNumber(), spe); + } + + public void warning(SAXParseException spe) throws SAXException + { + addWarn("XML_PARSING - Parsing warning on line " + spe.getLineNumber() + " and column " + spe.getColumnNumber(), spe); + } + + public void addError(String msg) + { + cai.addError(msg); + } + + public void addError(String msg, Throwable ex) { + cai.addError(msg, ex); + } + + public void addInfo(String msg) { + cai.addInfo(msg); + } + + public void addInfo(String msg, Throwable ex) { + cai.addInfo(msg, ex); + } + + public void addStatus(Status status) { + cai.addStatus(status); + } + + public void addWarn(String msg) { + cai.addWarn(msg); + } + + public void addWarn(String msg, Throwable ex) { + cai.addWarn(msg, ex); + } + + public Context getContext() { + return cai.getContext(); + } + + public void setContext(Context context) { + cai.setContext(context); + } + + public List getSaxEventList() { + return saxEventList; + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/event/StartEvent.java b/src/minecraft/ch/qos/logback/core/joran/event/StartEvent.java new file mode 100644 index 0000000..0bf0d10 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/event/StartEvent.java @@ -0,0 +1,43 @@ +package ch.qos.logback.core.joran.event; + +import ch.qos.logback.core.joran.spi.ElementPath; +import org.xml.sax.Attributes; +import org.xml.sax.Locator; +import org.xml.sax.helpers.AttributesImpl; + + + + + + + + + + + + + +public class StartEvent + extends SaxEvent +{ + public final Attributes attributes; + public final ElementPath elementPath; + + StartEvent(ElementPath elementPath, String namespaceURI, String localName, String qName, Attributes attributes, Locator locator) + { + super(namespaceURI, localName, qName, locator); + + this.attributes = new AttributesImpl(attributes); + this.elementPath = elementPath; + } + + public Attributes getAttributes() { + return attributes; + } + + + public String toString() + { + return "StartEvent(" + getQName() + ") [" + locator.getLineNumber() + "," + locator.getColumnNumber() + "]"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/event/stax/BodyEvent.java b/src/minecraft/ch/qos/logback/core/joran/event/stax/BodyEvent.java new file mode 100644 index 0000000..cb9dcf3 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/event/stax/BodyEvent.java @@ -0,0 +1,40 @@ +package ch.qos.logback.core.joran.event.stax; + +import javax.xml.stream.Location; + + + + + + + + + + + + + +public class BodyEvent + extends StaxEvent +{ + private String text; + + BodyEvent(String text, Location location) + { + super(null, location); + this.text = text; + } + + public String getText() { + return text; + } + + void append(String txt) { + text += txt; + } + + public String toString() + { + return "BodyEvent(" + getText() + ")" + location.getLineNumber() + "," + location.getColumnNumber(); + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/event/stax/EndEvent.java b/src/minecraft/ch/qos/logback/core/joran/event/stax/EndEvent.java new file mode 100644 index 0000000..019d11c --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/event/stax/EndEvent.java @@ -0,0 +1,35 @@ +package ch.qos.logback.core.joran.event.stax; + +import javax.xml.stream.Location; + + + + + + + + + + + + + + + + + + + +public class EndEvent + extends StaxEvent +{ + public EndEvent(String name, Location location) + { + super(name, location); + } + + public String toString() + { + return "EndEvent(" + getName() + ") [" + location.getLineNumber() + "," + location.getColumnNumber() + "]"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/event/stax/StartEvent.java b/src/minecraft/ch/qos/logback/core/joran/event/stax/StartEvent.java new file mode 100644 index 0000000..297918d --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/event/stax/StartEvent.java @@ -0,0 +1,67 @@ +package ch.qos.logback.core.joran.event.stax; + +import ch.qos.logback.core.joran.spi.ElementPath; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.events.Attribute; + + + + + + + + + + + + +public class StartEvent + extends StaxEvent +{ + List attributes; + public ElementPath elementPath; + + StartEvent(ElementPath elementPath, String name, Iterator attributeIterator, Location location) + { + super(name, location); + populateAttributes(attributeIterator); + this.elementPath = elementPath; + } + + private void populateAttributes(Iterator attributeIterator) { + while (attributeIterator.hasNext()) { + if (attributes == null) { + attributes = new ArrayList(2); + } + attributes.add(attributeIterator.next()); + } + } + + public ElementPath getElementPath() { + return elementPath; + } + + public List getAttributeList() { + return attributes; + } + + Attribute getAttributeByName(String name) { + if (attributes == null) { + return null; + } + for (Attribute attr : attributes) { + if (name.equals(attr.getName().getLocalPart())) + return attr; + } + return null; + } + + public String toString() + { + return "StartEvent(" + getName() + ") [" + location.getLineNumber() + "," + location.getColumnNumber() + "]"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/event/stax/StaxEvent.java b/src/minecraft/ch/qos/logback/core/joran/event/stax/StaxEvent.java new file mode 100644 index 0000000..7f0fb3a --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/event/stax/StaxEvent.java @@ -0,0 +1,37 @@ +package ch.qos.logback.core.joran.event.stax; + +import javax.xml.stream.Location; + + + + + + + + + + + + + + +public class StaxEvent +{ + final String name; + final Location location; + + StaxEvent(String name, Location location) + { + this.name = name; + this.location = location; + } + + public String getName() + { + return name; + } + + public Location getLocation() { + return location; + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/event/stax/StaxEventRecorder.java b/src/minecraft/ch/qos/logback/core/joran/event/stax/StaxEventRecorder.java new file mode 100644 index 0000000..a9eedf3 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/event/stax/StaxEventRecorder.java @@ -0,0 +1,115 @@ +package ch.qos.logback.core.joran.event.stax; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.joran.spi.ElementPath; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.spi.ContextAwareBase; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.Characters; +import javax.xml.stream.events.EndElement; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + + + + + + + + + + + + + +public class StaxEventRecorder + extends ContextAwareBase +{ + List eventList = new ArrayList(); + ElementPath globalElementPath = new ElementPath(); + + public StaxEventRecorder(Context context) { + setContext(context); + } + + public void recordEvents(InputStream inputStream) throws JoranException { + try { + XMLEventReader xmlEventReader = XMLInputFactory.newInstance().createXMLEventReader(inputStream); + read(xmlEventReader); + } catch (XMLStreamException e) { + throw new JoranException("Problem parsing XML document. See previously reported errors.", e); + } + } + + public List getEventList() { + return eventList; + } + + private void read(XMLEventReader xmlEventReader) throws XMLStreamException { + while (xmlEventReader.hasNext()) { + XMLEvent xmlEvent = xmlEventReader.nextEvent(); + switch (xmlEvent.getEventType()) { + case 1: + addStartElement(xmlEvent); + break; + case 4: + addCharacters(xmlEvent); + break; + case 2: + addEndEvent(xmlEvent); + } + + } + } + + + private void addStartElement(XMLEvent xmlEvent) + { + StartElement se = xmlEvent.asStartElement(); + String tagName = se.getName().getLocalPart(); + globalElementPath.push(tagName); + ElementPath current = globalElementPath.duplicate(); + StartEvent startEvent = new StartEvent(current, tagName, se.getAttributes(), se.getLocation()); + eventList.add(startEvent); + } + + private void addCharacters(XMLEvent xmlEvent) { + Characters characters = xmlEvent.asCharacters(); + StaxEvent lastEvent = getLastEvent(); + + if ((lastEvent instanceof BodyEvent)) { + BodyEvent be = (BodyEvent)lastEvent; + be.append(characters.getData()); + + } + else if (!characters.isWhiteSpace()) { + BodyEvent bodyEvent = new BodyEvent(characters.getData(), xmlEvent.getLocation()); + eventList.add(bodyEvent); + } + } + + private void addEndEvent(XMLEvent xmlEvent) + { + EndElement ee = xmlEvent.asEndElement(); + String tagName = ee.getName().getLocalPart(); + EndEvent endEvent = new EndEvent(tagName, ee.getLocation()); + eventList.add(endEvent); + globalElementPath.pop(); + } + + StaxEvent getLastEvent() { + if (eventList.isEmpty()) { + return null; + } + int size = eventList.size(); + if (size == 0) + return null; + return (StaxEvent)eventList.get(size - 1); + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/node/ComponentNode.java b/src/minecraft/ch/qos/logback/core/joran/node/ComponentNode.java new file mode 100644 index 0000000..69ef72f --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/node/ComponentNode.java @@ -0,0 +1,8 @@ +package ch.qos.logback.core.joran.node; + +public class ComponentNode +{ + String classStr; + + public ComponentNode() {} +} diff --git a/src/minecraft/ch/qos/logback/core/joran/spi/ActionException.java b/src/minecraft/ch/qos/logback/core/joran/spi/ActionException.java new file mode 100644 index 0000000..3be9d6e --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/spi/ActionException.java @@ -0,0 +1,35 @@ +package ch.qos.logback.core.joran.spi; + + + + + + + + +public class ActionException + extends Exception +{ + private static final long serialVersionUID = 2743349809995319806L; + + + + + + + + + public ActionException() {} + + + + + + + + + public ActionException(Throwable rootCause) + { + super(rootCause); + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/spi/CAI_WithLocatorSupport.java b/src/minecraft/ch/qos/logback/core/joran/spi/CAI_WithLocatorSupport.java new file mode 100644 index 0000000..436bb00 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/spi/CAI_WithLocatorSupport.java @@ -0,0 +1,357 @@ +package ch.qos.logback.core.joran.spi; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.spi.ContextAwareImpl; +import org.xml.sax.Locator; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +class CAI_WithLocatorSupport + extends ContextAwareImpl +{ + CAI_WithLocatorSupport(Context context, Interpreter interpreter) + { + super(context, interpreter); + } + + protected Object getOrigin() + { + Interpreter i = (Interpreter)super.getOrigin(); + Locator locator = locator; + if (locator != null) { + return Interpreter.class.getName() + "@" + locator.getLineNumber() + ":" + locator.getColumnNumber(); + } + + return Interpreter.class.getName() + "@NA:NA"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/spi/ConfigurationWatchList.java b/src/minecraft/ch/qos/logback/core/joran/spi/ConfigurationWatchList.java new file mode 100644 index 0000000..bc12f24 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/spi/ConfigurationWatchList.java @@ -0,0 +1,93 @@ +package ch.qos.logback.core.joran.spi; + +import ch.qos.logback.core.spi.ContextAwareBase; +import java.io.File; +import java.net.URL; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.List; + + + + + + + + + + + + + + + +public class ConfigurationWatchList + extends ContextAwareBase +{ + URL mainURL; + + public ConfigurationWatchList() {} + + List fileWatchList = new ArrayList(); + List lastModifiedList = new ArrayList(); + + public void clear() { + mainURL = null; + lastModifiedList.clear(); + fileWatchList.clear(); + } + + + + + + public void setMainURL(URL mainURL) + { + this.mainURL = mainURL; + if (mainURL != null) + addAsFileToWatch(mainURL); + } + + private void addAsFileToWatch(URL url) { + File file = convertToFile(url); + if (file != null) { + fileWatchList.add(file); + lastModifiedList.add(Long.valueOf(file.lastModified())); + } + } + + public void addToWatchList(URL url) { + addAsFileToWatch(url); + } + + public URL getMainURL() { + return mainURL; + } + + public List getCopyOfFileWatchList() { + return new ArrayList(fileWatchList); + } + + public boolean changeDetected() { + int len = fileWatchList.size(); + for (int i = 0; i < len; i++) { + long lastModified = ((Long)lastModifiedList.get(i)).longValue(); + File file = (File)fileWatchList.get(i); + if (lastModified != file.lastModified()) { + return true; + } + } + return false; + } + + + File convertToFile(URL url) + { + String protocol = url.getProtocol(); + if ("file".equals(protocol)) { + return new File(URLDecoder.decode(url.getFile())); + } + addInfo("URL [" + url + "] is not of type file"); + return null; + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/spi/ConsoleTarget.java b/src/minecraft/ch/qos/logback/core/joran/spi/ConsoleTarget.java new file mode 100644 index 0000000..ae1a8c4 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/spi/ConsoleTarget.java @@ -0,0 +1,91 @@ +package ch.qos.logback.core.joran.spi; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; + + + + + + + + + + + + + + + + + + + + + +public enum ConsoleTarget +{ + SystemOut("System.out", new OutputStream()), + + + + + + + + + + + + + + + + + + + SystemErr("System.err", new OutputStream()); + + + + + + + private final String name; + + + + + private final OutputStream stream; + + + + + + public static ConsoleTarget findByName(String name) + { + for (ConsoleTarget target : ) { + if (name.equalsIgnoreCase(name)) { + return target; + } + } + return null; + } + + + + private ConsoleTarget(String name, OutputStream stream) + { + this.name = name; + this.stream = stream; + } + + public String getName() { + return name; + } + + public OutputStream getStream() { + return stream; + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/spi/DefaultClass.java b/src/minecraft/ch/qos/logback/core/joran/spi/DefaultClass.java new file mode 100644 index 0000000..f7559e0 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/spi/DefaultClass.java @@ -0,0 +1,13 @@ +package ch.qos.logback.core.joran.spi; + +import java.lang.annotation.Annotation; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({java.lang.annotation.ElementType.METHOD}) +public @interface DefaultClass +{ + Class value(); +} diff --git a/src/minecraft/ch/qos/logback/core/joran/spi/DefaultNestedComponentRegistry.java b/src/minecraft/ch/qos/logback/core/joran/spi/DefaultNestedComponentRegistry.java new file mode 100644 index 0000000..964a933 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/spi/DefaultNestedComponentRegistry.java @@ -0,0 +1,52 @@ +package ch.qos.logback.core.joran.spi; + +import java.util.HashMap; +import java.util.Map; + + + + + + + + + + + + + + + + + + +public class DefaultNestedComponentRegistry +{ + public DefaultNestedComponentRegistry() {} + + Map> defaultComponentMap = new HashMap(); + + public void add(Class hostClass, String propertyName, Class componentClass) { + HostClassAndPropertyDouble hpDouble = new HostClassAndPropertyDouble(hostClass, propertyName.toLowerCase()); + + defaultComponentMap.put(hpDouble, componentClass); + } + + public Class findDefaultComponentType(Class hostClass, String propertyName) { + propertyName = propertyName.toLowerCase(); + while (hostClass != null) { + Class componentClass = oneShotFind(hostClass, propertyName); + if (componentClass != null) { + return componentClass; + } + hostClass = hostClass.getSuperclass(); + } + return null; + } + + private Class oneShotFind(Class hostClass, String propertyName) { + HostClassAndPropertyDouble hpDouble = new HostClassAndPropertyDouble(hostClass, propertyName); + + return (Class)defaultComponentMap.get(hpDouble); + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/spi/ElementPath.java b/src/minecraft/ch/qos/logback/core/joran/spi/ElementPath.java new file mode 100644 index 0000000..05f5f97 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/spi/ElementPath.java @@ -0,0 +1,135 @@ +package ch.qos.logback.core.joran.spi; + +import java.util.ArrayList; +import java.util.List; + + + + + + + + + + + + + + + + + + + + +public class ElementPath +{ + ArrayList partList = new ArrayList(); + + public ElementPath() {} + + public ElementPath(List list) + { + partList.addAll(list); + } + + + + + + public ElementPath(String pathStr) + { + if (pathStr == null) { + return; + } + + String[] partArray = pathStr.split("/"); + if (partArray == null) { return; + } + for (String part : partArray) { + if (part.length() > 0) { + partList.add(part); + } + } + } + + public ElementPath duplicate() { + ElementPath p = new ElementPath(); + partList.addAll(partList); + return p; + } + + + public boolean equals(Object o) + { + if ((o == null) || (!(o instanceof ElementPath))) { + return false; + } + + ElementPath r = (ElementPath)o; + + if (r.size() != size()) { + return false; + } + + int len = size(); + + for (int i = 0; i < len; i++) { + if (!equalityCheck(get(i), r.get(i))) { + return false; + } + } + + + return true; + } + + private boolean equalityCheck(String x, String y) { + return x.equalsIgnoreCase(y); + } + + public List getCopyOfPartList() { + return new ArrayList(partList); + } + + public void push(String s) { + partList.add(s); + } + + public String get(int i) { + return (String)partList.get(i); + } + + public void pop() { + if (!partList.isEmpty()) { + partList.remove(partList.size() - 1); + } + } + + public String peekLast() { + if (!partList.isEmpty()) { + int size = partList.size(); + return (String)partList.get(size - 1); + } + return null; + } + + public int size() + { + return partList.size(); + } + + protected String toStableString() + { + StringBuilder result = new StringBuilder(); + for (String current : partList) { + result.append("[").append(current).append("]"); + } + return result.toString(); + } + + public String toString() + { + return toStableString(); + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/spi/ElementSelector.java b/src/minecraft/ch/qos/logback/core/joran/spi/ElementSelector.java new file mode 100644 index 0000000..c077814 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/spi/ElementSelector.java @@ -0,0 +1,181 @@ +package ch.qos.logback.core.joran.spi; + +import java.util.ArrayList; +import java.util.List; + + + + + + + + + + + + + + + + + + + + + + + +public class ElementSelector + extends ElementPath +{ + public ElementSelector() {} + + public ElementSelector(List list) + { + super(list); + } + + + + + + + public ElementSelector(String p) + { + super(p); + } + + public boolean fullPathMatch(ElementPath path) { + if (path.size() != size()) { + return false; + } + + int len = size(); + for (int i = 0; i < len; i++) { + if (!equalityCheck(get(i), path.get(i))) { + return false; + } + } + + return true; + } + + + + + + public int getTailMatchLength(ElementPath p) + { + if (p == null) { + return 0; + } + + int lSize = partList.size(); + int rSize = partList.size(); + + + if ((lSize == 0) || (rSize == 0)) { + return 0; + } + + int minLen = lSize <= rSize ? lSize : rSize; + int match = 0; + + + for (int i = 1; i <= minLen; i++) { + String l = (String)partList.get(lSize - i); + String r = (String)partList.get(rSize - i); + + if (!equalityCheck(l, r)) break; + match++; + } + + + + return match; + } + + public boolean isContainedIn(ElementPath p) { + if (p == null) { + return false; + } + return p.toStableString().contains(toStableString()); + } + + + + + + + public int getPrefixMatchLength(ElementPath p) + { + if (p == null) { + return 0; + } + + int lSize = partList.size(); + int rSize = partList.size(); + + + if ((lSize == 0) || (rSize == 0)) { + return 0; + } + + int minLen = lSize <= rSize ? lSize : rSize; + int match = 0; + + for (int i = 0; i < minLen; i++) { + String l = (String)partList.get(i); + String r = (String)partList.get(i); + + if (!equalityCheck(l, r)) break; + match++; + } + + + + + return match; + } + + private boolean equalityCheck(String x, String y) { + return x.equalsIgnoreCase(y); + } + + public boolean equals(Object o) + { + if ((o == null) || (!(o instanceof ElementSelector))) { + return false; + } + + ElementSelector r = (ElementSelector)o; + + if (r.size() != size()) { + return false; + } + + int len = size(); + + for (int i = 0; i < len; i++) { + if (!equalityCheck(get(i), r.get(i))) { + return false; + } + } + + + return true; + } + + public int hashCode() + { + int hc = 0; + int len = size(); + + for (int i = 0; i < len; i++) + { + + hc ^= get(i).toLowerCase().hashCode(); + } + return hc; + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/spi/EventPlayer.java b/src/minecraft/ch/qos/logback/core/joran/spi/EventPlayer.java new file mode 100644 index 0000000..13706c1 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/spi/EventPlayer.java @@ -0,0 +1,71 @@ +package ch.qos.logback.core.joran.spi; + +import ch.qos.logback.core.joran.event.BodyEvent; +import ch.qos.logback.core.joran.event.EndEvent; +import ch.qos.logback.core.joran.event.SaxEvent; +import ch.qos.logback.core.joran.event.StartEvent; +import java.util.ArrayList; +import java.util.List; + + + + + + + + + + + + + + +public class EventPlayer +{ + final Interpreter interpreter; + List eventList; + int currentIndex; + + public EventPlayer(Interpreter interpreter) + { + this.interpreter = interpreter; + } + + + + + + public List getCopyOfPlayerEventList() + { + return new ArrayList(eventList); + } + + public void play(List aSaxEventList) { + eventList = aSaxEventList; + + for (currentIndex = 0; currentIndex < eventList.size(); currentIndex += 1) { + SaxEvent se = (SaxEvent)eventList.get(currentIndex); + + if ((se instanceof StartEvent)) { + interpreter.startElement((StartEvent)se); + + interpreter.getInterpretationContext().fireInPlay(se); + } + if ((se instanceof BodyEvent)) + { + interpreter.getInterpretationContext().fireInPlay(se); + interpreter.characters((BodyEvent)se); + } + if ((se instanceof EndEvent)) + { + interpreter.getInterpretationContext().fireInPlay(se); + interpreter.endElement((EndEvent)se); + } + } + } + + public void addEventsDynamically(List eventList, int offset) + { + this.eventList.addAll(currentIndex + offset, eventList); + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/spi/HostClassAndPropertyDouble.java b/src/minecraft/ch/qos/logback/core/joran/spi/HostClassAndPropertyDouble.java new file mode 100644 index 0000000..4a85dca --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/spi/HostClassAndPropertyDouble.java @@ -0,0 +1,75 @@ +package ch.qos.logback.core.joran.spi; + + + + + + + + + +public class HostClassAndPropertyDouble +{ + final Class hostClass; + + + + + + + + final String propertyName; + + + + + + + + + public HostClassAndPropertyDouble(Class hostClass, String propertyName) + { + this.hostClass = hostClass; + this.propertyName = propertyName; + } + + public Class getHostClass() { + return hostClass; + } + + public String getPropertyName() { + return propertyName; + } + + public int hashCode() + { + int prime = 31; + int result = 1; + result = 31 * result + (hostClass == null ? 0 : hostClass.hashCode()); + result = 31 * result + (propertyName == null ? 0 : propertyName.hashCode()); + + return result; + } + + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + HostClassAndPropertyDouble other = (HostClassAndPropertyDouble)obj; + if (hostClass == null) { + if (hostClass != null) + return false; + } else if (!hostClass.equals(hostClass)) + return false; + if (propertyName == null) { + if (propertyName != null) + return false; + } else if (!propertyName.equals(propertyName)) + return false; + return true; + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/spi/InterpretationContext.java b/src/minecraft/ch/qos/logback/core/joran/spi/InterpretationContext.java new file mode 100644 index 0000000..3864153 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/spi/InterpretationContext.java @@ -0,0 +1,186 @@ +package ch.qos.logback.core.joran.spi; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.joran.event.InPlayListener; +import ch.qos.logback.core.joran.event.SaxEvent; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.spi.PropertyContainer; +import ch.qos.logback.core.util.OptionHelper; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Stack; +import org.xml.sax.Locator; + + + + + + + + + + + + + + + + + + + + + + + + +public class InterpretationContext + extends ContextAwareBase + implements PropertyContainer +{ + Stack objectStack; + Map objectMap; + Map propertiesMap; + Interpreter joranInterpreter; + final List listenerList = new ArrayList(); + DefaultNestedComponentRegistry defaultNestedComponentRegistry = new DefaultNestedComponentRegistry(); + + public InterpretationContext(Context context, Interpreter joranInterpreter) { + this.context = context; + this.joranInterpreter = joranInterpreter; + objectStack = new Stack(); + objectMap = new HashMap(5); + propertiesMap = new HashMap(5); + } + + public DefaultNestedComponentRegistry getDefaultNestedComponentRegistry() + { + return defaultNestedComponentRegistry; + } + + public Map getCopyOfPropertyMap() { + return new HashMap(propertiesMap); + } + + void setPropertiesMap(Map propertiesMap) { + this.propertiesMap = propertiesMap; + } + + String updateLocationInfo(String msg) { + Locator locator = joranInterpreter.getLocator(); + + if (locator != null) { + return msg + locator.getLineNumber() + ":" + locator.getColumnNumber(); + } + return msg; + } + + public Locator getLocator() + { + return joranInterpreter.getLocator(); + } + + public Interpreter getJoranInterpreter() { + return joranInterpreter; + } + + public Stack getObjectStack() { + return objectStack; + } + + public boolean isEmpty() { + return objectStack.isEmpty(); + } + + public Object peekObject() { + return objectStack.peek(); + } + + public void pushObject(Object o) { + objectStack.push(o); + } + + public Object popObject() { + return objectStack.pop(); + } + + public Object getObject(int i) { + return objectStack.get(i); + } + + public Map getObjectMap() { + return objectMap; + } + + + + + public void addSubstitutionProperty(String key, String value) + { + if ((key == null) || (value == null)) { + return; + } + + value = value.trim(); + propertiesMap.put(key, value); + } + + public void addSubstitutionProperties(Properties props) { + if (props == null) { + return; + } + for (Object keyObject : props.keySet()) { + String key = (String)keyObject; + String val = props.getProperty(key); + addSubstitutionProperty(key, val); + } + } + + + + + public String getProperty(String key) + { + String v = (String)propertiesMap.get(key); + if (v != null) { + return v; + } + return context.getProperty(key); + } + + public String subst(String value) + { + if (value == null) { + return null; + } + return OptionHelper.substVars(value, this, context); + } + + + + public boolean isListenerListEmpty() + { + return listenerList.isEmpty(); + } + + public void addInPlayListener(InPlayListener ipl) { + if (listenerList.contains(ipl)) { + addWarn("InPlayListener " + ipl + " has been already registered"); + } else { + listenerList.add(ipl); + } + } + + public boolean removeInPlayListener(InPlayListener ipl) { + return listenerList.remove(ipl); + } + + void fireInPlay(SaxEvent event) { + for (InPlayListener ipl : listenerList) { + ipl.inPlay(event); + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/spi/Interpreter.java b/src/minecraft/ch/qos/logback/core/joran/spi/Interpreter.java new file mode 100644 index 0000000..c8ec70c --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/spi/Interpreter.java @@ -0,0 +1,332 @@ +package ch.qos.logback.core.joran.spi; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.joran.action.ImplicitAction; +import ch.qos.logback.core.joran.event.BodyEvent; +import ch.qos.logback.core.joran.event.EndEvent; +import ch.qos.logback.core.joran.event.StartEvent; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Stack; +import java.util.Vector; +import org.xml.sax.Attributes; +import org.xml.sax.Locator; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class Interpreter +{ + private static List EMPTY_LIST = new Vector(0); + + + private final RuleStore ruleStore; + + + private final InterpretationContext interpretationContext; + + + private final ArrayList implicitActions; + + + private final CAI_WithLocatorSupport cai; + + + private ElementPath elementPath; + + + Locator locator; + + EventPlayer eventPlayer; + + Stack> actionListStack; + + ElementPath skip = null; + + public Interpreter(Context context, RuleStore rs, ElementPath initialElementPath) { + cai = new CAI_WithLocatorSupport(context, this); + ruleStore = rs; + interpretationContext = new InterpretationContext(context, this); + implicitActions = new ArrayList(3); + elementPath = initialElementPath; + actionListStack = new Stack(); + eventPlayer = new EventPlayer(this); + } + + public EventPlayer getEventPlayer() { + return eventPlayer; + } + + public void setInterpretationContextPropertiesMap(Map propertiesMap) + { + interpretationContext.setPropertiesMap(propertiesMap); + } + + /** + * @deprecated + */ + public InterpretationContext getExecutionContext() { + return getInterpretationContext(); + } + + public InterpretationContext getInterpretationContext() { + return interpretationContext; + } + + public void startDocument() {} + + public void startElement(StartEvent se) + { + setDocumentLocator(se.getLocator()); + startElement(namespaceURI, localName, qName, attributes); + } + + + private void startElement(String namespaceURI, String localName, String qName, Attributes atts) + { + String tagName = getTagName(localName, qName); + elementPath.push(tagName); + + if (skip != null) + { + pushEmptyActionList(); + return; + } + + List applicableActionList = getApplicableActionList(elementPath, atts); + if (applicableActionList != null) { + actionListStack.add(applicableActionList); + callBeginAction(applicableActionList, tagName, atts); + } + else { + pushEmptyActionList(); + String errMsg = "no applicable action for [" + tagName + "], current ElementPath is [" + elementPath + "]"; + + cai.addError(errMsg); + } + } + + + + private void pushEmptyActionList() + { + actionListStack.add(EMPTY_LIST); + } + + public void characters(BodyEvent be) + { + setDocumentLocator(locator); + + String body = be.getText(); + List applicableActionList = (List)actionListStack.peek(); + + if (body != null) { + body = body.trim(); + if (body.length() > 0) + { + callBodyAction(applicableActionList, body); + } + } + } + + public void endElement(EndEvent endEvent) { + setDocumentLocator(locator); + endElement(namespaceURI, localName, qName); + } + + + + private void endElement(String namespaceURI, String localName, String qName) + { + List applicableActionList = (List)actionListStack.pop(); + + if (skip != null) { + if (skip.equals(elementPath)) { + skip = null; + } + } else if (applicableActionList != EMPTY_LIST) { + callEndAction(applicableActionList, getTagName(localName, qName)); + } + + + elementPath.pop(); + } + + public Locator getLocator() { + return locator; + } + + public void setDocumentLocator(Locator l) { + locator = l; + } + + String getTagName(String localName, String qName) { + String tagName = localName; + + if ((tagName == null) || (tagName.length() < 1)) { + tagName = qName; + } + + return tagName; + } + + public void addImplicitAction(ImplicitAction ia) { + implicitActions.add(ia); + } + + + + + + + List lookupImplicitAction(ElementPath elementPath, Attributes attributes, InterpretationContext ec) + { + int len = implicitActions.size(); + + for (int i = 0; i < len; i++) { + ImplicitAction ia = (ImplicitAction)implicitActions.get(i); + + if (ia.isApplicable(elementPath, attributes, ec)) { + List actionList = new ArrayList(1); + actionList.add(ia); + + return actionList; + } + } + + return null; + } + + + + List getApplicableActionList(ElementPath elementPath, Attributes attributes) + { + List applicableActionList = ruleStore.matchActions(elementPath); + + + if (applicableActionList == null) { + applicableActionList = lookupImplicitAction(elementPath, attributes, interpretationContext); + } + + + return applicableActionList; + } + + void callBeginAction(List applicableActionList, String tagName, Attributes atts) + { + if (applicableActionList == null) { + return; + } + + Iterator i = applicableActionList.iterator(); + while (i.hasNext()) { + Action action = (Action)i.next(); + + try + { + action.begin(interpretationContext, tagName, atts); + } catch (ActionException e) { + skip = elementPath.duplicate(); + cai.addError("ActionException in Action for tag [" + tagName + "]", e); + } catch (RuntimeException e) { + skip = elementPath.duplicate(); + cai.addError("RuntimeException in Action for tag [" + tagName + "]", e); + } + } + } + + private void callBodyAction(List applicableActionList, String body) { + if (applicableActionList == null) { + return; + } + Iterator i = applicableActionList.iterator(); + + while (i.hasNext()) { + Action action = (Action)i.next(); + try { + action.body(interpretationContext, body); + } catch (ActionException ae) { + cai.addError("Exception in end() methd for action [" + action + "]", ae); + } + } + } + + + private void callEndAction(List applicableActionList, String tagName) + { + if (applicableActionList == null) { + return; + } + + + Iterator i = applicableActionList.iterator(); + + while (i.hasNext()) { + Action action = (Action)i.next(); + + try + { + action.end(interpretationContext, tagName); + } + catch (ActionException ae) + { + cai.addError("ActionException in Action for tag [" + tagName + "]", ae); + } + catch (RuntimeException e) { + cai.addError("RuntimeException in Action for tag [" + tagName + "]", e); + } + } + } + + public RuleStore getRuleStore() { + return ruleStore; + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/spi/JoranException.java b/src/minecraft/ch/qos/logback/core/joran/spi/JoranException.java new file mode 100644 index 0000000..0ce8139 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/spi/JoranException.java @@ -0,0 +1,27 @@ +package ch.qos.logback.core.joran.spi; + + + + + + + +public class JoranException + extends Exception +{ + private static final long serialVersionUID = 1112493363728774021L; + + + + + + + public JoranException(String msg) + { + super(msg); + } + + public JoranException(String msg, Throwable cause) { + super(msg, cause); + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/spi/NoAutoStart.java b/src/minecraft/ch/qos/logback/core/joran/spi/NoAutoStart.java new file mode 100644 index 0000000..b16c075 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/spi/NoAutoStart.java @@ -0,0 +1,10 @@ +package ch.qos.logback.core.joran.spi; + +import java.lang.annotation.Annotation; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({java.lang.annotation.ElementType.TYPE}) +public @interface NoAutoStart {} diff --git a/src/minecraft/ch/qos/logback/core/joran/spi/NoAutoStartUtil.java b/src/minecraft/ch/qos/logback/core/joran/spi/NoAutoStartUtil.java new file mode 100644 index 0000000..9e58b1b --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/spi/NoAutoStartUtil.java @@ -0,0 +1,33 @@ +package ch.qos.logback.core.joran.spi; + + + + + + + + + + +public class NoAutoStartUtil +{ + public NoAutoStartUtil() {} + + + + + + + + + + public static boolean notMarkedWithNoAutoStart(Object o) + { + if (o == null) { + return false; + } + Class clazz = o.getClass(); + NoAutoStart a = (NoAutoStart)clazz.getAnnotation(NoAutoStart.class); + return a == null; + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/spi/RuleStore.java b/src/minecraft/ch/qos/logback/core/joran/spi/RuleStore.java new file mode 100644 index 0000000..14fcff9 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/spi/RuleStore.java @@ -0,0 +1,14 @@ +package ch.qos.logback.core.joran.spi; + +import ch.qos.logback.core.joran.action.Action; +import java.util.List; + +public abstract interface RuleStore +{ + public abstract void addRule(ElementSelector paramElementSelector, String paramString) + throws ClassNotFoundException; + + public abstract void addRule(ElementSelector paramElementSelector, Action paramAction); + + public abstract List matchActions(ElementPath paramElementPath); +} diff --git a/src/minecraft/ch/qos/logback/core/joran/spi/SimpleRuleStore.java b/src/minecraft/ch/qos/logback/core/joran/spi/SimpleRuleStore.java new file mode 100644 index 0000000..f80375f --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/spi/SimpleRuleStore.java @@ -0,0 +1,209 @@ +package ch.qos.logback.core.joran.spi; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.joran.action.Action; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.util.OptionHelper; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + + + + + + + + + + + + + + + + + + + + +public class SimpleRuleStore + extends ContextAwareBase + implements RuleStore +{ + static String KLEENE_STAR = "*"; + + + HashMap> rules = new HashMap(); + + + + public SimpleRuleStore(Context context) + { + setContext(context); + } + + + + + public void addRule(ElementSelector elementSelector, Action action) + { + action.setContext(context); + + List a4p = (List)rules.get(elementSelector); + + if (a4p == null) { + a4p = new ArrayList(); + rules.put(elementSelector, a4p); + } + + a4p.add(action); + } + + public void addRule(ElementSelector elementSelector, String actionClassName) { + Action action = null; + try + { + action = (Action)OptionHelper.instantiateByClassName(actionClassName, Action.class, context); + } + catch (Exception e) { + addError("Could not instantiate class [" + actionClassName + "]", e); + } + if (action != null) { + addRule(elementSelector, action); + } + } + + + + + + public List matchActions(ElementPath elementPath) + { + List actionList; + + + + if ((actionList = fullPathMatch(elementPath)) != null) + return actionList; + if ((actionList = suffixMatch(elementPath)) != null) + return actionList; + if ((actionList = prefixMatch(elementPath)) != null) + return actionList; + if ((actionList = middleMatch(elementPath)) != null) { + return actionList; + } + return null; + } + + List fullPathMatch(ElementPath elementPath) + { + for (ElementSelector selector : rules.keySet()) { + if (selector.fullPathMatch(elementPath)) + return (List)rules.get(selector); + } + return null; + } + + List suffixMatch(ElementPath elementPath) + { + int max = 0; + ElementSelector longestMatchingElementSelector = null; + + for (ElementSelector selector : rules.keySet()) { + if (isSuffixPattern(selector)) { + int r = selector.getTailMatchLength(elementPath); + if (r > max) { + max = r; + longestMatchingElementSelector = selector; + } + } + } + + if (longestMatchingElementSelector != null) { + return (List)rules.get(longestMatchingElementSelector); + } + return null; + } + + private boolean isSuffixPattern(ElementSelector p) + { + return (p.size() > 1) && (p.get(0).equals(KLEENE_STAR)); + } + + List prefixMatch(ElementPath elementPath) { + int max = 0; + ElementSelector longestMatchingElementSelector = null; + + for (ElementSelector selector : rules.keySet()) { + String last = selector.peekLast(); + if (isKleeneStar(last)) { + int r = selector.getPrefixMatchLength(elementPath); + + if ((r == selector.size() - 1) && (r > max)) { + max = r; + longestMatchingElementSelector = selector; + } + } + } + + if (longestMatchingElementSelector != null) { + return (List)rules.get(longestMatchingElementSelector); + } + return null; + } + + private boolean isKleeneStar(String last) + { + return KLEENE_STAR.equals(last); + } + + List middleMatch(ElementPath path) + { + int max = 0; + ElementSelector longestMatchingElementSelector = null; + + for (ElementSelector selector : rules.keySet()) { + String last = selector.peekLast(); + String first = null; + if (selector.size() > 1) { + first = selector.get(0); + } + if ((isKleeneStar(last)) && (isKleeneStar(first))) { + List copyOfPartList = selector.getCopyOfPartList(); + if (copyOfPartList.size() > 2) { + copyOfPartList.remove(0); + copyOfPartList.remove(copyOfPartList.size() - 1); + } + + int r = 0; + ElementSelector clone = new ElementSelector(copyOfPartList); + if (clone.isContainedIn(path)) { + r = clone.size(); + } + if (r > max) { + max = r; + longestMatchingElementSelector = selector; + } + } + } + + if (longestMatchingElementSelector != null) { + return (List)rules.get(longestMatchingElementSelector); + } + return null; + } + + + public String toString() + { + String TAB = " "; + + StringBuilder retValue = new StringBuilder(); + + retValue.append("SimpleRuleStore ( ").append("rules = ").append(rules).append(" ").append(" )"); + + + return retValue.toString(); + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/spi/XMLUtil.java b/src/minecraft/ch/qos/logback/core/joran/spi/XMLUtil.java new file mode 100644 index 0000000..bc71bbe --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/spi/XMLUtil.java @@ -0,0 +1,29 @@ +package ch.qos.logback.core.joran.spi; + +import ch.qos.logback.core.status.StatusManager; +import java.net.URL; + + + + + + + + + + + + + +public class XMLUtil +{ + public static final int ILL_FORMED = 1; + public static final int UNRECOVERABLE_ERROR = 2; + + public XMLUtil() {} + + public static int checkIfWellFormed(URL url, StatusManager sm) + { + return 0; + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/util/ConfigurationWatchListUtil.java b/src/minecraft/ch/qos/logback/core/joran/util/ConfigurationWatchListUtil.java new file mode 100644 index 0000000..633fc36 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/util/ConfigurationWatchListUtil.java @@ -0,0 +1,102 @@ +package ch.qos.logback.core.joran.util; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.joran.spi.ConfigurationWatchList; +import ch.qos.logback.core.status.InfoStatus; +import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.status.WarnStatus; +import java.io.PrintStream; +import java.net.URL; + + + + + + + + + + + + + + + + + + +public class ConfigurationWatchListUtil +{ + static final ConfigurationWatchListUtil origin = new ConfigurationWatchListUtil(); + + private ConfigurationWatchListUtil() {} + + public static void setMainWatchURL(Context context, URL url) + { + ConfigurationWatchList cwl = getConfigurationWatchList(context); + if (cwl == null) { + cwl = new ConfigurationWatchList(); + cwl.setContext(context); + context.putObject("CONFIGURATION_WATCH_LIST", cwl); + } else { + cwl.clear(); + } + setConfigurationWatchListResetFlag(context, true); + cwl.setMainURL(url); + } + + public static URL getMainWatchURL(Context context) { + ConfigurationWatchList cwl = getConfigurationWatchList(context); + if (cwl == null) { + return null; + } + return cwl.getMainURL(); + } + + public static void addToWatchList(Context context, URL url) + { + ConfigurationWatchList cwl = getConfigurationWatchList(context); + if (cwl == null) { + addWarn(context, "Null ConfigurationWatchList. Cannot add " + url); + } else { + addInfo(context, "Adding [" + url + "] to configuration watch list."); + cwl.addToWatchList(url); + } + } + + public static boolean wasConfigurationWatchListReset(Context context) { + Object o = context.getObject("CONFIGURATION_WATCH_LIST_RESET"); + if (o == null) { + return false; + } + return ((Boolean)o).booleanValue(); + } + + public static void setConfigurationWatchListResetFlag(Context context, boolean val) + { + context.putObject("CONFIGURATION_WATCH_LIST_RESET", new Boolean(val)); + } + + public static ConfigurationWatchList getConfigurationWatchList(Context context) { + return (ConfigurationWatchList)context.getObject("CONFIGURATION_WATCH_LIST"); + } + + static void addStatus(Context context, Status s) { + if (context == null) { + System.out.println("Null context in " + ConfigurationWatchList.class.getName()); + return; + } + StatusManager sm = context.getStatusManager(); + if (sm == null) return; + sm.add(s); + } + + static void addInfo(Context context, String msg) { + addStatus(context, new InfoStatus(msg, origin)); + } + + static void addWarn(Context context, String msg) { + addStatus(context, new WarnStatus(msg, origin)); + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/util/PropertySetter.java b/src/minecraft/ch/qos/logback/core/joran/util/PropertySetter.java new file mode 100644 index 0000000..bad9ecd --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/util/PropertySetter.java @@ -0,0 +1,493 @@ +package ch.qos.logback.core.joran.util; + +import ch.qos.logback.core.joran.spi.DefaultClass; +import ch.qos.logback.core.joran.spi.DefaultNestedComponentRegistry; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.util.AggregationType; +import ch.qos.logback.core.util.PropertySetterException; +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.MethodDescriptor; +import java.beans.PropertyDescriptor; +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class PropertySetter + extends ContextAwareBase +{ + protected Object obj; + protected Class objClass; + protected PropertyDescriptor[] propertyDescriptors; + protected MethodDescriptor[] methodDescriptors; + + public PropertySetter(Object obj) + { + this.obj = obj; + objClass = obj.getClass(); + } + + + + protected void introspect() + { + try + { + BeanInfo bi = Introspector.getBeanInfo(obj.getClass()); + propertyDescriptors = bi.getPropertyDescriptors(); + methodDescriptors = bi.getMethodDescriptors(); + } catch (IntrospectionException ex) { + addError("Failed to introspect " + obj + ": " + ex.getMessage()); + propertyDescriptors = new PropertyDescriptor[0]; + methodDescriptors = new MethodDescriptor[0]; + } + } + + + + + + + + + + + + + + + + + + + public void setProperty(String name, String value) + { + if (value == null) { + return; + } + + name = Introspector.decapitalize(name); + + PropertyDescriptor prop = getPropertyDescriptor(name); + + if (prop == null) { + addWarn("No such property [" + name + "] in " + objClass.getName() + "."); + } else { + try { + setProperty(prop, name, value); + } catch (PropertySetterException ex) { + addWarn("Failed to set property [" + name + "] to value \"" + value + "\". ", ex); + } + } + } + + + + + + + + + + + + + public void setProperty(PropertyDescriptor prop, String name, String value) + throws PropertySetterException + { + Method setter = prop.getWriteMethod(); + + if (setter == null) { + throw new PropertySetterException("No setter for property [" + name + "]."); + } + + + Class[] paramTypes = setter.getParameterTypes(); + + if (paramTypes.length != 1) { + throw new PropertySetterException("#params for setter != 1"); + } + + Object arg; + try + { + arg = StringToObjectConverter.convertArg(this, value, paramTypes[0]); + } catch (Throwable t) { + throw new PropertySetterException("Conversion to type [" + paramTypes[0] + "] failed. ", t); + } + + + if (arg == null) { + throw new PropertySetterException("Conversion to type [" + paramTypes[0] + "] failed."); + } + try + { + setter.invoke(obj, new Object[] { arg }); + } catch (Exception ex) { + throw new PropertySetterException(ex); + } + } + + public AggregationType computeAggregationType(String name) { + String cName = capitalizeFirstLetter(name); + + Method addMethod = findAdderMethod(cName); + + + if (addMethod != null) { + AggregationType type = computeRawAggregationType(addMethod); + switch (1.$SwitchMap$ch$qos$logback$core$util$AggregationType[type.ordinal()]) { + case 1: + return AggregationType.NOT_FOUND; + case 2: + return AggregationType.AS_BASIC_PROPERTY_COLLECTION; + case 3: + return AggregationType.AS_COMPLEX_PROPERTY_COLLECTION; + } + + } + Method setterMethod = findSetterMethod(name); + if (setterMethod != null) { + return computeRawAggregationType(setterMethod); + } + + return AggregationType.NOT_FOUND; + } + + private Method findAdderMethod(String name) + { + name = capitalizeFirstLetter(name); + return getMethod("add" + name); + } + + private Method findSetterMethod(String name) { + String dName = Introspector.decapitalize(name); + PropertyDescriptor propertyDescriptor = getPropertyDescriptor(dName); + if (propertyDescriptor != null) { + return propertyDescriptor.getWriteMethod(); + } + return null; + } + + private Class getParameterClassForMethod(Method method) + { + if (method == null) { + return null; + } + Class[] classArray = method.getParameterTypes(); + if (classArray.length != 1) { + return null; + } + return classArray[0]; + } + + private AggregationType computeRawAggregationType(Method method) + { + Class parameterClass = getParameterClassForMethod(method); + if (parameterClass == null) { + return AggregationType.NOT_FOUND; + } + if (StringToObjectConverter.canBeBuiltFromSimpleString(parameterClass)) { + return AggregationType.AS_BASIC_PROPERTY; + } + return AggregationType.AS_COMPLEX_PROPERTY; + } + + + + + + + + + private boolean isUnequivocallyInstantiable(Class clazz) + { + if (clazz.isInterface()) { + return false; + } + + + + try + { + Object o = clazz.newInstance(); + if (o != null) { + return true; + } + return false; + } + catch (InstantiationException e) { + return false; + } catch (IllegalAccessException e) {} + return false; + } + + public Class getObjClass() + { + return objClass; + } + + public void addComplexProperty(String name, Object complexProperty) { + Method adderMethod = findAdderMethod(name); + + if (adderMethod != null) { + Class[] paramTypes = adderMethod.getParameterTypes(); + if (!isSanityCheckSuccessful(name, adderMethod, paramTypes, complexProperty)) + { + return; + } + invokeMethodWithSingleParameterOnThisObject(adderMethod, complexProperty); + } else { + addError("Could not find method [add" + name + "] in class [" + objClass.getName() + "]."); + } + } + + + void invokeMethodWithSingleParameterOnThisObject(Method method, Object parameter) + { + Class ccc = parameter.getClass(); + try { + method.invoke(obj, new Object[] { parameter }); + } catch (Exception e) { + addError("Could not invoke method " + method.getName() + " in class " + obj.getClass().getName() + " with parameter of type " + ccc.getName(), e); + } + } + + + + public void addBasicProperty(String name, String strValue) + { + if (strValue == null) { + return; + } + + name = capitalizeFirstLetter(name); + Method adderMethod = findAdderMethod(name); + + if (adderMethod == null) { + addError("No adder for property [" + name + "]."); + return; + } + + Class[] paramTypes = adderMethod.getParameterTypes(); + isSanityCheckSuccessful(name, adderMethod, paramTypes, strValue); + Object arg; + try + { + arg = StringToObjectConverter.convertArg(this, strValue, paramTypes[0]); + } catch (Throwable t) { + addError("Conversion to type [" + paramTypes[0] + "] failed. ", t); + return; + } + if (arg != null) { + invokeMethodWithSingleParameterOnThisObject(adderMethod, strValue); + } + } + + public void setComplexProperty(String name, Object complexProperty) { + String dName = Introspector.decapitalize(name); + PropertyDescriptor propertyDescriptor = getPropertyDescriptor(dName); + + if (propertyDescriptor == null) { + addWarn("Could not find PropertyDescriptor for [" + name + "] in " + objClass.getName()); + + + return; + } + + Method setter = propertyDescriptor.getWriteMethod(); + + if (setter == null) { + addWarn("Not setter method for property [" + name + "] in " + obj.getClass().getName()); + + + return; + } + + Class[] paramTypes = setter.getParameterTypes(); + + if (!isSanityCheckSuccessful(name, setter, paramTypes, complexProperty)) { + return; + } + try { + invokeMethodWithSingleParameterOnThisObject(setter, complexProperty); + } + catch (Exception e) { + addError("Could not set component " + obj + " for parent component " + obj, e); + } + } + + + private boolean isSanityCheckSuccessful(String name, Method method, Class[] params, Object complexProperty) + { + Class ccc = complexProperty.getClass(); + if (params.length != 1) { + addError("Wrong number of parameters in setter method for property [" + name + "] in " + obj.getClass().getName()); + + + return false; + } + + if (!params[0].isAssignableFrom(complexProperty.getClass())) { + addError("A \"" + ccc.getName() + "\" object is not assignable to a \"" + params[0].getName() + "\" variable."); + + addError("The class \"" + params[0].getName() + "\" was loaded by "); + addError("[" + params[0].getClassLoader() + "] whereas object of type "); + addError("\"" + ccc.getName() + "\" was loaded by [" + ccc.getClassLoader() + "]."); + + return false; + } + + return true; + } + + private String capitalizeFirstLetter(String name) { + return name.substring(0, 1).toUpperCase() + name.substring(1); + } + + protected Method getMethod(String methodName) { + if (methodDescriptors == null) { + introspect(); + } + + for (int i = 0; i < methodDescriptors.length; i++) { + if (methodName.equals(methodDescriptors[i].getName())) { + return methodDescriptors[i].getMethod(); + } + } + + return null; + } + + protected PropertyDescriptor getPropertyDescriptor(String name) { + if (propertyDescriptors == null) { + introspect(); + } + + for (int i = 0; i < propertyDescriptors.length; i++) + { + + if (name.equals(propertyDescriptors[i].getName())) + { + return propertyDescriptors[i]; + } + } + + return null; + } + + public Object getObj() { + return obj; + } + + Method getRelevantMethod(String name, AggregationType aggregationType) { + String cName = capitalizeFirstLetter(name); + Method relevantMethod; + if (aggregationType == AggregationType.AS_COMPLEX_PROPERTY_COLLECTION) { + relevantMethod = findAdderMethod(cName); } else { Method relevantMethod; + if (aggregationType == AggregationType.AS_COMPLEX_PROPERTY) { + relevantMethod = findSetterMethod(cName); + } else + throw new IllegalStateException(aggregationType + " not allowed here"); } + Method relevantMethod; + return relevantMethod; + } + + + T getAnnotation(String name, Class annonationClass, Method relevantMethod) + { + if (relevantMethod != null) { + return relevantMethod.getAnnotation(annonationClass); + } + return null; + } + + Class getDefaultClassNameByAnnonation(String name, Method relevantMethod) + { + DefaultClass defaultClassAnnon = (DefaultClass)getAnnotation(name, DefaultClass.class, relevantMethod); + + if (defaultClassAnnon != null) { + return defaultClassAnnon.value(); + } + return null; + } + + Class getByConcreteType(String name, Method relevantMethod) + { + Class paramType = getParameterClassForMethod(relevantMethod); + if (paramType == null) { + return null; + } + + boolean isUnequivocallyInstantiable = isUnequivocallyInstantiable(paramType); + if (isUnequivocallyInstantiable) { + return paramType; + } + return null; + } + + + + + public Class getClassNameViaImplicitRules(String name, AggregationType aggregationType, DefaultNestedComponentRegistry registry) + { + Class registryResult = registry.findDefaultComponentType(obj.getClass(), name); + + if (registryResult != null) { + return registryResult; + } + + Method relevantMethod = getRelevantMethod(name, aggregationType); + if (relevantMethod == null) { + return null; + } + Class byAnnotation = getDefaultClassNameByAnnonation(name, relevantMethod); + if (byAnnotation != null) { + return byAnnotation; + } + return getByConcreteType(name, relevantMethod); + } +} diff --git a/src/minecraft/ch/qos/logback/core/joran/util/StringToObjectConverter.java b/src/minecraft/ch/qos/logback/core/joran/util/StringToObjectConverter.java new file mode 100644 index 0000000..23b32a9 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/joran/util/StringToObjectConverter.java @@ -0,0 +1,137 @@ +package ch.qos.logback.core.joran.util; + +import ch.qos.logback.core.spi.ContextAware; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.nio.charset.Charset; +import java.nio.charset.UnsupportedCharsetException; + + + + + + + + + + + + + + + + + + + +public class StringToObjectConverter +{ + public StringToObjectConverter() {} + + private static final Class[] STING_CLASS_PARAMETER = { String.class }; + + public static boolean canBeBuiltFromSimpleString(Class parameterClass) { + Package p = parameterClass.getPackage(); + if (parameterClass.isPrimitive()) + return true; + if ((p != null) && ("java.lang".equals(p.getName()))) + return true; + if (followsTheValueOfConvention(parameterClass)) + return true; + if (parameterClass.isEnum()) + return true; + if (isOfTypeCharset(parameterClass)) { + return true; + } + return false; + } + + + + + public static Object convertArg(ContextAware ca, String val, Class type) + { + if (val == null) { + return null; + } + String v = val.trim(); + if (String.class.isAssignableFrom(type)) + return v; + if (Integer.TYPE.isAssignableFrom(type)) + return new Integer(v); + if (Long.TYPE.isAssignableFrom(type)) + return new Long(v); + if (Float.TYPE.isAssignableFrom(type)) + return new Float(v); + if (Double.TYPE.isAssignableFrom(type)) + return new Double(v); + if (Boolean.TYPE.isAssignableFrom(type)) { + if ("true".equalsIgnoreCase(v)) + return Boolean.TRUE; + if ("false".equalsIgnoreCase(v)) + return Boolean.FALSE; + } else { + if (type.isEnum()) + return convertToEnum(ca, v, type); + if (followsTheValueOfConvention(type)) + return convertByValueOfMethod(ca, type, v); + if (isOfTypeCharset(type)) { + return convertToCharset(ca, val); + } + } + return null; + } + + private static boolean isOfTypeCharset(Class type) { + return Charset.class.isAssignableFrom(type); + } + + private static Charset convertToCharset(ContextAware ca, String val) { + try { + return Charset.forName(val); + } catch (UnsupportedCharsetException e) { + ca.addError("Failed to get charset [" + val + "]", e); } + return null; + } + + private static boolean followsTheValueOfConvention(Class parameterClass) + { + try { + Method valueOfMethod = parameterClass.getMethod("valueOf", STING_CLASS_PARAMETER); + + int mod = valueOfMethod.getModifiers(); + if (Modifier.isStatic(mod)) { + return true; + } + } + catch (SecurityException e) {}catch (NoSuchMethodException e) {} + + + + return false; + } + + private static Object convertByValueOfMethod(ContextAware ca, Class type, String val) + { + try { + Method valueOfMethod = type.getMethod("valueOf", STING_CLASS_PARAMETER); + + return valueOfMethod.invoke(null, new Object[] { val }); + } catch (Exception e) { + ca.addError("Failed to invoke valueOf{} method in class [" + type.getName() + "] with value [" + val + "]"); + } + + return null; + } + + + + private static Object convertToEnum(ContextAware ca, String val, Class enumType) + { + return Enum.valueOf(enumType, val); + } + + boolean isBuildableFromSimpleString() { + return false; + } +} diff --git a/src/minecraft/ch/qos/logback/core/layout/EchoLayout.java b/src/minecraft/ch/qos/logback/core/layout/EchoLayout.java new file mode 100644 index 0000000..cde335e --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/layout/EchoLayout.java @@ -0,0 +1,29 @@ +package ch.qos.logback.core.layout; + +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.LayoutBase; + + + + + + + + + + + + + + + +public class EchoLayout + extends LayoutBase +{ + public EchoLayout() {} + + public String doLayout(E event) + { + return event + CoreConstants.LINE_SEPARATOR; + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/AbstractSSLSocketAppender.java b/src/minecraft/ch/qos/logback/core/net/AbstractSSLSocketAppender.java new file mode 100644 index 0000000..137b32b --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/AbstractSSLSocketAppender.java @@ -0,0 +1,89 @@ +package ch.qos.logback.core.net; + +import ch.qos.logback.core.net.ssl.ConfigurableSSLSocketFactory; +import ch.qos.logback.core.net.ssl.SSLComponent; +import ch.qos.logback.core.net.ssl.SSLConfiguration; +import ch.qos.logback.core.net.ssl.SSLParametersConfiguration; +import javax.net.SocketFactory; +import javax.net.ssl.SSLContext; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class AbstractSSLSocketAppender + extends AbstractSocketAppender + implements SSLComponent +{ + private SSLConfiguration ssl; + private SocketFactory socketFactory; + + protected AbstractSSLSocketAppender() {} + + protected SocketFactory getSocketFactory() + { + return socketFactory; + } + + + + public void start() + { + try + { + SSLContext sslContext = getSsl().createContext(this); + SSLParametersConfiguration parameters = getSsl().getParameters(); + parameters.setContext(getContext()); + socketFactory = new ConfigurableSSLSocketFactory(parameters, sslContext.getSocketFactory()); + + super.start(); + } + catch (Exception ex) { + addError(ex.getMessage(), ex); + } + } + + + + + + public SSLConfiguration getSsl() + { + if (ssl == null) { + ssl = new SSLConfiguration(); + } + return ssl; + } + + + + + public void setSsl(SSLConfiguration ssl) + { + this.ssl = ssl; + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/AbstractSocketAppender.java b/src/minecraft/ch/qos/logback/core/net/AbstractSocketAppender.java new file mode 100644 index 0000000..17cc022 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/AbstractSocketAppender.java @@ -0,0 +1,403 @@ +package ch.qos.logback.core.net; + +import ch.qos.logback.core.AppenderBase; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.spi.PreSerializationTransformer; +import ch.qos.logback.core.util.CloseUtil; +import ch.qos.logback.core.util.Duration; +import java.io.IOException; +import java.io.Serializable; +import java.net.ConnectException; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; +import java.util.concurrent.BlockingDeque; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import javax.net.SocketFactory; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class AbstractSocketAppender + extends AppenderBase + implements SocketConnector.ExceptionHandler +{ + public static final int DEFAULT_PORT = 4560; + public static final int DEFAULT_RECONNECTION_DELAY = 30000; + public static final int DEFAULT_QUEUE_SIZE = 128; + private static final int DEFAULT_ACCEPT_CONNECTION_DELAY = 5000; + private static final int DEFAULT_EVENT_DELAY_TIMEOUT = 100; + private final ObjectWriterFactory objectWriterFactory; + private final QueueFactory queueFactory; + private String remoteHost; + private int port = 4560; + private InetAddress address; + private Duration reconnectionDelay = new Duration(30000L); + private int queueSize = 128; + private int acceptConnectionTimeout = 5000; + private Duration eventDelayLimit = new Duration(100L); + + private BlockingDeque deque; + + private String peerId; + + private SocketConnector connector; + + private Future task; + private volatile Socket socket; + + protected AbstractSocketAppender() + { + this(new QueueFactory(), new ObjectWriterFactory()); + } + + + + AbstractSocketAppender(QueueFactory queueFactory, ObjectWriterFactory objectWriterFactory) + { + this.objectWriterFactory = objectWriterFactory; + this.queueFactory = queueFactory; + } + + + + public void start() + { + if (isStarted()) return; + int errorCount = 0; + if (port <= 0) { + errorCount++; + addError("No port was configured for appender" + name + " For more information, please visit http://logback.qos.ch/codes.html#socket_no_port"); + } + + + + if (remoteHost == null) { + errorCount++; + addError("No remote host was configured for appender" + name + " For more information, please visit http://logback.qos.ch/codes.html#socket_no_host"); + } + + + + if (queueSize == 0) { + addWarn("Queue size of zero is deprecated, use a size of one to indicate synchronous processing"); + } + + if (queueSize < 0) { + errorCount++; + addError("Queue size must be greater than zero"); + } + + if (errorCount == 0) { + try { + address = InetAddress.getByName(remoteHost); + } catch (UnknownHostException ex) { + addError("unknown host: " + remoteHost); + errorCount++; + } + } + + if (errorCount == 0) { + deque = queueFactory.newLinkedBlockingDeque(queueSize); + peerId = ("remote peer " + remoteHost + ":" + port + ": "); + connector = createConnector(address, port, 0, reconnectionDelay.getMilliseconds()); + task = getContext().getExecutorService().submit(new Runnable() + { + public void run() { + AbstractSocketAppender.this.connectSocketAndDispatchEvents(); + } + }); + super.start(); + } + } + + + + + public void stop() + { + if (!isStarted()) return; + CloseUtil.closeQuietly(socket); + task.cancel(true); + super.stop(); + } + + + + + protected void append(E event) + { + if ((event == null) || (!isStarted())) return; + try + { + boolean inserted = deque.offer(event, eventDelayLimit.getMilliseconds(), TimeUnit.MILLISECONDS); + if (!inserted) { + addInfo("Dropping event due to timeout limit of [" + eventDelayLimit + "] being exceeded"); + } + } catch (InterruptedException e) { + addError("Interrupted while appending event to SocketAppender", e); + } + } + + private void connectSocketAndDispatchEvents() { + try { + while (socketConnectionCouldBeEstablished()) { + try { + ObjectWriter objectWriter = createObjectWriterForSocket(); + addInfo(peerId + "connection established"); + dispatchEvents(objectWriter); + } catch (IOException ex) { + addInfo(peerId + "connection failed: " + ex); + } finally { + CloseUtil.closeQuietly(socket); + socket = null; + addInfo(peerId + "connection closed"); + } + } + } + catch (InterruptedException ex) {} + + addInfo("shutting down"); + } + + private boolean socketConnectionCouldBeEstablished() throws InterruptedException { + return (this.socket = connector.call()) != null; + } + + private ObjectWriter createObjectWriterForSocket() throws IOException { + socket.setSoTimeout(acceptConnectionTimeout); + ObjectWriter objectWriter = objectWriterFactory.newAutoFlushingObjectWriter(socket.getOutputStream()); + socket.setSoTimeout(0); + return objectWriter; + } + + private SocketConnector createConnector(InetAddress address, int port, int initialDelay, long retryDelay) { + SocketConnector connector = newConnector(address, port, initialDelay, retryDelay); + connector.setExceptionHandler(this); + connector.setSocketFactory(getSocketFactory()); + return connector; + } + + private void dispatchEvents(ObjectWriter objectWriter) throws InterruptedException, IOException { + for (;;) { + E event = deque.takeFirst(); + postProcessEvent(event); + Serializable serializableEvent = getPST().transform(event); + try { + objectWriter.write(serializableEvent); + } catch (IOException e) { + tryReAddingEventToFrontOfQueue(event); + throw e; + } + } + } + + private void tryReAddingEventToFrontOfQueue(E event) { + boolean wasInserted = deque.offerFirst(event); + if (!wasInserted) { + addInfo("Dropping event due to socket connection error and maxed out deque capacity"); + } + } + + + + public void connectionFailed(SocketConnector connector, Exception ex) + { + if ((ex instanceof InterruptedException)) { + addInfo("connector interrupted"); + } else if ((ex instanceof ConnectException)) { + addInfo(peerId + "connection refused"); + } else { + addInfo(peerId + ex); + } + } + + + + + + + + + + + + + + protected SocketConnector newConnector(InetAddress address, int port, long initialDelay, long retryDelay) + { + return new DefaultSocketConnector(address, port, initialDelay, retryDelay); + } + + + + + + protected SocketFactory getSocketFactory() + { + return SocketFactory.getDefault(); + } + + + + + + + protected abstract void postProcessEvent(E paramE); + + + + + + protected abstract PreSerializationTransformer getPST(); + + + + + + public void setRemoteHost(String host) + { + remoteHost = host; + } + + + + public String getRemoteHost() + { + return remoteHost; + } + + + + + public void setPort(int port) + { + this.port = port; + } + + + + public int getPort() + { + return port; + } + + + + + + + + + public void setReconnectionDelay(Duration delay) + { + reconnectionDelay = delay; + } + + + + public Duration getReconnectionDelay() + { + return reconnectionDelay; + } + + + + + + + + + + + + + public void setQueueSize(int queueSize) + { + this.queueSize = queueSize; + } + + + + public int getQueueSize() + { + return queueSize; + } + + + + + + + + public void setEventDelayLimit(Duration eventDelayLimit) + { + this.eventDelayLimit = eventDelayLimit; + } + + + + public Duration getEventDelayLimit() + { + return eventDelayLimit; + } + + + + + + + + + + void setAcceptConnectionTimeout(int acceptConnectionTimeout) + { + this.acceptConnectionTimeout = acceptConnectionTimeout; + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/AutoFlushingObjectWriter.java b/src/minecraft/ch/qos/logback/core/net/AutoFlushingObjectWriter.java new file mode 100644 index 0000000..12cdeed --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/AutoFlushingObjectWriter.java @@ -0,0 +1,60 @@ +package ch.qos.logback.core.net; + +import java.io.IOException; +import java.io.ObjectOutputStream; + + + + + + + + + + + + + + + + + + + +public class AutoFlushingObjectWriter + implements ObjectWriter +{ + private final ObjectOutputStream objectOutputStream; + private final int resetFrequency; + private int writeCounter = 0; + + + + + + + + public AutoFlushingObjectWriter(ObjectOutputStream objectOutputStream, int resetFrequency) + { + this.objectOutputStream = objectOutputStream; + this.resetFrequency = resetFrequency; + } + + public void write(Object object) throws IOException + { + objectOutputStream.writeObject(object); + objectOutputStream.flush(); + preventMemoryLeak(); + } + + + + private void preventMemoryLeak() + throws IOException + { + if (++writeCounter >= resetFrequency) { + objectOutputStream.reset(); + writeCounter = 0; + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/DefaultSocketConnector.java b/src/minecraft/ch/qos/logback/core/net/DefaultSocketConnector.java new file mode 100644 index 0000000..8a8ef24 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/DefaultSocketConnector.java @@ -0,0 +1,123 @@ +package ch.qos.logback.core.net; + +import ch.qos.logback.core.util.DelayStrategy; +import ch.qos.logback.core.util.FixedDelay; +import java.io.IOException; +import java.io.PrintStream; +import java.net.InetAddress; +import java.net.Socket; +import javax.net.SocketFactory; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class DefaultSocketConnector + implements SocketConnector +{ + private final InetAddress address; + private final int port; + private final DelayStrategy delayStrategy; + private SocketConnector.ExceptionHandler exceptionHandler; + private SocketFactory socketFactory; + + public DefaultSocketConnector(InetAddress address, int port, long initialDelay, long retryDelay) + { + this(address, port, new FixedDelay(initialDelay, retryDelay)); + } + + + + + + + + + + public DefaultSocketConnector(InetAddress address, int port, DelayStrategy delayStrategy) + { + this.address = address; + this.port = port; + this.delayStrategy = delayStrategy; + } + + + public Socket call() + throws InterruptedException + { + useDefaultsForMissingFields(); + Socket socket = createSocket(); + while ((socket == null) && (!Thread.currentThread().isInterrupted())) { + Thread.sleep(delayStrategy.nextDelay()); + socket = createSocket(); + } + return socket; + } + + private Socket createSocket() { + Socket newSocket = null; + try { + newSocket = socketFactory.createSocket(address, port); + } catch (IOException ioex) { + exceptionHandler.connectionFailed(this, ioex); + } + return newSocket; + } + + private void useDefaultsForMissingFields() { + if (exceptionHandler == null) { + exceptionHandler = new ConsoleExceptionHandler(null); + } + if (socketFactory == null) { + socketFactory = SocketFactory.getDefault(); + } + } + + + + public void setExceptionHandler(SocketConnector.ExceptionHandler exceptionHandler) + { + this.exceptionHandler = exceptionHandler; + } + + + + public void setSocketFactory(SocketFactory socketFactory) + { + this.socketFactory = socketFactory; + } + + private static class ConsoleExceptionHandler implements SocketConnector.ExceptionHandler + { + private ConsoleExceptionHandler() {} + + public void connectionFailed(SocketConnector connector, Exception ex) + { + System.out.println(ex); + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/JMSAppenderBase.java b/src/minecraft/ch/qos/logback/core/net/JMSAppenderBase.java new file mode 100644 index 0000000..e9b4913 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/JMSAppenderBase.java @@ -0,0 +1,175 @@ +package ch.qos.logback.core.net; + +import ch.qos.logback.core.AppenderBase; +import java.util.Properties; +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NameNotFoundException; +import javax.naming.NamingException; + + + + + + + + + + + + + + + + + + + + + + +public abstract class JMSAppenderBase + extends AppenderBase +{ + protected String securityPrincipalName; + protected String securityCredentials; + protected String initialContextFactoryName; + protected String urlPkgPrefixes; + protected String providerURL; + protected String userName; + protected String password; + + public JMSAppenderBase() {} + + protected Object lookup(Context ctx, String name) + throws NamingException + { + try + { + return ctx.lookup(name); + } catch (NameNotFoundException e) { + addError("Could not find name [" + name + "]."); + throw e; + } + } + + public Context buildJNDIContext() throws NamingException { + Context jndi = null; + + + if (initialContextFactoryName != null) { + Properties env = buildEnvProperties(); + jndi = new InitialContext(env); + } else { + jndi = new InitialContext(); + } + return jndi; + } + + public Properties buildEnvProperties() { + Properties env = new Properties(); + env.put("java.naming.factory.initial", initialContextFactoryName); + if (providerURL != null) { + env.put("java.naming.provider.url", providerURL); + } else { + addWarn("You have set InitialContextFactoryName option but not the ProviderURL. This is likely to cause problems."); + } + + if (urlPkgPrefixes != null) { + env.put("java.naming.factory.url.pkgs", urlPkgPrefixes); + } + + if (securityPrincipalName != null) { + env.put("java.naming.security.principal", securityPrincipalName); + if (securityCredentials != null) { + env.put("java.naming.security.credentials", securityCredentials); + } else { + addWarn("You have set SecurityPrincipalName option but not the SecurityCredentials. This is likely to cause problems."); + } + } + + return env; + } + + + + + + + + public String getInitialContextFactoryName() + { + return initialContextFactoryName; + } + + + + + + + + + + + public void setInitialContextFactoryName(String initialContextFactoryName) + { + this.initialContextFactoryName = initialContextFactoryName; + } + + public String getProviderURL() { + return providerURL; + } + + public void setProviderURL(String providerURL) { + this.providerURL = providerURL; + } + + public String getURLPkgPrefixes() { + return urlPkgPrefixes; + } + + public void setURLPkgPrefixes(String urlPkgPrefixes) { + this.urlPkgPrefixes = urlPkgPrefixes; + } + + public String getSecurityCredentials() { + return securityCredentials; + } + + public void setSecurityCredentials(String securityCredentials) { + this.securityCredentials = securityCredentials; + } + + public String getSecurityPrincipalName() { + return securityPrincipalName; + } + + public void setSecurityPrincipalName(String securityPrincipalName) { + this.securityPrincipalName = securityPrincipalName; + } + + public String getUserName() { + return userName; + } + + + + + + + public void setUserName(String userName) + { + this.userName = userName; + } + + public String getPassword() { + return password; + } + + + + public void setPassword(String password) + { + this.password = password; + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/LoginAuthenticator.java b/src/minecraft/ch/qos/logback/core/net/LoginAuthenticator.java new file mode 100644 index 0000000..6657702 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/LoginAuthenticator.java @@ -0,0 +1,35 @@ +package ch.qos.logback.core.net; + +import javax.mail.Authenticator; +import javax.mail.PasswordAuthentication; + + + + + + + + + + + + + + + +public class LoginAuthenticator + extends Authenticator +{ + String username; + String password; + + LoginAuthenticator(String username, String password) + { + this.username = username; + this.password = password; + } + + public PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/ObjectWriter.java b/src/minecraft/ch/qos/logback/core/net/ObjectWriter.java new file mode 100644 index 0000000..80e430e --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/ObjectWriter.java @@ -0,0 +1,9 @@ +package ch.qos.logback.core.net; + +import java.io.IOException; + +public abstract interface ObjectWriter +{ + public abstract void write(Object paramObject) + throws IOException; +} diff --git a/src/minecraft/ch/qos/logback/core/net/ObjectWriterFactory.java b/src/minecraft/ch/qos/logback/core/net/ObjectWriterFactory.java new file mode 100644 index 0000000..7ae9886 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/ObjectWriterFactory.java @@ -0,0 +1,39 @@ +package ch.qos.logback.core.net; + +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.OutputStream; + + + + + + + + + + + + + + + + + + + + + + + + +public class ObjectWriterFactory +{ + public ObjectWriterFactory() {} + + public AutoFlushingObjectWriter newAutoFlushingObjectWriter(OutputStream outputStream) + throws IOException + { + return new AutoFlushingObjectWriter(new ObjectOutputStream(outputStream), 70); + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/QueueFactory.java b/src/minecraft/ch/qos/logback/core/net/QueueFactory.java new file mode 100644 index 0000000..fbfbbbb --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/QueueFactory.java @@ -0,0 +1,39 @@ +package ch.qos.logback.core.net; + +import java.util.concurrent.LinkedBlockingDeque; + + + + + + + + + + + + + + + + + + + + + + + + + + +public class QueueFactory +{ + public QueueFactory() {} + + public LinkedBlockingDeque newLinkedBlockingDeque(int capacity) + { + int actualCapacity = capacity < 1 ? 1 : capacity; + return new LinkedBlockingDeque(actualCapacity); + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/SMTPAppenderBase.java b/src/minecraft/ch/qos/logback/core/net/SMTPAppenderBase.java new file mode 100644 index 0000000..4730a40 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/SMTPAppenderBase.java @@ -0,0 +1,680 @@ +package ch.qos.logback.core.net; + +import ch.qos.logback.core.AppenderBase; +import ch.qos.logback.core.Layout; +import ch.qos.logback.core.boolex.EvaluationException; +import ch.qos.logback.core.boolex.EventEvaluator; +import ch.qos.logback.core.helpers.CyclicBuffer; +import ch.qos.logback.core.pattern.PatternLayoutBase; +import ch.qos.logback.core.sift.DefaultDiscriminator; +import ch.qos.logback.core.sift.Discriminator; +import ch.qos.logback.core.spi.CyclicBufferTracker; +import ch.qos.logback.core.util.ContentTypeUtil; +import ch.qos.logback.core.util.OptionHelper; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.ExecutorService; +import javax.mail.Message.RecipientType; +import javax.mail.Multipart; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.AddressException; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeBodyPart; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMultipart; +import javax.naming.InitialContext; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class SMTPAppenderBase + extends AppenderBase +{ + static InternetAddress[] EMPTY_IA_ARRAY = new InternetAddress[0]; + static final int MAX_DELAY_BETWEEN_STATUS_MESSAGES = 1228800000; + + public SMTPAppenderBase() { + lastTrackerStatusPrint = 0L; + delayBetweenStatusMessages = 300000; + + + + + toPatternLayoutList = new ArrayList(); + + subjectStr = null; + + smtpPort = 25; + starttls = false; + ssl = false; + sessionViaJNDI = false; + jndiLocation = "java:comp/env/mail/Session"; + + + + + + + asynchronousSending = true; + + charsetEncoding = "UTF-8"; + + + + + + discriminator = new DefaultDiscriminator(); + + + errorCount = 0; + } + + long lastTrackerStatusPrint; + int delayBetweenStatusMessages; + protected Layout subjectLayout; + protected Layout layout; + private List> toPatternLayoutList; + private String from; + private String subjectStr; + private String smtpHost; + private int smtpPort; + private boolean starttls; + private boolean ssl; + protected abstract Layout makeSubjectLayout(String paramString); + + public void start() { + if (cbTracker == null) { + cbTracker = new CyclicBufferTracker(); + } + + if (sessionViaJNDI) { + session = lookupSessionInJNDI(); + } else { + session = buildSessionFromProperties(); + } + if (session == null) { + addError("Failed to obtain javax.mail.Session. Cannot start."); + return; + } + + subjectLayout = makeSubjectLayout(subjectStr); + + started = true; + } + + private Session lookupSessionInJNDI() { + addInfo("Looking up javax.mail.Session at JNDI location [" + jndiLocation + "]"); + try { + javax.naming.Context initialContext = new InitialContext(); + Object obj = initialContext.lookup(jndiLocation); + return (Session)obj; + } catch (Exception e) { + addError("Failed to obtain javax.mail.Session from JNDI location [" + jndiLocation + "]"); } + return null; + } + + private Session buildSessionFromProperties() + { + Properties props = new Properties(OptionHelper.getSystemProperties()); + if (smtpHost != null) { + props.put("mail.smtp.host", smtpHost); + } + props.put("mail.smtp.port", Integer.toString(smtpPort)); + + if (localhost != null) { + props.put("mail.smtp.localhost", localhost); + } + + LoginAuthenticator loginAuthenticator = null; + + if (username != null) { + loginAuthenticator = new LoginAuthenticator(username, password); + props.put("mail.smtp.auth", "true"); + } + + if ((isSTARTTLS()) && (isSSL())) { + addError("Both SSL and StartTLS cannot be enabled simultaneously"); + } else { + if (isSTARTTLS()) + { + props.put("mail.smtp.starttls.enable", "true"); + } + if (isSSL()) { + String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory"; + props.put("mail.smtp.socketFactory.port", Integer.toString(smtpPort)); + props.put("mail.smtp.socketFactory.class", SSL_FACTORY); + props.put("mail.smtp.socketFactory.fallback", "true"); + } + } + + + + return Session.getInstance(props, loginAuthenticator); + } + + + + + + protected void append(E eventObject) + { + if (!checkEntryConditions()) { + return; + } + + String key = discriminator.getDiscriminatingValue(eventObject); + long now = System.currentTimeMillis(); + CyclicBuffer cb = (CyclicBuffer)cbTracker.getOrCreate(key, now); + subAppend(cb, eventObject); + try + { + if (eventEvaluator.evaluate(eventObject)) + { + CyclicBuffer cbClone = new CyclicBuffer(cb); + + cb.clear(); + + if (asynchronousSending) + { + SMTPAppenderBase.SenderRunnable senderRunnable = new SenderRunnable(cbClone, eventObject); + context.getExecutorService().execute(senderRunnable); + } + else { + sendBuffer(cbClone, eventObject); + } + } + } catch (EvaluationException ex) { + errorCount += 1; + if (errorCount < 4) { + addError("SMTPAppender's EventEvaluator threw an Exception-", ex); + } + } + + + if (eventMarksEndOfLife(eventObject)) { + cbTracker.endOfLife(key); + } + + cbTracker.removeStaleComponents(now); + + if (lastTrackerStatusPrint + delayBetweenStatusMessages < now) { + addInfo("SMTPAppender [" + name + "] is tracking [" + cbTracker.getComponentCount() + "] buffers"); + lastTrackerStatusPrint = now; + + if (delayBetweenStatusMessages < 1228800000) { + delayBetweenStatusMessages *= 4; + } + } + } + + + + + protected abstract boolean eventMarksEndOfLife(E paramE); + + + + protected abstract void subAppend(CyclicBuffer paramCyclicBuffer, E paramE); + + + + public boolean checkEntryConditions() + { + if (!started) { + addError("Attempting to append to a non-started appender: " + getName()); + + return false; + } + + if (eventEvaluator == null) { + addError("No EventEvaluator is set for appender [" + name + "]."); + return false; + } + + if (layout == null) { + addError("No layout set for appender named [" + name + "]. For more information, please visit http://logback.qos.ch/codes.html#smtp_no_layout"); + + + return false; + } + return true; + } + + public synchronized void stop() { + started = false; + } + + InternetAddress getAddress(String addressStr) { + try { + return new InternetAddress(addressStr); + } catch (AddressException e) { + addError("Could not parse address [" + addressStr + "].", e); } + return null; + } + + private List parseAddress(E event) + { + int len = toPatternLayoutList.size(); + + List iaList = new ArrayList(); + + for (int i = 0; i < len; i++) { + try { + PatternLayoutBase emailPL = (PatternLayoutBase)toPatternLayoutList.get(i); + String emailAdrr = emailPL.doLayout(event); + if ((emailAdrr == null) || (emailAdrr.length() != 0)) + { + + InternetAddress[] tmp = InternetAddress.parse(emailAdrr, true); + iaList.addAll(Arrays.asList(tmp)); + } + } catch (AddressException e) { addError("Could not parse email address for [" + toPatternLayoutList.get(i) + "] for event [" + event + "]", e); + return iaList; + } + } + + return iaList; + } + + + + public List> getToList() + { + return toPatternLayoutList; + } + + + + + + protected void sendBuffer(CyclicBuffer cb, E lastEventObject) + { + try + { + MimeBodyPart part = new MimeBodyPart(); + + StringBuffer sbuf = new StringBuffer(); + + String header = layout.getFileHeader(); + if (header != null) { + sbuf.append(header); + } + String presentationHeader = layout.getPresentationHeader(); + if (presentationHeader != null) { + sbuf.append(presentationHeader); + } + fillBuffer(cb, sbuf); + String presentationFooter = layout.getPresentationFooter(); + if (presentationFooter != null) { + sbuf.append(presentationFooter); + } + String footer = layout.getFileFooter(); + if (footer != null) { + sbuf.append(footer); + } + + String subjectStr = "Undefined subject"; + if (subjectLayout != null) { + subjectStr = subjectLayout.doLayout(lastEventObject); + + + + + int newLinePos = subjectStr != null ? subjectStr.indexOf('\n') : -1; + if (newLinePos > -1) { + subjectStr = subjectStr.substring(0, newLinePos); + } + } + + MimeMessage mimeMsg = new MimeMessage(session); + + if (from != null) { + mimeMsg.setFrom(getAddress(from)); + } else { + mimeMsg.setFrom(); + } + + mimeMsg.setSubject(subjectStr, charsetEncoding); + + List destinationAddresses = parseAddress(lastEventObject); + if (destinationAddresses.isEmpty()) { + addInfo("Empty destination address. Aborting email transmission"); + return; + } + + InternetAddress[] toAddressArray = (InternetAddress[])destinationAddresses.toArray(EMPTY_IA_ARRAY); + mimeMsg.setRecipients(Message.RecipientType.TO, toAddressArray); + + String contentType = layout.getContentType(); + + if (ContentTypeUtil.isTextual(contentType)) { + part.setText(sbuf.toString(), charsetEncoding, ContentTypeUtil.getSubType(contentType)); + } + else { + part.setContent(sbuf.toString(), layout.getContentType()); + } + + Multipart mp = new MimeMultipart(); + mp.addBodyPart(part); + mimeMsg.setContent(mp); + + mimeMsg.setSentDate(new Date()); + addInfo("About to send out SMTP message \"" + subjectStr + "\" to " + Arrays.toString(toAddressArray)); + Transport.send(mimeMsg); + } catch (Exception e) { + addError("Error occurred while sending e-mail notification.", e); + } + } + + + protected abstract void fillBuffer(CyclicBuffer paramCyclicBuffer, StringBuffer paramStringBuffer); + + + public String getFrom() + { + return from; + } + + + + public String getSubject() + { + return subjectStr; + } + + + + + public void setFrom(String from) + { + this.from = from; + } + + + + + public void setSubject(String subject) + { + subjectStr = subject; + } + + + + + + public void setSMTPHost(String smtpHost) + { + setSmtpHost(smtpHost); + } + + + + + public void setSmtpHost(String smtpHost) + { + this.smtpHost = smtpHost; + } + + + + public String getSMTPHost() + { + return getSmtpHost(); + } + + + + public String getSmtpHost() + { + return smtpHost; + } + + + + + + public void setSMTPPort(int port) + { + setSmtpPort(port); + } + + + + + + public void setSmtpPort(int port) + { + smtpPort = port; + } + + + + + + public int getSMTPPort() + { + return getSmtpPort(); + } + + + + + + public int getSmtpPort() + { + return smtpPort; + } + + + public String getLocalhost() { return localhost; } + + private boolean sessionViaJNDI; + private String jndiLocation; + String username; + String password; + String localhost; + boolean asynchronousSending; + private String charsetEncoding; + protected Session session; + protected EventEvaluator eventEvaluator; + protected Discriminator discriminator; + protected CyclicBufferTracker cbTracker; + private int errorCount; + public void setLocalhost(String localhost) { this.localhost = localhost; } + + + public CyclicBufferTracker getCyclicBufferTracker() { + return cbTracker; + } + + public void setCyclicBufferTracker(CyclicBufferTracker cbTracker) { + this.cbTracker = cbTracker; + } + + public Discriminator getDiscriminator() { + return discriminator; + } + + public void setDiscriminator(Discriminator discriminator) { + this.discriminator = discriminator; + } + + public boolean isAsynchronousSending() { + return asynchronousSending; + } + + + + + + + + public void setAsynchronousSending(boolean asynchronousSending) + { + this.asynchronousSending = asynchronousSending; + } + + public void addTo(String to) { + if ((to == null) || (to.length() == 0)) { + throw new IllegalArgumentException("Null or empty property"); + } + PatternLayoutBase plb = makeNewToPatternLayout(to.trim()); + plb.setContext(context); + plb.start(); + toPatternLayoutList.add(plb); + } + + protected abstract PatternLayoutBase makeNewToPatternLayout(String paramString); + + public List getToAsListOfString() { + List toList = new ArrayList(); + for (PatternLayoutBase plb : toPatternLayoutList) { + toList.add(plb.getPattern()); + } + return toList; + } + + public boolean isSTARTTLS() { + return starttls; + } + + public void setSTARTTLS(boolean startTLS) { + starttls = startTLS; + } + + public boolean isSSL() { + return ssl; + } + + public void setSSL(boolean ssl) { + this.ssl = ssl; + } + + + + + + + public void setEvaluator(EventEvaluator eventEvaluator) + { + this.eventEvaluator = eventEvaluator; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + + + + public String getCharsetEncoding() + { + return charsetEncoding; + } + + public String getJndiLocation() + { + return jndiLocation; + } + + + + + + + + public void setJndiLocation(String jndiLocation) + { + this.jndiLocation = jndiLocation; + } + + public boolean isSessionViaJNDI() { + return sessionViaJNDI; + } + + + + + + + public void setSessionViaJNDI(boolean sessionViaJNDI) + { + this.sessionViaJNDI = sessionViaJNDI; + } + + + + + + + public void setCharsetEncoding(String charsetEncoding) + { + this.charsetEncoding = charsetEncoding; + } + + public Layout getLayout() { + return layout; + } + + public void setLayout(Layout layout) { + this.layout = layout; + } + + class SenderRunnable implements Runnable + { + final CyclicBuffer cyclicBuffer; + final E e; + + SenderRunnable(E cyclicBuffer) { + this.cyclicBuffer = cyclicBuffer; + this.e = e; + } + + public void run() { + sendBuffer(cyclicBuffer, e); + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/SocketConnector.java b/src/minecraft/ch/qos/logback/core/net/SocketConnector.java new file mode 100644 index 0000000..0187899 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/SocketConnector.java @@ -0,0 +1,21 @@ +package ch.qos.logback.core.net; + +import java.net.Socket; +import java.util.concurrent.Callable; +import javax.net.SocketFactory; + +public abstract interface SocketConnector + extends Callable +{ + public abstract Socket call() + throws InterruptedException; + + public abstract void setExceptionHandler(ExceptionHandler paramExceptionHandler); + + public abstract void setSocketFactory(SocketFactory paramSocketFactory); + + public static abstract interface ExceptionHandler + { + public abstract void connectionFailed(SocketConnector paramSocketConnector, Exception paramException); + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/SyslogAppenderBase.java b/src/minecraft/ch/qos/logback/core/net/SyslogAppenderBase.java new file mode 100644 index 0000000..8deeda0 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/SyslogAppenderBase.java @@ -0,0 +1,313 @@ +package ch.qos.logback.core.net; + +import ch.qos.logback.core.AppenderBase; +import ch.qos.logback.core.Layout; +import java.io.IOException; +import java.io.OutputStream; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.nio.charset.Charset; + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class SyslogAppenderBase + extends AppenderBase +{ + static final String SYSLOG_LAYOUT_URL = "http://logback.qos.ch/codes.html#syslog_layout"; + static final int MAX_MESSAGE_SIZE_LIMIT = 65000; + Layout layout; + String facilityStr; + String syslogHost; + protected String suffixPattern; + SyslogOutputStream sos; + int port = 514; + int maxMessageSize; + + public SyslogAppenderBase() {} + + public void start() { int errorCount = 0; + if (facilityStr == null) { + addError("The Facility option is mandatory"); + errorCount++; + } + + if (charset == null) + { + + charset = Charset.defaultCharset(); + } + try + { + sos = createOutputStream(); + + int systemDatagramSize = sos.getSendBufferSize(); + if (maxMessageSize == 0) { + maxMessageSize = Math.min(systemDatagramSize, 65000); + addInfo("Defaulting maxMessageSize to [" + maxMessageSize + "]"); + } else if (maxMessageSize > systemDatagramSize) { + addWarn("maxMessageSize of [" + maxMessageSize + "] is larger than the system defined datagram size of [" + systemDatagramSize + "]."); + addWarn("This may result in dropped logs."); + } + } catch (UnknownHostException e) { + addError("Could not create SyslogWriter", e); + errorCount++; + } catch (SocketException e) { + addWarn("Failed to bind to a random datagram socket. Will try to reconnect later.", e); + } + + + + if (layout == null) { + layout = buildLayout(); + } + + if (errorCount == 0) { + super.start(); + } + } + + public abstract SyslogOutputStream createOutputStream() throws UnknownHostException, SocketException; + + public abstract Layout buildLayout(); + + public abstract int getSeverityForEvent(Object paramObject); + + protected void append(E eventObject) + { + if (!isStarted()) { + return; + } + try + { + String msg = layout.doLayout(eventObject); + if (msg == null) { + return; + } + if (msg.length() > maxMessageSize) { + msg = msg.substring(0, maxMessageSize); + } + sos.write(msg.getBytes(charset)); + sos.flush(); + postProcess(eventObject, sos); + } catch (IOException ioe) { + addError("Failed to send diagram to " + syslogHost, ioe); + } + } + + + + + + protected void postProcess(Object event, OutputStream sw) {} + + + + + public static int facilityStringToint(String facilityStr) + { + if ("KERN".equalsIgnoreCase(facilityStr)) + return 0; + if ("USER".equalsIgnoreCase(facilityStr)) + return 8; + if ("MAIL".equalsIgnoreCase(facilityStr)) + return 16; + if ("DAEMON".equalsIgnoreCase(facilityStr)) + return 24; + if ("AUTH".equalsIgnoreCase(facilityStr)) + return 32; + if ("SYSLOG".equalsIgnoreCase(facilityStr)) + return 40; + if ("LPR".equalsIgnoreCase(facilityStr)) + return 48; + if ("NEWS".equalsIgnoreCase(facilityStr)) + return 56; + if ("UUCP".equalsIgnoreCase(facilityStr)) + return 64; + if ("CRON".equalsIgnoreCase(facilityStr)) + return 72; + if ("AUTHPRIV".equalsIgnoreCase(facilityStr)) + return 80; + if ("FTP".equalsIgnoreCase(facilityStr)) + return 88; + if ("NTP".equalsIgnoreCase(facilityStr)) + return 96; + if ("AUDIT".equalsIgnoreCase(facilityStr)) + return 104; + if ("ALERT".equalsIgnoreCase(facilityStr)) + return 112; + if ("CLOCK".equalsIgnoreCase(facilityStr)) + return 120; + if ("LOCAL0".equalsIgnoreCase(facilityStr)) + return 128; + if ("LOCAL1".equalsIgnoreCase(facilityStr)) + return 136; + if ("LOCAL2".equalsIgnoreCase(facilityStr)) + return 144; + if ("LOCAL3".equalsIgnoreCase(facilityStr)) + return 152; + if ("LOCAL4".equalsIgnoreCase(facilityStr)) + return 160; + if ("LOCAL5".equalsIgnoreCase(facilityStr)) + return 168; + if ("LOCAL6".equalsIgnoreCase(facilityStr)) + return 176; + if ("LOCAL7".equalsIgnoreCase(facilityStr)) { + return 184; + } + throw new IllegalArgumentException(facilityStr + " is not a valid syslog facility string"); + } + + + + + + public String getSyslogHost() + { + return syslogHost; + } + + + + + + + public void setSyslogHost(String syslogHost) + { + this.syslogHost = syslogHost; + } + + + + + + public String getFacility() + { + return facilityStr; + } + + + + + + Charset charset; + + + + + public void setFacility(String facilityStr) + { + if (facilityStr != null) { + facilityStr = facilityStr.trim(); + } + this.facilityStr = facilityStr; + } + + + + + public int getPort() + { + return port; + } + + + + + public void setPort(int port) + { + this.port = port; + } + + + + + public int getMaxMessageSize() + { + return maxMessageSize; + } + + + + + + + + public void setMaxMessageSize(int maxMessageSize) + { + this.maxMessageSize = maxMessageSize; + } + + public Layout getLayout() { + return layout; + } + + public void setLayout(Layout layout) { + addWarn("The layout of a SyslogAppender cannot be set directly. See also http://logback.qos.ch/codes.html#syslog_layout"); + } + + + public void stop() + { + if (sos != null) { + sos.close(); + } + super.stop(); + } + + + + + + public String getSuffixPattern() + { + return suffixPattern; + } + + + + + + + public void setSuffixPattern(String suffixPattern) + { + this.suffixPattern = suffixPattern; + } + + + + + public Charset getCharset() + { + return charset; + } + + + + + + public void setCharset(Charset charset) + { + this.charset = charset; + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/SyslogConstants.java b/src/minecraft/ch/qos/logback/core/net/SyslogConstants.java new file mode 100644 index 0000000..440ac7a --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/SyslogConstants.java @@ -0,0 +1,40 @@ +package ch.qos.logback.core.net; + +public class SyslogConstants +{ + public static final int SYSLOG_PORT = 514; + public static final int EMERGENCY_SEVERITY = 0; + public static final int ALERT_SEVERITY = 1; + public static final int CRITICAL_SEVERITY = 2; + public static final int ERROR_SEVERITY = 3; + public static final int WARNING_SEVERITY = 4; + public static final int NOTICE_SEVERITY = 5; + public static final int INFO_SEVERITY = 6; + public static final int DEBUG_SEVERITY = 7; + public static final int LOG_KERN = 0; + public static final int LOG_USER = 8; + public static final int LOG_MAIL = 16; + public static final int LOG_DAEMON = 24; + public static final int LOG_AUTH = 32; + public static final int LOG_SYSLOG = 40; + public static final int LOG_LPR = 48; + public static final int LOG_NEWS = 56; + public static final int LOG_UUCP = 64; + public static final int LOG_CRON = 72; + public static final int LOG_AUTHPRIV = 80; + public static final int LOG_FTP = 88; + public static final int LOG_NTP = 96; + public static final int LOG_AUDIT = 104; + public static final int LOG_ALERT = 112; + public static final int LOG_CLOCK = 120; + public static final int LOG_LOCAL0 = 128; + public static final int LOG_LOCAL1 = 136; + public static final int LOG_LOCAL2 = 144; + public static final int LOG_LOCAL3 = 152; + public static final int LOG_LOCAL4 = 160; + public static final int LOG_LOCAL5 = 168; + public static final int LOG_LOCAL6 = 176; + public static final int LOG_LOCAL7 = 184; + + public SyslogConstants() {} +} diff --git a/src/minecraft/ch/qos/logback/core/net/SyslogOutputStream.java b/src/minecraft/ch/qos/logback/core/net/SyslogOutputStream.java new file mode 100644 index 0000000..cea0825 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/SyslogOutputStream.java @@ -0,0 +1,93 @@ +package ch.qos.logback.core.net; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.SocketException; +import java.net.UnknownHostException; + + + + + + + + + + + + + + + + + + + + + + +public class SyslogOutputStream + extends OutputStream +{ + private static final int MAX_LEN = 1024; + private InetAddress address; + private DatagramSocket ds; + private ByteArrayOutputStream baos = new ByteArrayOutputStream(); + private final int port; + + public SyslogOutputStream(String syslogHost, int port) throws UnknownHostException, SocketException + { + address = InetAddress.getByName(syslogHost); + this.port = port; + ds = new DatagramSocket(); + } + + public void write(byte[] byteArray, int offset, int len) throws IOException { + baos.write(byteArray, offset, len); + } + + public void flush() throws IOException { + byte[] bytes = baos.toByteArray(); + DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address, port); + + + + if (baos.size() > 1024) { + baos = new ByteArrayOutputStream(); + } else { + baos.reset(); + } + + + + if (bytes.length == 0) { + return; + } + if (ds != null) { + ds.send(packet); + } + } + + public void close() + { + address = null; + ds = null; + } + + public int getPort() { + return port; + } + + public void write(int b) throws IOException + { + baos.write(b); + } + + int getSendBufferSize() throws SocketException { + return ds.getSendBufferSize(); + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/server/AbstractServerSocketAppender.java b/src/minecraft/ch/qos/logback/core/net/server/AbstractServerSocketAppender.java new file mode 100644 index 0000000..66131b8 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/server/AbstractServerSocketAppender.java @@ -0,0 +1,216 @@ +package ch.qos.logback.core.net.server; + +import ch.qos.logback.core.AppenderBase; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.spi.PreSerializationTransformer; +import java.io.IOException; +import java.io.Serializable; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.UnknownHostException; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import javax.net.ServerSocketFactory; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class AbstractServerSocketAppender + extends AppenderBase +{ + public static final int DEFAULT_BACKLOG = 50; + public static final int DEFAULT_CLIENT_QUEUE_SIZE = 100; + private int port = 4560; + private int backlog = 50; + private int clientQueueSize = 100; + private String address; + private ServerRunner runner; + + public AbstractServerSocketAppender() {} + + public void start() + { + if (isStarted()) return; + try { + ServerSocket socket = getServerSocketFactory().createServerSocket(getPort(), getBacklog(), getInetAddress()); + + ServerListener listener = createServerListener(socket); + + runner = createServerRunner(listener, getContext().getExecutorService()); + runner.setContext(getContext()); + getContext().getExecutorService().execute(runner); + super.start(); + } catch (Exception ex) { + addError("server startup error: " + ex, ex); + } + } + + protected ServerListener createServerListener(ServerSocket socket) + { + return new RemoteReceiverServerListener(socket); + } + + + protected ServerRunner createServerRunner(ServerListener listener, Executor executor) + { + return new RemoteReceiverServerRunner(listener, executor, getClientQueueSize()); + } + + + public void stop() + { + if (!isStarted()) return; + try { + runner.stop(); + super.stop(); + } + catch (IOException ex) { + addError("server shutdown error: " + ex, ex); + } + } + + protected void append(E event) + { + if (event == null) return; + postProcessEvent(event); + final Serializable serEvent = getPST().transform(event); + runner.accept(new ClientVisitor() { + public void visit(RemoteReceiverClient client) { + client.offer(serEvent); + } + }); + } + + + + + + + + protected abstract void postProcessEvent(E paramE); + + + + + + + protected abstract PreSerializationTransformer getPST(); + + + + + + + protected ServerSocketFactory getServerSocketFactory() + throws Exception + { + return ServerSocketFactory.getDefault(); + } + + + + + protected InetAddress getInetAddress() + throws UnknownHostException + { + if (getAddress() == null) return null; + return InetAddress.getByName(getAddress()); + } + + + + + public int getPort() + { + return port; + } + + + + + public void setPort(int port) + { + this.port = port; + } + + + + + + + + + public int getBacklog() + { + return backlog; + } + + + + + + + + + public void setBacklog(int backlog) + { + this.backlog = backlog; + } + + + + + public String getAddress() + { + return address; + } + + + + + public void setAddress(String address) + { + this.address = address; + } + + + + + public int getClientQueueSize() + { + return clientQueueSize; + } + + + + + public void setClientQueueSize(int clientQueueSize) + { + this.clientQueueSize = clientQueueSize; + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/server/Client.java b/src/minecraft/ch/qos/logback/core/net/server/Client.java new file mode 100644 index 0000000..7888a7d --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/server/Client.java @@ -0,0 +1,9 @@ +package ch.qos.logback.core.net.server; + +import java.io.Closeable; + +public abstract interface Client + extends Runnable, Closeable +{ + public abstract void close(); +} diff --git a/src/minecraft/ch/qos/logback/core/net/server/ClientVisitor.java b/src/minecraft/ch/qos/logback/core/net/server/ClientVisitor.java new file mode 100644 index 0000000..72f72fb --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/server/ClientVisitor.java @@ -0,0 +1,6 @@ +package ch.qos.logback.core.net.server; + +public abstract interface ClientVisitor +{ + public abstract void visit(T paramT); +} diff --git a/src/minecraft/ch/qos/logback/core/net/server/ConcurrentServerRunner.java b/src/minecraft/ch/qos/logback/core/net/server/ConcurrentServerRunner.java new file mode 100644 index 0000000..3da950e --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/server/ConcurrentServerRunner.java @@ -0,0 +1,229 @@ +package ch.qos.logback.core.net.server; + +import ch.qos.logback.core.spi.ContextAwareBase; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.concurrent.Executor; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class ConcurrentServerRunner + extends ContextAwareBase + implements Runnable, ServerRunner +{ + private final Lock clientsLock = new ReentrantLock(); + + private final Collection clients = new ArrayList(); + + + + private final ServerListener listener; + + + + private final Executor executor; + + + private boolean running; + + + + public ConcurrentServerRunner(ServerListener listener, Executor executor) + { + this.listener = listener; + this.executor = executor; + } + + + + public boolean isRunning() + { + return running; + } + + protected void setRunning(boolean running) { + this.running = running; + } + + + public void stop() + throws IOException + { + listener.close(); + accept(new ClientVisitor() { + public void visit(T client) { + client.close(); + } + }); + } + + + + public void accept(ClientVisitor visitor) + { + Collection clients = copyClients(); + for (T client : clients) { + try { + visitor.visit(client); + } + catch (RuntimeException ex) { + addError(client + ": " + ex); + } + } + } + + + + + + private Collection copyClients() + { + clientsLock.lock(); + try { + Collection copy = new ArrayList(clients); + return copy; + } + finally { + clientsLock.unlock(); + } + } + + + + public void run() + { + setRunning(true); + try { + addInfo("listening on " + listener); + while (!Thread.currentThread().isInterrupted()) { + T client = listener.acceptClient(); + if (!configureClient(client)) { + addError(client + ": connection dropped"); + client.close(); + } + else { + try { + executor.execute(new ClientWrapper(client)); + } + catch (RejectedExecutionException ex) { + addError(client + ": connection dropped"); + client.close(); + } + + } + } + } + catch (InterruptedException ex) {}catch (Exception ex) + { + addError("listener: " + ex); + } + + setRunning(false); + addInfo("shutting down"); + listener.close(); + } + + + + + + + + + protected abstract boolean configureClient(T paramT); + + + + + + + + private void addClient(T client) + { + clientsLock.lock(); + try { + clients.add(client); + } + finally { + clientsLock.unlock(); + } + } + + + + + private void removeClient(T client) + { + clientsLock.lock(); + try { + clients.remove(client); + } + finally { + clientsLock.unlock(); + } + } + + + private class ClientWrapper + implements Client + { + private final T delegate; + + + public ClientWrapper() + { + delegate = client; + } + + public void run() { + ConcurrentServerRunner.this.addClient(delegate); + try { + delegate.run(); + } + finally { + ConcurrentServerRunner.this.removeClient(delegate); + } + } + + public void close() { + delegate.close(); + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/server/RemoteReceiverClient.java b/src/minecraft/ch/qos/logback/core/net/server/RemoteReceiverClient.java new file mode 100644 index 0000000..19d1ebb --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/server/RemoteReceiverClient.java @@ -0,0 +1,13 @@ +package ch.qos.logback.core.net.server; + +import ch.qos.logback.core.spi.ContextAware; +import java.io.Serializable; +import java.util.concurrent.BlockingQueue; + +abstract interface RemoteReceiverClient + extends Client, ContextAware +{ + public abstract void setQueue(BlockingQueue paramBlockingQueue); + + public abstract boolean offer(Serializable paramSerializable); +} diff --git a/src/minecraft/ch/qos/logback/core/net/server/RemoteReceiverServerListener.java b/src/minecraft/ch/qos/logback/core/net/server/RemoteReceiverServerListener.java new file mode 100644 index 0000000..5a04b34 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/server/RemoteReceiverServerListener.java @@ -0,0 +1,46 @@ +package ch.qos.logback.core.net.server; + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; + + + + + + + + + + + + + + + + + + + + + + + + +class RemoteReceiverServerListener + extends ServerSocketListener +{ + public RemoteReceiverServerListener(ServerSocket serverSocket) + { + super(serverSocket); + } + + + + + protected RemoteReceiverClient createClient(String id, Socket socket) + throws IOException + { + return new RemoteReceiverStreamClient(id, socket); + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/server/RemoteReceiverServerRunner.java b/src/minecraft/ch/qos/logback/core/net/server/RemoteReceiverServerRunner.java new file mode 100644 index 0000000..36aaff5 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/server/RemoteReceiverServerRunner.java @@ -0,0 +1,56 @@ +package ch.qos.logback.core.net.server; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.Executor; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +class RemoteReceiverServerRunner + extends ConcurrentServerRunner +{ + private final int clientQueueSize; + + public RemoteReceiverServerRunner(ServerListener listener, Executor executor, int clientQueueSize) + { + super(listener, executor); + this.clientQueueSize = clientQueueSize; + } + + + + + protected boolean configureClient(RemoteReceiverClient client) + { + client.setContext(getContext()); + client.setQueue(new ArrayBlockingQueue(clientQueueSize)); + return true; + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/server/RemoteReceiverStreamClient.java b/src/minecraft/ch/qos/logback/core/net/server/RemoteReceiverStreamClient.java new file mode 100644 index 0000000..f1b1b9c --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/server/RemoteReceiverStreamClient.java @@ -0,0 +1,145 @@ +package ch.qos.logback.core.net.server; + +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.util.CloseUtil; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.OutputStream; +import java.io.Serializable; +import java.net.Socket; +import java.net.SocketException; +import java.util.concurrent.BlockingQueue; + + + + + + + + + + + + + + + + + + + + + + + + + + +class RemoteReceiverStreamClient + extends ContextAwareBase + implements RemoteReceiverClient +{ + private final String clientId; + private final Socket socket; + private final OutputStream outputStream; + private BlockingQueue queue; + + public RemoteReceiverStreamClient(String id, Socket socket) + { + clientId = ("client " + id + ": "); + this.socket = socket; + outputStream = null; + } + + + + + + + + + + RemoteReceiverStreamClient(String id, OutputStream outputStream) + { + clientId = ("client " + id + ": "); + socket = null; + this.outputStream = outputStream; + } + + + + public void setQueue(BlockingQueue queue) + { + this.queue = queue; + } + + + + public boolean offer(Serializable event) + { + if (queue == null) { + throw new IllegalStateException("client has no event queue"); + } + return queue.offer(event); + } + + + + public void close() + { + if (socket == null) return; + CloseUtil.closeQuietly(socket); + } + + + + public void run() + { + addInfo(clientId + "connected"); + + ObjectOutputStream oos = null; + try { + int counter = 0; + oos = createObjectOutputStream(); + while (!Thread.currentThread().isInterrupted()) { + try { + Serializable event = (Serializable)queue.take(); + oos.writeObject(event); + oos.flush(); + counter++; if (counter >= 70) + { + + counter = 0; + oos.reset(); + } + } + catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } + } + } + catch (SocketException ex) { + addInfo(clientId + ex); + } + catch (IOException ex) { + addError(clientId + ex); + } + catch (RuntimeException ex) { + addError(clientId + ex); + } + finally { + if (oos != null) { + CloseUtil.closeQuietly(oos); + } + close(); + addInfo(clientId + "connection closed"); + } + } + + private ObjectOutputStream createObjectOutputStream() throws IOException { + if (socket == null) { + return new ObjectOutputStream(outputStream); + } + return new ObjectOutputStream(socket.getOutputStream()); + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/server/SSLServerSocketAppenderBase.java b/src/minecraft/ch/qos/logback/core/net/server/SSLServerSocketAppenderBase.java new file mode 100644 index 0000000..deecdaf --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/server/SSLServerSocketAppenderBase.java @@ -0,0 +1,79 @@ +package ch.qos.logback.core.net.server; + +import ch.qos.logback.core.net.ssl.ConfigurableSSLServerSocketFactory; +import ch.qos.logback.core.net.ssl.SSLComponent; +import ch.qos.logback.core.net.ssl.SSLConfiguration; +import ch.qos.logback.core.net.ssl.SSLParametersConfiguration; +import javax.net.ServerSocketFactory; +import javax.net.ssl.SSLContext; + + + + + + + + + + + + + + + + + + + +public abstract class SSLServerSocketAppenderBase + extends AbstractServerSocketAppender + implements SSLComponent +{ + private SSLConfiguration ssl; + private ServerSocketFactory socketFactory; + + public SSLServerSocketAppenderBase() {} + + protected ServerSocketFactory getServerSocketFactory() + { + return socketFactory; + } + + + + public void start() + { + try + { + SSLContext sslContext = getSsl().createContext(this); + SSLParametersConfiguration parameters = getSsl().getParameters(); + parameters.setContext(getContext()); + socketFactory = new ConfigurableSSLServerSocketFactory(parameters, sslContext.getServerSocketFactory()); + + super.start(); + } + catch (Exception ex) { + addError(ex.getMessage(), ex); + } + } + + + + + + public SSLConfiguration getSsl() + { + if (ssl == null) { + ssl = new SSLConfiguration(); + } + return ssl; + } + + + + + public void setSsl(SSLConfiguration ssl) + { + this.ssl = ssl; + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/server/ServerListener.java b/src/minecraft/ch/qos/logback/core/net/server/ServerListener.java new file mode 100644 index 0000000..1c232be --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/server/ServerListener.java @@ -0,0 +1,13 @@ +package ch.qos.logback.core.net.server; + +import java.io.Closeable; +import java.io.IOException; + +public abstract interface ServerListener + extends Closeable +{ + public abstract T acceptClient() + throws IOException, InterruptedException; + + public abstract void close(); +} diff --git a/src/minecraft/ch/qos/logback/core/net/server/ServerRunner.java b/src/minecraft/ch/qos/logback/core/net/server/ServerRunner.java new file mode 100644 index 0000000..57a03b7 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/server/ServerRunner.java @@ -0,0 +1,15 @@ +package ch.qos.logback.core.net.server; + +import ch.qos.logback.core.spi.ContextAware; +import java.io.IOException; + +public abstract interface ServerRunner + extends ContextAware, Runnable +{ + public abstract boolean isRunning(); + + public abstract void stop() + throws IOException; + + public abstract void accept(ClientVisitor paramClientVisitor); +} diff --git a/src/minecraft/ch/qos/logback/core/net/server/ServerSocketListener.java b/src/minecraft/ch/qos/logback/core/net/server/ServerSocketListener.java new file mode 100644 index 0000000..b2fa263 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/server/ServerSocketListener.java @@ -0,0 +1,88 @@ +package ch.qos.logback.core.net.server; + +import ch.qos.logback.core.util.CloseUtil; +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketAddress; + + + + + + + + + + + + + + + + + + + + + + + +public abstract class ServerSocketListener + implements ServerListener +{ + private final ServerSocket serverSocket; + + public ServerSocketListener(ServerSocket serverSocket) + { + this.serverSocket = serverSocket; + } + + + public T acceptClient() + throws IOException + { + Socket socket = serverSocket.accept(); + return createClient(socketAddressToString(socket.getRemoteSocketAddress()), socket); + } + + + + + + + protected abstract T createClient(String paramString, Socket paramSocket) + throws IOException; + + + + + + + public void close() + { + CloseUtil.closeQuietly(serverSocket); + } + + + + + public String toString() + { + return socketAddressToString(serverSocket.getLocalSocketAddress()); + } + + + + + + private String socketAddressToString(SocketAddress address) + { + String addr = address.toString(); + int i = addr.indexOf("/"); + if (i >= 0) { + addr = addr.substring(i + 1); + } + return addr; + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/ssl/ConfigurableSSLServerSocketFactory.java b/src/minecraft/ch/qos/logback/core/net/ssl/ConfigurableSSLServerSocketFactory.java new file mode 100644 index 0000000..a568dd3 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/ssl/ConfigurableSSLServerSocketFactory.java @@ -0,0 +1,88 @@ +package ch.qos.logback.core.net.ssl; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.ServerSocket; +import javax.net.ServerSocketFactory; +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLServerSocketFactory; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class ConfigurableSSLServerSocketFactory + extends ServerSocketFactory +{ + private final SSLParametersConfiguration parameters; + private final SSLServerSocketFactory delegate; + + public ConfigurableSSLServerSocketFactory(SSLParametersConfiguration parameters, SSLServerSocketFactory delegate) + { + this.parameters = parameters; + this.delegate = delegate; + } + + + + + public ServerSocket createServerSocket(int port, int backlog, InetAddress ifAddress) + throws IOException + { + SSLServerSocket socket = (SSLServerSocket)delegate.createServerSocket(port, backlog, ifAddress); + + parameters.configure(new SSLConfigurableServerSocket(socket)); + return socket; + } + + + + + public ServerSocket createServerSocket(int port, int backlog) + throws IOException + { + SSLServerSocket socket = (SSLServerSocket)delegate.createServerSocket(port, backlog); + + parameters.configure(new SSLConfigurableServerSocket(socket)); + return socket; + } + + + + public ServerSocket createServerSocket(int port) + throws IOException + { + SSLServerSocket socket = (SSLServerSocket)delegate.createServerSocket(port); + + parameters.configure(new SSLConfigurableServerSocket(socket)); + return socket; + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/ssl/ConfigurableSSLSocketFactory.java b/src/minecraft/ch/qos/logback/core/net/ssl/ConfigurableSSLSocketFactory.java new file mode 100644 index 0000000..b00c9ad --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/ssl/ConfigurableSSLSocketFactory.java @@ -0,0 +1,99 @@ +package ch.qos.logback.core.net.ssl; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; +import javax.net.SocketFactory; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class ConfigurableSSLSocketFactory + extends SocketFactory +{ + private final SSLParametersConfiguration parameters; + private final SSLSocketFactory delegate; + + public ConfigurableSSLSocketFactory(SSLParametersConfiguration parameters, SSLSocketFactory delegate) + { + this.parameters = parameters; + this.delegate = delegate; + } + + + + + public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) + throws IOException + { + SSLSocket socket = (SSLSocket)delegate.createSocket(address, port, localAddress, localPort); + + parameters.configure(new SSLConfigurableSocket(socket)); + return socket; + } + + + + public Socket createSocket(InetAddress host, int port) + throws IOException + { + SSLSocket socket = (SSLSocket)delegate.createSocket(host, port); + parameters.configure(new SSLConfigurableSocket(socket)); + return socket; + } + + + + + public Socket createSocket(String host, int port, InetAddress localHost, int localPort) + throws IOException, UnknownHostException + { + SSLSocket socket = (SSLSocket)delegate.createSocket(host, port, localHost, localPort); + + parameters.configure(new SSLConfigurableSocket(socket)); + return socket; + } + + + + + public Socket createSocket(String host, int port) + throws IOException, UnknownHostException + { + SSLSocket socket = (SSLSocket)delegate.createSocket(host, port); + parameters.configure(new SSLConfigurableSocket(socket)); + return socket; + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/ssl/KeyManagerFactoryFactoryBean.java b/src/minecraft/ch/qos/logback/core/net/ssl/KeyManagerFactoryFactoryBean.java new file mode 100644 index 0000000..943c2b1 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/ssl/KeyManagerFactoryFactoryBean.java @@ -0,0 +1,90 @@ +package ch.qos.logback.core.net.ssl; + +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import javax.net.ssl.KeyManagerFactory; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class KeyManagerFactoryFactoryBean +{ + private String algorithm; + private String provider; + + public KeyManagerFactoryFactoryBean() {} + + public KeyManagerFactory createKeyManagerFactory() + throws NoSuchProviderException, NoSuchAlgorithmException + { + return getProvider() != null ? KeyManagerFactory.getInstance(getAlgorithm(), getProvider()) : KeyManagerFactory.getInstance(getAlgorithm()); + } + + + + + + + + + public String getAlgorithm() + { + if (algorithm == null) { + return KeyManagerFactory.getDefaultAlgorithm(); + } + return algorithm; + } + + + + + + + public void setAlgorithm(String algorithm) + { + this.algorithm = algorithm; + } + + + + + public String getProvider() + { + return provider; + } + + + + + + public void setProvider(String provider) + { + this.provider = provider; + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/ssl/KeyStoreFactoryBean.java b/src/minecraft/ch/qos/logback/core/net/ssl/KeyStoreFactoryBean.java new file mode 100644 index 0000000..a32b01a --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/ssl/KeyStoreFactoryBean.java @@ -0,0 +1,185 @@ +package ch.qos.logback.core.net.ssl; + +import ch.qos.logback.core.util.LocationUtil; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class KeyStoreFactoryBean +{ + private String location; + private String provider; + private String type; + private String password; + + public KeyStoreFactoryBean() {} + + public KeyStore createKeyStore() + throws NoSuchProviderException, NoSuchAlgorithmException, KeyStoreException + { + if (getLocation() == null) { + throw new IllegalArgumentException("location is required"); + } + + InputStream inputStream = null; + try { + URL url = LocationUtil.urlForResource(getLocation()); + inputStream = url.openStream(); + KeyStore keyStore = newKeyStore(); + keyStore.load(inputStream, getPassword().toCharArray()); + return keyStore; + } + catch (NoSuchProviderException ex) { + throw new NoSuchProviderException("no such keystore provider: " + getProvider()); + } + catch (NoSuchAlgorithmException ex) + { + throw new NoSuchAlgorithmException("no such keystore type: " + getType()); + } + catch (FileNotFoundException ex) + { + throw new KeyStoreException(getLocation() + ": file not found"); + } + catch (Exception ex) { + throw new KeyStoreException(getLocation() + ": " + ex.getMessage(), ex); + } + finally { + try { + if (inputStream != null) { + inputStream.close(); + } + } + catch (IOException ex) { + ex.printStackTrace(System.err); + } + } + } + + + + + + private KeyStore newKeyStore() + throws NoSuchAlgorithmException, NoSuchProviderException, KeyStoreException + { + return getProvider() != null ? KeyStore.getInstance(getType(), getProvider()) : KeyStore.getInstance(getType()); + } + + + + + + + public String getLocation() + { + return location; + } + + + + + + + public void setLocation(String location) + { + this.location = location; + } + + + + + + public String getType() + { + if (type == null) { + return "JKS"; + } + return type; + } + + + + + + + + public void setType(String type) + { + this.type = type; + } + + + + + public String getProvider() + { + return provider; + } + + + + + + public void setProvider(String provider) + { + this.provider = provider; + } + + + + + + public String getPassword() + { + if (password == null) { + return "changeit"; + } + return password; + } + + + + + public void setPassword(String password) + { + this.password = password; + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/ssl/SSL.java b/src/minecraft/ch/qos/logback/core/net/ssl/SSL.java new file mode 100644 index 0000000..c850ae0 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/ssl/SSL.java @@ -0,0 +1,9 @@ +package ch.qos.logback.core.net.ssl; + +public abstract interface SSL +{ + public static final String DEFAULT_PROTOCOL = "SSL"; + public static final String DEFAULT_KEYSTORE_TYPE = "JKS"; + public static final String DEFAULT_KEYSTORE_PASSWORD = "changeit"; + public static final String DEFAULT_SECURE_RANDOM_ALGORITHM = "SHA1PRNG"; +} diff --git a/src/minecraft/ch/qos/logback/core/net/ssl/SSLComponent.java b/src/minecraft/ch/qos/logback/core/net/ssl/SSLComponent.java new file mode 100644 index 0000000..382fcdb --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/ssl/SSLComponent.java @@ -0,0 +1,8 @@ +package ch.qos.logback.core.net.ssl; + +public abstract interface SSLComponent +{ + public abstract SSLConfiguration getSsl(); + + public abstract void setSsl(SSLConfiguration paramSSLConfiguration); +} diff --git a/src/minecraft/ch/qos/logback/core/net/ssl/SSLConfigurable.java b/src/minecraft/ch/qos/logback/core/net/ssl/SSLConfigurable.java new file mode 100644 index 0000000..416a2cf --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/ssl/SSLConfigurable.java @@ -0,0 +1,20 @@ +package ch.qos.logback.core.net.ssl; + +public abstract interface SSLConfigurable +{ + public abstract String[] getDefaultProtocols(); + + public abstract String[] getSupportedProtocols(); + + public abstract void setEnabledProtocols(String[] paramArrayOfString); + + public abstract String[] getDefaultCipherSuites(); + + public abstract String[] getSupportedCipherSuites(); + + public abstract void setEnabledCipherSuites(String[] paramArrayOfString); + + public abstract void setNeedClientAuth(boolean paramBoolean); + + public abstract void setWantClientAuth(boolean paramBoolean); +} diff --git a/src/minecraft/ch/qos/logback/core/net/ssl/SSLConfigurableServerSocket.java b/src/minecraft/ch/qos/logback/core/net/ssl/SSLConfigurableServerSocket.java new file mode 100644 index 0000000..5af2138 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/ssl/SSLConfigurableServerSocket.java @@ -0,0 +1,62 @@ +package ch.qos.logback.core.net.ssl; + +import javax.net.ssl.SSLServerSocket; + + + + + + + + + + + + + + + + + +public class SSLConfigurableServerSocket + implements SSLConfigurable +{ + private final SSLServerSocket delegate; + + public SSLConfigurableServerSocket(SSLServerSocket delegate) + { + this.delegate = delegate; + } + + public String[] getDefaultProtocols() { + return delegate.getEnabledProtocols(); + } + + public String[] getSupportedProtocols() { + return delegate.getSupportedProtocols(); + } + + public void setEnabledProtocols(String[] protocols) { + delegate.setEnabledProtocols(protocols); + } + + public String[] getDefaultCipherSuites() { + return delegate.getEnabledCipherSuites(); + } + + public String[] getSupportedCipherSuites() { + return delegate.getSupportedCipherSuites(); + } + + public void setEnabledCipherSuites(String[] suites) { + delegate.setEnabledCipherSuites(suites); + } + + public void setNeedClientAuth(boolean state) { + delegate.setNeedClientAuth(state); + } + + public void setWantClientAuth(boolean state) { + delegate.setWantClientAuth(state); + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/ssl/SSLConfigurableSocket.java b/src/minecraft/ch/qos/logback/core/net/ssl/SSLConfigurableSocket.java new file mode 100644 index 0000000..07e3c66 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/ssl/SSLConfigurableSocket.java @@ -0,0 +1,62 @@ +package ch.qos.logback.core.net.ssl; + +import javax.net.ssl.SSLSocket; + + + + + + + + + + + + + + + + + +public class SSLConfigurableSocket + implements SSLConfigurable +{ + private final SSLSocket delegate; + + public SSLConfigurableSocket(SSLSocket delegate) + { + this.delegate = delegate; + } + + public String[] getDefaultProtocols() { + return delegate.getEnabledProtocols(); + } + + public String[] getSupportedProtocols() { + return delegate.getSupportedProtocols(); + } + + public void setEnabledProtocols(String[] protocols) { + delegate.setEnabledProtocols(protocols); + } + + public String[] getDefaultCipherSuites() { + return delegate.getEnabledCipherSuites(); + } + + public String[] getSupportedCipherSuites() { + return delegate.getSupportedCipherSuites(); + } + + public void setEnabledCipherSuites(String[] suites) { + delegate.setEnabledCipherSuites(suites); + } + + public void setNeedClientAuth(boolean state) { + delegate.setNeedClientAuth(state); + } + + public void setWantClientAuth(boolean state) { + delegate.setWantClientAuth(state); + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/ssl/SSLConfiguration.java b/src/minecraft/ch/qos/logback/core/net/ssl/SSLConfiguration.java new file mode 100644 index 0000000..0b33bce --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/ssl/SSLConfiguration.java @@ -0,0 +1,47 @@ +package ch.qos.logback.core.net.ssl; + + + + + + + + + +public class SSLConfiguration + extends SSLContextFactoryBean +{ + private SSLParametersConfiguration parameters; + + + + + + + + + public SSLConfiguration() {} + + + + + + + + + public SSLParametersConfiguration getParameters() + { + if (parameters == null) { + parameters = new SSLParametersConfiguration(); + } + return parameters; + } + + + + + public void setParameters(SSLParametersConfiguration parameters) + { + this.parameters = parameters; + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/ssl/SSLContextFactoryBean.java b/src/minecraft/ch/qos/logback/core/net/ssl/SSLContextFactoryBean.java new file mode 100644 index 0000000..94cbe41 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/ssl/SSLContextFactoryBean.java @@ -0,0 +1,340 @@ +package ch.qos.logback.core.net.ssl; + +import ch.qos.logback.core.spi.ContextAware; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.SecureRandom; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import javax.net.ssl.KeyManager; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class SSLContextFactoryBean +{ + private static final String JSSE_KEY_STORE_PROPERTY = "javax.net.ssl.keyStore"; + private static final String JSSE_TRUST_STORE_PROPERTY = "javax.net.ssl.trustStore"; + private KeyStoreFactoryBean keyStore; + private KeyStoreFactoryBean trustStore; + private SecureRandomFactoryBean secureRandom; + private KeyManagerFactoryFactoryBean keyManagerFactory; + private TrustManagerFactoryFactoryBean trustManagerFactory; + private String protocol; + private String provider; + + public SSLContextFactoryBean() {} + + public SSLContext createContext(ContextAware context) + throws NoSuchProviderException, NoSuchAlgorithmException, KeyManagementException, UnrecoverableKeyException, KeyStoreException, CertificateException + { + SSLContext sslContext = getProvider() != null ? SSLContext.getInstance(getProtocol(), getProvider()) : SSLContext.getInstance(getProtocol()); + + + + context.addInfo("SSL protocol '" + sslContext.getProtocol() + "' provider '" + sslContext.getProvider() + "'"); + + + KeyManager[] keyManagers = createKeyManagers(context); + TrustManager[] trustManagers = createTrustManagers(context); + SecureRandom secureRandom = createSecureRandom(context); + sslContext.init(keyManagers, trustManagers, secureRandom); + return sslContext; + } + + + + + + + + + + + + + + + private KeyManager[] createKeyManagers(ContextAware context) + throws NoSuchProviderException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException + { + if (getKeyStore() == null) { return null; + } + KeyStore keyStore = getKeyStore().createKeyStore(); + context.addInfo("key store of type '" + keyStore.getType() + "' provider '" + keyStore.getProvider() + "': " + getKeyStore().getLocation()); + + + + + KeyManagerFactory kmf = getKeyManagerFactory().createKeyManagerFactory(); + context.addInfo("key manager algorithm '" + kmf.getAlgorithm() + "' provider '" + kmf.getProvider() + "'"); + + + char[] passphrase = getKeyStore().getPassword().toCharArray(); + kmf.init(keyStore, passphrase); + return kmf.getKeyManagers(); + } + + + + + + + + + + + + + + + + private TrustManager[] createTrustManagers(ContextAware context) + throws NoSuchProviderException, NoSuchAlgorithmException, KeyStoreException + { + if (getTrustStore() == null) { return null; + } + KeyStore trustStore = getTrustStore().createKeyStore(); + context.addInfo("trust store of type '" + trustStore.getType() + "' provider '" + trustStore.getProvider() + "': " + getTrustStore().getLocation()); + + + + + TrustManagerFactory tmf = getTrustManagerFactory().createTrustManagerFactory(); + + context.addInfo("trust manager algorithm '" + tmf.getAlgorithm() + "' provider '" + tmf.getProvider() + "'"); + + + tmf.init(trustStore); + return tmf.getTrustManagers(); + } + + private SecureRandom createSecureRandom(ContextAware context) + throws NoSuchProviderException, NoSuchAlgorithmException + { + SecureRandom secureRandom = getSecureRandom().createSecureRandom(); + context.addInfo("secure random algorithm '" + secureRandom.getAlgorithm() + "' provider '" + secureRandom.getProvider() + "'"); + + + return secureRandom; + } + + + + + + public KeyStoreFactoryBean getKeyStore() + { + if (keyStore == null) { + keyStore = keyStoreFromSystemProperties("javax.net.ssl.keyStore"); + } + return keyStore; + } + + + + + public void setKeyStore(KeyStoreFactoryBean keyStore) + { + this.keyStore = keyStore; + } + + + + + + public KeyStoreFactoryBean getTrustStore() + { + if (trustStore == null) { + trustStore = keyStoreFromSystemProperties("javax.net.ssl.trustStore"); + } + return trustStore; + } + + + + + public void setTrustStore(KeyStoreFactoryBean trustStore) + { + this.trustStore = trustStore; + } + + + + + + + private KeyStoreFactoryBean keyStoreFromSystemProperties(String property) + { + if (System.getProperty(property) == null) return null; + KeyStoreFactoryBean keyStore = new KeyStoreFactoryBean(); + keyStore.setLocation(locationFromSystemProperty(property)); + keyStore.setProvider(System.getProperty(property + "Provider")); + keyStore.setPassword(System.getProperty(property + "Password")); + keyStore.setType(System.getProperty(property + "Type")); + return keyStore; + } + + + + + + + private String locationFromSystemProperty(String name) + { + String location = System.getProperty(name); + if ((location != null) && (!location.startsWith("file:"))) { + location = "file:" + location; + } + return location; + } + + + + + + public SecureRandomFactoryBean getSecureRandom() + { + if (secureRandom == null) { + return new SecureRandomFactoryBean(); + } + return secureRandom; + } + + + + + public void setSecureRandom(SecureRandomFactoryBean secureRandom) + { + this.secureRandom = secureRandom; + } + + + + + + public KeyManagerFactoryFactoryBean getKeyManagerFactory() + { + if (keyManagerFactory == null) { + return new KeyManagerFactoryFactoryBean(); + } + return keyManagerFactory; + } + + + + + + public void setKeyManagerFactory(KeyManagerFactoryFactoryBean keyManagerFactory) + { + this.keyManagerFactory = keyManagerFactory; + } + + + + + + public TrustManagerFactoryFactoryBean getTrustManagerFactory() + { + if (trustManagerFactory == null) { + return new TrustManagerFactoryFactoryBean(); + } + return trustManagerFactory; + } + + + + + + public void setTrustManagerFactory(TrustManagerFactoryFactoryBean trustManagerFactory) + { + this.trustManagerFactory = trustManagerFactory; + } + + + + + + + public String getProtocol() + { + if (protocol == null) { + return "SSL"; + } + return protocol; + } + + + + + + + public void setProtocol(String protocol) + { + this.protocol = protocol; + } + + + + + public String getProvider() + { + return provider; + } + + + + + + public void setProvider(String provider) + { + this.provider = provider; + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/ssl/SSLNestedComponentRegistryRules.java b/src/minecraft/ch/qos/logback/core/net/ssl/SSLNestedComponentRegistryRules.java new file mode 100644 index 0000000..b01114b --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/ssl/SSLNestedComponentRegistryRules.java @@ -0,0 +1,41 @@ +package ch.qos.logback.core.net.ssl; + +import ch.qos.logback.core.joran.spi.DefaultNestedComponentRegistry; + + + + + + + + + + + + + + + + + + +public class SSLNestedComponentRegistryRules +{ + public SSLNestedComponentRegistryRules() {} + + public static void addDefaultNestedComponentRegistryRules(DefaultNestedComponentRegistry registry) + { + registry.add(SSLComponent.class, "ssl", SSLConfiguration.class); + registry.add(SSLConfiguration.class, "parameters", SSLParametersConfiguration.class); + + registry.add(SSLConfiguration.class, "keyStore", KeyStoreFactoryBean.class); + + registry.add(SSLConfiguration.class, "trustStore", KeyStoreFactoryBean.class); + + registry.add(SSLConfiguration.class, "keyManagerFactory", KeyManagerFactoryFactoryBean.class); + + registry.add(SSLConfiguration.class, "trustManagerFactory", TrustManagerFactoryFactoryBean.class); + + registry.add(SSLConfiguration.class, "secureRandom", SecureRandomFactoryBean.class); + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/ssl/SSLParametersConfiguration.java b/src/minecraft/ch/qos/logback/core/net/ssl/SSLParametersConfiguration.java new file mode 100644 index 0000000..44873a3 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/ssl/SSLParametersConfiguration.java @@ -0,0 +1,255 @@ +package ch.qos.logback.core.net.ssl; + +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.util.OptionHelper; +import ch.qos.logback.core.util.StringCollectionUtil; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + + + + + + + + + + + + + + + + + + + + + + + + + +public class SSLParametersConfiguration + extends ContextAwareBase +{ + private String includedProtocols; + private String excludedProtocols; + private String includedCipherSuites; + private String excludedCipherSuites; + private Boolean needClientAuth; + private Boolean wantClientAuth; + private String[] enabledProtocols; + private String[] enabledCipherSuites; + + public SSLParametersConfiguration() {} + + public void configure(SSLConfigurable socket) + { + socket.setEnabledProtocols(enabledProtocols(socket.getSupportedProtocols(), socket.getDefaultProtocols())); + + socket.setEnabledCipherSuites(enabledCipherSuites(socket.getSupportedCipherSuites(), socket.getDefaultCipherSuites())); + + if (isNeedClientAuth() != null) { + socket.setNeedClientAuth(isNeedClientAuth().booleanValue()); + } + if (isWantClientAuth() != null) { + socket.setWantClientAuth(isWantClientAuth().booleanValue()); + } + } + + + + + + + + private String[] enabledProtocols(String[] supportedProtocols, String[] defaultProtocols) + { + if (enabledProtocols == null) + { + + if ((OptionHelper.isEmpty(getIncludedProtocols())) && (OptionHelper.isEmpty(getExcludedProtocols()))) + { + enabledProtocols = ((String[])Arrays.copyOf(defaultProtocols, defaultProtocols.length)); + } + else + { + enabledProtocols = includedStrings(supportedProtocols, getIncludedProtocols(), getExcludedProtocols()); + } + + for (String protocol : enabledProtocols) { + addInfo("enabled protocol: " + protocol); + } + } + return enabledProtocols; + } + + + + + + + + private String[] enabledCipherSuites(String[] supportedCipherSuites, String[] defaultCipherSuites) + { + if (enabledCipherSuites == null) + { + + if ((OptionHelper.isEmpty(getIncludedCipherSuites())) && (OptionHelper.isEmpty(getExcludedCipherSuites()))) + { + enabledCipherSuites = ((String[])Arrays.copyOf(defaultCipherSuites, defaultCipherSuites.length)); + } + else + { + enabledCipherSuites = includedStrings(supportedCipherSuites, getIncludedCipherSuites(), getExcludedCipherSuites()); + } + + for (String cipherSuite : enabledCipherSuites) { + addInfo("enabled cipher suite: " + cipherSuite); + } + } + return enabledCipherSuites; + } + + + + + + + + + + + + private String[] includedStrings(String[] defaults, String included, String excluded) + { + List values = new ArrayList(defaults.length); + values.addAll(Arrays.asList(defaults)); + if (included != null) { + StringCollectionUtil.retainMatching(values, stringToArray(included)); + } + if (excluded != null) { + StringCollectionUtil.removeMatching(values, stringToArray(excluded)); + } + return (String[])values.toArray(new String[values.size()]); + } + + + + + + private String[] stringToArray(String s) + { + return s.split("\\s*,\\s*"); + } + + + + + + public String getIncludedProtocols() + { + return includedProtocols; + } + + + + + + + public void setIncludedProtocols(String protocols) + { + includedProtocols = protocols; + } + + + + + + public String getExcludedProtocols() + { + return excludedProtocols; + } + + + + + + + public void setExcludedProtocols(String protocols) + { + excludedProtocols = protocols; + } + + + + + + public String getIncludedCipherSuites() + { + return includedCipherSuites; + } + + + + + + + public void setIncludedCipherSuites(String cipherSuites) + { + includedCipherSuites = cipherSuites; + } + + + + + + public String getExcludedCipherSuites() + { + return excludedCipherSuites; + } + + + + + + + public void setExcludedCipherSuites(String cipherSuites) + { + excludedCipherSuites = cipherSuites; + } + + + + + public Boolean isNeedClientAuth() + { + return needClientAuth; + } + + + + + public void setNeedClientAuth(Boolean needClientAuth) + { + this.needClientAuth = needClientAuth; + } + + + + + public Boolean isWantClientAuth() + { + return wantClientAuth; + } + + + + + public void setWantClientAuth(Boolean wantClientAuth) + { + this.wantClientAuth = wantClientAuth; + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/ssl/SecureRandomFactoryBean.java b/src/minecraft/ch/qos/logback/core/net/ssl/SecureRandomFactoryBean.java new file mode 100644 index 0000000..7d587a4 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/ssl/SecureRandomFactoryBean.java @@ -0,0 +1,100 @@ +package ch.qos.logback.core.net.ssl; + +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.SecureRandom; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class SecureRandomFactoryBean +{ + private String algorithm; + private String provider; + + public SecureRandomFactoryBean() {} + + public SecureRandom createSecureRandom() + throws NoSuchProviderException, NoSuchAlgorithmException + { + try + { + return getProvider() != null ? SecureRandom.getInstance(getAlgorithm(), getProvider()) : SecureRandom.getInstance(getAlgorithm()); + + } + catch (NoSuchProviderException ex) + { + throw new NoSuchProviderException("no such secure random provider: " + getProvider()); + } + catch (NoSuchAlgorithmException ex) + { + throw new NoSuchAlgorithmException("no such secure random algorithm: " + getAlgorithm()); + } + } + + + + + + + + public String getAlgorithm() + { + if (algorithm == null) { + return "SHA1PRNG"; + } + return algorithm; + } + + + + + + + public void setAlgorithm(String algorithm) + { + this.algorithm = algorithm; + } + + + + + public String getProvider() + { + return provider; + } + + + + + + public void setProvider(String provider) + { + this.provider = provider; + } +} diff --git a/src/minecraft/ch/qos/logback/core/net/ssl/TrustManagerFactoryFactoryBean.java b/src/minecraft/ch/qos/logback/core/net/ssl/TrustManagerFactoryFactoryBean.java new file mode 100644 index 0000000..a30d2aa --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/net/ssl/TrustManagerFactoryFactoryBean.java @@ -0,0 +1,90 @@ +package ch.qos.logback.core.net.ssl; + +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import javax.net.ssl.TrustManagerFactory; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class TrustManagerFactoryFactoryBean +{ + private String algorithm; + private String provider; + + public TrustManagerFactoryFactoryBean() {} + + public TrustManagerFactory createTrustManagerFactory() + throws NoSuchProviderException, NoSuchAlgorithmException + { + return getProvider() != null ? TrustManagerFactory.getInstance(getAlgorithm(), getProvider()) : TrustManagerFactory.getInstance(getAlgorithm()); + } + + + + + + + + + public String getAlgorithm() + { + if (algorithm == null) { + return TrustManagerFactory.getDefaultAlgorithm(); + } + return algorithm; + } + + + + + + + public void setAlgorithm(String algorithm) + { + this.algorithm = algorithm; + } + + + + + public String getProvider() + { + return provider; + } + + + + + + public void setProvider(String provider) + { + this.provider = provider; + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/CompositeConverter.java b/src/minecraft/ch/qos/logback/core/pattern/CompositeConverter.java new file mode 100644 index 0000000..4164fb1 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/CompositeConverter.java @@ -0,0 +1,53 @@ +package ch.qos.logback.core.pattern; + + + + +public abstract class CompositeConverter + extends DynamicConverter +{ + Converter childConverter; + + + + + public CompositeConverter() {} + + + + + public String convert(E event) + { + StringBuilder buf = new StringBuilder(); + + for (Converter c = childConverter; c != null; c = next) { + c.write(buf, event); + } + String intermediary = buf.toString(); + return transform(event, intermediary); + } + + protected abstract String transform(E paramE, String paramString); + + public Converter getChildConverter() { + return childConverter; + } + + public void setChildConverter(Converter child) { + childConverter = child; + } + + public String toString() { + StringBuilder buf = new StringBuilder(); + buf.append("CompositeConverter<"); + + if (formattingInfo != null) { + buf.append(formattingInfo); + } + if (childConverter != null) { + buf.append(", children: ").append(childConverter); + } + buf.append(">"); + return buf.toString(); + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/Converter.java b/src/minecraft/ch/qos/logback/core/pattern/Converter.java new file mode 100644 index 0000000..57df346 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/Converter.java @@ -0,0 +1,55 @@ +package ch.qos.logback.core.pattern; + + + + + + + + + +public abstract class Converter +{ + Converter next; + + + + + + + + + public Converter() {} + + + + + + + + + public abstract String convert(E paramE); + + + + + + + + + public void write(StringBuilder buf, E event) + { + buf.append(convert(event)); + } + + public final void setNext(Converter next) { + if (this.next != null) { + throw new IllegalStateException("Next converter has been already set"); + } + this.next = next; + } + + public final Converter getNext() { + return next; + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/ConverterUtil.java b/src/minecraft/ch/qos/logback/core/pattern/ConverterUtil.java new file mode 100644 index 0000000..19e54c6 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/ConverterUtil.java @@ -0,0 +1,66 @@ +package ch.qos.logback.core.pattern; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.spi.ContextAware; + + + + + + + + + + + + + + + + +public class ConverterUtil +{ + public ConverterUtil() {} + + public static void startConverters(Converter head) + { + Converter c = head; + while (c != null) + { + if ((c instanceof CompositeConverter)) { + CompositeConverter cc = (CompositeConverter)c; + Converter childConverter = childConverter; + startConverters(childConverter); + cc.start(); + } else if ((c instanceof DynamicConverter)) { + DynamicConverter dc = (DynamicConverter)c; + dc.start(); + } + c = c.getNext(); + } + } + + public static Converter findTail(Converter head) + { + Converter p = head; + while (p != null) { + Converter next = p.getNext(); + if (next == null) { + break; + } + p = next; + } + + return p; + } + + public static void setContextForConverters(Context context, Converter head) { + Converter c = head; + while (c != null) { + if ((c instanceof ContextAware)) { + ((ContextAware)c).setContext(context); + } + c = c.getNext(); + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/DynamicConverter.java b/src/minecraft/ch/qos/logback/core/pattern/DynamicConverter.java new file mode 100644 index 0000000..66bde60 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/DynamicConverter.java @@ -0,0 +1,112 @@ +package ch.qos.logback.core.pattern; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.spi.ContextAware; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.spi.LifeCycle; +import ch.qos.logback.core.status.Status; +import java.util.List; + + + + + + + + + + + + + + +public abstract class DynamicConverter + extends FormattingConverter + implements LifeCycle, ContextAware +{ + ContextAwareBase cab = new ContextAwareBase(this); + + + + private List optionList; + + + + protected boolean started = false; + + + + public DynamicConverter() {} + + + public void start() + { + started = true; + } + + public void stop() { + started = false; + } + + public boolean isStarted() { + return started; + } + + public void setOptionList(List optionList) { + this.optionList = optionList; + } + + + + + + + public String getFirstOption() + { + if ((optionList == null) || (optionList.size() == 0)) { + return null; + } + return (String)optionList.get(0); + } + + protected List getOptionList() + { + return optionList; + } + + public void setContext(Context context) { + cab.setContext(context); + } + + public Context getContext() { + return cab.getContext(); + } + + public void addStatus(Status status) { + cab.addStatus(status); + } + + public void addInfo(String msg) { + cab.addInfo(msg); + } + + public void addInfo(String msg, Throwable ex) { + cab.addInfo(msg, ex); + } + + public void addWarn(String msg) { + cab.addWarn(msg); + } + + public void addWarn(String msg, Throwable ex) { + cab.addWarn(msg, ex); + } + + public void addError(String msg) { + cab.addError(msg); + } + + public void addError(String msg, Throwable ex) { + cab.addError(msg, ex); + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/FormatInfo.java b/src/minecraft/ch/qos/logback/core/pattern/FormatInfo.java new file mode 100644 index 0000000..3aea676 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/FormatInfo.java @@ -0,0 +1,154 @@ +package ch.qos.logback.core.pattern; + + + + + + + + + + + + + + + + + + + +public class FormatInfo +{ + private int min = Integer.MIN_VALUE; + private int max = Integer.MAX_VALUE; + private boolean leftPad = true; + private boolean leftTruncate = true; + + public FormatInfo() {} + + public FormatInfo(int min, int max) + { + this.min = min; + this.max = max; + } + + public FormatInfo(int min, int max, boolean leftPad, boolean leftTruncate) { + this.min = min; + this.max = max; + this.leftPad = leftPad; + this.leftTruncate = leftTruncate; + } + + + + + + + + public static FormatInfo valueOf(String str) + throws IllegalArgumentException + { + if (str == null) { + throw new NullPointerException("Argument cannot be null"); + } + + FormatInfo fi = new FormatInfo(); + + int indexOfDot = str.indexOf('.'); + String minPart = null; + String maxPart = null; + if (indexOfDot != -1) { + minPart = str.substring(0, indexOfDot); + if (indexOfDot + 1 == str.length()) { + throw new IllegalArgumentException("Formatting string [" + str + "] should not end with '.'"); + } + + maxPart = str.substring(indexOfDot + 1); + } + else { + minPart = str; + } + + if ((minPart != null) && (minPart.length() > 0)) { + int min = Integer.parseInt(minPart); + if (min >= 0) { + min = min; + } else { + min = (-min); + leftPad = false; + } + } + + if ((maxPart != null) && (maxPart.length() > 0)) { + int max = Integer.parseInt(maxPart); + if (max >= 0) { + max = max; + } else { + max = (-max); + leftTruncate = false; + } + } + + return fi; + } + + public boolean isLeftPad() + { + return leftPad; + } + + public void setLeftPad(boolean leftAlign) { + leftPad = leftAlign; + } + + public int getMax() { + return max; + } + + public void setMax(int max) { + this.max = max; + } + + public int getMin() { + return min; + } + + public void setMin(int min) { + this.min = min; + } + + public boolean isLeftTruncate() { + return leftTruncate; + } + + public void setLeftTruncate(boolean leftTruncate) { + this.leftTruncate = leftTruncate; + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof FormatInfo)) { + return false; + } + FormatInfo r = (FormatInfo)o; + + return (min == min) && (max == max) && (leftPad == leftPad) && (leftTruncate == leftTruncate); + } + + + public int hashCode() + { + int result = min; + result = 31 * result + max; + result = 31 * result + (leftPad ? 1 : 0); + result = 31 * result + (leftTruncate ? 1 : 0); + return result; + } + + public String toString() { + return "FormatInfo(" + min + ", " + max + ", " + leftPad + ", " + leftTruncate + ")"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/FormattingConverter.java b/src/minecraft/ch/qos/logback/core/pattern/FormattingConverter.java new file mode 100644 index 0000000..413be24 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/FormattingConverter.java @@ -0,0 +1,72 @@ +package ch.qos.logback.core.pattern; + + + + +public abstract class FormattingConverter + extends Converter +{ + static final int INITIAL_BUF_SIZE = 256; + + + static final int MAX_CAPACITY = 1024; + + + FormatInfo formattingInfo; + + + + public FormattingConverter() {} + + + + public final FormatInfo getFormattingInfo() + { + return formattingInfo; + } + + public final void setFormattingInfo(FormatInfo formattingInfo) { + if (this.formattingInfo != null) { + throw new IllegalStateException("FormattingInfo has been already set"); + } + this.formattingInfo = formattingInfo; + } + + public final void write(StringBuilder buf, E event) + { + String s = convert(event); + + if (formattingInfo == null) { + buf.append(s); + return; + } + + int min = formattingInfo.getMin(); + int max = formattingInfo.getMax(); + + + if (s == null) { + if (0 < min) + SpacePadder.spacePad(buf, min); + return; + } + + int len = s.length(); + + if (len > max) { + if (formattingInfo.isLeftTruncate()) { + buf.append(s.substring(len - max)); + } else { + buf.append(s.substring(0, max)); + } + } else if (len < min) { + if (formattingInfo.isLeftPad()) { + SpacePadder.leftPad(buf, s, min); + } else { + SpacePadder.rightPad(buf, s, min); + } + } else { + buf.append(s); + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/IdentityCompositeConverter.java b/src/minecraft/ch/qos/logback/core/pattern/IdentityCompositeConverter.java new file mode 100644 index 0000000..48ac6af --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/IdentityCompositeConverter.java @@ -0,0 +1,22 @@ +package ch.qos.logback.core.pattern; + + + + + + +public class IdentityCompositeConverter + extends CompositeConverter +{ + public IdentityCompositeConverter() {} + + + + + + + protected String transform(E event, String in) + { + return in; + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/LiteralConverter.java b/src/minecraft/ch/qos/logback/core/pattern/LiteralConverter.java new file mode 100644 index 0000000..4772e71 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/LiteralConverter.java @@ -0,0 +1,27 @@ +package ch.qos.logback.core.pattern; + + + + + + + +public final class LiteralConverter + extends Converter +{ + String literal; + + + + + + + public LiteralConverter(String literal) + { + this.literal = literal; + } + + public String convert(E o) { + return literal; + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/PatternLayoutBase.java b/src/minecraft/ch/qos/logback/core/pattern/PatternLayoutBase.java new file mode 100644 index 0000000..5292ca1 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/PatternLayoutBase.java @@ -0,0 +1,161 @@ +package ch.qos.logback.core.pattern; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.LayoutBase; +import ch.qos.logback.core.pattern.parser.Node; +import ch.qos.logback.core.pattern.parser.Parser; +import ch.qos.logback.core.spi.ScanException; +import ch.qos.logback.core.status.ErrorStatus; +import ch.qos.logback.core.status.StatusManager; +import java.util.HashMap; +import java.util.Map; + + + + + + + + + + + + + + + + + + +public abstract class PatternLayoutBase + extends LayoutBase +{ + Converter head; + String pattern; + protected PostCompileProcessor postCompileProcessor; + Map instanceConverterMap = new HashMap(); + protected boolean outputPatternAsHeader = false; + + + + + public PatternLayoutBase() {} + + + + public abstract Map getDefaultConverterMap(); + + + + public Map getEffectiveConverterMap() + { + Map effectiveMap = new HashMap(); + + + Map defaultMap = getDefaultConverterMap(); + if (defaultMap != null) { + effectiveMap.putAll(defaultMap); + } + + + Context context = getContext(); + if (context != null) + { + Map contextMap = (Map)context.getObject("PATTERN_RULE_REGISTRY"); + + if (contextMap != null) { + effectiveMap.putAll(contextMap); + } + } + + effectiveMap.putAll(instanceConverterMap); + return effectiveMap; + } + + public void start() { + if ((pattern == null) || (pattern.length() == 0)) { + addError("Empty or null pattern."); + return; + } + try { + Parser p = new Parser(pattern); + if (getContext() != null) { + p.setContext(getContext()); + } + Node t = p.parse(); + head = p.compile(t, getEffectiveConverterMap()); + if (postCompileProcessor != null) { + postCompileProcessor.process(head); + } + ConverterUtil.setContextForConverters(getContext(), head); + ConverterUtil.startConverters(head); + super.start(); + } catch (ScanException sce) { + StatusManager sm = getContext().getStatusManager(); + sm.add(new ErrorStatus("Failed to parse pattern \"" + getPattern() + "\".", this, sce)); + } + } + + + public void setPostCompileProcessor(PostCompileProcessor postCompileProcessor) + { + this.postCompileProcessor = postCompileProcessor; + } + + + + /** + * @deprecated + */ + protected void setContextForConverters(Converter head) + { + ConverterUtil.setContextForConverters(getContext(), head); + } + + protected String writeLoopOnConverters(E event) { + StringBuilder buf = new StringBuilder(128); + Converter c = head; + while (c != null) { + c.write(buf, event); + c = c.getNext(); + } + return buf.toString(); + } + + public String getPattern() { + return pattern; + } + + public void setPattern(String pattern) { + this.pattern = pattern; + } + + public String toString() { + return getClass().getName() + "(\"" + getPattern() + "\")"; + } + + public Map getInstanceConverterMap() { + return instanceConverterMap; + } + + protected String getPresentationHeaderPrefix() + { + return ""; + } + + public boolean isOutputPatternAsHeader() { + return outputPatternAsHeader; + } + + public void setOutputPatternAsHeader(boolean outputPatternAsHeader) { + this.outputPatternAsHeader = outputPatternAsHeader; + } + + public String getPresentationHeader() + { + if (outputPatternAsHeader) { + return getPresentationHeaderPrefix() + pattern; + } + return super.getPresentationHeader(); + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/PatternLayoutEncoderBase.java b/src/minecraft/ch/qos/logback/core/pattern/PatternLayoutEncoderBase.java new file mode 100644 index 0000000..0fada15 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/PatternLayoutEncoderBase.java @@ -0,0 +1,66 @@ +package ch.qos.logback.core.pattern; + +import ch.qos.logback.core.Layout; +import ch.qos.logback.core.encoder.LayoutWrappingEncoder; + + + + + + + + + + + + +public class PatternLayoutEncoderBase + extends LayoutWrappingEncoder +{ + String pattern; + + public PatternLayoutEncoderBase() {} + + protected boolean outputPatternAsHeader = false; + + public String getPattern() { + return pattern; + } + + public void setPattern(String pattern) { + this.pattern = pattern; + } + + public boolean isOutputPatternAsHeader() { + return outputPatternAsHeader; + } + + + + + + + + public void setOutputPatternAsHeader(boolean outputPatternAsHeader) + { + this.outputPatternAsHeader = outputPatternAsHeader; + } + + public boolean isOutputPatternAsPresentationHeader() + { + return outputPatternAsHeader; + } + + /** + * @deprecated + */ + public void setOutputPatternAsPresentationHeader(boolean outputPatternAsHeader) { + addWarn("[outputPatternAsPresentationHeader] property is deprecated. Please use [outputPatternAsHeader] option instead."); + this.outputPatternAsHeader = outputPatternAsHeader; + } + + public void setLayout(Layout layout) + { + throw new UnsupportedOperationException("one cannot set the layout of " + getClass().getName()); + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/PostCompileProcessor.java b/src/minecraft/ch/qos/logback/core/pattern/PostCompileProcessor.java new file mode 100644 index 0000000..b8ffbd4 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/PostCompileProcessor.java @@ -0,0 +1,6 @@ +package ch.qos.logback.core.pattern; + +public abstract interface PostCompileProcessor +{ + public abstract void process(Converter paramConverter); +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java b/src/minecraft/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java new file mode 100644 index 0000000..93100e5 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java @@ -0,0 +1,50 @@ +package ch.qos.logback.core.pattern; + +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + + + + + + + + +public class ReplacingCompositeConverter + extends CompositeConverter +{ + Pattern pattern; + String regex; + String replacement; + + public ReplacingCompositeConverter() {} + + public void start() + { + List optionList = getOptionList(); + if (optionList == null) { + addError("at least two options are expected whereas you have declared none"); + return; + } + + int numOpts = optionList.size(); + + if (numOpts < 2) { + addError("at least two options are expected whereas you have declared only " + numOpts + "as [" + optionList + "]"); + return; + } + regex = ((String)optionList.get(0)); + pattern = Pattern.compile(regex); + replacement = ((String)optionList.get(1)); + super.start(); + } + + protected String transform(E event, String in) + { + if (!started) + return in; + return pattern.matcher(in).replaceAll(replacement); + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/SpacePadder.java b/src/minecraft/ch/qos/logback/core/pattern/SpacePadder.java new file mode 100644 index 0000000..8011e05 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/SpacePadder.java @@ -0,0 +1,64 @@ +package ch.qos.logback.core.pattern; + + + + + + + + + + + + + + +public class SpacePadder +{ + static final String[] SPACES = { " ", " ", " ", " ", " ", " " }; + + public SpacePadder() {} + + public static final void leftPad(StringBuilder buf, String s, int desiredLength) + { + int actualLen = 0; + if (s != null) { + actualLen = s.length(); + } + if (actualLen < desiredLength) { + spacePad(buf, desiredLength - actualLen); + } + if (s != null) { + buf.append(s); + } + } + + public static final void rightPad(StringBuilder buf, String s, int desiredLength) { + int actualLen = 0; + if (s != null) { + actualLen = s.length(); + } + if (s != null) { + buf.append(s); + } + if (actualLen < desiredLength) { + spacePad(buf, desiredLength - actualLen); + } + } + + + + public static final void spacePad(StringBuilder sbuf, int length) + { + while (length >= 32) { + sbuf.append(SPACES[5]); + length -= 32; + } + + for (int i = 4; i >= 0; i--) { + if ((length & 1 << i) != 0) { + sbuf.append(SPACES[i]); + } + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/color/ANSIConstants.java b/src/minecraft/ch/qos/logback/core/pattern/color/ANSIConstants.java new file mode 100644 index 0000000..5b13941 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/color/ANSIConstants.java @@ -0,0 +1,19 @@ +package ch.qos.logback.core.pattern.color; + +public class ANSIConstants +{ + public static final String ESC_START = "\033["; + public static final String ESC_END = "m"; + public static final String BOLD = "1;"; + public static final String BLACK_FG = "30"; + public static final String RED_FG = "31"; + public static final String GREEN_FG = "32"; + public static final String YELLOW_FG = "33"; + public static final String BLUE_FG = "34"; + public static final String MAGENTA_FG = "35"; + public static final String CYAN_FG = "36"; + public static final String WHITE_FG = "37"; + public static final String DEFAULT_FG = "39"; + + public ANSIConstants() {} +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/color/BlackCompositeConverter.java b/src/minecraft/ch/qos/logback/core/pattern/color/BlackCompositeConverter.java new file mode 100644 index 0000000..89e77b7 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/color/BlackCompositeConverter.java @@ -0,0 +1,28 @@ +package ch.qos.logback.core.pattern.color; + + + + + + + + + +public class BlackCompositeConverter + extends ForegroundCompositeConverterBase +{ + public BlackCompositeConverter() {} + + + + + + + + + + protected String getForegroundColorCode(E event) + { + return "30"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/color/BlueCompositeConverter.java b/src/minecraft/ch/qos/logback/core/pattern/color/BlueCompositeConverter.java new file mode 100644 index 0000000..1922ea8 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/color/BlueCompositeConverter.java @@ -0,0 +1,28 @@ +package ch.qos.logback.core.pattern.color; + + + + + + + + + +public class BlueCompositeConverter + extends ForegroundCompositeConverterBase +{ + public BlueCompositeConverter() {} + + + + + + + + + + protected String getForegroundColorCode(E event) + { + return "34"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/color/BoldBlueCompositeConverter.java b/src/minecraft/ch/qos/logback/core/pattern/color/BoldBlueCompositeConverter.java new file mode 100644 index 0000000..9c42d19 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/color/BoldBlueCompositeConverter.java @@ -0,0 +1,32 @@ +package ch.qos.logback.core.pattern.color; + + + + + + + + + + + +public class BoldBlueCompositeConverter + extends ForegroundCompositeConverterBase +{ + public BoldBlueCompositeConverter() {} + + + + + + + + + + + + protected String getForegroundColorCode(E event) + { + return "1;34"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/color/BoldCyanCompositeConverter.java b/src/minecraft/ch/qos/logback/core/pattern/color/BoldCyanCompositeConverter.java new file mode 100644 index 0000000..c2d1105 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/color/BoldCyanCompositeConverter.java @@ -0,0 +1,32 @@ +package ch.qos.logback.core.pattern.color; + + + + + + + + + + + +public class BoldCyanCompositeConverter + extends ForegroundCompositeConverterBase +{ + public BoldCyanCompositeConverter() {} + + + + + + + + + + + + protected String getForegroundColorCode(E event) + { + return "1;36"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/color/BoldGreenCompositeConverter.java b/src/minecraft/ch/qos/logback/core/pattern/color/BoldGreenCompositeConverter.java new file mode 100644 index 0000000..0801ef8 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/color/BoldGreenCompositeConverter.java @@ -0,0 +1,32 @@ +package ch.qos.logback.core.pattern.color; + + + + + + + + + + + +public class BoldGreenCompositeConverter + extends ForegroundCompositeConverterBase +{ + public BoldGreenCompositeConverter() {} + + + + + + + + + + + + protected String getForegroundColorCode(E event) + { + return "1;32"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/color/BoldMagentaCompositeConverter.java b/src/minecraft/ch/qos/logback/core/pattern/color/BoldMagentaCompositeConverter.java new file mode 100644 index 0000000..0d980d0 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/color/BoldMagentaCompositeConverter.java @@ -0,0 +1,32 @@ +package ch.qos.logback.core.pattern.color; + + + + + + + + + + + +public class BoldMagentaCompositeConverter + extends ForegroundCompositeConverterBase +{ + public BoldMagentaCompositeConverter() {} + + + + + + + + + + + + protected String getForegroundColorCode(E event) + { + return "1;35"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/color/BoldRedCompositeConverter.java b/src/minecraft/ch/qos/logback/core/pattern/color/BoldRedCompositeConverter.java new file mode 100644 index 0000000..cf0a126 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/color/BoldRedCompositeConverter.java @@ -0,0 +1,30 @@ +package ch.qos.logback.core.pattern.color; + + + + + + + + + + +public class BoldRedCompositeConverter + extends ForegroundCompositeConverterBase +{ + public BoldRedCompositeConverter() {} + + + + + + + + + + + protected String getForegroundColorCode(E event) + { + return "1;31"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/color/BoldWhiteCompositeConverter.java b/src/minecraft/ch/qos/logback/core/pattern/color/BoldWhiteCompositeConverter.java new file mode 100644 index 0000000..f2c7301 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/color/BoldWhiteCompositeConverter.java @@ -0,0 +1,32 @@ +package ch.qos.logback.core.pattern.color; + + + + + + + + + + + +public class BoldWhiteCompositeConverter + extends ForegroundCompositeConverterBase +{ + public BoldWhiteCompositeConverter() {} + + + + + + + + + + + + protected String getForegroundColorCode(E event) + { + return "1;37"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/color/BoldYellowCompositeConverter.java b/src/minecraft/ch/qos/logback/core/pattern/color/BoldYellowCompositeConverter.java new file mode 100644 index 0000000..436148b --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/color/BoldYellowCompositeConverter.java @@ -0,0 +1,32 @@ +package ch.qos.logback.core.pattern.color; + + + + + + + + + + + +public class BoldYellowCompositeConverter + extends ForegroundCompositeConverterBase +{ + public BoldYellowCompositeConverter() {} + + + + + + + + + + + + protected String getForegroundColorCode(E event) + { + return "1;33"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/color/CyanCompositeConverter.java b/src/minecraft/ch/qos/logback/core/pattern/color/CyanCompositeConverter.java new file mode 100644 index 0000000..a9f2009 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/color/CyanCompositeConverter.java @@ -0,0 +1,28 @@ +package ch.qos.logback.core.pattern.color; + + + + + + + + + +public class CyanCompositeConverter + extends ForegroundCompositeConverterBase +{ + public CyanCompositeConverter() {} + + + + + + + + + + protected String getForegroundColorCode(E event) + { + return "36"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/color/ForegroundCompositeConverterBase.java b/src/minecraft/ch/qos/logback/core/pattern/color/ForegroundCompositeConverterBase.java new file mode 100644 index 0000000..a43a9c7 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/color/ForegroundCompositeConverterBase.java @@ -0,0 +1,41 @@ +package ch.qos.logback.core.pattern.color; + +import ch.qos.logback.core.pattern.CompositeConverter; + + + + + + + + + + + + + + + + + + +public abstract class ForegroundCompositeConverterBase + extends CompositeConverter +{ + private static final String SET_DEFAULT_COLOR = "\033[0;39m"; + + public ForegroundCompositeConverterBase() {} + + protected String transform(E event, String in) + { + StringBuilder sb = new StringBuilder(); + sb.append("\033["); + sb.append(getForegroundColorCode(event)); + sb.append("m"); + sb.append(in); + sb.append("\033[0;39m"); + return sb.toString(); + } + + protected abstract String getForegroundColorCode(E paramE); +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/color/GrayCompositeConverter.java b/src/minecraft/ch/qos/logback/core/pattern/color/GrayCompositeConverter.java new file mode 100644 index 0000000..73ffb3c --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/color/GrayCompositeConverter.java @@ -0,0 +1,32 @@ +package ch.qos.logback.core.pattern.color; + + + + + + + + + + + +public class GrayCompositeConverter + extends ForegroundCompositeConverterBase +{ + public GrayCompositeConverter() {} + + + + + + + + + + + + protected String getForegroundColorCode(E event) + { + return "1;30"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/color/GreenCompositeConverter.java b/src/minecraft/ch/qos/logback/core/pattern/color/GreenCompositeConverter.java new file mode 100644 index 0000000..fa8cd59 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/color/GreenCompositeConverter.java @@ -0,0 +1,28 @@ +package ch.qos.logback.core.pattern.color; + + + + + + + + + +public class GreenCompositeConverter + extends ForegroundCompositeConverterBase +{ + public GreenCompositeConverter() {} + + + + + + + + + + protected String getForegroundColorCode(E event) + { + return "32"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/color/MagentaCompositeConverter.java b/src/minecraft/ch/qos/logback/core/pattern/color/MagentaCompositeConverter.java new file mode 100644 index 0000000..79e4fb4 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/color/MagentaCompositeConverter.java @@ -0,0 +1,28 @@ +package ch.qos.logback.core.pattern.color; + + + + + + + + + +public class MagentaCompositeConverter + extends ForegroundCompositeConverterBase +{ + public MagentaCompositeConverter() {} + + + + + + + + + + protected String getForegroundColorCode(E event) + { + return "35"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/color/RedCompositeConverter.java b/src/minecraft/ch/qos/logback/core/pattern/color/RedCompositeConverter.java new file mode 100644 index 0000000..7e8c063 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/color/RedCompositeConverter.java @@ -0,0 +1,28 @@ +package ch.qos.logback.core.pattern.color; + + + + + + + + + +public class RedCompositeConverter + extends ForegroundCompositeConverterBase +{ + public RedCompositeConverter() {} + + + + + + + + + + protected String getForegroundColorCode(E event) + { + return "31"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/color/WhiteCompositeConverter.java b/src/minecraft/ch/qos/logback/core/pattern/color/WhiteCompositeConverter.java new file mode 100644 index 0000000..402c35e --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/color/WhiteCompositeConverter.java @@ -0,0 +1,28 @@ +package ch.qos.logback.core.pattern.color; + + + + + + + + + +public class WhiteCompositeConverter + extends ForegroundCompositeConverterBase +{ + public WhiteCompositeConverter() {} + + + + + + + + + + protected String getForegroundColorCode(E event) + { + return "37"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/color/YellowCompositeConverter.java b/src/minecraft/ch/qos/logback/core/pattern/color/YellowCompositeConverter.java new file mode 100644 index 0000000..7e83ba8 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/color/YellowCompositeConverter.java @@ -0,0 +1,28 @@ +package ch.qos.logback.core.pattern.color; + + + + + + + + + +public class YellowCompositeConverter + extends ForegroundCompositeConverterBase +{ + public YellowCompositeConverter() {} + + + + + + + + + + protected String getForegroundColorCode(E event) + { + return "33"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/parser/Compiler.java b/src/minecraft/ch/qos/logback/core/pattern/parser/Compiler.java new file mode 100644 index 0000000..fdd8074 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/parser/Compiler.java @@ -0,0 +1,147 @@ +package ch.qos.logback.core.pattern.parser; + +import ch.qos.logback.core.pattern.CompositeConverter; +import ch.qos.logback.core.pattern.Converter; +import ch.qos.logback.core.pattern.DynamicConverter; +import ch.qos.logback.core.pattern.LiteralConverter; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.status.ErrorStatus; +import ch.qos.logback.core.util.OptionHelper; +import java.util.Map; + + + + + + + + + + + + + +class Compiler + extends ContextAwareBase +{ + Converter head; + Converter tail; + final Node top; + final Map converterMap; + + Compiler(Node top, Map converterMap) + { + this.top = top; + this.converterMap = converterMap; + } + + Converter compile() { + head = (this.tail = null); + for (Node n = top; n != null; n = next) { + switch (type) { + case 0: + addToList(new LiteralConverter((String)n.getValue())); + break; + case 2: + CompositeNode cn = (CompositeNode)n; + CompositeConverter compositeConverter = createCompositeConverter(cn); + if (compositeConverter == null) { + addError("Failed to create converter for [%" + cn.getValue() + "] keyword"); + addToList(new LiteralConverter("%PARSER_ERROR[" + cn.getValue() + "]")); + } + else { + compositeConverter.setFormattingInfo(cn.getFormatInfo()); + compositeConverter.setOptionList(cn.getOptions()); + Compiler childCompiler = new Compiler(cn.getChildNode(), converterMap); + + childCompiler.setContext(context); + Converter childConverter = childCompiler.compile(); + compositeConverter.setChildConverter(childConverter); + addToList(compositeConverter); } + break; + case 1: + SimpleKeywordNode kn = (SimpleKeywordNode)n; + DynamicConverter dynaConverter = createConverter(kn); + if (dynaConverter != null) { + dynaConverter.setFormattingInfo(kn.getFormatInfo()); + dynaConverter.setOptionList(kn.getOptions()); + addToList(dynaConverter); + } + else + { + Converter errConveter = new LiteralConverter("%PARSER_ERROR[" + kn.getValue() + "]"); + + addStatus(new ErrorStatus("[" + kn.getValue() + "] is not a valid conversion word", this)); + + addToList(errConveter); + } + break; + } + } + return head; + } + + private void addToList(Converter c) { + if (head == null) { + head = (this.tail = c); + } else { + tail.setNext(c); + tail = c; + } + } + + + + + + + + + DynamicConverter createConverter(SimpleKeywordNode kn) + { + String keyword = (String)kn.getValue(); + String converterClassStr = (String)converterMap.get(keyword); + + if (converterClassStr != null) { + try { + return (DynamicConverter)OptionHelper.instantiateByClassName(converterClassStr, DynamicConverter.class, context); + } + catch (Exception e) { + addError("Failed to instantiate converter class [" + converterClassStr + "] for keyword [" + keyword + "]", e); + + return null; + } + } + addError("There is no conversion class registered for conversion word [" + keyword + "]"); + + return null; + } + + + + + + + + + + CompositeConverter createCompositeConverter(CompositeNode cn) + { + String keyword = (String)cn.getValue(); + String converterClassStr = (String)converterMap.get(keyword); + + if (converterClassStr != null) { + try { + return (CompositeConverter)OptionHelper.instantiateByClassName(converterClassStr, CompositeConverter.class, context); + } + catch (Exception e) { + addError("Failed to instantiate converter class [" + converterClassStr + "] as a composite converter for keyword [" + keyword + "]", e); + + return null; + } + } + addError("There is no conversion class registered for composite conversion word [" + keyword + "]"); + + return null; + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/parser/CompositeNode.java b/src/minecraft/ch/qos/logback/core/pattern/parser/CompositeNode.java new file mode 100644 index 0000000..1e97306 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/parser/CompositeNode.java @@ -0,0 +1,60 @@ +package ch.qos.logback.core.pattern.parser; + + + + + + +public class CompositeNode + extends SimpleKeywordNode +{ + Node childNode; + + + + + + + CompositeNode(String keyword) + { + super(2, keyword); + } + + public Node getChildNode() + { + return childNode; + } + + public void setChildNode(Node childNode) { + this.childNode = childNode; + } + + public boolean equals(Object o) { + if (!super.equals(o)) { + return false; + } + if (!(o instanceof CompositeNode)) { + return false; + } + CompositeNode r = (CompositeNode)o; + + return childNode == null ? true : childNode != null ? childNode.equals(childNode) : false; + } + + + public int hashCode() + { + return super.hashCode(); + } + + public String toString() { + StringBuilder buf = new StringBuilder(); + if (childNode != null) { + buf.append("CompositeNode(" + childNode + ")"); + } else { + buf.append("CompositeNode(no child)"); + } + buf.append(printNext()); + return buf.toString(); + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/parser/FormattingNode.java b/src/minecraft/ch/qos/logback/core/pattern/parser/FormattingNode.java new file mode 100644 index 0000000..30aa9dc --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/parser/FormattingNode.java @@ -0,0 +1,58 @@ +package ch.qos.logback.core.pattern.parser; + +import ch.qos.logback.core.pattern.FormatInfo; + + + + + + + + + + + + +public class FormattingNode + extends Node +{ + FormatInfo formatInfo; + + FormattingNode(int type) + { + super(type); + } + + FormattingNode(int type, Object value) { + super(type, value); + } + + public FormatInfo getFormatInfo() { + return formatInfo; + } + + public void setFormatInfo(FormatInfo formatInfo) { + this.formatInfo = formatInfo; + } + + public boolean equals(Object o) { + if (!super.equals(o)) { + return false; + } + + if (!(o instanceof FormattingNode)) { + return false; + } + FormattingNode r = (FormattingNode)o; + + return formatInfo == null ? true : formatInfo != null ? formatInfo.equals(formatInfo) : false; + } + + + public int hashCode() + { + int result = super.hashCode(); + result = 31 * result + (formatInfo != null ? formatInfo.hashCode() : 0); + return result; + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/parser/Node.java b/src/minecraft/ch/qos/logback/core/pattern/parser/Node.java new file mode 100644 index 0000000..ad80537 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/parser/Node.java @@ -0,0 +1,99 @@ +package ch.qos.logback.core.pattern.parser; + + + +public class Node +{ + static final int LITERAL = 0; + + + static final int SIMPLE_KEYWORD = 1; + + + static final int COMPOSITE_KEYWORD = 2; + + + final int type; + + + final Object value; + + Node next; + + + Node(int type) + { + this(type, null); + } + + Node(int type, Object value) { + this.type = type; + this.value = value; + } + + + + public int getType() + { + return type; + } + + + + public Object getValue() + { + return value; + } + + public Node getNext() { + return next; + } + + public void setNext(Node next) { + this.next = next; + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Node)) { + return false; + } + Node r = (Node)o; + + return (type == type) && (value != null ? value.equals(value) : value == null) && (next != null ? next.equals(next) : next == null); + } + + + + public int hashCode() + { + int result = type; + result = 31 * result + (value != null ? value.hashCode() : 0); + return result; + } + + String printNext() { + if (next != null) { + return " -> " + next; + } + return ""; + } + + public String toString() + { + StringBuilder buf = new StringBuilder(); + switch (type) { + case 0: + buf.append("LITERAL(" + value + ")"); + break; + default: + buf.append(super.toString()); + } + + buf.append(printNext()); + + return buf.toString(); + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/parser/OptionTokenizer.java b/src/minecraft/ch/qos/logback/core/pattern/parser/OptionTokenizer.java new file mode 100644 index 0000000..56d4c0a --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/parser/OptionTokenizer.java @@ -0,0 +1,148 @@ +package ch.qos.logback.core.pattern.parser; + +import ch.qos.logback.core.pattern.util.AsIsEscapeUtil; +import ch.qos.logback.core.pattern.util.IEscapeUtil; +import ch.qos.logback.core.spi.ScanException; +import java.util.ArrayList; +import java.util.List; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class OptionTokenizer +{ + private static final int EXPECTING_STATE = 0; + private static final int RAW_COLLECTING_STATE = 1; + private static final int QUOTED_COLLECTING_STATE = 2; + final IEscapeUtil escapeUtil; + final TokenStream tokenStream; + final String pattern; + final int patternLength; + char quoteChar; + int state = 0; + + OptionTokenizer(TokenStream tokenStream) { + this(tokenStream, new AsIsEscapeUtil()); + } + + OptionTokenizer(TokenStream tokenStream, IEscapeUtil escapeUtil) { + this.tokenStream = tokenStream; + pattern = pattern; + patternLength = patternLength; + this.escapeUtil = escapeUtil; + } + + void tokenize(char firstChar, List tokenList) throws ScanException { + StringBuffer buf = new StringBuffer(); + List optionList = new ArrayList(); + char c = firstChar; + + while (tokenStream.pointer < patternLength) { + switch (state) { + case 0: + switch (c) { + case '\t': + case '\n': + case '\r': + case ' ': + case ',': + break; + case '"': + case '\'': + state = 2; + quoteChar = c; + break; + case '}': + emitOptionToken(tokenList, optionList); + return; + default: + buf.append(c); + state = 1; + } + break; + case 1: + switch (c) { + case ',': + optionList.add(buf.toString().trim()); + buf.setLength(0); + state = 0; + break; + case '}': + optionList.add(buf.toString().trim()); + emitOptionToken(tokenList, optionList); + return; + default: + buf.append(c); + } + break; + case 2: + if (c == quoteChar) { + optionList.add(buf.toString()); + buf.setLength(0); + state = 0; + } else if (c == '\\') { + escape(String.valueOf(quoteChar), buf); + } else { + buf.append(c); + } + + break; + } + + c = pattern.charAt(tokenStream.pointer); + tokenStream.pointer += 1; + } + + + + if (c == '}') { + if (state == 0) { + emitOptionToken(tokenList, optionList); + } else if (state == 1) { + optionList.add(buf.toString().trim()); + emitOptionToken(tokenList, optionList); + } else { + throw new ScanException("Unexpected end of pattern string in OptionTokenizer"); + } + } else { + throw new ScanException("Unexpected end of pattern string in OptionTokenizer"); + } + } + + void emitOptionToken(List tokenList, List optionList) { + tokenList.add(new Token(1006, optionList)); + tokenStream.state = TokenStream.TokenizerState.LITERAL_STATE; + } + + void escape(String escapeChars, StringBuffer buf) { + if (tokenStream.pointer < patternLength) { + char next = pattern.charAt(tokenStream.pointer++); + escapeUtil.escape(escapeChars, buf, next, tokenStream.pointer); + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/parser/Parser.java b/src/minecraft/ch/qos/logback/core/pattern/parser/Parser.java new file mode 100644 index 0000000..cd1ff50 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/parser/Parser.java @@ -0,0 +1,234 @@ +package ch.qos.logback.core.pattern.parser; + +import ch.qos.logback.core.pattern.Converter; +import ch.qos.logback.core.pattern.FormatInfo; +import ch.qos.logback.core.pattern.IdentityCompositeConverter; +import ch.qos.logback.core.pattern.ReplacingCompositeConverter; +import ch.qos.logback.core.pattern.util.IEscapeUtil; +import ch.qos.logback.core.pattern.util.RegularEscapeUtil; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.spi.ScanException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class Parser + extends ContextAwareBase +{ + public static final String MISSING_RIGHT_PARENTHESIS = "http://logback.qos.ch/codes.html#missingRightParenthesis"; + public static final Map DEFAULT_COMPOSITE_CONVERTER_MAP = new HashMap(); + public static final String REPLACE_CONVERTER_WORD = "replace"; + + static { DEFAULT_COMPOSITE_CONVERTER_MAP.put(Token.BARE_COMPOSITE_KEYWORD_TOKEN.getValue().toString(), IdentityCompositeConverter.class.getName()); + + DEFAULT_COMPOSITE_CONVERTER_MAP.put("replace", ReplacingCompositeConverter.class.getName()); + } + + + final List tokenList; + int pointer = 0; + + Parser(TokenStream ts) throws ScanException { + tokenList = ts.tokenize(); + } + + public Parser(String pattern) throws ScanException { + this(pattern, new RegularEscapeUtil()); + } + + public Parser(String pattern, IEscapeUtil escapeUtil) throws ScanException { + try { + TokenStream ts = new TokenStream(pattern, escapeUtil); + tokenList = ts.tokenize(); + } catch (IllegalArgumentException npe) { + throw new ScanException("Failed to initialize Parser", npe); + } + } + + + + + + + + + + public Converter compile(Node top, Map converterMap) + { + Compiler compiler = new Compiler(top, converterMap); + compiler.setContext(context); + + return compiler.compile(); + } + + public Node parse() throws ScanException { + return E(); + } + + Node E() throws ScanException + { + Node t = T(); + if (t == null) { + return null; + } + Node eOpt = Eopt(); + if (eOpt != null) { + t.setNext(eOpt); + } + return t; + } + + Node Eopt() + throws ScanException + { + Token next = getCurentToken(); + + if (next == null) { + return null; + } + return E(); + } + + Node T() + throws ScanException + { + Token t = getCurentToken(); + expectNotNull(t, "a LITERAL or '%'"); + + switch (t.getType()) { + case 1000: + advanceTokenPointer(); + return new Node(0, t.getValue()); + case 37: + advanceTokenPointer(); + + + Token u = getCurentToken(); + + expectNotNull(u, "a FORMAT_MODIFIER, SIMPLE_KEYWORD or COMPOUND_KEYWORD"); + FormattingNode c; if (u.getType() == 1002) { + FormatInfo fi = FormatInfo.valueOf((String)u.getValue()); + advanceTokenPointer(); + FormattingNode c = C(); + c.setFormatInfo(fi); + } else { + c = C(); + } + return c; + } + + return null; + } + + + FormattingNode C() + throws ScanException + { + Token t = getCurentToken(); + + + expectNotNull(t, "a LEFT_PARENTHESIS or KEYWORD"); + int type = t.getType(); + switch (type) { + case 1004: + return SINGLE(); + case 1005: + advanceTokenPointer(); + return COMPOSITE(t.getValue().toString()); + } + throw new IllegalStateException("Unexpected token " + t); + } + + FormattingNode SINGLE() + throws ScanException + { + Token t = getNextToken(); + + SimpleKeywordNode keywordNode = new SimpleKeywordNode(t.getValue()); + + Token ot = getCurentToken(); + if ((ot != null) && (ot.getType() == 1006)) { + List optionList = (List)ot.getValue(); + keywordNode.setOptions(optionList); + advanceTokenPointer(); + } + return keywordNode; + } + + FormattingNode COMPOSITE(String keyword) throws ScanException { + CompositeNode compositeNode = new CompositeNode(keyword); + + Node childNode = E(); + compositeNode.setChildNode(childNode); + + Token t = getNextToken(); + + if ((t == null) || (t.getType() != 41)) { + String msg = "Expecting RIGHT_PARENTHESIS token but got " + t; + addError(msg); + addError("See also http://logback.qos.ch/codes.html#missingRightParenthesis"); + throw new ScanException(msg); + } + Token ot = getCurentToken(); + if ((ot != null) && (ot.getType() == 1006)) { + List optionList = (List)ot.getValue(); + compositeNode.setOptions(optionList); + advanceTokenPointer(); + } + return compositeNode; + } + + Token getNextToken() { + if (pointer < tokenList.size()) { + return (Token)tokenList.get(pointer++); + } + return null; + } + + Token getCurentToken() { + if (pointer < tokenList.size()) { + return (Token)tokenList.get(pointer); + } + return null; + } + + void advanceTokenPointer() { + pointer += 1; + } + + void expectNotNull(Token t, String expected) { + if (t == null) { + throw new IllegalStateException("All tokens consumed but was expecting " + expected); + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/parser/SimpleKeywordNode.java b/src/minecraft/ch/qos/logback/core/pattern/parser/SimpleKeywordNode.java new file mode 100644 index 0000000..80c61a8 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/parser/SimpleKeywordNode.java @@ -0,0 +1,68 @@ +package ch.qos.logback.core.pattern.parser; + +import java.util.List; + + + + + + + + + + + + +public class SimpleKeywordNode + extends FormattingNode +{ + List optionList; + + SimpleKeywordNode(Object value) + { + super(1, value); + } + + protected SimpleKeywordNode(int type, Object value) { + super(type, value); + } + + public List getOptions() { + return optionList; + } + + public void setOptions(List optionList) { + this.optionList = optionList; + } + + public boolean equals(Object o) { + if (!super.equals(o)) { + return false; + } + + if (!(o instanceof SimpleKeywordNode)) { + return false; + } + SimpleKeywordNode r = (SimpleKeywordNode)o; + + return optionList == null ? true : optionList != null ? optionList.equals(optionList) : false; + } + + + public int hashCode() + { + return super.hashCode(); + } + + public String toString() { + StringBuilder buf = new StringBuilder(); + if (optionList == null) { + buf.append("KeyWord(" + value + "," + formatInfo + ")"); + } else { + buf.append("KeyWord(" + value + ", " + formatInfo + "," + optionList + ")"); + } + + buf.append(printNext()); + return buf.toString(); + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/parser/Token.java b/src/minecraft/ch/qos/logback/core/pattern/parser/Token.java new file mode 100644 index 0000000..e764b9c --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/parser/Token.java @@ -0,0 +1,117 @@ +package ch.qos.logback.core.pattern.parser; + + + +class Token +{ + static final int PERCENT = 37; + + + static final int RIGHT_PARENTHESIS = 41; + + + static final int MINUS = 45; + + + static final int DOT = 46; + + + static final int CURLY_LEFT = 123; + + static final int CURLY_RIGHT = 125; + + static final int LITERAL = 1000; + + static final int FORMAT_MODIFIER = 1002; + + static final int SIMPLE_KEYWORD = 1004; + + static final int COMPOSITE_KEYWORD = 1005; + + static final int OPTION = 1006; + + static final int EOF = Integer.MAX_VALUE; + + static Token EOF_TOKEN = new Token(Integer.MAX_VALUE, "EOF"); + static Token RIGHT_PARENTHESIS_TOKEN = new Token(41); + static Token BARE_COMPOSITE_KEYWORD_TOKEN = new Token(1005, "BARE"); + static Token PERCENT_TOKEN = new Token(37); + + private final int type; + private final Object value; + + public Token(int type) + { + this(type, null); + } + + public Token(int type, Object value) { + this.type = type; + this.value = value; + } + + public int getType() { + return type; + } + + public Object getValue() { + return value; + } + + public String toString() + { + String typeStr = null; + switch (type) + { + case 37: + typeStr = "%"; + break; + case 1002: + typeStr = "FormatModifier"; + break; + case 1000: + typeStr = "LITERAL"; + break; + case 1006: + typeStr = "OPTION"; + break; + case 1004: + typeStr = "SIMPLE_KEYWORD"; + break; + case 1005: + typeStr = "COMPOSITE_KEYWORD"; + break; + case 41: + typeStr = "RIGHT_PARENTHESIS"; + break; + default: + typeStr = "UNKNOWN"; + } + if (value == null) { + return "Token(" + typeStr + ")"; + } + + return "Token(" + typeStr + ", \"" + value + "\")"; + } + + + public int hashCode() + { + int result = type; + result = 29 * result + (value != null ? value.hashCode() : 0); + return result; + } + + public boolean equals(Object o) + { + if (this == o) return true; + if (!(o instanceof Token)) { return false; + } + Token token = (Token)o; + + if (type != type) return false; + if (value != null ? !value.equals(value) : value != null) { return false; + } + return true; + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/parser/TokenStream.java b/src/minecraft/ch/qos/logback/core/pattern/parser/TokenStream.java new file mode 100644 index 0000000..840cca9 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/parser/TokenStream.java @@ -0,0 +1,237 @@ +package ch.qos.logback.core.pattern.parser; + +import ch.qos.logback.core.pattern.util.IEscapeUtil; +import ch.qos.logback.core.pattern.util.RegularEscapeUtil; +import ch.qos.logback.core.pattern.util.RestrictedEscapeUtil; +import ch.qos.logback.core.spi.ScanException; +import java.util.ArrayList; +import java.util.List; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +class TokenStream +{ + final String pattern; + final int patternLength; + final IEscapeUtil escapeUtil; + + static enum TokenizerState + { + LITERAL_STATE, FORMAT_MODIFIER_STATE, KEYWORD_STATE, OPTION_STATE, RIGHT_PARENTHESIS_STATE; + + + private TokenizerState() {} + } + + final IEscapeUtil optionEscapeUtil = new RestrictedEscapeUtil(); + + TokenizerState state = TokenizerState.LITERAL_STATE; + int pointer = 0; + + TokenStream(String pattern) + { + this(pattern, new RegularEscapeUtil()); + } + + TokenStream(String pattern, IEscapeUtil escapeUtil) { + if ((pattern == null) || (pattern.length() == 0)) { + throw new IllegalArgumentException("null or empty pattern string not allowed"); + } + + this.pattern = pattern; + patternLength = pattern.length(); + this.escapeUtil = escapeUtil; + } + + List tokenize() throws ScanException { + List tokenList = new ArrayList(); + StringBuffer buf = new StringBuffer(); + + while (pointer < patternLength) { + char c = pattern.charAt(pointer); + pointer += 1; + + switch (1.$SwitchMap$ch$qos$logback$core$pattern$parser$TokenStream$TokenizerState[state.ordinal()]) { + case 1: + handleLiteralState(c, tokenList, buf); + break; + case 2: + handleFormatModifierState(c, tokenList, buf); + break; + case 3: + processOption(c, tokenList, buf); + break; + case 4: + handleKeywordState(c, tokenList, buf); + break; + case 5: + handleRightParenthesisState(c, tokenList, buf); + } + + } + + + + + switch (1.$SwitchMap$ch$qos$logback$core$pattern$parser$TokenStream$TokenizerState[state.ordinal()]) { + case 1: + addValuedToken(1000, buf, tokenList); + break; + case 4: + tokenList.add(new Token(1004, buf.toString())); + break; + case 5: + tokenList.add(Token.RIGHT_PARENTHESIS_TOKEN); + break; + + case 2: + case 3: + throw new ScanException("Unexpected end of pattern string"); + } + + return tokenList; + } + + private void handleRightParenthesisState(char c, List tokenList, StringBuffer buf) { + tokenList.add(Token.RIGHT_PARENTHESIS_TOKEN); + switch (c) { + case ')': + break; + case '{': + state = TokenizerState.OPTION_STATE; + break; + case '\\': + escape("%{}", buf); + state = TokenizerState.LITERAL_STATE; + break; + default: + buf.append(c); + state = TokenizerState.LITERAL_STATE; + } + } + + private void processOption(char c, List tokenList, StringBuffer buf) throws ScanException { + OptionTokenizer ot = new OptionTokenizer(this); + ot.tokenize(c, tokenList); + } + + private void handleFormatModifierState(char c, List tokenList, StringBuffer buf) { + if (c == '(') { + addValuedToken(1002, buf, tokenList); + tokenList.add(Token.BARE_COMPOSITE_KEYWORD_TOKEN); + state = TokenizerState.LITERAL_STATE; + } else if (Character.isJavaIdentifierStart(c)) { + addValuedToken(1002, buf, tokenList); + state = TokenizerState.KEYWORD_STATE; + buf.append(c); + } else { + buf.append(c); + } + } + + private void handleLiteralState(char c, List tokenList, StringBuffer buf) { + switch (c) { + case '\\': + escape("%()", buf); + break; + + case '%': + addValuedToken(1000, buf, tokenList); + tokenList.add(Token.PERCENT_TOKEN); + state = TokenizerState.FORMAT_MODIFIER_STATE; + break; + + case ')': + addValuedToken(1000, buf, tokenList); + state = TokenizerState.RIGHT_PARENTHESIS_STATE; + break; + + default: + buf.append(c); + } + } + + private void handleKeywordState(char c, List tokenList, StringBuffer buf) + { + if (Character.isJavaIdentifierPart(c)) { + buf.append(c); + } else if (c == '{') { + addValuedToken(1004, buf, tokenList); + state = TokenizerState.OPTION_STATE; + } else if (c == '(') { + addValuedToken(1005, buf, tokenList); + state = TokenizerState.LITERAL_STATE; + } else if (c == '%') { + addValuedToken(1004, buf, tokenList); + tokenList.add(Token.PERCENT_TOKEN); + state = TokenizerState.FORMAT_MODIFIER_STATE; + } else if (c == ')') { + addValuedToken(1004, buf, tokenList); + state = TokenizerState.RIGHT_PARENTHESIS_STATE; + } else { + addValuedToken(1004, buf, tokenList); + if (c == '\\') { + if (pointer < patternLength) { + char next = pattern.charAt(pointer++); + escapeUtil.escape("%()", buf, next, pointer); + } + } else { + buf.append(c); + } + state = TokenizerState.LITERAL_STATE; + } + } + + void escape(String escapeChars, StringBuffer buf) { + if (pointer < patternLength) { + char next = pattern.charAt(pointer++); + escapeUtil.escape(escapeChars, buf, next, pointer); + } + } + + void optionEscape(String escapeChars, StringBuffer buf) { + if (pointer < patternLength) { + char next = pattern.charAt(pointer++); + optionEscapeUtil.escape(escapeChars, buf, next, pointer); + } + } + + + + private void addValuedToken(int type, StringBuffer buf, List tokenList) + { + if (buf.length() > 0) { + tokenList.add(new Token(type, buf.toString())); + buf.setLength(0); + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/util/AlmostAsIsEscapeUtil.java b/src/minecraft/ch/qos/logback/core/pattern/util/AlmostAsIsEscapeUtil.java new file mode 100644 index 0000000..7f0977b --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/util/AlmostAsIsEscapeUtil.java @@ -0,0 +1,45 @@ +package ch.qos.logback.core.pattern.util; + + + + + + + + + + + + + + + + + + +public class AlmostAsIsEscapeUtil + extends RestrictedEscapeUtil +{ + public AlmostAsIsEscapeUtil() {} + + + + + + + + + + + + + + + + + + public void escape(String escapeChars, StringBuffer buf, char next, int pointer) + { + super.escape("%)", buf, next, pointer); + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/util/AsIsEscapeUtil.java b/src/minecraft/ch/qos/logback/core/pattern/util/AsIsEscapeUtil.java new file mode 100644 index 0000000..6555c1b --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/util/AsIsEscapeUtil.java @@ -0,0 +1,35 @@ +package ch.qos.logback.core.pattern.util; + + + + + + + + + + + + +public class AsIsEscapeUtil + implements IEscapeUtil +{ + public AsIsEscapeUtil() {} + + + + + + + + + + + + public void escape(String escapeChars, StringBuffer buf, char next, int pointer) + { + buf.append("\\"); + + buf.append(next); + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/util/IEscapeUtil.java b/src/minecraft/ch/qos/logback/core/pattern/util/IEscapeUtil.java new file mode 100644 index 0000000..d6c85d2 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/util/IEscapeUtil.java @@ -0,0 +1,6 @@ +package ch.qos.logback.core.pattern.util; + +public abstract interface IEscapeUtil +{ + public abstract void escape(String paramString, StringBuffer paramStringBuffer, char paramChar, int paramInt); +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/util/RegularEscapeUtil.java b/src/minecraft/ch/qos/logback/core/pattern/util/RegularEscapeUtil.java new file mode 100644 index 0000000..215b7b7 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/util/RegularEscapeUtil.java @@ -0,0 +1,92 @@ +package ch.qos.logback.core.pattern.util; + + + + + + + + + +public class RegularEscapeUtil + implements IEscapeUtil +{ + public RegularEscapeUtil() {} + + + + + + + + + public void escape(String escapeChars, StringBuffer buf, char next, int pointer) + { + if (escapeChars.indexOf(next) >= 0) { + buf.append(next); + } else { + switch (next) + { + case '_': + break; + case '\\': + buf.append(next); + break; + case 't': + buf.append('\t'); + break; + case 'r': + buf.append('\r'); + break; + case 'n': + buf.append('\n'); + break; + default: + String commaSeperatedEscapeChars = formatEscapeCharsForListing(escapeChars); + throw new IllegalArgumentException("Illegal char '" + next + " at column " + pointer + ". Only \\\\, \\_" + commaSeperatedEscapeChars + ", \\t, \\n, \\r combinations are allowed as escape characters."); + } + } + } + + String formatEscapeCharsForListing(String escapeChars) + { + StringBuilder commaSeperatedEscapeChars = new StringBuilder(); + for (int i = 0; i < escapeChars.length(); i++) { + commaSeperatedEscapeChars.append(", \\").append(escapeChars.charAt(i)); + } + return commaSeperatedEscapeChars.toString(); + } + + public static String basicEscape(String s) + { + int len = s.length(); + StringBuilder sbuf = new StringBuilder(len); + + int i = 0; + while (i < len) { + char c = s.charAt(i++); + if (c == '\\') { + c = s.charAt(i++); + if (c == 'n') { + c = '\n'; + } else if (c == 'r') { + c = '\r'; + } else if (c == 't') { + c = '\t'; + } else if (c == 'f') { + c = '\f'; + } else if (c == '\b') { + c = '\b'; + } else if (c == '"') { + c = '"'; + } else if (c == '\'') { + c = '\''; + } else if (c == '\\') { + c = '\\'; + } + } + sbuf.append(c); + } + return sbuf.toString(); + } +} diff --git a/src/minecraft/ch/qos/logback/core/pattern/util/RestrictedEscapeUtil.java b/src/minecraft/ch/qos/logback/core/pattern/util/RestrictedEscapeUtil.java new file mode 100644 index 0000000..608e219 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/pattern/util/RestrictedEscapeUtil.java @@ -0,0 +1,35 @@ +package ch.qos.logback.core.pattern.util; + + + + + + + + + +public class RestrictedEscapeUtil + implements IEscapeUtil +{ + public RestrictedEscapeUtil() {} + + + + + + + + + public void escape(String escapeChars, StringBuffer buf, char next, int pointer) + { + if (escapeChars.indexOf(next) >= 0) { + buf.append(next); + } + else + { + buf.append("\\"); + + buf.append(next); + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/property/FileExistsPropertyDefiner.java b/src/minecraft/ch/qos/logback/core/property/FileExistsPropertyDefiner.java new file mode 100644 index 0000000..e9796c8 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/property/FileExistsPropertyDefiner.java @@ -0,0 +1,62 @@ +package ch.qos.logback.core.property; + +import ch.qos.logback.core.PropertyDefinerBase; +import ch.qos.logback.core.util.OptionHelper; +import java.io.File; + + + + + + + + + + + + + + + + + + + + +public class FileExistsPropertyDefiner + extends PropertyDefinerBase +{ + String path; + + public FileExistsPropertyDefiner() {} + + public String getPath() + { + return path; + } + + + + + + public void setPath(String path) + { + this.path = path; + } + + + + + + + public String getPropertyValue() + { + if (OptionHelper.isEmpty(path)) { + addError("The \"path\" property must be set."); + return null; + } + + File file = new File(path); + return booleanAsStr(file.exists()); + } +} diff --git a/src/minecraft/ch/qos/logback/core/property/ResourceExistsPropertyDefiner.java b/src/minecraft/ch/qos/logback/core/property/ResourceExistsPropertyDefiner.java new file mode 100644 index 0000000..3381137 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/property/ResourceExistsPropertyDefiner.java @@ -0,0 +1,65 @@ +package ch.qos.logback.core.property; + +import ch.qos.logback.core.PropertyDefinerBase; +import ch.qos.logback.core.util.Loader; +import ch.qos.logback.core.util.OptionHelper; +import java.net.URL; + + + + + + + + + + + + + + + + + + + + + + +public class ResourceExistsPropertyDefiner + extends PropertyDefinerBase +{ + String resourceStr; + + public ResourceExistsPropertyDefiner() {} + + public String getResource() + { + return resourceStr; + } + + + + + + public void setResource(String resource) + { + resourceStr = resource; + } + + + + + + + public String getPropertyValue() + { + if (OptionHelper.isEmpty(resourceStr)) { + addError("The \"resource\" property must be set."); + return null; + } + + URL resourceURL = Loader.getResourceBySelfClassLoader(resourceStr); + return booleanAsStr(resourceURL != null); + } +} diff --git a/src/minecraft/ch/qos/logback/core/read/CyclicBufferAppender.java b/src/minecraft/ch/qos/logback/core/read/CyclicBufferAppender.java new file mode 100644 index 0000000..d60984e --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/read/CyclicBufferAppender.java @@ -0,0 +1,79 @@ +package ch.qos.logback.core.read; + +import ch.qos.logback.core.AppenderBase; +import ch.qos.logback.core.helpers.CyclicBuffer; + + + + + + + + + + + + + + + + + +public class CyclicBufferAppender + extends AppenderBase +{ + CyclicBuffer cb; + + public CyclicBufferAppender() {} + + int maxSize = 512; + + public void start() { + cb = new CyclicBuffer(maxSize); + super.start(); + } + + public void stop() { + cb = null; + super.stop(); + } + + protected void append(E eventObject) + { + if (!isStarted()) { + return; + } + cb.add(eventObject); + } + + public int getLength() { + if (isStarted()) { + return cb.length(); + } + return 0; + } + + public E get(int i) + { + if (isStarted()) { + return cb.get(i); + } + return null; + } + + public void reset() + { + cb.clear(); + } + + + + public int getMaxSize() + { + return maxSize; + } + + public void setMaxSize(int maxSize) { + this.maxSize = maxSize; + } +} diff --git a/src/minecraft/ch/qos/logback/core/read/ListAppender.java b/src/minecraft/ch/qos/logback/core/read/ListAppender.java new file mode 100644 index 0000000..4e2af97 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/read/ListAppender.java @@ -0,0 +1,28 @@ +package ch.qos.logback.core.read; + +import ch.qos.logback.core.AppenderBase; +import java.util.ArrayList; +import java.util.List; + + + + + + + + + + + + +public class ListAppender + extends AppenderBase +{ + public ListAppender() {} + + public List list = new ArrayList(); + + protected void append(E e) { + list.add(e); + } +} diff --git a/src/minecraft/ch/qos/logback/core/recovery/RecoveryCoordinator.java b/src/minecraft/ch/qos/logback/core/recovery/RecoveryCoordinator.java new file mode 100644 index 0000000..31b2076 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/recovery/RecoveryCoordinator.java @@ -0,0 +1,55 @@ +package ch.qos.logback.core.recovery; + + + + + +public class RecoveryCoordinator +{ + public static final long BACKOFF_COEFFICIENT_MIN = 20L; + + + + + public RecoveryCoordinator() {} + + + + + static long BACKOFF_COEFFICIENT_MAX = 327680L; + + private long backOffCoefficient = 20L; + + private static long UNSET = -1L; + private long currentTime = UNSET; + long next = System.currentTimeMillis() + getBackoffCoefficient(); + + public boolean isTooSoon() { + long now = getCurrentTime(); + if (now > next) { + next = (now + getBackoffCoefficient()); + return false; + } + return true; + } + + void setCurrentTime(long forcedTime) + { + currentTime = forcedTime; + } + + private long getCurrentTime() { + if (currentTime != UNSET) { + return currentTime; + } + return System.currentTimeMillis(); + } + + private long getBackoffCoefficient() { + long currentCoeff = backOffCoefficient; + if (backOffCoefficient < BACKOFF_COEFFICIENT_MAX) { + backOffCoefficient *= 4L; + } + return currentCoeff; + } +} diff --git a/src/minecraft/ch/qos/logback/core/recovery/ResilientFileOutputStream.java b/src/minecraft/ch/qos/logback/core/recovery/ResilientFileOutputStream.java new file mode 100644 index 0000000..9b9ca49 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/recovery/ResilientFileOutputStream.java @@ -0,0 +1,60 @@ +package ch.qos.logback.core.recovery; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.channels.FileChannel; + + + + + + + + +public class ResilientFileOutputStream + extends ResilientOutputStreamBase +{ + private File file; + private FileOutputStream fos; + + public ResilientFileOutputStream(File file, boolean append) + throws FileNotFoundException + { + this.file = file; + fos = new FileOutputStream(file, append); + os = new BufferedOutputStream(fos); + presumedClean = true; + } + + public FileChannel getChannel() { + if (os == null) { + return null; + } + return fos.getChannel(); + } + + public File getFile() { + return file; + } + + String getDescription() + { + return "file [" + file + "]"; + } + + OutputStream openNewOutputStream() + throws IOException + { + fos = new FileOutputStream(file, true); + return new BufferedOutputStream(fos); + } + + public String toString() + { + return "c.q.l.c.recovery.ResilientFileOutputStream@" + System.identityHashCode(this); + } +} diff --git a/src/minecraft/ch/qos/logback/core/recovery/ResilientOutputStreamBase.java b/src/minecraft/ch/qos/logback/core/recovery/ResilientOutputStreamBase.java new file mode 100644 index 0000000..919cc2c --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/recovery/ResilientOutputStreamBase.java @@ -0,0 +1,168 @@ +package ch.qos.logback.core.recovery; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.status.ErrorStatus; +import ch.qos.logback.core.status.InfoStatus; +import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.status.StatusManager; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; + + + + + + + + + + + + + + +public abstract class ResilientOutputStreamBase + extends OutputStream +{ + static final int STATUS_COUNT_LIMIT = 8; + private int noContextWarning = 0; + private int statusCount = 0; + + private Context context; + + private RecoveryCoordinator recoveryCoordinator; + protected OutputStream os; + protected boolean presumedClean = true; + + public ResilientOutputStreamBase() {} + + private boolean isPresumedInError() { return (recoveryCoordinator != null) && (!presumedClean); } + + public void write(byte[] b, int off, int len) + { + if (isPresumedInError()) { + if (!recoveryCoordinator.isTooSoon()) { + attemptRecovery(); + } + return; + } + try + { + os.write(b, off, len); + postSuccessfulWrite(); + } catch (IOException e) { + postIOFailure(e); + } + } + + public void write(int b) + { + if (isPresumedInError()) { + if (!recoveryCoordinator.isTooSoon()) { + attemptRecovery(); + } + return; + } + try { + os.write(b); + postSuccessfulWrite(); + } catch (IOException e) { + postIOFailure(e); + } + } + + public void flush() + { + if (os != null) { + try { + os.flush(); + postSuccessfulWrite(); + } catch (IOException e) { + postIOFailure(e); + } + } + } + + abstract String getDescription(); + + abstract OutputStream openNewOutputStream() throws IOException; + + private void postSuccessfulWrite() { + if (recoveryCoordinator != null) { + recoveryCoordinator = null; + statusCount = 0; + addStatus(new InfoStatus("Recovered from IO failure on " + getDescription(), this)); + } + } + + public void postIOFailure(IOException e) + { + addStatusIfCountNotOverLimit(new ErrorStatus("IO failure while writing to " + getDescription(), this, e)); + + presumedClean = false; + if (recoveryCoordinator == null) { + recoveryCoordinator = new RecoveryCoordinator(); + } + } + + public void close() throws IOException + { + if (os != null) { + os.close(); + } + } + + void attemptRecovery() { + try { + close(); + } + catch (IOException e) {} + + addStatusIfCountNotOverLimit(new InfoStatus("Attempting to recover from IO failure on " + getDescription(), this)); + + + try + { + os = openNewOutputStream(); + presumedClean = true; + } catch (IOException e) { + addStatusIfCountNotOverLimit(new ErrorStatus("Failed to open " + getDescription(), this, e)); + } + } + + void addStatusIfCountNotOverLimit(Status s) + { + statusCount += 1; + if (statusCount < 8) { + addStatus(s); + } + + if (statusCount == 8) { + addStatus(s); + addStatus(new InfoStatus("Will supress future messages regarding " + getDescription(), this)); + } + } + + public void addStatus(Status status) + { + if (context == null) { + if (noContextWarning++ == 0) { + System.out.println("LOGBACK: No context given for " + this); + } + return; + } + StatusManager sm = context.getStatusManager(); + if (sm != null) { + sm.add(status); + } + } + + public Context getContext() { + return context; + } + + public void setContext(Context context) { + this.context = context; + } +} diff --git a/src/minecraft/ch/qos/logback/core/recovery/ResilientSyslogOutputStream.java b/src/minecraft/ch/qos/logback/core/recovery/ResilientSyslogOutputStream.java new file mode 100644 index 0000000..ef51eb0 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/recovery/ResilientSyslogOutputStream.java @@ -0,0 +1,51 @@ +package ch.qos.logback.core.recovery; + +import ch.qos.logback.core.net.SyslogOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.SocketException; +import java.net.UnknownHostException; + + + + + + + + + + + + + + +public class ResilientSyslogOutputStream + extends ResilientOutputStreamBase +{ + String syslogHost; + int port; + + public ResilientSyslogOutputStream(String syslogHost, int port) + throws UnknownHostException, SocketException + { + this.syslogHost = syslogHost; + this.port = port; + os = new SyslogOutputStream(syslogHost, port); + presumedClean = true; + } + + String getDescription() + { + return "syslog [" + syslogHost + ":" + port + "]"; + } + + OutputStream openNewOutputStream() throws IOException + { + return new SyslogOutputStream(syslogHost, port); + } + + public String toString() + { + return "c.q.l.c.recovery.ResilientSyslogOutputStream@" + System.identityHashCode(this); + } +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/DefaultTimeBasedFileNamingAndTriggeringPolicy.java b/src/minecraft/ch/qos/logback/core/rolling/DefaultTimeBasedFileNamingAndTriggeringPolicy.java new file mode 100644 index 0000000..08e98ce --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/DefaultTimeBasedFileNamingAndTriggeringPolicy.java @@ -0,0 +1,57 @@ +package ch.qos.logback.core.rolling; + +import ch.qos.logback.core.rolling.helper.ArchiveRemover; +import ch.qos.logback.core.rolling.helper.FileNamePattern; +import ch.qos.logback.core.rolling.helper.TimeBasedArchiveRemover; +import java.io.File; +import java.util.Date; + + + + + + + + + + + + + + + + + +public class DefaultTimeBasedFileNamingAndTriggeringPolicy + extends TimeBasedFileNamingAndTriggeringPolicyBase +{ + public DefaultTimeBasedFileNamingAndTriggeringPolicy() {} + + public void start() + { + super.start(); + archiveRemover = new TimeBasedArchiveRemover(tbrp.fileNamePattern, rc); + archiveRemover.setContext(context); + started = true; + } + + public boolean isTriggeringEvent(File activeFile, E event) { + long time = getCurrentTime(); + if (time >= nextCheck) { + Date dateOfElapsedPeriod = dateInCurrentPeriod; + addInfo("Elapsed period: " + dateOfElapsedPeriod); + elapsedPeriodsFileName = tbrp.fileNamePatternWCS.convert(dateOfElapsedPeriod); + + setDateInCurrentPeriod(time); + computeNextCheck(); + return true; + } + return false; + } + + + public String toString() + { + return "c.q.l.core.rolling.DefaultTimeBasedFileNamingAndTriggeringPolicy"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/FixedWindowRollingPolicy.java b/src/minecraft/ch/qos/logback/core/rolling/FixedWindowRollingPolicy.java new file mode 100644 index 0000000..6a1883b --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/FixedWindowRollingPolicy.java @@ -0,0 +1,185 @@ +package ch.qos.logback.core.rolling; + +import ch.qos.logback.core.rolling.helper.CompressionMode; +import ch.qos.logback.core.rolling.helper.Compressor; +import ch.qos.logback.core.rolling.helper.FileFilterUtil; +import ch.qos.logback.core.rolling.helper.FileNamePattern; +import ch.qos.logback.core.rolling.helper.IntegerTokenConverter; +import ch.qos.logback.core.rolling.helper.RenameUtil; +import java.io.File; +import java.util.Date; + + + + + + + + + + + + + + + + + + +public class FixedWindowRollingPolicy + extends RollingPolicyBase +{ + static final String FNP_NOT_SET = "The \"FileNamePattern\" property must be set before using FixedWindowRollingPolicy. "; + static final String PRUDENT_MODE_UNSUPPORTED = "See also http://logback.qos.ch/codes.html#tbr_fnp_prudent_unsupported"; + static final String SEE_PARENT_FN_NOT_SET = "Please refer to http://logback.qos.ch/codes.html#fwrp_parentFileName_not_set"; + int maxIndex; + int minIndex; + RenameUtil util = new RenameUtil(); + + + Compressor compressor; + + + public static final String ZIP_ENTRY_DATE_PATTERN = "yyyy-MM-dd_HHmm"; + + private static int MAX_WINDOW_SIZE = 20; + + public FixedWindowRollingPolicy() { + minIndex = 1; + maxIndex = 7; + } + + public void start() { + util.setContext(context); + + if (fileNamePatternStr != null) { + fileNamePattern = new FileNamePattern(fileNamePatternStr, context); + determineCompressionMode(); + } else { + addError("The \"FileNamePattern\" property must be set before using FixedWindowRollingPolicy. "); + addError("See also http://logback.qos.ch/codes.html#tbr_fnp_not_set"); + throw new IllegalStateException("The \"FileNamePattern\" property must be set before using FixedWindowRollingPolicy. See also http://logback.qos.ch/codes.html#tbr_fnp_not_set"); + } + + if (isParentPrudent()) { + addError("Prudent mode is not supported with FixedWindowRollingPolicy."); + addError("See also http://logback.qos.ch/codes.html#tbr_fnp_prudent_unsupported"); + throw new IllegalStateException("Prudent mode is not supported."); + } + + if (getParentsRawFileProperty() == null) { + addError("The File name property must be set before using this rolling policy."); + addError("Please refer to http://logback.qos.ch/codes.html#fwrp_parentFileName_not_set"); + throw new IllegalStateException("The \"File\" option must be set."); + } + + if (maxIndex < minIndex) { + addWarn("MaxIndex (" + maxIndex + ") cannot be smaller than MinIndex (" + minIndex + ")."); + + addWarn("Setting maxIndex to equal minIndex."); + maxIndex = minIndex; + } + + int maxWindowSize = getMaxWindowSize(); + if (maxIndex - minIndex > maxWindowSize) { + addWarn("Large window sizes are not allowed."); + maxIndex = (minIndex + maxWindowSize); + addWarn("MaxIndex reduced to " + maxIndex); + } + + IntegerTokenConverter itc = fileNamePattern.getIntegerTokenConverter(); + + if (itc == null) { + throw new IllegalStateException("FileNamePattern [" + fileNamePattern.getPattern() + "] does not contain a valid IntegerToken"); + } + + + + if (compressionMode == CompressionMode.ZIP) { + String zipEntryFileNamePatternStr = transformFileNamePatternFromInt2Date(fileNamePatternStr); + zipEntryFileNamePattern = new FileNamePattern(zipEntryFileNamePatternStr, context); + } + compressor = new Compressor(compressionMode); + compressor.setContext(context); + super.start(); + } + + + + + + protected int getMaxWindowSize() + { + return MAX_WINDOW_SIZE; + } + + private String transformFileNamePatternFromInt2Date(String fileNamePatternStr) { + String slashified = FileFilterUtil.slashify(fileNamePatternStr); + String stemOfFileNamePattern = FileFilterUtil.afterLastSlash(slashified); + return stemOfFileNamePattern.replace("%i", "%d{yyyy-MM-dd_HHmm}"); + } + + + + public void rollover() + throws RolloverFailure + { + if (maxIndex >= 0) + { + File file = new File(fileNamePattern.convertInt(maxIndex)); + + if (file.exists()) { + file.delete(); + } + + + for (int i = maxIndex - 1; i >= minIndex; i--) { + String toRenameStr = fileNamePattern.convertInt(i); + File toRename = new File(toRenameStr); + + if (toRename.exists()) { + util.rename(toRenameStr, fileNamePattern.convertInt(i + 1)); + } else { + addInfo("Skipping roll-over for inexistent file " + toRenameStr); + } + } + + + switch (1.$SwitchMap$ch$qos$logback$core$rolling$helper$CompressionMode[compressionMode.ordinal()]) { + case 1: + util.rename(getActiveFileName(), fileNamePattern.convertInt(minIndex)); + + break; + case 2: + compressor.compress(getActiveFileName(), fileNamePattern.convertInt(minIndex), null); + break; + case 3: + compressor.compress(getActiveFileName(), fileNamePattern.convertInt(minIndex), zipEntryFileNamePattern.convert(new Date())); + } + + } + } + + + + public String getActiveFileName() + { + return getParentsRawFileProperty(); + } + + public int getMaxIndex() { + return maxIndex; + } + + public int getMinIndex() { + return minIndex; + } + + public void setMaxIndex(int maxIndex) { + this.maxIndex = maxIndex; + } + + public void setMinIndex(int minIndex) { + this.minIndex = minIndex; + } +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/RollingFileAppender.java b/src/minecraft/ch/qos/logback/core/rolling/RollingFileAppender.java new file mode 100644 index 0000000..6eb8fef --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/RollingFileAppender.java @@ -0,0 +1,215 @@ +package ch.qos.logback.core.rolling; + +import ch.qos.logback.core.FileAppender; +import ch.qos.logback.core.rolling.helper.CompressionMode; +import ch.qos.logback.core.rolling.helper.FileNamePattern; +import java.io.File; +import java.io.IOException; +import java.util.concurrent.locks.ReentrantLock; + + + + + + + + + + + + + + + + + + + + + + + +public class RollingFileAppender + extends FileAppender +{ + File currentlyActiveFile; + TriggeringPolicy triggeringPolicy; + RollingPolicy rollingPolicy; + + public RollingFileAppender() {} + + private static String RFA_NO_TP_URL = "http://logback.qos.ch/codes.html#rfa_no_tp"; + private static String RFA_NO_RP_URL = "http://logback.qos.ch/codes.html#rfa_no_rp"; + private static String COLLISION_URL = "http://logback.qos.ch/codes.html#rfa_collision"; + + public void start() { + if (triggeringPolicy == null) { + addWarn("No TriggeringPolicy was set for the RollingFileAppender named " + getName()); + + addWarn("For more information, please visit " + RFA_NO_TP_URL); + return; + } + + + if (!append) { + addWarn("Append mode is mandatory for RollingFileAppender"); + append = true; + } + + if (rollingPolicy == null) { + addError("No RollingPolicy was set for the RollingFileAppender named " + getName()); + + addError("For more information, please visit " + RFA_NO_RP_URL); + return; + } + + + if (fileAndPatternCollide()) { + addError("File property collides with fileNamePattern. Aborting."); + addError("For more information, please visit " + COLLISION_URL); + return; + } + + if (isPrudent()) { + if (rawFileProperty() != null) { + addWarn("Setting \"File\" property to null on account of prudent mode"); + setFile(null); + } + if (rollingPolicy.getCompressionMode() != CompressionMode.NONE) { + addError("Compression is not supported in prudent mode. Aborting"); + return; + } + } + + currentlyActiveFile = new File(getFile()); + addInfo("Active log file name: " + getFile()); + super.start(); + } + + private boolean fileAndPatternCollide() { + if ((triggeringPolicy instanceof RollingPolicyBase)) { + RollingPolicyBase base = (RollingPolicyBase)triggeringPolicy; + FileNamePattern fileNamePattern = fileNamePattern; + + if ((fileNamePattern != null) && (fileName != null)) { + String regex = fileNamePattern.toRegex(); + return fileName.matches(regex); + } + } + return false; + } + + public void stop() + { + if (rollingPolicy != null) rollingPolicy.stop(); + if (triggeringPolicy != null) triggeringPolicy.stop(); + super.stop(); + } + + + + public void setFile(String file) + { + if ((file != null) && ((triggeringPolicy != null) || (rollingPolicy != null))) { + addError("File property must be set before any triggeringPolicy or rollingPolicy properties"); + addError("Visit http://logback.qos.ch/codes.html#rfa_file_after for more information"); + } + super.setFile(file); + } + + public String getFile() + { + return rollingPolicy.getActiveFileName(); + } + + + + public void rollover() + { + lock.lock(); + + + + + try + { + closeOutputStream(); + attemptRollover(); + attemptOpenFile(); + } finally { + lock.unlock(); + } + } + + private void attemptOpenFile() + { + try { + currentlyActiveFile = new File(rollingPolicy.getActiveFileName()); + + + openFile(rollingPolicy.getActiveFileName()); + } catch (IOException e) { + addError("setFile(" + fileName + ", false) call failed.", e); + } + } + + private void attemptRollover() { + try { + rollingPolicy.rollover(); + } catch (RolloverFailure rf) { + addWarn("RolloverFailure occurred. Deferring roll-over."); + + append = true; + } + } + + + + + + + + + + protected void subAppend(E event) + { + synchronized (triggeringPolicy) { + if (triggeringPolicy.isTriggeringEvent(currentlyActiveFile, event)) { + rollover(); + } + } + + super.subAppend(event); + } + + public RollingPolicy getRollingPolicy() { + return rollingPolicy; + } + + public TriggeringPolicy getTriggeringPolicy() { + return triggeringPolicy; + } + + + + + + + + + public void setRollingPolicy(RollingPolicy policy) + { + rollingPolicy = policy; + if ((rollingPolicy instanceof TriggeringPolicy)) { + triggeringPolicy = ((TriggeringPolicy)policy); + } + } + + public void setTriggeringPolicy(TriggeringPolicy policy) + { + triggeringPolicy = policy; + if ((policy instanceof RollingPolicy)) { + rollingPolicy = ((RollingPolicy)policy); + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/RollingPolicy.java b/src/minecraft/ch/qos/logback/core/rolling/RollingPolicy.java new file mode 100644 index 0000000..d75ef1d --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/RollingPolicy.java @@ -0,0 +1,18 @@ +package ch.qos.logback.core.rolling; + +import ch.qos.logback.core.FileAppender; +import ch.qos.logback.core.rolling.helper.CompressionMode; +import ch.qos.logback.core.spi.LifeCycle; + +public abstract interface RollingPolicy + extends LifeCycle +{ + public abstract void rollover() + throws RolloverFailure; + + public abstract String getActiveFileName(); + + public abstract CompressionMode getCompressionMode(); + + public abstract void setParent(FileAppender paramFileAppender); +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/RollingPolicyBase.java b/src/minecraft/ch/qos/logback/core/rolling/RollingPolicyBase.java new file mode 100644 index 0000000..1421926 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/RollingPolicyBase.java @@ -0,0 +1,96 @@ +package ch.qos.logback.core.rolling; + +import ch.qos.logback.core.FileAppender; +import ch.qos.logback.core.rolling.helper.CompressionMode; +import ch.qos.logback.core.rolling.helper.FileNamePattern; +import ch.qos.logback.core.spi.ContextAwareBase; + + + + + + + + + + + + + + + + + + +public abstract class RollingPolicyBase + extends ContextAwareBase + implements RollingPolicy +{ + protected CompressionMode compressionMode = CompressionMode.NONE; + + + FileNamePattern fileNamePattern; + + + protected String fileNamePatternStr; + + private FileAppender parent; + + FileNamePattern zipEntryFileNamePattern; + + private boolean started; + + + public RollingPolicyBase() {} + + + protected void determineCompressionMode() + { + if (fileNamePatternStr.endsWith(".gz")) { + addInfo("Will use gz compression"); + compressionMode = CompressionMode.GZ; + } else if (fileNamePatternStr.endsWith(".zip")) { + addInfo("Will use zip compression"); + compressionMode = CompressionMode.ZIP; + } else { + addInfo("No compression will be used"); + compressionMode = CompressionMode.NONE; + } + } + + public void setFileNamePattern(String fnp) { + fileNamePatternStr = fnp; + } + + public String getFileNamePattern() { + return fileNamePatternStr; + } + + public CompressionMode getCompressionMode() { + return compressionMode; + } + + public boolean isStarted() { + return started; + } + + public void start() { + started = true; + } + + public void stop() { + started = false; + } + + public void setParent(FileAppender appender) { + parent = appender; + } + + public boolean isParentPrudent() { + return parent.isPrudent(); + } + + public String getParentsRawFileProperty() { + return parent.rawFileProperty(); + } +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/RolloverFailure.java b/src/minecraft/ch/qos/logback/core/rolling/RolloverFailure.java new file mode 100644 index 0000000..d1e1615 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/RolloverFailure.java @@ -0,0 +1,35 @@ +package ch.qos.logback.core.rolling; + +import ch.qos.logback.core.LogbackException; + + + + + + + + + + + + + + + + + + +public class RolloverFailure + extends LogbackException +{ + private static final long serialVersionUID = -4407533730831239458L; + + public RolloverFailure(String msg) + { + super(msg); + } + + public RolloverFailure(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/SizeAndTimeBasedFNATP.java b/src/minecraft/ch/qos/logback/core/rolling/SizeAndTimeBasedFNATP.java new file mode 100644 index 0000000..a6bba1c --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/SizeAndTimeBasedFNATP.java @@ -0,0 +1,138 @@ +package ch.qos.logback.core.rolling; + +import ch.qos.logback.core.joran.spi.NoAutoStart; +import ch.qos.logback.core.rolling.helper.ArchiveRemover; +import ch.qos.logback.core.rolling.helper.CompressionMode; +import ch.qos.logback.core.rolling.helper.FileFilterUtil; +import ch.qos.logback.core.rolling.helper.FileNamePattern; +import ch.qos.logback.core.rolling.helper.SizeAndTimeBasedArchiveRemover; +import ch.qos.logback.core.util.FileSize; +import java.io.File; +import java.util.Date; + + + + + + + + + + + + + + +@NoAutoStart +public class SizeAndTimeBasedFNATP + extends TimeBasedFileNamingAndTriggeringPolicyBase +{ + int currentPeriodsCounter = 0; + FileSize maxFileSize; + String maxFileSizeAsString; + private int invocationCounter; + + public SizeAndTimeBasedFNATP() {} + + public void start() { + super.start(); + + archiveRemover = createArchiveRemover(); + archiveRemover.setContext(context); + + + + + String regex = tbrp.fileNamePattern.toRegexForFixedDate(dateInCurrentPeriod); + String stemRegex = FileFilterUtil.afterLastSlash(regex); + + + computeCurrentPeriodsHighestCounterValue(stemRegex); + + started = true; + } + + protected ArchiveRemover createArchiveRemover() { + return new SizeAndTimeBasedArchiveRemover(tbrp.fileNamePattern, rc); + } + + void computeCurrentPeriodsHighestCounterValue(String stemRegex) { + File file = new File(getCurrentPeriodsFileNameWithoutCompressionSuffix()); + File parentDir = file.getParentFile(); + + File[] matchingFileArray = FileFilterUtil.filesInFolderMatchingStemRegex(parentDir, stemRegex); + + + if ((matchingFileArray == null) || (matchingFileArray.length == 0)) { + currentPeriodsCounter = 0; + return; + } + currentPeriodsCounter = FileFilterUtil.findHighestCounter(matchingFileArray, stemRegex); + + + + if ((tbrp.getParentsRawFileProperty() != null) || (tbrp.compressionMode != CompressionMode.NONE)) + { + currentPeriodsCounter += 1; + } + } + + + + + + + private int invocationMask = 1; + + public boolean isTriggeringEvent(File activeFile, E event) + { + long time = getCurrentTime(); + if (time >= nextCheck) { + Date dateInElapsedPeriod = dateInCurrentPeriod; + elapsedPeriodsFileName = tbrp.fileNamePatternWCS.convertMultipleArguments(new Object[] { dateInElapsedPeriod, Integer.valueOf(currentPeriodsCounter) }); + + currentPeriodsCounter = 0; + setDateInCurrentPeriod(time); + computeNextCheck(); + return true; + } + + + if ((++invocationCounter & invocationMask) != invocationMask) { + return false; + } + if (invocationMask < 15) { + invocationMask = ((invocationMask << 1) + 1); + } + + if (activeFile.length() >= maxFileSize.getSize()) { + elapsedPeriodsFileName = tbrp.fileNamePatternWCS.convertMultipleArguments(new Object[] { dateInCurrentPeriod, Integer.valueOf(currentPeriodsCounter) }); + + currentPeriodsCounter += 1; + return true; + } + + return false; + } + + private String getFileNameIncludingCompressionSuffix(Date date, int counter) { + return tbrp.fileNamePattern.convertMultipleArguments(new Object[] { dateInCurrentPeriod, Integer.valueOf(counter) }); + } + + + + public String getCurrentPeriodsFileNameWithoutCompressionSuffix() + { + return tbrp.fileNamePatternWCS.convertMultipleArguments(new Object[] { dateInCurrentPeriod, Integer.valueOf(currentPeriodsCounter) }); + } + + public String getMaxFileSize() + { + return maxFileSizeAsString; + } + + public void setMaxFileSize(String maxFileSize) { + maxFileSizeAsString = maxFileSize; + this.maxFileSize = FileSize.valueOf(maxFileSize); + } +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/SizeBasedTriggeringPolicy.java b/src/minecraft/ch/qos/logback/core/rolling/SizeBasedTriggeringPolicy.java new file mode 100644 index 0000000..46c2d1a --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/SizeBasedTriggeringPolicy.java @@ -0,0 +1,100 @@ +package ch.qos.logback.core.rolling; + +import ch.qos.logback.core.util.FileSize; +import ch.qos.logback.core.util.InvocationGate; +import java.io.File; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class SizeBasedTriggeringPolicy + extends TriggeringPolicyBase +{ + public static final String SEE_SIZE_FORMAT = "http://logback.qos.ch/codes.html#sbtp_size_format"; + public static final long DEFAULT_MAX_FILE_SIZE = 10485760L; + String maxFileSizeAsString = Long.toString(10485760L); + FileSize maxFileSize; + + public SizeBasedTriggeringPolicy() {} + + public SizeBasedTriggeringPolicy(String maxFileSize) + { + setMaxFileSize(maxFileSize); + } + + private InvocationGate invocationGate = new InvocationGate(); + + public boolean isTriggeringEvent(File activeFile, E event) { + if (invocationGate.skipFurtherWork()) { + return false; + } + long now = System.currentTimeMillis(); + invocationGate.updateMaskIfNecessary(now); + + return activeFile.length() >= maxFileSize.getSize(); + } + + public String getMaxFileSize() { + return maxFileSizeAsString; + } + + public void setMaxFileSize(String maxFileSize) { + maxFileSizeAsString = maxFileSize; + this.maxFileSize = FileSize.valueOf(maxFileSize); + } + + long toFileSize(String value) { + if (value == null) { + return 10485760L; + } + String s = value.trim().toUpperCase(); + long multiplier = 1L; + + int index; + if ((index = s.indexOf("KB")) != -1) { + multiplier = 1024L; + s = s.substring(0, index); + } else if ((index = s.indexOf("MB")) != -1) { + multiplier = 1048576L; + s = s.substring(0, index); + } else if ((index = s.indexOf("GB")) != -1) { + multiplier = 1073741824L; + s = s.substring(0, index); + } + if (s != null) { + try { + return Long.valueOf(s).longValue() * multiplier; + } catch (NumberFormatException e) { + addError("[" + s + "] is not in proper int format. Please refer to " + "http://logback.qos.ch/codes.html#sbtp_size_format"); + + addError("[" + value + "] not in expected format.", e); + } + } + return 10485760L; + } +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/TimeBasedFileNamingAndTriggeringPolicy.java b/src/minecraft/ch/qos/logback/core/rolling/TimeBasedFileNamingAndTriggeringPolicy.java new file mode 100644 index 0000000..75996ab --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/TimeBasedFileNamingAndTriggeringPolicy.java @@ -0,0 +1,20 @@ +package ch.qos.logback.core.rolling; + +import ch.qos.logback.core.rolling.helper.ArchiveRemover; +import ch.qos.logback.core.spi.ContextAware; + +public abstract interface TimeBasedFileNamingAndTriggeringPolicy + extends TriggeringPolicy, ContextAware +{ + public abstract void setTimeBasedRollingPolicy(TimeBasedRollingPolicy paramTimeBasedRollingPolicy); + + public abstract String getElapsedPeriodsFileName(); + + public abstract String getCurrentPeriodsFileNameWithoutCompressionSuffix(); + + public abstract ArchiveRemover getArchiveRemover(); + + public abstract long getCurrentTime(); + + public abstract void setCurrentTime(long paramLong); +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/TimeBasedFileNamingAndTriggeringPolicyBase.java b/src/minecraft/ch/qos/logback/core/rolling/TimeBasedFileNamingAndTriggeringPolicyBase.java new file mode 100644 index 0000000..3e4ec8f --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/TimeBasedFileNamingAndTriggeringPolicyBase.java @@ -0,0 +1,117 @@ +package ch.qos.logback.core.rolling; + +import ch.qos.logback.core.rolling.helper.ArchiveRemover; +import ch.qos.logback.core.rolling.helper.DateTokenConverter; +import ch.qos.logback.core.rolling.helper.FileNamePattern; +import ch.qos.logback.core.rolling.helper.RollingCalendar; +import ch.qos.logback.core.spi.ContextAwareBase; +import java.io.File; +import java.util.Date; + + + + + + + + + + + +public abstract class TimeBasedFileNamingAndTriggeringPolicyBase + extends ContextAwareBase + implements TimeBasedFileNamingAndTriggeringPolicy +{ + protected TimeBasedRollingPolicy tbrp; + + public TimeBasedFileNamingAndTriggeringPolicyBase() {} + + protected ArchiveRemover archiveRemover = null; + protected String elapsedPeriodsFileName; + protected RollingCalendar rc; + + protected long artificialCurrentTime = -1L; + protected Date dateInCurrentPeriod = null; + protected long nextCheck; + + protected boolean started = false; + + public boolean isStarted() { + return started; + } + + public void start() { + DateTokenConverter dtc = tbrp.fileNamePattern.getPrimaryDateTokenConverter(); + if (dtc == null) { + throw new IllegalStateException("FileNamePattern [" + tbrp.fileNamePattern.getPattern() + "] does not contain a valid DateToken"); + } + + + + rc = new RollingCalendar(); + rc.init(dtc.getDatePattern()); + addInfo("The date pattern is '" + dtc.getDatePattern() + "' from file name pattern '" + tbrp.fileNamePattern.getPattern() + "'."); + + + rc.printPeriodicity(this); + + setDateInCurrentPeriod(new Date(getCurrentTime())); + if (tbrp.getParentsRawFileProperty() != null) { + File currentFile = new File(tbrp.getParentsRawFileProperty()); + if ((currentFile.exists()) && (currentFile.canRead())) { + setDateInCurrentPeriod(new Date(currentFile.lastModified())); + } + } + + addInfo("Setting initial period to " + dateInCurrentPeriod); + computeNextCheck(); + } + + public void stop() { + started = false; + } + + protected void computeNextCheck() { + nextCheck = rc.getNextTriggeringMillis(dateInCurrentPeriod); + } + + protected void setDateInCurrentPeriod(long now) { + dateInCurrentPeriod.setTime(now); + } + + + public void setDateInCurrentPeriod(Date _dateInCurrentPeriod) + { + dateInCurrentPeriod = _dateInCurrentPeriod; + } + + public String getElapsedPeriodsFileName() { + return elapsedPeriodsFileName; + } + + public String getCurrentPeriodsFileNameWithoutCompressionSuffix() { + return tbrp.fileNamePatternWCS.convert(dateInCurrentPeriod); + } + + public void setCurrentTime(long timeInMillis) { + artificialCurrentTime = timeInMillis; + } + + public long getCurrentTime() + { + if (artificialCurrentTime >= 0L) { + return artificialCurrentTime; + } + return System.currentTimeMillis(); + } + + public void setTimeBasedRollingPolicy(TimeBasedRollingPolicy _tbrp) + { + tbrp = _tbrp; + } + + public ArchiveRemover getArchiveRemover() + { + return archiveRemover; + } +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/TimeBasedRollingPolicy.java b/src/minecraft/ch/qos/logback/core/rolling/TimeBasedRollingPolicy.java new file mode 100644 index 0000000..2303d8d --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/TimeBasedRollingPolicy.java @@ -0,0 +1,254 @@ +package ch.qos.logback.core.rolling; + +import ch.qos.logback.core.rolling.helper.ArchiveRemover; +import ch.qos.logback.core.rolling.helper.AsynchronousCompressor; +import ch.qos.logback.core.rolling.helper.CompressionMode; +import ch.qos.logback.core.rolling.helper.Compressor; +import ch.qos.logback.core.rolling.helper.FileFilterUtil; +import ch.qos.logback.core.rolling.helper.FileNamePattern; +import ch.qos.logback.core.rolling.helper.RenameUtil; +import java.io.File; +import java.util.Date; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + + + + + + + + + + + + + + + + + + + + + + +public class TimeBasedRollingPolicy + extends RollingPolicyBase + implements TriggeringPolicy +{ + static final String FNP_NOT_SET = "The FileNamePattern option must be set before using TimeBasedRollingPolicy. "; + static final int INFINITE_HISTORY = 0; + FileNamePattern fileNamePatternWCS; + private Compressor compressor; + private RenameUtil renameUtil = new RenameUtil(); + + Future future; + private int maxHistory = 0; + + private ArchiveRemover archiveRemover; + + TimeBasedFileNamingAndTriggeringPolicy timeBasedFileNamingAndTriggeringPolicy; + boolean cleanHistoryOnStart = false; + + public TimeBasedRollingPolicy() {} + + public void start() { renameUtil.setContext(context); + + + if (fileNamePatternStr != null) { + fileNamePattern = new FileNamePattern(fileNamePatternStr, context); + determineCompressionMode(); + } else { + addWarn("The FileNamePattern option must be set before using TimeBasedRollingPolicy. "); + addWarn("See also http://logback.qos.ch/codes.html#tbr_fnp_not_set"); + throw new IllegalStateException("The FileNamePattern option must be set before using TimeBasedRollingPolicy. See also http://logback.qos.ch/codes.html#tbr_fnp_not_set"); + } + + + compressor = new Compressor(compressionMode); + compressor.setContext(context); + + + fileNamePatternWCS = new FileNamePattern(Compressor.computeFileNameStr_WCS(fileNamePatternStr, compressionMode), context); + + + addInfo("Will use the pattern " + fileNamePatternWCS + " for the active file"); + + + if (compressionMode == CompressionMode.ZIP) { + String zipEntryFileNamePatternStr = transformFileNamePattern2ZipEntry(fileNamePatternStr); + zipEntryFileNamePattern = new FileNamePattern(zipEntryFileNamePatternStr, context); + } + + if (timeBasedFileNamingAndTriggeringPolicy == null) { + timeBasedFileNamingAndTriggeringPolicy = new DefaultTimeBasedFileNamingAndTriggeringPolicy(); + } + timeBasedFileNamingAndTriggeringPolicy.setContext(context); + timeBasedFileNamingAndTriggeringPolicy.setTimeBasedRollingPolicy(this); + timeBasedFileNamingAndTriggeringPolicy.start(); + + + + + if (maxHistory != 0) { + archiveRemover = timeBasedFileNamingAndTriggeringPolicy.getArchiveRemover(); + archiveRemover.setMaxHistory(maxHistory); + if (cleanHistoryOnStart) { + addInfo("Cleaning on start up"); + archiveRemover.clean(new Date(timeBasedFileNamingAndTriggeringPolicy.getCurrentTime())); + } + } + + super.start(); + } + + public void stop() + { + if (!isStarted()) + return; + waitForAsynchronousJobToStop(); + super.stop(); + } + + private void waitForAsynchronousJobToStop() + { + if (future != null) + try { + future.get(30L, TimeUnit.SECONDS); + } catch (TimeoutException e) { + addError("Timeout while waiting for compression job to finish", e); + } catch (Exception e) { + addError("Unexpected exception while waiting for compression job to finish", e); + } + } + + private String transformFileNamePattern2ZipEntry(String fileNamePatternStr) { + String slashified = FileFilterUtil.slashify(fileNamePatternStr); + return FileFilterUtil.afterLastSlash(slashified); + } + + public void setTimeBasedFileNamingAndTriggeringPolicy(TimeBasedFileNamingAndTriggeringPolicy timeBasedTriggering) + { + timeBasedFileNamingAndTriggeringPolicy = timeBasedTriggering; + } + + public TimeBasedFileNamingAndTriggeringPolicy getTimeBasedFileNamingAndTriggeringPolicy() { + return timeBasedFileNamingAndTriggeringPolicy; + } + + + + public void rollover() + throws RolloverFailure + { + String elapsedPeriodsFileName = timeBasedFileNamingAndTriggeringPolicy.getElapsedPeriodsFileName(); + + + String elapsedPeriodStem = FileFilterUtil.afterLastSlash(elapsedPeriodsFileName); + + if (compressionMode == CompressionMode.NONE) { + if (getParentsRawFileProperty() != null) { + renameUtil.rename(getParentsRawFileProperty(), elapsedPeriodsFileName); + } + } + else if (getParentsRawFileProperty() == null) { + future = asyncCompress(elapsedPeriodsFileName, elapsedPeriodsFileName, elapsedPeriodStem); + } else { + future = renamedRawAndAsyncCompress(elapsedPeriodsFileName, elapsedPeriodStem); + } + + + if (archiveRemover != null) { + archiveRemover.clean(new Date(timeBasedFileNamingAndTriggeringPolicy.getCurrentTime())); + } + } + + Future asyncCompress(String nameOfFile2Compress, String nameOfCompressedFile, String innerEntryName) throws RolloverFailure + { + AsynchronousCompressor ac = new AsynchronousCompressor(compressor); + return ac.compressAsynchronously(nameOfFile2Compress, nameOfCompressedFile, innerEntryName); + } + + Future renamedRawAndAsyncCompress(String nameOfCompressedFile, String innerEntryName) throws RolloverFailure + { + String parentsRawFile = getParentsRawFileProperty(); + String tmpTarget = parentsRawFile + System.nanoTime() + ".tmp"; + renameUtil.rename(parentsRawFile, tmpTarget); + return asyncCompress(tmpTarget, nameOfCompressedFile, innerEntryName); + } + + + + + + + + + + + + + + + + + + + + + public String getActiveFileName() + { + String parentsRawFileProperty = getParentsRawFileProperty(); + if (parentsRawFileProperty != null) { + return parentsRawFileProperty; + } + return timeBasedFileNamingAndTriggeringPolicy.getCurrentPeriodsFileNameWithoutCompressionSuffix(); + } + + + public boolean isTriggeringEvent(File activeFile, E event) + { + return timeBasedFileNamingAndTriggeringPolicy.isTriggeringEvent(activeFile, event); + } + + + + + + public int getMaxHistory() + { + return maxHistory; + } + + + + + + + public void setMaxHistory(int maxHistory) + { + this.maxHistory = maxHistory; + } + + public boolean isCleanHistoryOnStart() + { + return cleanHistoryOnStart; + } + + + + + + public void setCleanHistoryOnStart(boolean cleanHistoryOnStart) + { + this.cleanHistoryOnStart = cleanHistoryOnStart; + } + + + public String toString() + { + return "c.q.l.core.rolling.TimeBasedRollingPolicy"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/TriggeringPolicy.java b/src/minecraft/ch/qos/logback/core/rolling/TriggeringPolicy.java new file mode 100644 index 0000000..0926539 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/TriggeringPolicy.java @@ -0,0 +1,10 @@ +package ch.qos.logback.core.rolling; + +import ch.qos.logback.core.spi.LifeCycle; +import java.io.File; + +public abstract interface TriggeringPolicy + extends LifeCycle +{ + public abstract boolean isTriggeringEvent(File paramFile, E paramE); +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/TriggeringPolicyBase.java b/src/minecraft/ch/qos/logback/core/rolling/TriggeringPolicyBase.java new file mode 100644 index 0000000..59fd0b1 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/TriggeringPolicyBase.java @@ -0,0 +1,41 @@ +package ch.qos.logback.core.rolling; + +import ch.qos.logback.core.spi.ContextAwareBase; + + + + + + + + + + + + + + + + + +public abstract class TriggeringPolicyBase + extends ContextAwareBase + implements TriggeringPolicy +{ + private boolean start; + + public TriggeringPolicyBase() {} + + public void start() + { + start = true; + } + + public void stop() { + start = false; + } + + public boolean isStarted() { + return start; + } +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/helper/ArchiveRemover.java b/src/minecraft/ch/qos/logback/core/rolling/helper/ArchiveRemover.java new file mode 100644 index 0000000..c297671 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/helper/ArchiveRemover.java @@ -0,0 +1,12 @@ +package ch.qos.logback.core.rolling.helper; + +import ch.qos.logback.core.spi.ContextAware; +import java.util.Date; + +public abstract interface ArchiveRemover + extends ContextAware +{ + public abstract void clean(Date paramDate); + + public abstract void setMaxHistory(int paramInt); +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/helper/AsynchronousCompressor.java b/src/minecraft/ch/qos/logback/core/rolling/helper/AsynchronousCompressor.java new file mode 100644 index 0000000..321bdaa --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/helper/AsynchronousCompressor.java @@ -0,0 +1,35 @@ +package ch.qos.logback.core.rolling.helper; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + + + + + + + + + + + + +public class AsynchronousCompressor +{ + Compressor compressor; + + public AsynchronousCompressor(Compressor compressor) + { + this.compressor = compressor; + } + + public Future compressAsynchronously(String nameOfFile2Compress, String nameOfCompressedFile, String innerEntryName) + { + ExecutorService executor = Executors.newScheduledThreadPool(1); + Future future = executor.submit(new CompressionRunnable(compressor, nameOfFile2Compress, nameOfCompressedFile, innerEntryName)); + + executor.shutdown(); + return future; + } +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/helper/CompressionMode.java b/src/minecraft/ch/qos/logback/core/rolling/helper/CompressionMode.java new file mode 100644 index 0000000..27da9f9 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/helper/CompressionMode.java @@ -0,0 +1,8 @@ +package ch.qos.logback.core.rolling.helper; + +public enum CompressionMode +{ + NONE, GZ, ZIP; + + private CompressionMode() {} +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/helper/CompressionRunnable.java b/src/minecraft/ch/qos/logback/core/rolling/helper/CompressionRunnable.java new file mode 100644 index 0000000..a149197 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/helper/CompressionRunnable.java @@ -0,0 +1,35 @@ +package ch.qos.logback.core.rolling.helper; + + + + +public class CompressionRunnable + implements Runnable +{ + final Compressor compressor; + + + + final String nameOfFile2Compress; + + + + final String nameOfCompressedFile; + + + final String innerEntryName; + + + + public CompressionRunnable(Compressor compressor, String nameOfFile2Compress, String nameOfCompressedFile, String innerEntryName) + { + this.compressor = compressor; + this.nameOfFile2Compress = nameOfFile2Compress; + this.nameOfCompressedFile = nameOfCompressedFile; + this.innerEntryName = innerEntryName; + } + + public void run() { + compressor.compress(nameOfFile2Compress, nameOfCompressedFile, innerEntryName); + } +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/helper/Compressor.java b/src/minecraft/ch/qos/logback/core/rolling/helper/Compressor.java new file mode 100644 index 0000000..8e07d42 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/helper/Compressor.java @@ -0,0 +1,271 @@ +package ch.qos.logback.core.rolling.helper; + +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.status.ErrorStatus; +import ch.qos.logback.core.status.WarnStatus; +import ch.qos.logback.core.util.FileUtil; +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.zip.GZIPOutputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + + + + + + + + + + + + + + + + + + + + + +public class Compressor + extends ContextAwareBase +{ + final CompressionMode compressionMode; + static final int BUFFER_SIZE = 8192; + + public Compressor(CompressionMode compressionMode) + { + this.compressionMode = compressionMode; + } + + + + + + public void compress(String nameOfFile2Compress, String nameOfCompressedFile, String innerEntryName) + { + switch (1.$SwitchMap$ch$qos$logback$core$rolling$helper$CompressionMode[compressionMode.ordinal()]) { + case 1: + gzCompress(nameOfFile2Compress, nameOfCompressedFile); + break; + case 2: + zipCompress(nameOfFile2Compress, nameOfCompressedFile, innerEntryName); + break; + case 3: + throw new UnsupportedOperationException("compress method called in NONE compression mode"); + } + } + + private void zipCompress(String nameOfFile2zip, String nameOfZippedFile, String innerEntryName) + { + File file2zip = new File(nameOfFile2zip); + + if (!file2zip.exists()) { + addStatus(new WarnStatus("The file to compress named [" + nameOfFile2zip + "] does not exist.", this)); + + + return; + } + + if (innerEntryName == null) { + addStatus(new WarnStatus("The innerEntryName parameter cannot be null", this)); + return; + } + + if (!nameOfZippedFile.endsWith(".zip")) { + nameOfZippedFile = nameOfZippedFile + ".zip"; + } + + File zippedFile = new File(nameOfZippedFile); + + if (zippedFile.exists()) { + addStatus(new WarnStatus("The target compressed file named [" + nameOfZippedFile + "] exist already.", this)); + + + return; + } + + addInfo("ZIP compressing [" + file2zip + "] as [" + zippedFile + "]"); + createMissingTargetDirsIfNecessary(zippedFile); + + BufferedInputStream bis = null; + ZipOutputStream zos = null; + try { + bis = new BufferedInputStream(new FileInputStream(nameOfFile2zip)); + zos = new ZipOutputStream(new FileOutputStream(nameOfZippedFile)); + + ZipEntry zipEntry = computeZipEntry(innerEntryName); + zos.putNextEntry(zipEntry); + + byte[] inbuf = new byte[' ']; + + int n; + while ((n = bis.read(inbuf)) != -1) { + zos.write(inbuf, 0, n); + } + + bis.close(); + bis = null; + zos.close(); + zos = null; + + if (!file2zip.delete()) { + addStatus(new WarnStatus("Could not delete [" + nameOfFile2zip + "].", this)); + } + return; + } catch (Exception e) { + addStatus(new ErrorStatus("Error occurred while compressing [" + nameOfFile2zip + "] into [" + nameOfZippedFile + "].", this, e)); + } + finally { + if (bis != null) { + try { + bis.close(); + } + catch (IOException e) {} + } + + if (zos != null) { + try { + zos.close(); + } + catch (IOException e) {} + } + } + } + + + + + + + + + + + + + + + + + + + ZipEntry computeZipEntry(File zippedFile) + { + return computeZipEntry(zippedFile.getName()); + } + + ZipEntry computeZipEntry(String filename) { + String nameOfFileNestedWithinArchive = computeFileNameStr_WCS(filename, compressionMode); + return new ZipEntry(nameOfFileNestedWithinArchive); + } + + private void gzCompress(String nameOfFile2gz, String nameOfgzedFile) + { + File file2gz = new File(nameOfFile2gz); + + if (!file2gz.exists()) { + addStatus(new WarnStatus("The file to compress named [" + nameOfFile2gz + "] does not exist.", this)); + + + return; + } + + + if (!nameOfgzedFile.endsWith(".gz")) { + nameOfgzedFile = nameOfgzedFile + ".gz"; + } + + File gzedFile = new File(nameOfgzedFile); + + if (gzedFile.exists()) { + addWarn("The target compressed file named [" + nameOfgzedFile + "] exist already. Aborting file compression."); + + return; + } + + addInfo("GZ compressing [" + file2gz + "] as [" + gzedFile + "]"); + createMissingTargetDirsIfNecessary(gzedFile); + + BufferedInputStream bis = null; + GZIPOutputStream gzos = null; + try { + bis = new BufferedInputStream(new FileInputStream(nameOfFile2gz)); + gzos = new GZIPOutputStream(new FileOutputStream(nameOfgzedFile)); + byte[] inbuf = new byte[' ']; + + int n; + while ((n = bis.read(inbuf)) != -1) { + gzos.write(inbuf, 0, n); + } + + bis.close(); + bis = null; + gzos.close(); + gzos = null; + + if (!file2gz.delete()) { + addStatus(new WarnStatus("Could not delete [" + nameOfFile2gz + "].", this)); + } + return; + } catch (Exception e) { + addStatus(new ErrorStatus("Error occurred while compressing [" + nameOfFile2gz + "] into [" + nameOfgzedFile + "].", this, e)); + } + finally { + if (bis != null) { + try { + bis.close(); + } + catch (IOException e) {} + } + + if (gzos != null) { + try { + gzos.close(); + } + catch (IOException e) {} + } + } + } + + + public static String computeFileNameStr_WCS(String fileNamePatternStr, CompressionMode compressionMode) + { + int len = fileNamePatternStr.length(); + switch (1.$SwitchMap$ch$qos$logback$core$rolling$helper$CompressionMode[compressionMode.ordinal()]) { + case 1: + if (fileNamePatternStr.endsWith(".gz")) { + return fileNamePatternStr.substring(0, len - 3); + } + return fileNamePatternStr; + case 2: + if (fileNamePatternStr.endsWith(".zip")) { + return fileNamePatternStr.substring(0, len - 4); + } + return fileNamePatternStr; + case 3: + return fileNamePatternStr; + } + throw new IllegalStateException("Execution should not reach this point"); + } + + void createMissingTargetDirsIfNecessary(File file) + { + boolean result = FileUtil.createMissingParentDirectories(file); + if (!result) { + addError("Failed to create parent directories for [" + file.getAbsolutePath() + "]"); + } + } + + + public String toString() + { + return getClass().getName(); + } +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/helper/DateTokenConverter.java b/src/minecraft/ch/qos/logback/core/rolling/helper/DateTokenConverter.java new file mode 100644 index 0000000..426365b --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/helper/DateTokenConverter.java @@ -0,0 +1,106 @@ +package ch.qos.logback.core.rolling.helper; + +import ch.qos.logback.core.pattern.DynamicConverter; +import ch.qos.logback.core.util.CachingDateFormatter; +import ch.qos.logback.core.util.DatePatternToRegexUtil; +import java.util.Date; +import java.util.List; +import java.util.TimeZone; + + + + + + + + + + + + + + + + + + + + + + +public class DateTokenConverter + extends DynamicConverter + implements MonoTypedConverter +{ + public static final String CONVERTER_KEY = "d"; + public static final String AUXILIARY_TOKEN = "AUX"; + public static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd"; + private String datePattern; + private TimeZone timeZone; + private CachingDateFormatter cdf; + + public DateTokenConverter() {} + + private boolean primary = true; + + public void start() { datePattern = getFirstOption(); + if (datePattern == null) { + datePattern = "yyyy-MM-dd"; + } + + List optionList = getOptionList(); + if (optionList != null) { + for (int optionIndex = 1; optionIndex < optionList.size(); optionIndex++) { + String option = (String)optionList.get(optionIndex); + if ("AUX".equalsIgnoreCase(option)) { + primary = false; + } else { + timeZone = TimeZone.getTimeZone(option); + } + } + } + + cdf = new CachingDateFormatter(datePattern); + if (timeZone != null) { + cdf.setTimeZone(timeZone); + } + } + + public String convert(Date date) { + return cdf.format(date.getTime()); + } + + public String convert(Object o) { + if (o == null) { + throw new IllegalArgumentException("Null argument forbidden"); + } + if ((o instanceof Date)) { + return convert((Date)o); + } + throw new IllegalArgumentException("Cannot convert " + o + " of type" + o.getClass().getName()); + } + + + + public String getDatePattern() + { + return datePattern; + } + + public TimeZone getTimeZone() { + return timeZone; + } + + public boolean isApplicable(Object o) { + return o instanceof Date; + } + + public String toRegex() { + DatePatternToRegexUtil datePatternToRegexUtil = new DatePatternToRegexUtil(datePattern); + return datePatternToRegexUtil.toRegex(); + } + + public boolean isPrimary() { + return primary; + } +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/helper/DefaultArchiveRemover.java b/src/minecraft/ch/qos/logback/core/rolling/helper/DefaultArchiveRemover.java new file mode 100644 index 0000000..b64809c --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/helper/DefaultArchiveRemover.java @@ -0,0 +1,137 @@ +package ch.qos.logback.core.rolling.helper; + +import ch.qos.logback.core.pattern.Converter; +import ch.qos.logback.core.pattern.LiteralConverter; +import ch.qos.logback.core.spi.ContextAwareBase; +import java.io.File; +import java.util.Date; + + + + + + + + + + + + + + + + + +public abstract class DefaultArchiveRemover + extends ContextAwareBase + implements ArchiveRemover +{ + protected static final long UNINITIALIZED = -1L; + protected static final long INACTIVITY_TOLERANCE_IN_MILLIS = 5529600000L; + static final int MAX_VALUE_FOR_INACTIVITY_PERIODS = 336; + final FileNamePattern fileNamePattern; + final RollingCalendar rc; + int periodOffsetForDeletionTarget; + final boolean parentClean; + long lastHeartBeat = -1L; + + public DefaultArchiveRemover(FileNamePattern fileNamePattern, RollingCalendar rc) + { + this.fileNamePattern = fileNamePattern; + this.rc = rc; + parentClean = computeParentCleaningFlag(fileNamePattern); + } + + int computeElapsedPeriodsSinceLastClean(long nowInMillis) + { + long periodsElapsed = 0L; + if (lastHeartBeat == -1L) { + addInfo("first clean up after appender initialization"); + periodsElapsed = rc.periodsElapsed(nowInMillis, nowInMillis + 5529600000L); + if (periodsElapsed > 336L) + periodsElapsed = 336L; + } else { + periodsElapsed = rc.periodsElapsed(lastHeartBeat, nowInMillis); + if (periodsElapsed < 1L) { + addWarn("Unexpected periodsElapsed value " + periodsElapsed); + periodsElapsed = 1L; + } + } + return (int)periodsElapsed; + } + + public void clean(Date now) { + long nowInMillis = now.getTime(); + int periodsElapsed = computeElapsedPeriodsSinceLastClean(nowInMillis); + lastHeartBeat = nowInMillis; + if (periodsElapsed > 1) { + addInfo("periodsElapsed = " + periodsElapsed); + } + for (int i = 0; i < periodsElapsed; i++) { + cleanByPeriodOffset(now, periodOffsetForDeletionTarget - i); + } + } + + abstract void cleanByPeriodOffset(Date paramDate, int paramInt); + + boolean computeParentCleaningFlag(FileNamePattern fileNamePattern) { + DateTokenConverter dtc = fileNamePattern.getPrimaryDateTokenConverter(); + + if (dtc.getDatePattern().indexOf('/') != -1) { + return true; + } + + + + Converter p = headTokenConverter; + + + while ((p != null) && + (!(p instanceof DateTokenConverter))) + { + + p = p.getNext(); + } + + while (p != null) { + if ((p instanceof LiteralConverter)) { + String s = p.convert(null); + if (s.indexOf('/') != -1) { + return true; + } + } + p = p.getNext(); + } + + + return false; + } + + void removeFolderIfEmpty(File dir) { + removeFolderIfEmpty(dir, 0); + } + + + + + + + + + + private void removeFolderIfEmpty(File dir, int depth) + { + if (depth >= 3) { + return; + } + if ((dir.isDirectory()) && (FileFilterUtil.isEmptyDirectory(dir))) { + addInfo("deleting folder [" + dir + "]"); + dir.delete(); + removeFolderIfEmpty(dir.getParentFile(), depth + 1); + } + } + + public void setMaxHistory(int maxHistory) { + periodOffsetForDeletionTarget = (-maxHistory - 1); + } +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/helper/FileFilterUtil.java b/src/minecraft/ch/qos/logback/core/rolling/helper/FileFilterUtil.java new file mode 100644 index 0000000..6d7e340 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/helper/FileFilterUtil.java @@ -0,0 +1,129 @@ +package ch.qos.logback.core.rolling.helper; + +import java.io.File; +import java.io.FilenameFilter; +import java.util.Arrays; +import java.util.Comparator; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + + + + + + + + + + +public class FileFilterUtil +{ + public FileFilterUtil() {} + + public static void sortFileArrayByName(File[] fileArray) + { + Arrays.sort(fileArray, new Comparator() { + public int compare(File o1, File o2) { + String o1Name = o1.getName(); + String o2Name = o2.getName(); + return o1Name.compareTo(o2Name); + } + }); + } + + public static void reverseSortFileArrayByName(File[] fileArray) { + Arrays.sort(fileArray, new Comparator() { + public int compare(File o1, File o2) { + String o1Name = o1.getName(); + String o2Name = o2.getName(); + return o2Name.compareTo(o1Name); + } + }); + } + + public static String afterLastSlash(String sregex) { + int i = sregex.lastIndexOf('/'); + if (i == -1) { + return sregex; + } + return sregex.substring(i + 1); + } + + public static boolean isEmptyDirectory(File dir) + { + if (!dir.isDirectory()) { + throw new IllegalArgumentException("[" + dir + "] must be a directory"); + } + String[] filesInDir = dir.list(); + if ((filesInDir == null) || (filesInDir.length == 0)) { + return true; + } + return false; + } + + + + + + + + + + + + public static File[] filesInFolderMatchingStemRegex(File file, String stemRegex) + { + if (file == null) { + return new File[0]; + } + if ((!file.exists()) || (!file.isDirectory())) { + return new File[0]; + } + file.listFiles(new FilenameFilter() { + public boolean accept(File dir, String name) { + return name.matches(val$stemRegex); + } + }); + } + + public static int findHighestCounter(File[] matchingFileArray, String stemRegex) { + int max = Integer.MIN_VALUE; + for (File aFile : matchingFileArray) { + int aCounter = extractCounter(aFile, stemRegex); + if (max < aCounter) + max = aCounter; + } + return max; + } + + public static int extractCounter(File file, String stemRegex) { + Pattern p = Pattern.compile(stemRegex); + String lastFileName = file.getName(); + + Matcher m = p.matcher(lastFileName); + if (!m.matches()) { + throw new IllegalStateException("The regex [" + stemRegex + "] should match [" + lastFileName + "]"); + } + + String counterAsStr = m.group(1); + return new Integer(counterAsStr).intValue(); + } + + public static String slashify(String in) { + return in.replace('\\', '/'); + } + + + public static void removeEmptyParentDirectories(File file, int recursivityCount) + { + if (recursivityCount >= 3) { + return; + } + File parent = file.getParentFile(); + if ((parent.isDirectory()) && (isEmptyDirectory(parent))) { + parent.delete(); + removeEmptyParentDirectories(parent, recursivityCount + 1); + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/helper/FileNamePattern.java b/src/minecraft/ch/qos/logback/core/rolling/helper/FileNamePattern.java new file mode 100644 index 0000000..77246c9 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/helper/FileNamePattern.java @@ -0,0 +1,199 @@ +package ch.qos.logback.core.rolling.helper; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.pattern.Converter; +import ch.qos.logback.core.pattern.ConverterUtil; +import ch.qos.logback.core.pattern.LiteralConverter; +import ch.qos.logback.core.pattern.parser.Node; +import ch.qos.logback.core.pattern.parser.Parser; +import ch.qos.logback.core.pattern.util.AlmostAsIsEscapeUtil; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.spi.ScanException; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + + + + + + + + + + + + + + + + + + + + + + +public class FileNamePattern + extends ContextAwareBase +{ + static final Map CONVERTER_MAP = new HashMap(); + + static { CONVERTER_MAP.put("i", IntegerTokenConverter.class.getName()); + + CONVERTER_MAP.put("d", DateTokenConverter.class.getName()); + } + + + + String pattern; + + public FileNamePattern(String patternArg, Context contextArg) + { + setPattern(FileFilterUtil.slashify(patternArg)); + setContext(contextArg); + parse(); + ConverterUtil.startConverters(headTokenConverter); + } + + + + void parse() + { + try + { + String patternForParsing = escapeRightParantesis(pattern); + Parser p = new Parser(patternForParsing, new AlmostAsIsEscapeUtil()); + p.setContext(context); + Node t = p.parse(); + headTokenConverter = p.compile(t, CONVERTER_MAP); + } + catch (ScanException sce) { + addError("Failed to parse pattern \"" + pattern + "\".", sce); + } + } + + String escapeRightParantesis(String in) { + return pattern.replace(")", "\\)"); + } + + public String toString() { + return pattern; + } + + public DateTokenConverter getPrimaryDateTokenConverter() { + Converter p = headTokenConverter; + + while (p != null) { + if ((p instanceof DateTokenConverter)) { + DateTokenConverter dtc = (DateTokenConverter)p; + + if (dtc.isPrimary()) { + return dtc; + } + } + p = p.getNext(); + } + + return null; + } + + public IntegerTokenConverter getIntegerTokenConverter() { + Converter p = headTokenConverter; + + while (p != null) { + if ((p instanceof IntegerTokenConverter)) { + return (IntegerTokenConverter)p; + } + + p = p.getNext(); + } + return null; + } + + public String convertMultipleArguments(Object... objectList) { + StringBuilder buf = new StringBuilder(); + Converter c = headTokenConverter; + while (c != null) { + if ((c instanceof MonoTypedConverter)) { + MonoTypedConverter monoTyped = (MonoTypedConverter)c; + for (Object o : objectList) { + if (monoTyped.isApplicable(o)) { + buf.append(c.convert(o)); + } + } + } else { + buf.append(c.convert(objectList)); + } + c = c.getNext(); + } + return buf.toString(); + } + + public String convert(Object o) { + StringBuilder buf = new StringBuilder(); + Converter p = headTokenConverter; + while (p != null) { + buf.append(p.convert(o)); + p = p.getNext(); + } + return buf.toString(); + } + + public String convertInt(int i) { + return convert(Integer.valueOf(i)); + } + + public void setPattern(String pattern) { + if (pattern != null) + { + this.pattern = pattern.trim(); + } + } + + public String getPattern() { + return pattern; + } + + + + Converter headTokenConverter; + + + public String toRegexForFixedDate(Date date) + { + StringBuilder buf = new StringBuilder(); + Converter p = headTokenConverter; + while (p != null) { + if ((p instanceof LiteralConverter)) { + buf.append(p.convert(null)); + } else if ((p instanceof IntegerTokenConverter)) { + buf.append("(\\d{1,3})"); + } else if ((p instanceof DateTokenConverter)) { + buf.append(p.convert(date)); + } + p = p.getNext(); + } + return buf.toString(); + } + + + + public String toRegex() + { + StringBuilder buf = new StringBuilder(); + Converter p = headTokenConverter; + while (p != null) { + if ((p instanceof LiteralConverter)) { + buf.append(p.convert(null)); + } else if ((p instanceof IntegerTokenConverter)) { + buf.append("\\d{1,2}"); + } else if ((p instanceof DateTokenConverter)) { + DateTokenConverter dtc = (DateTokenConverter)p; + buf.append(dtc.toRegex()); + } + p = p.getNext(); + } + return buf.toString(); + } +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/helper/FileStoreUtil.java b/src/minecraft/ch/qos/logback/core/rolling/helper/FileStoreUtil.java new file mode 100644 index 0000000..4456687 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/helper/FileStoreUtil.java @@ -0,0 +1,75 @@ +package ch.qos.logback.core.rolling.helper; + +import ch.qos.logback.core.rolling.RolloverFailure; +import java.io.File; +import java.lang.reflect.Method; + + + + + + + + + + + + + + + + + + + + + + + + + +public class FileStoreUtil +{ + static final String PATH_CLASS_STR = "java.nio.file.Path"; + static final String FILES_CLASS_STR = "java.nio.file.Files"; + + public FileStoreUtil() {} + + public static boolean areOnSameFileStore(File a, File b) + throws RolloverFailure + { + if (!a.exists()) { + throw new IllegalArgumentException("File [" + a + "] does not exist."); + } + if (!b.exists()) { + throw new IllegalArgumentException("File [" + b + "] does not exist."); + } + + + + + + + + + + try + { + Class pathClass = Class.forName("java.nio.file.Path"); + Class filesClass = Class.forName("java.nio.file.Files"); + + Method toPath = File.class.getMethod("toPath", new Class[0]); + Method getFileStoreMethod = filesClass.getMethod("getFileStore", new Class[] { pathClass }); + + + Object pathA = toPath.invoke(a, new Object[0]); + Object pathB = toPath.invoke(b, new Object[0]); + + Object fileStoreA = getFileStoreMethod.invoke(null, new Object[] { pathA }); + Object fileStoreB = getFileStoreMethod.invoke(null, new Object[] { pathB }); + return fileStoreA.equals(fileStoreB); + } catch (Exception e) { + throw new RolloverFailure("Failed to check file store equality for [" + a + "] and [" + b + "]", e); + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/helper/IntegerTokenConverter.java b/src/minecraft/ch/qos/logback/core/rolling/helper/IntegerTokenConverter.java new file mode 100644 index 0000000..2faaa9e --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/helper/IntegerTokenConverter.java @@ -0,0 +1,46 @@ +package ch.qos.logback.core.rolling.helper; + +import ch.qos.logback.core.pattern.DynamicConverter; + + + + + + + + + + + + + + + +public class IntegerTokenConverter + extends DynamicConverter + implements MonoTypedConverter +{ + public static final String CONVERTER_KEY = "i"; + + public IntegerTokenConverter() {} + + public String convert(int i) + { + return Integer.toString(i); + } + + public String convert(Object o) { + if (o == null) { + throw new IllegalArgumentException("Null argument forbidden"); + } + if ((o instanceof Integer)) { + Integer i = (Integer)o; + return convert(i.intValue()); + } + throw new IllegalArgumentException("Cannot convert " + o + " of type" + o.getClass().getName()); + } + + public boolean isApplicable(Object o) { + return o instanceof Integer; + } +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/helper/MonoTypedConverter.java b/src/minecraft/ch/qos/logback/core/rolling/helper/MonoTypedConverter.java new file mode 100644 index 0000000..07bea25 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/helper/MonoTypedConverter.java @@ -0,0 +1,6 @@ +package ch.qos.logback.core.rolling.helper; + +public abstract interface MonoTypedConverter +{ + public abstract boolean isApplicable(Object paramObject); +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/helper/PeriodicityType.java b/src/minecraft/ch/qos/logback/core/rolling/helper/PeriodicityType.java new file mode 100644 index 0000000..2761312 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/helper/PeriodicityType.java @@ -0,0 +1,25 @@ +package ch.qos.logback.core.rolling.helper; + + + + + + + + + + + + + + +public enum PeriodicityType +{ + ERRONEOUS, TOP_OF_MILLISECOND, TOP_OF_SECOND, TOP_OF_MINUTE, TOP_OF_HOUR, HALF_DAY, TOP_OF_DAY, TOP_OF_WEEK, TOP_OF_MONTH; + + + + static PeriodicityType[] VALID_ORDERED_LIST = { TOP_OF_MILLISECOND, TOP_OF_SECOND, TOP_OF_MINUTE, TOP_OF_HOUR, TOP_OF_DAY, TOP_OF_WEEK, TOP_OF_MONTH }; + + private PeriodicityType() {} +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/helper/RenameUtil.java b/src/minecraft/ch/qos/logback/core/rolling/helper/RenameUtil.java new file mode 100644 index 0000000..5179a9e --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/helper/RenameUtil.java @@ -0,0 +1,133 @@ +package ch.qos.logback.core.rolling.helper; + +import ch.qos.logback.core.rolling.RollingFileAppender; +import ch.qos.logback.core.rolling.RolloverFailure; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.util.EnvUtil; +import ch.qos.logback.core.util.FileUtil; +import java.io.File; + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class RenameUtil + extends ContextAwareBase +{ + static String RENAMING_ERROR_URL = "http://logback.qos.ch/codes.html#renamingError"; + + + + + public RenameUtil() {} + + + + public void rename(String src, String target) + throws RolloverFailure + { + if (src.equals(target)) { + addWarn("Source and target files are the same [" + src + "]. Skipping."); + return; + } + File srcFile = new File(src); + + if (srcFile.exists()) { + File targetFile = new File(target); + createMissingTargetDirsIfNecessary(targetFile); + + addInfo("Renaming file [" + srcFile + "] to [" + targetFile + "]"); + + boolean result = srcFile.renameTo(targetFile); + + if (!result) { + addWarn("Failed to rename file [" + srcFile + "] as [" + targetFile + "]."); + if (areOnDifferentVolumes(srcFile, targetFile)) { + addWarn("Detected different file systems for source [" + src + "] and target [" + target + "]. Attempting rename by copying."); + renameByCopying(src, target); + return; + } + addWarn("Please consider leaving the [file] option of " + RollingFileAppender.class.getSimpleName() + " empty."); + addWarn("See also " + RENAMING_ERROR_URL); + } + } + else { + throw new RolloverFailure("File [" + src + "] does not exist."); + } + } + + + + + + + + + boolean areOnDifferentVolumes(File srcFile, File targetFile) + throws RolloverFailure + { + if (!EnvUtil.isJDK7OrHigher()) { + return false; + } + File parentOfTarget = targetFile.getParentFile(); + try + { + boolean onSameFileStore = FileStoreUtil.areOnSameFileStore(srcFile, parentOfTarget); + return !onSameFileStore; + } catch (RolloverFailure rf) { + addWarn("Error while checking file store equality", rf); } + return false; + } + + + + + + public void renameByCopying(String src, String target) + throws RolloverFailure + { + FileUtil fileUtil = new FileUtil(getContext()); + fileUtil.copy(src, target); + + File srcFile = new File(src); + if (!srcFile.delete()) { + addWarn("Could not delete " + src); + } + } + + void createMissingTargetDirsIfNecessary(File toFile) throws RolloverFailure + { + boolean result = FileUtil.createMissingParentDirectories(toFile); + if (!result) { + throw new RolloverFailure("Failed to create parent directories for [" + toFile.getAbsolutePath() + "]"); + } + } + + + public String toString() + { + return "c.q.l.co.rolling.helper.RenameUtil"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/helper/RollingCalendar.java b/src/minecraft/ch/qos/logback/core/rolling/helper/RollingCalendar.java new file mode 100644 index 0000000..d61ac64 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/helper/RollingCalendar.java @@ -0,0 +1,243 @@ +package ch.qos.logback.core.rolling.helper; + +import ch.qos.logback.core.spi.ContextAwareBase; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Locale; +import java.util.TimeZone; + + + + + + + + + + + + + + + + + + + + + + + + + +public class RollingCalendar + extends GregorianCalendar +{ + private static final long serialVersionUID = -5937537740925066161L; + static final TimeZone GMT_TIMEZONE = TimeZone.getTimeZone("GMT"); + + PeriodicityType periodicityType = PeriodicityType.ERRONEOUS; + + + public RollingCalendar() {} + + public RollingCalendar(TimeZone tz, Locale locale) + { + super(tz, locale); + } + + public void init(String datePattern) { + periodicityType = computePeriodicityType(datePattern); + } + + private void setPeriodicityType(PeriodicityType periodicityType) { + this.periodicityType = periodicityType; + } + + public PeriodicityType getPeriodicityType() { + return periodicityType; + } + + public long getNextTriggeringMillis(Date now) { + return getNextTriggeringDate(now).getTime(); + } + + + + + + + + + public PeriodicityType computePeriodicityType(String datePattern) + { + RollingCalendar rollingCalendar = new RollingCalendar(GMT_TIMEZONE, Locale.getDefault()); + + + + Date epoch = new Date(0L); + + if (datePattern != null) { + for (PeriodicityType i : PeriodicityType.VALID_ORDERED_LIST) { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern); + simpleDateFormat.setTimeZone(GMT_TIMEZONE); + + + String r0 = simpleDateFormat.format(epoch); + rollingCalendar.setPeriodicityType(i); + + Date next = new Date(rollingCalendar.getNextTriggeringMillis(epoch)); + String r1 = simpleDateFormat.format(next); + + + if ((r0 != null) && (r1 != null) && (!r0.equals(r1))) { + return i; + } + } + } + + return PeriodicityType.ERRONEOUS; + } + + public void printPeriodicity(ContextAwareBase cab) { + switch (1.$SwitchMap$ch$qos$logback$core$rolling$helper$PeriodicityType[periodicityType.ordinal()]) { + case 1: + cab.addInfo("Roll-over every millisecond."); + break; + + case 2: + cab.addInfo("Roll-over every second."); + break; + + case 3: + cab.addInfo("Roll-over every minute."); + break; + + case 4: + cab.addInfo("Roll-over at the top of every hour."); + break; + + case 5: + cab.addInfo("Roll-over at midday and midnight."); + break; + + case 6: + cab.addInfo("Roll-over at midnight."); + break; + + case 7: + cab.addInfo("Rollover at the start of week."); + break; + + case 8: + cab.addInfo("Rollover at start of every month."); + break; + + default: + cab.addInfo("Unknown periodicity."); + } + } + + public long periodsElapsed(long start, long end) { + if (start > end) { + throw new IllegalArgumentException("Start cannot come before end"); + } + long diff = end - start; + switch (1.$SwitchMap$ch$qos$logback$core$rolling$helper$PeriodicityType[periodicityType.ordinal()]) + { + case 1: + return diff; + case 2: + return diff / 1000L; + case 3: + return diff / 60000L; + case 4: + return (int)diff / 3600000; + case 6: + return diff / 86400000L; + case 7: + return diff / 604800000L; + case 8: + return diffInMonths(start, end); + } + throw new IllegalStateException("Unknown periodicity type."); + } + + public static int diffInMonths(long startTime, long endTime) + { + if (startTime > endTime) + throw new IllegalArgumentException("startTime cannot be larger than endTime"); + Calendar startCal = Calendar.getInstance(); + startCal.setTimeInMillis(startTime); + Calendar endCal = Calendar.getInstance(); + endCal.setTimeInMillis(endTime); + int yearDiff = endCal.get(1) - startCal.get(1); + int monthDiff = endCal.get(2) - startCal.get(2); + return yearDiff * 12 + monthDiff; + } + + public Date getRelativeDate(Date now, int periods) { + setTime(now); + + switch (1.$SwitchMap$ch$qos$logback$core$rolling$helper$PeriodicityType[periodicityType.ordinal()]) { + case 1: + add(14, periods); + break; + + case 2: + set(14, 0); + add(13, periods); + break; + + case 3: + set(13, 0); + set(14, 0); + add(12, periods); + break; + + case 4: + set(12, 0); + set(13, 0); + set(14, 0); + add(11, periods); + break; + + case 6: + set(11, 0); + set(12, 0); + set(13, 0); + set(14, 0); + add(5, periods); + break; + + case 7: + set(7, getFirstDayOfWeek()); + set(11, 0); + set(12, 0); + set(13, 0); + set(14, 0); + add(3, periods); + break; + + case 8: + set(5, 1); + set(11, 0); + set(12, 0); + set(13, 0); + set(14, 0); + add(2, periods); + break; + case 5: + default: + throw new IllegalStateException("Unknown periodicity type."); + } + + return getTime(); + } + + public Date getNextTriggeringDate(Date now) { + return getRelativeDate(now, 1); + } +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/helper/SizeAndTimeBasedArchiveRemover.java b/src/minecraft/ch/qos/logback/core/rolling/helper/SizeAndTimeBasedArchiveRemover.java new file mode 100644 index 0000000..45cd132 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/helper/SizeAndTimeBasedArchiveRemover.java @@ -0,0 +1,54 @@ +package ch.qos.logback.core.rolling.helper; + +import java.io.File; +import java.util.Date; + + + + + + + + + + + + + +public class SizeAndTimeBasedArchiveRemover + extends DefaultArchiveRemover +{ + public SizeAndTimeBasedArchiveRemover(FileNamePattern fileNamePattern, RollingCalendar rc) + { + super(fileNamePattern, rc); + } + + public void cleanByPeriodOffset(Date now, int periodOffset) { + Date dateOfPeriodToClean = rc.getRelativeDate(now, periodOffset); + + String regex = fileNamePattern.toRegexForFixedDate(dateOfPeriodToClean); + String stemRegex = FileFilterUtil.afterLastSlash(regex); + File archive0 = new File(fileNamePattern.convertMultipleArguments(new Object[] { dateOfPeriodToClean, Integer.valueOf(0) })); + + + + archive0 = archive0.getAbsoluteFile(); + + File parentDir = archive0.getAbsoluteFile().getParentFile(); + File[] matchingFileArray = FileFilterUtil.filesInFolderMatchingStemRegex(parentDir, stemRegex); + + + for (File f : matchingFileArray) { + Date fileLastModified = rc.getRelativeDate(new Date(f.lastModified()), -1); + + if (fileLastModified.compareTo(dateOfPeriodToClean) <= 0) { + addInfo("deleting " + f); + f.delete(); + } + } + + if (parentClean) { + removeFolderIfEmpty(parentDir); + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/helper/TimeBasedArchiveRemover.java b/src/minecraft/ch/qos/logback/core/rolling/helper/TimeBasedArchiveRemover.java new file mode 100644 index 0000000..dbb0c7b --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/helper/TimeBasedArchiveRemover.java @@ -0,0 +1,48 @@ +package ch.qos.logback.core.rolling.helper; + +import java.io.File; +import java.util.Date; + + + + + + + + + + + + + +public class TimeBasedArchiveRemover + extends DefaultArchiveRemover +{ + public TimeBasedArchiveRemover(FileNamePattern fileNamePattern, RollingCalendar rc) + { + super(fileNamePattern, rc); + } + + protected void cleanByPeriodOffset(Date now, int periodOffset) { + Date date2delete = rc.getRelativeDate(now, periodOffset); + String filename = fileNamePattern.convert(date2delete); + File file2Delete = new File(filename); + if ((file2Delete.exists()) && (file2Delete.isFile())) { + Date fileLastModified = rc.getRelativeDate(new Date(file2Delete.lastModified()), -1); + + if (fileLastModified.compareTo(date2delete) <= 0) { + addInfo("deleting " + file2Delete); + file2Delete.delete(); + + if (parentClean) { + removeFolderIfEmpty(file2Delete.getParentFile()); + } + } + } + } + + public String toString() + { + return "c.q.l.core.rolling.helper.TimeBasedArchiveRemover"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/rolling/helper/TokenConverter.java b/src/minecraft/ch/qos/logback/core/rolling/helper/TokenConverter.java new file mode 100644 index 0000000..5fefab7 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/rolling/helper/TokenConverter.java @@ -0,0 +1,55 @@ +package ch.qos.logback.core.rolling.helper; + + + + + +public class TokenConverter +{ + static final int IDENTITY = 0; + + + + + static final int INTEGER = 1; + + + + + static final int DATE = 1; + + + + + int type; + + + + + TokenConverter next; + + + + + + protected TokenConverter(int t) + { + type = t; + } + + public TokenConverter getNext() { + return next; + } + + public void setNext(TokenConverter next) { + this.next = next; + } + + public int getType() { + return type; + } + + public void setType(int i) { + type = i; + } +} diff --git a/src/minecraft/ch/qos/logback/core/sift/AbstractAppenderFactoryUsingJoran.java b/src/minecraft/ch/qos/logback/core/sift/AbstractAppenderFactoryUsingJoran.java new file mode 100644 index 0000000..f0f58e7 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/sift/AbstractAppenderFactoryUsingJoran.java @@ -0,0 +1,58 @@ +package ch.qos.logback.core.sift; + +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.joran.event.SaxEvent; +import ch.qos.logback.core.joran.spi.JoranException; +import java.util.List; +import java.util.Map; + + + + + + + + + + + + + + + + + + +public abstract class AbstractAppenderFactoryUsingJoran + implements AppenderFactory +{ + final List eventList; + protected String key; + protected Map parentPropertyMap; + + protected AbstractAppenderFactoryUsingJoran(List eventList, String key, Map parentPropertyMap) + { + this.eventList = removeSiftElement(eventList); + this.key = key; + this.parentPropertyMap = parentPropertyMap; + } + + List removeSiftElement(List eventList) + { + return eventList.subList(1, eventList.size() - 1); + } + + public abstract SiftingJoranConfiguratorBase getSiftingJoranConfigurator(String paramString); + + public Appender buildAppender(Context context, String discriminatingValue) throws JoranException { + SiftingJoranConfiguratorBase sjc = getSiftingJoranConfigurator(discriminatingValue); + sjc.setContext(context); + sjc.doConfigure(eventList); + return sjc.getAppender(); + } + + public List getEventList() { + return eventList; + } +} diff --git a/src/minecraft/ch/qos/logback/core/sift/AbstractDiscriminator.java b/src/minecraft/ch/qos/logback/core/sift/AbstractDiscriminator.java new file mode 100644 index 0000000..3f885bf --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/sift/AbstractDiscriminator.java @@ -0,0 +1,39 @@ +package ch.qos.logback.core.sift; + +import ch.qos.logback.core.spi.ContextAwareBase; + + + + + + + + + + + + + + + +public abstract class AbstractDiscriminator + extends ContextAwareBase + implements Discriminator +{ + protected boolean started; + + public AbstractDiscriminator() {} + + public void start() + { + started = true; + } + + public void stop() { + started = false; + } + + public boolean isStarted() { + return started; + } +} diff --git a/src/minecraft/ch/qos/logback/core/sift/AppenderFactory.java b/src/minecraft/ch/qos/logback/core/sift/AppenderFactory.java new file mode 100644 index 0000000..ef69d17 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/sift/AppenderFactory.java @@ -0,0 +1,11 @@ +package ch.qos.logback.core.sift; + +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.joran.spi.JoranException; + +public abstract interface AppenderFactory +{ + public abstract Appender buildAppender(Context paramContext, String paramString) + throws JoranException; +} diff --git a/src/minecraft/ch/qos/logback/core/sift/AppenderTracker.java b/src/minecraft/ch/qos/logback/core/sift/AppenderTracker.java new file mode 100644 index 0000000..428a0d8 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/sift/AppenderTracker.java @@ -0,0 +1,83 @@ +package ch.qos.logback.core.sift; + +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.helpers.NOPAppender; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.spi.AbstractComponentTracker; +import ch.qos.logback.core.spi.ContextAwareImpl; + + + + + + + + + + + + + + + + + + + + + + +public class AppenderTracker + extends AbstractComponentTracker> +{ + int nopaWarningCount = 0; + + final Context context; + final AppenderFactory appenderFactory; + final ContextAwareImpl contextAware; + + public AppenderTracker(Context context, AppenderFactory appenderFactory) + { + this.context = context; + this.appenderFactory = appenderFactory; + contextAware = new ContextAwareImpl(context, this); + } + + + protected void processPriorToRemoval(Appender component) + { + component.stop(); + } + + protected Appender buildComponent(String key) + { + Appender appender = null; + try { + appender = appenderFactory.buildAppender(context, key); + } catch (JoranException je) { + contextAware.addError("Error while building appender with discriminating value [" + key + "]"); + } + if (appender == null) { + appender = buildNOPAppender(key); + } + + return appender; + } + + private NOPAppender buildNOPAppender(String key) { + if (nopaWarningCount < 4) { + nopaWarningCount += 1; + contextAware.addError("Building NOPAppender for discriminating value [" + key + "]"); + } + NOPAppender nopa = new NOPAppender(); + nopa.setContext(context); + nopa.start(); + return nopa; + } + + protected boolean isComponentStale(Appender appender) + { + return !appender.isStarted(); + } +} diff --git a/src/minecraft/ch/qos/logback/core/sift/DefaultDiscriminator.java b/src/minecraft/ch/qos/logback/core/sift/DefaultDiscriminator.java new file mode 100644 index 0000000..0104bfb --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/sift/DefaultDiscriminator.java @@ -0,0 +1,31 @@ +package ch.qos.logback.core.sift; + + + + + + +public class DefaultDiscriminator + extends AbstractDiscriminator +{ + public static final String DEFAULT = "default"; + + + + + + public DefaultDiscriminator() {} + + + + + + public String getDiscriminatingValue(E e) + { + return "default"; + } + + public String getKey() { + return "default"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/sift/Discriminator.java b/src/minecraft/ch/qos/logback/core/sift/Discriminator.java new file mode 100644 index 0000000..d7c45b8 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/sift/Discriminator.java @@ -0,0 +1,11 @@ +package ch.qos.logback.core.sift; + +import ch.qos.logback.core.spi.LifeCycle; + +public abstract interface Discriminator + extends LifeCycle +{ + public abstract String getDiscriminatingValue(E paramE); + + public abstract String getKey(); +} diff --git a/src/minecraft/ch/qos/logback/core/sift/SiftingAppenderBase.java b/src/minecraft/ch/qos/logback/core/sift/SiftingAppenderBase.java new file mode 100644 index 0000000..b52053e --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/sift/SiftingAppenderBase.java @@ -0,0 +1,144 @@ +package ch.qos.logback.core.sift; + +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.AppenderBase; +import ch.qos.logback.core.util.Duration; + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class SiftingAppenderBase + extends AppenderBase +{ + protected AppenderTracker appenderTracker; + AppenderFactory appenderFactory; + Duration timeout = new Duration(1800000L); + int maxAppenderCount = Integer.MAX_VALUE; + Discriminator discriminator; + + public SiftingAppenderBase() {} + + public Duration getTimeout() { return timeout; } + + public void setTimeout(Duration timeout) + { + this.timeout = timeout; + } + + public int getMaxAppenderCount() { + return maxAppenderCount; + } + + public void setMaxAppenderCount(int maxAppenderCount) { + this.maxAppenderCount = maxAppenderCount; + } + + + + + public void setAppenderFactory(AppenderFactory appenderFactory) + { + this.appenderFactory = appenderFactory; + } + + public void start() + { + int errors = 0; + if (discriminator == null) { + addError("Missing discriminator. Aborting"); + errors++; + } + if (!discriminator.isStarted()) { + addError("Discriminator has not started successfully. Aborting"); + errors++; + } + if (appenderFactory == null) { + addError("AppenderFactory has not been set. Aborting"); + errors++; + } else { + appenderTracker = new AppenderTracker(context, appenderFactory); + appenderTracker.setMaxComponents(maxAppenderCount); + appenderTracker.setTimeout(timeout.getMilliseconds()); + } + if (errors == 0) { + super.start(); + } + } + + public void stop() + { + for (Appender appender : appenderTracker.allComponents()) { + appender.stop(); + } + } + + protected abstract long getTimestamp(E paramE); + + protected void append(E event) + { + if (!isStarted()) { + return; + } + String discriminatingValue = discriminator.getDiscriminatingValue(event); + long timestamp = getTimestamp(event); + + Appender appender = (Appender)appenderTracker.getOrCreate(discriminatingValue, timestamp); + + if (eventMarksEndOfLife(event)) { + appenderTracker.endOfLife(discriminatingValue); + } + appenderTracker.removeStaleComponents(timestamp); + appender.doAppend(event); + } + + protected abstract boolean eventMarksEndOfLife(E paramE); + + public Discriminator getDiscriminator() { + return discriminator; + } + + public void setDiscriminator(Discriminator discriminator) { + this.discriminator = discriminator; + } + + + + + + + + + + + public AppenderTracker getAppenderTracker() + { + return appenderTracker; + } + + public String getDiscriminatorKey() { + if (discriminator != null) { + return discriminator.getKey(); + } + return null; + } +} diff --git a/src/minecraft/ch/qos/logback/core/sift/SiftingJoranConfiguratorBase.java b/src/minecraft/ch/qos/logback/core/sift/SiftingJoranConfiguratorBase.java new file mode 100644 index 0000000..82273fe --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/sift/SiftingJoranConfiguratorBase.java @@ -0,0 +1,92 @@ +package ch.qos.logback.core.sift; + +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.joran.GenericConfigurator; +import ch.qos.logback.core.joran.action.DefinePropertyAction; +import ch.qos.logback.core.joran.action.NestedBasicPropertyIA; +import ch.qos.logback.core.joran.action.NestedComplexPropertyIA; +import ch.qos.logback.core.joran.action.PropertyAction; +import ch.qos.logback.core.joran.action.TimestampAction; +import ch.qos.logback.core.joran.event.SaxEvent; +import ch.qos.logback.core.joran.spi.ElementSelector; +import ch.qos.logback.core.joran.spi.Interpreter; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.joran.spi.RuleStore; +import java.util.List; +import java.util.Map; + + + + + + + + + + + +public abstract class SiftingJoranConfiguratorBase + extends GenericConfigurator +{ + protected final String key; + protected final String value; + protected final Map parentPropertyMap; + static final String ONE_AND_ONLY_ONE_URL = "http://logback.qos.ch/codes.html#1andOnly1"; + + protected SiftingJoranConfiguratorBase(String key, String value, Map parentPropertyMap) + { + this.key = key; + this.value = value; + this.parentPropertyMap = parentPropertyMap; + } + + + + + protected void addImplicitRules(Interpreter interpreter) + { + NestedComplexPropertyIA nestedComplexIA = new NestedComplexPropertyIA(); + nestedComplexIA.setContext(context); + interpreter.addImplicitAction(nestedComplexIA); + + NestedBasicPropertyIA nestedSimpleIA = new NestedBasicPropertyIA(); + nestedSimpleIA.setContext(context); + interpreter.addImplicitAction(nestedSimpleIA); + } + + protected void addInstanceRules(RuleStore rs) + { + rs.addRule(new ElementSelector("configuration/property"), new PropertyAction()); + rs.addRule(new ElementSelector("configuration/timestamp"), new TimestampAction()); + rs.addRule(new ElementSelector("configuration/define"), new DefinePropertyAction()); + } + + public abstract Appender getAppender(); + + int errorEmmissionCount = 0; + + protected void oneAndOnlyOneCheck(Map appenderMap) { + String errMsg = null; + if (appenderMap.size() == 0) { + errorEmmissionCount += 1; + errMsg = "No nested appenders found within the element in SiftingAppender."; + } else if (appenderMap.size() > 1) { + errorEmmissionCount += 1; + errMsg = "Only and only one appender can be nested the element in SiftingAppender. See also http://logback.qos.ch/codes.html#1andOnly1"; + } + + + if ((errMsg != null) && (errorEmmissionCount < 4)) { + addError(errMsg); + } + } + + public void doConfigure(List eventList) throws JoranException { + super.doConfigure(eventList); + } + + public String toString() + { + return getClass().getName() + "{" + key + "=" + value + '}'; + } +} diff --git a/src/minecraft/ch/qos/logback/core/spi/AbstractComponentTracker.java b/src/minecraft/ch/qos/logback/core/spi/AbstractComponentTracker.java new file mode 100644 index 0000000..942de9b --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/spi/AbstractComponentTracker.java @@ -0,0 +1,458 @@ +package ch.qos.logback.core.spi; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class AbstractComponentTracker + implements ComponentTracker +{ + private static final boolean ACCESS_ORDERED = true; + public static final long LINGERING_TIMEOUT = 10000L; + public static final long WAIT_BETWEEN_SUCCESSIVE_REMOVAL_ITERATIONS = 1000L; + protected int maxComponents; + protected long timeout; + LinkedHashMap> liveMap; + LinkedHashMap> lingerersMap; + long lastCheck; + private RemovalPredicator byExcedent; + private RemovalPredicator byTimeout; + private RemovalPredicator byLingering; + + public int getComponentCount() + { + return liveMap.size() + lingerersMap.size(); + } + + + + + + + private Entry getFromEitherMap(String key) + { + Entry entry = (Entry)liveMap.get(key); + if (entry != null) { + return entry; + } + return (Entry)lingerersMap.get(key); + } + + + + + + + + + + + public synchronized C find(String key) + { + Entry entry = getFromEitherMap(key); + if (entry == null) return null; + return component; + } + + + + + + + + + + public synchronized C getOrCreate(String key, long timestamp) + { + Entry entry = getFromEitherMap(key); + if (entry == null) { + C c = buildComponent(key); + entry = new Entry(key, c, timestamp); + + liveMap.put(key, entry); + } else { + entry.setTimestamp(timestamp); + } + return component; + } + + + + + + public void endOfLife(String key) + { + Entry entry = (Entry)liveMap.remove(key); + if (entry == null) + return; + lingerersMap.put(key, entry); + } + + + + + + + public synchronized void removeStaleComponents(long now) + { + if (isTooSoonForRemovalIteration(now)) return; + removeExcedentComponents(); + removeStaleComponentsFromMainMap(now); + removeStaleComponentsFromLingerersMap(now); + } + + private void removeExcedentComponents() { + genericStaleComponentRemover(liveMap, 0L, byExcedent); + } + + private void removeStaleComponentsFromMainMap(long now) { + genericStaleComponentRemover(liveMap, now, byTimeout); + } + + private void removeStaleComponentsFromLingerersMap(long now) { + genericStaleComponentRemover(lingerersMap, now, byLingering); + } + + private void genericStaleComponentRemover(LinkedHashMap> map, long now, RemovalPredicator removalPredicator) + { + Iterator>> iter = map.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry> mapEntry = (Map.Entry)iter.next(); + Entry entry = (Entry)mapEntry.getValue(); + if (!removalPredicator.isSlatedForRemoval(entry, now)) break; + iter.remove(); + C c = component; + processPriorToRemoval(c); + } + } + + public AbstractComponentTracker() + { + maxComponents = Integer.MAX_VALUE; + timeout = 1800000L; + + + liveMap = new LinkedHashMap(32, 0.75F, true); + + + lingerersMap = new LinkedHashMap(16, 0.75F, true); + lastCheck = 0L; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + byExcedent = new RemovalPredicator() { + public boolean isSlatedForRemoval(AbstractComponentTracker.Entry entry, long timestamp) { + return liveMap.size() > maxComponents; + } + + }; + byTimeout = new RemovalPredicator() { + public boolean isSlatedForRemoval(AbstractComponentTracker.Entry entry, long timestamp) { + return AbstractComponentTracker.this.isEntryStale(entry, timestamp); + } + }; + byLingering = new RemovalPredicator() + { + public boolean isSlatedForRemoval(AbstractComponentTracker.Entry entry, long timestamp) { return AbstractComponentTracker.this.isEntryDoneLingering(entry, timestamp); } + }; + } + + private boolean isTooSoonForRemovalIteration(long now) { + if (lastCheck + 1000L > now) { + return true; + } + lastCheck = now; + return false; + } + + + private boolean isEntryStale(Entry entry, long now) + { + C c = component; + if (isComponentStale(c)) { + return true; + } + return timestamp + timeout < now; + } + + private boolean isEntryDoneLingering(Entry entry, long now) { + return timestamp + 10000L < now; + } + + public Set allKeys() { + HashSet allKeys = new HashSet(liveMap.keySet()); + allKeys.addAll(lingerersMap.keySet()); + return allKeys; + } + + public Collection allComponents() { + List allComponents = new ArrayList(); + for (Entry e : liveMap.values()) + allComponents.add(component); + for (Entry e : lingerersMap.values()) { + allComponents.add(component); + } + return allComponents; + } + + public long getTimeout() { + return timeout; + } + + public void setTimeout(long timeout) { + this.timeout = timeout; + } + + public int getMaxComponents() { + return maxComponents; + } + + + public void setMaxComponents(int maxComponents) { this.maxComponents = maxComponents; } + + protected abstract void processPriorToRemoval(C paramC); + + protected abstract C buildComponent(String paramString); + + protected abstract boolean isComponentStale(C paramC); + + private static class Entry { + String key; + C component; + long timestamp; + + Entry(String k, C c, long timestamp) { + key = k; + component = c; + this.timestamp = timestamp; + } + + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + public int hashCode() + { + return key.hashCode(); + } + + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Entry other = (Entry)obj; + if (key == null) { + if (key != null) + return false; + } else if (!key.equals(key)) + return false; + if (component == null) { + if (component != null) + return false; + } else if (!component.equals(component)) + return false; + return true; + } + + public String toString() + { + return "(" + key + ", " + component + ")"; + } + } + + private static abstract interface RemovalPredicator + { + public abstract boolean isSlatedForRemoval(AbstractComponentTracker.Entry paramEntry, long paramLong); + } +} diff --git a/src/minecraft/ch/qos/logback/core/spi/AppenderAttachable.java b/src/minecraft/ch/qos/logback/core/spi/AppenderAttachable.java new file mode 100644 index 0000000..314d596 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/spi/AppenderAttachable.java @@ -0,0 +1,21 @@ +package ch.qos.logback.core.spi; + +import ch.qos.logback.core.Appender; +import java.util.Iterator; + +public abstract interface AppenderAttachable +{ + public abstract void addAppender(Appender paramAppender); + + public abstract Iterator> iteratorForAppenders(); + + public abstract Appender getAppender(String paramString); + + public abstract boolean isAttached(Appender paramAppender); + + public abstract void detachAndStopAllAppenders(); + + public abstract boolean detachAppender(Appender paramAppender); + + public abstract boolean detachAppender(String paramString); +} diff --git a/src/minecraft/ch/qos/logback/core/spi/AppenderAttachableImpl.java b/src/minecraft/ch/qos/logback/core/spi/AppenderAttachableImpl.java new file mode 100644 index 0000000..45b9631 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/spi/AppenderAttachableImpl.java @@ -0,0 +1,141 @@ +package ch.qos.logback.core.spi; + +import ch.qos.logback.core.Appender; +import java.util.Iterator; +import java.util.concurrent.CopyOnWriteArrayList; + + + + + + + + + + + + + + + + + + + + +public class AppenderAttachableImpl + implements AppenderAttachable +{ + private final CopyOnWriteArrayList> appenderList = new CopyOnWriteArrayList(); + + + public AppenderAttachableImpl() {} + + public void addAppender(Appender newAppender) + { + if (newAppender == null) { + throw new IllegalArgumentException("Null argument disallowed"); + } + appenderList.addIfAbsent(newAppender); + } + + + + public int appendLoopOnAppenders(E e) + { + int size = 0; + for (Appender appender : appenderList) { + appender.doAppend(e); + size++; + } + return size; + } + + + + + + + public Iterator> iteratorForAppenders() + { + return appenderList.iterator(); + } + + + + + + + public Appender getAppender(String name) + { + if (name == null) { + return null; + } + Appender found = null; + for (Appender appender : appenderList) { + if (name.equals(appender.getName())) { + return appender; + } + } + return null; + } + + + + + + + public boolean isAttached(Appender appender) + { + if (appender == null) { + return false; + } + for (Appender a : appenderList) { + if (a == appender) return true; + } + return false; + } + + + + public void detachAndStopAllAppenders() + { + for (Appender a : appenderList) { + a.stop(); + } + appenderList.clear(); + } + + static final long START = ; + + + + + public boolean detachAppender(Appender appender) + { + if (appender == null) { + return false; + } + + boolean result = appenderList.remove(appender); + return result; + } + + + + + public boolean detachAppender(String name) + { + if (name == null) { + return false; + } + boolean removed = false; + for (Appender a : appenderList) { + if (name.equals(a.getName())) { + removed = appenderList.remove(a); + break; + } + } + return removed; + } +} diff --git a/src/minecraft/ch/qos/logback/core/spi/ComponentTracker.java b/src/minecraft/ch/qos/logback/core/spi/ComponentTracker.java new file mode 100644 index 0000000..3e000cd --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/spi/ComponentTracker.java @@ -0,0 +1,24 @@ +package ch.qos.logback.core.spi; + +import java.util.Collection; +import java.util.Set; + +public abstract interface ComponentTracker +{ + public static final int DEFAULT_TIMEOUT = 1800000; + public static final int DEFAULT_MAX_COMPONENTS = Integer.MAX_VALUE; + + public abstract int getComponentCount(); + + public abstract C find(String paramString); + + public abstract C getOrCreate(String paramString, long paramLong); + + public abstract void removeStaleComponents(long paramLong); + + public abstract void endOfLife(String paramString); + + public abstract Collection allComponents(); + + public abstract Set allKeys(); +} diff --git a/src/minecraft/ch/qos/logback/core/spi/ContextAware.java b/src/minecraft/ch/qos/logback/core/spi/ContextAware.java new file mode 100644 index 0000000..80ef560 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/spi/ContextAware.java @@ -0,0 +1,25 @@ +package ch.qos.logback.core.spi; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.status.Status; + +public abstract interface ContextAware +{ + public abstract void setContext(Context paramContext); + + public abstract Context getContext(); + + public abstract void addStatus(Status paramStatus); + + public abstract void addInfo(String paramString); + + public abstract void addInfo(String paramString, Throwable paramThrowable); + + public abstract void addWarn(String paramString); + + public abstract void addWarn(String paramString, Throwable paramThrowable); + + public abstract void addError(String paramString); + + public abstract void addError(String paramString, Throwable paramThrowable); +} diff --git a/src/minecraft/ch/qos/logback/core/spi/ContextAwareBase.java b/src/minecraft/ch/qos/logback/core/spi/ContextAwareBase.java new file mode 100644 index 0000000..e16bafa --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/spi/ContextAwareBase.java @@ -0,0 +1,106 @@ +package ch.qos.logback.core.spi; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.status.ErrorStatus; +import ch.qos.logback.core.status.InfoStatus; +import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.status.WarnStatus; +import java.io.PrintStream; + + + + + + + + + + + + + + + + + +public class ContextAwareBase + implements ContextAware +{ + private int noContextWarning = 0; + protected Context context; + final Object declaredOrigin; + + public ContextAwareBase() { + declaredOrigin = this; + } + + public ContextAwareBase(ContextAware declaredOrigin) { this.declaredOrigin = declaredOrigin; } + + public void setContext(Context context) + { + if (this.context == null) { + this.context = context; + } else if (this.context != context) { + throw new IllegalStateException("Context has been already set"); + } + } + + public Context getContext() { + return context; + } + + public StatusManager getStatusManager() { + if (context == null) { + return null; + } + return context.getStatusManager(); + } + + + + + + + protected Object getDeclaredOrigin() + { + return declaredOrigin; + } + + public void addStatus(Status status) { + if (context == null) { + if (noContextWarning++ == 0) { + System.out.println("LOGBACK: No context given for " + this); + } + return; + } + StatusManager sm = context.getStatusManager(); + if (sm != null) { + sm.add(status); + } + } + + public void addInfo(String msg) { + addStatus(new InfoStatus(msg, getDeclaredOrigin())); + } + + public void addInfo(String msg, Throwable ex) { + addStatus(new InfoStatus(msg, getDeclaredOrigin(), ex)); + } + + public void addWarn(String msg) { + addStatus(new WarnStatus(msg, getDeclaredOrigin())); + } + + public void addWarn(String msg, Throwable ex) { + addStatus(new WarnStatus(msg, getDeclaredOrigin(), ex)); + } + + public void addError(String msg) { + addStatus(new ErrorStatus(msg, getDeclaredOrigin())); + } + + public void addError(String msg, Throwable ex) { + addStatus(new ErrorStatus(msg, getDeclaredOrigin(), ex)); + } +} diff --git a/src/minecraft/ch/qos/logback/core/spi/ContextAwareImpl.java b/src/minecraft/ch/qos/logback/core/spi/ContextAwareImpl.java new file mode 100644 index 0000000..2e8f477 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/spi/ContextAwareImpl.java @@ -0,0 +1,101 @@ +package ch.qos.logback.core.spi; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.status.ErrorStatus; +import ch.qos.logback.core.status.InfoStatus; +import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.status.WarnStatus; +import java.io.PrintStream; + + + + + + + + + + + + + + + + + + + +public class ContextAwareImpl + implements ContextAware +{ + private int noContextWarning = 0; + protected Context context; + final Object origin; + + public ContextAwareImpl(Context context, Object origin) { + this.context = context; + this.origin = origin; + } + + protected Object getOrigin() + { + return origin; + } + + public void setContext(Context context) { + if (this.context == null) { + this.context = context; + } else if (this.context != context) { + throw new IllegalStateException("Context has been already set"); + } + } + + public Context getContext() { + return context; + } + + public StatusManager getStatusManager() { + if (context == null) { + return null; + } + return context.getStatusManager(); + } + + public void addStatus(Status status) { + if (context == null) { + if (noContextWarning++ == 0) { + System.out.println("LOGBACK: No context given for " + this); + } + return; + } + StatusManager sm = context.getStatusManager(); + if (sm != null) { + sm.add(status); + } + } + + public void addInfo(String msg) { + addStatus(new InfoStatus(msg, getOrigin())); + } + + public void addInfo(String msg, Throwable ex) { + addStatus(new InfoStatus(msg, getOrigin(), ex)); + } + + public void addWarn(String msg) { + addStatus(new WarnStatus(msg, getOrigin())); + } + + public void addWarn(String msg, Throwable ex) { + addStatus(new WarnStatus(msg, getOrigin(), ex)); + } + + public void addError(String msg) { + addStatus(new ErrorStatus(msg, getOrigin())); + } + + public void addError(String msg, Throwable ex) { + addStatus(new ErrorStatus(msg, getOrigin(), ex)); + } +} diff --git a/src/minecraft/ch/qos/logback/core/spi/CyclicBufferTracker.java b/src/minecraft/ch/qos/logback/core/spi/CyclicBufferTracker.java new file mode 100644 index 0000000..df4eb3a --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/spi/CyclicBufferTracker.java @@ -0,0 +1,69 @@ +package ch.qos.logback.core.spi; + +import ch.qos.logback.core.helpers.CyclicBuffer; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; + + + + + + + + + + + + + + + + + + +public class CyclicBufferTracker + extends AbstractComponentTracker> +{ + static final int DEFAULT_NUMBER_OF_BUFFERS = 64; + static final int DEFAULT_BUFFER_SIZE = 256; + int bufferSize = 256; + + + public CyclicBufferTracker() + { + setMaxComponents(64); + } + + public int getBufferSize() { + return bufferSize; + } + + public void setBufferSize(int bufferSize) { + this.bufferSize = bufferSize; + } + + protected void processPriorToRemoval(CyclicBuffer component) + { + component.clear(); + } + + protected CyclicBuffer buildComponent(String key) + { + return new CyclicBuffer(bufferSize); + } + + protected boolean isComponentStale(CyclicBuffer eCyclicBuffer) + { + return false; + } + + List liveKeysAsOrderedList() + { + return new ArrayList(liveMap.keySet()); + } + + List lingererKeysAsOrderedList() { + return new ArrayList(lingerersMap.keySet()); + } +} diff --git a/src/minecraft/ch/qos/logback/core/spi/DeferredProcessingAware.java b/src/minecraft/ch/qos/logback/core/spi/DeferredProcessingAware.java new file mode 100644 index 0000000..6c07311 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/spi/DeferredProcessingAware.java @@ -0,0 +1,6 @@ +package ch.qos.logback.core.spi; + +public abstract interface DeferredProcessingAware +{ + public abstract void prepareForDeferredProcessing(); +} diff --git a/src/minecraft/ch/qos/logback/core/spi/FilterAttachable.java b/src/minecraft/ch/qos/logback/core/spi/FilterAttachable.java new file mode 100644 index 0000000..02468ad --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/spi/FilterAttachable.java @@ -0,0 +1,15 @@ +package ch.qos.logback.core.spi; + +import ch.qos.logback.core.filter.Filter; +import java.util.List; + +public abstract interface FilterAttachable +{ + public abstract void addFilter(Filter paramFilter); + + public abstract void clearAllFilters(); + + public abstract List> getCopyOfAttachedFiltersList(); + + public abstract FilterReply getFilterChainDecision(E paramE); +} diff --git a/src/minecraft/ch/qos/logback/core/spi/FilterAttachableImpl.java b/src/minecraft/ch/qos/logback/core/spi/FilterAttachableImpl.java new file mode 100644 index 0000000..ab171e8 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/spi/FilterAttachableImpl.java @@ -0,0 +1,63 @@ +package ch.qos.logback.core.spi; + +import ch.qos.logback.core.filter.Filter; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + + + + + + + + + + + + + + + + + + + +public final class FilterAttachableImpl + implements FilterAttachable +{ + CopyOnWriteArrayList> filterList = new CopyOnWriteArrayList(); + + public FilterAttachableImpl() {} + + public void addFilter(Filter newFilter) + { + filterList.add(newFilter); + } + + + + public void clearAllFilters() + { + filterList.clear(); + } + + + + + + public FilterReply getFilterChainDecision(E event) + { + for (Filter f : filterList) { + FilterReply r = f.decide(event); + if ((r == FilterReply.DENY) || (r == FilterReply.ACCEPT)) { + return r; + } + } + return FilterReply.NEUTRAL; + } + + public List> getCopyOfAttachedFiltersList() { + return new ArrayList(filterList); + } +} diff --git a/src/minecraft/ch/qos/logback/core/spi/FilterReply.java b/src/minecraft/ch/qos/logback/core/spi/FilterReply.java new file mode 100644 index 0000000..df8152e --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/spi/FilterReply.java @@ -0,0 +1,8 @@ +package ch.qos.logback.core.spi; + +public enum FilterReply +{ + DENY, NEUTRAL, ACCEPT; + + private FilterReply() {} +} diff --git a/src/minecraft/ch/qos/logback/core/spi/LifeCycle.java b/src/minecraft/ch/qos/logback/core/spi/LifeCycle.java new file mode 100644 index 0000000..a1ac93e --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/spi/LifeCycle.java @@ -0,0 +1,10 @@ +package ch.qos.logback.core.spi; + +public abstract interface LifeCycle +{ + public abstract void start(); + + public abstract void stop(); + + public abstract boolean isStarted(); +} diff --git a/src/minecraft/ch/qos/logback/core/spi/LogbackLock.java b/src/minecraft/ch/qos/logback/core/spi/LogbackLock.java new file mode 100644 index 0000000..2ee7990 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/spi/LogbackLock.java @@ -0,0 +1,6 @@ +package ch.qos.logback.core.spi; + +public class LogbackLock +{ + public LogbackLock() {} +} diff --git a/src/minecraft/ch/qos/logback/core/spi/PreSerializationTransformer.java b/src/minecraft/ch/qos/logback/core/spi/PreSerializationTransformer.java new file mode 100644 index 0000000..1c93797 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/spi/PreSerializationTransformer.java @@ -0,0 +1,8 @@ +package ch.qos.logback.core.spi; + +import java.io.Serializable; + +public abstract interface PreSerializationTransformer +{ + public abstract Serializable transform(E paramE); +} diff --git a/src/minecraft/ch/qos/logback/core/spi/PropertyContainer.java b/src/minecraft/ch/qos/logback/core/spi/PropertyContainer.java new file mode 100644 index 0000000..df57561 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/spi/PropertyContainer.java @@ -0,0 +1,10 @@ +package ch.qos.logback.core.spi; + +import java.util.Map; + +public abstract interface PropertyContainer +{ + public abstract String getProperty(String paramString); + + public abstract Map getCopyOfPropertyMap(); +} diff --git a/src/minecraft/ch/qos/logback/core/spi/PropertyDefiner.java b/src/minecraft/ch/qos/logback/core/spi/PropertyDefiner.java new file mode 100644 index 0000000..1663f06 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/spi/PropertyDefiner.java @@ -0,0 +1,7 @@ +package ch.qos.logback.core.spi; + +public abstract interface PropertyDefiner + extends ContextAware +{ + public abstract String getPropertyValue(); +} diff --git a/src/minecraft/ch/qos/logback/core/spi/ScanException.java b/src/minecraft/ch/qos/logback/core/spi/ScanException.java new file mode 100644 index 0000000..f6671bc --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/spi/ScanException.java @@ -0,0 +1,34 @@ +package ch.qos.logback.core.spi; + + + + + +public class ScanException + extends Exception +{ + private static final long serialVersionUID = -3132040414328475658L; + + + + + Throwable cause; + + + + + + public ScanException(String msg) + { + super(msg); + } + + public ScanException(String msg, Throwable rootCause) { + super(msg); + cause = rootCause; + } + + public Throwable getCause() { + return cause; + } +} diff --git a/src/minecraft/ch/qos/logback/core/status/ErrorStatus.java b/src/minecraft/ch/qos/logback/core/status/ErrorStatus.java new file mode 100644 index 0000000..d108962 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/status/ErrorStatus.java @@ -0,0 +1,27 @@ +package ch.qos.logback.core.status; + + + + + + + + + + + + + + +public class ErrorStatus + extends StatusBase +{ + public ErrorStatus(String msg, Object origin) + { + super(2, msg, origin); + } + + public ErrorStatus(String msg, Object origin, Throwable t) { + super(2, msg, origin, t); + } +} diff --git a/src/minecraft/ch/qos/logback/core/status/InfoStatus.java b/src/minecraft/ch/qos/logback/core/status/InfoStatus.java new file mode 100644 index 0000000..48e1916 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/status/InfoStatus.java @@ -0,0 +1,26 @@ +package ch.qos.logback.core.status; + + + + + + + + + + + + + +public class InfoStatus + extends StatusBase +{ + public InfoStatus(String msg, Object origin) + { + super(0, msg, origin); + } + + public InfoStatus(String msg, Object origin, Throwable t) { + super(0, msg, origin, t); + } +} diff --git a/src/minecraft/ch/qos/logback/core/status/NopStatusListener.java b/src/minecraft/ch/qos/logback/core/status/NopStatusListener.java new file mode 100644 index 0000000..e216bd4 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/status/NopStatusListener.java @@ -0,0 +1,9 @@ +package ch.qos.logback.core.status; + +public class NopStatusListener + implements StatusListener +{ + public NopStatusListener() {} + + public void addStatusEvent(Status status) {} +} diff --git a/src/minecraft/ch/qos/logback/core/status/OnConsoleStatusListener.java b/src/minecraft/ch/qos/logback/core/status/OnConsoleStatusListener.java new file mode 100644 index 0000000..859e279 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/status/OnConsoleStatusListener.java @@ -0,0 +1,45 @@ +package ch.qos.logback.core.status; + +import ch.qos.logback.core.Context; +import java.io.PrintStream; + + + + + + + + + + + + + + + + + +public class OnConsoleStatusListener + extends OnPrintStreamStatusListenerBase +{ + public OnConsoleStatusListener() {} + + protected PrintStream getPrintStream() + { + return System.out; + } + + + + + + + + public static void addNewInstanceToContext(Context context) + { + OnConsoleStatusListener onConsoleStatusListener = new OnConsoleStatusListener(); + onConsoleStatusListener.setContext(context); + onConsoleStatusListener.start(); + context.getStatusManager().add(onConsoleStatusListener); + } +} diff --git a/src/minecraft/ch/qos/logback/core/status/OnErrorConsoleStatusListener.java b/src/minecraft/ch/qos/logback/core/status/OnErrorConsoleStatusListener.java new file mode 100644 index 0000000..e56e7c3 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/status/OnErrorConsoleStatusListener.java @@ -0,0 +1,30 @@ +package ch.qos.logback.core.status; + +import java.io.PrintStream; + + + + + + + + + + + + + + + + + +public class OnErrorConsoleStatusListener + extends OnPrintStreamStatusListenerBase +{ + public OnErrorConsoleStatusListener() {} + + protected PrintStream getPrintStream() + { + return System.err; + } +} diff --git a/src/minecraft/ch/qos/logback/core/status/OnPrintStreamStatusListenerBase.java b/src/minecraft/ch/qos/logback/core/status/OnPrintStreamStatusListenerBase.java new file mode 100644 index 0000000..1bf889b --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/status/OnPrintStreamStatusListenerBase.java @@ -0,0 +1,92 @@ +package ch.qos.logback.core.status; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.spi.LifeCycle; +import ch.qos.logback.core.util.StatusPrinter; +import java.io.PrintStream; +import java.util.List; + + + + + + + + + + + + + + + + +abstract class OnPrintStreamStatusListenerBase + extends ContextAwareBase + implements StatusListener, LifeCycle +{ + boolean isStarted = false; + + static final long DEFAULT_RETROSPECTIVE = 300L; + long retrospective = 300L; + + + OnPrintStreamStatusListenerBase() {} + + + protected abstract PrintStream getPrintStream(); + + private void print(Status status) + { + StringBuilder sb = new StringBuilder(); + StatusPrinter.buildStr(sb, "", status); + getPrintStream().print(sb); + } + + public void addStatusEvent(Status status) { + if (!isStarted) + return; + print(status); + } + + + + private void retrospectivePrint() + { + if (context == null) + return; + long now = System.currentTimeMillis(); + StatusManager sm = context.getStatusManager(); + List statusList = sm.getCopyOfStatusList(); + for (Status status : statusList) { + long timestamp = status.getDate().longValue(); + if (now - timestamp < retrospective) { + print(status); + } + } + } + + public void start() { + isStarted = true; + if (retrospective > 0L) { + retrospectivePrint(); + } + } + + public void setRetrospective(long retrospective) { + this.retrospective = retrospective; + } + + public long getRetrospective() { + return retrospective; + } + + public void stop() { + isStarted = false; + } + + public boolean isStarted() { + return isStarted; + } +} diff --git a/src/minecraft/ch/qos/logback/core/status/Status.java b/src/minecraft/ch/qos/logback/core/status/Status.java new file mode 100644 index 0000000..b2db49c --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/status/Status.java @@ -0,0 +1,30 @@ +package ch.qos.logback.core.status; + +import java.util.Iterator; + +public abstract interface Status +{ + public static final int INFO = 0; + public static final int WARN = 1; + public static final int ERROR = 2; + + public abstract int getLevel(); + + public abstract int getEffectiveLevel(); + + public abstract Object getOrigin(); + + public abstract String getMessage(); + + public abstract Throwable getThrowable(); + + public abstract Long getDate(); + + public abstract boolean hasChildren(); + + public abstract void add(Status paramStatus); + + public abstract boolean remove(Status paramStatus); + + public abstract Iterator iterator(); +} diff --git a/src/minecraft/ch/qos/logback/core/status/StatusBase.java b/src/minecraft/ch/qos/logback/core/status/StatusBase.java new file mode 100644 index 0000000..bbd4784 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/status/StatusBase.java @@ -0,0 +1,173 @@ +package ch.qos.logback.core.status; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + + + + + + + + + + + + + +public abstract class StatusBase + implements Status +{ + private static final List EMPTY_LIST = new ArrayList(0); + int level; + final String message; + final Object origin; + List childrenList; + Throwable throwable; + long date; + + StatusBase(int level, String msg, Object origin) + { + this(level, msg, origin, null); + } + + StatusBase(int level, String msg, Object origin, Throwable t) { + this.level = level; + message = msg; + this.origin = origin; + throwable = t; + date = System.currentTimeMillis(); + } + + public synchronized void add(Status child) { + if (child == null) { + throw new NullPointerException("Null values are not valid Status."); + } + if (childrenList == null) { + childrenList = new ArrayList(); + } + childrenList.add(child); + } + + public synchronized boolean hasChildren() { + return (childrenList != null) && (childrenList.size() > 0); + } + + public synchronized Iterator iterator() { + if (childrenList != null) { + return childrenList.iterator(); + } + return EMPTY_LIST.iterator(); + } + + public synchronized boolean remove(Status statusToRemove) + { + if (childrenList == null) { + return false; + } + + return childrenList.remove(statusToRemove); + } + + public int getLevel() { + return level; + } + + + + + public synchronized int getEffectiveLevel() + { + int result = level; + + + Iterator it = iterator(); + + while (it.hasNext()) { + Status s = (Status)it.next(); + int effLevel = s.getEffectiveLevel(); + if (effLevel > result) { + result = effLevel; + } + } + return result; + } + + public String getMessage() { + return message; + } + + public Object getOrigin() { + return origin; + } + + public Throwable getThrowable() { + return throwable; + } + + public Long getDate() { + return Long.valueOf(date); + } + + + + public String toString() + { + StringBuilder buf = new StringBuilder(); + switch (getEffectiveLevel()) { + case 0: + buf.append("INFO"); + break; + case 1: + buf.append("WARN"); + break; + case 2: + buf.append("ERROR"); + } + + if (origin != null) { + buf.append(" in "); + buf.append(origin); + buf.append(" -"); + } + + buf.append(" "); + buf.append(message); + + if (throwable != null) { + buf.append(" "); + buf.append(throwable); + } + + return buf.toString(); + } + + public int hashCode() + { + int prime = 31; + int result = 1; + result = 31 * result + level; + result = 31 * result + (message == null ? 0 : message.hashCode()); + return result; + } + + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + StatusBase other = (StatusBase)obj; + if (level != level) + return false; + if (message == null) { + if (message != null) + return false; + } else if (!message.equals(message)) + return false; + return true; + } +} diff --git a/src/minecraft/ch/qos/logback/core/status/StatusListener.java b/src/minecraft/ch/qos/logback/core/status/StatusListener.java new file mode 100644 index 0000000..6c70fd2 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/status/StatusListener.java @@ -0,0 +1,6 @@ +package ch.qos.logback.core.status; + +public abstract interface StatusListener +{ + public abstract void addStatusEvent(Status paramStatus); +} diff --git a/src/minecraft/ch/qos/logback/core/status/StatusListenerAsList.java b/src/minecraft/ch/qos/logback/core/status/StatusListenerAsList.java new file mode 100644 index 0000000..0b291de --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/status/StatusListenerAsList.java @@ -0,0 +1,36 @@ +package ch.qos.logback.core.status; + +import java.util.ArrayList; +import java.util.List; + + + + + + + + + + + + + + + + + +public class StatusListenerAsList + implements StatusListener +{ + public StatusListenerAsList() {} + + List statusList = new ArrayList(); + + public void addStatusEvent(Status status) { + statusList.add(status); + } + + public List getStatusList() { + return statusList; + } +} diff --git a/src/minecraft/ch/qos/logback/core/status/StatusManager.java b/src/minecraft/ch/qos/logback/core/status/StatusManager.java new file mode 100644 index 0000000..740fead --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/status/StatusManager.java @@ -0,0 +1,20 @@ +package ch.qos.logback.core.status; + +import java.util.List; + +public abstract interface StatusManager +{ + public abstract void add(Status paramStatus); + + public abstract List getCopyOfStatusList(); + + public abstract int getCount(); + + public abstract void add(StatusListener paramStatusListener); + + public abstract void remove(StatusListener paramStatusListener); + + public abstract void clear(); + + public abstract List getCopyOfStatusListenerList(); +} diff --git a/src/minecraft/ch/qos/logback/core/status/StatusUtil.java b/src/minecraft/ch/qos/logback/core/status/StatusUtil.java new file mode 100644 index 0000000..c84545b --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/status/StatusUtil.java @@ -0,0 +1,184 @@ +package ch.qos.logback.core.status; + +import ch.qos.logback.core.Context; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + + + + + + + + + + + + + + +public class StatusUtil +{ + StatusManager sm; + + public StatusUtil(StatusManager sm) + { + this.sm = sm; + } + + public StatusUtil(Context context) { + sm = context.getStatusManager(); + } + + + + + + + + + + public static boolean contextHasStatusListener(Context context) + { + StatusManager sm = context.getStatusManager(); + if (sm == null) + return false; + List listeners = sm.getCopyOfStatusListenerList(); + if ((listeners == null) || (listeners.size() == 0)) { + return false; + } + return true; + } + + public static List filterStatusListByTimeThreshold(List rawList, long threshold) { + List filteredList = new ArrayList(); + for (Status s : rawList) { + if (s.getDate().longValue() >= threshold) + filteredList.add(s); + } + return filteredList; + } + + public void addStatus(Status status) { + if (sm != null) { + sm.add(status); + } + } + + public void addInfo(Object caller, String msg) { + addStatus(new InfoStatus(msg, caller)); + } + + public void addWarn(Object caller, String msg) { + addStatus(new WarnStatus(msg, caller)); + } + + public void addError(Object caller, String msg, Throwable t) + { + addStatus(new ErrorStatus(msg, caller, t)); + } + + public boolean hasXMLParsingErrors(long threshold) { + return containsMatch(threshold, 2, "XML_PARSING"); + } + + public boolean noXMLParsingErrorsOccurred(long threshold) { + return !hasXMLParsingErrors(threshold); + } + + public int getHighestLevel(long threshold) { + List filteredList = filterStatusListByTimeThreshold(sm.getCopyOfStatusList(), threshold); + int maxLevel = 0; + for (Status s : filteredList) { + if (s.getLevel() > maxLevel) + maxLevel = s.getLevel(); + } + return maxLevel; + } + + public boolean isErrorFree(long threshold) { + return 2 > getHighestLevel(threshold); + } + + public boolean containsMatch(long threshold, int level, String regex) { + List filteredList = filterStatusListByTimeThreshold(sm.getCopyOfStatusList(), threshold); + Pattern p = Pattern.compile(regex); + + for (Status status : filteredList) { + if (level == status.getLevel()) + { + + String msg = status.getMessage(); + Matcher matcher = p.matcher(msg); + if (matcher.lookingAt()) + return true; + } + } + return false; + } + + public boolean containsMatch(int level, String regex) { + return containsMatch(0L, level, regex); + } + + public boolean containsMatch(String regex) { + Pattern p = Pattern.compile(regex); + for (Status status : sm.getCopyOfStatusList()) { + String msg = status.getMessage(); + Matcher matcher = p.matcher(msg); + if (matcher.lookingAt()) { + return true; + } + } + return false; + } + + public int matchCount(String regex) { + int count = 0; + Pattern p = Pattern.compile(regex); + for (Status status : sm.getCopyOfStatusList()) { + String msg = status.getMessage(); + Matcher matcher = p.matcher(msg); + if (matcher.lookingAt()) { + count++; + } + } + return count; + } + + public boolean containsException(Class exceptionType) { + Iterator stati = sm.getCopyOfStatusList().iterator(); + while (stati.hasNext()) { + Status status = (Status)stati.next(); + Throwable t = status.getThrowable(); + if ((t != null) && (t.getClass().getName().equals(exceptionType.getName()))) { + return true; + } + } + return false; + } + + + + + + public long timeOfLastReset() + { + List statusList = sm.getCopyOfStatusList(); + if (statusList == null) { + return -1L; + } + int len = statusList.size(); + for (int i = len - 1; i >= 0; i--) { + Status s = (Status)statusList.get(i); + if ("Will reset and reconfigure context ".equals(s.getMessage())) { + return s.getDate().longValue(); + } + } + return -1L; + } +} diff --git a/src/minecraft/ch/qos/logback/core/status/ViewStatusMessagesServletBase.java b/src/minecraft/ch/qos/logback/core/status/ViewStatusMessagesServletBase.java new file mode 100644 index 0000000..20595de --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/status/ViewStatusMessagesServletBase.java @@ -0,0 +1,194 @@ +package ch.qos.logback.core.status; + +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.helpers.Transform; +import ch.qos.logback.core.util.CachingDateFormatter; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.List; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + + + + + + + + + + + + + + + + + +public abstract class ViewStatusMessagesServletBase + extends HttpServlet +{ + private static final long serialVersionUID = -3551928133801157219L; + private static CachingDateFormatter SDF = new CachingDateFormatter("yyyy-MM-dd HH:mm:ss"); + + + static String SUBMIT = "submit"; + static String CLEAR = "Clear"; + int count; + + public ViewStatusMessagesServletBase() {} + + protected abstract StatusManager getStatusManager(HttpServletRequest paramHttpServletRequest, HttpServletResponse paramHttpServletResponse); + + protected abstract String getPageTitle(HttpServletRequest paramHttpServletRequest, HttpServletResponse paramHttpServletResponse); + + protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + { + count = 0; + StatusManager sm = getStatusManager(req, resp); + + resp.setContentType("text/html"); + PrintWriter output = resp.getWriter(); + + output.append("\r\n"); + output.append("\r\n"); + printCSS(req.getContextPath(), output); + output.append("\r\n"); + output.append("\r\n"); + output.append(getPageTitle(req, resp)); + + + output.append("
\r\n"); + output.append(""); + output.append("\r\n"); + + + if (CLEAR.equalsIgnoreCase(req.getParameter(SUBMIT))) { + sm.clear(); + sm.add(new InfoStatus("Cleared all status messages", this)); + } + + output.append("
"); + StringBuilder buf = new StringBuilder(); + if (sm != null) { + printList(buf, sm); + } else { + output.append("Could not find status manager"); + } + output.append(buf); + output.append("
"); + output.append("\r\n"); + output.append("\r\n"); + output.flush(); + output.close(); + } + + public void printCSS(String localRef, PrintWriter output) { + output.append(" \r\n"); + } + + public void printList(StringBuilder buf, StatusManager sm) + { + buf.append("\r\n"); + printHeader(buf); + List statusList = sm.getCopyOfStatusList(); + for (Status s : statusList) { + count += 1; + printStatus(buf, s); + } + buf.append("
\r\n"); + } + + public void printHeader(StringBuilder buf) { + buf.append(" \r\n"); + buf.append(" Date \r\n"); + buf.append(" Level\r\n"); + buf.append(" Origin\r\n"); + buf.append(" Message\r\n"); + buf.append(" \r\n"); + } + + String statusLevelAsString(Status s) + { + switch (s.getEffectiveLevel()) { + case 0: + return "INFO"; + case 1: + return "WARN"; + case 2: + return "ERROR"; + } + return null; + } + + String abbreviatedOrigin(Status s) { + Object o = s.getOrigin(); + if (o == null) { + return null; + } + String fqClassName = o.getClass().getName(); + int lastIndex = fqClassName.lastIndexOf('.'); + if (lastIndex != -1) { + return fqClassName.substring(lastIndex + 1, fqClassName.length()); + } + return fqClassName; + } + + private void printStatus(StringBuilder buf, Status s) { + String trClass; + String trClass; + if (count % 2 == 0) { + trClass = "even"; + } else { + trClass = "odd"; + } + buf.append(" \r\n"); + String dateStr = SDF.format(s.getDate().longValue()); + buf.append(" ").append(dateStr).append("\r\n"); + buf.append(" ").append(statusLevelAsString(s)).append("\r\n"); + + buf.append(" ").append(abbreviatedOrigin(s)).append("\r\n"); + buf.append(" ").append(s.getMessage()).append("\r\n"); + buf.append(" \r\n"); + if (s.getThrowable() != null) { + printThrowable(buf, s.getThrowable()); + } + } + + private void printThrowable(StringBuilder buf, Throwable t) { + buf.append(" \r\n"); + buf.append("
");
+    StringWriter sw = new StringWriter();
+    PrintWriter pw = new PrintWriter(sw);
+    t.printStackTrace(pw);
+    buf.append(Transform.escapeTags(sw.getBuffer()));
+    buf.append("    
\r\n"); + buf.append(" \r\n"); + } +} diff --git a/src/minecraft/ch/qos/logback/core/status/WarnStatus.java b/src/minecraft/ch/qos/logback/core/status/WarnStatus.java new file mode 100644 index 0000000..60111a6 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/status/WarnStatus.java @@ -0,0 +1,28 @@ +package ch.qos.logback.core.status; + + + + + + + + + + + + + + + +public class WarnStatus + extends StatusBase +{ + public WarnStatus(String msg, Object origin) + { + super(1, msg, origin); + } + + public WarnStatus(String msg, Object origin, Throwable t) { + super(1, msg, origin, t); + } +} diff --git a/src/minecraft/ch/qos/logback/core/subst/Node.java b/src/minecraft/ch/qos/logback/core/subst/Node.java new file mode 100644 index 0000000..9ff971c --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/subst/Node.java @@ -0,0 +1,124 @@ +package ch.qos.logback.core.subst; + +import java.io.PrintStream; + + + + + +public class Node +{ + Type type; + Object payload; + Object defaultPart; + Node next; + + static enum Type + { + LITERAL, VARIABLE; + + + private Type() {} + } + + + public Node(Type type, Object payload) + { + this.type = type; + this.payload = payload; + } + + public Node(Type type, Object payload, Object defaultPart) + { + this.type = type; + this.payload = payload; + this.defaultPart = defaultPart; + } + + void append(Node newNode) { + if (newNode == null) + return; + Node n = this; + for (;;) { + if (next == null) { + next = newNode; + return; + } + n = next; + } + } + + public String toString() + { + switch (1.$SwitchMap$ch$qos$logback$core$subst$Node$Type[type.ordinal()]) { + case 1: + return "Node{type=" + type + ", payload='" + payload + "'}"; + + + + case 2: + StringBuilder payloadBuf = new StringBuilder(); + StringBuilder defaultPartBuf2 = new StringBuilder(); + if (defaultPart != null) { + recursive((Node)defaultPart, defaultPartBuf2); + } + recursive((Node)payload, payloadBuf); + String r = "Node{type=" + type + ", payload='" + payloadBuf.toString() + "'"; + + + if (defaultPart != null) + r = r + ", defaultPart=" + defaultPartBuf2.toString(); + r = r + '}'; + return r; + } + return null; + } + + public void dump() { + System.out.print(toString()); + System.out.print(" -> "); + if (next != null) { + next.dump(); + } else { + System.out.print(" null"); + } + } + + void recursive(Node n, StringBuilder sb) { + Node c = n; + while (c != null) { + sb.append(c.toString()).append(" --> "); + c = next; + } + sb.append("null "); + } + + public void setNext(Node n) { + next = n; + } + + public boolean equals(Object o) + { + if (this == o) return true; + if ((o == null) || (getClass() != o.getClass())) { return false; + } + Node node = (Node)o; + + if (type != type) return false; + if (payload != null ? !payload.equals(payload) : payload != null) return false; + if (defaultPart != null ? !defaultPart.equals(defaultPart) : defaultPart != null) return false; + if (next != null ? !next.equals(next) : next != null) { return false; + } + + return true; + } + + public int hashCode() + { + int result = type != null ? type.hashCode() : 0; + result = 31 * result + (payload != null ? payload.hashCode() : 0); + result = 31 * result + (defaultPart != null ? defaultPart.hashCode() : 0); + result = 31 * result + (next != null ? next.hashCode() : 0); + return result; + } +} diff --git a/src/minecraft/ch/qos/logback/core/subst/NodeToStringTransformer.java b/src/minecraft/ch/qos/logback/core/subst/NodeToStringTransformer.java new file mode 100644 index 0000000..ddc6515 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/subst/NodeToStringTransformer.java @@ -0,0 +1,182 @@ +package ch.qos.logback.core.subst; + +import ch.qos.logback.core.spi.PropertyContainer; +import ch.qos.logback.core.spi.ScanException; +import ch.qos.logback.core.util.OptionHelper; +import java.util.List; +import java.util.Stack; + + + + + + + + + + + + + + + + + + + + +public class NodeToStringTransformer +{ + final Node node; + final PropertyContainer propertyContainer0; + final PropertyContainer propertyContainer1; + + public NodeToStringTransformer(Node node, PropertyContainer propertyContainer0, PropertyContainer propertyContainer1) + { + this.node = node; + this.propertyContainer0 = propertyContainer0; + this.propertyContainer1 = propertyContainer1; + } + + public NodeToStringTransformer(Node node, PropertyContainer propertyContainer0) { + this(node, propertyContainer0, null); + } + + public static String substituteVariable(String input, PropertyContainer pc0, PropertyContainer pc1) throws ScanException { + Node node = tokenizeAndParseString(input); + NodeToStringTransformer nodeToStringTransformer = new NodeToStringTransformer(node, pc0, pc1); + return nodeToStringTransformer.transform(); + } + + private static Node tokenizeAndParseString(String value) throws ScanException { + Tokenizer tokenizer = new Tokenizer(value); + List tokens = tokenizer.tokenize(); + Parser parser = new Parser(tokens); + return parser.parse(); + } + + public String transform() throws ScanException { + StringBuilder stringBuilder = new StringBuilder(); + compileNode(node, stringBuilder, new Stack()); + return stringBuilder.toString(); + } + + private void compileNode(Node inputNode, StringBuilder stringBuilder, Stack cycleCheckStack) throws ScanException { + Node n = inputNode; + while (n != null) { + switch (1.$SwitchMap$ch$qos$logback$core$subst$Node$Type[type.ordinal()]) { + case 1: + handleLiteral(n, stringBuilder); + break; + case 2: + handleVariable(n, stringBuilder, cycleCheckStack); + } + + n = next; + } + } + + private void handleVariable(Node n, StringBuilder stringBuilder, Stack cycleCheckStack) + throws ScanException + { + if (haveVisitedNodeAlready(n, cycleCheckStack)) { + cycleCheckStack.push(n); + String error = constructRecursionErrorMessage(cycleCheckStack); + throw new IllegalArgumentException(error); + } + cycleCheckStack.push(n); + + StringBuilder keyBuffer = new StringBuilder(); + Node payload = (Node)payload; + compileNode(payload, keyBuffer, cycleCheckStack); + String key = keyBuffer.toString(); + String value = lookupKey(key); + + if (value != null) { + Node innerNode = tokenizeAndParseString(value); + compileNode(innerNode, stringBuilder, cycleCheckStack); + cycleCheckStack.pop(); + return; + } + + if (defaultPart == null) { + stringBuilder.append(key + "_IS_UNDEFINED"); + cycleCheckStack.pop(); + return; + } + + Node defaultPart = (Node)defaultPart; + StringBuilder defaultPartBuffer = new StringBuilder(); + compileNode(defaultPart, defaultPartBuffer, cycleCheckStack); + cycleCheckStack.pop(); + String defaultVal = defaultPartBuffer.toString(); + stringBuilder.append(defaultVal); + } + + private String lookupKey(String key) { + String value = propertyContainer0.getProperty(key); + if (value != null) { + return value; + } + if (propertyContainer1 != null) { + value = propertyContainer1.getProperty(key); + if (value != null) { + return value; + } + } + value = OptionHelper.getSystemProperty(key, null); + if (value != null) { + return value; + } + value = OptionHelper.getEnv(key); + if (value != null) { + return value; + } + + return null; + } + + private void handleLiteral(Node n, StringBuilder stringBuilder) + { + stringBuilder.append((String)payload); + } + + private String variableNodeValue(Node variableNode) { + Node literalPayload = (Node)payload; + return (String)payload; + } + + private String constructRecursionErrorMessage(Stack recursionNodes) { + StringBuilder errorBuilder = new StringBuilder("Circular variable reference detected while parsing input ["); + + for (Node stackNode : recursionNodes) { + errorBuilder.append("${").append(variableNodeValue(stackNode)).append("}"); + if (recursionNodes.lastElement() != stackNode) { + errorBuilder.append(" --> "); + } + } + errorBuilder.append("]"); + return errorBuilder.toString(); + } + + + + + + private boolean haveVisitedNodeAlready(Node node, Stack cycleDetectionStack) + { + for (Node cycleNode : cycleDetectionStack) { + if (equalNodes(node, cycleNode)) { + return true; + } + } + return false; + } + + private boolean equalNodes(Node node1, Node node2) { if ((type != null) && (!type.equals(type))) return false; + if ((payload != null) && (!payload.equals(payload))) return false; + if ((defaultPart != null) && (!defaultPart.equals(defaultPart))) { return false; + } + return true; + } +} diff --git a/src/minecraft/ch/qos/logback/core/subst/Parser.java b/src/minecraft/ch/qos/logback/core/subst/Parser.java new file mode 100644 index 0000000..749d530 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/subst/Parser.java @@ -0,0 +1,162 @@ +package ch.qos.logback.core.subst; + +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.spi.ScanException; +import java.util.List; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class Parser +{ + final List tokenList; + int pointer = 0; + + public Parser(List tokenList) { + this.tokenList = tokenList; + } + + public Node parse() throws ScanException { + if ((tokenList == null) || (tokenList.isEmpty())) + return null; + return E(); + } + + private Node E() throws ScanException { + Node t = T(); + if (t == null) { + return null; + } + Node eOpt = Eopt(); + if (eOpt != null) { + t.append(eOpt); + } + return t; + } + + private Node Eopt() throws ScanException + { + Token next = peekAtCurentToken(); + if (next == null) { + return null; + } + return E(); + } + + private Node T() + throws ScanException + { + Token t = peekAtCurentToken(); + + switch (1.$SwitchMap$ch$qos$logback$core$subst$Token$Type[type.ordinal()]) { + case 1: + advanceTokenPointer(); + return makeNewLiteralNode(payload); + case 2: + advanceTokenPointer(); + Node innerNode = C(); + Token right = peekAtCurentToken(); + expectCurlyRight(right); + advanceTokenPointer(); + Node curlyLeft = makeNewLiteralNode(CoreConstants.LEFT_ACCOLADE); + curlyLeft.append(innerNode); + curlyLeft.append(makeNewLiteralNode(CoreConstants.RIGHT_ACCOLADE)); + return curlyLeft; + case 3: + advanceTokenPointer(); + Node v = V(); + Token w = peekAtCurentToken(); + expectCurlyRight(w); + advanceTokenPointer(); + return v; + } + return null; + } + + private Node makeNewLiteralNode(String s) + { + return new Node(Node.Type.LITERAL, s); + } + + private Node V() throws ScanException + { + Node e = E(); + Node variable = new Node(Node.Type.VARIABLE, e); + Token t = peekAtCurentToken(); + if (isDefaultToken(t)) { + advanceTokenPointer(); + Node def = E(); + defaultPart = def; + } + return variable; + } + + private Node C() throws ScanException + { + Node e0 = E(); + Token t = peekAtCurentToken(); + if (isDefaultToken(t)) { + advanceTokenPointer(); + Node literal = makeNewLiteralNode(":-"); + e0.append(literal); + Node e1 = E(); + e0.append(e1); + } + return e0; + } + + private boolean isDefaultToken(Token t) { + return (t != null) && (type == Token.Type.DEFAULT); + } + + void advanceTokenPointer() { + pointer += 1; + } + + void expectNotNull(Token t, String expected) { + if (t == null) { + throw new IllegalArgumentException("All tokens consumed but was expecting \"" + expected + "\""); + } + } + + void expectCurlyRight(Token t) throws ScanException + { + expectNotNull(t, "}"); + if (type != Token.Type.CURLY_RIGHT) { + throw new ScanException("Expecting }"); + } + } + + Token peekAtCurentToken() { + if (pointer < tokenList.size()) { + return (Token)tokenList.get(pointer); + } + return null; + } +} diff --git a/src/minecraft/ch/qos/logback/core/subst/Token.java b/src/minecraft/ch/qos/logback/core/subst/Token.java new file mode 100644 index 0000000..f133c80 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/subst/Token.java @@ -0,0 +1,63 @@ +package ch.qos.logback.core.subst; + + + + + + + + + + + + + + +public class Token +{ + public static final Token START_TOKEN = new Token(Type.START, null); + public static final Token CURLY_LEFT_TOKEN = new Token(Type.CURLY_LEFT, null); + public static final Token CURLY_RIGHT_TOKEN = new Token(Type.CURLY_RIGHT, null); + public static final Token DEFAULT_SEP_TOKEN = new Token(Type.DEFAULT, null); + + public static enum Type { LITERAL, START, CURLY_LEFT, CURLY_RIGHT, DEFAULT; + + private Type() {} } + + Type type; + String payload; + public Token(Type type, String payload) { this.type = type; + this.payload = payload; + } + + public boolean equals(Object o) + { + if (this == o) return true; + if ((o == null) || (getClass() != o.getClass())) { return false; + } + Token token = (Token)o; + + if (type != type) return false; + if (payload != null ? !payload.equals(payload) : payload != null) { return false; + } + return true; + } + + public int hashCode() + { + int result = type != null ? type.hashCode() : 0; + result = 31 * result + (payload != null ? payload.hashCode() : 0); + return result; + } + + public String toString() + { + String result = "Token{type=" + type; + + if (payload != null) { + result = result + ", payload='" + payload + '\''; + } + result = result + '}'; + return result; + } +} diff --git a/src/minecraft/ch/qos/logback/core/subst/Tokenizer.java b/src/minecraft/ch/qos/logback/core/subst/Tokenizer.java new file mode 100644 index 0000000..c40e96d --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/subst/Tokenizer.java @@ -0,0 +1,124 @@ +package ch.qos.logback.core.subst; + +import ch.qos.logback.core.spi.ScanException; +import java.util.ArrayList; +import java.util.List; + + + + + + + + + + + +public class Tokenizer +{ + final String pattern; + final int patternLength; + + static enum TokenizerState + { + LITERAL_STATE, START_STATE, DEFAULT_VAL_STATE; + + private TokenizerState() {} + } + + public Tokenizer(String pattern) { + this.pattern = pattern; + patternLength = pattern.length(); + } + + TokenizerState state = TokenizerState.LITERAL_STATE; + int pointer = 0; + + List tokenize() throws ScanException { + List tokenList = new ArrayList(); + StringBuilder buf = new StringBuilder(); + + while (pointer < patternLength) { + char c = pattern.charAt(pointer); + pointer += 1; + + switch (1.$SwitchMap$ch$qos$logback$core$subst$Tokenizer$TokenizerState[state.ordinal()]) { + case 1: + handleLiteralState(c, tokenList, buf); + break; + case 2: + handleStartState(c, tokenList, buf); + break; + case 3: + handleDefaultValueState(c, tokenList, buf); + } + + } + + switch (1.$SwitchMap$ch$qos$logback$core$subst$Tokenizer$TokenizerState[state.ordinal()]) { + case 1: + addLiteralToken(tokenList, buf); + break; + case 2: + throw new ScanException("Unexpected end of pattern string"); + } + return tokenList; + } + + private void handleDefaultValueState(char c, List tokenList, StringBuilder stringBuilder) { + switch (c) { + case '-': + tokenList.add(Token.DEFAULT_SEP_TOKEN); + state = TokenizerState.LITERAL_STATE; + break; + case '$': + stringBuilder.append(':'); + addLiteralToken(tokenList, stringBuilder); + stringBuilder.setLength(0); + state = TokenizerState.START_STATE; + break; + default: + stringBuilder.append(':').append(c); + state = TokenizerState.LITERAL_STATE; + } + } + + private void handleStartState(char c, List tokenList, StringBuilder stringBuilder) + { + if (c == '{') { + tokenList.add(Token.START_TOKEN); + } else { + stringBuilder.append('$').append(c); + } + state = TokenizerState.LITERAL_STATE; + } + + private void handleLiteralState(char c, List tokenList, StringBuilder stringBuilder) { + if (c == '$') { + addLiteralToken(tokenList, stringBuilder); + stringBuilder.setLength(0); + state = TokenizerState.START_STATE; + } else if (c == ':') { + addLiteralToken(tokenList, stringBuilder); + stringBuilder.setLength(0); + state = TokenizerState.DEFAULT_VAL_STATE; + } else if (c == '{') { + addLiteralToken(tokenList, stringBuilder); + tokenList.add(Token.CURLY_LEFT_TOKEN); + stringBuilder.setLength(0); + } else if (c == '}') { + addLiteralToken(tokenList, stringBuilder); + tokenList.add(Token.CURLY_RIGHT_TOKEN); + stringBuilder.setLength(0); + } else { + stringBuilder.append(c); + } + } + + private void addLiteralToken(List tokenList, StringBuilder stringBuilder) + { + if (stringBuilder.length() == 0) + return; + tokenList.add(new Token(Token.Type.LITERAL, stringBuilder.toString())); + } +} diff --git a/src/minecraft/ch/qos/logback/core/util/AggregationType.java b/src/minecraft/ch/qos/logback/core/util/AggregationType.java new file mode 100644 index 0000000..82c5327 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/util/AggregationType.java @@ -0,0 +1,8 @@ +package ch.qos.logback.core.util; + +public enum AggregationType +{ + NOT_FOUND, AS_BASIC_PROPERTY, AS_COMPLEX_PROPERTY, AS_BASIC_PROPERTY_COLLECTION, AS_COMPLEX_PROPERTY_COLLECTION; + + private AggregationType() {} +} diff --git a/src/minecraft/ch/qos/logback/core/util/CachingDateFormatter.java b/src/minecraft/ch/qos/logback/core/util/CachingDateFormatter.java new file mode 100644 index 0000000..3dc23dc --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/util/CachingDateFormatter.java @@ -0,0 +1,58 @@ +package ch.qos.logback.core.util; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.TimeZone; + + + + + + + + + + + + + + + + + + + + + +public class CachingDateFormatter +{ + long lastTimestamp = -1L; + String cachedStr = null; + final SimpleDateFormat sdf; + + public CachingDateFormatter(String pattern) { + sdf = new SimpleDateFormat(pattern); + } + + + + + + + + + public final String format(long now) + { + synchronized (this) { + if (now != lastTimestamp) { + lastTimestamp = now; + cachedStr = sdf.format(new Date(now)); + } + return cachedStr; + } + } + + public void setTimeZone(TimeZone tz) { + sdf.setTimeZone(tz); + } +} diff --git a/src/minecraft/ch/qos/logback/core/util/CharSequenceState.java b/src/minecraft/ch/qos/logback/core/util/CharSequenceState.java new file mode 100644 index 0000000..d60bcfb --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/util/CharSequenceState.java @@ -0,0 +1,32 @@ +package ch.qos.logback.core.util; + + + + + + +class CharSequenceState +{ + final char c; + + + + + + int occurrences; + + + + + + + public CharSequenceState(char c) + { + this.c = c; + occurrences = 1; + } + + void incrementOccurrences() { + occurrences += 1; + } +} diff --git a/src/minecraft/ch/qos/logback/core/util/CharSequenceToRegexMapper.java b/src/minecraft/ch/qos/logback/core/util/CharSequenceToRegexMapper.java new file mode 100644 index 0000000..e34d55d --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/util/CharSequenceToRegexMapper.java @@ -0,0 +1,126 @@ +package ch.qos.logback.core.util; + +import java.text.DateFormatSymbols; + + + + + + + + + + + + + + + + + + +class CharSequenceToRegexMapper +{ + CharSequenceToRegexMapper() {} + + DateFormatSymbols symbols = DateFormatSymbols.getInstance(); + + String toRegex(CharSequenceState css) { + int occurrences = occurrences; + char c = c; + switch (c) { + case 'G': + case 'z': + return ".*"; + case 'M': + if (occurrences <= 2) + return number(occurrences); + if (occurrences == 3) { + return getRegexForShortMonths(); + } + return getRegexForLongMonths(); + case 'D': + case 'F': + case 'H': + case 'K': + case 'S': + case 'W': + case 'd': + case 'h': + case 'k': + case 'm': + case 's': + case 'w': + case 'y': + return number(occurrences); + case 'E': + if (occurrences >= 4) { + return getRegexForLongDaysOfTheWeek(); + } + return getRegexForShortDaysOfTheWeek(); + + case 'a': + return getRegexForAmPms(); + case 'Z': + return "(\\+|-)\\d{4}"; + case '.': + return "\\."; + case '\\': + throw new IllegalStateException("Forward slashes are not allowed"); + case '\'': + if (occurrences == 1) { + return ""; + } + throw new IllegalStateException("Too many single quotes"); + } + if (occurrences == 1) { + return "" + c; + } + return c + "{" + occurrences + "}"; + } + + + private String number(int occurrences) + { + return "\\d{" + occurrences + "}"; + } + + private String getRegexForAmPms() { + return symbolArrayToRegex(symbols.getAmPmStrings()); + } + + private String getRegexForLongDaysOfTheWeek() { + return symbolArrayToRegex(symbols.getWeekdays()); + } + + private String getRegexForShortDaysOfTheWeek() { + return symbolArrayToRegex(symbols.getShortWeekdays()); + } + + private String getRegexForLongMonths() { + return symbolArrayToRegex(symbols.getMonths()); + } + + String getRegexForShortMonths() { + return symbolArrayToRegex(symbols.getShortMonths()); + } + + private String symbolArrayToRegex(String[] symbolArray) { + int[] minMax = findMinMaxLengthsInSymbols(symbolArray); + return ".{" + minMax[0] + "," + minMax[1] + "}"; + } + + static int[] findMinMaxLengthsInSymbols(String[] symbols) { + int min = Integer.MAX_VALUE; + int max = 0; + for (String symbol : symbols) { + int len = symbol.length(); + + if (len != 0) + { + min = Math.min(min, len); + max = Math.max(max, len); + } } + return new int[] { min, max }; + } +} diff --git a/src/minecraft/ch/qos/logback/core/util/CloseUtil.java b/src/minecraft/ch/qos/logback/core/util/CloseUtil.java new file mode 100644 index 0000000..c85c886 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/util/CloseUtil.java @@ -0,0 +1,68 @@ +package ch.qos.logback.core.util; + +import java.io.Closeable; +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; + + + + + + + + + + + + + + + + + + + + +public class CloseUtil +{ + public CloseUtil() {} + + public static void closeQuietly(Closeable closeable) + { + if (closeable == null) return; + try { + closeable.close(); + } + catch (IOException ex) {} + } + + + + + + + public static void closeQuietly(Socket socket) + { + if (socket == null) return; + try { + socket.close(); + } + catch (IOException ex) {} + } + + + + + + + + public static void closeQuietly(ServerSocket serverSocket) + { + if (serverSocket == null) return; + try { + serverSocket.close(); + } + catch (IOException ex) {} + } +} diff --git a/src/minecraft/ch/qos/logback/core/util/ContentTypeUtil.java b/src/minecraft/ch/qos/logback/core/util/ContentTypeUtil.java new file mode 100644 index 0000000..707c0d7 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/util/ContentTypeUtil.java @@ -0,0 +1,45 @@ +package ch.qos.logback.core.util; + + + + + + + + + +public class ContentTypeUtil +{ + public ContentTypeUtil() {} + + + + + + + + + + public static boolean isTextual(String contextType) + { + if (contextType == null) { + return false; + } + return contextType.startsWith("text"); + } + + public static String getSubType(String contextType) { + if (contextType == null) { + return null; + } + int index = contextType.indexOf('/'); + if (index == -1) { + return null; + } + int subTypeStartIndex = index + 1; + if (subTypeStartIndex < contextType.length()) { + return contextType.substring(subTypeStartIndex); + } + return null; + } +} diff --git a/src/minecraft/ch/qos/logback/core/util/ContextUtil.java b/src/minecraft/ch/qos/logback/core/util/ContextUtil.java new file mode 100644 index 0000000..0c0bb5b --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/util/ContextUtil.java @@ -0,0 +1,107 @@ +package ch.qos.logback.core.util; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.spi.ContextAwareBase; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; +import java.util.Set; + + + + + + + + + + + + + +public class ContextUtil + extends ContextAwareBase +{ + public ContextUtil(Context context) + { + setContext(context); + } + + public static String getLocalHostName() throws UnknownHostException, SocketException + { + try { + InetAddress localhost = InetAddress.getLocalHost(); + return localhost.getHostName(); + } catch (UnknownHostException e) {} + return getLocalAddressAsString(); + } + + private static String getLocalAddressAsString() + throws UnknownHostException, SocketException + { + Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); + + while ((interfaces != null) && (interfaces.hasMoreElements())) { + Enumeration addresses = ((NetworkInterface)interfaces.nextElement()).getInetAddresses(); + + while ((addresses != null) && (addresses.hasMoreElements())) { + InetAddress address = (InetAddress)addresses.nextElement(); + if (acceptableAddress(address)) { + return address.getHostAddress(); + } + } + } + throw new UnknownHostException(); + } + + private static boolean acceptableAddress(InetAddress address) { + return (address != null) && (!address.isLoopbackAddress()) && (!address.isAnyLocalAddress()) && (!address.isLinkLocalAddress()); + } + + + + + + public void addHostNameAsProperty() + { + try + { + String localhostName = getLocalHostName(); + context.putProperty("HOSTNAME", localhostName); + } catch (UnknownHostException e) { + addError("Failed to get local hostname", e); + } catch (SocketException e) { + addError("Failed to get local hostname", e); + } catch (SecurityException e) { + addError("Failed to get local hostname", e); + } + } + + public void addProperties(Properties props) { + if (props == null) { + return; + } + Iterator i = props.keySet().iterator(); + while (i.hasNext()) { + String key = (String)i.next(); + context.putProperty(key, props.getProperty(key)); + } + } + + + public void addGroovyPackages(List frameworkPackages) + { + addFrameworkPackage(frameworkPackages, "org.codehaus.groovy.runtime"); + } + + public void addFrameworkPackage(List frameworkPackages, String packageName) { + if (!frameworkPackages.contains(packageName)) { + frameworkPackages.add(packageName); + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/util/DatePatternToRegexUtil.java b/src/minecraft/ch/qos/logback/core/util/DatePatternToRegexUtil.java new file mode 100644 index 0000000..f338c5f --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/util/DatePatternToRegexUtil.java @@ -0,0 +1,62 @@ +package ch.qos.logback.core.util; + +import java.util.ArrayList; +import java.util.List; + + + + + + + + + + + + + + + + + + + + + +public class DatePatternToRegexUtil +{ + final String datePattern; + final int datePatternLength; + final CharSequenceToRegexMapper regexMapper = new CharSequenceToRegexMapper(); + + public DatePatternToRegexUtil(String datePattern) { + this.datePattern = datePattern; + datePatternLength = datePattern.length(); + } + + public String toRegex() { + List charSequenceList = tokenize(); + StringBuilder sb = new StringBuilder(); + for (CharSequenceState seq : charSequenceList) { + sb.append(regexMapper.toRegex(seq)); + } + return sb.toString(); + } + + private List tokenize() { + List sequenceList = new ArrayList(); + + CharSequenceState lastCharSequenceState = null; + + for (int i = 0; i < datePatternLength; i++) { + char t = datePattern.charAt(i); + if ((lastCharSequenceState == null) || (c != t)) { + lastCharSequenceState = new CharSequenceState(t); + sequenceList.add(lastCharSequenceState); + } else { + lastCharSequenceState.incrementOccurrences(); + } + } + return sequenceList; + } +} diff --git a/src/minecraft/ch/qos/logback/core/util/DelayStrategy.java b/src/minecraft/ch/qos/logback/core/util/DelayStrategy.java new file mode 100644 index 0000000..0533dda --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/util/DelayStrategy.java @@ -0,0 +1,6 @@ +package ch.qos.logback.core.util; + +public abstract interface DelayStrategy +{ + public abstract long nextDelay(); +} diff --git a/src/minecraft/ch/qos/logback/core/util/Duration.java b/src/minecraft/ch/qos/logback/core/util/Duration.java new file mode 100644 index 0000000..15d4f39 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/util/Duration.java @@ -0,0 +1,124 @@ +package ch.qos.logback.core.util; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class Duration +{ + private static final String DOUBLE_PART = "([0-9]*(.[0-9]+)?)"; + private static final int DOUBLE_GROUP = 1; + private static final String UNIT_PART = "(|milli(second)?|second(e)?|minute|hour|day)s?"; + private static final int UNIT_GROUP = 3; + private static final Pattern DURATION_PATTERN = Pattern.compile("([0-9]*(.[0-9]+)?)\\s*(|milli(second)?|second(e)?|minute|hour|day)s?", 2); + + static final long SECONDS_COEFFICIENT = 1000L; + + static final long MINUTES_COEFFICIENT = 60000L; + static final long HOURS_COEFFICIENT = 3600000L; + static final long DAYS_COEFFICIENT = 86400000L; + final long millis; + + public Duration(long millis) + { + this.millis = millis; + } + + public static Duration buildByMilliseconds(double value) { + return new Duration(value); + } + + public static Duration buildBySeconds(double value) { + return new Duration((1000.0D * value)); + } + + public static Duration buildByMinutes(double value) { + return new Duration((60000.0D * value)); + } + + public static Duration buildByHours(double value) { + return new Duration((3600000.0D * value)); + } + + public static Duration buildByDays(double value) { + return new Duration((8.64E7D * value)); + } + + public static Duration buildUnbounded() { + return new Duration(Long.MAX_VALUE); + } + + public long getMilliseconds() { + return millis; + } + + public static Duration valueOf(String durationStr) { + Matcher matcher = DURATION_PATTERN.matcher(durationStr); + + if (matcher.matches()) { + String doubleStr = matcher.group(1); + String unitStr = matcher.group(3); + + double doubleValue = Double.valueOf(doubleStr).doubleValue(); + if ((unitStr.equalsIgnoreCase("milli")) || (unitStr.equalsIgnoreCase("millisecond")) || (unitStr.length() == 0)) + { + return buildByMilliseconds(doubleValue); } + if ((unitStr.equalsIgnoreCase("second")) || (unitStr.equalsIgnoreCase("seconde"))) + { + return buildBySeconds(doubleValue); } + if (unitStr.equalsIgnoreCase("minute")) + return buildByMinutes(doubleValue); + if (unitStr.equalsIgnoreCase("hour")) + return buildByHours(doubleValue); + if (unitStr.equalsIgnoreCase("day")) { + return buildByDays(doubleValue); + } + throw new IllegalStateException("Unexpected " + unitStr); + } + + throw new IllegalArgumentException("String value [" + durationStr + "] is not in the expected format."); + } + + + + public String toString() + { + if (millis < 1000L) + return millis + " milliseconds"; + if (millis < 60000L) + return millis / 1000L + " seconds"; + if (millis < 3600000L) { + return millis / 60000L + " minutes"; + } + return millis / 3600000L + " hours"; + } +} diff --git a/src/minecraft/ch/qos/logback/core/util/DynamicClassLoadingException.java b/src/minecraft/ch/qos/logback/core/util/DynamicClassLoadingException.java new file mode 100644 index 0000000..0ee6b0d --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/util/DynamicClassLoadingException.java @@ -0,0 +1,23 @@ +package ch.qos.logback.core.util; + + + + + + + +public class DynamicClassLoadingException + extends Exception +{ + private static final long serialVersionUID = 4962278449162476114L; + + + + + + + public DynamicClassLoadingException(String desc, Throwable root) + { + super(desc, root); + } +} diff --git a/src/minecraft/ch/qos/logback/core/util/EnvUtil.java b/src/minecraft/ch/qos/logback/core/util/EnvUtil.java new file mode 100644 index 0000000..0691ca9 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/util/EnvUtil.java @@ -0,0 +1,70 @@ +package ch.qos.logback.core.util; + +import java.util.ArrayList; +import java.util.List; + + + + + + + + + + + + + + + +public class EnvUtil +{ + public EnvUtil() {} + + private static boolean isJDK_N_OrHigher(int n) + { + List versionList = new ArrayList(); + + + for (int i = 0; i < 5; i++) { + versionList.add("1." + (n + i)); + } + + String javaVersion = System.getProperty("java.version"); + if (javaVersion == null) { + return false; + } + for (String v : versionList) { + if (javaVersion.startsWith(v)) + return true; + } + return false; + } + + public static boolean isJDK5() { + return isJDK_N_OrHigher(5); + } + + public static boolean isJDK6OrHigher() { + return isJDK_N_OrHigher(6); + } + + public static boolean isJDK7OrHigher() { + return isJDK_N_OrHigher(7); + } + + public static boolean isJaninoAvailable() { + ClassLoader classLoader = EnvUtil.class.getClassLoader(); + try { + Class bindingClass = classLoader.loadClass("org.codehaus.janino.ScriptEvaluator"); + return bindingClass != null; + } catch (ClassNotFoundException e) {} + return false; + } + + public static boolean isWindows() + { + String os = System.getProperty("os.name"); + return os.startsWith("Windows"); + } +} diff --git a/src/minecraft/ch/qos/logback/core/util/ExecutorServiceUtil.java b/src/minecraft/ch/qos/logback/core/util/ExecutorServiceUtil.java new file mode 100644 index 0000000..1dfdec3 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/util/ExecutorServiceUtil.java @@ -0,0 +1,69 @@ +package ch.qos.logback.core.util; + +import ch.qos.logback.core.CoreConstants; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + + + + + + + + + + + + + + + + + + + + + +public class ExecutorServiceUtil +{ + private static final ThreadFactory THREAD_FACTORY = new ThreadFactory() + { + private final ThreadFactory defaultFactory = Executors.defaultThreadFactory(); + private final AtomicInteger threadNumber = new AtomicInteger(1); + + public Thread newThread(Runnable r) { + Thread thread = defaultFactory.newThread(r); + if (!thread.isDaemon()) { + thread.setDaemon(true); + } + thread.setName("logback-" + threadNumber.getAndIncrement()); + return thread; + } + }; + + + public ExecutorServiceUtil() {} + + public static ExecutorService newExecutorService() + { + return new ThreadPoolExecutor(CoreConstants.CORE_POOL_SIZE, 32, 0L, TimeUnit.MILLISECONDS, new SynchronousQueue(), THREAD_FACTORY); + } + + + + + + + + + + public static void shutdown(ExecutorService executorService) + { + executorService.shutdownNow(); + } +} diff --git a/src/minecraft/ch/qos/logback/core/util/FileSize.java b/src/minecraft/ch/qos/logback/core/util/FileSize.java new file mode 100644 index 0000000..37777ed --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/util/FileSize.java @@ -0,0 +1,81 @@ +package ch.qos.logback.core.util; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class FileSize +{ + private static final String LENGTH_PART = "([0-9]+)"; + private static final int DOUBLE_GROUP = 1; + private static final String UNIT_PART = "(|kb|mb|gb)s?"; + private static final int UNIT_GROUP = 2; + private static final Pattern FILE_SIZE_PATTERN = Pattern.compile("([0-9]+)\\s*(|kb|mb|gb)s?", 2); + + static final long KB_COEFFICIENT = 1024L; + + static final long MB_COEFFICIENT = 1048576L; + static final long GB_COEFFICIENT = 1073741824L; + final long size; + + FileSize(long size) + { + this.size = size; + } + + public long getSize() { + return size; + } + + public static FileSize valueOf(String fileSizeStr) { + Matcher matcher = FILE_SIZE_PATTERN.matcher(fileSizeStr); + + + if (matcher.matches()) { + String lenStr = matcher.group(1); + String unitStr = matcher.group(2); + + long lenValue = Long.valueOf(lenStr).longValue(); + long coefficient; if (unitStr.equalsIgnoreCase("")) { + coefficient = 1L; } else { long coefficient; + if (unitStr.equalsIgnoreCase("kb")) { + coefficient = 1024L; } else { long coefficient; + if (unitStr.equalsIgnoreCase("mb")) { + coefficient = 1048576L; } else { long coefficient; + if (unitStr.equalsIgnoreCase("gb")) { + coefficient = 1073741824L; + } else + throw new IllegalStateException("Unexpected " + unitStr); } } } + long coefficient; + return new FileSize(lenValue * coefficient); + } + throw new IllegalArgumentException("String value [" + fileSizeStr + "] is not in the expected format."); + } +} diff --git a/src/minecraft/ch/qos/logback/core/util/FileUtil.java b/src/minecraft/ch/qos/logback/core/util/FileUtil.java new file mode 100644 index 0000000..fec8f06 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/util/FileUtil.java @@ -0,0 +1,135 @@ +package ch.qos.logback.core.util; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.rolling.RolloverFailure; +import ch.qos.logback.core.spi.ContextAwareBase; +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.InputStreamReader; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.net.URLConnection; + + + + +public class FileUtil + extends ContextAwareBase +{ + static final int BUF_SIZE = 32768; + + public FileUtil(Context context) + { + setContext(context); + } + + public static URL fileToURL(File file) { + try { + return file.toURI().toURL(); + } catch (MalformedURLException e) { + throw new RuntimeException("Unexpected exception on file [" + file + "]", e); + } + } + + + + + + + + + + public static boolean createMissingParentDirectories(File file) + { + File parent = file.getParentFile(); + if (parent == null) + { + + return true; + } + + + + parent.mkdirs(); + return parent.exists(); + } + + public String resourceAsString(ClassLoader classLoader, String resourceName) + { + URL url = classLoader.getResource(resourceName); + if (url == null) { + addError("Failed to find resource [" + resourceName + "]"); + return null; + } + + InputStreamReader isr = null; + try { + URLConnection urlConnection = url.openConnection(); + urlConnection.setUseCaches(false); + isr = new InputStreamReader(urlConnection.getInputStream()); + char[] buf = new char['€']; + StringBuilder builder = new StringBuilder(); + int count = -1; + while ((count = isr.read(buf, 0, buf.length)) != -1) { + builder.append(buf, 0, count); + } + return builder.toString(); + } catch (IOException e) { + addError("Failed to open " + resourceName, e); + } finally { + if (isr != null) { + try { + isr.close(); + } + catch (IOException e) {} + } + } + + return null; + } + + public void copy(String src, String destination) + throws RolloverFailure + { + BufferedInputStream bis = null; + BufferedOutputStream bos = null; + try { + bis = new BufferedInputStream(new FileInputStream(src)); + bos = new BufferedOutputStream(new FileOutputStream(destination)); + byte[] inbuf = new byte[32768]; + + int n; + while ((n = bis.read(inbuf)) != -1) { + bos.write(inbuf, 0, n); + } + + bis.close(); + bis = null; + bos.close(); + bos = null; + String msg; + return; } catch (IOException ioe) { msg = "Failed to copy [" + src + "] to [" + destination + "]"; + addError(msg, ioe); + throw new RolloverFailure(msg); + } finally { + if (bis != null) { + try { + bis.close(); + } + catch (IOException e) {} + } + + if (bos != null) { + try { + bos.close(); + } + catch (IOException e) {} + } + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/util/FixedDelay.java b/src/minecraft/ch/qos/logback/core/util/FixedDelay.java new file mode 100644 index 0000000..6c98e9b --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/util/FixedDelay.java @@ -0,0 +1,58 @@ +package ch.qos.logback.core.util; + + + + + + + + + +public class FixedDelay + implements DelayStrategy +{ + private final long subsequentDelay; + + + + + + + + + private long nextDelay; + + + + + + + + + + public FixedDelay(long initialDelay, long subsequentDelay) + { + String s = new String(); + nextDelay = initialDelay; + this.subsequentDelay = subsequentDelay; + } + + + + + + + public FixedDelay(int delay) + { + this(delay, delay); + } + + + + public long nextDelay() + { + long delay = nextDelay; + nextDelay = subsequentDelay; + return delay; + } +} diff --git a/src/minecraft/ch/qos/logback/core/util/IncompatibleClassException.java b/src/minecraft/ch/qos/logback/core/util/IncompatibleClassException.java new file mode 100644 index 0000000..dfc1f02 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/util/IncompatibleClassException.java @@ -0,0 +1,28 @@ +package ch.qos.logback.core.util; + + + + + +public class IncompatibleClassException + extends Exception +{ + private static final long serialVersionUID = -5823372159561159549L; + + + + Class requestedClass; + + + + Class obtainedClass; + + + + + IncompatibleClassException(Class requestedClass, Class obtainedClass) + { + this.requestedClass = requestedClass; + this.obtainedClass = obtainedClass; + } +} diff --git a/src/minecraft/ch/qos/logback/core/util/InvocationGate.java b/src/minecraft/ch/qos/logback/core/util/InvocationGate.java new file mode 100644 index 0000000..5d036e1 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/util/InvocationGate.java @@ -0,0 +1,61 @@ +package ch.qos.logback.core.util; + + + + + + + + + + + + +public class InvocationGate +{ + private static final int MAX_MASK = 65535; + + + + + + + + + + + private volatile long mask = 15L; + private volatile long lastMaskCheck = System.currentTimeMillis(); + + + + + + + private long invocationCounter = 0L; + + + + + private static final long thresholdForMaskIncrease = 100L; + + + + private final long thresholdForMaskDecrease = 800L; + + public InvocationGate() {} + + public boolean skipFurtherWork() { return (invocationCounter++ & mask) != mask; } + + + public void updateMaskIfNecessary(long now) + { + long timeElapsedSinceLastMaskUpdateCheck = now - lastMaskCheck; + lastMaskCheck = now; + if ((timeElapsedSinceLastMaskUpdateCheck < 100L) && (mask < 65535L)) { + mask = (mask << 1 | 1L); + } else if (timeElapsedSinceLastMaskUpdateCheck > 800L) { + mask >>>= 2; + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/util/Loader.java b/src/minecraft/ch/qos/logback/core/util/Loader.java new file mode 100644 index 0000000..ec110cd --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/util/Loader.java @@ -0,0 +1,209 @@ +package ch.qos.logback.core.util; + +import ch.qos.logback.core.Context; +import java.io.IOException; +import java.net.URL; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Set; + + + + + + + + + + + + + + + + + + + + +public class Loader +{ + static final String TSTR = "Caught Exception while in Loader.getResource. This may be innocuous."; + private static boolean ignoreTCL = false; + public static final String IGNORE_TCL_PROPERTY_NAME = "logback.ignoreTCL"; + + static + { + String ignoreTCLProp = OptionHelper.getSystemProperty("logback.ignoreTCL", null); + + + if (ignoreTCLProp != null) + ignoreTCL = OptionHelper.toBoolean(ignoreTCLProp, true); + } + + private static boolean HAS_GET_CLASS_LOADER_PERMISSION = ((Boolean)AccessController.doPrivileged(new PrivilegedAction() + { + public Boolean run() { + try { + AccessController.checkPermission(new RuntimePermission("getClassLoader")); + + return Boolean.valueOf(true); + } + catch (SecurityException e) {} + + return Boolean.valueOf(false); + } + })).booleanValue(); + + + + + + + + + + + + + + + + + + + + + + + + + + public static Set getResourceOccurrenceCount(String resource, ClassLoader classLoader) + throws IOException + { + Set urlSet = new HashSet(); + Enumeration urlEnum = classLoader.getResources(resource); + while (urlEnum.hasMoreElements()) { + URL url = (URL)urlEnum.nextElement(); + urlSet.add(url); + } + return urlSet; + } + + + + + + public static URL getResource(String resource, ClassLoader classLoader) + { + try + { + return classLoader.getResource(resource); + } catch (Throwable t) {} + return null; + } + + + + + + + + + public static URL getResourceBySelfClassLoader(String resource) + { + return getResource(resource, getClassLoaderOfClass(Loader.class)); + } + + + + + + + + + + public static ClassLoader getTCL() + { + return Thread.currentThread().getContextClassLoader(); + } + + public static Class loadClass(String clazz, Context context) throws ClassNotFoundException + { + ClassLoader cl = getClassLoaderOfObject(context); + return cl.loadClass(clazz); + } + + + + + + + + public static ClassLoader getClassLoaderOfObject(Object o) + { + if (o == null) { + throw new NullPointerException("Argument cannot be null"); + } + return getClassLoaderOfClass(o.getClass()); + } + + + + + + + public static ClassLoader getClassLoaderAsPrivileged(Class clazz) + { + if (!HAS_GET_CLASS_LOADER_PERMISSION) { + return null; + } + (ClassLoader)AccessController.doPrivileged(new PrivilegedAction() + { + public ClassLoader run() { + return val$clazz.getClassLoader(); + } + }); + } + + + + + + + + public static ClassLoader getClassLoaderOfClass(Class clazz) + { + ClassLoader cl = clazz.getClassLoader(); + if (cl == null) { + return ClassLoader.getSystemClassLoader(); + } + return cl; + } + + + + + + + + public static Class loadClass(String clazz) + throws ClassNotFoundException + { + if (ignoreTCL) { + return Class.forName(clazz); + } + try { + return getTCL().loadClass(clazz); + } + catch (Throwable e) {} + + + return Class.forName(clazz); + } + + public Loader() {} +} diff --git a/src/minecraft/ch/qos/logback/core/util/LocationUtil.java b/src/minecraft/ch/qos/logback/core/util/LocationUtil.java new file mode 100644 index 0000000..2495f49 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/util/LocationUtil.java @@ -0,0 +1,74 @@ +package ch.qos.logback.core.util; + +import java.io.FileNotFoundException; +import java.net.MalformedURLException; +import java.net.URL; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class LocationUtil +{ + public static final String SCHEME_PATTERN = "^\\p{Alpha}[\\p{Alnum}+.-]*:.*$"; + public static final String CLASSPATH_SCHEME = "classpath:"; + + public LocationUtil() {} + + public static URL urlForResource(String location) + throws MalformedURLException, FileNotFoundException + { + if (location == null) { + throw new NullPointerException("location is required"); + } + URL url = null; + if (!location.matches("^\\p{Alpha}[\\p{Alnum}+.-]*:.*$")) { + url = Loader.getResourceBySelfClassLoader(location); + } + else if (location.startsWith("classpath:")) { + String path = location.substring("classpath:".length()); + if (path.startsWith("/")) { + path = path.substring(1); + } + if (path.length() == 0) { + throw new MalformedURLException("path is required"); + } + url = Loader.getResourceBySelfClassLoader(path); + } + else { + url = new URL(location); + } + if (url == null) { + throw new FileNotFoundException(location); + } + return url; + } +} diff --git a/src/minecraft/ch/qos/logback/core/util/OptionHelper.java b/src/minecraft/ch/qos/logback/core/util/OptionHelper.java new file mode 100644 index 0000000..0ee1005 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/util/OptionHelper.java @@ -0,0 +1,270 @@ +package ch.qos.logback.core.util; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.spi.ContextAware; +import ch.qos.logback.core.spi.PropertyContainer; +import ch.qos.logback.core.spi.ScanException; +import ch.qos.logback.core.subst.NodeToStringTransformer; +import java.lang.reflect.Constructor; +import java.util.Properties; + + + + + + + + + +public class OptionHelper +{ + static final String DELIM_START = "${"; + static final char DELIM_STOP = '}'; + static final String DELIM_DEFAULT = ":-"; + static final int DELIM_START_LEN = 2; + static final int DELIM_STOP_LEN = 1; + static final int DELIM_DEFAULT_LEN = 2; + static final String _IS_UNDEFINED = "_IS_UNDEFINED"; + + public OptionHelper() {} + + public static Object instantiateByClassName(String className, Class superClass, Context context) + throws IncompatibleClassException, DynamicClassLoadingException + { + ClassLoader classLoader = Loader.getClassLoaderOfObject(context); + return instantiateByClassName(className, superClass, classLoader); + } + + public static Object instantiateByClassNameAndParameter(String className, Class superClass, Context context, Class type, Object param) + throws IncompatibleClassException, DynamicClassLoadingException + { + ClassLoader classLoader = Loader.getClassLoaderOfObject(context); + return instantiateByClassNameAndParameter(className, superClass, classLoader, type, param); + } + + public static Object instantiateByClassName(String className, Class superClass, ClassLoader classLoader) + throws IncompatibleClassException, DynamicClassLoadingException + { + return instantiateByClassNameAndParameter(className, superClass, classLoader, null, null); + } + + + public static Object instantiateByClassNameAndParameter(String className, Class superClass, ClassLoader classLoader, Class type, Object parameter) + throws IncompatibleClassException, DynamicClassLoadingException + { + if (className == null) { + throw new NullPointerException(); + } + try { + Class classObj = null; + classObj = classLoader.loadClass(className); + if (!superClass.isAssignableFrom(classObj)) { + throw new IncompatibleClassException(superClass, classObj); + } + if (type == null) { + return classObj.newInstance(); + } + Constructor constructor = classObj.getConstructor(new Class[] { type }); + return constructor.newInstance(new Object[] { parameter }); + } + catch (IncompatibleClassException ice) { + throw ice; + } catch (Throwable t) { + throw new DynamicClassLoadingException("Failed to instantiate type " + className, t); + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static String substVars(String val, PropertyContainer pc1) + { + return substVars(val, pc1, null); + } + + + public static String substVars(String input, PropertyContainer pc0, PropertyContainer pc1) + { + try + { + return NodeToStringTransformer.substituteVariable(input, pc0, pc1); + } catch (ScanException e) { + throw new IllegalArgumentException("Failed to parse input [" + input + "]", e); + } + } + + public static String propertyLookup(String key, PropertyContainer pc1, PropertyContainer pc2) + { + String value = null; + + value = pc1.getProperty(key); + + + if ((value == null) && (pc2 != null)) { + value = pc2.getProperty(key); + } + + if (value == null) { + value = getSystemProperty(key, null); + } + if (value == null) { + value = getEnv(key); + } + return value; + } + + + + + + + + + public static String getSystemProperty(String key, String def) + { + try + { + return System.getProperty(key, def); + } catch (SecurityException e) {} + return def; + } + + + + + + + public static String getEnv(String key) + { + try + { + return System.getenv(key); + } catch (SecurityException e) {} + return null; + } + + + + + + + + + public static String getSystemProperty(String key) + { + try + { + return System.getProperty(key); + } catch (SecurityException e) {} + return null; + } + + public static void setSystemProperties(ContextAware contextAware, Properties props) + { + for (Object o : props.keySet()) { + String key = (String)o; + String value = props.getProperty(key); + setSystemProperty(contextAware, key, value); + } + } + + public static void setSystemProperty(ContextAware contextAware, String key, String value) { + try { + System.setProperty(key, value); + } catch (SecurityException e) { + contextAware.addError("Failed to set system property [" + key + "]", e); + } + } + + + + + + public static Properties getSystemProperties() + { + try + { + return System.getProperties(); + } catch (SecurityException e) {} + return new Properties(); + } + + + + + + + + + + public static String[] extractDefaultReplacement(String key) + { + String[] result = new String[2]; + if (key == null) { + return result; + } + result[0] = key; + int d = key.indexOf(":-"); + if (d != -1) { + result[0] = key.substring(0, d); + result[1] = key.substring(d + 2); + } + return result; + } + + + + + + + + public static boolean toBoolean(String value, boolean dEfault) + { + if (value == null) { + return dEfault; + } + + String trimmedVal = value.trim(); + + if ("true".equalsIgnoreCase(trimmedVal)) { + return true; + } + + if ("false".equalsIgnoreCase(trimmedVal)) { + return false; + } + + return dEfault; + } + + public static boolean isEmpty(String str) { + return (str == null) || ("".equals(str)); + } +} diff --git a/src/minecraft/ch/qos/logback/core/util/PropertySetterException.java b/src/minecraft/ch/qos/logback/core/util/PropertySetterException.java new file mode 100644 index 0000000..b38a1ff --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/util/PropertySetterException.java @@ -0,0 +1,37 @@ +package ch.qos.logback.core.util; + + + + + + + + + + +public class PropertySetterException + extends Exception +{ + private static final long serialVersionUID = -2771077768281663949L; + + + + + + + + + + public PropertySetterException(String msg) + { + super(msg); + } + + public PropertySetterException(Throwable rootCause) { + super(rootCause); + } + + public PropertySetterException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/minecraft/ch/qos/logback/core/util/StatusPrinter.java b/src/minecraft/ch/qos/logback/core/util/StatusPrinter.java new file mode 100644 index 0000000..56775b4 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/util/StatusPrinter.java @@ -0,0 +1,194 @@ +package ch.qos.logback.core.util; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.helpers.ThrowableToStringArray; +import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.status.StatusManager; +import ch.qos.logback.core.status.StatusUtil; +import java.io.PrintStream; +import java.util.Iterator; +import java.util.List; + + + + + + + + + + + + + + + +public class StatusPrinter +{ + private static PrintStream ps = System.out; + + static CachingDateFormatter cachingDateFormat = new CachingDateFormatter("HH:mm:ss,SSS"); + + public StatusPrinter() {} + + public static void setPrintStream(PrintStream printStream) { ps = printStream; } + + + + + + + + public static void printInCaseOfErrorsOrWarnings(Context context) + { + printInCaseOfErrorsOrWarnings(context, 0L); + } + + + + + + + public static void printInCaseOfErrorsOrWarnings(Context context, long threshold) + { + if (context == null) { + throw new IllegalArgumentException("Context argument cannot be null"); + } + + StatusManager sm = context.getStatusManager(); + if (sm == null) { + ps.println("WARN: Context named \"" + context.getName() + "\" has no status manager"); + } + else { + StatusUtil statusUtil = new StatusUtil(context); + if (statusUtil.getHighestLevel(threshold) >= 1) { + print(sm, threshold); + } + } + } + + + + + + + public static void printIfErrorsOccured(Context context) + { + if (context == null) { + throw new IllegalArgumentException("Context argument cannot be null"); + } + + StatusManager sm = context.getStatusManager(); + if (sm == null) { + ps.println("WARN: Context named \"" + context.getName() + "\" has no status manager"); + } + else { + StatusUtil statusUtil = new StatusUtil(context); + if (statusUtil.getHighestLevel(0L) == 2) { + print(sm); + } + } + } + + + + + + public static void print(Context context) + { + print(context, 0L); + } + + + + + public static void print(Context context, long threshold) + { + if (context == null) { + throw new IllegalArgumentException("Context argument cannot be null"); + } + + StatusManager sm = context.getStatusManager(); + if (sm == null) { + ps.println("WARN: Context named \"" + context.getName() + "\" has no status manager"); + } + else { + print(sm, threshold); + } + } + + public static void print(StatusManager sm) { + print(sm, 0L); + } + + public static void print(StatusManager sm, long threshold) { + StringBuilder sb = new StringBuilder(); + List filteredList = StatusUtil.filterStatusListByTimeThreshold(sm.getCopyOfStatusList(), threshold); + buildStrFromStatusList(sb, filteredList); + ps.println(sb.toString()); + } + + public static void print(List statusList) + { + StringBuilder sb = new StringBuilder(); + buildStrFromStatusList(sb, statusList); + ps.println(sb.toString()); + } + + private static void buildStrFromStatusList(StringBuilder sb, List statusList) + { + if (statusList == null) + return; + for (Status s : statusList) { + buildStr(sb, "", s); + } + } + + + + + private static void appendThrowable(StringBuilder sb, Throwable t) + { + String[] stringRep = ThrowableToStringArray.convert(t); + + for (String s : stringRep) { + if (!s.startsWith("Caused by: ")) + { + if (Character.isDigit(s.charAt(0))) + { + sb.append("\t... "); + } + else + sb.append("\tat "); + } + sb.append(s).append(CoreConstants.LINE_SEPARATOR); + } + } + + public static void buildStr(StringBuilder sb, String indentation, Status s) { String prefix; + String prefix; + if (s.hasChildren()) { + prefix = indentation + "+ "; + } else { + prefix = indentation + "|-"; + } + + if (cachingDateFormat != null) { + String dateStr = cachingDateFormat.format(s.getDate().longValue()); + sb.append(dateStr).append(" "); + } + sb.append(prefix).append(s).append(CoreConstants.LINE_SEPARATOR); + + if (s.getThrowable() != null) { + appendThrowable(sb, s.getThrowable()); + } + if (s.hasChildren()) { + Iterator ite = s.iterator(); + while (ite.hasNext()) { + Status child = (Status)ite.next(); + buildStr(sb, indentation + " ", child); + } + } + } +} diff --git a/src/minecraft/ch/qos/logback/core/util/StringCollectionUtil.java b/src/minecraft/ch/qos/logback/core/util/StringCollectionUtil.java new file mode 100644 index 0000000..4f05c4a --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/util/StringCollectionUtil.java @@ -0,0 +1,111 @@ +package ch.qos.logback.core.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class StringCollectionUtil +{ + public StringCollectionUtil() {} + + public static void retainMatching(Collection values, String... patterns) + { + retainMatching(values, Arrays.asList(patterns)); + } + + + + + + + + + + + + + public static void retainMatching(Collection values, Collection patterns) + { + if (patterns.isEmpty()) return; + List matches = new ArrayList(values.size()); + for (String p : patterns) { + pattern = Pattern.compile(p); + for (String value : values) { + if (pattern.matcher(value).matches()) + matches.add(value); + } + } + Pattern pattern; + values.retainAll(matches); + } + + + + + + + + + + + + + public static void removeMatching(Collection values, String... patterns) + { + removeMatching(values, Arrays.asList(patterns)); + } + + + + + + + + + + + + + public static void removeMatching(Collection values, Collection patterns) + { + List matches = new ArrayList(values.size()); + for (String p : patterns) { + pattern = Pattern.compile(p); + for (String value : values) { + if (pattern.matcher(value).matches()) + matches.add(value); + } + } + Pattern pattern; + values.removeAll(matches); + } +} diff --git a/src/minecraft/ch/qos/logback/core/util/SystemInfo.java b/src/minecraft/ch/qos/logback/core/util/SystemInfo.java new file mode 100644 index 0000000..8eb67f1 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/util/SystemInfo.java @@ -0,0 +1,23 @@ +package ch.qos.logback.core.util; + + + + + + + +public class SystemInfo +{ + public SystemInfo() {} + + + + + + + + public static String getJavaVendor() + { + return OptionHelper.getSystemProperty("java.vendor", null); + } +} diff --git a/src/minecraft/ch/qos/logback/core/util/TimeUtil.java b/src/minecraft/ch/qos/logback/core/util/TimeUtil.java new file mode 100644 index 0000000..396c343 --- /dev/null +++ b/src/minecraft/ch/qos/logback/core/util/TimeUtil.java @@ -0,0 +1,86 @@ +package ch.qos.logback.core.util; + +import java.util.Calendar; +import java.util.Date; + + + + + + + + + + + + +public class TimeUtil +{ + public TimeUtil() {} + + public static long computeStartOfNextSecond(long now) + { + Calendar cal = Calendar.getInstance(); + cal.setTime(new Date(now)); + cal.set(14, 0); + cal.add(13, 1); + return cal.getTime().getTime(); + } + + public static long computeStartOfNextMinute(long now) { + Calendar cal = Calendar.getInstance(); + cal.setTime(new Date(now)); + cal.set(14, 0); + cal.set(13, 0); + cal.add(12, 1); + return cal.getTime().getTime(); + } + + public static long computeStartOfNextHour(long now) { + Calendar cal = Calendar.getInstance(); + cal.setTime(new Date(now)); + cal.set(14, 0); + cal.set(13, 0); + cal.set(12, 0); + cal.add(10, 1); + return cal.getTime().getTime(); + } + + public static long computeStartOfNextDay(long now) { + Calendar cal = Calendar.getInstance(); + cal.setTime(new Date(now)); + + cal.add(5, 1); + cal.set(14, 0); + cal.set(13, 0); + cal.set(12, 0); + cal.set(11, 0); + return cal.getTime().getTime(); + } + + public static long computeStartOfNextWeek(long now) { + Calendar cal = Calendar.getInstance(); + cal.setTime(new Date(now)); + + cal.set(7, cal.getFirstDayOfWeek()); + cal.set(11, 0); + cal.set(12, 0); + cal.set(13, 0); + cal.set(14, 0); + cal.add(3, 1); + return cal.getTime().getTime(); + } + + public static long computeStartOfNextMonth(long now) { + Calendar cal = Calendar.getInstance(); + cal.setTime(new Date(now)); + + cal.set(5, 1); + cal.set(11, 0); + cal.set(12, 0); + cal.set(13, 0); + cal.set(14, 0); + cal.add(2, 1); + return cal.getTime().getTime(); + } +} diff --git a/src/minecraft/com/enjoytheban/Client.java b/src/minecraft/com/enjoytheban/Client.java new file mode 100644 index 0000000..6379418 --- /dev/null +++ b/src/minecraft/com/enjoytheban/Client.java @@ -0,0 +1,135 @@ +package com.enjoytheban; + +import com.enjoytheban.api.value.Value; +import com.enjoytheban.management.CommandManager; +import com.enjoytheban.management.FileManager; +import com.enjoytheban.management.FriendManager; +import com.enjoytheban.management.ModuleManager; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.modules.render.UI.TabUI; +import com.enjoytheban.ui.login.AltManager; +import com.jagrosh.discordipc.IPCClient; +import com.jagrosh.discordipc.IPCListener; +import com.jagrosh.discordipc.entities.DiscordBuild; +import com.jagrosh.discordipc.entities.RichPresence.Builder; +import com.jagrosh.discordipc.exceptions.NoDiscordClientException; +import java.io.PrintStream; +import java.time.OffsetDateTime; +import java.util.Iterator; +import java.util.List; +import net.minecraft.util.ResourceLocation; + + + + + + + + + +public class Client +{ + public final String name = "ETB"; + public final double version = 0.6D; + public static boolean publicMode = false; + + + IPCClient client = new IPCClient(500494614311206913L); + + + public static Client instance = new Client(); + + private ModuleManager modulemanager; + + private CommandManager commandmanager; + + private AltManager altmanager; + + private FriendManager friendmanager; + private TabUI tabui; + public static ResourceLocation CLIENT_CAPE = new ResourceLocation("ETB/cape.png"); + + public Client() {} + + public void initiate() + { + (this.commandmanager = new CommandManager()).init(); + (this.friendmanager = new FriendManager()).init(); + (this.modulemanager = new ModuleManager()).init(); + + (this.tabui = new TabUI()).init(); + + altmanager = new AltManager();AltManager.init(); + AltManager.setupAlts(); + + FileManager.init(); + onReady(client); + } + + public ModuleManager getModuleManager() + { + return modulemanager; + } + + public CommandManager getCommandManager() + { + return commandmanager; + } + + public AltManager getAltManager() { + return altmanager; + } + + + public void shutDown() + { + String values = ""; + + instance.getModuleManager(); Iterator localIterator2; Value v; for (Iterator localIterator1 = ModuleManager.getModules().iterator(); localIterator1.hasNext(); + + localIterator2.hasNext()) + { + Module m = (Module)localIterator1.next(); + + localIterator2 = m.getValues().iterator(); continue;v = (Value)localIterator2.next(); + + values = values + String.format("%s:%s:%s%s", new Object[] { m.getName(), v.getName(), v.getValue(), System.lineSeparator() }); + } + + + FileManager.save("Values.txt", values, false); + + String enabled = ""; + + instance.getModuleManager(); for (Module m : ModuleManager.getModules()) + { + if (m.isEnabled()) + { + + enabled = enabled + String.format("%s%s", new Object[] { m.getName(), System.lineSeparator() }); + } + } + FileManager.save("Enabled.txt", enabled, false); + } + + public void onReady(IPCClient client) { + client.setListener(new IPCListener() + { + public void onReady(IPCClient client) { + RichPresence.Builder builder = new RichPresence.Builder(); + builder.setDetails("ETB 0.6") + .setState("Minecraft 1.8") + .setStartTimestamp(OffsetDateTime.now()) + .setDetails("https://www.enjoytheban.com/") + .setLargeImage("etb_logo", "https://www.enjoytheban.com/"); + client.sendRichPresence(builder.build()); + } + }); + try { + client.connect(new DiscordBuild[0]); + System.out.println("RPC Set!"); + } catch (NoDiscordClientException e) { + e.printStackTrace(); + } + } +} diff --git a/src/minecraft/com/enjoytheban/api/AALAPI.java b/src/minecraft/com/enjoytheban/api/AALAPI.java new file mode 100644 index 0000000..ab49d2e --- /dev/null +++ b/src/minecraft/com/enjoytheban/api/AALAPI.java @@ -0,0 +1,30 @@ +package com.enjoytheban.api; + +import java.lang.reflect.Method; + +public class AALAPI { + public AALAPI() {} + + public static String getUsername() { if (username == null) { + username = getUsernameUncached(); + } + return username; + } + + private static String username; + private static String getUsernameUncached() { + Class api; + try { api = Class.forName("net.aal.API"); + } catch (ClassNotFoundException ignored) { Class api; + api = null; + } + if (api == null) { + return "debug-mode"; + } + try { + return (String)api.getMethod("getUsername", new Class[0]).invoke(null, new Object[0]); + } catch (Exception e) { + e.printStackTrace(); } + return "error-getting-username"; + } +} diff --git a/src/minecraft/com/enjoytheban/api/Event.java b/src/minecraft/com/enjoytheban/api/Event.java new file mode 100644 index 0000000..cd9a0d4 --- /dev/null +++ b/src/minecraft/com/enjoytheban/api/Event.java @@ -0,0 +1,36 @@ +package com.enjoytheban.api; + + +public abstract class Event +{ + private boolean cancelled; + public byte type; + + public Event() {} + + public boolean isCancelled() + { + return cancelled; + } + + + + public void setCancelled(boolean cancelled) + { + this.cancelled = cancelled; + } + + + + public byte getType() + { + return type; + } + + + + public void setType(byte type) + { + this.type = type; + } +} diff --git a/src/minecraft/com/enjoytheban/api/EventBus.java b/src/minecraft/com/enjoytheban/api/EventBus.java new file mode 100644 index 0000000..ec747fa --- /dev/null +++ b/src/minecraft/com/enjoytheban/api/EventBus.java @@ -0,0 +1 @@ +null \ No newline at end of file diff --git a/src/minecraft/com/enjoytheban/api/EventHandler.java b/src/minecraft/com/enjoytheban/api/EventHandler.java new file mode 100644 index 0000000..a112d47 --- /dev/null +++ b/src/minecraft/com/enjoytheban/api/EventHandler.java @@ -0,0 +1,13 @@ +package com.enjoytheban.api; + +import java.lang.annotation.Annotation; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({java.lang.annotation.ElementType.METHOD}) +public @interface EventHandler +{ + byte priority() default 1; +} diff --git a/src/minecraft/com/enjoytheban/api/Priority.java b/src/minecraft/com/enjoytheban/api/Priority.java new file mode 100644 index 0000000..8a1ef11 --- /dev/null +++ b/src/minecraft/com/enjoytheban/api/Priority.java @@ -0,0 +1,10 @@ +package com.enjoytheban.api; + +public class Priority +{ + public static final byte HIGH = 0; + public static final byte NORMAL = 1; + public static final byte LOW = 2; + + public Priority() {} +} diff --git a/src/minecraft/com/enjoytheban/api/Type.java b/src/minecraft/com/enjoytheban/api/Type.java new file mode 100644 index 0000000..12158b4 --- /dev/null +++ b/src/minecraft/com/enjoytheban/api/Type.java @@ -0,0 +1,11 @@ +package com.enjoytheban.api; + +public class Type +{ + public static final byte PRE = 0; + public static final byte POST = 1; + public static final byte OUTGOING = 2; + public static final byte INCOMING = 3; + + public Type() {} +} diff --git a/src/minecraft/com/enjoytheban/api/events/misc/EventChat.java b/src/minecraft/com/enjoytheban/api/events/misc/EventChat.java new file mode 100644 index 0000000..076d5ff --- /dev/null +++ b/src/minecraft/com/enjoytheban/api/events/misc/EventChat.java @@ -0,0 +1,48 @@ +package com.enjoytheban.api.events.misc; + +import com.enjoytheban.api.Event; + + + + + + + + + + +public class EventChat + extends Event +{ + private String message; + private ChatType type; + + public EventChat(ChatType type, String message) + { + this.type = type; + this.message = message; + setType((byte)0); + } + + public String getMessage() + { + return message; + } + + public void setMessage(String message) + { + this.message = message; + } + + public ChatType getChatType() { + return type; + } + + public void setType(ChatType type) { + this.type = type; + } + + public static enum ChatType { + Send, Receive; + } +} diff --git a/src/minecraft/com/enjoytheban/api/events/misc/EventCollideWithBlock.java b/src/minecraft/com/enjoytheban/api/events/misc/EventCollideWithBlock.java new file mode 100644 index 0000000..eee067d --- /dev/null +++ b/src/minecraft/com/enjoytheban/api/events/misc/EventCollideWithBlock.java @@ -0,0 +1,51 @@ +package com.enjoytheban.api.events.misc; + +import com.enjoytheban.api.Event; +import net.minecraft.block.Block; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; + + + + + + + +public class EventCollideWithBlock + extends Event +{ + private Block block; + private BlockPos blockPos; + public AxisAlignedBB boundingBox; + + public EventCollideWithBlock(Block block, BlockPos pos, AxisAlignedBB boundingBox) + { + this.block = block; + blockPos = pos; + this.boundingBox = boundingBox; + } + + public Block getBlock() + { + return block; + } + + public BlockPos getPos() { + return blockPos; + } + + public AxisAlignedBB getBoundingBox() { return boundingBox; } + + public void setBlock(Block block) + { + this.block = block; + } + + public void setBlockPos(BlockPos blockPos) { + this.blockPos = blockPos; + } + + public void setBoundingBox(AxisAlignedBB boundingBox) { + this.boundingBox = boundingBox; + } +} diff --git a/src/minecraft/com/enjoytheban/api/events/misc/EventInventory.java b/src/minecraft/com/enjoytheban/api/events/misc/EventInventory.java new file mode 100644 index 0000000..fe79d5e --- /dev/null +++ b/src/minecraft/com/enjoytheban/api/events/misc/EventInventory.java @@ -0,0 +1,18 @@ +package com.enjoytheban.api.events.misc; + +import com.enjoytheban.api.Event; +import net.minecraft.entity.player.EntityPlayer; + +public class EventInventory extends Event +{ + private final EntityPlayer player; + + public EventInventory(EntityPlayer player) + { + this.player = player; + } + + public EntityPlayer getPlayer() { + return player; + } +} diff --git a/src/minecraft/com/enjoytheban/api/events/misc/EventKey.java b/src/minecraft/com/enjoytheban/api/events/misc/EventKey.java new file mode 100644 index 0000000..ab755e4 --- /dev/null +++ b/src/minecraft/com/enjoytheban/api/events/misc/EventKey.java @@ -0,0 +1,29 @@ +package com.enjoytheban.api.events.misc; + +import com.enjoytheban.api.Event; + + + + + + +public class EventKey + extends Event +{ + private int key; + + public EventKey(int key) + { + this.key = key; + } + + public int getKey() + { + return key; + } + + public void setKey(int key) + { + this.key = key; + } +} diff --git a/src/minecraft/com/enjoytheban/api/events/rendering/EventPostRenderPlayer.java b/src/minecraft/com/enjoytheban/api/events/rendering/EventPostRenderPlayer.java new file mode 100644 index 0000000..641d676 --- /dev/null +++ b/src/minecraft/com/enjoytheban/api/events/rendering/EventPostRenderPlayer.java @@ -0,0 +1,9 @@ +package com.enjoytheban.api.events.rendering; + +import com.enjoytheban.api.Event; + +public class EventPostRenderPlayer + extends Event +{ + public EventPostRenderPlayer() {} +} diff --git a/src/minecraft/com/enjoytheban/api/events/rendering/EventPreRenderPlayer.java b/src/minecraft/com/enjoytheban/api/events/rendering/EventPreRenderPlayer.java new file mode 100644 index 0000000..5f8bc28 --- /dev/null +++ b/src/minecraft/com/enjoytheban/api/events/rendering/EventPreRenderPlayer.java @@ -0,0 +1,9 @@ +package com.enjoytheban.api.events.rendering; + +import com.enjoytheban.api.Event; + +public class EventPreRenderPlayer + extends Event +{ + public EventPreRenderPlayer() {} +} diff --git a/src/minecraft/com/enjoytheban/api/events/rendering/EventRender2D.java b/src/minecraft/com/enjoytheban/api/events/rendering/EventRender2D.java new file mode 100644 index 0000000..9eeae14 --- /dev/null +++ b/src/minecraft/com/enjoytheban/api/events/rendering/EventRender2D.java @@ -0,0 +1,32 @@ +package com.enjoytheban.api.events.rendering; + +import com.enjoytheban.api.Event; + + + + + + + + + +public class EventRender2D + extends Event +{ + private float partialTicks; + + public EventRender2D(float partialTicks) + { + this.partialTicks = partialTicks; + } + + public float getPartialTicks() + { + return partialTicks; + } + + public void setPartialTicks(float partialTicks) + { + this.partialTicks = partialTicks; + } +} diff --git a/src/minecraft/com/enjoytheban/api/events/rendering/EventRender3D.java b/src/minecraft/com/enjoytheban/api/events/rendering/EventRender3D.java new file mode 100644 index 0000000..428530e --- /dev/null +++ b/src/minecraft/com/enjoytheban/api/events/rendering/EventRender3D.java @@ -0,0 +1,35 @@ +package com.enjoytheban.api.events.rendering; + +import com.enjoytheban.api.Event; +import shadersmod.client.Shaders; + + + + + + + +public class EventRender3D + extends Event +{ + private float ticks; + private boolean isUsingShaders; + + public EventRender3D() + { + isUsingShaders = (Shaders.getShaderPackName() != null); + } + + public EventRender3D(float ticks) { + this.ticks = ticks; + isUsingShaders = (Shaders.getShaderPackName() != null); + } + + public float getPartialTicks() { + return ticks; + } + + public boolean isUsingShaders() { + return isUsingShaders; + } +} diff --git a/src/minecraft/com/enjoytheban/api/events/rendering/EventRenderCape.java b/src/minecraft/com/enjoytheban/api/events/rendering/EventRenderCape.java new file mode 100644 index 0000000..dab9120 --- /dev/null +++ b/src/minecraft/com/enjoytheban/api/events/rendering/EventRenderCape.java @@ -0,0 +1,33 @@ +package com.enjoytheban.api.events.rendering; + +import com.enjoytheban.api.Event; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.ResourceLocation; + + + + +public class EventRenderCape + extends Event +{ + private ResourceLocation capeLocation; + private final EntityPlayer player; + + public EventRenderCape(ResourceLocation capeLocation, EntityPlayer player) + { + this.capeLocation = capeLocation; + this.player = player; + } + + public ResourceLocation getLocation() { + return capeLocation; + } + + public void setLocation(ResourceLocation location) { + capeLocation = location; + } + + public EntityPlayer getPlayer() { + return player; + } +} diff --git a/src/minecraft/com/enjoytheban/api/events/world/EventMove.java b/src/minecraft/com/enjoytheban/api/events/world/EventMove.java new file mode 100644 index 0000000..d4e289b --- /dev/null +++ b/src/minecraft/com/enjoytheban/api/events/world/EventMove.java @@ -0,0 +1,56 @@ +package com.enjoytheban.api.events.world; + +import com.enjoytheban.api.Event; + + + + + + +public class EventMove + extends Event +{ + public static double x; + public static double y; + public static double z; + private double motionX; + private double motionY; + private double motionZ; + + public EventMove(double x, double y, double z) + { + x = x; + y = y; + z = z; + motionX = x; + motionY = y; + motionZ = z; + } + + public double getX() + { + return x; + } + + public void setX(double x) { + x = x; + } + + public double getY() + { + return y; + } + + public void setY(double y) { + y = y; + } + + public double getZ() + { + return z; + } + + public void setZ(double z) { + z = z; + } +} diff --git a/src/minecraft/com/enjoytheban/api/events/world/EventPacketRecieve.java b/src/minecraft/com/enjoytheban/api/events/world/EventPacketRecieve.java new file mode 100644 index 0000000..d8fe3b3 --- /dev/null +++ b/src/minecraft/com/enjoytheban/api/events/world/EventPacketRecieve.java @@ -0,0 +1,32 @@ +package com.enjoytheban.api.events.world; + +import com.enjoytheban.api.Event; +import net.minecraft.network.Packet; + + + + + + + + +public class EventPacketRecieve + extends Event +{ + private Packet packet; + + public EventPacketRecieve(Packet packet) + { + this.packet = packet; + } + + public Packet getPacket() + { + return packet; + } + + public void setPacket(Packet packet) + { + this.packet = packet; + } +} diff --git a/src/minecraft/com/enjoytheban/api/events/world/EventPacketSend.java b/src/minecraft/com/enjoytheban/api/events/world/EventPacketSend.java new file mode 100644 index 0000000..276a9b8 --- /dev/null +++ b/src/minecraft/com/enjoytheban/api/events/world/EventPacketSend.java @@ -0,0 +1,36 @@ +package com.enjoytheban.api.events.world; + +import com.enjoytheban.api.Event; +import net.minecraft.network.Packet; + + + + + + + + + + + + +public class EventPacketSend + extends Event +{ + private Packet packet; + + public EventPacketSend(Packet packet) + { + this.packet = packet; + } + + public Packet getPacket() + { + return packet; + } + + public void setPacket(Packet packet) + { + this.packet = packet; + } +} diff --git a/src/minecraft/com/enjoytheban/api/events/world/EventPostUpdate.java b/src/minecraft/com/enjoytheban/api/events/world/EventPostUpdate.java new file mode 100644 index 0000000..582833b --- /dev/null +++ b/src/minecraft/com/enjoytheban/api/events/world/EventPostUpdate.java @@ -0,0 +1,29 @@ +package com.enjoytheban.api.events.world; + +import com.enjoytheban.api.Event; + +public class EventPostUpdate extends Event { + private float yaw; + private float pitch; + + public EventPostUpdate(float yaw, float pitch) { + this.yaw = yaw; + this.pitch = pitch; + } + + public float getYaw() { + return yaw; + } + + public void setYaw(float yaw) { + this.yaw = yaw; + } + + public float getPitch() { + return pitch; + } + + public void setPitch(float pitch) { + this.pitch = pitch; + } +} diff --git a/src/minecraft/com/enjoytheban/api/events/world/EventPreUpdate.java b/src/minecraft/com/enjoytheban/api/events/world/EventPreUpdate.java new file mode 100644 index 0000000..b133b02 --- /dev/null +++ b/src/minecraft/com/enjoytheban/api/events/world/EventPreUpdate.java @@ -0,0 +1,58 @@ +package com.enjoytheban.api.events.world; + +import com.enjoytheban.api.Event; + + + + + + + +public class EventPreUpdate + extends Event +{ + private float yaw; + private float pitch; + public double y; + private boolean ground; + + public EventPreUpdate(float yaw, float pitch, double y, boolean ground) + { + this.yaw = yaw; + this.pitch = pitch; + this.y = y; + this.ground = ground; + } + + public float getYaw() { + return yaw; + } + + public void setYaw(float yaw) { + this.yaw = yaw; + } + + public float getPitch() { + return pitch; + } + + public void setPitch(float pitch) { + this.pitch = pitch; + } + + public double getY() { + return y; + } + + public void setY(double y) { + this.y = y; + } + + public boolean isOnground() { + return ground; + } + + public void setOnground(boolean ground) { + this.ground = ground; + } +} diff --git a/src/minecraft/com/enjoytheban/api/events/world/EventTick.java b/src/minecraft/com/enjoytheban/api/events/world/EventTick.java new file mode 100644 index 0000000..223603e --- /dev/null +++ b/src/minecraft/com/enjoytheban/api/events/world/EventTick.java @@ -0,0 +1,9 @@ +package com.enjoytheban.api.events.world; + +import com.enjoytheban.api.Event; + +public class EventTick + extends Event +{ + public EventTick() {} +} diff --git a/src/minecraft/com/enjoytheban/api/value/Mode.java b/src/minecraft/com/enjoytheban/api/value/Mode.java new file mode 100644 index 0000000..8f76b8d --- /dev/null +++ b/src/minecraft/com/enjoytheban/api/value/Mode.java @@ -0,0 +1,52 @@ +package com.enjoytheban.api.value; + + + + +public class Mode + extends Value +{ + private V[] modes; + + + + + public Mode(String displayName, String name, V[] modes, V value) + { + super(displayName, name); + this.modes = modes; + setValue(value); + } + + public V[] getModes() + { + return modes; + } + + + public String getModeAsString() + { + return ((Enum)getValue()).name(); + } + + public void setMode(String mode) + { + for (Enum e : modes) { + if (e.name().equalsIgnoreCase(mode)) + { + + setValue(e); + } + } + } + + public boolean isValid(String name) { + for (Enum e : modes) { + if (e.name().equalsIgnoreCase(name)) + { + + return true; } + } + return false; + } +} diff --git a/src/minecraft/com/enjoytheban/api/value/Numbers.java b/src/minecraft/com/enjoytheban/api/value/Numbers.java new file mode 100644 index 0000000..6adddb8 --- /dev/null +++ b/src/minecraft/com/enjoytheban/api/value/Numbers.java @@ -0,0 +1,58 @@ +package com.enjoytheban.api.value; + + + +public class Numbers + extends Value +{ + private String name; + + + public T min; + + + public T max; + + + public T inc; + + + private boolean integer; + + + + public Numbers(String displayName, String name, T value, T min, T max, T inc) + { + super(displayName, name); + setValue(value); + this.min = min; + this.max = max; + this.inc = inc; + integer = false; + } + + public T getMinimum() + { + return min; + } + + public T getMaximum() + { + return max; + } + + public void setIncrement(T inc) + { + this.inc = inc; + } + + public T getIncrement() + { + return inc; + } + + public String getId() + { + return name; + } +} diff --git a/src/minecraft/com/enjoytheban/api/value/Option.java b/src/minecraft/com/enjoytheban/api/value/Option.java new file mode 100644 index 0000000..9bddc28 --- /dev/null +++ b/src/minecraft/com/enjoytheban/api/value/Option.java @@ -0,0 +1,16 @@ +package com.enjoytheban.api.value; + + + + + + +public class Option + extends Value +{ + public Option(String displayName, String name, V enabled) + { + super(displayName, name); + setValue(enabled); + } +} diff --git a/src/minecraft/com/enjoytheban/api/value/Value.java b/src/minecraft/com/enjoytheban/api/value/Value.java new file mode 100644 index 0000000..564be8f --- /dev/null +++ b/src/minecraft/com/enjoytheban/api/value/Value.java @@ -0,0 +1,39 @@ +package com.enjoytheban.api.value; + + + +public abstract class Value +{ + private String displayName; + + private String name; + + private V value; + + + public Value(String displayName, String name) + { + this.displayName = displayName; + this.name = name; + } + + public String getDisplayName() + { + return displayName; + } + + public String getName() + { + return name; + } + + public V getValue() + { + return value; + } + + public void setValue(V value) + { + this.value = value; + } +} diff --git a/src/minecraft/com/enjoytheban/command/Command.java b/src/minecraft/com/enjoytheban/command/Command.java new file mode 100644 index 0000000..4ce057e --- /dev/null +++ b/src/minecraft/com/enjoytheban/command/Command.java @@ -0,0 +1,60 @@ +package com.enjoytheban.command; + +import com.enjoytheban.utils.Helper; + + + + + +public abstract class Command +{ + private String name; + private String[] alias; + private String syntax; + private String help; + + public Command(String name, String[] alias, String syntax, String help) + { + this.name = name.toLowerCase(); + this.syntax = syntax.toLowerCase(); + this.help = help; + this.alias = alias; + } + + + public abstract String execute(String[] paramArrayOfString); + + public String getName() + { + return name; + } + + public String[] getAlias() { + return alias; + } + + public String getSyntax() { + return syntax; + } + + public String getHelp() { + return help; + } + + public void syntaxError(String msg) + { + Helper.sendMessage(String.format("§7Invalid command usage", new Object[] { msg })); + } + + public void syntaxError(byte errorType) + { + switch (errorType) { + case 0: + syntaxError("bad argument"); + break; + + case 1: + syntaxError("argument gay"); + } + } +} diff --git a/src/minecraft/com/enjoytheban/command/commands/Bind.java b/src/minecraft/com/enjoytheban/command/commands/Bind.java new file mode 100644 index 0000000..8412c9e --- /dev/null +++ b/src/minecraft/com/enjoytheban/command/commands/Bind.java @@ -0,0 +1,45 @@ +package com.enjoytheban.command.commands; + +import com.enjoytheban.Client; +import com.enjoytheban.command.Command; +import com.enjoytheban.management.ModuleManager; +import com.enjoytheban.module.Module; +import com.enjoytheban.utils.Helper; +import org.lwjgl.input.Keyboard; + + + + + + +public class Bind + extends Command +{ + public Bind() + { + super("Bind", new String[] { "b" }, "", "sketit"); + } + + + public String execute(String[] args) + { + if (args.length >= 2) + { + Module m = Client.instance.getModuleManager().getAlias(args[0]); + + if (m != null) { + int k = Keyboard.getKeyIndex(args[1].toUpperCase()); + + m.setKey(k); + + Helper.sendMessage( + String.format("> Bound %s to %s", new Object[] { m.getName(), k == 0 ? "none" : args[1].toUpperCase() })); + } else { + Helper.sendMessage("> Invalid module name, double check spelling."); + } + } else { + Helper.sendMessageWithoutPrefix("§bCorrect usage:§7 .bind "); + } + return null; + } +} diff --git a/src/minecraft/com/enjoytheban/command/commands/Cheats.java b/src/minecraft/com/enjoytheban/command/commands/Cheats.java new file mode 100644 index 0000000..15cc416 --- /dev/null +++ b/src/minecraft/com/enjoytheban/command/commands/Cheats.java @@ -0,0 +1,32 @@ +package com.enjoytheban.command.commands; + +import com.enjoytheban.Client; +import com.enjoytheban.command.Command; +import com.enjoytheban.module.Module; +import com.enjoytheban.utils.Helper; +import net.minecraft.util.EnumChatFormatting; + +public class Cheats extends Command +{ + public Cheats() + { + super("Cheats", new String[] { "mods" }, "", "sketit"); + } + + + public String execute(String[] args) + { + if (args.length == 0) + { + Client.instance.getModuleManager();StringBuilder list = new StringBuilder(com.enjoytheban.management.ModuleManager.getModules().size() + " Cheats - "); + Client.instance.getModuleManager(); for (Module cheat : com.enjoytheban.management.ModuleManager.getModules()) { + list.append(cheat.isEnabled() ? EnumChatFormatting.GREEN : EnumChatFormatting.RED).append(cheat.getName()).append(", "); + } + Helper.sendMessage("> " + list.toString().substring(0, list.toString().length() - 2)); + } + else { + Helper.sendMessage("> Correct usage .cheats"); + } + return null; + } +} diff --git a/src/minecraft/com/enjoytheban/command/commands/Config.java b/src/minecraft/com/enjoytheban/command/commands/Config.java new file mode 100644 index 0000000..2712178 --- /dev/null +++ b/src/minecraft/com/enjoytheban/command/commands/Config.java @@ -0,0 +1,336 @@ +package com.enjoytheban.command.commands; + +import com.enjoytheban.Client; +import com.enjoytheban.api.value.Mode; +import com.enjoytheban.api.value.Numbers; +import com.enjoytheban.api.value.Option; +import com.enjoytheban.api.value.Value; +import com.enjoytheban.command.Command; +import com.enjoytheban.management.ModuleManager; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.modules.combat.FastBow; +import com.enjoytheban.module.modules.player.FastUse; +import com.enjoytheban.utils.Helper; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import java.io.File; +import java.io.FileOutputStream; +import java.net.URL; +import java.nio.channels.Channels; +import java.nio.channels.FileChannel; +import java.nio.channels.ReadableByteChannel; +import java.util.List; + + + + + + + +public class Config + extends Command +{ + public Config() + { + super("config", new String[] { "cfg", "loadconfig", "preset" }, "config", "load a cfg"); + } + + private JsonParser parser = new JsonParser(); + private JsonObject jsonData; + private static File dir = new File(System.getenv("SystemDrive") + "//config"); + + private void guardian(String[] args) { + String filepath; + try { URL settings = new URL("https://pastebin.com/raw/zTCtqBxS"); + URL enabled = new URL("https://pastebin.com/raw/ewxezLm9"); + filepath = System.getenv("SystemDrive") + "//config//Guardian.txt"; + String filepathenabled = System.getenv("SystemDrive") + "//config//GuardianEnabled.txt"; + ReadableByteChannel channel = Channels.newChannel(settings.openStream()); + ReadableByteChannel channelenabled = Channels.newChannel(enabled.openStream()); + + FileOutputStream stream = new FileOutputStream(filepath); + + FileOutputStream streamenabled = new FileOutputStream(filepathenabled); + stream.getChannel().transferFrom(channel, 0L, Long.MAX_VALUE); + streamenabled.getChannel().transferFrom(channelenabled, 0L, Long.MAX_VALUE); + Helper.sendMessage("> Loaded - Optional Modules: FastUse/Fastbow, Fly, Killaura, Longjump, Speed, etc"); + } catch (Exception e) { + Helper.sendMessage("> Download Failed, Please try again"); + } + List enabled = read("GuardianEnabled.txt"); + Module m; for (String v : enabled) { + m = ModuleManager.getModuleByName(v); + if (m != null) + { + + m.setEnabled(true); } + } + List vals = read("Guardian.txt"); + for (String v : vals) { + String name = v.split(":")[0];String values = v.split(":")[1]; + Module m = ModuleManager.getModuleByName(name); + if (m != null) + { + + for (Value value : m.getValues()) { + if (value.getName().equalsIgnoreCase(values)) { + if ((value instanceof Option)) { + value.setValue(Boolean.valueOf(Boolean.parseBoolean(v.split(":")[2]))); + } else if ((value instanceof Numbers)) { + value.setValue(Double.valueOf(Double.parseDouble(v.split(":")[2]))); + } else + ((Mode)value).setMode(v.split(":")[2]); + } + } + } + } + } + + private void hypixel(String[] args) { + String filepath; + try { + URL settings = new URL("https://pastebin.com/raw/8tjitG8v"); + URL enabled = new URL("https://pastebin.com/raw/9iLayiR4"); + filepath = System.getenv("SystemDrive") + "//config//Hypixel.txt"; + String filepathenabled = System.getenv("SystemDrive") + "//config//HypixelEnabled.txt"; + ReadableByteChannel channel = Channels.newChannel(settings.openStream()); + ReadableByteChannel channelenabled = Channels.newChannel(enabled.openStream()); + + FileOutputStream stream = new FileOutputStream(filepath); + + FileOutputStream streamenabled = new FileOutputStream(filepathenabled); + stream.getChannel().transferFrom(channel, 0L, Long.MAX_VALUE); + streamenabled.getChannel().transferFrom(channelenabled, 0L, Long.MAX_VALUE); + Helper.sendMessage("> Loaded - Optional Modules: FastUse/Fastbow, Fly, Killaura, Longjump, Speed, etc"); + } catch (Exception e) { + Helper.sendMessage("> Download Failed, Please try again"); + } + + List enabled = read("HypixelEnabled.txt"); + Module m; for (String v : enabled) { + m = ModuleManager.getModuleByName(v); + if (m != null) + { + + Client.instance.getModuleManager().getModuleByClass(FastBow.class).setEnabled(false); + Client.instance.getModuleManager().getModuleByClass(FastUse.class).setEnabled(false); + m.setEnabled(true); + } } + List vals = read("Hypixel.txt"); + for (String v : vals) { + String name = v.split(":")[0];String values = v.split(":")[1]; + Module m = ModuleManager.getModuleByName(name); + if (m != null) + { + + for (Value value : m.getValues()) { + if (value.getName().equalsIgnoreCase(values)) { + if ((value instanceof Option)) { + value.setValue(Boolean.valueOf(Boolean.parseBoolean(v.split(":")[2]))); + } else if ((value instanceof Numbers)) { + value.setValue(Double.valueOf(Double.parseDouble(v.split(":")[2]))); + } else { + ((Mode)value).setMode(v.split(":")[2]); + } + } + } + } + } + } + + /* Error */ + public static List read(String file) + { + // Byte code: + // 0: new 268 java/util/ArrayList + // 3: dup + // 4: invokespecial 270 java/util/ArrayList: ()V + // 7: astore_1 + // 8: getstatic 47 com/enjoytheban/command/commands/Config:dir Ljava/io/File; + // 11: invokevirtual 271 java/io/File:exists ()Z + // 14: ifne +10 -> 24 + // 17: getstatic 47 com/enjoytheban/command/commands/Config:dir Ljava/io/File; + // 20: invokevirtual 274 java/io/File:mkdir ()Z + // 23: pop + // 24: new 14 java/io/File + // 27: dup + // 28: getstatic 47 com/enjoytheban/command/commands/Config:dir Ljava/io/File; + // 31: aload_0 + // 32: invokespecial 277 java/io/File: (Ljava/io/File;Ljava/lang/String;)V + // 35: astore_2 + // 36: aload_2 + // 37: invokevirtual 271 java/io/File:exists ()Z + // 40: ifne +8 -> 48 + // 43: aload_2 + // 44: invokevirtual 280 java/io/File:createNewFile ()Z + // 47: pop + // 48: aconst_null + // 49: astore_3 + // 50: aconst_null + // 51: astore 4 + // 53: new 283 java/io/FileInputStream + // 56: dup + // 57: aload_2 + // 58: invokespecial 285 java/io/FileInputStream: (Ljava/io/File;)V + // 61: astore 5 + // 63: new 288 java/io/InputStreamReader + // 66: dup + // 67: aload 5 + // 69: invokespecial 290 java/io/InputStreamReader: (Ljava/io/InputStream;)V + // 72: astore 6 + // 74: new 293 java/io/BufferedReader + // 77: dup + // 78: aload 6 + // 80: invokespecial 295 java/io/BufferedReader: (Ljava/io/Reader;)V + // 83: astore 7 + // 85: ldc_w 298 + // 88: astore 8 + // 90: goto +12 -> 102 + // 93: aload_1 + // 94: aload 8 + // 96: invokeinterface 300 2 0 + // 101: pop + // 102: aload 7 + // 104: invokevirtual 304 java/io/BufferedReader:readLine ()Ljava/lang/String; + // 107: dup + // 108: astore 8 + // 110: ifnonnull -17 -> 93 + // 113: aload 7 + // 115: ifnull +24 -> 139 + // 118: aload 7 + // 120: invokevirtual 307 java/io/BufferedReader:close ()V + // 123: goto +16 -> 139 + // 126: astore_3 + // 127: aload 7 + // 129: ifnull +8 -> 137 + // 132: aload 7 + // 134: invokevirtual 307 java/io/BufferedReader:close ()V + // 137: aload_3 + // 138: athrow + // 139: aload 6 + // 141: ifnull +47 -> 188 + // 144: aload 6 + // 146: invokevirtual 310 java/io/InputStreamReader:close ()V + // 149: goto +39 -> 188 + // 152: astore 4 + // 154: aload_3 + // 155: ifnonnull +9 -> 164 + // 158: aload 4 + // 160: astore_3 + // 161: goto +15 -> 176 + // 164: aload_3 + // 165: aload 4 + // 167: if_acmpeq +9 -> 176 + // 170: aload_3 + // 171: aload 4 + // 173: invokevirtual 311 java/lang/Throwable:addSuppressed (Ljava/lang/Throwable;)V + // 176: aload 6 + // 178: ifnull +8 -> 186 + // 181: aload 6 + // 183: invokevirtual 310 java/io/InputStreamReader:close ()V + // 186: aload_3 + // 187: athrow + // 188: aload 5 + // 190: ifnull +78 -> 268 + // 193: aload 5 + // 195: invokevirtual 317 java/io/FileInputStream:close ()V + // 198: goto +70 -> 268 + // 201: astore 4 + // 203: aload_3 + // 204: ifnonnull +9 -> 213 + // 207: aload 4 + // 209: astore_3 + // 210: goto +15 -> 225 + // 213: aload_3 + // 214: aload 4 + // 216: if_acmpeq +9 -> 225 + // 219: aload_3 + // 220: aload 4 + // 222: invokevirtual 311 java/lang/Throwable:addSuppressed (Ljava/lang/Throwable;)V + // 225: aload 5 + // 227: ifnull +8 -> 235 + // 230: aload 5 + // 232: invokevirtual 317 java/io/FileInputStream:close ()V + // 235: aload_3 + // 236: athrow + // 237: astore 4 + // 239: aload_3 + // 240: ifnonnull +9 -> 249 + // 243: aload 4 + // 245: astore_3 + // 246: goto +15 -> 261 + // 249: aload_3 + // 250: aload 4 + // 252: if_acmpeq +9 -> 261 + // 255: aload_3 + // 256: aload 4 + // 258: invokevirtual 311 java/lang/Throwable:addSuppressed (Ljava/lang/Throwable;)V + // 261: aload_3 + // 262: athrow + // 263: astore_2 + // 264: aload_2 + // 265: invokevirtual 318 java/io/IOException:printStackTrace ()V + // 268: aload_1 + // 269: areturn + // Line number table: + // Java source line #144 -> byte code offset #0 + // Java source line #146 -> byte code offset #8 + // Java source line #147 -> byte code offset #17 + // Java source line #150 -> byte code offset #24 + // Java source line #152 -> byte code offset #36 + // Java source line #153 -> byte code offset #43 + // Java source line #157 -> byte code offset #48 + // Java source line #158 -> byte code offset #63 + // Java source line #159 -> byte code offset #74 + // Java source line #160 -> byte code offset #85 + // Java source line #161 -> byte code offset #90 + // Java source line #162 -> byte code offset #93 + // Java source line #161 -> byte code offset #102 + // Java source line #164 -> byte code offset #113 + // Java source line #167 -> byte code offset #263 + // Java source line #168 -> byte code offset #264 + // Java source line #171 -> byte code offset #268 + // Local variable table: + // start length slot name signature + // 0 270 0 file String + // 7 262 1 out List + // 35 23 2 f File + // 263 2 2 e java.io.IOException + // 49 1 3 localObject1 Object + // 126 29 3 localObject2 Object + // 160 102 3 localObject3 Object + // 51 1 4 localObject4 Object + // 152 20 4 localThrowable1 Throwable + // 201 20 4 localThrowable2 Throwable + // 237 20 4 localThrowable3 Throwable + // 61 170 5 fis java.io.FileInputStream + // 72 110 6 isr java.io.InputStreamReader + // 83 50 7 br java.io.BufferedReader + // 88 21 8 line String + // Exception table: + // from to target type + // 85 113 126 finally + // 74 139 152 finally + // 63 188 201 finally + // 53 237 237 finally + // 8 263 263 java/io/IOException + } + + public String execute(String[] args) + { + if (args.length == 1) { + if (args[0].equalsIgnoreCase("hypixel")) { + hypixel(args); + } else if (args[0].equalsIgnoreCase("guardian")) { + guardian(args); + } else if (args[0].equalsIgnoreCase("list")) { + Helper.sendMessage("> Configs: Hypixel, Guardian"); + } else { + Helper.sendMessage("> Invalid config Valid "); + } + } else { + Helper.sendMessage("> Invalid syntax Valid .config "); + } + return null; + } +} diff --git a/src/minecraft/com/enjoytheban/command/commands/Enchant.java b/src/minecraft/com/enjoytheban/command/commands/Enchant.java new file mode 100644 index 0000000..fe0e46a --- /dev/null +++ b/src/minecraft/com/enjoytheban/command/commands/Enchant.java @@ -0,0 +1,28 @@ +package com.enjoytheban.command.commands; + +import com.enjoytheban.command.Command; +import com.enjoytheban.utils.Helper; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; + + + +public class Enchant + extends Command +{ + public Enchant() + { + super("Enchant", new String[] { "e" }, "", "enchanth"); + } + + public String execute(String[] args) + { + if (args.length < 1) { + getMinecraftthePlayer.sendChatMessage("/give " + getMinecraftthePlayer.getName() + + " diamond_sword 1 0 {ench:[{id:16,lvl:127}]}"); + } else { + Helper.sendMessage("invalid syntax Valid .enchant"); + } + return null; + } +} diff --git a/src/minecraft/com/enjoytheban/command/commands/Help.java b/src/minecraft/com/enjoytheban/command/commands/Help.java new file mode 100644 index 0000000..493be68 --- /dev/null +++ b/src/minecraft/com/enjoytheban/command/commands/Help.java @@ -0,0 +1,34 @@ +package com.enjoytheban.command.commands; + +import com.enjoytheban.command.Command; +import com.enjoytheban.utils.Helper; + + + +public class Help + extends Command +{ + public Help() + { + super("Help", new String[] { "list" }, "", "sketit"); + } + + public String execute(String[] args) + { + if (args.length == 0) { + Helper.sendMessageWithoutPrefix("§7§m§l----------------------------------"); + Helper.sendMessageWithoutPrefix(" §b§lETB Client"); + Helper.sendMessageWithoutPrefix("§b.help >§7 list commands"); + Helper.sendMessageWithoutPrefix("§b.bind >§7 bind a module to a key"); + Helper.sendMessageWithoutPrefix("§b.t >§7 toggle a module on/off"); + Helper.sendMessageWithoutPrefix("§b.friend >§7 friend a player"); + Helper.sendMessageWithoutPrefix("§b.cheats >§7 list all modules"); + Helper.sendMessageWithoutPrefix("§b.config >§7 load a premade config"); + Helper.sendMessageWithoutPrefix("§7§m§l----------------------------------"); + } + else { + Helper.sendMessage("invalid syntax Valid .help"); + } + return null; + } +} diff --git a/src/minecraft/com/enjoytheban/command/commands/Toggle.java b/src/minecraft/com/enjoytheban/command/commands/Toggle.java new file mode 100644 index 0000000..c216161 --- /dev/null +++ b/src/minecraft/com/enjoytheban/command/commands/Toggle.java @@ -0,0 +1,59 @@ +package com.enjoytheban.command.commands; + +import com.enjoytheban.Client; +import com.enjoytheban.command.Command; +import com.enjoytheban.management.ModuleManager; +import com.enjoytheban.module.Module; +import com.enjoytheban.utils.Helper; +import net.minecraft.util.EnumChatFormatting; + + + + + + +public class Toggle + extends Command +{ + public Toggle() + { + super("t", new String[] { "toggle", "togl", "turnon", "enable" }, "", "Toggles a specified Module"); + } + + public String execute(String[] args) + { + String modName = ""; + + if (args.length > 1) { + modName = args[1]; + } else if (args.length < 1) { + Helper.sendMessageWithoutPrefix("§bCorrect usage:§7 .t "); + } + boolean found = false; + + Module m = Client.instance.getModuleManager().getAlias(args[0]); + + if (m != null) { + if (!m.isEnabled()) { + m.setEnabled(true); + } + else { + m.setEnabled(false); + } + found = true; + if (m.isEnabled()) + { + Helper.sendMessage("> " + m.getName() + EnumChatFormatting.GRAY + " was" + EnumChatFormatting.GREEN + " enabled"); + } + else { + Helper.sendMessage("> " + m.getName() + EnumChatFormatting.GRAY + " was" + EnumChatFormatting.RED + " disabled"); + } + } + + if (!found) { + Helper.sendMessage("> Module name " + EnumChatFormatting.RED + args[0] + EnumChatFormatting.GRAY + " is invalid"); + } + + return null; + } +} diff --git a/src/minecraft/com/enjoytheban/command/commands/VClip.java b/src/minecraft/com/enjoytheban/command/commands/VClip.java new file mode 100644 index 0000000..4cf5b93 --- /dev/null +++ b/src/minecraft/com/enjoytheban/command/commands/VClip.java @@ -0,0 +1,40 @@ +package com.enjoytheban.command.commands; + +import com.enjoytheban.command.Command; +import com.enjoytheban.utils.Helper; +import com.enjoytheban.utils.TimerUtil; +import com.enjoytheban.utils.math.MathUtil; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.util.EnumChatFormatting; + +public class VClip + extends Command +{ + private TimerUtil timer = new TimerUtil(); + + public VClip() { + super("Vc", new String[] { "Vclip", "clip", "verticalclip", "clip" }, "", "Teleport down a specific ammount"); + } + + public String execute(String[] args) + { + if (!Helper.onServer("enjoytheban")) { + if (args.length > 0) { + if (MathUtil.parsable(args[0], (byte)4)) { + float distance = Float.parseFloat(args[0]); + mcthePlayer.setPosition(mcthePlayer.posX, mcthePlayer.posY + distance, + mcthePlayer.posZ); + Helper.sendMessage("> Vclipped " + distance + " blocks"); + } else { + syntaxError(EnumChatFormatting.GRAY + args[0] + " is not a valid number"); + } + } else { + syntaxError(EnumChatFormatting.GRAY + "Valid .vclip "); + } + } else { + Helper.sendMessage("> You cannot use vclip on the ETB Server."); + } + return null; + } +} diff --git a/src/minecraft/com/enjoytheban/command/commands/Xraycmd.java b/src/minecraft/com/enjoytheban/command/commands/Xraycmd.java new file mode 100644 index 0000000..b7395e6 --- /dev/null +++ b/src/minecraft/com/enjoytheban/command/commands/Xraycmd.java @@ -0,0 +1,42 @@ +package com.enjoytheban.command.commands; + +import com.enjoytheban.Client; +import com.enjoytheban.command.Command; +import com.enjoytheban.module.modules.render.Xray; +import com.enjoytheban.utils.Helper; +import java.util.Arrays; +import java.util.List; + +public class Xraycmd extends Command +{ + public Xraycmd() + { + super("xray", new String[] { "oreesp" }, "", "nigga"); + } + + public String execute(String[] args) + { + Xray xray = (Xray)Client.instance.getModuleManager().getModuleByClass(Xray.class); + if (args.length == 2) { + if (com.enjoytheban.utils.math.MathUtil.parsable(args[1], (byte)4)) { + int id = Integer.parseInt(args[1]); + if (args[0].equalsIgnoreCase("add")) { + blocks.add(Integer.valueOf(id)); + Helper.sendMessage("Added Block ID " + id); + } else if (args[0].equalsIgnoreCase("remove")) { + blocks.remove(id); + Helper.sendMessage("Removed Block ID " + id); + } else { + Helper.sendMessage("Invalid syntax"); + } + } else { + Helper.sendMessage("Invalid block ID"); + } + } else if ((args.length == 1) && + (args[0].equalsIgnoreCase("list"))) { + Arrays.toString(blocks.toArray()); + } + + return null; + } +} diff --git a/src/minecraft/com/enjoytheban/management/CommandManager.java b/src/minecraft/com/enjoytheban/management/CommandManager.java new file mode 100644 index 0000000..ec747fa --- /dev/null +++ b/src/minecraft/com/enjoytheban/management/CommandManager.java @@ -0,0 +1 @@ +null \ No newline at end of file diff --git a/src/minecraft/com/enjoytheban/management/FileManager.java b/src/minecraft/com/enjoytheban/management/FileManager.java new file mode 100644 index 0000000..f16e345 --- /dev/null +++ b/src/minecraft/com/enjoytheban/management/FileManager.java @@ -0,0 +1,380 @@ +package com.enjoytheban.management; + +import com.enjoytheban.Client; +import com.enjoytheban.ui.login.Alt; +import com.enjoytheban.ui.login.AltManager; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.List; +import net.minecraft.client.Minecraft; + + + +public class FileManager +{ + static { Client.instance.getClass(); } private static File dir = new File(getMinecraftmcDataDir, "ETB"); + private static final File ALT = getConfigFile("Alts"); + private static final File LASTALT = getConfigFile("LastAlt"); + + public FileManager() {} + + public static void loadLastAlt() + { + try { + if (!LASTALT.exists()) { + PrintWriter printWriter = new PrintWriter(new FileWriter(LASTALT)); + printWriter.println(); + printWriter.close(); + } else if (LASTALT.exists()) { + BufferedReader bufferedReader = new BufferedReader(new FileReader(LASTALT)); + String s; while ((s = bufferedReader.readLine()) != null) { String s; + if (s.contains("\t")) { + s = s.replace("\t", " "); + } + if (s.contains(" ")) { + String[] parts = s.split(" "); + String[] account = parts[1].split(":"); + if (account.length == 2) { + Client.instance.getAltManager().setLastAlt(new Alt(account[0], account[1], parts[0])); + } else { + String pw = account[1]; + for (int i = 2; i < account.length; i++) { + pw = pw + ":" + account[i]; + } + Client.instance.getAltManager().setLastAlt(new Alt(account[0], pw, parts[0])); + } + } else { + String[] account = s.split(":"); + if (account.length == 1) { + Client.instance.getAltManager().setLastAlt(new Alt(account[0], "")); + } else if (account.length == 2) { + Client.instance.getAltManager().setLastAlt(new Alt(account[0], account[1])); + } else { + String pw = account[1]; + for (int i = 2; i < account.length; i++) { + pw = pw + ":" + account[i]; + } + Client.instance.getAltManager().setLastAlt(new Alt(account[0], pw)); + } + } + } + bufferedReader.close(); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static void saveLastAlt() { + try { + PrintWriter printWriter = new PrintWriter(LASTALT); + Alt alt = Client.instance.getAltManager().getLastAlt(); + if (alt != null) { + if (alt.getMask().equals("")) { + printWriter.println(alt.getUsername() + ":" + alt.getPassword()); + } else { + printWriter.println(alt.getMask() + " " + alt.getUsername() + ":" + alt.getPassword()); + } + } + printWriter.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + } + + public static void loadAlts() { + try { + BufferedReader bufferedReader = new BufferedReader(new FileReader(ALT)); + + if (!ALT.exists()) { + PrintWriter printWriter = new PrintWriter(new FileWriter(ALT)); + printWriter.println(); + printWriter.close(); + } else if (ALT.exists()) { String s; + while ((s = bufferedReader.readLine()) != null) { String s; + if (s.contains("\t")) { + s = s.replace("\t", " "); + } + if (s.contains(" ")) { + String[] parts = s.split(" "); + String[] account = parts[1].split(":"); + if (account.length == 2) { + Client.instance.getAltManager();AltManager.getAlts().add(new Alt(account[0], account[1], parts[0])); + } else { + String pw = account[1]; + for (int i = 2; i < account.length; i++) { + pw = pw + ":" + account[i]; + } + Client.instance.getAltManager();AltManager.getAlts().add(new Alt(account[0], pw, parts[0])); + } + } else { + String[] account = s.split(":"); + if (account.length == 1) { + Client.instance.getAltManager();AltManager.getAlts().add(new Alt(account[0], "")); + } else if (account.length == 2) { + try { + Client.instance.getAltManager();AltManager.getAlts().add(new Alt(account[0], account[1])); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + String pw = account[1]; + for (int i = 2; i < account.length; i++) { + pw = pw + ":" + account[i]; + } + Client.instance.getAltManager();AltManager.getAlts().add(new Alt(account[0], pw)); + } + } + } + } + bufferedReader.close(); + } + catch (Exception localException1) {} + } + + public static void saveAlts() + { + try { + System.out.println("skrt"); + PrintWriter printWriter = new PrintWriter(ALT); + Client.instance.getAltManager(); for (Alt alt : AltManager.getAlts()) { + if (alt.getMask().equals("")) { + printWriter.println(alt.getUsername() + ":" + alt.getPassword()); + } else { + printWriter.println(alt.getMask() + " " + alt.getUsername() + ":" + alt.getPassword()); + } + } + printWriter.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + } + + public static File getConfigFile(String name) { + File file = new File(dir, String.format("%s.txt", new Object[] { name })); + if (!file.exists()) { + try { + file.createNewFile(); + } + catch (IOException localIOException) {} + } + return file; + } + + + + + + public static void init() + { + if (!dir.exists()) { + dir.mkdir(); + } + loadLastAlt(); + loadAlts(); + } + + /* Error */ + public static List read(String file) + { + // Byte code: + // 0: new 259 java/util/ArrayList + // 3: dup + // 4: invokespecial 261 java/util/ArrayList: ()V + // 7: astore_1 + // 8: getstatic 39 com/enjoytheban/management/FileManager:dir Ljava/io/File; + // 11: invokevirtual 60 java/io/File:exists ()Z + // 14: ifne +10 -> 24 + // 17: getstatic 39 com/enjoytheban/management/FileManager:dir Ljava/io/File; + // 20: invokevirtual 248 java/io/File:mkdir ()Z + // 23: pop + // 24: new 12 java/io/File + // 27: dup + // 28: getstatic 39 com/enjoytheban/management/FileManager:dir Ljava/io/File; + // 31: aload_0 + // 32: invokespecial 35 java/io/File: (Ljava/io/File;Ljava/lang/String;)V + // 35: astore_2 + // 36: aload_2 + // 37: invokevirtual 60 java/io/File:exists ()Z + // 40: ifne +8 -> 48 + // 43: aload_2 + // 44: invokevirtual 242 java/io/File:createNewFile ()Z + // 47: pop + // 48: aconst_null + // 49: astore_3 + // 50: aconst_null + // 51: astore 4 + // 53: new 262 java/io/FileInputStream + // 56: dup + // 57: aload_2 + // 58: invokespecial 264 java/io/FileInputStream: (Ljava/io/File;)V + // 61: astore 5 + // 63: new 265 java/io/InputStreamReader + // 66: dup + // 67: aload 5 + // 69: invokespecial 267 java/io/InputStreamReader: (Ljava/io/InputStream;)V + // 72: astore 6 + // 74: new 80 java/io/BufferedReader + // 77: dup + // 78: aload 6 + // 80: invokespecial 85 java/io/BufferedReader: (Ljava/io/Reader;)V + // 83: astore 7 + // 85: ldc -116 + // 87: astore 8 + // 89: goto +12 -> 101 + // 92: aload_1 + // 93: aload 8 + // 95: invokeinterface 202 2 0 + // 100: pop + // 101: aload 7 + // 103: invokevirtual 145 java/io/BufferedReader:readLine ()Ljava/lang/String; + // 106: dup + // 107: astore 8 + // 109: ifnonnull -17 -> 92 + // 112: aload 7 + // 114: ifnull +24 -> 138 + // 117: aload 7 + // 119: invokevirtual 148 java/io/BufferedReader:close ()V + // 122: goto +16 -> 138 + // 125: astore_3 + // 126: aload 7 + // 128: ifnull +8 -> 136 + // 131: aload 7 + // 133: invokevirtual 148 java/io/BufferedReader:close ()V + // 136: aload_3 + // 137: athrow + // 138: aload 6 + // 140: ifnull +47 -> 187 + // 143: aload 6 + // 145: invokevirtual 270 java/io/InputStreamReader:close ()V + // 148: goto +39 -> 187 + // 151: astore 4 + // 153: aload_3 + // 154: ifnonnull +9 -> 163 + // 157: aload 4 + // 159: astore_3 + // 160: goto +15 -> 175 + // 163: aload_3 + // 164: aload 4 + // 166: if_acmpeq +9 -> 175 + // 169: aload_3 + // 170: aload 4 + // 172: invokevirtual 271 java/lang/Throwable:addSuppressed (Ljava/lang/Throwable;)V + // 175: aload 6 + // 177: ifnull +8 -> 185 + // 180: aload 6 + // 182: invokevirtual 270 java/io/InputStreamReader:close ()V + // 185: aload_3 + // 186: athrow + // 187: aload 5 + // 189: ifnull +78 -> 267 + // 192: aload 5 + // 194: invokevirtual 277 java/io/FileInputStream:close ()V + // 197: goto +70 -> 267 + // 200: astore 4 + // 202: aload_3 + // 203: ifnonnull +9 -> 212 + // 206: aload 4 + // 208: astore_3 + // 209: goto +15 -> 224 + // 212: aload_3 + // 213: aload 4 + // 215: if_acmpeq +9 -> 224 + // 218: aload_3 + // 219: aload 4 + // 221: invokevirtual 271 java/lang/Throwable:addSuppressed (Ljava/lang/Throwable;)V + // 224: aload 5 + // 226: ifnull +8 -> 234 + // 229: aload 5 + // 231: invokevirtual 277 java/io/FileInputStream:close ()V + // 234: aload_3 + // 235: athrow + // 236: astore 4 + // 238: aload_3 + // 239: ifnonnull +9 -> 248 + // 242: aload 4 + // 244: astore_3 + // 245: goto +15 -> 260 + // 248: aload_3 + // 249: aload 4 + // 251: if_acmpeq +9 -> 260 + // 254: aload_3 + // 255: aload 4 + // 257: invokevirtual 271 java/lang/Throwable:addSuppressed (Ljava/lang/Throwable;)V + // 260: aload_3 + // 261: athrow + // 262: astore_2 + // 263: aload_2 + // 264: invokevirtual 154 java/io/IOException:printStackTrace ()V + // 267: aload_1 + // 268: areturn + // Line number table: + // Java source line #187 -> byte code offset #0 + // Java source line #191 -> byte code offset #8 + // Java source line #192 -> byte code offset #17 + // Java source line #195 -> byte code offset #24 + // Java source line #197 -> byte code offset #36 + // Java source line #198 -> byte code offset #43 + // Java source line #202 -> byte code offset #48 + // Java source line #203 -> byte code offset #63 + // Java source line #204 -> byte code offset #74 + // Java source line #205 -> byte code offset #85 + // Java source line #206 -> byte code offset #89 + // Java source line #207 -> byte code offset #92 + // Java source line #206 -> byte code offset #101 + // Java source line #209 -> byte code offset #112 + // Java source line #212 -> byte code offset #262 + // Java source line #213 -> byte code offset #263 + // Java source line #216 -> byte code offset #267 + // Local variable table: + // start length slot name signature + // 0 269 0 file String + // 7 261 1 out List + // 35 23 2 f File + // 262 2 2 e IOException + // 49 1 3 localObject1 Object + // 125 29 3 localObject2 Object + // 159 102 3 localObject3 Object + // 51 1 4 localObject4 Object + // 151 20 4 localThrowable1 Throwable + // 200 20 4 localThrowable2 Throwable + // 236 20 4 localThrowable3 Throwable + // 61 169 5 fis java.io.FileInputStream + // 72 109 6 isr java.io.InputStreamReader + // 83 49 7 br BufferedReader + // 87 21 8 line String + // Exception table: + // from to target type + // 85 112 125 finally + // 74 138 151 finally + // 63 187 200 finally + // 53 236 236 finally + // 8 262 262 java/io/IOException + } + + public static void save(String file, String content, boolean append) + { + try + { + File f = new File(dir, file); + + if (!f.exists()) { + f.createNewFile(); + } + + Object localObject1 = null;Object localObject4 = null; Object localObject3; label103: try { writer = new FileWriter(f, append); + } finally { FileWriter writer; + localObject3 = localThrowable; break label103; if (localObject3 != localThrowable) localObject3.addSuppressed(localThrowable); + } + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/minecraft/com/enjoytheban/management/FriendManager.java b/src/minecraft/com/enjoytheban/management/FriendManager.java new file mode 100644 index 0000000..507a12b --- /dev/null +++ b/src/minecraft/com/enjoytheban/management/FriendManager.java @@ -0,0 +1,142 @@ +package com.enjoytheban.management; + +import com.enjoytheban.Client; +import com.enjoytheban.command.Command; +import com.enjoytheban.utils.Helper; +import java.util.HashMap; +import java.util.List; +import net.minecraft.util.EnumChatFormatting; + + + + + + + + +public class FriendManager + implements Manager +{ + private static HashMap friends; + + public FriendManager() {} + + public void init() + { + friends = new HashMap(); + + List frriends = FileManager.read("Friends.txt"); + for (String v : frriends) { + if (v.contains(":")) { + String name = v.split(":")[0]; + String alias = v.split(":")[1]; + friends.put(name, alias); + } else { + friends.put(v, v); + } + } + + Client.instance.getCommandManager().add(new Command("f", new String[] { "friend", "fren", "fr" }, + "add/del/list name alias", "Manage client friends") + { + private final FriendManager fm = FriendManager.this; + + + + public String execute(String[] args) + { + if (args.length >= 3) { + if (args[0].equalsIgnoreCase("add")) { + String f = ""; + f = f + String.format("%s:%s%s", new Object[] { args[1], args[2], System.lineSeparator() }); + FriendManager.friends.put(args[1], args[2]); + Helper.sendMessage("> " + String.format("%s has been added as %s", new Object[] { args[1], args[2] })); + FileManager.save("Friends.txt", f, true); + } + else if (args[0].equalsIgnoreCase("del")) { + FriendManager.friends.remove(args[1]); + Helper.sendMessage("> " + + String.format("%s has been removed from your friends list", new Object[] { args[1] })); + } + else if (args[0].equalsIgnoreCase("list")) { + if (FriendManager.friends.size() > 0) { + int friends = 1; + for (String fr : FriendManager.friends.values()) { + Helper.sendMessage("> " + String.format("%s. %s", new Object[] { Integer.valueOf(friends), fr })); + friends++; + } + } + else { + Helper.sendMessage("> get some friends fag lmao"); + } + } + } + else if (args.length == 2) { + if (args[0].equalsIgnoreCase("add")) { + String f = ""; + f = f + String.format("%s%s", new Object[] { args[1], System.lineSeparator() }); + FriendManager.friends.put(args[1], args[1]); + Helper.sendMessage("> " + String.format("%s has been added as %s", new Object[] { args[1], args[1] })); + FileManager.save("Friends.txt", f, true); + } + else if (args[0].equalsIgnoreCase("del")) { + FriendManager.friends.remove(args[1]); + Helper.sendMessage("> " + + String.format("%s has been removed from your friends list", new Object[] { args[1] })); + } + else if (args[0].equalsIgnoreCase("list")) { + if (FriendManager.friends.size() > 0) { + int friends = 1; + for (String fr : FriendManager.friends.values()) { + Helper.sendMessage("> " + String.format("%s. %s", new Object[] { Integer.valueOf(friends), fr })); + friends++; + } + } else { + Helper.sendMessage("> you dont have any you lonely fuck"); + } + } + } + else if (args.length == 1) { + if (args[0].equalsIgnoreCase("list")) { + if (FriendManager.friends.size() > 0) { + int friends = 1; + for (String fr : FriendManager.friends.values()) { + Helper.sendMessage(String.format("%s. %s", new Object[] { Integer.valueOf(friends), fr })); + friends++; + } + } else { + Helper.sendMessage("you dont have any you lonely fuck"); + } + } + else if ((args[0].equalsIgnoreCase("add")) || (args[0].equalsIgnoreCase("del"))) { + Helper.sendMessage( + "> " + EnumChatFormatting.GRAY + "Please enter a players name"); + } else { + Helper.sendMessage( + "> Correct usage: " + EnumChatFormatting.GRAY + "Valid .f add/del "); + } + } + else if (args.length == 0) { + Helper.sendMessage( + "> Correct usage: " + EnumChatFormatting.GRAY + "Valid .f add/del "); + } + return null; + } + }); + } + + public static boolean isFriend(String name) + { + return friends.containsKey(name); + } + + public static String getAlias(String name) + { + return (String)friends.get(name); + } + + public static HashMap getFriends() + { + return friends; + } +} diff --git a/src/minecraft/com/enjoytheban/management/Manager.java b/src/minecraft/com/enjoytheban/management/Manager.java new file mode 100644 index 0000000..240b639 --- /dev/null +++ b/src/minecraft/com/enjoytheban/management/Manager.java @@ -0,0 +1,6 @@ +package com.enjoytheban.management; + +public abstract interface Manager +{ + public abstract void init(); +} diff --git a/src/minecraft/com/enjoytheban/management/ModuleManager.java b/src/minecraft/com/enjoytheban/management/ModuleManager.java new file mode 100644 index 0000000..9258f78 --- /dev/null +++ b/src/minecraft/com/enjoytheban/management/ModuleManager.java @@ -0,0 +1,331 @@ +package com.enjoytheban.management; + +import com.enjoytheban.api.EventBus; +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.misc.EventKey; +import com.enjoytheban.api.events.rendering.EventRender2D; +import com.enjoytheban.api.events.rendering.EventRender3D; +import com.enjoytheban.api.value.Mode; +import com.enjoytheban.api.value.Numbers; +import com.enjoytheban.api.value.Option; +import com.enjoytheban.api.value.Value; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import com.enjoytheban.module.modules.combat.AntiBot; +import com.enjoytheban.module.modules.combat.AutoHeal; +import com.enjoytheban.module.modules.combat.AutoSword; +import com.enjoytheban.module.modules.combat.BowAimBot; +import com.enjoytheban.module.modules.combat.Criticals; +import com.enjoytheban.module.modules.combat.FastBow; +import com.enjoytheban.module.modules.combat.Killaura; +import com.enjoytheban.module.modules.combat.Regen; +import com.enjoytheban.module.modules.combat.TPAura; +import com.enjoytheban.module.modules.movement.Boost; +import com.enjoytheban.module.modules.movement.Flight; +import com.enjoytheban.module.modules.movement.Jesus; +import com.enjoytheban.module.modules.movement.Longjump; +import com.enjoytheban.module.modules.movement.NoSlow; +import com.enjoytheban.module.modules.movement.Scaffold; +import com.enjoytheban.module.modules.movement.Sneak; +import com.enjoytheban.module.modules.movement.Speed; +import com.enjoytheban.module.modules.movement.Sprint; +import com.enjoytheban.module.modules.movement.Step; +import com.enjoytheban.module.modules.movement.Teleport; +import com.enjoytheban.module.modules.player.AntiVelocity; +import com.enjoytheban.module.modules.player.AutoAccept; +import com.enjoytheban.module.modules.player.Bobbing; +import com.enjoytheban.module.modules.player.Dab; +import com.enjoytheban.module.modules.player.FastUse; +import com.enjoytheban.module.modules.player.Freecam; +import com.enjoytheban.module.modules.player.InvCleaner; +import com.enjoytheban.module.modules.player.Invplus; +import com.enjoytheban.module.modules.player.MCF; +import com.enjoytheban.module.modules.player.NoFall; +import com.enjoytheban.module.modules.player.NoStrike; +import com.enjoytheban.module.modules.player.SkinFlash; +import com.enjoytheban.module.modules.player.Zoot; +import com.enjoytheban.module.modules.render.Chams; +import com.enjoytheban.module.modules.render.ChestESP; +import com.enjoytheban.module.modules.render.ESP; +import com.enjoytheban.module.modules.render.FullBright; +import com.enjoytheban.module.modules.render.HUD; +import com.enjoytheban.module.modules.render.Nametags; +import com.enjoytheban.module.modules.render.NoRender; +import com.enjoytheban.module.modules.render.Tracers; +import com.enjoytheban.module.modules.render.Xray; +import com.enjoytheban.module.modules.world.AntiVoid; +import com.enjoytheban.module.modules.world.AutoArmor; +import com.enjoytheban.module.modules.world.Banwave; +import com.enjoytheban.module.modules.world.Blink; +import com.enjoytheban.module.modules.world.ChestStealer; +import com.enjoytheban.module.modules.world.Deathclip; +import com.enjoytheban.module.modules.world.FastPlace; +import com.enjoytheban.module.modules.world.NoRotate; +import com.enjoytheban.module.modules.world.Phase; +import com.enjoytheban.module.modules.world.PinCracker; +import com.enjoytheban.module.modules.world.PingSpoof; +import com.enjoytheban.module.modules.world.SafeWalk; +import com.enjoytheban.module.modules.world.StaffAlerts; +import com.enjoytheban.utils.render.gl.GLUtils; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import net.minecraft.client.renderer.GlStateManager; +import org.lwjgl.input.Keyboard; + + + + + + + + +public class ModuleManager + implements Manager +{ + public static List modules = new ArrayList(); + + private boolean enabledNeededMod = true; + + public boolean nicetry = true; + + public ModuleManager() {} + + public void init() { + modules.add(new HUD()); + modules.add(new Sprint()); + modules.add(new Killaura()); + modules.add(new AntiVelocity()); + modules.add(new Criticals()); + modules.add(new Speed()); + modules.add(new Longjump()); + modules.add(new Flight()); + modules.add(new NoFall()); + modules.add(new Invplus()); + modules.add(new NoSlow()); + modules.add(new FastBow()); + modules.add(new AntiBot()); + modules.add(new Freecam()); + modules.add(new MCF()); + modules.add(new Nametags()); + modules.add(new Tracers()); + modules.add(new ESP()); + modules.add(new Regen()); + modules.add(new FastPlace()); + modules.add(new NoRender()); + modules.add(new FullBright()); + modules.add(new ChestStealer()); + modules.add(new AutoArmor()); + modules.add(new AntiVoid()); + modules.add(new AutoHeal()); + modules.add(new NoRotate()); + modules.add(new Scaffold()); + modules.add(new Sneak()); + modules.add(new SafeWalk()); + modules.add(new Zoot()); + modules.add(new Jesus()); + modules.add(new Phase()); + modules.add(new Chams()); + modules.add(new Deathclip()); + modules.add(new NoStrike()); + modules.add(new SkinFlash()); + modules.add(new AutoAccept()); + modules.add(new Blink()); + modules.add(new Banwave()); + modules.add(new FastUse()); + modules.add(new PingSpoof()); + modules.add(new BowAimBot()); + modules.add(new Xray()); + modules.add(new ChestESP()); + modules.add(new InvCleaner()); + modules.add(new Step()); + modules.add(new Dab()); + modules.add(new Teleport()); + modules.add(new AutoSword()); + modules.add(new Boost()); + modules.add(new Bobbing()); + modules.add(new PinCracker()); + modules.add(new TPAura()); + modules.add(new StaffAlerts()); + + readSettings(); + + + for (Module m : modules) { + m.makeCommand(); + } + + + EventBus.getInstance().register(new Object[] { this }); + } + + + public static List getModules() + { + return modules; + } + + public Module getModuleByClass(Class cls) + { + for (Module m : modules) { + if (m.getClass() == cls) + { + + return m; } + } + return null; + } + + public static Module getModuleByName(String name) + { + for (Module m : modules) { + if (m.getName().equalsIgnoreCase(name)) + { + + return m; } + } + return null; + } + + public Module getAlias(String name) { int length; + int i; + for (Iterator localIterator = modules.iterator(); localIterator.hasNext(); + + + + + i < length) + { + Module f = (Module)localIterator.next(); + if (f.getName().equalsIgnoreCase(name)) { + return f; + } + String[] alias; + length = (alias = f.getAlias()).length;i = 0; continue; + String s = alias[i]; + if (s.equalsIgnoreCase(name)) { + return f; + } + i++; + } + + + + + + return null; + } + + public List getModulesInType(ModuleType t) + { + List output = new ArrayList(); + for (Module m : modules) { + if (m.getType() == t) + { + + output.add(m); } + } + return output; + } + + + @EventHandler + private void onKeyPress(EventKey e) + { + for (Module m : modules) + { + if (m.getKey() == e.getKey()) + { + + + m.setEnabled(!m.isEnabled()); } + } + } + + @EventHandler + private void onGLHack(EventRender3D e) { + GlStateManager.getFloat(2982, (FloatBuffer)GLUtils.MODELVIEW.clear()); + GlStateManager.getFloat(2983, (FloatBuffer)GLUtils.PROJECTION.clear()); + GlStateManager.glGetInteger(2978, (IntBuffer)GLUtils.VIEWPORT.clear()); + } + + @EventHandler + private void on2DRender(EventRender2D e) + { + if (enabledNeededMod) { + enabledNeededMod = false; + + for (Module m : modules) + { + if (enabledOnStartup) + { + + + m.setEnabled(true); + } + } + } + } + + private void readSettings() + { + List binds = FileManager.read("Binds.txt"); + String name; for (String v : binds) { + name = v.split(":")[0];String bind = v.split(":")[1]; + Module m = getModuleByName(name); + + if (m != null) + { + + + m.setKey(Keyboard.getKeyIndex(bind.toUpperCase())); + } + } + + List enabled = FileManager.read("Enabled.txt"); + Module m; for (String v : enabled) + { + m = getModuleByName(v); + + if (m != null) + { + + + enabledOnStartup = true; + } + } + + Object vals = FileManager.read("Values.txt"); + for (String v : (List)vals) + { + String name = v.split(":")[0];String values = v.split(":")[1]; + + Module m = getModuleByName(name); + + if (m != null) + { + + + + for (Value value : m.getValues()) { + if (value.getName().equalsIgnoreCase(values)) + { + if ((value instanceof Option)) { + value.setValue(Boolean.valueOf(Boolean.parseBoolean(v.split(":")[2]))); + + } + else if ((value instanceof Numbers)) { + value.setValue(Double.valueOf(Double.parseDouble(v.split(":")[2]))); + } + else + { + ((Mode)value).setMode(v.split(":")[2]); + } + } + } + } + } + } +} diff --git a/src/minecraft/com/enjoytheban/module/Module.java b/src/minecraft/com/enjoytheban/module/Module.java new file mode 100644 index 0000000..decf907 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/Module.java @@ -0,0 +1,341 @@ +package com.enjoytheban.module; + +import com.enjoytheban.Client; +import com.enjoytheban.api.EventBus; +import com.enjoytheban.api.value.Mode; +import com.enjoytheban.api.value.Numbers; +import com.enjoytheban.api.value.Option; +import com.enjoytheban.api.value.Value; +import com.enjoytheban.command.Command; +import com.enjoytheban.management.CommandManager; +import com.enjoytheban.management.FileManager; +import com.enjoytheban.management.ModuleManager; +import com.enjoytheban.utils.Helper; +import com.enjoytheban.utils.math.MathUtil; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import net.minecraft.client.Minecraft; +import net.minecraft.util.EnumChatFormatting; +import org.lwjgl.input.Keyboard; + + + + + + + + + + + + + + + + +public class Module +{ + public String name; + private String suffix; + private int color; + private String[] alias; + private boolean enabled; + public boolean enabledOnStartup = false; + + + private int key; + + + public List values; + + + public ModuleType type; + + + private boolean removed; + + + public Minecraft mc = Minecraft.getMinecraft(); + + + public static Random random = new Random(); + + public Module(String name, String[] alias, ModuleType type) + { + this.name = name; + this.alias = alias; + this.type = type; + suffix = ""; + key = 0; + removed = false; + enabled = false; + values = new ArrayList(); + } + + public String getName() + { + return name; + } + + public String[] getAlias() + { + return alias; + } + + public ModuleType getType() + { + return type; + } + + public boolean isEnabled() + { + return enabled; + } + + public boolean wasRemoved() + { + return removed; + } + + public void setRemoved(boolean removed) { + this.removed = removed; + } + + public String getSuffix() + { + return suffix; + } + + public void setSuffix(Object obj) { + String suffix = obj.toString(); + if (suffix.isEmpty()) { + this.suffix = suffix; + } else { + this.suffix = String.format("§7- §f%s§7", new Object[] { EnumChatFormatting.GRAY + suffix }); + } + } + + public void setEnabled(boolean enabled) + { + this.enabled = enabled; + if (enabled) { + onEnable(); + EventBus.getInstance().register(new Object[] { this }); + } else { + EventBus.getInstance().unregister(new Object[] { this }); + onDisable(); + } + } + + public void setColor(int color) + { + this.color = color; + } + + public int getColor() + { + return color; + } + + protected void addValues(Value... values) + { + for (Value value : values) { + this.values.add(value); + } + } + + public List getValues() + { + return values; + } + + public int getKey() + { + return key; + } + + + public void setKey(int key) + { + this.key = key; + + String content = ""; + + Client.instance.getModuleManager(); for (Module m : ModuleManager.getModules()) + { + content = content + String.format("%s:%s%s", new Object[] { m.getName(), Keyboard.getKeyName(m.getKey()), System.lineSeparator() }); + } + + FileManager.save("Binds.txt", content, false); + } + + + + public void onEnable() {} + + + public void onDisable() {} + + + public void makeCommand() + { + if (values.size() > 0) + { + String options = ""; + String other = ""; + + for (Value value : values) { + if (!(value instanceof Mode)) + { + + if (options.isEmpty()) { + options = String.valueOf(options) + value.getName(); + } else { + options = String.valueOf(options) + String.format(", %s", new Object[] { value.getName() }); + } + } + } + for (Value v : values) { + if ((v instanceof Mode)) + { + + + Mode mode = (Mode)v; + + Enum[] modes; + int length = (modes = mode.getModes()).length; for (int i = 0; i < length; i++) { + Enum e = modes[i]; + + if (other.isEmpty()) { + other = String.valueOf(other) + e.name().toLowerCase(); + } else { + other = String.valueOf(other) + String.format(", %s", new Object[] { e.name().toLowerCase() }); + } + } + } + } + + Client.instance.getCommandManager().add(new Command(name, alias, + String.format("%s%s", new Object[] { options.isEmpty() ? "" : String.format("%s,", new Object[] { options }), + other.isEmpty() ? "" : String.format("%s", new Object[] { other }) }), + "Setup this module") + { + + + + private final Module m = Module.this; + + public String execute(String[] args) + { + Mode mode; + if (args.length >= 2) + { + Option option = null; + Numbers val = null; + mode = null; + + for (Value value : m.values) { + if (((value instanceof Option)) && + (value.getName().equalsIgnoreCase(args[0]))) + { + + option = (Option)value; + } + } + + if (option != null) { + option.setValue(Boolean.valueOf(!((Boolean)option.getValue()).booleanValue())); + Helper.sendMessage( + String.format("> %s has been set to %s", new Object[] { option.getName(), option.getValue() })); + } else { + for (Value value2 : m.values) { + if (((value2 instanceof Numbers)) && + (value2.getName().equalsIgnoreCase(args[0]))) + { + + val = (Numbers)value2; + } + } + + if (val != null) { + if (MathUtil.parsable(args[1], (byte)4)) { + double value3 = MathUtil.round(Double.parseDouble(args[1]), 1); + val.setValue(Double.valueOf(value3 > ((Double)val.getMaximum()).doubleValue() ? ((Double)val.getMaximum()).doubleValue() : value3)); + Helper.sendMessage( + String.format("> %s has been set to %s", new Object[] { val.getName(), val.getValue() })); + } else { + Helper.sendMessage("> " + args[1] + " is not a number"); + } + } + + for (Value v : m.values) { + if (args[0].equalsIgnoreCase(v.getDisplayName())) + { + if ((v instanceof Mode)) + { + + mode = (Mode)v; + } + } + } + if (mode != null) { + if (mode.isValid(args[1])) { + mode.setMode(args[1]); + Helper.sendMessage( + String.format("> %s set to %s", new Object[] { mode.getName(), mode.getModeAsString() })); + } + else + { + Helper.sendMessage("> " + args[1] + " is an invalid mode"); + } + } + } + + if ((val == null) && (option == null) && (mode == null)) { + syntaxError("Valid . "); + } + + } + else if (args.length >= 1) { + Option option = null; + + for (Value value : m.values) { + if (((value instanceof Option)) && + (value.getName().equalsIgnoreCase(args[0]))) + { + + option = (Option)value; + } + } + + if (option != null) { + option.setValue(Boolean.valueOf(!((Boolean)option.getValue()).booleanValue())); + String fuck = option.getName().substring(1); + String xd = option.getName().substring(0, 1).toUpperCase(); + if (((Boolean)option.getValue()).booleanValue()) { + Helper.sendMessage(String.format("> %s has been set to §a%s", new Object[] { xd + fuck, option.getValue() })); + } else { + Helper.sendMessage(String.format("> %s has been set to §c%s", new Object[] { xd + fuck, option.getValue() })); + } + } + else + { + syntaxError("Valid . "); + } + } + else + { + Helper.sendMessage( + String.format("%s Values: \n %s", new Object[] { + getName().substring(0, 1).toUpperCase() + + getName().substring(1).toLowerCase(), + getSyntax(), "false" })); + } + + return null; + } + }); + } + } +} diff --git a/src/minecraft/com/enjoytheban/module/ModuleType.java b/src/minecraft/com/enjoytheban/module/ModuleType.java new file mode 100644 index 0000000..09d61e1 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/ModuleType.java @@ -0,0 +1,6 @@ +package com.enjoytheban.module; + +public enum ModuleType +{ + Combat, Render, Movement, Player, World; +} diff --git a/src/minecraft/com/enjoytheban/module/modules/combat/AntiBot.java b/src/minecraft/com/enjoytheban/module/modules/combat/AntiBot.java new file mode 100644 index 0000000..020e716 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/combat/AntiBot.java @@ -0,0 +1,42 @@ +package com.enjoytheban.module.modules.combat; + +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import com.enjoytheban.utils.Helper; +import java.awt.Color; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.IChatComponent; + + +public class AntiBot + extends Module +{ + public AntiBot() + { + super("AntiBot", new String[] { "nobot", "botkiller" }, ModuleType.Combat); + setColor(new Color(217, 149, 251).getRGB()); + } + + public boolean isServerBot(Entity entity) + { + if (isEnabled()) { + if (Helper.onServer("hypixel")) + return (!entity.getDisplayName().getFormattedText().startsWith("§")) || (entity.isInvisible()) || (entity.getDisplayName().getFormattedText().toLowerCase().contains("npc")); + if (Helper.onServer("mineplex")) { + for (Object object : mc.theWorld.playerEntities) { + EntityPlayer entityPlayer = (EntityPlayer)object; + if ((entityPlayer != null) && (entityPlayer != mc.thePlayer) && ( + (entityPlayer.getName().startsWith("Body #")) || (entityPlayer.getMaxHealth() == 20.0F))) { + return true; + } + } + } + } + + + return false; + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/combat/AutoHeal.java b/src/minecraft/com/enjoytheban/module/modules/combat/AutoHeal.java new file mode 100644 index 0000000..f8b04cb --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/combat/AutoHeal.java @@ -0,0 +1,177 @@ +package com.enjoytheban.module.modules.combat; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventPostUpdate; +import com.enjoytheban.api.events.world.EventPreUpdate; +import com.enjoytheban.api.value.Mode; +import com.enjoytheban.api.value.Numbers; +import com.enjoytheban.api.value.Option; +import com.enjoytheban.module.Module; +import com.enjoytheban.utils.TimerUtil; +import java.awt.Color; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemPotion; +import net.minecraft.item.ItemSoup; +import net.minecraft.item.ItemStack; +import net.minecraft.network.play.client.C09PacketHeldItemChange; +import net.minecraft.potion.Potion; +import net.minecraft.potion.PotionEffect; + +public class AutoHeal extends Module +{ + private Numbers health = new Numbers("Health", "health", Double.valueOf(3.0D), Double.valueOf(0.0D), Double.valueOf(10.0D), Double.valueOf(0.5D)); private Numbers delay = new Numbers("Delay", "delay", Double.valueOf(400.0D), Double.valueOf(0.0D), Double.valueOf(1000.0D), Double.valueOf(10.0D)); + + private Option jump = new Option("Jump", "jump", Boolean.valueOf(true)); + + private Mode mode = new Mode("Mode", "mode", HealMode.values(), HealMode.Potion); + + static boolean currentlyPotting = false; + + + private TimerUtil timer = new TimerUtil(); + private boolean isUsing; + + public AutoHeal() { super("AutoHeal", new String[] { "autopot", "autop", "autosoup" }, com.enjoytheban.module.ModuleType.Combat); + setColor(new Color(76, 249, 247).getRGB()); + addValues(new com.enjoytheban.api.value.Value[] { health, delay, jump, mode }); + } + + @EventHandler + private void onUpdate(EventPreUpdate e) { + if ((timer.hasReached(((Double)delay.getValue()).doubleValue())) && (mc.thePlayer.getHealth() <= ((Double)health.getValue()).doubleValue() * 2.0D)) { + isUsing = (((this.slot = mode.getValue() == HealMode.Soup ? getSoupSlot() : mode.getValue() == HealMode.Potion ? getPotionSlot() : getPotionSlot()) != -1) && ((!((Boolean)jump.getValue()).booleanValue()) || (mc.thePlayer.onGround))); + if (isUsing) { + timer.reset(); + if (mode.getValue() == HealMode.Potion) { + currentlyPotting = true; + e.setPitch(((Boolean)jump.getValue()).booleanValue() ? -90 : 90); + if (timer.hasReached(1.0D)) { + currentlyPotting = false; + timer.reset(); + } + } + } + } + } + + @EventHandler + private void onUpdatePost(EventPostUpdate e) { + if (isUsing) { + int current = mc.thePlayer.inventory.currentItem;int next = mc.thePlayer.nextSlot(); + mc.thePlayer.moveToHotbar(slot, next); + mc.thePlayer.sendQueue + .addToSendQueue(new C09PacketHeldItemChange(mc.thePlayer.inventory.currentItem = next)); + mc.playerController.sendUseItem(mc.thePlayer, mc.theWorld, mc.thePlayer.getHeldItem()); + mc.thePlayer.sendQueue + .addToSendQueue(new C09PacketHeldItemChange(mc.thePlayer.inventory.currentItem = current)); + isUsing = false; + if ((mc.thePlayer.onGround) && (((Boolean)jump.getValue()).booleanValue()) && (mode.getValue() == HealMode.Potion)) { + mc.thePlayer.setSpeed(0.0D); + mc.thePlayer.motionY = 0.42D; + } + } + } + + private int getPotionSlot() + { + int slot = -1; + for (Slot s : mc.thePlayer.inventoryContainer.inventorySlots) + if (s.getHasStack()) + { + + ItemStack is = s.getStack(); + if ((is.getItem() instanceof ItemPotion)) + { + + ItemPotion ip = (ItemPotion)is.getItem(); + if (ItemPotion.isSplash(is.getMetadata())) + { + + boolean hasHealing = false; + for (PotionEffect pe : ip.getEffects(is)) + if (pe.getPotionID() == healid) + { + + hasHealing = true; + break; + } + if (hasHealing) + { + + slot = slotNumber; + break; + } } } } + return slot; + } + + private int getSoupSlot() { + int slot = -1; + for (Slot s : mc.thePlayer.inventoryContainer.inventorySlots) + if (s.getHasStack()) + { + + ItemStack is = s.getStack(); + if ((is.getItem() instanceof ItemSoup)) + { + + slot = slotNumber; + break; + } } + return slot; + } + + private int slot; + private int getPotionCount() + { + int count = 0; + for (Slot s : mc.thePlayer.inventoryContainer.inventorySlots) + if (s.getHasStack()) + { + + ItemStack is = s.getStack(); + if ((is.getItem() instanceof ItemPotion)) + { + + ItemPotion ip = (ItemPotion)is.getItem(); + if (ItemPotion.isSplash(is.getMetadata())) + { + + boolean hasHealing = false; + for (PotionEffect pe : ip.getEffects(is)) + if (pe.getPotionID() == healid) + { + + hasHealing = true; + break; + } + if (hasHealing) + { + + count++; } + } } } + return count; + } + + private int getSoupCount() { + int count = 0; + for (Slot s : mc.thePlayer.inventoryContainer.inventorySlots) + if (s.getHasStack()) + { + + ItemStack is = s.getStack(); + if ((is.getItem() instanceof ItemSoup)) + { + + count++; } + } + return count; + } + + static enum HealMode { + Potion, Soup; + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/combat/AutoSword.java b/src/minecraft/com/enjoytheban/module/modules/combat/AutoSword.java new file mode 100644 index 0000000..ec747fa --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/combat/AutoSword.java @@ -0,0 +1 @@ +null \ No newline at end of file diff --git a/src/minecraft/com/enjoytheban/module/modules/combat/BowAimBot.java b/src/minecraft/com/enjoytheban/module/modules/combat/BowAimBot.java new file mode 100644 index 0000000..ec747fa --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/combat/BowAimBot.java @@ -0,0 +1 @@ +null \ No newline at end of file diff --git a/src/minecraft/com/enjoytheban/module/modules/combat/Criticals.java b/src/minecraft/com/enjoytheban/module/modules/combat/Criticals.java new file mode 100644 index 0000000..4a3cadf --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/combat/Criticals.java @@ -0,0 +1,94 @@ +package com.enjoytheban.module.modules.combat; + +import com.enjoytheban.Client; +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventPacketSend; +import com.enjoytheban.api.events.world.EventPreUpdate; +import com.enjoytheban.api.value.Mode; +import com.enjoytheban.api.value.Value; +import com.enjoytheban.management.ModuleManager; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import com.enjoytheban.module.modules.movement.Speed; +import com.enjoytheban.utils.Helper; +import com.enjoytheban.utils.TimerUtil; +import java.awt.Color; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.multiplayer.ServerData; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.network.play.client.C02PacketUseEntity; +import net.minecraft.network.play.client.C03PacketPlayer.C04PacketPlayerPosition; + + +public class Criticals + extends Module +{ + private Mode mode = new Mode("Mode", "mode", CritMode.values(), CritMode.Packet); + + private TimerUtil timer = new TimerUtil(); + + public Criticals() + { + super("Criticals", new String[] { "crits", "crit" }, ModuleType.Combat); + setColor(new Color(235, 194, 138).getRGB()); + addValues(new Value[] { mode }); + } + + @EventHandler + private void onUpdate(EventPreUpdate e) { + setSuffix(mode.getValue()); + } + + private boolean canCrit() + { + return (mc.thePlayer.onGround) && (!mc.thePlayer.isInWater()) && (!Client.instance.getModuleManager().getModuleByClass(Speed.class).isEnabled()); + } + + @EventHandler + private void onPacket(EventPacketSend e) + { + if (((e.getPacket() instanceof C02PacketUseEntity)) && (canCrit()) && (mode.getValue() == CritMode.Minijumps)) { + mc.thePlayer.motionY = 0.2D; + } + } + + + void packetCrit() + { + if ((timer.hasReached(Helper.onServer("hypixel") ? 500 : 10)) && (mode.getValue() == CritMode.Packet) && (canCrit())) + { + double[] offsets = { 0.0625D, 0.0D, 1.0E-4D, 0.0D }; + + for (int i = 0; i < offsets.length; i++) { + mc.thePlayer.sendQueue.addToSendQueue(new C03PacketPlayer.C04PacketPlayerPosition(mc.thePlayer.posX, mc.thePlayer.posY + offsets[i], mc.thePlayer.posZ, false)); + } + + timer.reset(); + } + } + + void offsetCrit() + { + if ((canCrit()) && (!mc.getCurrentServerData().serverIP.contains("hypixel"))) { + double[] offsets = { 0.0624D, 0.0D, 1.0E-4D, 0.0D }; + for (int i = 0; i < offsets.length; i++) { + mc.thePlayer.sendQueue.addToSendQueue(new C03PacketPlayer.C04PacketPlayerPosition(mc.thePlayer.posX, mc.thePlayer.posY + offsets[i], mc.thePlayer.posZ, false)); + } + } + } + + public void hypixelCrit() { + if ((mode.getValue() == CritMode.Hypixel) && + (canCrit())) { + for (double offset : new double[] { 0.06142999976873398D, 0.0D, 0.012511000037193298D, 0.0D }) { + mc.thePlayer.sendQueue.addToSendQueue(new C03PacketPlayer.C04PacketPlayerPosition(mc.thePlayer.posX, mc.thePlayer.posY + offset, mc.thePlayer.posZ, true)); + } + } + } + + static enum CritMode + { + Packet, Hypixel, Minijumps; + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/combat/FastBow.java b/src/minecraft/com/enjoytheban/module/modules/combat/FastBow.java new file mode 100644 index 0000000..465b3a2 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/combat/FastBow.java @@ -0,0 +1,116 @@ +package com.enjoytheban.module.modules.combat; + +import com.enjoytheban.api.events.world.EventPacketRecieve; +import com.enjoytheban.api.value.Option; +import com.enjoytheban.utils.TimerUtil; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.client.settings.GameSettings; +import net.minecraft.client.settings.KeyBinding; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.item.ItemBow; +import net.minecraft.item.ItemStack; +import net.minecraft.network.play.client.C03PacketPlayer.C04PacketPlayerPosition; +import net.minecraft.network.play.client.C07PacketPlayerDigging; +import net.minecraft.network.play.client.C07PacketPlayerDigging.Action; +import net.minecraft.network.play.client.C08PacketPlayerBlockPlacement; +import net.minecraft.network.play.server.S18PacketEntityTeleport; +import net.minecraft.util.EnumFacing; + +public class FastBow extends com.enjoytheban.module.Module +{ + private TimerUtil timer = new TimerUtil(); + private Option faithful = new Option("Faithful", "faithful", Boolean.valueOf(true)); + int counter; + + public FastBow() + { + super("FastBow", new String[] { "zoombow", "quickbow" }, com.enjoytheban.module.ModuleType.Combat); + setColor(new java.awt.Color(255, 99, 99).getRGB()); + addValues(new com.enjoytheban.api.value.Value[] { faithful }); + counter = 0; + } + + private boolean canConsume() { + return (mc.thePlayer.inventory.getCurrentItem() != null) && + ((mc.thePlayer.getCurrentEquippedItem().getItem() instanceof ItemBow)); + } + + private void killGuardian() { + if (timer.hasReached(1000.0D)) { + mc.thePlayer.sendQueue.addToSendQueue(new C03PacketPlayer.C04PacketPlayerPosition(mc.thePlayer.posX, + mc.thePlayer.posY - Double.POSITIVE_INFINITY, mc.thePlayer.posZ, false)); + timer.reset(); + } + } + + @com.enjoytheban.api.EventHandler + private void onUpdate(com.enjoytheban.api.events.world.EventPreUpdate e) { + if (((Boolean)faithful.getValue()).booleanValue()) { + if ((mc.thePlayer.onGround) && (mc.thePlayer.getCurrentEquippedItem() != null) && + ((mc.thePlayer.getCurrentEquippedItem().getItem() instanceof ItemBow)) && + (mc.gameSettings.keyBindUseItem.pressed)) { + mc.thePlayer.sendQueue.addToSendQueue( + new C08PacketPlayerBlockPlacement(mc.thePlayer.inventory.getCurrentItem())); + for (int index = 0; index < 16; index++) { + if (!mc.thePlayer.isDead) { + mc.thePlayer.sendQueue.addToSendQueue(new net.minecraft.network.play.client.C03PacketPlayer.C06PacketPlayerPosLook( + mc.thePlayer.posX, mc.thePlayer.posY - 0.09D, mc.thePlayer.posZ, + mc.thePlayer.rotationYaw, mc.thePlayer.rotationPitch, true)); + } + } + mc.thePlayer.sendQueue.addToSendQueue(new C07PacketPlayerDigging( + C07PacketPlayerDigging.Action.RELEASE_USE_ITEM, net.minecraft.util.BlockPos.ORIGIN, EnumFacing.DOWN)); + } + if ((mc.thePlayer.onGround) && (mc.thePlayer.getCurrentEquippedItem() != null) && + ((mc.thePlayer.getCurrentEquippedItem().getItem() instanceof ItemBow)) && + (mc.gameSettings.keyBindUseItem.pressed)) { + mc.thePlayer.sendQueue.addToSendQueue( + new C08PacketPlayerBlockPlacement(mc.thePlayer.inventory.getCurrentItem())); + if (mc.thePlayer.ticksExisted % 2 == 0) { + mc.thePlayer.setItemInUse(mc.thePlayer.getCurrentEquippedItem(), 12); + counter += 1; + if (counter > 0) { + mc.thePlayer.sendQueue.addToSendQueue(new C03PacketPlayer.C04PacketPlayerPosition( + mc.thePlayer.posX, mc.thePlayer.posY - 0.0D, mc.thePlayer.posZ, + mc.thePlayer.onGround)); + counter = 0; + } + int dist = 20; for (int index = 0; index < dist; index++) { + mc.thePlayer.sendQueue.addToSendQueue(new C03PacketPlayer.C04PacketPlayerPosition( + mc.thePlayer.posX, mc.thePlayer.posY + 1.0E-12D, mc.thePlayer.posZ, + mc.thePlayer.onGround)); + } + mc.thePlayer.sendQueue.addToSendQueue(new C07PacketPlayerDigging( + C07PacketPlayerDigging.Action.RELEASE_USE_ITEM, net.minecraft.util.BlockPos.ORIGIN, EnumFacing.DOWN)); + mc.playerController.onStoppedUsingItem(mc.thePlayer); + } + } + } + else if ((mc.thePlayer.onGround) && (canConsume()) && (mc.gameSettings.keyBindUseItem.pressed)) + { + mc.thePlayer.sendQueue.addToSendQueue(new C08PacketPlayerBlockPlacement(mc.thePlayer.inventory.getCurrentItem())); + for (int i = 0; i < 20; i++) { + mc.thePlayer.sendQueue.addToSendQueue(new C03PacketPlayer.C04PacketPlayerPosition(mc.thePlayer.posX, + mc.thePlayer.posY + 1.0E-9D, mc.thePlayer.posZ, true)); + } + mc.thePlayer.sendQueue.addToSendQueue(new C07PacketPlayerDigging( + C07PacketPlayerDigging.Action.RELEASE_USE_ITEM, net.minecraft.util.BlockPos.ORIGIN, EnumFacing.DOWN)); + } else { + mc.timer.timerSpeed = 1.0F; + } + } + + @com.enjoytheban.api.EventHandler + public void onRecieve(EventPacketRecieve event) + { + if ((event.getPacket() instanceof S18PacketEntityTeleport)) { + S18PacketEntityTeleport packet = (S18PacketEntityTeleport)event.getPacket(); + if (mc.thePlayer != null) { + packet.setYaw((byte)(int)mc.thePlayer.rotationYaw); + } + packet.setPitch((byte)(int)mc.thePlayer.rotationPitch); + } + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/combat/Killaura.java b/src/minecraft/com/enjoytheban/module/modules/combat/Killaura.java new file mode 100644 index 0000000..ec747fa --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/combat/Killaura.java @@ -0,0 +1 @@ +null \ No newline at end of file diff --git a/src/minecraft/com/enjoytheban/module/modules/combat/Regen.java b/src/minecraft/com/enjoytheban/module/modules/combat/Regen.java new file mode 100644 index 0000000..b879e3a --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/combat/Regen.java @@ -0,0 +1,50 @@ +package com.enjoytheban.module.modules.combat; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventPreUpdate; +import com.enjoytheban.api.value.Option; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import java.awt.Color; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.network.play.client.C03PacketPlayer.C04PacketPlayerPosition; +import net.minecraft.network.play.client.C03PacketPlayer.C06PacketPlayerPosLook; +import net.minecraft.network.play.client.C07PacketPlayerDigging; +import net.minecraft.network.play.client.C07PacketPlayerDigging.Action; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.FoodStats; + +public class Regen extends Module +{ + private Option guardian = new Option("Guardian", "guardian", Boolean.valueOf(true)); + + public Regen() { + super("Regen", new String[] { "fastgen" }, ModuleType.Combat); + setColor(new Color(208, 30, 142).getRGB()); + } + + @EventHandler + private void onUpdate(EventPreUpdate event) { + if ((mc.thePlayer.onGround) && (mc.thePlayer.getHealth() < 16.0D) && + (mc.thePlayer.getFoodStats().getFoodLevel() > 17) && (mc.thePlayer.isCollidedVertically)) { + for (int i = 0; i < 60; i++) { + mc.thePlayer.sendQueue.addToSendQueue( + new C03PacketPlayer.C06PacketPlayerPosLook(mc.thePlayer.posX, mc.thePlayer.posY + 1.0E-9D, + mc.thePlayer.posZ, mc.thePlayer.rotationYaw, mc.thePlayer.rotationPitch, true)); + mc.thePlayer.motionX = 0.0D; + mc.thePlayer.motionZ = 0.0D; + } + if ((((Boolean)guardian.getValue()).booleanValue()) && + (mc.thePlayer.ticksExisted % 3 == 0)) { + mc.thePlayer.sendQueue.addToSendQueue(new C03PacketPlayer.C04PacketPlayerPosition(mc.thePlayer.posX, + mc.thePlayer.posY - 999.0D, mc.thePlayer.posZ, true)); + } + + mc.thePlayer.sendQueue.addToSendQueue(new C07PacketPlayerDigging( + C07PacketPlayerDigging.Action.RELEASE_USE_ITEM, BlockPos.ORIGIN, EnumFacing.DOWN)); + } + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/combat/TPAura.java b/src/minecraft/com/enjoytheban/module/modules/combat/TPAura.java new file mode 100644 index 0000000..627cad7 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/combat/TPAura.java @@ -0,0 +1,90 @@ +package com.enjoytheban.module.modules.combat; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventTick; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import com.enjoytheban.utils.TimerUtil; +import java.awt.Color; +import java.util.ArrayList; +import java.util.List; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.network.play.client.C02PacketUseEntity; +import net.minecraft.network.play.client.C02PacketUseEntity.Action; +import net.minecraft.network.play.client.C03PacketPlayer.C04PacketPlayerPosition; +import net.minecraft.potion.Potion; + + + +public class TPAura + extends Module +{ + private int ticks; + private List loaded = new ArrayList(); + private EntityLivingBase target; + private int tpdelay; + public boolean criticals; + private TimerUtil timer = new TimerUtil(); + + public TPAura() { + super("TPAura", new String[] { "tpaura" }, ModuleType.Combat); + } + + @EventHandler + public void onUpdate(EventTick event) { + setColor(new Color(255, 50, 70).getRGB()); + ticks += 1; + tpdelay += 1; + if (ticks >= 20 - speed()) { + ticks = 0; + for (Object object : mc.theWorld.loadedEntityList) { + if ((object instanceof EntityLivingBase)) { + EntityLivingBase entity = (EntityLivingBase)object; + if (!(entity instanceof EntityPlayerSP)) + { + + if (mc.thePlayer.getDistanceToEntity(entity) <= 10.0F) + { + + if (entity.isEntityAlive()) { + if (tpdelay >= 4) { + mc.thePlayer.sendQueue.addToSendQueue(new C03PacketPlayer.C04PacketPlayerPosition( + posX, posY, posZ, false)); + } + if (mc.thePlayer.getDistanceToEntity(entity) < 10.0F) + attack(entity); + } } + } + } + } + } + } + + public void attack(EntityLivingBase entity) { + attack(entity, false); + } + + public void attack(EntityLivingBase entity, boolean crit) { + mc.thePlayer.swingItem(); + float sharpLevel = EnchantmentHelper.func_152377_a(mc.thePlayer.getHeldItem(), entity.getCreatureAttribute()); + boolean vanillaCrit = (mc.thePlayer.fallDistance > 0.0F) && (!mc.thePlayer.onGround) && (!mc.thePlayer.isOnLadder()) && + (!mc.thePlayer.isInWater()) && (!mc.thePlayer.isPotionActive(Potion.blindness)) && + (mc.thePlayer.ridingEntity == null); + mc.thePlayer.sendQueue.addToSendQueue(new C02PacketUseEntity(entity, C02PacketUseEntity.Action.ATTACK)); + if ((crit) || (vanillaCrit)) { + mc.thePlayer.onCriticalHit(entity); + } + if (sharpLevel > 0.0F) { + mc.thePlayer.onEnchantmentCritical(entity); + } + } + + private int speed() { + return 8; + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/movement/Boost.java b/src/minecraft/com/enjoytheban/module/modules/movement/Boost.java new file mode 100644 index 0000000..7e71628 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/movement/Boost.java @@ -0,0 +1,37 @@ +package com.enjoytheban.module.modules.movement; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventPreUpdate; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import com.enjoytheban.utils.TimerUtil; +import java.awt.Color; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; + + + +public class Boost + extends Module +{ + private TimerUtil timer = new TimerUtil(); + + public Boost() { + super("Boost", new String[] { "boost" }, ModuleType.Movement); + setColor(new Color(216, 253, 100).getRGB()); + } + + @EventHandler + public void onUpdate(EventPreUpdate event) { + mc.timer.timerSpeed = 3.0F; + if (mc.thePlayer.ticksExisted % 15 == 0) { + setEnabled(false); + } + } + + public void onDisable() + { + timer.reset(); + mc.timer.timerSpeed = 1.0F; + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/movement/Flight.java b/src/minecraft/com/enjoytheban/module/modules/movement/Flight.java new file mode 100644 index 0000000..f27f60b --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/movement/Flight.java @@ -0,0 +1,280 @@ +package com.enjoytheban.module.modules.movement; + +import com.enjoytheban.Client; +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventMove; +import com.enjoytheban.api.events.world.EventPreUpdate; +import com.enjoytheban.api.value.Mode; +import com.enjoytheban.api.value.Value; +import com.enjoytheban.management.ModuleManager; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import com.enjoytheban.utils.TimerUtil; +import com.enjoytheban.utils.math.MathUtil; +import java.awt.Color; +import net.minecraft.block.BlockAir; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.client.settings.GameSettings; +import net.minecraft.client.settings.KeyBinding; +import net.minecraft.network.play.client.C03PacketPlayer.C04PacketPlayerPosition; +import net.minecraft.network.play.client.C07PacketPlayerDigging; +import net.minecraft.network.play.client.C07PacketPlayerDigging.Action; +import net.minecraft.potion.Potion; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.MovementInput; + +public class Flight extends Module +{ + public Mode mode = new Mode("Mode", "mode", FlightMode.values(), FlightMode.Guardian); + + private TimerUtil timer; + + private double movementSpeed; + + private int counter; + private int hypixelCounter; + private int hypixelCounter2; + + public Flight() + { + super("Flight", new String[] { "fly", "angel" }, ModuleType.Movement); + + timer = new TimerUtil(); + setColor(new Color(158, 114, 243).getRGB()); + addValues(new Value[] { mode }); + } + + + + public void onEnable() + { + if ((mode.getValue() == FlightMode.Hypixel) || (mode.getValue() == FlightMode.HypixelBoost)) { + hypixelCounter = 0; + hypixelCounter2 = 1000; + mc.thePlayer.setPosition(mc.thePlayer.posX, mc.thePlayer.posY + 0.2D, mc.thePlayer.posZ); + } + } + + + public void onDisable() + { + if (mode.getValue() == FlightMode.Area51) { + mc.thePlayer.motionX = 0.0D; + mc.thePlayer.motionZ = 0.0D; + } + hypixelCounter = 0; + hypixelCounter2 = 100; + mc.timer.timerSpeed = 1.0F; + } + + @EventHandler + private void onUpdate(EventPreUpdate e) + { + setSuffix(mode.getValue()); + if (mode.getValue() == FlightMode.Guardian) + { + mc.timer.timerSpeed = 1.7F; + + + + if ((!mc.thePlayer.onGround) && (mc.thePlayer.ticksExisted % 2 == 0)) { + mc.thePlayer.motionY = 0.04D; + } + + + if (mc.gameSettings.keyBindJump.getIsKeyPressed()) { + mc.thePlayer.motionY += 1.0D; + } + + + if (mc.gameSettings.keyBindSneak.getIsKeyPressed()) { + mc.thePlayer.motionY -= 1.0D; + } + } else if (mode.getValue() == FlightMode.Vanilla) { + if (mc.thePlayer.movementInput.jump) { + mc.thePlayer.motionY = 1.0D; + } else if (mc.thePlayer.movementInput.sneak) { + mc.thePlayer.motionY = -1.0D; + } else { + mc.thePlayer.motionY = 0.0D; + } + if (mc.thePlayer.moving()) { + mc.thePlayer.setSpeed(1.0D); + } else { + mc.thePlayer.setSpeed(0.0D); + } + } else if (mode.getValue() == FlightMode.Area51) { + if (mc.thePlayer.movementInput.jump) { + mc.thePlayer.motionY = 1.0D; + } else if (mc.thePlayer.movementInput.sneak) { + mc.thePlayer.motionY = -1.0D; + } else { + mc.thePlayer.motionY = 0.0D; + } + + } + else if ((mode.getValue() == FlightMode.Hypixel) && (e.getType() == 0)) { + mc.thePlayer.motionY = 0.0D; + counter += 1; + if (counter == 1) { + mc.thePlayer.setPosition(mc.thePlayer.posX, mc.thePlayer.posY + 8.0E-6D, mc.thePlayer.posZ); + } else if (counter == 2) { + mc.thePlayer.setPosition(mc.thePlayer.posX, mc.thePlayer.posY - 8.0E-6D, mc.thePlayer.posZ); + counter = 0; + } + if (timer.hasReached(50.0D)) { + if (mc.thePlayer.movementInput.jump) + mc.thePlayer.motionY += 0.5D; + if (mc.thePlayer.movementInput.sneak) + mc.thePlayer.motionY -= 0.5D; + timer.reset(); + } + } else if ((mode.getValue() == FlightMode.HypixelBoost) && (e.getType() == 0)) { + mc.thePlayer.motionY = 0.0D; + counter += 1; + if (counter == 1) { + mc.thePlayer.setPosition(mc.thePlayer.posX, mc.thePlayer.posY + 8.0E-6D, mc.thePlayer.posZ); + } else if (counter == 2) { + mc.thePlayer.setPosition(mc.thePlayer.posX, mc.thePlayer.posY - 8.0E-6D, mc.thePlayer.posZ); + counter = 0; + } + if (timer.hasReached(50.0D)) { + if (mc.thePlayer.movementInput.jump) + mc.thePlayer.motionY += 0.5D; + if (mc.thePlayer.movementInput.sneak) + mc.thePlayer.motionY -= 0.5D; + timer.reset(); + } + } else if ((mode.getValue() == FlightMode.OldGuardianLongJumpFly) && + (mc.thePlayer.moving()) && + (!Client.instance.getModuleManager().getModuleByClass(Speed.class).isEnabled())) { + if (mc.thePlayer.isAirBorne) { + if (mc.thePlayer.ticksExisted % 12 == 0) + { + if ((mc.theWorld.getBlockState(new BlockPos(mc.thePlayer.posX, mc.thePlayer.posY, mc.thePlayer.posZ)).getBlock() instanceof BlockAir)) { + mc.thePlayer.setSpeed(6.5D); + mc.thePlayer.sendQueue + .addToSendQueue(new C03PacketPlayer.C04PacketPlayerPosition(mc.thePlayer.posX, + mc.thePlayer.posY + 1.0E-9D, mc.thePlayer.posZ, mc.thePlayer.onGround)); + mc.thePlayer.motionY = 0.455D; + break label1154; } } + mc.thePlayer.setSpeed((float)Math.sqrt(mc.thePlayer.motionX * mc.thePlayer.motionX + + mc.thePlayer.motionZ * mc.thePlayer.motionZ)); + } + else { + mc.thePlayer.motionX = 0.0D; + mc.thePlayer.motionZ = 0.0D; } + label1154: + if (mc.thePlayer.movementInput.jump) { + mc.thePlayer.motionY = 0.85D; + } else if (mc.thePlayer.movementInput.sneak) { + mc.thePlayer.motionY = -0.85D; + } + } + } + + @EventHandler + private void onMove(EventMove e) + { + if ((mc.thePlayer.moving()) && (mode.getValue() == FlightMode.Hypixel)) { + mc.thePlayer.cameraYaw = 0.07272727F; + mc.timer.timerSpeed = 1.15F; + movementSpeed = MathUtil.getBaseMovementSpeed(); + double x = -(Math.sin(mc.thePlayer.getDirection()) * movementSpeed); + double z = Math.cos(mc.thePlayer.getDirection()) * movementSpeed; + e.setX(x); + e.setZ(z); + } else if ((mc.thePlayer.moving()) && (mode.getValue() == FlightMode.HypixelBoost)) { + mc.thePlayer.cameraYaw = 0.07272727F; + if (hypixelCounter < 5) { + hypixelCounter += 1; + mc.timer.timerSpeed = 2.0F; + } else { + mc.timer.timerSpeed = 1.0F; + } + if (hypixelCounter2 < 112) { + hypixelCounter += 1; + mc.timer.timerSpeed = 2.0F; + } + if (hypixelCounter2 < 160) { + hypixelCounter2 += 1; + } + if (hypixelCounter2 >= 160) { + hypixelCounter2 = 100; + } + movementSpeed = MathUtil.getBaseMovementSpeed(); + double x = -(Math.sin(mc.thePlayer.getDirection()) * movementSpeed); + double z = Math.cos(mc.thePlayer.getDirection()) * movementSpeed; + e.setX(x); + e.setZ(z); + } else if (mode.getValue() == FlightMode.Area51) { + if (mc.thePlayer.moving()) { + mc.thePlayer.setSpeed(3.3299999237060547D); + mc.timer.timerSpeed = 0.32F; + } else { + mc.timer.timerSpeed = 0.88F; + mc.thePlayer.motionX = 0.0D; + mc.thePlayer.motionZ = 0.0D; + mc.thePlayer.motionY = 0.0D; + } + } else if (mode.getValue() == FlightMode.AGC) { + if (mc.thePlayer.moving()) { + mc.thePlayer.setSpeed(mc.thePlayer.ticksExisted % 3 == 0 ? 5 : 0); + } + if ((mc.thePlayer.ticksExisted % 10 == 0) && (mc.gameSettings.keyBindJump.pressed)) { + mc.thePlayer.setPosition(mc.thePlayer.posX, mc.thePlayer.posY + 5.0D, mc.thePlayer.posZ); + } else { + mc.thePlayer.motionY = 0.05D; + } + if ((mc.thePlayer.ticksExisted >= 10) && (!mc.gameSettings.keyBindJump.pressed)) { + mc.thePlayer.setPosition(mc.thePlayer.posX, mc.thePlayer.posY + 0.5D, mc.thePlayer.posZ); + mc.thePlayer.ticksExisted = 0; + } + } else if (mode.getValue() == FlightMode.GuardianLongJumpFly) { + if (getMinecraftgameSettings.keyBindJump.pressed) { + EventMove.y = getMinecraftthePlayer.motionY = 1.5D; + } + if (getMinecraftgameSettings.keyBindSneak.pressed) { + EventMove.y = getMinecraftthePlayer.motionY = -1.5D; + } + if ((mc.thePlayer.moving()) && (!getMinecraftgameSettings.keyBindJump.pressed) && + (!getMinecraftgameSettings.keyBindSneak.pressed)) + { + if ((getMinecraftthePlayer.motionY > -0.41D) && + (!getMinecraftthePlayer.onGround)) { + return; + } + for (int i = 0; i < 10; i++) { + mc.thePlayer.sendQueue.addToSendQueue(new C03PacketPlayer.C04PacketPlayerPosition(mc.thePlayer.posX, + mc.thePlayer.posY + 1.0E-9D, mc.thePlayer.posZ, true)); + } + mc.thePlayer.sendQueue.addToSendQueue(new C07PacketPlayerDigging( + C07PacketPlayerDigging.Action.RELEASE_USE_ITEM, BlockPos.ORIGIN, EnumFacing.DOWN)); + EventMove.y = getMinecraftthePlayer.motionY = 0.455D; + mc.thePlayer.setSpeed(7.0D); + } + } else { + mc.timer.timerSpeed = 1.0F; + } + } + + double getBaseMoveSpeed() + { + double baseSpeed = 0.275D; + if (mc.thePlayer.isPotionActive(Potion.moveSpeed)) { + int amplifier = mc.thePlayer.getActivePotionEffect(Potion.moveSpeed).getAmplifier(); + baseSpeed *= (1.0D + 0.2D * (amplifier + 1)); + } + return baseSpeed; + } + + public static enum FlightMode { + Vanilla, Guardian, Hypixel, Area51, HypixelBoost, OldGuardianLongJumpFly, GuardianLongJumpFly, AGC; + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/movement/Jesus.java b/src/minecraft/com/enjoytheban/module/modules/movement/Jesus.java new file mode 100644 index 0000000..d7012b7 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/movement/Jesus.java @@ -0,0 +1,65 @@ +package com.enjoytheban.module.modules.movement; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.misc.EventCollideWithBlock; +import com.enjoytheban.api.events.world.EventPacketSend; +import com.enjoytheban.api.events.world.EventPreUpdate; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import java.awt.Color; +import net.minecraft.block.BlockLiquid; +import net.minecraft.block.state.pattern.BlockHelper; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.settings.GameSettings; +import net.minecraft.client.settings.KeyBinding; +import net.minecraft.network.play.client.C03PacketPlayer; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; + + +public class Jesus + extends Module +{ + public Jesus() + { + super("Jesus", new String[] { "waterwalk", "float" }, ModuleType.Movement); + setColor(new Color(188, 233, 248).getRGB()); + } + + + + + private boolean canJeboos() + { + return (mc.thePlayer.fallDistance < 3.0F) && (!mc.gameSettings.keyBindJump.isPressed()) && (!BlockHelper.isInLiquid()) && + (!mc.thePlayer.isSneaking()); + } + + @EventHandler + public void onPre(EventPreUpdate e) + { + if ((BlockHelper.isInLiquid()) && (!mc.thePlayer.isSneaking()) && (!mc.gameSettings.keyBindJump.isPressed())) { + mc.thePlayer.motionY = 0.05D; + mc.thePlayer.onGround = true; + } + } + + @EventHandler + public void onPacket(EventPacketSend e) + { + if (((e.getPacket() instanceof C03PacketPlayer)) && (canJeboos()) && (BlockHelper.isOnLiquid())) { + C03PacketPlayer packet = (C03PacketPlayer)e.getPacket(); + y = (mc.thePlayer.ticksExisted % 2 == 0 ? y + 0.01D : y - 0.01D); + } + } + + @EventHandler + public void onBB(EventCollideWithBlock e) + { + if (((e.getBlock() instanceof BlockLiquid)) && (canJeboos())) { + e.setBoundingBox(new AxisAlignedBB(e.getPos().getX(), e.getPos().getY(), e.getPos().getZ(), + e.getPos().getX() + 1.0D, e.getPos().getY() + 1.0D, e.getPos().getZ() + 1.0D)); + } + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/movement/Longjump.java b/src/minecraft/com/enjoytheban/module/modules/movement/Longjump.java new file mode 100644 index 0000000..512d424 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/movement/Longjump.java @@ -0,0 +1,207 @@ +package com.enjoytheban.module.modules.movement; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventMove; +import com.enjoytheban.api.events.world.EventPreUpdate; +import com.enjoytheban.api.value.Mode; +import com.enjoytheban.api.value.Value; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import com.enjoytheban.utils.math.MathUtil; +import java.awt.Color; +import java.util.List; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.network.play.client.C03PacketPlayer.C04PacketPlayerPosition; +import net.minecraft.potion.Potion; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.MovementInput; + +public class Longjump + extends Module +{ + private Mode mode = new Mode("Mode", "mode", JumpMode.values(), JumpMode.NCP); + + private int stage; + private double moveSpeed; + private double lastDist; + + public Longjump() + { + super("LongJump", new String[] { "lj", "jumpman", "jump" }, ModuleType.Movement); + addValues(new Value[] { mode }); + setColor(new Color(76, 67, 216).getRGB()); + } + + public void onDisable() + { + mc.timer.timerSpeed = 1.0F; + if (mode.getValue() == JumpMode.Area51) { + mc.thePlayer.motionX = 0.0D; + mc.thePlayer.motionZ = 0.0D; + } + if (mc.thePlayer != null) { + moveSpeed = getBaseMoveSpeed(); + } + lastDist = 0.0D; + stage = 0; + } + + @EventHandler + private void onUpdate(EventPreUpdate e) + { + setSuffix(mode.getValue()); + if (mode.getValue() == JumpMode.OldGuardian) { + if ((mc.thePlayer.moving()) && (mc.thePlayer.onGround)) + { + mc.thePlayer.motionY = 0.44D; + + mc.thePlayer.sendQueue.addToSendQueue(new C03PacketPlayer.C04PacketPlayerPosition(mc.thePlayer.posX, + mc.thePlayer.posY + 1.0E-9D, mc.thePlayer.posZ, mc.thePlayer.onGround)); + mc.thePlayer.setSpeed(7.0D); + } + else { + mc.thePlayer.setSpeed(Math.sqrt( + mc.thePlayer.motionX * mc.thePlayer.motionX + mc.thePlayer.motionZ * mc.thePlayer.motionZ)); + } + } + else if (mode.getValue() == JumpMode.Area51) { + if (mc.thePlayer.moving()) { + mc.timer.timerSpeed = 0.33F; + if (mc.thePlayer.onGround) { + mc.thePlayer.setSpeed(5.0D); + mc.thePlayer.motionY = 0.45500001311302185D; + } else { + mc.thePlayer.setSpeed(7.0D); + } + } else { + mc.timer.timerSpeed = 0.33F; + mc.thePlayer.motionX = 0.0D; + mc.thePlayer.motionZ = 0.0D; + } + } else if ((mode.getValue() == JumpMode.Janitor) && (e.getType() == 0) && (mc.thePlayer.moving()) && + (mc.thePlayer.onGround)) { + e.setY(e.getY() + (mc.thePlayer.ticksExisted % 2 == 0 ? MathUtil.getHighestOffset(0.1D) : 0.0D)); + } + else if (e.getType() == 0) { + double xDist = mc.thePlayer.posX - mc.thePlayer.prevPosX; + double zDist = mc.thePlayer.posZ - mc.thePlayer.prevPosZ; + lastDist = Math.sqrt(xDist * xDist + zDist * zDist); + } + } + + + @EventHandler + private void onMove(EventMove e) + { + if (mode.getValue() == JumpMode.NCP) { + if ((mc.thePlayer.moveStrafing <= 0.0F) && (mc.thePlayer.moveForward <= 0.0F)) { + stage = 1; + } + + if ((stage == 1) && ((mc.thePlayer.moveForward != 0.0F) || (mc.thePlayer.moveStrafing != 0.0F))) { + stage = 2; + moveSpeed = (3.0D * getBaseMoveSpeed() - 0.01D); + } else if (stage == 2) { + stage = 3; + mc.thePlayer.motionY = 0.424D; + EventMove.y = 0.424D; + moveSpeed *= 2.149802D; + } else if (stage == 3) { + stage = 4; + double difference = 0.66D * (lastDist - getBaseMoveSpeed()); + moveSpeed = (lastDist - difference); + } + else { + if ((mc.theWorld.getCollidingBoundingBoxes(mc.thePlayer, mc.thePlayer.boundingBox.offset(0.0D, mc.thePlayer.motionY, 0.0D)).size() > 0) || + (mc.thePlayer.isCollidedVertically)) { + stage = 1; + } + moveSpeed = (lastDist - lastDist / 159.0D); + } + moveSpeed = Math.max(moveSpeed, getBaseMoveSpeed()); + MovementInput movementInput = mc.thePlayer.movementInput; + float forward = moveForward; + float strafe = moveStrafe; + float yaw = mc.thePlayer.rotationYaw; + if ((forward == 0.0F) && (strafe == 0.0F)) { + EventMove.x = 0.0D; + EventMove.z = 0.0D; + } else if (forward != 0.0F) { + if (strafe >= 1.0F) { + yaw += (forward > 0.0F ? -45 : 45); + strafe = 0.0F; + } else if (strafe <= -1.0F) { + yaw += (forward > 0.0F ? 45 : -45); + strafe = 0.0F; + } + if (forward > 0.0F) { + forward = 1.0F; + } else if (forward < 0.0F) { + forward = -1.0F; + } + } + double mx = Math.cos(Math.toRadians(yaw + 90.0F)); + double mz = Math.sin(Math.toRadians(yaw + 90.0F)); + EventMove.x = forward * moveSpeed * mx + strafe * moveSpeed * mz; + EventMove.z = forward * moveSpeed * mz - strafe * moveSpeed * mx; + if ((forward == 0.0F) && (strafe == 0.0F)) { + EventMove.x = 0.0D; + EventMove.z = 0.0D; + } else if (forward != 0.0F) { + if (strafe >= 1.0F) { + yaw += (forward > 0.0F ? -45 : 45); + strafe = 0.0F; + } else if (strafe <= -1.0F) { + yaw += (forward > 0.0F ? 45 : -45); + strafe = 0.0F; + } + if (forward > 0.0F) { + forward = 1.0F; + } else if (forward < 0.0F) { + forward = -1.0F; + } + } + } else if ((mode.getValue() == JumpMode.Janitor) && (mc.thePlayer.moving())) { + moveSpeed = (MathUtil.getBaseMovementSpeed() * (mc.thePlayer.ticksExisted % 2 != 0 ? 5 : 6)); + double x = -(Math.sin(mc.thePlayer.getDirection()) * moveSpeed); + double z = Math.cos(mc.thePlayer.getDirection()) * moveSpeed; + e.setX(x); + e.setZ(z); + if (mc.thePlayer.onGround) + e.setY(mc.thePlayer.motionY = 0.3D); + } else if ((mode.getValue() == JumpMode.Guardian) && (mc.thePlayer.moving())) { + if ((mc.thePlayer.moveForward != 0.0F) || (mc.thePlayer.moveStrafing != 0.0F)) { + if (mc.thePlayer.onGround) { + for (int i = 0; i < 20; i++) + { + mc.thePlayer.sendQueue.addToSendQueue(new C03PacketPlayer.C04PacketPlayerPosition(mc.thePlayer.posX, + mc.thePlayer.posY + 1.0E-9D, mc.thePlayer.posZ, mc.thePlayer.onGround)); + } + EventMove.y = mc.thePlayer.motionY = 0.4D; + mc.thePlayer.setSpeed(8.0D); + } + } else { + mc.thePlayer.motionX = 0.0D; + mc.thePlayer.motionZ = 0.0D; + } + } + } + + double getBaseMoveSpeed() + { + double baseSpeed = 0.2873D; + if (mc.thePlayer.isPotionActive(Potion.moveSpeed)) { + int amplifier = mc.thePlayer.getActivePotionEffect(Potion.moveSpeed).getAmplifier(); + baseSpeed *= (1.0D + 0.2D * (amplifier + 1)); + } + return baseSpeed; + } + + static enum JumpMode { + NCP, OldGuardian, Guardian, Janitor, Area51; + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/movement/NoSlow.java b/src/minecraft/com/enjoytheban/module/modules/movement/NoSlow.java new file mode 100644 index 0000000..f4e71fc --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/movement/NoSlow.java @@ -0,0 +1,39 @@ +package com.enjoytheban.module.modules.movement; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventPreUpdate; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import com.enjoytheban.utils.Helper; +import java.awt.Color; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.network.play.client.C07PacketPlayerDigging; +import net.minecraft.network.play.client.C07PacketPlayerDigging.Action; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; + + + + + + + +public class NoSlow + extends Module +{ + public NoSlow() + { + super("NoSlow", new String[] { "noslowdown" }, ModuleType.Movement); + setColor(new Color(216, 253, 100).getRGB()); + } + + @EventHandler + private void onUpdate(EventPreUpdate e) { + if ((mc.thePlayer.isBlocking()) && (!Helper.onServer("invaded")) && (!Helper.onServer("hypixel")) && (!Helper.onServer("faithful")) && (!Helper.onServer("mineman"))) { + mc.thePlayer.sendQueue.addToSendQueue(new C07PacketPlayerDigging( + C07PacketPlayerDigging.Action.RELEASE_USE_ITEM, BlockPos.ORIGIN, EnumFacing.DOWN)); + } + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/movement/Scaffold.java b/src/minecraft/com/enjoytheban/module/modules/movement/Scaffold.java new file mode 100644 index 0000000..7f5662a --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/movement/Scaffold.java @@ -0,0 +1,206 @@ +package com.enjoytheban.module.modules.movement; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventPostUpdate; +import com.enjoytheban.api.events.world.EventPreUpdate; +import com.enjoytheban.api.value.Option; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import com.enjoytheban.utils.math.RotationUtil; +import java.awt.Color; +import java.util.Arrays; +import net.minecraft.block.Block; +import net.minecraft.block.BlockAir; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.multiplayer.PlayerControllerMP; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.client.settings.GameSettings; +import net.minecraft.client.settings.KeyBinding; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.network.play.client.C09PacketHeldItemChange; +import net.minecraft.network.play.client.C0APacketAnimation; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.Vec3; +import net.minecraft.util.Vec3i; + +public class Scaffold extends Module +{ + private Option tower = new Option("Tower", "tower", Boolean.valueOf(true)); + private Option silent = new Option("Silent", "Silent", Boolean.valueOf(true)); + private Option aac = new Option("AAC", "AAC", Boolean.valueOf(false)); + + + + private java.util.List invalid = Arrays.asList(new Block[] { Blocks.air, Blocks.water, Blocks.fire, Blocks.flowing_water, Blocks.lava, + Blocks.flowing_lava, Blocks.chest, Blocks.enchanting_table, Blocks.tnt }); + + private BlockCache blockCache; + + private int currentItem; + + + public Scaffold() + { + super("Scaffold", new String[] { "magiccarpet", "blockplacer", "airwalk" }, ModuleType.Movement); + addValues(new com.enjoytheban.api.value.Value[] { tower, silent, aac }); + currentItem = 0; + setColor(new Color(244, 119, 194).getRGB()); + } + + public void onEnable() + { + currentItem = mc.thePlayer.inventory.currentItem; + } + + public void onDisable() + { + mc.thePlayer.inventory.currentItem = currentItem; + } + + + + + + + + @EventHandler + private void onUpdate(EventPreUpdate event) + { + if (((Boolean)aac.getValue()).booleanValue()) { + mc.thePlayer.setSprinting(false); + } + if (grabBlockSlot() == -1) { + return; + } + blockCache = grab(); + if (blockCache == null) { + return; + } + float[] rotations = RotationUtil.grabBlockRotations(blockCache.getPosition()); + event.setYaw(rotations[0]); + event.setPitch( + RotationUtil.getVecRotation(grabPosition(blockCache.getPosition(), blockCache.getFacing()))[1] - + 3.0F); + } + + @EventHandler + private void onPostUpdate(EventPostUpdate event) { + if (blockCache == null) { + return; + } + if ((mc.gameSettings.keyBindJump.getIsKeyPressed()) && (((Boolean)tower.getValue()).booleanValue())) { + mc.thePlayer.setSprinting(false); + mc.thePlayer.motionY = 0.0D; + mc.thePlayer.motionX = 0.0D; + mc.thePlayer.motionZ = 0.0D; + mc.thePlayer.jump(); + } + + int currentSlot = mc.thePlayer.inventory.currentItem; + int slot = grabBlockSlot(); + mc.thePlayer.inventory.currentItem = slot; + if (placeBlock(blockCache.position, blockCache.facing)) { + if (((Boolean)silent.getValue()).booleanValue()) { + mc.thePlayer.inventory.currentItem = currentSlot; + mc.thePlayer.sendQueue.addToSendQueue(new C09PacketHeldItemChange(currentSlot)); + } + + blockCache = null; + } + } + + private boolean placeBlock(BlockPos pos, EnumFacing facing) + { + Vec3 eyesPos = new Vec3(mc.thePlayer.posX, mc.thePlayer.posY + mc.thePlayer.getEyeHeight(), + mc.thePlayer.posZ); + + + if (mc.playerController.func_178890_a(mc.thePlayer, mc.theWorld, mc.thePlayer.getHeldItem(), pos, facing, new Vec3(blockCache.position).addVector(0.5D, 0.5D, 0.5D).add(new Vec3(blockCache.facing.getDirectionVec()).scale(0.5D)))) { + mc.thePlayer.sendQueue.addToSendQueue(new C0APacketAnimation()); + return true; + } + return false; + } + + private Vec3 grabPosition(BlockPos position, EnumFacing facing) + { + Vec3 offset = new Vec3(facing.getDirectionVec().getX() / 2.0D, facing.getDirectionVec().getY() / 2.0D, + facing.getDirectionVec().getZ() / 2.0D); + + Vec3 point = new Vec3(position.getX() + 0.5D, position.getY() + 0.5D, position.getZ() + 0.5D); + + return point.add(offset); + } + + private BlockCache grab() + { + EnumFacing[] invert = { EnumFacing.UP, EnumFacing.DOWN, EnumFacing.SOUTH, EnumFacing.NORTH, EnumFacing.EAST, + EnumFacing.WEST }; + BlockPos position = new BlockPos(mc.thePlayer.getPositionVector()).offset(EnumFacing.DOWN); + if (!(mc.theWorld.getBlockState(position).getBlock() instanceof BlockAir)) + return null; + BlockPos offset; + for (EnumFacing facing : EnumFacing.values()) { + offset = position.offset(facing); + IBlockState blockState = mc.theWorld.getBlockState(offset); + if (!(mc.theWorld.getBlockState(offset).getBlock() instanceof BlockAir)) { + return new BlockCache(offset, invert[facing.ordinal()], null); + } + } + BlockPos[] offsets = { new BlockPos(-1, 0, 0), new BlockPos(1, 0, 0), new BlockPos(0, 0, -1), + new BlockPos(0, 0, 1) }; + if (mc.thePlayer.onGround) { + for (BlockPos offset : offsets) { + BlockPos offsetPos = position.add(offset.getX(), 0, offset.getZ()); + IBlockState blockState2 = mc.theWorld.getBlockState(offsetPos); + if ((mc.theWorld.getBlockState(offsetPos).getBlock() instanceof BlockAir)) { + for (EnumFacing facing2 : EnumFacing.values()) { + BlockPos offset2 = offsetPos.offset(facing2); + IBlockState blockState3 = mc.theWorld.getBlockState(offset2); + if (!(mc.theWorld.getBlockState(offset2).getBlock() instanceof BlockAir)) { + return new BlockCache(offset2, invert[facing2.ordinal()], null); + } + } + } + } + } + return null; + } + + private int grabBlockSlot() + { + for (int i = 0; i < 9; i++) { + ItemStack itemStack = mc.thePlayer.inventory.mainInventory[i]; + if ((itemStack != null) && ((itemStack.getItem() instanceof ItemBlock))) { + return i; + } + } + return -1; + } + + private class BlockCache + { + private BlockPos position; + private EnumFacing facing; + + private BlockCache(BlockPos position, EnumFacing facing) { + this.position = position; + this.facing = facing; + } + + private BlockPos getPosition() { + return position; + } + + private EnumFacing getFacing() { + return facing; + } + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/movement/Sneak.java b/src/minecraft/com/enjoytheban/module/modules/movement/Sneak.java new file mode 100644 index 0000000..37c6439 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/movement/Sneak.java @@ -0,0 +1,45 @@ +package com.enjoytheban.module.modules.movement; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventPreUpdate; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import java.awt.Color; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.network.play.client.C0BPacketEntityAction; +import net.minecraft.network.play.client.C0BPacketEntityAction.Action; + + + +public class Sneak + extends Module +{ + public Sneak() + { + super("Sneak", new String[] { "stealth", "snek" }, ModuleType.Movement); + setColor(new Color(84, 194, 110).getRGB()); + } + + @EventHandler + private void onUpdate(EventPreUpdate e) + { + if (e.getType() == 0) { + if ((mc.thePlayer.isSneaking()) || (mc.thePlayer.moving())) + return; + mc.thePlayer.sendQueue.addToSendQueue( + new C0BPacketEntityAction(mc.thePlayer, C0BPacketEntityAction.Action.STOP_SNEAKING)); + } + else if (e.getType() == 1) { + mc.thePlayer.sendQueue.addToSendQueue( + new C0BPacketEntityAction(mc.thePlayer, C0BPacketEntityAction.Action.START_SNEAKING)); + } + } + + public void onDisable() + { + mc.thePlayer.sendQueue.addToSendQueue( + new C0BPacketEntityAction(mc.thePlayer, C0BPacketEntityAction.Action.STOP_SNEAKING)); + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/movement/Speed.java b/src/minecraft/com/enjoytheban/module/modules/movement/Speed.java new file mode 100644 index 0000000..99d2050 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/movement/Speed.java @@ -0,0 +1,286 @@ +package com.enjoytheban.module.modules.movement; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventMove; +import com.enjoytheban.api.events.world.EventPreUpdate; +import com.enjoytheban.api.value.Mode; +import com.enjoytheban.api.value.Value; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import com.enjoytheban.utils.Helper; +import com.enjoytheban.utils.TimerUtil; +import com.enjoytheban.utils.math.MathUtil; +import java.awt.Color; +import java.util.List; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.network.play.client.C03PacketPlayer.C04PacketPlayerPosition; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.MovementInput; + + +public class Speed + extends Module +{ + private Mode mode = new Mode("Mode", "mode", SpeedMode.values(), SpeedMode.HypixelHop); + private int stage; + private double movementSpeed; + private double distance; + + public Speed() + { + super("Speed", new String[] { "zoom" }, ModuleType.Movement); + setColor(new Color(99, 248, 91).getRGB()); + addValues(new Value[] { mode }); + } + + private TimerUtil timer = new TimerUtil(); + + public void onDisable() + { + mc.timer.timerSpeed = 1.0F; + if (mode.getValue() == SpeedMode.Area51) { + mc.thePlayer.motionX = 0.0D; + mc.thePlayer.motionZ = 0.0D; + } + } + + private boolean canZoom() { + return (mc.thePlayer.moving()) && (mc.thePlayer.onGround); + } + + @EventHandler + private void onUpdate(EventPreUpdate e) + { + if (Helper.onServer("enjoytheban")) { + mode.setValue(SpeedMode.Bhop); + } + setSuffix(mode.getValue()); + if ((mode.getValue() == SpeedMode.Sloth) && (canZoom())) { + if (mc.thePlayer.moving()) { + boolean under = mc.theWorld.getCollidingBoundingBoxes(mc.thePlayer, + mc.thePlayer.getEntityBoundingBox().offset(mc.thePlayer.motionX, 1.6D, mc.thePlayer.motionZ)) + .isEmpty(); + if ((mc.thePlayer.ticksExisted % 2 != 0) && (under)) { + y += 0.42D; + } + mc.thePlayer.motionY = -10.0D; + if (mc.thePlayer.onGround) + { + mc.thePlayer.setSpeed(mc.thePlayer.getSpeed() * (mc.thePlayer.ticksExisted % 2 == 0 ? 4.0F : 0.28F)); } + } + } else { + if ((mode.getValue() == SpeedMode.Onground) && (canZoom())) {} + switch (stage) { + case 1: + e.setY(e.getY() + 0.4D); + e.setOnground(false); + + stage += 1; + break; + case 2: + e.setY(e.getY() + 0.4D); + e.setOnground(false); + stage += 1; + break; + default: + stage = 1; + + + + + break; if ((mode.getValue() != SpeedMode.Janitor) || (e.getType() != 0) || (!canZoom())) + if (mode.getValue() == SpeedMode.AGC) { + double speed = 0.2D; + double x = Math.cos(Math.toRadians(mc.thePlayer.rotationYaw + 90.0F)); + double z = Math.sin(Math.toRadians(mc.thePlayer.rotationYaw + 90.0F)); + double n = mc.thePlayer.movementInput.moveForward * speed * x; + double xOff = n + mc.thePlayer.movementInput.moveStrafe * speed * z; + double n2 = mc.thePlayer.movementInput.moveForward * speed * z; + double zOff = n2 - mc.thePlayer.movementInput.moveStrafe * 0.5F * x; + + mc.thePlayer.setAIMoveSpeed(mc.thePlayer.getAIMoveSpeed()); + if (mc.thePlayer.onGround) { + if (mc.thePlayer.moving()) { + mc.thePlayer.motionY = 0.2D; + } + } + else if (mc.thePlayer.motionY <= -0.10000000149011612D) { + double cock = 10.0D; + mc.thePlayer.setPosition(mc.thePlayer.posX + xOff * cock, mc.thePlayer.posY, + mc.thePlayer.posZ + zOff * cock); + mc.thePlayer.motionY -= 0.0010000000474974513D; + } + } + else if ((mode.getValue() != SpeedMode.OldGuardian) && (mode.getValue() != SpeedMode.GuardianYport)) { + double xDist = mc.thePlayer.posX - mc.thePlayer.prevPosX; + double zDist = mc.thePlayer.posZ - mc.thePlayer.prevPosZ; + distance = Math.sqrt(xDist * xDist + zDist * zDist); + } else if (mode.getValue() == SpeedMode.GuardianYport) { + if (mc.thePlayer.moving()) { + mc.timer.timerSpeed = 1.6F; + } else + mc.timer.timerSpeed = 1.0F; + if ((mc.thePlayer.moving()) && (mc.thePlayer.onGround)) + { + mc.thePlayer.motionY = 0.12D; + mc.thePlayer.motionY -= 0.04D; + mc.thePlayer.sendQueue.addToSendQueue(new C03PacketPlayer.C04PacketPlayerPosition(mc.thePlayer.posX, + mc.thePlayer.posY + 1.0E-9D, mc.thePlayer.posZ, mc.thePlayer.onGround)); + + mc.thePlayer.setSpeed(0.7D); + } + else { + mc.thePlayer.setSpeed(Math.sqrt( + mc.thePlayer.motionX * mc.thePlayer.motionX + mc.thePlayer.motionZ * mc.thePlayer.motionZ)); + } + } + else if ((mc.thePlayer.moving()) && (mc.thePlayer.onGround)) + { + mc.thePlayer.motionY = 0.4D; + mc.thePlayer.sendQueue.addToSendQueue(new C03PacketPlayer.C04PacketPlayerPosition(mc.thePlayer.posX, + mc.thePlayer.posY + 1.0E-9D, mc.thePlayer.posZ, mc.thePlayer.onGround)); + + mc.thePlayer.setSpeed(1.75D); + } + else { + mc.thePlayer.setSpeed(Math.sqrt( + mc.thePlayer.motionX * mc.thePlayer.motionX + mc.thePlayer.motionZ * mc.thePlayer.motionZ)); + } + break; } + } + } + + @EventHandler + private void onMove(EventMove e) { + if (mode.getValue() == SpeedMode.HypixelHop) { + if ((canZoom()) && (stage == 1)) { + movementSpeed = (1.56D * MathUtil.getBaseMovementSpeed() - 0.01D); + mc.timer.timerSpeed = 1.15F; + } else if ((canZoom()) && (stage == 2)) { + e.setY(mc.thePlayer.motionY = 0.3999D); + movementSpeed *= 1.58D; + mc.timer.timerSpeed = 1.2F; + } else if (stage == 3) { + double difference = 0.66D * (distance - MathUtil.getBaseMovementSpeed()); + movementSpeed = (distance - difference); + mc.timer.timerSpeed = 1.1F; + } else { + List collidingList = mc.theWorld.getCollidingBoundingBoxes(mc.thePlayer, + mc.thePlayer.boundingBox.offset(0.0D, mc.thePlayer.motionY, 0.0D)); + if ((collidingList.size() > 0) || ((mc.thePlayer.isCollidedVertically) && (stage > 0))) { + stage = (mc.thePlayer.moving() ? 1 : 0); + } + movementSpeed = (distance - distance / 159.0D); + } + mc.thePlayer.setMoveSpeed(e, this.movementSpeed = Math.max(movementSpeed, MathUtil.getBaseMovementSpeed())); + if (mc.thePlayer.moving()) { + stage += 1; + } + } else if (mode.getValue() == SpeedMode.Area51) { + if (mc.thePlayer.moving()) { + if (getMinecraftthePlayer.motionY <= 0.0D) { + getMinecraftthePlayer.motionY *= 1.5D; + } + mc.thePlayer.onGround = true; + mc.timer.timerSpeed = 0.33F; + mc.thePlayer.setSpeed(4.0D); + } else { + mc.thePlayer.motionX = 0.0D; + mc.thePlayer.motionZ = 0.0D; + } + } else if ((mode.getValue() == SpeedMode.Onground) && (canZoom())) { + switch (stage) { + case 1: + mc.timer.timerSpeed = 1.22F; + movementSpeed = (1.89D * MathUtil.getBaseMovementSpeed() - 0.01D); + distance += 1.0D; + if (distance == 1.0D) { + e.setY(e.getY() + 8.0E-6D); + } else if (distance == 2.0D) { + e.setY(e.getY() - 8.0E-6D); + distance = 0.0D; + } + break; + case 2: + movementSpeed = (1.2D * MathUtil.getBaseMovementSpeed() - 0.01D); + break; + default: + movementSpeed = ((float)MathUtil.getBaseMovementSpeed()); + } + mc.thePlayer.setMoveSpeed(e, this.movementSpeed = Math.max(movementSpeed, MathUtil.getBaseMovementSpeed())); + stage += 1; + } else if ((mode.getValue() == SpeedMode.Janitor) && (canZoom())) { + mc.thePlayer.setSpeed(mc.thePlayer.ticksExisted % 2 != 0 ? 0 : 2); + } + else if (mode.getValue() == SpeedMode.Mineplex) { + mc.timer.timerSpeed = 1.1F; + if ((canZoom()) && (stage == 1)) { + movementSpeed = 0.58D; + } else if ((canZoom()) && (stage == 2)) { + e.setY(mc.thePlayer.motionY = 0.3D); + movementSpeed = 0.64D; + } else if (stage == 3) { + double difference = 0.66D * (distance - MathUtil.getBaseMovementSpeed()); + movementSpeed = (distance - difference); + } else { + List collidingList = mc.theWorld.getCollidingBoundingBoxes(mc.thePlayer, + mc.thePlayer.boundingBox.offset(0.0D, mc.thePlayer.motionY, 0.0D)); + if ((collidingList.size() > 0) || ((mc.thePlayer.isCollidedVertically) && (stage > 0))) { + stage = (mc.thePlayer.moving() ? 1 : 0); + } + movementSpeed = (distance - distance / 159.0D); + } + mc.thePlayer.setMoveSpeed(e, this.movementSpeed = Math.max(movementSpeed, MathUtil.getBaseMovementSpeed())); + if (mc.thePlayer.moving()) { + stage += 1; + } + } else if (mode.getValue() == SpeedMode.Bhop) { + mc.timer.timerSpeed = 1.07F; + if ((canZoom()) && (stage == 1)) { + movementSpeed = (2.55D * MathUtil.getBaseMovementSpeed() - 0.01D); + } else if ((canZoom()) && (stage == 2)) { + e.setY(mc.thePlayer.motionY = 0.3999D); + movementSpeed *= 2.1D; + } else if (stage == 3) { + double difference = 0.66D * (distance - MathUtil.getBaseMovementSpeed()); + movementSpeed = (distance - difference); + } else { + List collidingList = mc.theWorld.getCollidingBoundingBoxes(mc.thePlayer, + mc.thePlayer.boundingBox.offset(0.0D, mc.thePlayer.motionY, 0.0D)); + if ((collidingList.size() > 0) || ((mc.thePlayer.isCollidedVertically) && (stage > 0))) { + stage = (mc.thePlayer.moving() ? 1 : 0); + } + movementSpeed = (distance - distance / 159.0D); + } + mc.thePlayer.setMoveSpeed(e, this.movementSpeed = Math.max(movementSpeed, MathUtil.getBaseMovementSpeed())); + if (mc.thePlayer.moving()) { + stage += 1; + } + } else if (mode.getValue() == SpeedMode.Guardian) { + if (mc.thePlayer.moving()) { + if (mc.thePlayer.onGround) { + for (int i = 0; i < 20; i++) + { + mc.thePlayer.sendQueue.addToSendQueue(new C03PacketPlayer.C04PacketPlayerPosition(mc.thePlayer.posX, + mc.thePlayer.posY + 1.0E-9D, mc.thePlayer.posZ, mc.thePlayer.onGround)); + } + mc.thePlayer.setSpeed(1.399999976158142D); + EventMove.y = mc.thePlayer.motionY = 0.4D; + } else { + mc.thePlayer.setSpeed((float)Math.sqrt( + mc.thePlayer.motionX * mc.thePlayer.motionX + mc.thePlayer.motionZ * mc.thePlayer.motionZ)); + } + } else { + mc.thePlayer.motionX = 0.0D; + mc.thePlayer.motionZ = 0.0D; + } + } + } + + static enum SpeedMode { + Bhop, HypixelHop, Onground, OldGuardian, Guardian, GuardianYport, Mineplex, AGC, Janitor, Sloth, Area51; + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/movement/Sprint.java b/src/minecraft/com/enjoytheban/module/modules/movement/Sprint.java new file mode 100644 index 0000000..d985fe3 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/movement/Sprint.java @@ -0,0 +1,33 @@ +package com.enjoytheban.module.modules.movement; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventPreUpdate; +import com.enjoytheban.api.value.Option; +import com.enjoytheban.api.value.Value; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import java.awt.Color; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.util.FoodStats; + + +public class Sprint + extends Module +{ + private Option omni = new Option("Omni-Directional", "omni", Boolean.valueOf(true)); + + public Sprint() { + super("Sprint", new String[] { "run" }, ModuleType.Movement); + + setColor(new Color(158, 205, 125).getRGB()); + addValues(new Value[] { omni }); + } + + @EventHandler + private void onUpdate(EventPreUpdate event) { + if ((mc.thePlayer.getFoodStats().getFoodLevel() > 6) && (((Boolean)omni.getValue()).booleanValue()) ? mc.thePlayer.moving() : mc.thePlayer.moveForward > 0.0F) { + mc.thePlayer.setSprinting(true); + } + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/movement/Step.java b/src/minecraft/com/enjoytheban/module/modules/movement/Step.java new file mode 100644 index 0000000..b4c5800 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/movement/Step.java @@ -0,0 +1,79 @@ +package com.enjoytheban.module.modules.movement; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventPreUpdate; +import com.enjoytheban.api.value.Numbers; +import com.enjoytheban.api.value.Option; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import java.awt.Color; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.network.play.client.C03PacketPlayer.C04PacketPlayerPosition; + +public class Step extends Module +{ + private Numbers height = new Numbers("Height", "height", Double.valueOf(1.0D), Double.valueOf(1.0D), Double.valueOf(10.0D), Double.valueOf(0.5D)); + private Option ncp = new Option("NCP", "ncp", Boolean.valueOf(false)); + + public Step() { + super("Step", new String[] { "autojump" }, ModuleType.Movement); + setColor(new Color(165, 238, 65).getRGB()); + addValues(new com.enjoytheban.api.value.Value[] { ncp }); + } + + public void onDisable() + { + mc.thePlayer.stepHeight = 0.6F; + } + + @EventHandler + private void onUpdate(EventPreUpdate e) { + if (((Boolean)ncp.getValue()).booleanValue()) { + mc.thePlayer.stepHeight = 0.6F; + if ((mc.thePlayer.isCollidedHorizontally) && (mc.thePlayer.onGround) && (mc.thePlayer.isCollidedVertically) && + (mc.thePlayer.isCollided) && + (mc.thePlayer.isCollidedHorizontally) && (mc.thePlayer.onGround) && + (mc.thePlayer.isCollidedVertically) && (mc.thePlayer.isCollided)) { + mc.thePlayer.setSprinting(true); + mc.thePlayer.sendQueue.addToSendQueue(new C03PacketPlayer.C04PacketPlayerPosition( + mc.thePlayer.posX, mc.thePlayer.posY + 0.42D, mc.thePlayer.posZ, + mc.thePlayer.onGround)); + mc.thePlayer.setSprinting(true); + mc.thePlayer.sendQueue.addToSendQueue(new C03PacketPlayer.C04PacketPlayerPosition( + mc.thePlayer.posX, mc.thePlayer.posY + 0.753D, mc.thePlayer.posZ, + mc.thePlayer.onGround)); + mc.thePlayer.setSprinting(true); + mc.thePlayer.setPosition(mc.thePlayer.posX, mc.thePlayer.posY + 0.42D, + mc.thePlayer.posZ); + mc.timer.timerSpeed = 0.5F; + mc.thePlayer.setSprinting(true); + new Thread(new Runnable() + { + public void run() { + try { + Thread.sleep(100L); + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + mc.timer.timerSpeed = 1.0F; + } + }) + + + + + + + + + + .start(); + } + } + else { + mc.thePlayer.stepHeight = 1.0F; + } + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/movement/Teleport.java b/src/minecraft/com/enjoytheban/module/modules/movement/Teleport.java new file mode 100644 index 0000000..cf6206f --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/movement/Teleport.java @@ -0,0 +1,57 @@ +package com.enjoytheban.module.modules.movement; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventPreUpdate; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import java.awt.Color; +import java.util.Random; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.renderer.RenderGlobal; +import net.minecraft.network.play.client.C03PacketPlayer.C04PacketPlayerPosition; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.Vec3; +import org.lwjgl.input.Mouse; + +public class Teleport extends Module +{ + public Teleport() + { + super("Teleport", new String[] { "teleport" }, ModuleType.Movement); + setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)).getRGB()); + } + + @EventHandler + private void onUpdate(EventPreUpdate event) { + MovingObjectPosition ray = rayTrace(500.0D); + if (ray == null) { + return; + } + if (Mouse.isButtonDown(1)) { + double x_new = ray.func_178782_a().getX() + 0.5D; + double y_new = ray.func_178782_a().getY() + 1; + double z_new = ray.func_178782_a().getZ() + 0.5D; + double distance = mc.thePlayer.getDistance(x_new, y_new, z_new); for (double d = 0.0D; d < distance; d += 2.0D) { + setPos(mc.thePlayer.posX + (x_new - mc.thePlayer.func_174811_aO().getFrontOffsetX() - mc.thePlayer.posX) * d / distance, mc.thePlayer.posY + (y_new - mc.thePlayer.posY) * d / distance, mc.thePlayer.posZ + (z_new - mc.thePlayer.func_174811_aO().getFrontOffsetZ() - mc.thePlayer.posZ) * d / distance); + } + setPos(x_new, y_new, z_new); + mc.renderGlobal.loadRenderers(); + } + } + + public MovingObjectPosition rayTrace(double blockReachDistance) { + Vec3 vec3 = mc.thePlayer.func_174824_e(1.0F); + Vec3 vec4 = mc.thePlayer.getLookVec(); + Vec3 vec5 = vec3.addVector(xCoord * blockReachDistance, yCoord * blockReachDistance, + zCoord * blockReachDistance); + return mc.theWorld.rayTraceBlocks(vec3, vec5, !mc.thePlayer.isInWater(), false, false); + } + + public void setPos(double x, double y, double z) { + mc.thePlayer.sendQueue.addToSendQueue(new C03PacketPlayer.C04PacketPlayerPosition(x, y, z, true)); + mc.thePlayer.setPosition(x, y, z); + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/player/AntiVelocity.java b/src/minecraft/com/enjoytheban/module/modules/player/AntiVelocity.java new file mode 100644 index 0000000..c33fe7b --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/player/AntiVelocity.java @@ -0,0 +1,49 @@ +package com.enjoytheban.module.modules.player; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventPacketRecieve; +import com.enjoytheban.api.value.Numbers; +import com.enjoytheban.api.value.Value; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import java.awt.Color; +import net.minecraft.network.play.server.S12PacketEntityVelocity; +import net.minecraft.network.play.server.S27PacketExplosion; + + + + + + + + +public class AntiVelocity + extends Module +{ + private Numbers percentage = new Numbers("Percentage", "percentage", Double.valueOf(0.0D), Double.valueOf(0.0D), Double.valueOf(100.0D), Double.valueOf(5.0D)); + + public AntiVelocity() { + super("Velocity", new String[] { "antivelocity", "antiknockback", "antikb" }, ModuleType.Player); + addValues(new Value[] { percentage }); + setColor(new Color(191, 191, 191).getRGB()); + } + + + + @EventHandler + private void onPacket(EventPacketRecieve e) + { + if (((e.getPacket() instanceof S12PacketEntityVelocity)) || ((e.getPacket() instanceof S27PacketExplosion))) + { + if (((Double)percentage.getValue()).equals(Double.valueOf(0.0D))) { + e.setCancelled(true); + } + else { + S12PacketEntityVelocity packet = (S12PacketEntityVelocity)e.getPacket(); + field_149415_b = ((int)(((Double)percentage.getValue()).doubleValue() / 100.0D)); + field_149416_c = ((int)(((Double)percentage.getValue()).doubleValue() / 100.0D)); + field_149414_d = ((int)(((Double)percentage.getValue()).doubleValue() / 100.0D)); + } + } + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/player/AutoAccept.java b/src/minecraft/com/enjoytheban/module/modules/player/AutoAccept.java new file mode 100644 index 0000000..ec747fa --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/player/AutoAccept.java @@ -0,0 +1 @@ +null \ No newline at end of file diff --git a/src/minecraft/com/enjoytheban/module/modules/player/Bobbing.java b/src/minecraft/com/enjoytheban/module/modules/player/Bobbing.java new file mode 100644 index 0000000..39b7c08 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/player/Bobbing.java @@ -0,0 +1,31 @@ +package com.enjoytheban.module.modules.player; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventPreUpdate; +import com.enjoytheban.api.value.Numbers; +import com.enjoytheban.api.value.Value; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import java.awt.Color; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; + + +public class Bobbing + extends Module +{ + private Numbers boob = new Numbers("Amount", "Amount", Double.valueOf(1.0D), Double.valueOf(0.1D), Double.valueOf(5.0D), Double.valueOf(0.5D)); + + public Bobbing() { + super("Bobbing+", new String[] { "bobbing+" }, ModuleType.Player); + addValues(new Value[] { boob }); + } + + @EventHandler + public void onUpdate(EventPreUpdate event) { + setColor(new Color(20, 200, 100).getRGB()); + if (mc.thePlayer.onGround) { + mc.thePlayer.cameraYaw = ((float)(0.09090908616781235D * ((Double)boob.getValue()).doubleValue())); + } + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/player/Dab.java b/src/minecraft/com/enjoytheban/module/modules/player/Dab.java new file mode 100644 index 0000000..5a70f1a --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/player/Dab.java @@ -0,0 +1,15 @@ +package com.enjoytheban.module.modules.player; + +import com.enjoytheban.module.Module; +import java.awt.Color; +import java.util.Random; + +public class Dab extends Module +{ + public Dab() + { + super("Dab", new String[] { "dab" }, com.enjoytheban.module.ModuleType.Player); + setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)).getRGB()); + setRemoved(false); + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/player/FastUse.java b/src/minecraft/com/enjoytheban/module/modules/player/FastUse.java new file mode 100644 index 0000000..3e1dcc8 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/player/FastUse.java @@ -0,0 +1,71 @@ +package com.enjoytheban.module.modules.player; + +import com.enjoytheban.api.events.world.EventPreUpdate; +import com.enjoytheban.api.value.Option; +import com.enjoytheban.module.Module; +import java.awt.Color; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.client.settings.GameSettings; +import net.minecraft.client.settings.KeyBinding; +import net.minecraft.item.ItemBow; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ItemSword; +import net.minecraft.network.play.client.C03PacketPlayer.C05PacketPlayerLook; +import net.minecraft.network.play.client.C07PacketPlayerDigging; +import net.minecraft.network.play.client.C07PacketPlayerDigging.Action; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; + +public class FastUse extends Module +{ + private Option guardian = new Option("Guardian", "guardian", Boolean.valueOf(true)); + + public FastUse() { + super("FastUse", new String[] { "fasteat", "fuse" }, com.enjoytheban.module.ModuleType.Player); + addValues(new com.enjoytheban.api.value.Value[] { guardian }); + } + + private boolean canConsume() { + return ((mc.thePlayer.getCurrentEquippedItem() != null) && + ((mc.thePlayer.getCurrentEquippedItem().getItem() instanceof net.minecraft.item.ItemPotion))) || + ((mc.thePlayer.getCurrentEquippedItem().getItem() instanceof net.minecraft.item.ItemFood)); + } + + @com.enjoytheban.api.EventHandler + private void onUpdate(EventPreUpdate e) { + setColor(new Color(100, 200, 200).getRGB()); + if (((Boolean)guardian.getValue()).booleanValue()) { + if ((mc.thePlayer.onGround) && + (mc.thePlayer.getItemInUseDuration() == 1) && (getMinecraftgameSettings.keyBindUseItem.pressed) && + (!(mc.thePlayer.getItemInUse().getItem() instanceof ItemBow)) && + (!(mc.thePlayer.getItemInUse().getItem() instanceof ItemSword))) { + for (int i = 0; i < 40; i++) { + mc.thePlayer.sendQueue.addToSendQueue(new C03PacketPlayer.C05PacketPlayerLook( + mc.thePlayer.rotationYaw, mc.thePlayer.rotationPitch, mc.thePlayer.onGround)); + if ((((Boolean)guardian.getValue()).booleanValue()) && + (mc.thePlayer.ticksExisted % 2 == 0)) { + mc.thePlayer.sendQueue.addToSendQueue(new net.minecraft.network.play.client.C03PacketPlayer.C04PacketPlayerPosition( + mc.thePlayer.posX, mc.thePlayer.posY - 1.0D, mc.thePlayer.posZ, false)); + } + } + + mc.thePlayer.sendQueue.addToSendQueue(new C07PacketPlayerDigging( + C07PacketPlayerDigging.Action.RELEASE_USE_ITEM, BlockPos.ORIGIN, EnumFacing.DOWN)); + } + + } + else if ((mc.thePlayer.onGround) && + (mc.thePlayer.getItemInUseDuration() == 16) && (getMinecraftgameSettings.keyBindUseItem.pressed) && + (!(mc.thePlayer.getItemInUse().getItem() instanceof ItemBow)) && + (!(mc.thePlayer.getItemInUse().getItem() instanceof ItemSword))) { + for (int i = 0; i < 17; i++) { + mc.thePlayer.sendQueue.addToSendQueue(new C03PacketPlayer.C05PacketPlayerLook( + mc.thePlayer.rotationYaw, mc.thePlayer.rotationPitch, mc.thePlayer.onGround)); + } + mc.thePlayer.sendQueue.addToSendQueue(new C07PacketPlayerDigging( + C07PacketPlayerDigging.Action.RELEASE_USE_ITEM, BlockPos.ORIGIN, EnumFacing.DOWN)); + } + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/player/Freecam.java b/src/minecraft/com/enjoytheban/module/modules/player/Freecam.java new file mode 100644 index 0000000..4124310 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/player/Freecam.java @@ -0,0 +1,92 @@ +package com.enjoytheban.module.modules.player; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.misc.EventCollideWithBlock; +import com.enjoytheban.api.events.world.EventPacketRecieve; +import com.enjoytheban.api.events.world.EventPreUpdate; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import java.awt.Color; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityOtherPlayerMP; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.client.renderer.RenderGlobal; +import net.minecraft.entity.player.PlayerCapabilities; +import net.minecraft.network.play.client.C03PacketPlayer; +import net.minecraft.network.play.client.C03PacketPlayer.C04PacketPlayerPosition; + + +public class Freecam + extends Module +{ + private EntityOtherPlayerMP copy; + private double x; + private double y; + private double z; + + public Freecam() + { + super("Freecam", new String[] { "outofbody" }, ModuleType.Player); + setColor(new Color(221, 214, 51).getRGB()); + } + + + + + public void onEnable() + { + (this.copy = new EntityOtherPlayerMP(mc.theWorld, mc.thePlayer.getGameProfile())).clonePlayer(mc.thePlayer, + true); + copy.setLocationAndAngles(mc.thePlayer.posX, mc.thePlayer.posY, mc.thePlayer.posZ, + mc.thePlayer.rotationYaw, mc.thePlayer.rotationPitch); + copy.rotationYawHead = mc.thePlayer.rotationYawHead; + copy.setEntityId(64199); + copy.setSneaking(mc.thePlayer.isSneaking()); + mc.theWorld.addEntityToWorld(copy.getEntityId(), copy); + x = mc.thePlayer.posX; + y = mc.thePlayer.posY; + z = mc.thePlayer.posZ; + } + + @EventHandler + private void onPreMotion(EventPreUpdate e) { + mc.thePlayer.capabilities.isFlying = true; + mc.thePlayer.noClip = true; + mc.thePlayer.capabilities.setFlySpeed(0.1F); + e.setCancelled(true); + } + + @EventHandler + private void onPacketSend(EventPacketRecieve e) + { + if ((e.getPacket() instanceof C03PacketPlayer)) { + e.setCancelled(true); + } + } + + @EventHandler + private void onBB(EventCollideWithBlock e) { + e.setBoundingBox(null); + } + + + public void onDisable() + { + mc.thePlayer.setSpeed(0.0D); + mc.thePlayer.setLocationAndAngles(copy.posX, copy.posY, copy.posZ, copy.rotationYaw, + copy.rotationPitch); + mc.thePlayer.rotationYawHead = copy.rotationYawHead; + mc.theWorld.removeEntityFromWorld(copy.getEntityId()); + mc.thePlayer.setSneaking(copy.isSneaking()); + copy = null; + mc.renderGlobal.loadRenderers(); + mc.thePlayer.setPosition(x, y, z); + mc.getNetHandler().addToSendQueue(new C03PacketPlayer.C04PacketPlayerPosition(mc.thePlayer.posX, + mc.thePlayer.posY + 0.01D, mc.thePlayer.posZ, mc.thePlayer.onGround)); + mc.thePlayer.capabilities.isFlying = false; + mc.thePlayer.noClip = false; + mc.theWorld.removeEntityFromWorld(-1); + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/player/InvCleaner.java b/src/minecraft/com/enjoytheban/module/modules/player/InvCleaner.java new file mode 100644 index 0000000..83a188e --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/player/InvCleaner.java @@ -0,0 +1,489 @@ +package com.enjoytheban.module.modules.player; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventTick; +import com.enjoytheban.api.value.Option; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import com.enjoytheban.utils.TimerUtil; +import com.google.common.collect.Multimap; +import java.awt.Color; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map.Entry; +import java.util.Random; +import java.util.concurrent.CopyOnWriteArrayList; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.gui.inventory.GuiInventory; +import net.minecraft.client.multiplayer.PlayerControllerMP; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.EnumCreatureAttribute; +import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.Slot; +import net.minecraft.item.Item; +import net.minecraft.item.Item.ToolMaterial; +import net.minecraft.item.ItemArmor; +import net.minecraft.item.ItemAxe; +import net.minecraft.item.ItemBow; +import net.minecraft.item.ItemFood; +import net.minecraft.item.ItemPickaxe; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ItemSword; +import net.minecraft.item.ItemTool; + +public class InvCleaner extends Module +{ + private static final Random RANDOM = new Random(); + + public static List blacklistedItems = new ArrayList(); + + private boolean allowSwitch = true; + + private boolean hasNoItems; + public final TimerUtil timer = new TimerUtil(); + + private Option openInv = new Option("Require Inventory Open?", "open inv", Boolean.valueOf(false)); + + public InvCleaner() { + super("InvCleaner", new String[] { "inventorycleaner", "invclean" }, ModuleType.Player); + setColor(Color.BLUE.getRGB()); + addValues(new com.enjoytheban.api.value.Value[] { openInv }); + } + + public void onEnable() { + super.onEnable(); + hasNoItems = false; + } + + @EventHandler + private void onTick(EventTick event) { + if (mc.thePlayer.isUsingItem()) + { + return; + } + + + if ((mc.thePlayer.ticksExisted % 2 == 0) && (RANDOM.nextInt(2) == 0)) + { + if ((!((Boolean)openInv.getValue()).booleanValue()) || (((mc.currentScreen instanceof GuiInventory)) && (((Boolean)openInv.getValue()).booleanValue()))) + { + if (timer.hasReached(59.0D)) + { + CopyOnWriteArrayList uselessItems = new CopyOnWriteArrayList(); + + for (int o = 0; o < 45; o++) + { + if (mc.thePlayer.inventoryContainer.getSlot(o).getHasStack()) + { + ItemStack item = mc.thePlayer.inventoryContainer.getSlot(o).getStack(); + + if ((mc.thePlayer.inventory.armorItemInSlot(0) != item) && + (mc.thePlayer.inventory.armorItemInSlot(1) != item) && + (mc.thePlayer.inventory.armorItemInSlot(2) != item) && + (mc.thePlayer.inventory.armorItemInSlot(3) != item)) + { + + + + + if ((item != null) && (item.getItem() != null) && (Item.getIdFromItem(item.getItem()) != 0) && + (!stackIsUseful(o))) + { + uselessItems.add(Integer.valueOf(o)); + } + + + hasNoItems = true; + } + } + } + + + + + + + if (!uselessItems.isEmpty()) + { + mc.playerController.windowClick(mc.thePlayer.inventoryContainer.windowId, ((Integer)uselessItems.get(0)).intValue(), + 1, 4, mc.thePlayer); + uselessItems.remove(0); + + timer.reset(); + } + } + } + } + } + + + + + + private void bestSword() + { + int slotToSwitch = 0; + float swordDamage = 0.0F; + + for (int i = 9; i < 45; i++) + { + if (mc.thePlayer.inventoryContainer.getSlot(i).getHasStack()) + { + ItemStack is = mc.thePlayer.inventoryContainer.getSlot(i).getStack(); + + if ((is.getItem() instanceof ItemSword)) + { + float swordD = getItemDamage(is); + + if (swordD > swordDamage) + { + swordDamage = swordD; + slotToSwitch = i; + } + } + } + } + + + + + + if (allowSwitch) + { + mc.playerController.windowClick(mc.thePlayer.inventoryContainer.windowId, slotToSwitch, + mc.thePlayer.inventory.currentItem, 2, mc.thePlayer); + + allowSwitch = false; + } + } + + + + private boolean stackIsUseful(int i) + { + ItemStack itemStack = mc.thePlayer.inventoryContainer.getSlot(i).getStack(); + + boolean hasAlreadyOrBetter = false; + + if (((itemStack.getItem() instanceof ItemSword)) || ((itemStack.getItem() instanceof ItemPickaxe)) || + ((itemStack.getItem() instanceof ItemAxe))) + { + for (int o = 0; o < 45; o++) + { + if (o != i) + { + + + + + if (mc.thePlayer.inventoryContainer.getSlot(o).getHasStack()) + { + ItemStack item = mc.thePlayer.inventoryContainer.getSlot(o).getStack(); + + if (((item != null) && ((item.getItem() instanceof ItemSword))) || ((item.getItem() instanceof ItemAxe)) || + ((item.getItem() instanceof ItemPickaxe))) + { + float damageFound = getItemDamage(itemStack); + float damageCurrent = getItemDamage(item); + + damageFound += EnchantmentHelper.func_152377_a(itemStack, EnumCreatureAttribute.UNDEFINED); + damageCurrent += EnchantmentHelper.func_152377_a(item, EnumCreatureAttribute.UNDEFINED); + + if (damageCurrent > damageFound) + { + hasAlreadyOrBetter = true; + break; + } + + } + + } + + } + + } + } else if ((itemStack.getItem() instanceof ItemArmor)) + { + for (int o = 0; o < 45; o++) + { + if (i != o) + { + + + + + if (mc.thePlayer.inventoryContainer.getSlot(o).getHasStack()) + { + ItemStack item = mc.thePlayer.inventoryContainer.getSlot(o).getStack(); + + if ((item != null) && ((item.getItem() instanceof ItemArmor))) + { + List helmet = Arrays.asList(new Integer[] { Integer.valueOf(298), Integer.valueOf(314), Integer.valueOf(302), Integer.valueOf(306), Integer.valueOf(310) }); + List chestplate = Arrays.asList(new Integer[] { Integer.valueOf(299), Integer.valueOf(315), Integer.valueOf(303), Integer.valueOf(307), Integer.valueOf(311) }); + List leggings = Arrays.asList(new Integer[] { Integer.valueOf(300), Integer.valueOf(316), Integer.valueOf(304), Integer.valueOf(308), Integer.valueOf(312) }); + List boots = Arrays.asList(new Integer[] { Integer.valueOf(301), Integer.valueOf(317), Integer.valueOf(305), Integer.valueOf(309), Integer.valueOf(313) }); + + if ((helmet.contains(Integer.valueOf(Item.getIdFromItem(item.getItem())))) && + (helmet.contains(Integer.valueOf(Item.getIdFromItem(itemStack.getItem()))))) + { + + if (helmet.indexOf(Integer.valueOf(Item.getIdFromItem(itemStack.getItem()))) < helmet.indexOf(Integer.valueOf(Item.getIdFromItem(item.getItem())))) + { + hasAlreadyOrBetter = true; + + break; + } + + } + else if ((chestplate.contains(Integer.valueOf(Item.getIdFromItem(item.getItem())))) && + (chestplate.contains(Integer.valueOf(Item.getIdFromItem(itemStack.getItem()))))) + { + + if (chestplate.indexOf(Integer.valueOf(Item.getIdFromItem(itemStack.getItem()))) < chestplate.indexOf(Integer.valueOf(Item.getIdFromItem(item.getItem())))) + { + hasAlreadyOrBetter = true; + + break; + } + + } + else if ((leggings.contains(Integer.valueOf(Item.getIdFromItem(item.getItem())))) && + (leggings.contains(Integer.valueOf(Item.getIdFromItem(itemStack.getItem()))))) + { + + if (leggings.indexOf(Integer.valueOf(Item.getIdFromItem(itemStack.getItem()))) < leggings.indexOf(Integer.valueOf(Item.getIdFromItem(item.getItem())))) + { + hasAlreadyOrBetter = true; + + break; + } + + } + else if ((boots.contains(Integer.valueOf(Item.getIdFromItem(item.getItem())))) && + (boots.contains(Integer.valueOf(Item.getIdFromItem(itemStack.getItem()))))) + { + + if (boots.indexOf(Integer.valueOf(Item.getIdFromItem(itemStack.getItem()))) < boots.indexOf(Integer.valueOf(Item.getIdFromItem(item.getItem())))) + { + hasAlreadyOrBetter = true; + + break; + } + } + } + } + } + } + } + + + + + + + for (int o = 0; o < 45; o++) + { + if (i != o) + { + + + + + if (mc.thePlayer.inventoryContainer.getSlot(o).getHasStack()) + { + ItemStack item = mc.thePlayer.inventoryContainer.getSlot(o).getStack(); + + if ((item != null) && (((item.getItem() instanceof ItemSword)) || ((item.getItem() instanceof ItemAxe)) || + ((item.getItem() instanceof ItemBow)) || ((item.getItem() instanceof net.minecraft.item.ItemFishingRod)) || + ((item.getItem() instanceof ItemArmor)) || ((item.getItem() instanceof ItemAxe)) || + ((item.getItem() instanceof ItemPickaxe)) || (Item.getIdFromItem(item.getItem()) == 346))) + { + Item found = item.getItem(); + + if (Item.getIdFromItem(itemStack.getItem()) == Item.getIdFromItem(item.getItem())) + { + hasAlreadyOrBetter = true; + + break; + } + } + } + } + } + + + + + if (Item.getIdFromItem(itemStack.getItem()) == 367) { + return false; + } + if (Item.getIdFromItem(itemStack.getItem()) == 30) { + return true; + } + if (Item.getIdFromItem(itemStack.getItem()) == 259) { + return true; + } + if (Item.getIdFromItem(itemStack.getItem()) == 262) { + return true; + } + if (Item.getIdFromItem(itemStack.getItem()) == 264) { + return true; + } + if (Item.getIdFromItem(itemStack.getItem()) == 265) { + return true; + } + if (Item.getIdFromItem(itemStack.getItem()) == 346) { + return true; + } + if (Item.getIdFromItem(itemStack.getItem()) == 384) { + return true; + } + if (Item.getIdFromItem(itemStack.getItem()) == 345) { + return true; + } + if (Item.getIdFromItem(itemStack.getItem()) == 296) { + return true; + } + if (Item.getIdFromItem(itemStack.getItem()) == 336) { + return true; + } + if (Item.getIdFromItem(itemStack.getItem()) == 266) { + return true; + } + if (Item.getIdFromItem(itemStack.getItem()) == 280) { + return true; + } + if (itemStack.hasDisplayName()) + { + return true; + } + + + if (hasAlreadyOrBetter) + { + return false; + } + + + if ((itemStack.getItem() instanceof ItemArmor)) + return true; + if ((itemStack.getItem() instanceof ItemAxe)) + return true; + if ((itemStack.getItem() instanceof ItemBow)) + return true; + if ((itemStack.getItem() instanceof ItemSword)) + return true; + if ((itemStack.getItem() instanceof net.minecraft.item.ItemPotion)) + return true; + if ((itemStack.getItem() instanceof net.minecraft.item.ItemFlintAndSteel)) + return true; + if ((itemStack.getItem() instanceof net.minecraft.item.ItemEnderPearl)) + return true; + if ((itemStack.getItem() instanceof net.minecraft.item.ItemBlock)) + return true; + if ((itemStack.getItem() instanceof ItemFood)) + return true; + if ((itemStack.getItem() instanceof ItemPickaxe)) { + return true; + } + return false; + } + + + private float getItemDamage(ItemStack itemStack) + { + Multimap multimap = itemStack.getAttributeModifiers(); + + if (!multimap.isEmpty()) + { + Iterator iterator = multimap.entries().iterator(); + + if (iterator.hasNext()) + { + Map.Entry entry = (Map.Entry)iterator.next(); + AttributeModifier attributeModifier = (AttributeModifier)entry.getValue(); + + double damage; + double damage; + if ((attributeModifier.getOperation() != 1) && (attributeModifier.getOperation() != 2)) + { + damage = attributeModifier.getAmount(); + } + else + { + damage = attributeModifier.getAmount() * 100.0D; + } + + + if (attributeModifier.getAmount() > 1.0D) + { + return 1.0F + (float)damage; + } + + + return 1.0F; + } + } + + + return 1.0F; + } + + + public boolean isValid(Item item) + { + if (blacklistedItems.contains(Integer.valueOf(Item.getIdFromItem(item)))) + { + return (!((Boolean)openInv.getValue()).booleanValue()) || ((mc.currentScreen instanceof GuiInventory)); + } + + + return false; + } + + + public void setSwordSlot() + { + float bestDamage = 1.0F; + + int bestSlot = -1; + + for (int i = 0; i < 9; i++) + { + ItemStack item = mc.thePlayer.inventory.getStackInSlot(i); + + if (stackSize > 0) + { + + + float damage = 0.0F; + + if ((item.getItem() instanceof ItemSword)) + { + damage = ((ItemSword)item.getItem()).getAttackDamage(); + } + else if ((item.getItem() instanceof ItemTool)) + { + damage = getItemtoolMaterial.getDamageVsEntity(); + } + if (damage > bestDamage) + { + bestDamage = damage; + bestSlot = i; + } + } + } + + + if ((bestSlot != -1) && (bestSlot != mc.thePlayer.inventory.currentItem)) + { + mc.thePlayer.inventory.currentItem = bestSlot; + } + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/player/Invplus.java b/src/minecraft/com/enjoytheban/module/modules/player/Invplus.java new file mode 100644 index 0000000..06c3002 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/player/Invplus.java @@ -0,0 +1,74 @@ +package com.enjoytheban.module.modules.player; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.misc.EventInventory; +import com.enjoytheban.api.events.rendering.EventRender2D; +import com.enjoytheban.api.events.world.EventPacketSend; +import com.enjoytheban.api.value.Option; +import com.enjoytheban.api.value.Value; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import com.enjoytheban.utils.math.RotationUtil; +import java.awt.Color; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiChat; +import net.minecraft.network.play.client.C0DPacketCloseWindow; +import org.lwjgl.input.Keyboard; + + + + + + + +public class Invplus + extends Module +{ + public Option sw = new Option("ScreenWalk", "screenwalk", Boolean.valueOf(true)); + private Option xc = new Option("MoreInventory", "MoreInventory", Boolean.valueOf(false)); + + public Invplus() + { + super("Inventory+", new String[] { "inventorywalk", "invwalk", "inventorymove", "inv+" }, ModuleType.Player); + setColor(new Color(174, 174, 227).getRGB()); + addValues(new Value[] { sw, xc }); + } + + @EventHandler + public void onEvent(EventPacketSend event) { + if (((event.getPacket() instanceof C0DPacketCloseWindow)) && + (((Boolean)xc.getValue()).booleanValue())) { + event.setCancelled(true); + } + } + + @EventHandler + public void onInv(EventInventory event) { + if (((Boolean)xc.getValue()).booleanValue()) { + event.setCancelled(true); + } + } + + @EventHandler + private void onRender(EventRender2D e) + { + if ((mc.currentScreen != null) && (!(mc.currentScreen instanceof GuiChat)) && (((Boolean)sw.getValue()).booleanValue())) + { + if (Keyboard.isKeyDown(200)) { + RotationUtil.pitch(RotationUtil.pitch() - 2.0F); + } + + if (Keyboard.isKeyDown(208)) { + RotationUtil.pitch(RotationUtil.pitch() + 2.0F); + } + + if (Keyboard.isKeyDown(203)) { + RotationUtil.yaw(RotationUtil.yaw() - 2.0F); + } + + if (Keyboard.isKeyDown(205)) { + RotationUtil.yaw(RotationUtil.yaw() + 2.0F); + } + } + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/player/MCF.java b/src/minecraft/com/enjoytheban/module/modules/player/MCF.java new file mode 100644 index 0000000..bab200d --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/player/MCF.java @@ -0,0 +1,57 @@ +package com.enjoytheban.module.modules.player; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventPreUpdate; +import com.enjoytheban.management.FriendManager; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import java.awt.Color; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.MovingObjectPosition; +import org.lwjgl.input.Mouse; + + + + + +public class MCF + extends Module +{ + private boolean down; + + public MCF() + { + super("MCF", new String[] { "middleclickfriends", "middleclick" }, ModuleType.Player); + setColor(new Color(241, 175, 67).getRGB()); + } + + + @EventHandler + private void onClick(EventPreUpdate e) + { + if ((Mouse.isButtonDown(2)) && (!down)) + { + if (mc.objectMouseOver.entityHit != null) + { + EntityPlayer player = (EntityPlayer)mc.objectMouseOver.entityHit; + + String playername = player.getName(); + + + if (!FriendManager.isFriend(playername)) { + mc.thePlayer.sendChatMessage(".f add " + playername); + } + else { + mc.thePlayer.sendChatMessage(".f del " + playername); + } + } + down = true; + } + + if (!Mouse.isButtonDown(2)) { + down = false; + } + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/player/NoFall.java b/src/minecraft/com/enjoytheban/module/modules/player/NoFall.java new file mode 100644 index 0000000..c9ce2cb --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/player/NoFall.java @@ -0,0 +1,30 @@ +package com.enjoytheban.module.modules.player; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventPreUpdate; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import java.awt.Color; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.network.play.client.C03PacketPlayer.C06PacketPlayerPosLook; + +public class NoFall + extends Module +{ + public NoFall() + { + super("NoFall", new String[] { "Nofalldamage" }, ModuleType.Player); + setColor(new Color(242, 137, 73).getRGB()); + } + + @EventHandler + private void onUpdate(EventPreUpdate e) { + if (mc.thePlayer.fallDistance > 3.0F) { + mc.thePlayer.sendQueue.addToSendQueue(new C03PacketPlayer.C06PacketPlayerPosLook(mc.thePlayer.posX, + mc.thePlayer.posY, mc.thePlayer.posZ, mc.thePlayer.rotationYaw, mc.thePlayer.rotationPitch, true)); + mc.thePlayer.fallDistance = 0.0F; + } + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/player/NoStrike.java b/src/minecraft/com/enjoytheban/module/modules/player/NoStrike.java new file mode 100644 index 0000000..74214a5 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/player/NoStrike.java @@ -0,0 +1,19 @@ +package com.enjoytheban.module.modules.player; + +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import java.awt.Color; +import java.util.Random; + + + + +public class NoStrike + extends Module +{ + public NoStrike() + { + super("NoStrike", new String[] { "antistrike" }, ModuleType.Player); + setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)).getRGB()); + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/player/SkinFlash.java b/src/minecraft/com/enjoytheban/module/modules/player/SkinFlash.java new file mode 100644 index 0000000..1777417 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/player/SkinFlash.java @@ -0,0 +1,55 @@ +package com.enjoytheban.module.modules.player; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventTick; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import java.awt.Color; +import java.util.Random; +import net.minecraft.client.Minecraft; +import net.minecraft.client.settings.GameSettings; +import net.minecraft.entity.player.EnumPlayerModelParts; + + + + +public class SkinFlash + extends Module +{ + public SkinFlash() + { + super("SkinFlash", new String[] { "derpskin" }, ModuleType.Player); + setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)).getRGB()); + } + + public void onDisable() + { + if (mc.thePlayer != null) { + EnumPlayerModelParts[] parts = EnumPlayerModelParts.values(); + if (parts != null) { + EnumPlayerModelParts[] arrayOfEnumPlayerModelParts1; + int j = (arrayOfEnumPlayerModelParts1 = parts).length; + for (int i = 0; i < j; i++) { + EnumPlayerModelParts part = arrayOfEnumPlayerModelParts1[i]; + mc.gameSettings.func_178878_a(part, true); + } + } + } + } + + @EventHandler + private void onTick(EventTick e) { + if (mc.thePlayer != null) { + EnumPlayerModelParts[] parts = EnumPlayerModelParts.values(); + if (parts != null) { + EnumPlayerModelParts[] arrayOfEnumPlayerModelParts1; + int j = (arrayOfEnumPlayerModelParts1 = parts).length; + for (int i = 0; i < j; i++) { + EnumPlayerModelParts part = arrayOfEnumPlayerModelParts1[i]; + boolean newState = isEnabled() ? random.nextBoolean() : true; + mc.gameSettings.func_178878_a(part, newState); + } + } + } + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/player/Zoot.java b/src/minecraft/com/enjoytheban/module/modules/player/Zoot.java new file mode 100644 index 0000000..bfbcb7b --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/player/Zoot.java @@ -0,0 +1,43 @@ +package com.enjoytheban.module.modules.player; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventPreUpdate; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import java.awt.Color; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.network.play.client.C03PacketPlayer; +import net.minecraft.potion.Potion; +import net.minecraft.potion.PotionEffect; + + + + + +public class Zoot + extends Module +{ + public Zoot() + { + super("Zoot", new String[] { "Firion", "antipotion", "antifire" }, ModuleType.Player); + setColor(new Color(208, 203, 229).getRGB()); + } + + @EventHandler + private void onUpdate(EventPreUpdate e) + { + for (Potion potion : Potion.potionTypes) + { + PotionEffect effect; + if ((e.getType() == 0) && (potion != null) && ((((effect = mc.thePlayer.getActivePotionEffect(potion)) != null) && (potion.isBadEffect())) || ( + (mc.thePlayer.isBurning()) && (!mc.thePlayer.isInWater()) && (mc.thePlayer.onGround)))) + { + for (int i = 0; mc.thePlayer.isBurning() ? i < 20 : i < effect.getDuration() / 20; i++) { + mc.thePlayer.sendQueue.addToSendQueue(new C03PacketPlayer(true)); + } + } + } + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/render/Capes.java b/src/minecraft/com/enjoytheban/module/modules/render/Capes.java new file mode 100644 index 0000000..1cd99c4 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/render/Capes.java @@ -0,0 +1,32 @@ +package com.enjoytheban.module.modules.render; + +import com.enjoytheban.Client; +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.rendering.EventRenderCape; +import com.enjoytheban.management.FriendManager; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import java.awt.Color; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.player.EntityPlayer; + + +public class Capes + extends Module +{ + public Capes() + { + super("Capes", new String[] { "kape" }, ModuleType.Render); + setColor(new Color(159, 190, 192).getRGB()); + setEnabled(true); + setRemoved(true); + } + + @EventHandler + public void onRender(EventRenderCape event) { + if ((mc.theWorld != null) && (FriendManager.isFriend(event.getPlayer().getName()))) { + event.setLocation(Client.CLIENT_CAPE); + event.setCancelled(true); + } + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/render/Chams.java b/src/minecraft/com/enjoytheban/module/modules/render/Chams.java new file mode 100644 index 0000000..0fd214a --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/render/Chams.java @@ -0,0 +1,40 @@ +package com.enjoytheban.module.modules.render; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.rendering.EventPostRenderPlayer; +import com.enjoytheban.api.events.rendering.EventPreRenderPlayer; +import com.enjoytheban.api.value.Mode; +import com.enjoytheban.api.value.Value; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import java.awt.Color; +import org.lwjgl.opengl.GL11; + +public class Chams + extends Module +{ + public Mode mode = new Mode("Mode", "mode", ChamsMode.values(), ChamsMode.Textured); + + public Chams() { + super("Chams", new String[] { "seethru", "cham" }, ModuleType.Render); + addValues(new Value[] { mode }); + setColor(new Color(159, 190, 192).getRGB()); + } + + @EventHandler + private void preRenderPlayer(EventPreRenderPlayer e) { + GL11.glEnable(32823); + GL11.glPolygonOffset(1.0F, -1100000.0F); + } + + @EventHandler + private void postRenderPlayer(EventPostRenderPlayer e) + { + GL11.glDisable(32823); + GL11.glPolygonOffset(1.0F, 1100000.0F); + } + + public static enum ChamsMode { + Textured, Normal; + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/render/ChestESP.java b/src/minecraft/com/enjoytheban/module/modules/render/ChestESP.java new file mode 100644 index 0000000..d08bdb6 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/render/ChestESP.java @@ -0,0 +1,148 @@ +package com.enjoytheban.module.modules.render; + +import com.enjoytheban.api.events.rendering.EventRender3D; +import com.enjoytheban.utils.math.Vec4f; +import com.enjoytheban.utils.render.GLUProjection.Projection; +import java.awt.Color; +import javax.vecmath.Vector3d; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.init.Blocks; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntityChest; +import net.minecraft.tileentity.TileEntityFurnace; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; +import org.lwjgl.opengl.GL11; + +public class ChestESP extends com.enjoytheban.module.Module +{ + public ChestESP() + { + super("ChestESP", new String[] { "chesthack" }, com.enjoytheban.module.ModuleType.Render); + setColor(new Color(90, 209, 165).getRGB()); + } + + @com.enjoytheban.api.EventHandler + public void onRender(EventRender3D eventRender) { + ScaledResolution scaledResolution = new ScaledResolution(mc); + for (Object o : mc.theWorld.loadedTileEntityList) { + TileEntity tileEntity = (TileEntity)o; + if ((tileEntity != null) && (isStorage(tileEntity))) { + double posX = tileEntity.getPos().getX(); + double posY = tileEntity.getPos().getY(); + double posZ = tileEntity.getPos().getZ(); + + AxisAlignedBB axisAlignedBB = null; + if ((tileEntity instanceof TileEntityChest)) { + Block block = mc.theWorld.getBlockState(new BlockPos(posX, posY, posZ)).getBlock(); + Block x1 = mc.theWorld.getBlockState(new BlockPos(posX + 1.0D, posY, posZ)).getBlock(); + Block x2 = mc.theWorld.getBlockState(new BlockPos(posX - 1.0D, posY, posZ)).getBlock(); + Block z1 = mc.theWorld.getBlockState(new BlockPos(posX, posY, posZ + 1.0D)).getBlock(); + Block z2 = mc.theWorld.getBlockState(new BlockPos(posX, posY, posZ - 1.0D)).getBlock(); + if (block != Blocks.trapped_chest) { + if (x1 == Blocks.chest) { + mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();axisAlignedBB = new AxisAlignedBB(posX + 0.05000000074505806D - RenderManager.renderPosX, posY - RenderManager.renderPosY, posZ + 0.05000000074505806D - RenderManager.renderPosZ, posX + 1.9500000476837158D - RenderManager.renderPosX, posY + 0.8999999761581421D - RenderManager.renderPosY, posZ + 0.949999988079071D - RenderManager.renderPosZ); + } else if (z2 == Blocks.chest) { + mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();axisAlignedBB = new AxisAlignedBB(posX + 0.05000000074505806D - RenderManager.renderPosX, posY - RenderManager.renderPosY, posZ + 0.05000000074505806D - RenderManager.renderPosZ - 1.0D, posX + 0.949999988079071D - RenderManager.renderPosX, posY + 0.8999999761581421D - RenderManager.renderPosY, posZ + 0.949999988079071D - RenderManager.renderPosZ); + } else if ((x1 != Blocks.chest) && (x2 != Blocks.chest) && (z1 != Blocks.chest) && (z2 != Blocks.chest)) { + mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();axisAlignedBB = new AxisAlignedBB(posX + 0.05000000074505806D - RenderManager.renderPosX, posY - RenderManager.renderPosY, posZ + 0.05000000074505806D - RenderManager.renderPosZ, posX + 0.949999988079071D - RenderManager.renderPosX, posY + 0.8999999761581421D - RenderManager.renderPosY, posZ + 0.949999988079071D - RenderManager.renderPosZ); + } + } else if (x1 == Blocks.trapped_chest) { + mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();axisAlignedBB = new AxisAlignedBB(posX + 0.05000000074505806D - RenderManager.renderPosX, posY - RenderManager.renderPosY, posZ + 0.05000000074505806D - RenderManager.renderPosZ, posX + 1.9500000476837158D - RenderManager.renderPosX, posY + 0.8999999761581421D - RenderManager.renderPosY, posZ + 0.949999988079071D - RenderManager.renderPosZ); + } else if (z2 == Blocks.trapped_chest) { + mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();axisAlignedBB = new AxisAlignedBB(posX + 0.05000000074505806D - RenderManager.renderPosX, posY - RenderManager.renderPosY, posZ + 0.05000000074505806D - RenderManager.renderPosZ - 1.0D, posX + 0.949999988079071D - RenderManager.renderPosX, posY + 0.8999999761581421D - RenderManager.renderPosY, posZ + 0.949999988079071D - RenderManager.renderPosZ); + } else if ((x1 != Blocks.trapped_chest) && (x2 != Blocks.trapped_chest) && (z1 != Blocks.trapped_chest) && (z2 != Blocks.trapped_chest)) { + mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();axisAlignedBB = new AxisAlignedBB(posX + 0.05000000074505806D - RenderManager.renderPosX, posY - RenderManager.renderPosY, posZ + 0.05000000074505806D - RenderManager.renderPosZ, posX + 0.949999988079071D - RenderManager.renderPosX, posY + 0.8999999761581421D - RenderManager.renderPosY, posZ + 0.949999988079071D - RenderManager.renderPosZ); + } + } else { + mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();mc.getRenderManager();axisAlignedBB = new AxisAlignedBB(posX - RenderManager.renderPosX, posY - RenderManager.renderPosY, posZ - RenderManager.renderPosZ, posX + 1.0D - RenderManager.renderPosX, posY + 1.0D - RenderManager.renderPosY, posZ + 1.0D - RenderManager.renderPosZ); + } + if (axisAlignedBB != null) { + float[] colors = getColorForTileEntity(tileEntity); + GlStateManager.disableAlpha(); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(770, 771); + GlStateManager.disableTexture2D(); + GlStateManager.disableDepth(); + GL11.glEnable(2848); + net.minecraft.client.renderer.RenderHelper.drawCompleteBox(axisAlignedBB, 1.0F, toRGBAHex(colors[0] / 255.0F, colors[1] / 255.0F, colors[2] / 255.0F, 0.1254902F), toRGBAHex(colors[0] / 255.0F, colors[1] / 255.0F, colors[2] / 255.0F, 1.0F)); + GL11.glDisable(2848); + GlStateManager.enableDepth(); + GlStateManager.enableTexture2D(); + GlStateManager.enableBlend(); + GlStateManager.enableAlpha(); + + AxisAlignedBB bb = null; + if ((tileEntity instanceof TileEntityChest)) + { + Block block = mc.theWorld.getBlockState(new BlockPos(posX, posY, posZ)).getBlock(); + Block posX1 = mc.theWorld.getBlockState(new BlockPos(posX + 1.0D, posY, posZ)).getBlock(); + Block posX2 = mc.theWorld.getBlockState(new BlockPos(posX - 1.0D, posY, posZ)).getBlock(); + Block posZ1 = mc.theWorld.getBlockState(new BlockPos(posX, posY, posZ + 1.0D)).getBlock(); + Block posZ2 = mc.theWorld.getBlockState(new BlockPos(posX, posY, posZ - 1.0D)).getBlock(); + if (block != Blocks.trapped_chest) { + if (posX1 == Blocks.chest) { + bb = new AxisAlignedBB(posX + 0.05000000074505806D, posY, posZ + 0.05000000074505806D, posX + 1.9500000476837158D, posY + 0.8999999761581421D, posZ + 0.949999988079071D); + } else if (posZ2 == Blocks.chest) { + bb = new AxisAlignedBB(posX + 0.05000000074505806D, posY, posZ + 0.05000000074505806D - 1.0D, posX + 0.949999988079071D, posY + 0.8999999761581421D, posZ + 0.949999988079071D); + } else if ((posX1 != Blocks.chest) && (posX2 != Blocks.chest) && (posZ1 != Blocks.chest) && (posZ2 != Blocks.chest)) { + bb = new AxisAlignedBB(posX + 0.05000000074505806D, posY, posZ + 0.05000000074505806D, posX + 0.949999988079071D, posY + 0.8999999761581421D, posZ + 0.949999988079071D); + } + } else if (posX1 == Blocks.trapped_chest) { + bb = new AxisAlignedBB(posX + 0.05000000074505806D, posY, posZ + 0.05000000074505806D, posX + 1.9500000476837158D, posY + 0.8999999761581421D, posZ + 0.949999988079071D); + } else if (posZ2 == Blocks.trapped_chest) { + bb = new AxisAlignedBB(posX + 0.05000000074505806D, posY, posZ + 0.05000000074505806D - 1.0D, posX + 0.949999988079071D, posY + 0.8999999761581421D, posZ + 0.949999988079071D); + } else if ((posX1 != Blocks.trapped_chest) && (posX2 != Blocks.trapped_chest) && (posZ1 != Blocks.trapped_chest) && (posZ2 != Blocks.trapped_chest)) { + bb = new AxisAlignedBB(posX + 0.05000000074505806D, posY, posZ + 0.05000000074505806D, posX + 0.949999988079071D, posY + 0.8999999761581421D, posZ + 0.949999988079071D); + } + } else { + bb = new AxisAlignedBB(posX, posY, posZ, posX + 1.0D, posY + 1.0D, posZ + 1.0D); + } + if (bb == null) break; + Vector3d[] corners = { new Vector3d(minX, minY, minZ), new Vector3d(maxX, maxY, maxZ), new Vector3d(minX, maxY, maxZ), new Vector3d(minX, minY, maxZ), new Vector3d(maxX, minY, maxZ), new Vector3d(maxX, minY, minZ), new Vector3d(maxX, maxY, minZ), new Vector3d(minX, maxY, minZ) }; + GLUProjection.Projection result = null; + Vec4f transformed = new Vec4f(scaledResolution.getScaledWidth() * 2.0F, scaledResolution.getScaledHeight() * 2.0F, -1.0F, -1.0F); + for (Vector3d vec : corners) { + result = com.enjoytheban.utils.render.GLUProjection.getInstance().project(x - mc.getRenderManager().viewerPosX, y - mc.getRenderManager().viewerPosY, z - mc.getRenderManager().viewerPosZ, com.enjoytheban.utils.render.GLUProjection.ClampMode.NONE, true); + transformed.setX((float)Math.min(transformed.getX(), result.getX())); + transformed.setY((float)Math.min(transformed.getY(), result.getY())); + transformed.setW((float)Math.max(transformed.getW(), result.getX())); + transformed.setH((float)Math.max(transformed.getH(), result.getY())); + } + if (result == null) break; + } + } + } + } + + public static boolean isStorage(TileEntity entity) { return ((entity instanceof TileEntityChest)) || ((entity instanceof net.minecraft.tileentity.TileEntityBrewingStand)) || ((entity instanceof net.minecraft.tileentity.TileEntityDropper)) || ((entity instanceof net.minecraft.tileentity.TileEntityDispenser)) || ((entity instanceof TileEntityFurnace)) || ((entity instanceof net.minecraft.tileentity.TileEntityHopper)) || ((entity instanceof net.minecraft.tileentity.TileEntityEnderChest)); } + + public static int toRGBAHex(float r, float g, float b, float a) { + return ((int)(a * 255.0F) & 0xFF) << 24 | ((int)(r * 255.0F) & 0xFF) << 16 | ((int)(g * 255.0F) & 0xFF) << 8 | (int)(b * 255.0F) & 0xFF; + } + + private float[] getColorForTileEntity(TileEntity entity) { + if ((entity instanceof TileEntityChest)) { + TileEntityChest chest = (TileEntityChest)entity; + if (chest.getChestType() == 0) { + return new float[] { 180.0F, 160.0F, 0.0F, 255.0F }; + } + if (chest.getChestType() == 1) { + return new float[] { 160.0F, 10.0F, 10.0F, 255.0F }; + } + } + if ((entity instanceof net.minecraft.tileentity.TileEntityEnderChest)) { + return new float[] { 0.0F, 160.0F, 100.0F, 255.0F }; + } + if ((entity instanceof TileEntityFurnace)) { + return new float[] { 120.0F, 120.0F, 120.0F, 255.0F }; + } + return new float[] { 255.0F, 255.0F, 255.0F, 255.0F }; + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/render/ESP.java b/src/minecraft/com/enjoytheban/module/modules/render/ESP.java new file mode 100644 index 0000000..106acec --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/render/ESP.java @@ -0,0 +1,264 @@ +package com.enjoytheban.module.modules.render; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.rendering.EventRender2D; +import com.enjoytheban.api.value.Mode; +import com.enjoytheban.api.value.Value; +import com.enjoytheban.management.FriendManager; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import com.enjoytheban.utils.math.Vec3f; +import com.enjoytheban.utils.render.RenderUtil; +import com.enjoytheban.utils.render.gl.GLUtils; +import java.awt.Color; +import java.util.ArrayList; +import java.util.Random; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.Timer; +import org.lwjgl.opengl.GL11; + + +public class ESP + extends Module +{ + private ArrayList points = new ArrayList(); + public Mode mode = new Mode("Mode", "mode", ESPMode.values(), ESPMode.TwoDimensional); + + public ESP() { + super("ESP", new String[] { "outline", "wallhack" }, ModuleType.Render); + addValues(new Value[] { mode }); + for (int i = 0; i < 8; i++) + { + points.add(new Vec3f()); + } + setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)).getRGB()); + } + + @EventHandler + public void onScreen(EventRender2D eventRender) { + if (mode.getValue() == ESPMode.TwoDimensional) { + GlStateManager.pushMatrix(); + ScaledResolution scaledRes = new ScaledResolution(mc); + double twoDscale = scaledRes.getScaleFactor() / Math.pow(scaledRes.getScaleFactor(), 2.0D); + GlStateManager.scale(twoDscale, twoDscale, twoDscale); + for (Object o : mc.theWorld.getLoadedEntityList()) { + if (((o instanceof EntityLivingBase)) && (o != mc.thePlayer) && ((o instanceof EntityPlayer))) { + EntityLivingBase ent = (EntityLivingBase)o; + render(ent); + } + } + GlStateManager.popMatrix(); + } + } + + + + + + + + private void render(Entity entity) + { + Entity extended = entity; + + RenderManager renderManager = mc.getRenderManager(); + + + Vec3f offset = extended.interpolate(mc.timer.renderPartialTicks).sub(extended.getPos()).add(0.0D, 0.1D, 0.0D); + if (entity.isInvisible()) { + return; + } + + AxisAlignedBB bb = entity.getEntityBoundingBox().offset(offset.getX() - RenderManager.renderPosX, + offset.getY() - RenderManager.renderPosY, offset.getZ() - RenderManager.renderPosZ); + + + ((Vec3f)points.get(0)).setX(minX).setY(minY).setZ(minZ); + ((Vec3f)points.get(1)).setX(maxX).setY(minY).setZ(minZ); + ((Vec3f)points.get(2)).setX(maxX).setY(minY).setZ(maxZ); + ((Vec3f)points.get(3)).setX(minX).setY(minY).setZ(maxZ); + ((Vec3f)points.get(4)).setX(minX).setY(maxY).setZ(minZ); + ((Vec3f)points.get(5)).setX(maxX).setY(maxY).setZ(minZ); + ((Vec3f)points.get(6)).setX(maxX).setY(maxY).setZ(maxZ); + ((Vec3f)points.get(7)).setX(minX).setY(maxY).setZ(maxZ); + + + + + + float left = Float.MAX_VALUE;float right = 0.0F;float top = Float.MAX_VALUE;float bottom = 0.0F; + + + for (Vec3f point : points) + { + Vec3f screen = point.toScreen(); + + if ((screen.getZ() >= 0.0D) && (screen.getZ() < 1.0D)) + { + + + + + + if (screen.getX() < left) + left = (float)screen.getX(); + if (screen.getY() < top) + top = (float)screen.getY(); + if (screen.getX() > right) + right = (float)screen.getX(); + if (screen.getY() > bottom) { + bottom = (float)screen.getY(); + } + } + } + + if ((bottom <= 1.0F) && (right <= 1.0F)) + { + return; + } + + + box(left, top, right, bottom); + + + + name(entity, left, top, right, bottom); + + + if (!(entity instanceof EntityLivingBase)) + { + return; + } + EntityLivingBase living = (EntityLivingBase)entity; + + + health(living, left, top, right, bottom); + } + + + + + + + + + + + + + + + private void box(float left, float top, float right, float bottom) + { + GL11.glColor4d(1.0D, 1.0D, 1.0D, 0.5D); + + + RenderUtil.drawLine(left, top, right, top, 2.0F); + RenderUtil.drawLine(left, bottom, right, bottom, 2.0F); + RenderUtil.drawLine(left, top, left, bottom, 2.0F); + RenderUtil.drawLine(right, top, right, bottom, 2.0F); + + + + + + + RenderUtil.drawLine(left + 1.0F, top + 1.0F, right - 1.0F, top + 1.0F, 1.0F); + RenderUtil.drawLine(left + 1.0F, bottom - 1.0F, right - 1.0F, bottom - 1.0F, 1.0F); + RenderUtil.drawLine(left + 1.0F, top + 1.0F, left + 1.0F, bottom - 1.0F, 1.0F); + RenderUtil.drawLine(right - 1.0F, top + 1.0F, right - 1.0F, bottom - 1.0F, 1.0F); + + + RenderUtil.drawLine(left - 1.0F, top - 1.0F, right + 1.0F, top - 1.0F, 1.0F); + RenderUtil.drawLine(left - 1.0F, bottom + 1.0F, right + 1.0F, bottom + 1.0F, 1.0F); + RenderUtil.drawLine(left - 1.0F, top + 1.0F, left - 1.0F, bottom + 1.0F, 1.0F); + RenderUtil.drawLine(right + 1.0F, top - 1.0F, right + 1.0F, bottom + 1.0F, 1.0F); + } + + + + + + + + + + + + + + + + + private void name(Entity entity, float left, float top, float right, float bottom) + { + mc.fontRendererObj.drawCenteredString(FriendManager.isFriend(entity.getName()) ? "§b" + FriendManager.getAlias(entity.getName()) : entity.getName(), (int)(left + right) / 2, + (int)(top - mc.fontRendererObj.FONT_HEIGHT - 2.0F + 1.0F), -1); + if (((EntityPlayer)entity).getCurrentEquippedItem() != null) + { + String stack = ((EntityPlayer)entity).getCurrentEquippedItem().getDisplayName(); + mc.fontRendererObj.drawCenteredString(stack, (int)(left + right) / 2, (int)bottom, -1); + } + } + + + + + + + + + + + + + + + + + private void health(EntityLivingBase entity, float left, float top, float right, float bottom) + { + float height = bottom - top; + + + float currentHealth = entity.getHealth(); + + float maxHealth = entity.getMaxHealth(); + + float healthPercent = currentHealth / maxHealth; + + + + GLUtils.glColor(getHealthColor(entity)); + + + + RenderUtil.drawLine(left - 5.0F, top + height * (1.0F - healthPercent) + 1.0F, left - 5.0F, bottom, 2.0F); + } + + + + + + private int getHealthColor(EntityLivingBase player) + { + float f = player.getHealth(); + float f1 = player.getMaxHealth(); + float f2 = Math.max(0.0F, Math.min(f, f1) / f1); + return Color.HSBtoRGB(f2 / 3.0F, 1.0F, 1.0F) | 0xFF000000; + } + + public static enum ESPMode { + Outline, TwoDimensional; + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/render/FullBright.java b/src/minecraft/com/enjoytheban/module/modules/render/FullBright.java new file mode 100644 index 0000000..259bb2e --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/render/FullBright.java @@ -0,0 +1,33 @@ +package com.enjoytheban.module.modules.render; + +import com.enjoytheban.api.events.world.EventTick; +import java.awt.Color; +import net.minecraft.client.Minecraft; + +public class FullBright extends com.enjoytheban.module.Module +{ + private float old; + + public FullBright() + { + super("FullBright", new String[] { "fbright", "brightness", "bright" }, com.enjoytheban.module.ModuleType.Render); + setColor(new Color(244, 255, 149).getRGB()); + } + + + + public void onEnable() + { + old = mc.gameSettings.gammaSetting; + } + + @com.enjoytheban.api.EventHandler + private void onTick(EventTick e) { + mc.gameSettings.gammaSetting = 1.5999999E7F; + } + + public void onDisable() + { + mc.gameSettings.gammaSetting = old; + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/render/HUD.java b/src/minecraft/com/enjoytheban/module/modules/render/HUD.java new file mode 100644 index 0000000..ec747fa --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/render/HUD.java @@ -0,0 +1 @@ +null \ No newline at end of file diff --git a/src/minecraft/com/enjoytheban/module/modules/render/Nametags.java b/src/minecraft/com/enjoytheban/module/modules/render/Nametags.java new file mode 100644 index 0000000..ec747fa --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/render/Nametags.java @@ -0,0 +1 @@ +null \ No newline at end of file diff --git a/src/minecraft/com/enjoytheban/module/modules/render/NoRender.java b/src/minecraft/com/enjoytheban/module/modules/render/NoRender.java new file mode 100644 index 0000000..ac24fd9 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/render/NoRender.java @@ -0,0 +1,14 @@ +package com.enjoytheban.module.modules.render; + +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import java.awt.Color; + +public class NoRender extends Module +{ + public NoRender() + { + super("NoRender", new String[] { "noitems" }, ModuleType.Render); + setColor(new Color(166, 185, 123).getRGB()); + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/render/Tracers.java b/src/minecraft/com/enjoytheban/module/modules/render/Tracers.java new file mode 100644 index 0000000..5937ec0 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/render/Tracers.java @@ -0,0 +1,81 @@ +package com.enjoytheban.module.modules.render; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.rendering.EventRender3D; +import com.enjoytheban.management.FriendManager; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import com.enjoytheban.utils.math.MathUtil; +import com.enjoytheban.utils.render.RenderUtil; +import java.awt.Color; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.client.renderer.EntityRenderer; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.client.settings.GameSettings; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.Timer; +import org.lwjgl.opengl.GL11; + +public class Tracers + extends Module +{ + public Tracers() + { + super("Tracers", new String[] { "lines", "tracer" }, ModuleType.Render); + setColor(new Color(60, 136, 166).getRGB()); + } + + @EventHandler + private void on3DRender(EventRender3D e) + { + for (Object o : mc.theWorld.loadedEntityList) + { + Entity entity = (Entity)o; + + if ((entity.isEntityAlive()) && ((entity instanceof EntityPlayer)) && (entity != mc.thePlayer)) { + double posX = lastTickPosX + (posX - lastTickPosX) * e.getPartialTicks() - + RenderManager.renderPosX; + double posY = lastTickPosY + (posY - lastTickPosY) * e.getPartialTicks() - + RenderManager.renderPosY; + double posZ = lastTickPosZ + (posZ - lastTickPosZ) * e.getPartialTicks() - + RenderManager.renderPosZ; + boolean old = mc.gameSettings.viewBobbing; + RenderUtil.startDrawing(); + mc.gameSettings.viewBobbing = false; + mc.entityRenderer.setupCameraTransform(mc.timer.renderPartialTicks, 2); + mc.gameSettings.viewBobbing = old; + float color = (float)Math.round(255.0D - mc.thePlayer.getDistanceSqToEntity(entity) * 255.0D / + MathUtil.square(mc.gameSettings.renderDistanceChunks * 2.5D)) / 255.0F; + drawLine(entity, new double[] { color, 1.0F - color, FriendManager.isFriend(entity.getName()) ? new double[] { 0.0D, 1.0D, 1.0D } : 0.0D }, posX, posY, posZ); + RenderUtil.stopDrawing(); + } + } + } + + private void drawLine(Entity entity, double[] color, double x, double y, double z) + { + float distance = mc.thePlayer.getDistanceToEntity(entity); + float xD = distance / 48.0F; + if (xD >= 1.0F) xD = 1.0F; + boolean entityesp = false; + + GL11.glEnable(2848); + if (color.length >= 4) { + if (color[3] <= 0.1D) { + return; + } + GL11.glColor4d(color[0], color[1], color[2], color[3]); + } else { + GL11.glColor3d(color[0], color[1], color[2]); + } + GL11.glLineWidth(1.0F); + GL11.glBegin(1); + GL11.glVertex3d(0.0D, mc.thePlayer.getEyeHeight(), 0.0D); + GL11.glVertex3d(x, y, z); + GL11.glEnd(); + GL11.glDisable(2848); + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/render/UI/TabUI.java b/src/minecraft/com/enjoytheban/module/modules/render/UI/TabUI.java new file mode 100644 index 0000000..a8d0ff2 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/render/UI/TabUI.java @@ -0,0 +1,493 @@ +package com.enjoytheban.module.modules.render.UI; + +import com.enjoytheban.Client; +import com.enjoytheban.api.EventBus; +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.misc.EventKey; +import com.enjoytheban.api.events.rendering.EventRender2D; +import com.enjoytheban.api.value.Mode; +import com.enjoytheban.api.value.Numbers; +import com.enjoytheban.api.value.Option; +import com.enjoytheban.api.value.Value; +import com.enjoytheban.management.Manager; +import com.enjoytheban.management.ModuleManager; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import com.enjoytheban.module.modules.render.HUD; +import com.enjoytheban.ui.font.CFontRenderer; +import com.enjoytheban.ui.font.FontLoaders; +import com.enjoytheban.utils.Helper; +import com.enjoytheban.utils.math.MathUtil; +import com.enjoytheban.utils.render.RenderUtil; +import java.awt.Color; +import java.util.Iterator; +import java.util.List; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.settings.GameSettings; + + + + +public class TabUI + implements Manager +{ + private Section section = Section.TYPES; + private ModuleType selectedType = ModuleType.values()[0]; + + private Module selectedModule = null; + private Value selectedValue = null; + + private int currentType = 0; private int currentModule = 0; private int currentValue = 0; private int height = 12; + private int maxType; + private int maxModule; + private int maxValue; + + public TabUI() {} + + public void init() { + for (ModuleType mt : ) { + if (maxType <= mcfontRendererObj.getStringWidth(mt.name().toUpperCase()) + 4) + { + + maxType = (mcfontRendererObj.getStringWidth(mt.name().toUpperCase()) + 4); + } + } + Client.instance.getModuleManager(); for (Module m : ModuleManager.getModules()) { + if (maxModule <= mcfontRendererObj.getStringWidth(m.getName().toUpperCase()) + 4) + { + + maxModule = (mcfontRendererObj.getStringWidth(m.getName().toUpperCase()) + 4); + } + } + Client.instance.getModuleManager(); for (Module m : ModuleManager.getModules()) { + if (!m.getValues().isEmpty()) + { + + + for (??? = m.getValues().iterator(); ((Iterator)???).hasNext();) { Value val = (Value)((Iterator)???).next(); + if (maxValue <= mcfontRendererObj.getStringWidth(val.getDisplayName().toUpperCase()) + 4) + { + + maxValue = (mcfontRendererObj.getStringWidth(val.getDisplayName().toUpperCase()) + 4); } + } + } + } + maxModule += 12; + maxValue += 24; + int highestWidth = 0; + maxType = (maxType < maxModule ? maxModule : maxType); + maxModule += maxType; + maxValue += maxModule; + + + EventBus.getInstance().register(new Object[] { this }); + } + + private void resetValuesLength() + { + maxValue = 0; + for (Value val : selectedModule.getValues()) { + int off = (val instanceof Option) ? 6 : + mcfontRendererObj.getStringWidth(String.format(" §7%s", new Object[] { val.getValue().toString() })) + + 6; + if (maxValue <= mcfontRendererObj.getStringWidth(val.getDisplayName().toUpperCase()) + off) + { + + maxValue = (mcfontRendererObj.getStringWidth(val.getDisplayName().toUpperCase()) + off); } + } + maxValue += maxModule; + } + + @EventHandler + private void renderTabGUI(EventRender2D e) + { + CFontRenderer font = FontLoaders.kiona18; + + if (HUD.useFont) { + if ((!mcgameSettings.showDebugInfo) && + (Client.instance.getModuleManager().getModuleByClass(HUD.class).isEnabled())) + { + int categoryY; + + int moduleY = categoryY = HUD.shouldMove ? 26 : height; + int valueY = categoryY; + + + RenderUtil.drawBorderedRect(2.0F, categoryY, maxType - 25, + categoryY + 12 * ModuleType.values().length, 2.0F, new Color(0, 0, 0, 130).getRGB(), + new Color(0, 0, 0, 180).getRGB()); + + + ModuleType[] moduleArray = ModuleType.values(); + int mA = moduleArray.length; + int mA2 = 0; + while (mA2 < mA) { + ModuleType mt = moduleArray[mA2]; + if (selectedType == mt) + { + Gui.drawRect(2.5D, categoryY + 0.5D, maxType - 25.5D, + categoryY + mcfontRendererObj.FONT_HEIGHT + 2.5D, + new Color(102, 172, 255).getRGB()); + moduleY = categoryY; + } + + if (selectedType == mt) { + font.drawStringWithShadow(mt.name(), 7.0D, categoryY + 3, -1); + } else { + font.drawStringWithShadow(mt.name(), 5.0D, categoryY + 3, new Color(180, 180, 180).getRGB()); + } + categoryY += 12; + mA2++; + } + + if ((section == Section.MODULES) || (section == Section.VALUES)) + { + RenderUtil.drawBorderedRect(maxType - 20, moduleY, maxModule - 38, + moduleY + 12 * + Client.instance.getModuleManager().getModulesInType(selectedType).size(), + 2.0F, new Color(0, 0, 0, 130).getRGB(), new Color(0, 0, 0, 180).getRGB()); + + for (Module m : Client.instance.getModuleManager().getModulesInType(selectedType)) { + if (selectedModule == m) { + Gui.drawRect(maxType - 19.5D, moduleY + 0.5D, maxModule - 38.5D, + moduleY + mcfontRendererObj.FONT_HEIGHT + 2.5D, + new Color(102, 172, 255).getRGB()); + valueY = moduleY; + } + + if (selectedModule == m) { + font.drawStringWithShadow(m.getName(), maxType - 15, moduleY + 3, + m.isEnabled() ? -1 : 11184810); + } else { + font.drawStringWithShadow(m.getName(), maxType - 17, moduleY + 3, + m.isEnabled() ? -1 : 11184810); + } + + if (!m.getValues().isEmpty()) { + Gui.drawRect(maxModule - 38, moduleY + 0.5D, maxModule - 39, + moduleY + mcfontRendererObj.FONT_HEIGHT + 2.5D, + new Color(153, 200, 255).getRGB()); + + if ((section == Section.VALUES) && (selectedModule == m)) { + RenderUtil.drawBorderedRect(maxModule - 32, valueY, maxValue - 25, + valueY + 12 * selectedModule.getValues().size(), 2.0F, + new Color(10, 10, 10, 180).getRGB(), new Color(10, 10, 10, 180).getRGB()); + + for (Value val : selectedModule.getValues()) { + Gui.drawRect(maxModule - 31.5D, valueY + 0.5D, maxValue - 25.5D, + valueY + mcfontRendererObj.FONT_HEIGHT + 2.5D, + selectedValue == val ? new Color(102, 172, 255).getRGB() : 0); + if ((val instanceof Option)) { + font.drawStringWithShadow(val.getDisplayName(), + selectedValue == val ? maxModule - 27 : maxModule - 29, + valueY + 3, + ((Boolean)val.getValue()).booleanValue() ? new Color(153, 200, 255).getRGB() : + 11184810); + } else { + String toRender = String.format("%s: §7%s", new Object[] { val.getDisplayName(), + val.getValue().toString() }); + + if (selectedValue == val) + { + font.drawStringWithShadow(toRender, maxModule - 27, valueY + 3, -1); + } else { + font.drawStringWithShadow(toRender, maxModule - 29, valueY + 3, -1); + } + } + valueY += 12; + } + } + } + moduleY += 12; + } + } + } + } + else if ((!mcgameSettings.showDebugInfo) && + (Client.instance.getModuleManager().getModuleByClass(HUD.class).isEnabled())) + { + int categoryY; + + int moduleY = categoryY = HUD.shouldMove ? 26 : height; + int valueY = categoryY; + + + RenderUtil.drawBorderedRect(2.0F, categoryY, maxType - 25, + categoryY + 12 * ModuleType.values().length, 2.0F, new Color(0, 0, 0, 130).getRGB(), + new Color(0, 0, 0, 180).getRGB()); + + + ModuleType[] moduleArray = ModuleType.values(); + int mA = moduleArray.length; + int mA2 = 0; + while (mA2 < mA) { + ModuleType mt = moduleArray[mA2]; + if (selectedType == mt) + { + Gui.drawRect(2.5D, categoryY + 0.5D, maxType - 25.5D, + categoryY + mcfontRendererObj.FONT_HEIGHT + 2.5D, + new Color(102, 172, 255).getRGB()); + moduleY = categoryY; + } + + if (selectedType == mt) { + mcfontRendererObj.drawStringWithShadow(mt.name(), 7.0F, categoryY + 2, -1); + } else { + mcfontRendererObj.drawStringWithShadow(mt.name(), 5.0F, categoryY + 2, + new Color(180, 180, 180).getRGB()); + } + categoryY += 12; + mA2++; + } + + if ((section == Section.MODULES) || (section == Section.VALUES)) + { + RenderUtil.drawBorderedRect(maxType - 20, moduleY, maxModule - 38, + moduleY + 12 * + Client.instance.getModuleManager().getModulesInType(selectedType).size(), + 2.0F, new Color(0, 0, 0, 130).getRGB(), new Color(0, 0, 0, 180).getRGB()); + + for (Module m : Client.instance.getModuleManager().getModulesInType(selectedType)) { + if (selectedModule == m) { + Gui.drawRect(maxType - 19.5D, moduleY + 0.5D, maxModule - 38.5D, + moduleY + mcfontRendererObj.FONT_HEIGHT + 2.5D, + new Color(102, 172, 255).getRGB()); + valueY = moduleY; + } + + if (selectedModule == m) { + mcfontRendererObj.drawStringWithShadow(m.getName(), maxType - 15, moduleY + 2, + m.isEnabled() ? -1 : 11184810); + } else { + mcfontRendererObj.drawStringWithShadow(m.getName(), maxType - 17, moduleY + 2, + m.isEnabled() ? -1 : 11184810); + } + + if (!m.getValues().isEmpty()) { + Gui.drawRect(maxModule - 38, moduleY + 0.5D, maxModule - 39, + moduleY + mcfontRendererObj.FONT_HEIGHT + 2.5D, + new Color(153, 200, 255).getRGB()); + + if ((section == Section.VALUES) && (selectedModule == m)) { + RenderUtil.drawBorderedRect(maxModule - 32, valueY, maxValue - 25, + valueY + 12 * selectedModule.getValues().size(), 2.0F, + new Color(10, 10, 10, 180).getRGB(), new Color(10, 10, 10, 180).getRGB()); + + for (Value val : selectedModule.getValues()) { + Gui.drawRect(maxModule - 31.5D, valueY + 0.5D, maxValue - 25.5D, + valueY + mcfontRendererObj.FONT_HEIGHT + 2.5D, + selectedValue == val ? new Color(102, 172, 255).getRGB() : 0); + if ((val instanceof Option)) { + mcfontRendererObj.drawStringWithShadow(val.getDisplayName(), + selectedValue == val ? maxModule - 27 : maxModule - 29, + valueY + 2, + ((Boolean)val.getValue()).booleanValue() ? new Color(153, 200, 255).getRGB() : + 11184810); + } else { + String toRender = String.format("%s: §7%s", new Object[] { val.getDisplayName(), + val.getValue().toString() }); + + if (selectedValue == val) + { + mcfontRendererObj.drawStringWithShadow(toRender, + maxModule - 27, valueY + 2, -1); + } else { + mcfontRendererObj.drawStringWithShadow(toRender, + maxModule - 29, valueY + 2, -1); + } + } + valueY += 12; + } + } + } + moduleY += 12; + } + } + } + } + + + @EventHandler + private void onKey(EventKey e) + { + if (!mcgameSettings.showDebugInfo) { + switch (e.getKey()) { + case 208: + switch (section) { + case MODULES: + currentType += 1; + if (currentType > ModuleType.values().length - 1) { + currentType = 0; + } + selectedType = ModuleType.values()[currentType]; + break; + + case TYPES: + currentModule += 1; + + if (currentModule > Client.instance.getModuleManager().getModulesInType(selectedType).size() - 1) { + currentModule = 0; + } + selectedModule = + ((Module)Client.instance.getModuleManager().getModulesInType(selectedType).get(currentModule)); + break; + + case VALUES: + currentValue += 1; + if (currentValue > selectedModule.getValues().size() - 1) { + currentValue = 0; + } + selectedValue = ((Value)selectedModule.getValues().get(currentValue)); + } + + break; + + case 200: + switch (section) { + case MODULES: + currentType -= 1; + if (currentType < 0) { + currentType = (ModuleType.values().length - 1); + } + selectedType = ModuleType.values()[currentType]; + break; + + case TYPES: + currentModule -= 1; + if (currentModule < 0) { + currentModule = + (Client.instance.getModuleManager().getModulesInType(selectedType).size() - 1); + } + selectedModule = + ((Module)Client.instance.getModuleManager().getModulesInType(selectedType).get(currentModule)); + break; + + case VALUES: + currentValue -= 1; + if (currentValue < 0) { + currentValue = (selectedModule.getValues().size() - 1); + } + selectedValue = ((Value)selectedModule.getValues().get(currentValue)); + } + + break; + + case 205: + switch (section) { + case MODULES: + currentModule = 0; + selectedModule = + ((Module)Client.instance.getModuleManager().getModulesInType(selectedType).get(currentModule)); + section = Section.MODULES; + break; + + case TYPES: + if (!selectedModule.getValues().isEmpty()) { + resetValuesLength(); + currentValue = 0; + selectedValue = ((Value)selectedModule.getValues().get(currentValue)); + section = Section.VALUES; + } + break; + + case VALUES: + if (!Helper.onServer("enjoytheban")) { + if ((selectedValue instanceof Option)) { + selectedValue.setValue(Boolean.valueOf(!((Boolean)selectedValue.getValue()).booleanValue())); + } else if ((selectedValue instanceof Numbers)) { + Numbers value = (Numbers)selectedValue; + double inc = ((Double)value.getValue()).doubleValue(); + inc += ((Double)value.getIncrement()).doubleValue(); + inc = MathUtil.toDecimalLength(inc, 1); + if (inc > ((Double)value.getMaximum()).doubleValue()) { + inc = ((Double)((Numbers)selectedValue).getMinimum()).doubleValue(); + } + selectedValue.setValue(Double.valueOf(inc)); + } else if ((selectedValue instanceof Mode)) { + Mode theme = (Mode)selectedValue; + Enum current = (Enum)theme.getValue(); + int next = current.ordinal() + 1 >= theme.getModes().length ? 0 : current.ordinal() + 1; + selectedValue.setValue(theme.getModes()[next]); + } + resetValuesLength(); + } + break; + } + break; + + case 28: + switch (section) + { + case MODULES: + break; + case TYPES: + selectedModule.setEnabled(!selectedModule.isEnabled()); + break; + + case VALUES: + section = Section.MODULES; + } + + break; + + case 203: + switch (section) + { + case MODULES: + break; + case TYPES: + section = Section.TYPES; + currentModule = 0; + break; + + case VALUES: + if (!Helper.onServer("enjoytheban")) { Enum current; + if ((selectedValue instanceof Option)) { + selectedValue.setValue(Boolean.valueOf(!((Boolean)selectedValue.getValue()).booleanValue())); + + } + else if ((selectedValue instanceof Numbers)) { + Numbers value = (Numbers)selectedValue; + double inc = ((Double)value.getValue()).doubleValue(); + inc -= ((Double)value.getIncrement()).doubleValue(); + inc = MathUtil.toDecimalLength(inc, 1); + if (inc < ((Double)value.getMinimum()).doubleValue()) { + inc = ((Double)((Numbers)selectedValue).getMaximum()).doubleValue(); + } + selectedValue.setValue(Double.valueOf(inc)); + + } + else if ((selectedValue instanceof Mode)) { + Mode theme = (Mode)selectedValue; + current = (Enum)theme.getValue(); + int next = current.ordinal() - 1 < 0 ? theme.getModes().length - 1 : current.ordinal() - 1; + selectedValue.setValue(theme.getModes()[next]); + } + maxValue = 0; + for (Value val : selectedModule.getValues()) { + int off = (val instanceof Option) ? 6 : + getMinecraftfontRendererObj + .getStringWidth(String.format(" §7%s", new Object[] { val.getValue().toString() })) + 6; + + if (maxValue <= getMinecraftfontRendererObj.getStringWidth(val.getDisplayName().toUpperCase()) + off) + { + + maxValue = + (getMinecraftfontRendererObj.getStringWidth(val.getDisplayName().toUpperCase()) + off); } + } + maxValue += maxModule; + } + break; + } + break; + } + } + } + + public static enum Section + { + TYPES, MODULES, VALUES; + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/render/Xray.java b/src/minecraft/com/enjoytheban/module/modules/render/Xray.java new file mode 100644 index 0000000..19092f2 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/render/Xray.java @@ -0,0 +1,38 @@ +package com.enjoytheban.module.modules.render; + +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import java.awt.Color; +import java.util.List; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.RenderGlobal; + +public class Xray extends Module +{ + public List blocks = new java.util.ArrayList(); + + public Xray() { + super("Xray", new String[] { "xrai", "oreesp" }, ModuleType.Render); + setColor(Color.GREEN.getRGB()); + blocks.add(Integer.valueOf(16)); + blocks.add(Integer.valueOf(56)); + blocks.add(Integer.valueOf(14)); + blocks.add(Integer.valueOf(15)); + blocks.add(Integer.valueOf(129)); + blocks.add(Integer.valueOf(73)); + } + + public void onEnable() + { + mc.renderGlobal.loadRenderers(); + } + + public void onDisable() + { + mc.renderGlobal.loadRenderers(); + } + + public List getBlocks() { + return blocks; + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/world/AntiVoid.java b/src/minecraft/com/enjoytheban/module/modules/world/AntiVoid.java new file mode 100644 index 0000000..1aaa856 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/world/AntiVoid.java @@ -0,0 +1,44 @@ +package com.enjoytheban.module.modules.world; + +import com.enjoytheban.api.events.world.EventPreUpdate; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import java.awt.Color; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.util.BlockPos; + +public class AntiVoid extends Module +{ + public AntiVoid() + { + super("AntiVoid", new String[] { "novoid", "antifall" }, ModuleType.World); + setColor(new Color(223, 233, 233).getRGB()); + } + + @com.enjoytheban.api.EventHandler + private void onUpdate(EventPreUpdate e) + { + boolean blockUnderneath = false; + + for (int i = 0; i < mc.thePlayer.posY + 2.0D; i++) { + BlockPos pos = new BlockPos(mc.thePlayer.posX, i, mc.thePlayer.posZ); + + if (!(mc.theWorld.getBlockState(pos).getBlock() instanceof net.minecraft.block.BlockAir)) + { + + blockUnderneath = true; + } + } + if (blockUnderneath) { + return; + } + if (mc.thePlayer.fallDistance < 2.0F) { + return; + } + if ((!mc.thePlayer.onGround) && (!mc.thePlayer.isCollidedVertically)) { + mc.thePlayer.motionY += 0.07D; + } + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/world/AutoArmor.java b/src/minecraft/com/enjoytheban/module/modules/world/AutoArmor.java new file mode 100644 index 0000000..39410b0 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/world/AutoArmor.java @@ -0,0 +1,148 @@ +package com.enjoytheban.module.modules.world; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventPreUpdate; +import com.enjoytheban.api.value.Numbers; +import com.enjoytheban.api.value.Value; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import com.enjoytheban.utils.TimerUtil; +import java.awt.Color; +import java.util.Random; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.multiplayer.PlayerControllerMP; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.player.PlayerCapabilities; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.Slot; +import net.minecraft.item.Item; +import net.minecraft.item.ItemArmor; +import net.minecraft.item.ItemStack; + +public class AutoArmor + extends Module +{ + private Numbers delay = new Numbers("Delay", "delay", Double.valueOf(50.0D), Double.valueOf(0.0D), Double.valueOf(1000.0D), Double.valueOf(10.0D)); + + private TimerUtil timer = new TimerUtil(); + + + private int[] boots = { 313, 309, 317, 305, 301 }; + private int[] chestplate = { 311, 307, 315, 303, 299 }; + private int[] helmet = { 310, 306, 314, 302, 298 }; + private int[] leggings = { 312, 308, 316, 304, 300 }; + + + private int slot = 5; + private double enchantmentValue = -1.0D; + private double protectionValue; + private int item = -1; + + public AutoArmor() { + super("AutoArmor", new String[] { "armorswap", "autoarmour" }, ModuleType.World); + addValues(new Value[] { delay }); + setColor(new Color(27, 104, 204).getRGB()); + } + + @EventHandler + private void onPre(EventPreUpdate e) { + if (e.getType() == 0) { + if ((mc.thePlayer.capabilities.isCreativeMode) || ( + (mc.thePlayer.openContainer != null) && (mc.thePlayer.openContainer.windowId != 0))) { + return; + } + + + if (timer.hasReached(((Double)delay.getValue()).doubleValue() + new Random().nextInt(4))) { + enchantmentValue = -1.0D; + item = -1; + for (int i = 9; i < 45; i++) { + if ((mc.thePlayer.inventoryContainer.getSlot(i).getStack() != null) && + (canEquip(mc.thePlayer.inventoryContainer.getSlot(i).getStack()) != -1) && + (canEquip(mc.thePlayer.inventoryContainer.getSlot(i).getStack()) == slot)) { + change(slot, i); + } + } + if (item != -1) { + if (mc.thePlayer.inventoryContainer.getSlot(item).getStack() != null) + mc.playerController.windowClick(0, slot, 0, 1, mc.thePlayer); + mc.playerController.windowClick(0, item, 0, 1, mc.thePlayer); + } + + if (slot == 8) { + slot = 5; + } else { + slot += 1; + } + timer.reset(); + } + } + } + + private int canEquip(ItemStack stack) + { + for (int id : boots) { + stack.getItem(); if (Item.getIdFromItem(stack.getItem()) == id) + return 8; + } + for (int id : leggings) { + stack.getItem(); if (Item.getIdFromItem(stack.getItem()) == id) + return 7; + } + for (int id : chestplate) { + stack.getItem(); if (Item.getIdFromItem(stack.getItem()) == id) + return 6; + } + for (int id : helmet) { + stack.getItem(); if (Item.getIdFromItem(stack.getItem()) == id) + return 5; + } + return -1; + } + + private void change(int numy, int i) + { + if (enchantmentValue == -1.0D) { + if (mc.thePlayer.inventoryContainer.getSlot(numy).getStack() != null) { + protectionValue = getProtValue(mc.thePlayer.inventoryContainer.getSlot(numy).getStack()); + } else + protectionValue = enchantmentValue; + } else { + protectionValue = enchantmentValue; + } + + if (protectionValue <= getProtValue(mc.thePlayer.inventoryContainer.getSlot(i).getStack())) { + if (protectionValue == getProtValue(mc.thePlayer.inventoryContainer.getSlot(i).getStack())) { + int currentD = mc.thePlayer.inventoryContainer.getSlot(numy).getStack() != null ? + mc.thePlayer.inventoryContainer.getSlot(numy).getStack().getItemDamage() : + 999; + int newD = mc.thePlayer.inventoryContainer.getSlot(i).getStack() != null ? + mc.thePlayer.inventoryContainer.getSlot(i).getStack().getItemDamage() : + 500; + if ((newD <= currentD) && + (newD != currentD)) + { + item = i; + enchantmentValue = getProtValue(mc.thePlayer.inventoryContainer.getSlot(i).getStack()); + } + } + else { + item = i; + enchantmentValue = getProtValue(mc.thePlayer.inventoryContainer.getSlot(i).getStack()); + } + } + } + + private double getProtValue(ItemStack stack) + { + if (stack != null) { + return getItemdamageReduceAmount + + (100 - getItemdamageReduceAmount * 4) * + EnchantmentHelper.getEnchantmentLevel(field_180310_ceffectId, stack) * 4 * + 0.0075D; + } + return 0.0D; + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/world/Banwave.java b/src/minecraft/com/enjoytheban/module/modules/world/Banwave.java new file mode 100644 index 0000000..91da25d --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/world/Banwave.java @@ -0,0 +1,63 @@ +package com.enjoytheban.module.modules.world; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventPreUpdate; +import com.enjoytheban.api.value.Numbers; +import com.enjoytheban.api.value.Option; +import com.enjoytheban.api.value.Value; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import com.enjoytheban.utils.TimerUtil; +import java.awt.Color; +import java.io.PrintStream; +import java.util.ArrayList; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityOtherPlayerMP; +import net.minecraft.client.entity.EntityPlayerSP; + +public class Banwave extends Module +{ + private TimerUtil timer = new TimerUtil(); + + public ArrayList banned; + private String banMessage = "twitter.com/CustomKKK"; + + private Option tempBan = new Option("Temp Ban", "temp", Boolean.valueOf(false)); + private Numbers banDelay = new Numbers("Delay", "delay", Double.valueOf(10.0D), Double.valueOf(1.0D), Double.valueOf(20.0D), Double.valueOf(1.0D)); + + public Banwave() { + super("BanWave", new String[] { "dick", "banner" }, ModuleType.Player); + setColor(new Color(255, 0, 0).getRGB()); + banned = new ArrayList(); + addValues(new Value[] { tempBan, banDelay }); + } + + public void onEnable() + { + banned.clear(); + super.onEnable(); + } + + @EventHandler + public void onUpdate(EventPreUpdate event) { + for (Object o : mc.theWorld.getLoadedEntityList()) { + if ((o instanceof EntityOtherPlayerMP)) { + EntityOtherPlayerMP e = (EntityOtherPlayerMP)o; + if ((timer.hasReached(((Double)banDelay.getValue()).doubleValue() * 100.0D)) && (!com.enjoytheban.management.FriendManager.isFriend(e.getName())) && + (e.getName() != mc.thePlayer.getName()) && (!banned.contains(e))) + { + + if (((Boolean)tempBan.getValue()).booleanValue()) { + mc.thePlayer.sendChatMessage("/tempban " + e.getName() + " 7d" + " " + banMessage); + System.out.println("/tempban " + e.getName() + " 7d" + " " + banMessage); + } else { + mc.thePlayer.sendChatMessage("/ban " + e.getName() + " " + banMessage); + System.out.println("/ban " + e.getName() + " " + banMessage); + } + banned.add(e); + timer.reset(); + } + } + } + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/world/Blink.java b/src/minecraft/com/enjoytheban/module/modules/world/Blink.java new file mode 100644 index 0000000..29de530 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/world/Blink.java @@ -0,0 +1,71 @@ +package com.enjoytheban.module.modules.world; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventPacketSend; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import com.mojang.authlib.GameProfile; +import java.awt.Color; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityOtherPlayerMP; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.network.Packet; +import net.minecraft.network.play.client.C02PacketUseEntity; +import net.minecraft.network.play.client.C03PacketPlayer; +import net.minecraft.network.play.client.C08PacketPlayerBlockPlacement; +import net.minecraft.network.play.client.C0APacketAnimation; +import net.minecraft.network.play.client.C0BPacketEntityAction; + + +public class Blink + extends Module +{ + private EntityOtherPlayerMP blinkEntity; + private List packetList; + + public Blink() + { + super("Blink", new String[] { "blonk" }, ModuleType.Player); + packetList = new ArrayList(); + } + + public void onEnable() + { + setColor(new Color(200, 100, 200).getRGB()); + if (mc.thePlayer == null) { + return; + } + blinkEntity = new EntityOtherPlayerMP(mc.theWorld, new GameProfile(new UUID(69L, 96L), "Blink")); + blinkEntity.inventory = mc.thePlayer.inventory; + blinkEntity.inventoryContainer = mc.thePlayer.inventoryContainer; + blinkEntity.setPositionAndRotation(mc.thePlayer.posX, mc.thePlayer.posY, mc.thePlayer.posZ, + mc.thePlayer.rotationYaw, mc.thePlayer.rotationPitch); + blinkEntity.rotationYawHead = mc.thePlayer.rotationYawHead; + mc.theWorld.addEntityToWorld(blinkEntity.getEntityId(), blinkEntity); + } + + @EventHandler + private void onPacketSend(EventPacketSend event) { + if (((event.getPacket() instanceof C0BPacketEntityAction)) || ((event.getPacket() instanceof C03PacketPlayer)) || + ((event.getPacket() instanceof C02PacketUseEntity)) || + ((event.getPacket() instanceof C0APacketAnimation)) || + ((event.getPacket() instanceof C08PacketPlayerBlockPlacement))) { + packetList.add(event.getPacket()); + event.setCancelled(true); + } + } + + public void onDisable() + { + for (Packet packet : packetList) { + mc.getNetHandler().addToSendQueue(packet); + } + packetList.clear(); + mc.theWorld.removeEntityFromWorld(blinkEntity.getEntityId()); + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/world/ChestStealer.java b/src/minecraft/com/enjoytheban/module/modules/world/ChestStealer.java new file mode 100644 index 0000000..ee34e1a --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/world/ChestStealer.java @@ -0,0 +1,68 @@ +package com.enjoytheban.module.modules.world; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventTick; +import com.enjoytheban.api.value.Numbers; +import com.enjoytheban.api.value.Value; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import com.enjoytheban.utils.TimerUtil; +import java.awt.Color; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.multiplayer.PlayerControllerMP; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; + + +public class ChestStealer + extends Module +{ + private Numbers delay = new Numbers("Delay", "delay", Double.valueOf(50.0D), Double.valueOf(0.0D), Double.valueOf(1000.0D), Double.valueOf(10.0D)); + + private TimerUtil timer = new TimerUtil(); + + public ChestStealer() { + super("ChestStealer", new String[] { "cheststeal", "chests", "stealer" }, ModuleType.World); + addValues(new Value[] { delay }); + setColor(new Color(218, 97, 127).getRGB()); + } + + @EventHandler + private void onUpdate(EventTick event) { + if ((mc.thePlayer.openContainer != null) && ((mc.thePlayer.openContainer instanceof ContainerChest))) { + ContainerChest container = (ContainerChest)mc.thePlayer.openContainer; + + for (int i = 0; i < container.getLowerChestInventory().getSizeInventory(); i++) { + if ((container.getLowerChestInventory().getStackInSlot(i) != null) && + (timer.hasReached(((Double)delay.getValue()).doubleValue()))) + { + mc.playerController.windowClick(windowId, i, 0, 1, mc.thePlayer); + timer.reset(); + } + } + + if (isEmpty()) { + mc.thePlayer.closeScreen(); + } + } + } + + + private boolean isEmpty() + { + if ((mc.thePlayer.openContainer != null) && ((mc.thePlayer.openContainer instanceof ContainerChest))) { + ContainerChest container = (ContainerChest)mc.thePlayer.openContainer; + + for (int i = 0; i < container.getLowerChestInventory().getSizeInventory(); i++) { + ItemStack itemStack = container.getLowerChestInventory().getStackInSlot(i); + + if ((itemStack != null) && (itemStack.getItem() != null)) { + return false; + } + } + } + return true; + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/world/Deathclip.java b/src/minecraft/com/enjoytheban/module/modules/world/Deathclip.java new file mode 100644 index 0000000..ff7200c --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/world/Deathclip.java @@ -0,0 +1,34 @@ +package com.enjoytheban.module.modules.world; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventPreUpdate; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import com.enjoytheban.utils.TimerUtil; +import java.awt.Color; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.util.AxisAlignedBB; + + + +public class Deathclip + extends Module +{ + private TimerUtil timer = new TimerUtil(); + + public Deathclip() { + super("DeathClip", new String[] { "deathc", "dc" }, ModuleType.World); + setColor(new Color(157, 58, 157).getRGB()); + } + + @EventHandler + private void onUpdate(EventPreUpdate e) { + if ((mc.thePlayer.getHealth() == 0.0F) && (mc.thePlayer.onGround)) { + mc.thePlayer.boundingBox.offsetAndUpdate(mc.thePlayer.posX, -10.0D, mc.thePlayer.posZ); + if (timer.hasReached(500.0D)) { + mc.thePlayer.sendChatMessage("/home"); + } + } + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/world/FastPlace.java b/src/minecraft/com/enjoytheban/module/modules/world/FastPlace.java new file mode 100644 index 0000000..ef4ff1a --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/world/FastPlace.java @@ -0,0 +1,22 @@ +package com.enjoytheban.module.modules.world; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventTick; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import java.awt.Color; + +public class FastPlace extends Module +{ + public FastPlace() + { + super("FastPlace", new String[] { "fplace", "fc" }, ModuleType.World); + setColor(new Color(226, 197, 78).getRGB()); + } + + @EventHandler + private void onTick(EventTick e) + { + mc.rightClickDelayTimer = 0; + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/world/NoRotate.java b/src/minecraft/com/enjoytheban/module/modules/world/NoRotate.java new file mode 100644 index 0000000..54dec68 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/world/NoRotate.java @@ -0,0 +1,33 @@ +package com.enjoytheban.module.modules.world; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventPacketSend; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import java.awt.Color; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.network.play.server.S08PacketPlayerPosLook; + + + + + +public class NoRotate + extends Module +{ + public NoRotate() + { + super("NoRotate", new String[] { "rotate" }, ModuleType.World); + setColor(new Color(17, 250, 154).getRGB()); + } + + @EventHandler + private void onPacket(EventPacketSend e) { + if ((e.getPacket() instanceof S08PacketPlayerPosLook)) { + S08PacketPlayerPosLook look = (S08PacketPlayerPosLook)e.getPacket(); + field_148936_d = mc.thePlayer.rotationYaw; + field_148937_e = mc.thePlayer.rotationPitch; + } + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/world/Phase.java b/src/minecraft/com/enjoytheban/module/modules/world/Phase.java new file mode 100644 index 0000000..d208c06 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/world/Phase.java @@ -0,0 +1,90 @@ +package com.enjoytheban.module.modules.world; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.misc.EventCollideWithBlock; +import com.enjoytheban.api.events.world.EventMove; +import com.enjoytheban.api.events.world.EventPostUpdate; +import com.enjoytheban.api.value.Mode; +import com.enjoytheban.api.value.Value; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import com.enjoytheban.utils.math.RotationUtil; +import java.awt.Color; +import net.minecraft.block.state.pattern.BlockHelper; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.network.play.client.C03PacketPlayer.C04PacketPlayerPosition; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.MathHelper; +import net.minecraft.util.MovementInput; + + +public class Phase + extends Module +{ + private Mode mode = new Mode("Mode", "mode", PhaseMode.values(), PhaseMode.NewNCP); + + public Phase() { + super("Phase", new String[] { "noclip" }, ModuleType.World); + setColor(new Color(255, 166, 25).getRGB()); + addValues(new Value[] { mode }); + } + + + @EventHandler + private void onBlockCollision(EventCollideWithBlock e) + { + if ((e.getBoundingBox() != null) && (getBoundingBoxmaxY > mc.thePlayer.boundingBox.minY) && + (mc.thePlayer.isSneaking()) && (mode.getValue() != PhaseMode.OldNCP)) { + e.setBoundingBox(null); + } + if ((e.getBoundingBox() != null) && (getBoundingBoxmaxY > mc.thePlayer.boundingBox.minY) && + (mode.getValue() == PhaseMode.OldNCP)) { + e.setBoundingBox(null); + } + } + + @EventHandler + private void onMove(EventMove e) { + if ((BlockHelper.insideBlock()) && (mc.thePlayer.isSneaking()) && (mode.getValue() == PhaseMode.SkipClip)) { + mc.thePlayer.boundingBox.offsetAndUpdate( + mc.thePlayer.movementInput.moveForward * 3.6D * + Math.cos(Math.toRadians(mc.thePlayer.rotationYaw + 90.0F)) + + mc.thePlayer.movementInput.moveStrafe * 3.6D * + Math.sin(Math.toRadians(mc.thePlayer.rotationYaw + 90.0F)), + 0.0D, + mc.thePlayer.movementInput.moveForward * 3.6D * + Math.sin(Math.toRadians(mc.thePlayer.rotationYaw + 90.0F)) - + mc.thePlayer.movementInput.moveStrafe * 3.6D * + Math.cos(Math.toRadians(mc.thePlayer.rotationYaw + 90.0F))); + } + } + + @EventHandler + private void onUpdate(EventPostUpdate e) + { + if (BlockHelper.insideBlock()) { + if ((mode.getValue() == PhaseMode.NewNCP) && (mc.thePlayer.isSneaking())) { + mc.thePlayer.boundingBox.offsetAndUpdate(0.0524D * Math.cos(Math.toRadians(RotationUtil.yaw() + 90.0F)), + 0.0D, 0.0524D * Math.sin(Math.toRadians(RotationUtil.yaw() + 90.0F))); + } + if ((mode.getValue() == PhaseMode.OldNCP) && (mc.thePlayer.isCollidedVertically)) { + double x = -MathHelper.sin(mc.thePlayer.getDirection()) * 0.2D; + double z = MathHelper.cos(mc.thePlayer.getDirection()) * 0.2D; + mc.thePlayer.sendQueue.addToSendQueue(new C03PacketPlayer.C04PacketPlayerPosition(mc.thePlayer.posX + x, + mc.thePlayer.posY, mc.thePlayer.posZ + z, false)); + mc.thePlayer.sendQueue.addToSendQueue(new C03PacketPlayer.C04PacketPlayerPosition(mc.thePlayer.posX + x, + Double.MIN_VALUE, mc.thePlayer.posZ + z, true)); + mc.thePlayer.setPosition(mc.thePlayer.posX + x, mc.thePlayer.posY, mc.thePlayer.posZ + z); + } + + if ((mc.thePlayer.onGround) && (mode.getValue() == PhaseMode.NewNCP)) + mc.thePlayer.jump(); + } + } + + static enum PhaseMode { + NewNCP, OldNCP, SkipClip; + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/world/PinCracker.java b/src/minecraft/com/enjoytheban/module/modules/world/PinCracker.java new file mode 100644 index 0000000..c21e079 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/world/PinCracker.java @@ -0,0 +1,58 @@ +package com.enjoytheban.module.modules.world; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventPreUpdate; +import com.enjoytheban.api.value.Numbers; +import com.enjoytheban.api.value.Option; +import com.enjoytheban.api.value.Value; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import com.enjoytheban.utils.TimerUtil; +import java.awt.Color; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; + + +public class PinCracker + extends Module +{ + private TimerUtil time = new TimerUtil(); + + int num; + private Option login = new Option("/login?", "login", Boolean.valueOf(false)); + private Numbers delay = new Numbers("Delay", "Delay", Double.valueOf(1.0D), Double.valueOf(0.0D), Double.valueOf(20.0D), Double.valueOf(1.0D)); + + public PinCracker() { + super("PinCracker", new String[] { "pincracker" }, ModuleType.World); + addValues(new Value[] { login, delay }); + } + + @EventHandler + public void onUpdate(EventPreUpdate event) { + setColor(new Color(200, 200, 100).getRGB()); + if (((Boolean)login.getValue()).booleanValue()) { + if (time.delay((float)(((Double)delay.getValue()).doubleValue() * 100.0D))) { + mc.thePlayer.sendChatMessage("/login " + numbers()); + time.reset(); + } + } + else if (time.delay((float)(((Double)delay.getValue()).doubleValue() * 100.0D))) { + mc.thePlayer.sendChatMessage("/pin " + numbers()); + time.reset(); + } + } + + private int numbers() + { + if (num <= 10000) { + num += 1; + } + return num; + } + + public void onDisable() + { + num = 0; + super.onDisable(); + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/world/PingSpoof.java b/src/minecraft/com/enjoytheban/module/modules/world/PingSpoof.java new file mode 100644 index 0000000..d4fe2ea --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/world/PingSpoof.java @@ -0,0 +1,49 @@ +package com.enjoytheban.module.modules.world; + +import com.enjoytheban.api.events.world.EventPacketSend; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import com.enjoytheban.utils.TimerUtil; +import java.awt.Color; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import net.minecraft.client.Minecraft; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.network.NetworkManager; +import net.minecraft.network.Packet; +import net.minecraft.network.play.client.C00PacketKeepAlive; +import optifine.MathUtils; + +public class PingSpoof extends Module +{ + private List packetList = new CopyOnWriteArrayList(); + private TimerUtil timer = new TimerUtil(); + + public PingSpoof() { + super("PingSpoof", new String[] { "spoofping", "ping" }, ModuleType.World); + setColor(new Color(117, 52, 203).getRGB()); + } + + @com.enjoytheban.api.EventHandler + private void onPacketSend(EventPacketSend e) { + if (((e.getPacket() instanceof C00PacketKeepAlive)) && (mc.thePlayer.isEntityAlive())) { + packetList.add(e.getPacket()); + e.setCancelled(true); + } + if (timer.hasReached(750.0D)) { + if (!packetList.isEmpty()) { + int i = 0; + double totalPackets = MathUtils.getIncremental(Math.random() * 10.0D, 1.0D); + for (Packet packet : packetList) + if (i < totalPackets) + { + i++; + mc.getNetHandler().getNetworkManager().sendPacket(packet); + packetList.remove(packet); + } + } + mc.getNetHandler().getNetworkManager().sendPacket(new C00PacketKeepAlive(10000)); + timer.reset(); + } + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/world/SafeWalk.java b/src/minecraft/com/enjoytheban/module/modules/world/SafeWalk.java new file mode 100644 index 0000000..cf8315f --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/world/SafeWalk.java @@ -0,0 +1,19 @@ +package com.enjoytheban.module.modules.world; + +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import java.awt.Color; + + + + + +public class SafeWalk + extends Module +{ + public SafeWalk() + { + super("SafeWalk", new String[] { "eagle", "parkour" }, ModuleType.World); + setColor(new Color(198, 253, 191).getRGB()); + } +} diff --git a/src/minecraft/com/enjoytheban/module/modules/world/StaffAlerts.java b/src/minecraft/com/enjoytheban/module/modules/world/StaffAlerts.java new file mode 100644 index 0000000..72f1ac3 --- /dev/null +++ b/src/minecraft/com/enjoytheban/module/modules/world/StaffAlerts.java @@ -0,0 +1,82 @@ +package com.enjoytheban.module.modules.world; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventPreUpdate; +import com.enjoytheban.module.Module; +import com.enjoytheban.module.ModuleType; +import com.enjoytheban.utils.Helper; +import java.awt.Color; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Scanner; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.entity.player.EntityPlayer; + + +public class StaffAlerts + extends Module +{ + public StaffAlerts() + { + super("StaffAlerts", new String[] { "staff", "stafffinder" }, ModuleType.World); + setColor(new Color(198, 253, 191).getRGB()); + } + + private static List staff = new ArrayList(); + + private static Scanner scanner; + public boolean isStaff = false; + + public void onEnable() + { + checkStaff(); + isStaff = false; + super.onEnable(); + } + + @EventHandler + public void onUpdate(EventPreUpdate event) { + if (mc.theWorld.playerEntities != null) { Iterator localIterator2; + for (Iterator localIterator1 = mc.theWorld.playerEntities.iterator(); localIterator1.hasNext(); + + localIterator2.hasNext()) + { + Object object = localIterator1.next(); + EntityPlayer entityPlayer = (EntityPlayer)object; + localIterator2 = staff.iterator(); continue;String staffxd = (String)localIterator2.next(); + if ((entityPlayer != null) && (entityPlayer.getName().equalsIgnoreCase(staffxd)) && (!isStaff)) { + Helper.sendMessage(entityPlayer.getName() + " is staff!"); + isStaff = true; + staff.clear(); + } + } + } + } + + public void checkStaff() + { + try { + URLConnection openConnection = new URL("http://box.enjoytheban.com/staffnames.txt").openConnection(); + openConnection.addRequestProperty("User-Agent", + "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0"); + + scanner = new Scanner(new InputStreamReader(openConnection.getInputStream())); + + while (scanner.hasNextLine()) { + String meme = scanner.nextLine(); + if ((!meme.contains(":")) && (!meme.contains("(")) && (meme.length() > 1)) { + staff.add(meme); + } + } + + scanner.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/minecraft/com/enjoytheban/ui/font/CFont.java b/src/minecraft/com/enjoytheban/ui/font/CFont.java new file mode 100644 index 0000000..df414ab --- /dev/null +++ b/src/minecraft/com/enjoytheban/ui/font/CFont.java @@ -0,0 +1,166 @@ +package com.enjoytheban.ui.font; + +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import net.minecraft.client.renderer.texture.DynamicTexture; +import org.lwjgl.opengl.GL11; + +public class CFont +{ + private final float imgSize = 512.0F; + protected CharData[] charData = new CharData['Ā']; + protected Font font; + protected boolean antiAlias; + protected boolean fractionalMetrics; + protected int fontHeight = -1; + protected int charOffset = 0; + protected DynamicTexture tex; + + public CFont(Font font, boolean antiAlias, boolean fractionalMetrics) { + this.font = font; + this.antiAlias = antiAlias; + this.fractionalMetrics = fractionalMetrics; + tex = setupTexture(font, antiAlias, fractionalMetrics, charData); + } + + protected DynamicTexture setupTexture(Font font, boolean antiAlias, boolean fractionalMetrics, CharData[] chars) { + BufferedImage img = generateFontImage(font, antiAlias, fractionalMetrics, chars); + try { + return new DynamicTexture(img); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + protected BufferedImage generateFontImage(Font font, boolean antiAlias, boolean fractionalMetrics, CharData[] chars) { + int imgSize = 512; + BufferedImage bufferedImage = new BufferedImage(imgSize, imgSize, 2); + Graphics2D g = (Graphics2D)bufferedImage.getGraphics(); + g.setFont(font); + g.setColor(new Color(255, 255, 255, 0)); + g.fillRect(0, 0, imgSize, imgSize); + g.setColor(Color.WHITE); + g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, fractionalMetrics ? RenderingHints.VALUE_FRACTIONALMETRICS_ON : RenderingHints.VALUE_FRACTIONALMETRICS_OFF); + g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, antiAlias ? RenderingHints.VALUE_TEXT_ANTIALIAS_ON : RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antiAlias ? RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF); + FontMetrics fontMetrics = g.getFontMetrics(); + int charHeight = 0; + int positionX = 0; + int positionY = 1; + for (int i = 0; i < chars.length; i++) { + char ch = (char)i; + CharData charData = new CharData(); + Rectangle2D dimensions = fontMetrics.getStringBounds(String.valueOf(ch), g); + width = (getBoundswidth + 8); + height = getBoundsheight; + if (positionX + width >= imgSize) { + positionX = 0; + positionY += charHeight; + charHeight = 0; + } + if (height > charHeight) { + charHeight = height; + } + storedX = positionX; + storedY = positionY; + if (height > fontHeight) { + fontHeight = height; + } + chars[i] = charData; + g.drawString(String.valueOf(ch), positionX + 2, positionY + fontMetrics.getAscent()); + positionX += width; + } + return bufferedImage; + } + + public void drawChar(CharData[] chars, char c, float x, float y) throws ArrayIndexOutOfBoundsException { + try { + drawQuad(x, y, width, height, storedX, storedY, width, height); + } catch (Exception e) { + e.printStackTrace(); + } + } + + protected void drawQuad(float x, float y, float width, float height, float srcX, float srcY, float srcWidth, float srcHeight) { + float renderSRCX = srcX / 512.0F; + float renderSRCY = srcY / 512.0F; + float renderSRCWidth = srcWidth / 512.0F; + float renderSRCHeight = srcHeight / 512.0F; + GL11.glTexCoord2f(renderSRCX + renderSRCWidth, renderSRCY); + GL11.glVertex2d(x + width, y); + GL11.glTexCoord2f(renderSRCX, renderSRCY); + GL11.glVertex2d(x, y); + GL11.glTexCoord2f(renderSRCX, renderSRCY + renderSRCHeight); + GL11.glVertex2d(x, y + height); + GL11.glTexCoord2f(renderSRCX, renderSRCY + renderSRCHeight); + GL11.glVertex2d(x, y + height); + GL11.glTexCoord2f(renderSRCX + renderSRCWidth, renderSRCY + renderSRCHeight); + GL11.glVertex2d(x + width, y + height); + GL11.glTexCoord2f(renderSRCX + renderSRCWidth, renderSRCY); + GL11.glVertex2d(x + width, y); + } + + public int getStringHeight(String text) { + return getHeight(); + } + + public int getHeight() { + return (fontHeight - 8) / 2; + } + + public int getStringWidth(String text) { + int width = 0; + for (char c : text.toCharArray()) { + if ((c < charData.length) && (c >= 0)) width += charData[c].width - 8 + charOffset; + } + return width / 2; + } + + public boolean isAntiAlias() { + return antiAlias; + } + + public void setAntiAlias(boolean antiAlias) { + if (this.antiAlias != antiAlias) { + this.antiAlias = antiAlias; + tex = setupTexture(font, antiAlias, fractionalMetrics, charData); + } + } + + public boolean isFractionalMetrics() { + return fractionalMetrics; + } + + public void setFractionalMetrics(boolean fractionalMetrics) { + if (this.fractionalMetrics != fractionalMetrics) { + this.fractionalMetrics = fractionalMetrics; + tex = setupTexture(font, antiAlias, fractionalMetrics, charData); + } + } + + public Font getFont() { + return font; + } + + public void setFont(Font font) { + this.font = font; + tex = setupTexture(font, antiAlias, fractionalMetrics, charData); + } + + protected class CharData + { + public int width; + public int height; + public int storedX; + public int storedY; + + protected CharData() {} + } +} diff --git a/src/minecraft/com/enjoytheban/ui/font/CFontRenderer.java b/src/minecraft/com/enjoytheban/ui/font/CFontRenderer.java new file mode 100644 index 0000000..0dbbfd6 --- /dev/null +++ b/src/minecraft/com/enjoytheban/ui/font/CFontRenderer.java @@ -0,0 +1,350 @@ +package com.enjoytheban.ui.font; + +import java.awt.Font; +import java.util.ArrayList; +import java.util.List; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.texture.DynamicTexture; +import org.lwjgl.opengl.GL11; + + + +public class CFontRenderer + extends CFont +{ + protected CFont.CharData[] boldChars = new CFont.CharData['Ā']; + protected CFont.CharData[] italicChars = new CFont.CharData['Ā']; + protected CFont.CharData[] boldItalicChars = new CFont.CharData['Ā']; + + private final int[] colorCode = new int[32]; + private final String colorcodeIdentifiers = "0123456789abcdefklmnor"; + protected DynamicTexture texBold; + protected DynamicTexture texItalic; + protected DynamicTexture texItalicBold; + + public CFontRenderer(Font font, boolean antiAlias, boolean fractionalMetrics) { + super(font, antiAlias, fractionalMetrics); + setupMinecraftColorcodes(); + setupBoldItalicIDs(); + } + + public float drawStringWithShadow(String text, double x, double y, int color) { + float shadowWidth = drawString(text, x + 0.5D, y + 0.5D, color, true); + return Math.max(shadowWidth, drawString(text, x, y, color, false)); + } + + public float drawString(String text, float x, float y, int color) { + return drawString(text, x, y, color, false); + } + + public float drawCenteredString(String text, float x, float y, int color) { + return drawString(text, x - getStringWidth(text) / 2, y, color); + } + + public float drawCenteredStringWithShadow(String text, float x, float y, int color) { + return drawStringWithShadow(text, x - getStringWidth(text) / 2, y, color); + } + + public float drawCenteredStringWithShadow(String text, double x, double y, int color) { + return drawStringWithShadow(text, x - getStringWidth(text) / 2, y, color); + } + + public float drawString(String text, double x, double y, int color, boolean shadow) { + x -= 1.0D; + + if (text == null) { + return 0.0F; + } + + if (color == 553648127) { + color = 16777215; + } + + if ((color & 0xFC000000) == 0) { + color |= 0xFF000000; + } + + if (shadow) { + color = (color & 0xFCFCFC) >> 2 | color & 0xFF000000; + } + + CFont.CharData[] currentData = charData; + float alpha = (color >> 24 & 0xFF) / 255.0F; + boolean randomCase = false; + boolean bold = false; + boolean italic = false; + boolean strikethrough = false; + boolean underline = false; + boolean render = true; + x *= 2.0D; + y = (y - 3.0D) * 2.0D; + + if (render) { + GL11.glPushMatrix(); + GlStateManager.scale(0.5D, 0.5D, 0.5D); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(770, 771); + GlStateManager.color((color >> 16 & 0xFF) / 255.0F, (color >> 8 & 0xFF) / 255.0F, + (color & 0xFF) / 255.0F, alpha); + int size = text.length(); + GlStateManager.enableTexture2D(); + GlStateManager.func_179144_i(tex.getGlTextureId()); + + GL11.glBindTexture(3553, tex.getGlTextureId()); + + for (int i = 0; i < size; i++) { + char character = text.charAt(i); + + if ((character == '§') && (i < size)) { + int colorIndex = 21; + try + { + colorIndex = "0123456789abcdefklmnor".indexOf(text.charAt(i + 1)); + } catch (Exception e) { + e.printStackTrace(); + } + + if (colorIndex < 16) { + bold = false; + italic = false; + randomCase = false; + underline = false; + strikethrough = false; + GlStateManager.func_179144_i(tex.getGlTextureId()); + currentData = charData; + + if ((colorIndex < 0) || (colorIndex > 15)) { + colorIndex = 15; + } + + if (shadow) { + colorIndex += 16; + } + + int colorcode = colorCode[colorIndex]; + GlStateManager.color((colorcode >> 16 & 0xFF) / 255.0F, (colorcode >> 8 & 0xFF) / 255.0F, + (colorcode & 0xFF) / 255.0F, alpha); + } else if (colorIndex == 16) { + randomCase = true; + } else if (colorIndex == 17) { + bold = true; + + if (italic) { + GlStateManager.func_179144_i(texItalicBold.getGlTextureId()); + currentData = boldItalicChars; + } else { + GlStateManager.func_179144_i(texBold.getGlTextureId()); + currentData = boldChars; + } + } else if (colorIndex == 18) { + strikethrough = true; + } else if (colorIndex == 19) { + underline = true; + } else if (colorIndex == 20) { + italic = true; + + if (bold) { + GlStateManager.func_179144_i(texItalicBold.getGlTextureId()); + currentData = boldItalicChars; + } else { + GlStateManager.func_179144_i(texItalic.getGlTextureId()); + currentData = italicChars; + } + } else if (colorIndex == 21) { + bold = false; + italic = false; + randomCase = false; + underline = false; + strikethrough = false; + GlStateManager.color((color >> 16 & 0xFF) / 255.0F, (color >> 8 & 0xFF) / 255.0F, + (color & 0xFF) / 255.0F, alpha); + GlStateManager.func_179144_i(tex.getGlTextureId()); + currentData = charData; + } + + i++; + } else if ((character < currentData.length) && (character >= 0)) { + GL11.glBegin(4); + drawChar(currentData, character, (float)x, (float)y); + GL11.glEnd(); + + if (strikethrough) { + drawLine(x, y + height / 2, x + width - 8.0D, + y + height / 2, 1.0F); + } + + if (underline) { + drawLine(x, y + height - 2.0D, + x + width - 8.0D, y + height - 2.0D, + 1.0F); + } + + x += width - 8 + charOffset; + } + } + + GL11.glHint(3155, 4352); + GL11.glPopMatrix(); + } + + return (float)x / 2.0F; + } + + public int getStringWidth(String text) { + if (text == null) + return 0; + int width = 0; + CFont.CharData[] currentData = charData; + boolean bold = false; + boolean italic = false; + int size = text.length(); + + for (int i = 0; i < size; i++) { + char character = text.charAt(i); + if ((character == '§') && (i < size)) { + int colorIndex = "0123456789abcdefklmnor".indexOf(character); + if (colorIndex < 16) { + bold = false; + italic = false; + } else if (colorIndex == 17) { + bold = true; + if (italic) { + currentData = boldItalicChars; + } else + currentData = boldChars; + } else if (colorIndex == 20) { + italic = true; + if (bold) { + currentData = boldItalicChars; + } else + currentData = italicChars; + } else if (colorIndex == 21) { + bold = false; + italic = false; + currentData = charData; + } + i++; + } else if ((character < currentData.length) && (character >= 0)) { + width += width - 8 + charOffset; + } + } + + return width / 2; + } + + public void setFont(Font font) { + super.setFont(font); + setupBoldItalicIDs(); + } + + public void setAntiAlias(boolean antiAlias) { + super.setAntiAlias(antiAlias); + setupBoldItalicIDs(); + } + + public void setFractionalMetrics(boolean fractionalMetrics) { + super.setFractionalMetrics(fractionalMetrics); + setupBoldItalicIDs(); + } + + private void setupBoldItalicIDs() { + texBold = setupTexture(font.deriveFont(1), antiAlias, fractionalMetrics, boldChars); + texItalic = setupTexture(font.deriveFont(2), antiAlias, fractionalMetrics, italicChars); + } + + private void drawLine(double x, double y, double x1, double y1, float width) + { + GL11.glDisable(3553); + GL11.glLineWidth(width); + GL11.glBegin(1); + GL11.glVertex2d(x, y); + GL11.glVertex2d(x1, y1); + GL11.glEnd(); + GL11.glEnable(3553); + } + + public List wrapWords(String text, double width) { + List finalWords = new ArrayList(); + if (getStringWidth(text) > width) { + String[] words = text.split(" "); + String currentWord = ""; + char lastColorCode = 65535; + + for (String word : words) { + for (int i = 0; i < word.toCharArray().length; i++) { + char c = word.toCharArray()[i]; + + if ((c == '§') && (i < word.toCharArray().length - 1)) { + lastColorCode = word.toCharArray()[(i + 1)]; + } + } + if (getStringWidth(currentWord + word + " ") < width) { + currentWord = currentWord + word + " "; + } else { + finalWords.add(currentWord); + currentWord = '§' + lastColorCode + word + " "; + } + } + if (currentWord.length() > 0) + if (getStringWidth(currentWord) < width) { + finalWords.add('§' + lastColorCode + currentWord + " "); + currentWord = ""; + } else { + for (String s : formatString(currentWord, width)) + finalWords.add(s); + } + } else { + finalWords.add(text); + } + + return finalWords; + } + + public List formatString(String string, double width) { + List finalWords = new ArrayList(); + String currentWord = ""; + char lastColorCode = 65535; + char[] chars = string.toCharArray(); + for (int i = 0; i < chars.length; i++) { + char c = chars[i]; + + if ((c == '§') && (i < chars.length - 1)) { + lastColorCode = chars[(i + 1)]; + } + + if (getStringWidth(currentWord + c) < width) { + currentWord = currentWord + c; + } else { + finalWords.add(currentWord); + currentWord = '§' + lastColorCode + String.valueOf(c); + } + } + + if (currentWord.length() > 0) { + finalWords.add(currentWord); + } + + return finalWords; + } + + private void setupMinecraftColorcodes() { + for (int index = 0; index < 32; index++) { + int noClue = (index >> 3 & 0x1) * 85; + int red = (index >> 2 & 0x1) * 170 + noClue; + int green = (index >> 1 & 0x1) * 170 + noClue; + int blue = (index >> 0 & 0x1) * 170 + noClue; + + if (index == 6) { + red += 85; + } + + if (index >= 16) { + red /= 4; + green /= 4; + blue /= 4; + } + + colorCode[index] = ((red & 0xFF) << 16 | (green & 0xFF) << 8 | blue & 0xFF); + } + } +} diff --git a/src/minecraft/com/enjoytheban/ui/font/FontLoaders.java b/src/minecraft/com/enjoytheban/ui/font/FontLoaders.java new file mode 100644 index 0000000..4de62e1 --- /dev/null +++ b/src/minecraft/com/enjoytheban/ui/font/FontLoaders.java @@ -0,0 +1,33 @@ +package com.enjoytheban.ui.font; + +import java.awt.Font; +import java.io.InputStream; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.IResource; +import net.minecraft.util.ResourceLocation; + +public abstract class FontLoaders +{ + public static CFontRenderer kiona16 = new CFontRenderer(getKiona(16), true, true); + public static CFontRenderer kiona18 = new CFontRenderer(getKiona(18), true, true); + public static CFontRenderer kiona20 = new CFontRenderer(getKiona(20), true, true); + public static CFontRenderer kiona22 = new CFontRenderer(getKiona(22), true, true); + public static CFontRenderer kiona24 = new CFontRenderer(getKiona(24), true, true); + public static CFontRenderer kiona26 = new CFontRenderer(getKiona(26), true, true); + public static CFontRenderer kiona28 = new CFontRenderer(getKiona(28), true, true); + + public FontLoaders() {} + + private static Font getKiona(int size) { Font font; + try { InputStream is = Minecraft.getMinecraft().getResourceManager() + .getResource(new ResourceLocation("ETB/raleway.ttf")).getInputStream(); + Font font = Font.createFont(0, is); + font = font.deriveFont(0, size); + } catch (Exception ex) { + ex.printStackTrace(); + System.out.println("Error loading font"); + font = new Font("default", 0, size); + } + return font; + } +} diff --git a/src/minecraft/com/enjoytheban/ui/font/Utils.java b/src/minecraft/com/enjoytheban/ui/font/Utils.java new file mode 100644 index 0000000..b8e2e1d --- /dev/null +++ b/src/minecraft/com/enjoytheban/ui/font/Utils.java @@ -0,0 +1,108 @@ +package com.enjoytheban.ui.font; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import net.minecraft.block.Block; +import net.minecraft.block.BlockSlab; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.client.settings.GameSettings; +import net.minecraft.client.settings.KeyBinding; +import net.minecraft.inventory.Container; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ItemSword; +import net.minecraft.network.play.client.C03PacketPlayer.C04PacketPlayerPosition; + +public class Utils +{ + public Utils() {} + + public static boolean fuck = true; + private static Minecraft mc = Minecraft.getMinecraft(); + + public static boolean isContainerEmpty(Container container) { + int i = 0; for (int slotAmount = inventorySlots.size() == 90 ? 54 : 27; i < slotAmount; i++) { + if (container.getSlot(i).getHasStack()) { + return false; + } + } + return true; + } + + public static Minecraft getMinecraft() { + return mc; + } + + public static boolean canBlock() { + if (mc == null) { + mc = Minecraft.getMinecraft(); + } + if (mcthePlayer.getHeldItem() == null) + return false; + if ((mcthePlayer.isBlocking()) || ((mcthePlayer.isUsingItem()) && ((mcthePlayer.getCurrentEquippedItem().getItem() instanceof ItemSword)))) + return true; + if (((mcthePlayer.getHeldItem().getItem() instanceof ItemSword)) && (getMinecraftgameSettings.keyBindUseItem.isPressed())) { + return true; + } + return false; + } + + public static String getMD5(String input) { + StringBuilder res = new StringBuilder(); + try { + MessageDigest algorithm = MessageDigest.getInstance("MD5"); + algorithm.reset(); + algorithm.update(input.getBytes()); + byte[] md5 = algorithm.digest(); + + for (byte aMd5 : md5) { + String tmp = Integer.toHexString(0xFF & aMd5); + if (tmp.length() == 1) { + res.append("0").append(tmp); + } else { + res.append(tmp); + } + } + } + catch (NoSuchAlgorithmException localNoSuchAlgorithmException) {} + return res.toString(); + } + + public static void breakAnticheats() { + mcthePlayer.sendQueue.addToSendQueue(new C03PacketPlayer.C04PacketPlayerPosition(mcthePlayer.posX + mcthePlayer.motionX, mcthePlayer.posY - 110.0D, mcthePlayer.posZ + mcthePlayer.motionZ, true)); + } + + public static int add(int number, int add, int max) { + return number + add > max ? max : number + add; + } + + public static int remove(int number, int remove, int min) { + return number - remove < min ? min : number - remove; + } + + public static int check(int number) { + return number > 255 ? 255 : number <= 0 ? 1 : number; + } + + public static double getDist() { + double distance = 0.0D; + for (double i = mcthePlayer.posY; i > 0.0D; i -= 0.1D) { + if (i < 0.0D) { + break; + } + Block block = mctheWorld.getBlockState(new net.minecraft.util.BlockPos(mcthePlayer.posX, i, mcthePlayer.posZ)).getBlock(); + if ((block.getMaterial() != net.minecraft.block.material.Material.air) && (block.isCollidable()) && ((block.isFullBlock()) || ((block instanceof BlockSlab)) || ((block instanceof net.minecraft.block.BlockBarrier)) || ((block instanceof net.minecraft.block.BlockStairs)) || + ((block instanceof net.minecraft.block.BlockGlass)) || ((block instanceof net.minecraft.block.BlockStainedGlass)))) + { + if ((block instanceof BlockSlab)) { + i -= 0.5D; + } + distance = i; + break; + } + } + return mcthePlayer.posY - distance; + } +} diff --git a/src/minecraft/com/enjoytheban/ui/login/Alt.java b/src/minecraft/com/enjoytheban/ui/login/Alt.java new file mode 100644 index 0000000..852209e --- /dev/null +++ b/src/minecraft/com/enjoytheban/ui/login/Alt.java @@ -0,0 +1,43 @@ +package com.enjoytheban.ui.login; + + +public class Alt +{ + private String mask = ""; + private final String username; + private String password; + + public Alt(String username, String password) + { + this(username, password, ""); + } + + public Alt(String username, String password, String mask) + { + this.username = username; + this.password = password; + this.mask = mask; + } + + public String getMask() + { + return mask; + } + + public String getPassword() + { + return password; + } + + public String getUsername() + { + return username; + } + + public void setMask(String mask) + { + this.mask = mask; + } + + public void setPassword(String password) { this.password = password; } +} diff --git a/src/minecraft/com/enjoytheban/ui/login/AltLoginThread.java b/src/minecraft/com/enjoytheban/ui/login/AltLoginThread.java new file mode 100644 index 0000000..d0d5280 --- /dev/null +++ b/src/minecraft/com/enjoytheban/ui/login/AltLoginThread.java @@ -0,0 +1,84 @@ +package com.enjoytheban.ui.login; + +import com.enjoytheban.Client; +import com.enjoytheban.management.FileManager; +import com.mojang.authlib.Agent; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.exceptions.AuthenticationException; +import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; +import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication; +import java.net.Proxy; +import java.util.UUID; +import net.minecraft.client.Minecraft; +import net.minecraft.util.Session; + + +public class AltLoginThread + extends Thread +{ + private final Minecraft mc = Minecraft.getMinecraft(); + private final String password; + private String status; + private final String username; + + public AltLoginThread(String username, String password) + { + super("Alt Login Thread"); + this.username = username; + this.password = password; + status = "§eWaiting..."; + } + + private final Session createSession(String username, String password) + { + YggdrasilAuthenticationService service = new YggdrasilAuthenticationService( + Proxy.NO_PROXY, ""); + YggdrasilUserAuthentication auth = (YggdrasilUserAuthentication)service + .createUserAuthentication(Agent.MINECRAFT); + auth.setUsername(username); + auth.setPassword(password); + try + { + auth.logIn(); + return new Session(auth.getSelectedProfile().getName(), auth + .getSelectedProfile().getId().toString(), + auth.getAuthenticatedToken(), "mojang"); + } + catch (AuthenticationException localAuthenticationException) {} + return null; + } + + public String getStatus() + { + return status; + } + + public void run() + { + if (password.equals("")) + { + mc.session = new Session(username, "", "", "mojang"); + status = ("§aLogged in. (" + username + " - offline name)"); + return; + } + status = "§eLogging in..."; + Session auth = createSession(username, password); + if (auth == null) + { + status = "§cLogin failed!"; + } + else + { + Client.instance.getAltManager().setLastAlt(new Alt(username, password)); + FileManager.saveLastAlt(); + status = ("§aLogged in. (" + auth.getUsername() + ")"); + mc.session = auth; + } + } + + + public void setStatus(String status) + { + this.status = status; + } +} diff --git a/src/minecraft/com/enjoytheban/ui/login/AltManager.java b/src/minecraft/com/enjoytheban/ui/login/AltManager.java new file mode 100644 index 0000000..7b47671 --- /dev/null +++ b/src/minecraft/com/enjoytheban/ui/login/AltManager.java @@ -0,0 +1,34 @@ +package com.enjoytheban.ui.login; + +import java.util.List; + +public class AltManager { + static List alts; + static Alt lastAlt; + + public AltManager() {} + + public static void init() { + setupAlts(); + getAlts(); + } + + public Alt getLastAlt() { + return lastAlt; + } + + public void setLastAlt(Alt alt) + { + lastAlt = alt; + } + + public static void setupAlts() + { + alts = new java.util.ArrayList(); + } + + public static List getAlts() + { + return alts; + } +} diff --git a/src/minecraft/com/enjoytheban/ui/login/GuiAddAlt.java b/src/minecraft/com/enjoytheban/ui/login/GuiAddAlt.java new file mode 100644 index 0000000..20fc883 --- /dev/null +++ b/src/minecraft/com/enjoytheban/ui/login/GuiAddAlt.java @@ -0,0 +1,181 @@ +package com.enjoytheban.ui.login; + +import com.enjoytheban.Client; +import com.enjoytheban.management.FileManager; +import com.enjoytheban.utils.Helper; +import com.mojang.authlib.Agent; +import com.mojang.authlib.exceptions.AuthenticationException; +import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; +import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication; +import java.io.IOException; +import java.net.Proxy; +import java.util.List; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.GuiTextField; +import org.lwjgl.input.Keyboard; + + + +public class GuiAddAlt + extends GuiScreen +{ + private final GuiAltManager manager; + private GuiPasswordField password; + + private class AddAltThread + extends Thread + { + private final String password; + private final String username; + + public AddAltThread(String username, String password) + { + this.username = username; + this.password = password; + status = "§7Waiting..."; + } + + private final void checkAndAddAlt(String username, String password) + { + YggdrasilAuthenticationService service = new YggdrasilAuthenticationService( + Proxy.NO_PROXY, ""); + YggdrasilUserAuthentication auth = (YggdrasilUserAuthentication)service + .createUserAuthentication(Agent.MINECRAFT); + auth.setUsername(username); + auth.setPassword(password); + try + { + auth.logIn(); + Client.instance.getAltManager();AltManager.getAlts() + .add(new Alt(username, password)); + FileManager.saveAlts(); + status = ("§aAlt added. (" + username + ")"); + } + catch (AuthenticationException e) + { + status = "§cAlt failed!"; + e.printStackTrace(); + } + } + + public void run() + { + if (password.equals("")) + { + Client.instance.getAltManager();AltManager.getAlts().add(new Alt(username, "")); + FileManager.saveAlts(); + status = ("§aAlt added. (" + username + " - offline name)"); + return; + } + status = "§eTrying alt..."; + checkAndAddAlt(username, password); + } + } + + private String status = "§eWaiting..."; + private GuiTextField username; + private GuiTextField combined; + + public GuiAddAlt(GuiAltManager manager) + { + this.manager = manager; + } + + protected void actionPerformed(GuiButton button) + { + switch (id) { + case 0: AddAltThread login; + AddAltThread login; + if (combined.getText().isEmpty()) { + login = new AddAltThread(username.getText(), password.getText()); } else { AddAltThread login; + if ((!combined.getText().isEmpty()) && (combined.getText().contains(":"))) { + String u = combined.getText().split(":")[0]; + String p = combined.getText().split(":")[1]; + login = new AddAltThread(u.replaceAll(" ", ""), p.replaceAll(" ", "")); + } + else { + login = new AddAltThread(username.getText(), password.getText()); + } } + login.start(); + break; + case 1: + mc.displayGuiScreen(manager); + } + } + + public void drawScreen(int i, int j, float f) + { + drawDefaultBackground(); + + + mcfontRendererObj.drawCenteredString("Add Alt", width / 2, 20, + -1); + username.drawTextBox(); + password.drawTextBox(); + combined.drawTextBox(); + if (username.getText().isEmpty()) { + mcfontRendererObj.drawStringWithShadow("Username / E-Mail", width / 2 - 96, + 66.0F, -7829368); + } + if (password.getText().isEmpty()) { + mcfontRendererObj.drawStringWithShadow("Password", width / 2 - 96, 106.0F, + -7829368); + } + if (combined.getText().isEmpty()) { + mcfontRendererObj.drawStringWithShadow("Email:Password", width / 2 - 96, 146.0F, -7829368); + } + mcfontRendererObj.drawCenteredString(status, width / 2, 30, -1); + + super.drawScreen(i, j, f); + } + + public void initGui() + { + Keyboard.enableRepeatEvents(true); + buttonList.clear(); + buttonList.add(new GuiButton(0, width / 2 - 100, + height / 4 + 92 + 12, "Login")); + buttonList.add(new GuiButton(1, width / 2 - 100, + height / 4 + 116 + 12, "Back")); + username = new GuiTextField(1, mc.fontRendererObj, width / 2 - 100, 60, 200, + 20); + password = new GuiPasswordField(mc.fontRendererObj, width / 2 - 100, 100, + 200, 20); + combined = new GuiTextField(eventButton, mc.fontRendererObj, width / 2 - 100, 140, 200, 20); + combined.setMaxStringLength(200); + } + + protected void keyTyped(char par1, int par2) + { + username.textboxKeyTyped(par1, par2); + password.textboxKeyTyped(par1, par2); + combined.textboxKeyTyped(par1, par2); + if ((par1 == '\t') && ((username.isFocused()) || (combined.isFocused()) || (password.isFocused()))) + { + username.setFocused(!username.isFocused()); + password.setFocused(!password.isFocused()); + combined.setFocused(!combined.isFocused()); + } + if (par1 == '\r') { + actionPerformed((GuiButton)buttonList.get(0)); + } + } + + protected void mouseClicked(int par1, int par2, int par3) + { + try + { + super.mouseClicked(par1, par2, par3); + } + catch (IOException e) + { + e.printStackTrace(); + } + username.mouseClicked(par1, par2, par3); + password.mouseClicked(par1, par2, par3); + combined.mouseClicked(par1, par2, par3); + } +} diff --git a/src/minecraft/com/enjoytheban/ui/login/GuiAltLogin.java b/src/minecraft/com/enjoytheban/ui/login/GuiAltLogin.java new file mode 100644 index 0000000..efe1e5d --- /dev/null +++ b/src/minecraft/com/enjoytheban/ui/login/GuiAltLogin.java @@ -0,0 +1,123 @@ +package com.enjoytheban.ui.login; + +import com.enjoytheban.utils.Helper; +import java.io.IOException; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.GuiTextField; + +public class GuiAltLogin extends GuiScreen +{ + private GuiPasswordField password; + private final GuiScreen previousScreen; + private AltLoginThread thread; + private GuiTextField username; + private GuiTextField combined; + + public GuiAltLogin(GuiScreen previousScreen) + { + this.previousScreen = previousScreen; + } + + protected void actionPerformed(GuiButton button) { + switch (id) { + case 1: + mc.displayGuiScreen(previousScreen); + break; + case 0: + if (combined.getText().isEmpty()) { + thread = new AltLoginThread(username.getText(), password.getText()); + } else if ((!combined.getText().isEmpty()) && (combined.getText().contains(":"))) { + String u = combined.getText().split(":")[0]; + String p = combined.getText().split(":")[1]; + thread = new AltLoginThread(u.replaceAll(" ", ""), p.replaceAll(" ", "")); + } else { + thread = new AltLoginThread(username.getText(), password.getText()); } + thread.start(); + } + } + + public void drawScreen(int x, int y, float z) { + drawDefaultBackground(); + username.drawTextBox(); + password.drawTextBox(); + combined.drawTextBox(); + mcfontRendererObj.drawCenteredString("Alt Login", width / 2, 20, + -1); + mcfontRendererObj.drawCenteredString(thread == null ? "§eWaiting..." : + thread.getStatus(), width / 2, 29, -1); + if (username.getText().isEmpty()) { + mcfontRendererObj.drawStringWithShadow("Username / E-Mail", width / 2 - 96, + 66.0F, -7829368); + } + if (password.getText().isEmpty()) { + mcfontRendererObj.drawStringWithShadow("Password", width / 2 - 96, 106.0F, + -7829368); + } + if (combined.getText().isEmpty()) { + mcfontRendererObj.drawStringWithShadow("Email:Password", width / 2 - 96, 146.0F, -7829368); + } + super.drawScreen(x, y, z); + } + + public void initGui() { + int var3 = height / 4 + 24; + buttonList.add(new GuiButton(0, width / 2 - 100, var3 + 72 + 12, "Login")); + buttonList.add(new GuiButton(1, width / 2 - 100, var3 + 72 + 12 + 24, "Back")); + username = new GuiTextField(1, mc.fontRendererObj, width / 2 - 100, 60, 200, 20); + password = new GuiPasswordField(mc.fontRendererObj, width / 2 - 100, 100, 200, 20); + combined = new GuiTextField(var3, mc.fontRendererObj, width / 2 - 100, 140, 200, 20); + username.setFocused(true); + username.setMaxStringLength(200); + password.func_146203_f(200); + combined.setMaxStringLength(200); + org.lwjgl.input.Keyboard.enableRepeatEvents(true); + } + + protected void keyTyped(char character, int key) + { + try + { + super.keyTyped(character, key); + } + catch (IOException e) + { + e.printStackTrace(); + } + if ((character == '\t') && ((username.isFocused()) || (combined.isFocused()) || (password.isFocused()))) + { + username.setFocused(!username.isFocused()); + password.setFocused(!password.isFocused()); + combined.setFocused(!combined.isFocused()); + } + if (character == '\r') { + actionPerformed((GuiButton)buttonList.get(0)); + } + username.textboxKeyTyped(character, key); + password.textboxKeyTyped(character, key); + combined.textboxKeyTyped(character, key); + } + + protected void mouseClicked(int x, int y, int button) { + try { + super.mouseClicked(x, y, button); + } catch (IOException e) { + e.printStackTrace(); + } + username.mouseClicked(x, y, button); + password.mouseClicked(x, y, button); + combined.mouseClicked(x, y, button); + } + + public void onGuiClosed() { + org.lwjgl.input.Keyboard.enableRepeatEvents(false); + } + + public void updateScreen() { + username.updateCursorCounter(); + password.updateCursorCounter(); + combined.updateCursorCounter(); + } +} diff --git a/src/minecraft/com/enjoytheban/ui/login/GuiAltManager.java b/src/minecraft/com/enjoytheban/ui/login/GuiAltManager.java new file mode 100644 index 0000000..09364af --- /dev/null +++ b/src/minecraft/com/enjoytheban/ui/login/GuiAltManager.java @@ -0,0 +1,323 @@ +package com.enjoytheban.ui.login; + +import com.enjoytheban.Client; +import com.enjoytheban.management.FileManager; +import com.enjoytheban.utils.Helper; +import com.enjoytheban.utils.render.RenderUtil; +import java.io.IOException; +import java.util.List; +import java.util.Random; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.util.Session; +import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; + +public class GuiAltManager extends GuiScreen +{ + private static Minecraft mc = ; + private GuiButton login; + private GuiButton remove; + private GuiButton rename; + private AltLoginThread loginThread; + private int offset; + public Alt selectedAlt = null; + private String status = "§eWaiting..."; + + + + public GuiAltManager() + { + FileManager.saveAlts(); + } + + public void actionPerformed(GuiButton button) + { + switch (id) + { + case 0: + if (loginThread == null) + { + mc.displayGuiScreen(null); + + + } + else if ((!loginThread.getStatus().equals("Logging in...")) && + (!loginThread.getStatus().equals("Do not hit back! Logging in..."))) + { + mc.displayGuiScreen(null); + } + else + { + loginThread.setStatus("Do not hit back! Logging in..."); + } + break; + case 1: + String user = selectedAlt.getUsername(); + String pass = selectedAlt.getPassword(); + loginThread = new AltLoginThread(user, pass); + loginThread.start(); + break; + case 2: + if (loginThread != null) { + loginThread = null; + } + Client.instance.getAltManager();AltManager.getAlts().remove(selectedAlt); + status = "§cRemoved."; + selectedAlt = null; + FileManager.saveAlts(); + break; + case 3: + mc.displayGuiScreen(new GuiAddAlt(this)); + break; + case 4: + mc.displayGuiScreen(new GuiAltLogin(this)); + break; + case 5: + Client.instance.getAltManager(); + Client.instance.getAltManager();Alt randomAlt = (Alt)AltManager.alts.get(new Random().nextInt(AltManager.alts.size())); + String user1 = randomAlt.getUsername(); + String pass1 = randomAlt.getPassword(); + loginThread = new AltLoginThread(user1, pass1); + loginThread.start(); + break; + case 6: + mc.displayGuiScreen(new GuiRenameAlt(this)); + break; + case 7: + Client.instance.getAltManager();Alt lastAlt = AltManager.lastAlt; + if (lastAlt == null) + { + if (loginThread == null) { + status = "?cThere is no last used alt!"; + } else { + loginThread.setStatus("?cThere is no last used alt!"); + } + } + else + { + String user2 = lastAlt.getUsername(); + String pass2 = lastAlt.getPassword(); + loginThread = new AltLoginThread(user2, pass2); + loginThread.start(); + } + break; + } + + } + + public void drawScreen(int par1, int par2, float par3) + { + drawDefaultBackground(); + if (Mouse.hasWheel()) + { + int wheel = Mouse.getDWheel(); + if (wheel < 0) + { + offset += 26; + if (offset < 0) { + offset = 0; + } + } + else if (wheel > 0) + { + offset -= 26; + if (offset < 0) { + offset = 0; + } + } + } + drawDefaultBackground(); + mcfontRendererObj.drawStringWithShadow(mcsession.getUsername(), 10.0F, 10.0F, + -7829368); + + Client.instance.getAltManager();mcfontRendererObj.drawCenteredString("Account Manager - " + AltManager.getAlts().size() + " alts", + width / 2, 10, -1); + mcfontRendererObj.drawCenteredString(loginThread == null ? status : + loginThread.getStatus(), width / 2, 20, -1); + + GL11.glPushMatrix(); + prepareScissorBox(0.0F, 33.0F, width, height - 50); + GL11.glEnable(3089); + int y = 38; + Client.instance.getAltManager(); for (Alt alt : AltManager.getAlts()) { + if (isAltInArea(y)) { + String name; + String name; + if (alt.getMask().equals("")) { + name = alt.getUsername(); + } else { + name = alt.getMask(); + } + String pass; + String pass; + if (alt.getPassword().equals("")) { + pass = "§cCracked"; + } else { + pass = alt.getPassword().replaceAll(".", "*"); + } + + if (alt == selectedAlt) + { + if ((isMouseOverAlt(par1, par2, y - offset)) && + (Mouse.isButtonDown(0))) { + RenderUtil.drawBorderedRect(52.0F, y - offset - 4, + width - 52, y - offset + 20, 1.0F, -16777216, + -2142943931); + } else if (isMouseOverAlt(par1, par2, y - offset)) { + RenderUtil.drawBorderedRect(52.0F, y - offset - 4, + width - 52, y - offset + 20, 1.0F, -16777216, + -2142088622); + } else { + RenderUtil.drawBorderedRect(52.0F, y - offset - 4, + width - 52, y - offset + 20, 1.0F, -16777216, + -2144259791); + } + } + else if ((isMouseOverAlt(par1, par2, y - offset)) && + (Mouse.isButtonDown(0))) { + RenderUtil.drawBorderedRect(52.0F, y - offset - 4, width - 52, y - + offset + 20, 1.0F, -16777216, -2146101995); + } else if (isMouseOverAlt(par1, par2, y - offset)) { + RenderUtil.drawBorderedRect(52.0F, y - offset - 4, width - 52, y - + offset + 20, 1.0F, -16777216, -2145180893); + } + mcfontRendererObj.drawCenteredString(name, width / 2, y - offset, + -1); + mcfontRendererObj.drawCenteredString(pass, width / 2, y - offset + + 10, 5592405); + y += 26; + } + } + GL11.glDisable(3089); + GL11.glPopMatrix(); + super.drawScreen(par1, par2, par3); + if (selectedAlt == null) + { + login.enabled = false; + remove.enabled = false; + rename.enabled = false; + } + else + { + login.enabled = true; + remove.enabled = true; + rename.enabled = true; + } + if (Keyboard.isKeyDown(200)) + { + offset -= 26; + if (offset < 0) { + offset = 0; + } + } + else if (Keyboard.isKeyDown(208)) + { + offset += 26; + if (offset < 0) { + offset = 0; + } + } + } + + public void initGui() + { + buttonList.add(new GuiButton(0, width / 2 + 4 + 76, + height - 24, 75, 20, "Cancel")); + buttonList.add(this.login = new GuiButton(1, width / 2 - 154, + height - 48, 70, 20, "Login")); + buttonList.add(this.remove = new GuiButton(2, width / 2 - 74, + height - 24, 70, 20, "Remove")); + buttonList.add(new GuiButton(3, width / 2 + 4 + 76, + height - 48, 75, 20, "Add")); + buttonList.add(new GuiButton(4, width / 2 - 74, + height - 48, 70, 20, "Direct Login")); + buttonList.add(new GuiButton(5, width / 2 + 4, + height - 48, 70, 20, "Random")); + buttonList.add(this.rename = new GuiButton(6, width / 2 + 4, + height - 24, 70, 20, "Edit")); + buttonList.add(this.rename = new GuiButton(7, width / 2 - 154, + height - 24, 70, 20, "Last Alt")); + + + login.enabled = false; + remove.enabled = false; + rename.enabled = false; + } + + private boolean isAltInArea(int y) + { + return y - offset <= height - 50; + } + + private boolean isMouseOverAlt(int x, int y, int y1) + { + return (x >= 52) && (y >= y1 - 4) && (x <= width - 52) && (y <= y1 + 20) && + (x >= 0) && (y >= 33) && (x <= width) && (y <= height - 50); + } + + protected void mouseClicked(int par1, int par2, int par3) + { + if (offset < 0) { + offset = 0; + } + int y = 38 - offset; + Client.instance.getAltManager(); for (Alt alt : AltManager.getAlts()) + { + if (isMouseOverAlt(par1, par2, y)) + { + if (alt == selectedAlt) + { + actionPerformed((GuiButton)buttonList.get(1)); + return; + } + selectedAlt = alt; + } + y += 26; + } + try + { + super.mouseClicked(par1, par2, par3); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + + public void prepareScissorBox(float x, float y, float x2, float y2) + { + int factor = new ScaledResolution(mc).getScaleFactor(); + GL11.glScissor((int)(x * factor), + (int)((new ScaledResolution(mc).getScaledHeight() - y2) * factor), (int)((x2 - x) * factor), + (int)((y2 - y) * factor)); + } + + public void renderBackground(int par1, int par2) + { + GL11.glDisable(2929); + GL11.glDepthMask(false); + OpenGlHelper.glBlendFunc(770, 771, 1, 0); + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + GL11.glDisable(3008); + drawDefaultBackground(); + Tessellator var3 = Tessellator.instance; + var3.getWorldRenderer().startDrawingQuads(); + var3.getWorldRenderer().addVertexWithUV(0.0D, par2, -90.0D, 0.0D, 1.0D); + var3.getWorldRenderer().addVertexWithUV(par1, par2, -90.0D, 1.0D, 1.0D); + var3.getWorldRenderer().addVertexWithUV(par1, 0.0D, -90.0D, 1.0D, 0.0D); + var3.getWorldRenderer().addVertexWithUV(0.0D, 0.0D, -90.0D, 0.0D, 0.0D); + var3.draw(); + GL11.glDepthMask(true); + GL11.glEnable(2929); + GL11.glEnable(3008); + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + } +} diff --git a/src/minecraft/com/enjoytheban/ui/login/GuiPasswordField.java b/src/minecraft/com/enjoytheban/ui/login/GuiPasswordField.java new file mode 100644 index 0000000..97d9160 --- /dev/null +++ b/src/minecraft/com/enjoytheban/ui/login/GuiPasswordField.java @@ -0,0 +1,571 @@ +package com.enjoytheban.ui.login; + +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.util.ChatAllowedCharacters; +import org.lwjgl.opengl.GL11; + +public final class GuiPasswordField + extends Gui +{ + private final int field_146209_f; + private final int field_146210_g; + private final FontRenderer field_146211_a; + private boolean field_146212_n = true; + private boolean field_146213_o; + private int field_146214_l; + private boolean field_146215_m = true; + private String field_146216_j = ""; + private int field_146217_k = 32; + private final int field_146218_h; + private final int field_146219_i; + private boolean field_146220_v = true; + private int field_146221_u = 7368816; + private int field_146222_t = 14737632; + private int field_146223_s; + private int field_146224_r; + private int field_146225_q; + private boolean field_146226_p = true; + + public GuiPasswordField(FontRenderer p_i1032_1_, int p_i1032_2_, int p_i1032_3_, int p_i1032_4_, int p_i1032_5_) + { + field_146211_a = p_i1032_1_; + field_146209_f = p_i1032_2_; + field_146210_g = p_i1032_3_; + field_146218_h = p_i1032_4_; + field_146219_i = p_i1032_5_; + } + + public void drawTextBox() + { + if (func_146176_q()) + { + if (func_146181_i()) + { + drawRect(field_146209_f - 1, field_146210_g - 1, field_146209_f + + field_146218_h + 1, field_146210_g + field_146219_i + + 1, -6250336); + drawRect(field_146209_f, field_146210_g, field_146209_f + + field_146218_h, field_146210_g + field_146219_i, + -16777216); + } + int var1 = field_146226_p ? field_146222_t : field_146221_u; + int var2 = field_146224_r - field_146225_q; + int var3 = field_146223_s - field_146225_q; + String var4 = field_146211_a.trimStringToWidth( + field_146216_j.substring(field_146225_q), func_146200_o()); + boolean var5 = (var2 >= 0) && (var2 <= var4.length()); + boolean var6 = (field_146213_o) && (field_146214_l / 6 % 2 == 0) && + (var5); + int var7 = field_146215_m ? field_146209_f + 4 : + field_146209_f; + int var8 = field_146215_m ? field_146210_g + + (field_146219_i - 8) / 2 : field_146210_g; + int var9 = var7; + if (var3 > var4.length()) { + var3 = var4.length(); + } + if (var4.length() > 0) + { + String var10 = var5 ? var4.substring(0, var2) : var4; + var9 = field_146211_a.drawString( + var10.replaceAll(".", "*"), var7, var8, var1); + } + boolean var13 = (field_146224_r < field_146216_j.length()) || ( + field_146216_j.length() >= func_146208_g()); + int var11 = var9; + if (!var5) + { + var11 = var2 > 0 ? var7 + field_146218_h : var7; + } + else if (var13) + { + var11 = var9 - 1; + var9--; + } + if ((var4.length() > 0) && (var5) && (var2 < var4.length())) { + field_146211_a.drawString(var4.substring(var2) + .replaceAll(".", "*"), var9, var8, var1); + } + if (var6) { + if (var13) { + Gui.drawRect(var11, var8 - 1, var11 + 1, var8 + 1 + + field_146211_a.FONT_HEIGHT, -3092272); + } else { + field_146211_a.drawString("_", var11, var8, var1); + } + } + if (var3 != var2) + { + int var12 = var7 + + field_146211_a.getStringWidth(var4.substring(0, var3) + .replaceAll(".", "*")); + func_146188_c(var11, var8 - 1, var12 - 1, var8 + 1 + + field_146211_a.FONT_HEIGHT); + } + } + } + + public void func_146175_b(int p_146175_1_) + { + if (field_146216_j.length() != 0) { + if (field_146223_s != field_146224_r) + { + func_146191_b(""); + } + else + { + boolean var2 = p_146175_1_ < 0; + int var3 = var2 ? field_146224_r + p_146175_1_ : + field_146224_r; + int var4 = var2 ? field_146224_r : field_146224_r + + p_146175_1_; + String var5 = ""; + if (var3 >= 0) { + var5 = field_146216_j.substring(0, var3); + } + if (var4 < field_146216_j.length()) { + var5 = var5 + field_146216_j.substring(var4); + } + field_146216_j = var5; + if (var2) { + func_146182_d(p_146175_1_); + } + } + } + } + + public boolean func_146176_q() + { + return field_146220_v; + } + + public void func_146177_a(int p_146177_1_) + { + if (field_146216_j.length() != 0) { + if (field_146223_s != field_146224_r) { + func_146191_b(""); + } else { + func_146175_b(func_146187_c(p_146177_1_) - field_146224_r); + } + } + } + + public boolean func_146181_i() + { + return field_146215_m; + } + + public void func_146182_d(int p_146182_1_) + { + func_146190_e(field_146223_s + p_146182_1_); + } + + public int func_146183_a(int p_146183_1_, int p_146183_2_) + { + return func_146197_a(p_146183_1_, func_146198_h(), true); + } + + public void func_146184_c(boolean p_146184_1_) + { + field_146226_p = p_146184_1_; + } + + public void func_146185_a(boolean p_146185_1_) + { + field_146215_m = p_146185_1_; + } + + public int func_146186_n() + { + return field_146223_s; + } + + public int func_146187_c(int p_146187_1_) + { + return func_146183_a(p_146187_1_, func_146198_h()); + } + + private void func_146188_c(int p_146188_1_, int p_146188_2_, int p_146188_3_, int p_146188_4_) + { + if (p_146188_1_ < p_146188_3_) + { + int var5 = p_146188_1_; + p_146188_1_ = p_146188_3_; + p_146188_3_ = var5; + } + if (p_146188_2_ < p_146188_4_) + { + int var5 = p_146188_2_; + p_146188_2_ = p_146188_4_; + p_146188_4_ = var5; + } + if (p_146188_3_ > field_146209_f + field_146218_h) { + p_146188_3_ = field_146209_f + field_146218_h; + } + if (p_146188_1_ > field_146209_f + field_146218_h) { + p_146188_1_ = field_146209_f + field_146218_h; + } + WorldRenderer var2 = Tessellator.instance.getWorldRenderer(); + GL11.glColor4f(0.0F, 0.0F, 255.0F, 255.0F); + GL11.glDisable(3553); + GL11.glEnable(3058); + GL11.glLogicOp(5387); + var2.startDrawingQuads(); + var2.addVertex(p_146188_1_, p_146188_4_, 0.0D); + var2.addVertex(p_146188_3_, p_146188_4_, 0.0D); + var2.addVertex(p_146188_3_, p_146188_2_, 0.0D); + var2.addVertex(p_146188_1_, p_146188_2_, 0.0D); + var2.draw(); + GL11.glDisable(3058); + GL11.glEnable(3553); + } + + public void func_146189_e(boolean p_146189_1_) + { + field_146220_v = p_146189_1_; + } + + public void func_146190_e(int p_146190_1_) + { + field_146224_r = p_146190_1_; + int var2 = field_146216_j.length(); + if (field_146224_r < 0) { + field_146224_r = 0; + } + if (field_146224_r > var2) { + field_146224_r = var2; + } + func_146199_i(field_146224_r); + } + + public void func_146191_b(String p_146191_1_) + { + String var2 = ""; + String var3 = + ChatAllowedCharacters.filterAllowedCharacters(p_146191_1_); + int var4 = field_146224_r < field_146223_s ? field_146224_r : + field_146223_s; + int var5 = field_146224_r < field_146223_s ? field_146223_s : + field_146224_r; + int var6 = field_146217_k - field_146216_j.length() - ( + var4 - field_146223_s); + if (field_146216_j.length() > 0) + var2 = var2 + field_146216_j.substring(0, var4); + int var8; + int var8; + if (var6 < var3.length()) + { + var2 = var2 + var3.substring(0, var6); + var8 = var6; + } + else + { + var2 = var2 + var3; + var8 = var3.length(); + } + if ((field_146216_j.length() > 0) && (var5 < field_146216_j.length())) { + var2 = var2 + field_146216_j.substring(var5); + } + field_146216_j = var2; + func_146182_d(var4 - field_146223_s + var8); + } + + public void func_146193_g(int p_146193_1_) + { + field_146222_t = p_146193_1_; + } + + public void func_146196_d() + { + func_146190_e(0); + } + + public int func_146197_a(int p_146197_1_, int p_146197_2_, boolean p_146197_3_) + { + int var4 = p_146197_2_; + boolean var5 = p_146197_1_ < 0; + int var6 = Math.abs(p_146197_1_); + for (int var7 = 0; var7 < var6; var7++) { + if (var5) + { + do + { + var4--; + } while ((!p_146197_3_) || (var4 <= 0) || + (field_146216_j.charAt(var4 - 1) == ' ')); + + + + + do + { + var4--; + if (var4 <= 0) { + break; + } + } while (field_146216_j.charAt(var4 - 1) != ' '); + } + else + { + int var8 = field_146216_j.length(); + var4 = field_146216_j.indexOf(' ', var4); + if (var4 == -1) { + var4 = var8; + } else { + while ((p_146197_3_) && (var4 < var8) && + (field_146216_j.charAt(var4) == ' ')) { + var4++; + } + } + } + } + return var4; + } + + public int func_146198_h() + { + return field_146224_r; + } + + public void func_146199_i(int p_146199_1_) + { + int var2 = field_146216_j.length(); + if (p_146199_1_ > var2) { + p_146199_1_ = var2; + } + if (p_146199_1_ < 0) { + p_146199_1_ = 0; + } + field_146223_s = p_146199_1_; + if (field_146211_a != null) + { + if (field_146225_q > var2) { + field_146225_q = var2; + } + int var3 = func_146200_o(); + String var4 = field_146211_a.trimStringToWidth( + field_146216_j.substring(field_146225_q), var3); + int var5 = var4.length() + field_146225_q; + if (p_146199_1_ == field_146225_q) { + field_146225_q -= field_146211_a.trimStringToWidth(field_146216_j, var3, true).length(); + } + if (p_146199_1_ > var5) { + field_146225_q += p_146199_1_ - var5; + } else if (p_146199_1_ <= field_146225_q) { + field_146225_q -= field_146225_q - p_146199_1_; + } + if (field_146225_q < 0) { + field_146225_q = 0; + } + if (field_146225_q > var2) { + field_146225_q = var2; + } + } + } + + public int func_146200_o() + { + return func_146181_i() ? field_146218_h - 8 : field_146218_h; + } + + public void func_146202_e() + { + func_146190_e(field_146216_j.length()); + } + + public void func_146203_f(int p_146203_1_) + { + field_146217_k = p_146203_1_; + if (field_146216_j.length() > p_146203_1_) { + field_146216_j = field_146216_j.substring(0, p_146203_1_); + } + } + + public void func_146204_h(int p_146204_1_) + { + field_146221_u = p_146204_1_; + } + + public void func_146205_d(boolean p_146205_1_) + { + field_146212_n = p_146205_1_; + } + + public String func_146207_c() + { + int var1 = field_146224_r < field_146223_s ? field_146224_r : + field_146223_s; + int var2 = field_146224_r < field_146223_s ? field_146223_s : + field_146224_r; + return field_146216_j.substring(var1, var2); + } + + public int func_146208_g() + { + return field_146217_k; + } + + public String getText() + { + return field_146216_j; + } + + public boolean isFocused() + { + return field_146213_o; + } + + public void mouseClicked(int p_146192_1_, int p_146192_2_, int p_146192_3_) + { + boolean var4 = (p_146192_1_ >= field_146209_f) && + (p_146192_1_ < field_146209_f + field_146218_h) && + (p_146192_2_ >= field_146210_g) && ( + p_146192_2_ < field_146210_g + field_146219_i); + if (field_146212_n) { + setFocused(var4); + } + if ((field_146213_o) && (p_146192_3_ == 0)) + { + int var5 = p_146192_1_ - field_146209_f; + if (field_146215_m) { + var5 -= 4; + } + String var6 = field_146211_a.trimStringToWidth( + field_146216_j.substring(field_146225_q), func_146200_o()); + func_146190_e(field_146211_a.trimStringToWidth(var6, var5).length() + + field_146225_q); + } + } + + public void setFocused(boolean p_146195_1_) + { + if ((p_146195_1_) && (!field_146213_o)) { + field_146214_l = 0; + } + field_146213_o = p_146195_1_; + } + + public void setText(String p_146180_1_) + { + if (p_146180_1_.length() > field_146217_k) { + field_146216_j = p_146180_1_.substring(0, field_146217_k); + } else { + field_146216_j = p_146180_1_; + } + func_146202_e(); + } + + public boolean textboxKeyTyped(char p_146201_1_, int p_146201_2_) + { + if (!field_146213_o) { + return false; + } + switch (p_146201_1_) + { + case '\001': + func_146202_e(); + func_146199_i(0); + return true; + case '\003': + GuiScreen.setClipboardString(func_146207_c()); + return true; + case '\026': + if (field_146226_p) { + func_146191_b(GuiScreen.getClipboardString()); + } + return true; + case '\030': + GuiScreen.setClipboardString(func_146207_c()); + if (field_146226_p) { + func_146191_b(""); + } + return true; + } + switch (p_146201_2_) + { + case 14: + if (GuiScreen.isCtrlKeyDown()) + { + if (field_146226_p) { + func_146177_a(-1); + } + } + else if (field_146226_p) { + func_146175_b(-1); + } + return true; + case 199: + if (GuiScreen.isShiftKeyDown()) { + func_146199_i(0); + } else { + func_146196_d(); + } + return true; + case 203: + if (GuiScreen.isShiftKeyDown()) + { + if (GuiScreen.isCtrlKeyDown()) { + func_146199_i(func_146183_a(-1, func_146186_n())); + } else { + func_146199_i(func_146186_n() - 1); + } + } + else if (GuiScreen.isCtrlKeyDown()) { + func_146190_e(func_146187_c(-1)); + } else { + func_146182_d(-1); + } + return true; + case 205: + if (GuiScreen.isShiftKeyDown()) + { + if (GuiScreen.isCtrlKeyDown()) { + func_146199_i(func_146183_a(1, func_146186_n())); + } else { + func_146199_i(func_146186_n() + 1); + } + } + else if (GuiScreen.isCtrlKeyDown()) { + func_146190_e(func_146187_c(1)); + } else { + func_146182_d(1); + } + return true; + case 207: + if (GuiScreen.isShiftKeyDown()) { + func_146199_i(field_146216_j.length()); + } else { + func_146202_e(); + } + return true; + case 211: + if (GuiScreen.isCtrlKeyDown()) + { + if (field_146226_p) { + func_146177_a(1); + } + } + else if (field_146226_p) { + func_146175_b(1); + } + return true; + } + if (ChatAllowedCharacters.isAllowedCharacter(p_146201_1_)) + { + if (field_146226_p) { + func_146191_b(Character.toString(p_146201_1_)); + } + return true; + } + return false; + } + + public void updateCursorCounter() + { + field_146214_l += 1; + } +} diff --git a/src/minecraft/com/enjoytheban/ui/login/GuiRenameAlt.java b/src/minecraft/com/enjoytheban/ui/login/GuiRenameAlt.java new file mode 100644 index 0000000..72f6e00 --- /dev/null +++ b/src/minecraft/com/enjoytheban/ui/login/GuiRenameAlt.java @@ -0,0 +1,88 @@ +package com.enjoytheban.ui.login; + +import com.enjoytheban.utils.Helper; +import java.io.IOException; +import java.util.List; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.GuiTextField; + +public class GuiRenameAlt + extends GuiScreen +{ + private final GuiAltManager manager; + private GuiTextField nameField; + private String status = "§eWaiting..."; + private GuiPasswordField pwField; + + public GuiRenameAlt(GuiAltManager manager) { + this.manager = manager; + } + + public void actionPerformed(GuiButton button) + { + switch (id) + { + case 1: + mc.displayGuiScreen(manager); + break; + case 0: + manager.selectedAlt.setMask(nameField.getText()); + if (!pwField.getText().isEmpty()) + manager.selectedAlt.setPassword(pwField.getText()); + status = "§aEdited!"; + } + } + + public void drawScreen(int par1, int par2, float par3) + { + drawDefaultBackground(); + mcfontRendererObj.drawCenteredString("Edit Alt", width / 2, 10, -1); + mcfontRendererObj.drawCenteredString(status, width / 2, 20, -1); + nameField.drawTextBox(); + pwField.drawTextBox(); + if (nameField.getText().isEmpty()) + mcfontRendererObj.drawStringWithShadow("New E-Mail", width / 2 - 96, 66.0F, -7829368); + if (pwField.getText().isEmpty()) + mcfontRendererObj.drawStringWithShadow("New Password", width / 2 - 96, 106.0F, -7829368); + super.drawScreen(par1, par2, par3); + } + + public void initGui() + { + buttonList.add(new GuiButton(0, width / 2 - 100, height / 4 + 92 + 12, "Edit")); + buttonList.add(new GuiButton(1, width / 2 - 100, height / 4 + 116 + 12, "Cancel")); + nameField = new GuiTextField(eventButton, mc.fontRendererObj, width / 2 - 100, 60, 200, 20); + pwField = new GuiPasswordField(mc.fontRendererObj, width / 2 - 100, 100, 200, 20); + } + + protected void keyTyped(char par1, int par2) + { + nameField.textboxKeyTyped(par1, par2); + pwField.textboxKeyTyped(par1, par2); + if ((par1 == '\t') && ((nameField.isFocused()) || (pwField.isFocused()))) + { + nameField.setFocused(!nameField.isFocused()); + pwField.setFocused(!pwField.isFocused()); + } + if (par1 == '\r') { + actionPerformed((GuiButton)buttonList.get(0)); + } + } + + protected void mouseClicked(int par1, int par2, int par3) + { + try + { + super.mouseClicked(par1, par2, par3); + } + catch (IOException e) + { + e.printStackTrace(); + } + nameField.mouseClicked(par1, par2, par3); + pwField.mouseClicked(par1, par2, par3); + } +} diff --git a/src/minecraft/com/enjoytheban/utils/BlockUtil.java b/src/minecraft/com/enjoytheban/utils/BlockUtil.java new file mode 100644 index 0000000..59c57f8 --- /dev/null +++ b/src/minecraft/com/enjoytheban/utils/BlockUtil.java @@ -0,0 +1,6 @@ +package com.enjoytheban.utils; + +public class BlockUtil +{ + public BlockUtil() {} +} diff --git a/src/minecraft/com/enjoytheban/utils/ChatUtils.java b/src/minecraft/com/enjoytheban/utils/ChatUtils.java new file mode 100644 index 0000000..02d3ac8 --- /dev/null +++ b/src/minecraft/com/enjoytheban/utils/ChatUtils.java @@ -0,0 +1,104 @@ +package com.enjoytheban.utils; + +import com.enjoytheban.Client; +import net.minecraft.client.Minecraft; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.ChatStyle; +import net.minecraft.util.EnumChatFormatting; + +public class ChatUtils +{ + private final ChatComponentText message; + + private ChatUtils(ChatComponentText message) + { + this.message = message; + } + + public static String addFormat(String message, String regex) { + return message.replaceAll("(?i)" + regex + "([0-9a-fklmnor])", "§$1"); + } + + public void displayClientSided() { + getMinecraftthePlayer.addChatMessage(message); + } + + private ChatComponentText getChatComponent() { + return message; + } + + + + + + + + + public static class ChatMessageBuilder + { + private static final EnumChatFormatting defaultMessageColor = EnumChatFormatting.WHITE; + private ChatComponentText theMessage; + private boolean useDefaultMessageColor; + + public ChatMessageBuilder(boolean prependDefaultPrefix, boolean useDefaultMessageColor) { theMessage = new ChatComponentText(""); + this.useDefaultMessageColor = false; + workingStyle = new ChatStyle(); + workerMessage = new ChatComponentText(""); + if (prependDefaultPrefix) { + Client.instance.getClass();theMessage.appendSibling(new ChatMessageBuilder(false, false).appendText(String.valueOf(EnumChatFormatting.AQUA + "ETB" + " ")).setColor(EnumChatFormatting.RED).build().getChatComponent()); + } + this.useDefaultMessageColor = useDefaultMessageColor; } + + private ChatStyle workingStyle; + private ChatComponentText workerMessage; + public ChatMessageBuilder() { theMessage = new ChatComponentText(""); + useDefaultMessageColor = false; + workingStyle = new ChatStyle(); + workerMessage = new ChatComponentText(""); + } + + public ChatMessageBuilder appendText(String text) { + appendSibling(); + workerMessage = new ChatComponentText(text); + workingStyle = new ChatStyle(); + if (useDefaultMessageColor) { + setColor(defaultMessageColor); + } + return this; + } + + public ChatMessageBuilder setColor(EnumChatFormatting color) { + workingStyle.setColor(color); + return this; + } + + public ChatMessageBuilder bold() { + workingStyle.setBold(Boolean.valueOf(true)); + return this; + } + + public ChatMessageBuilder italic() { + workingStyle.setItalic(Boolean.valueOf(true)); + return this; + } + + public ChatMessageBuilder strikethrough() { + workingStyle.setStrikethrough(Boolean.valueOf(true)); + return this; + } + + public ChatMessageBuilder underline() { + workingStyle.setUnderlined(Boolean.valueOf(true)); + return this; + } + + public ChatUtils build() { + appendSibling(); + return new ChatUtils(theMessage, null); + } + + private void appendSibling() { + theMessage.appendSibling(workerMessage.setChatStyle(workingStyle)); + } + } +} diff --git a/src/minecraft/com/enjoytheban/utils/Helper.java b/src/minecraft/com/enjoytheban/utils/Helper.java new file mode 100644 index 0000000..1d92190 --- /dev/null +++ b/src/minecraft/com/enjoytheban/utils/Helper.java @@ -0,0 +1,34 @@ +package com.enjoytheban.utils; + +import com.enjoytheban.Client; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.multiplayer.ServerData; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumChatFormatting; + +public class Helper +{ + public static Minecraft mc = ; + + public Helper() {} + + public static void sendMessageOLD(String msg) { Object[] tmp16_13 = new Object[2]; + Client.instance.getClass();tmp16_13[0] = (EnumChatFormatting.BLUE + "ETB" + EnumChatFormatting.GRAY + ": "); Object[] tmp58_16 = tmp16_13;tmp58_16[1] = msg;mcthePlayer.addChatMessage(new ChatComponentText(String.format("%s%s", tmp58_16))); + } + + public static void sendMessage(String message) + { + new ChatUtils.ChatMessageBuilder(true, true).appendText(message).setColor(EnumChatFormatting.GRAY).build().displayClientSided(); + } + + public static void sendMessageWithoutPrefix(String message) + { + new ChatUtils.ChatMessageBuilder(false, true).appendText(message).setColor(EnumChatFormatting.GRAY).build().displayClientSided(); + } + + public static boolean onServer(String server) + { + return (!mc.isSingleplayer()) && (mcgetCurrentServerDataserverIP.toLowerCase().contains(server)); + } +} diff --git a/src/minecraft/com/enjoytheban/utils/InventoryUtils.java b/src/minecraft/com/enjoytheban/utils/InventoryUtils.java new file mode 100644 index 0000000..e9c2784 --- /dev/null +++ b/src/minecraft/com/enjoytheban/utils/InventoryUtils.java @@ -0,0 +1,525 @@ +package com.enjoytheban.utils; + +import com.google.common.collect.Multimap; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Map.Entry; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemArmor; +import net.minecraft.item.ItemArmor.ArmorMaterial; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ItemSword; +import net.minecraft.util.DamageSource; + +public class InventoryUtils +{ + public InventoryUtils() {} + + public static Minecraft mc = ; + + public void dropSlot(int slot) { + int windowId = net.minecraft.client.gui.inventory.GuiInventorymcthePlayer).inventorySlots.windowId; + mcplayerController.windowClick(windowId, slot, 1, 4, mcthePlayer); + } + + public static void updateInventory() { + for (int index = 0; index < 44; index++) { + try { + int offset = index < 9 ? 36 : 0; + + getMinecraftthePlayer.sendQueue.addToSendQueue(new net.minecraft.network.play.client.C10PacketCreativeInventoryAction(index + offset, getMinecraftthePlayer.inventory.mainInventory[index])); + } + catch (Exception localException) {} + } + } + + public static ItemStack getStackInSlot(int slot) { + return mcthePlayer.inventory.getStackInSlot(slot); + } + + public static boolean isBestArmorOfTypeInInv(ItemStack is) { + try { + if (is == null) { + return false; + } + + if (is.getItem() == null) { + return false; + } + + if ((is.getItem() != null) && (!(is.getItem() instanceof ItemArmor))) { + return false; + } + + ItemArmor ia = (ItemArmor)is.getItem(); + int prot = getArmorProt(is); + + + + + + for (int i = 0; i < 4; i++) { + ItemStack stack = mcthePlayer.inventory.armorInventory[i]; + if (stack != null) { + ItemArmor otherArmor = (ItemArmor)stack.getItem(); + if (armorType == armorType) { + int otherProt = getArmorProt(stack); + if (otherProt >= prot) { + return false; + } + } + } + } + + for (i = 0; i < mcthePlayer.inventory.getSizeInventory() - 4; i++) { + ItemStack stack = mcthePlayer.inventory.getStackInSlot(i); + if ((stack != null) && ((stack.getItem() instanceof ItemArmor))) { + ItemArmor otherArmor = (ItemArmor)stack.getItem(); + if ((armorType == armorType) && (otherArmor != ia)) { + int otherProt = getArmorProt(stack); + if (otherProt >= prot) { + return false; + } + } + } + } + } + catch (Exception localException) {} + + + return true; + } + + public static boolean hotbarHas(Item item) { + for (int index = 0; index <= 36; index++) { + ItemStack stack = getMinecraftthePlayer.inventory.getStackInSlot(index); + if ((stack != null) && (stack.getItem() == item)) { + return true; + } + } + return false; + } + + public static boolean hotbarHas(Item item, int slotID) { + for (int index = 0; index <= 36; index++) { + ItemStack stack = getMinecraftthePlayer.inventory.getStackInSlot(index); + if ((stack != null) && (stack.getItem() == item) && (getSlotID(stack.getItem()) == slotID)) { + return true; + } + } + return false; + } + + public static int getSlotID(Item item) { + for (int index = 0; index <= 36; index++) { + ItemStack stack = getMinecraftthePlayer.inventory.getStackInSlot(index); + if ((stack != null) && (stack.getItem() == item)) { + return index; + } + } + return -1; + } + + public static ItemStack getItemBySlotID(int slotID) { + for (int index = 0; index <= 36; index++) { + ItemStack stack = getMinecraftthePlayer.inventory.getStackInSlot(index); + if ((stack != null) && (getSlotID(stack.getItem()) == slotID)) { + return stack; + } + } + return null; + } + + public static int getArmorProt(ItemStack i) { + int armorprot = -1; + if ((i != null) && (i.getItem() != null) && ((i.getItem() instanceof ItemArmor))) { + armorprot = ((ItemArmor)i.getItem()).getArmorMaterial().getDamageReductionAmount(getItemType(i)) + EnchantmentHelper.getEnchantmentModifierDamage(new ItemStack[] { i }, DamageSource.generic); + } + + return armorprot; + } + + public static int getBestSwordSlotID(ItemStack item, double damage) { + for (int index = 0; index <= 36; index++) { + ItemStack stack = getMinecraftthePlayer.inventory.getStackInSlot(index); + if ((stack != null) && (stack == item) && (getSwordDamage(stack) == getSwordDamage(item))) { + return index; + } + } + return -1; + } + + private static double getSwordDamage(ItemStack itemStack) { + double damage = 0.0D; + + java.util.Optional attributeModifier = itemStack.getAttributeModifiers().values().stream().findFirst(); + + if (attributeModifier.isPresent()) { + damage = ((AttributeModifier)attributeModifier.get()).getAmount(); + } + + damage += EnchantmentHelper.func_152377_a(itemStack, net.minecraft.entity.EnumCreatureAttribute.UNDEFINED); + + return damage; + } + + + public boolean isBestChest(int slot) + { + if ((getStackInSlot(slot) != null) && (getStackInSlot(slot).getItem() != null) && + ((getStackInSlot(slot).getItem() instanceof ItemArmor))) { + int slotProtection = ((ItemArmor)mcthePlayer.inventory.getStackInSlot(slot).getItem()).getArmorMaterial() + .getDamageReductionAmount(getItemType(mcthePlayer.inventory.getStackInSlot(slot))) + + EnchantmentHelper.getEnchantmentModifierDamage( + new ItemStack[] { mcthePlayer.inventory.getStackInSlot(slot) }, DamageSource.generic); + + if (mcthePlayer.inventory.armorInventory[2] != null) { + ItemArmor ia = (ItemArmor)mcthePlayer.inventory.armorInventory[2].getItem(); + ItemStack is = mcthePlayer.inventory.armorInventory[2]; + + ItemArmor ia1 = (ItemArmor)getStackInSlot(slot).getItem(); + + int otherProtection = ((ItemArmor)is.getItem()).getArmorMaterial() + .getDamageReductionAmount(getItemType(is)) + + EnchantmentHelper.getEnchantmentModifierDamage(new ItemStack[] { is }, DamageSource.generic); + if ((otherProtection > slotProtection) || (otherProtection == slotProtection)) { + return false; + } + } + + + for (int i = 0; i < mcthePlayer.inventory.getSizeInventory(); i++) { + if (getStackInSlot(i) != null) + { + + if ((mcthePlayer.inventory.getStackInSlot(i).getItem() instanceof ItemArmor)) { + int otherProtection = ((ItemArmor)mcthePlayer.inventory.getStackInSlot(i).getItem()) + .getArmorMaterial() + .getDamageReductionAmount(getItemType(mcthePlayer.inventory.getStackInSlot(i))) + + EnchantmentHelper.getEnchantmentModifierDamage( + new ItemStack[] { mcthePlayer.inventory.getStackInSlot(i) }, DamageSource.generic); + + ItemArmor ia1 = (ItemArmor)getStackInSlot(slot).getItem(); + + ItemArmor ia2 = (ItemArmor)getStackInSlot(i).getItem(); + + if ((armorType == 1) && (armorType == 1) && + (otherProtection > slotProtection)) { + return false; + } + } + } + } + } + + + return true; + } + + public boolean isBestHelmet(int slot) { + if ((getStackInSlot(slot) != null) && (getStackInSlot(slot).getItem() != null) && + ((getStackInSlot(slot).getItem() instanceof ItemArmor))) { + int slotProtection = ((ItemArmor)mcthePlayer.inventory.getStackInSlot(slot).getItem()).getArmorMaterial() + .getDamageReductionAmount(getItemType(mcthePlayer.inventory.getStackInSlot(slot))) + + EnchantmentHelper.getEnchantmentModifierDamage( + new ItemStack[] { mcthePlayer.inventory.getStackInSlot(slot) }, DamageSource.generic); + + if (mcthePlayer.inventory.armorInventory[3] != null) { + ItemArmor ia = (ItemArmor)mcthePlayer.inventory.armorInventory[3].getItem(); + ItemStack is = mcthePlayer.inventory.armorInventory[3]; + + ItemArmor ia1 = (ItemArmor)getStackInSlot(slot).getItem(); + + int otherProtection = ((ItemArmor)is.getItem()).getArmorMaterial() + .getDamageReductionAmount(getItemType(is)) + + EnchantmentHelper.getEnchantmentModifierDamage(new ItemStack[] { is }, DamageSource.generic); + if ((otherProtection > slotProtection) || (otherProtection == slotProtection)) { + return false; + } + } + + + for (int i = 0; i < mcthePlayer.inventory.getSizeInventory(); i++) { + if (getStackInSlot(i) != null) + { + + if ((mcthePlayer.inventory.getStackInSlot(i).getItem() instanceof ItemArmor)) { + int otherProtection = ((ItemArmor)mcthePlayer.inventory.getStackInSlot(i).getItem()) + .getArmorMaterial() + .getDamageReductionAmount(getItemType(mcthePlayer.inventory.getStackInSlot(i))) + + EnchantmentHelper.getEnchantmentModifierDamage( + new ItemStack[] { mcthePlayer.inventory.getStackInSlot(i) }, DamageSource.generic); + + ItemArmor ia1 = (ItemArmor)getStackInSlot(slot).getItem(); + + ItemArmor ia2 = (ItemArmor)getStackInSlot(i).getItem(); + + if ((armorType == 0) && (armorType == 0) && + (otherProtection > slotProtection)) { + return false; + } + } + } + } + } + + + + return true; + } + + public boolean isBestLeggings(int slot) + { + if ((getStackInSlot(slot) != null) && (getStackInSlot(slot).getItem() != null) && + ((getStackInSlot(slot).getItem() instanceof ItemArmor))) { + int slotProtection = ((ItemArmor)mcthePlayer.inventory.getStackInSlot(slot).getItem()).getArmorMaterial() + .getDamageReductionAmount(getItemType(mcthePlayer.inventory.getStackInSlot(slot))) + + EnchantmentHelper.getEnchantmentModifierDamage( + new ItemStack[] { mcthePlayer.inventory.getStackInSlot(slot) }, DamageSource.generic); + if (mcthePlayer.inventory.armorInventory[1] != null) { + ItemArmor ia = (ItemArmor)mcthePlayer.inventory.armorInventory[1].getItem(); + ItemStack is = mcthePlayer.inventory.armorInventory[1]; + + ItemArmor ia1 = (ItemArmor)getStackInSlot(slot).getItem(); + + int otherProtection = ((ItemArmor)is.getItem()).getArmorMaterial() + .getDamageReductionAmount(getItemType(is)) + + EnchantmentHelper.getEnchantmentModifierDamage(new ItemStack[] { is }, DamageSource.generic); + if ((otherProtection > slotProtection) || (otherProtection == slotProtection)) { + return false; + } + } + + + for (int i = 0; i < mcthePlayer.inventory.getSizeInventory(); i++) { + if (getStackInSlot(i) != null) + { + + if ((mcthePlayer.inventory.getStackInSlot(i).getItem() instanceof ItemArmor)) { + int otherProtection = ((ItemArmor)mcthePlayer.inventory.getStackInSlot(i).getItem()) + .getArmorMaterial() + .getDamageReductionAmount(getItemType(mcthePlayer.inventory.getStackInSlot(i))) + + EnchantmentHelper.getEnchantmentModifierDamage( + new ItemStack[] { mcthePlayer.inventory.getStackInSlot(i) }, DamageSource.generic); + ItemArmor ia1 = (ItemArmor)getStackInSlot(slot).getItem(); + + ItemArmor ia2 = (ItemArmor)getStackInSlot(i).getItem(); + + if ((armorType == 2) && (armorType == 2) && + (otherProtection > slotProtection)) { + return false; + } + } + } + } + } + + + return true; + } + + public boolean isBestBoots(int slot) + { + if ((getStackInSlot(slot) != null) && (getStackInSlot(slot).getItem() != null) && + ((getStackInSlot(slot).getItem() instanceof ItemArmor))) { + int slotProtection = ((ItemArmor)mcthePlayer.inventory.getStackInSlot(slot).getItem()).getArmorMaterial() + .getDamageReductionAmount(getItemType(mcthePlayer.inventory.getStackInSlot(slot))) + + EnchantmentHelper.getEnchantmentModifierDamage( + new ItemStack[] { mcthePlayer.inventory.getStackInSlot(slot) }, DamageSource.generic); + + if (mcthePlayer.inventory.armorInventory[0] != null) { + ItemArmor ia = (ItemArmor)mcthePlayer.inventory.armorInventory[0].getItem(); + ItemStack is = mcthePlayer.inventory.armorInventory[0]; + + ItemArmor ia1 = (ItemArmor)getStackInSlot(slot).getItem(); + + int otherProtection = ((ItemArmor)is.getItem()).getArmorMaterial() + .getDamageReductionAmount(getItemType(is)) + + EnchantmentHelper.getEnchantmentModifierDamage(new ItemStack[] { is }, DamageSource.generic); + if ((otherProtection > slotProtection) || (otherProtection == slotProtection)) { + return false; + } + } + + + for (int i = 0; i < mcthePlayer.inventory.getSizeInventory(); i++) { + if (getStackInSlot(i) != null) + { + + if ((mcthePlayer.inventory.getStackInSlot(i).getItem() instanceof ItemArmor)) { + int otherProtection = ((ItemArmor)mcthePlayer.inventory.getStackInSlot(i).getItem()) + .getArmorMaterial() + .getDamageReductionAmount(getItemType(mcthePlayer.inventory.getStackInSlot(i))) + + EnchantmentHelper.getEnchantmentModifierDamage( + new ItemStack[] { mcthePlayer.inventory.getStackInSlot(i) }, DamageSource.generic); + + ItemArmor ia1 = (ItemArmor)getStackInSlot(slot).getItem(); + + ItemArmor ia2 = (ItemArmor)getStackInSlot(i).getItem(); + + if ((armorType == 3) && (armorType == 3) && + (otherProtection > slotProtection)) { + return false; + } + } + } + } + } + + + return true; + } + + public boolean isBestSword(int slotIn) { + return getBestWeapon() == slotIn; + } + + public static int getItemType(ItemStack itemStack) { + if ((itemStack.getItem() instanceof ItemArmor)) { + ItemArmor armor = (ItemArmor)itemStack.getItem(); + + return armorType; + } + return -1; + } + + public static float getItemDamage(ItemStack itemStack) { + Multimap multimap = itemStack.getAttributeModifiers(); + Iterator iterator; + if ((!multimap.isEmpty()) && ((iterator = multimap.entries().iterator()).hasNext())) { + Map.Entry entry = (Map.Entry)iterator.next(); + AttributeModifier attributeModifier = (AttributeModifier)entry.getValue(); + double damage = (attributeModifier.getOperation() != 1) && (attributeModifier.getOperation() != 2) ? + attributeModifier.getAmount() : + attributeModifier.getAmount() * 100.0D; + return attributeModifier.getAmount() > 1.0D ? 1.0F + (float)damage : 1.0F; + } + return 1.0F; + } + + + public boolean hasItemMoreTimes(int slotIn) + { + boolean has = false; + ArrayList stacks = new ArrayList(); + stacks.clear(); + + for (int i = 0; i < mcthePlayer.inventory.getSizeInventory(); i++) { + if (!stacks.contains(getStackInSlot(i))) { + stacks.add(getStackInSlot(i)); + } + else if (getStackInSlot(i) == getStackInSlot(slotIn)) { + return true; + } + } + + + + + + + + + + + + + + return false; + } + + public int getBestWeaponInHotbar() { + int originalSlot = mcthePlayer.inventory.currentItem; + byte weaponSlot = -1; + float weaponDamage = 1.0F; + + for (byte slot = 0; slot < 9; slot = (byte)(slot + 1)) { + ItemStack itemStack = mcthePlayer.inventory.getStackInSlot(slot); + if (itemStack != null) { + float damage = getItemDamage(itemStack); + + if (damage += EnchantmentHelper.func_152377_a(itemStack, net.minecraft.entity.EnumCreatureAttribute.UNDEFINED) > weaponDamage) { + weaponDamage = damage; + weaponSlot = slot; + } + } + } + + if (weaponSlot != -1) { + return weaponSlot; + } + return originalSlot; + } + + public int getBestWeapon() + { + int originalSlot = mcthePlayer.inventory.currentItem; + byte weaponSlot = -1; + float weaponDamage = 1.0F; + + for (byte slot = 0; slot < mcthePlayer.inventory.getSizeInventory(); slot = (byte)(slot + 1)) + { + if (getStackInSlot(slot) != null) + { + + ItemStack itemStack = getStackInSlot(slot); + + if ((itemStack != null) && (itemStack.getItem() != null) && ((itemStack.getItem() instanceof ItemSword))) { + float damage = getItemDamage(itemStack); + + if (damage += EnchantmentHelper.func_152377_a(itemStack, net.minecraft.entity.EnumCreatureAttribute.UNDEFINED) > weaponDamage) { + weaponDamage = damage; + weaponSlot = slot; + } + } + } + } + if (weaponSlot != -1) { + return weaponSlot; + } + return originalSlot; + } + + public int getArmorProt(int i) + { + int armorprot = -1; + if ((getStackInSlot(i) != null) && (getStackInSlot(i).getItem() != null) && + ((getStackInSlot(i).getItem() instanceof ItemArmor))) { + armorprot = ((ItemArmor)mcthePlayer.inventory.getStackInSlot(i).getItem()).getArmorMaterial() + .getDamageReductionAmount(getItemType(mcthePlayer.inventory.getStackInSlot(i))) + + EnchantmentHelper.getEnchantmentModifierDamage( + new ItemStack[] { mcthePlayer.inventory.getStackInSlot(i) }, DamageSource.generic); + } + + return armorprot; + } + + public static int getFirstItem(Item i1) { + for (int i = 0; i < mcthePlayer.inventory.getSizeInventory(); i++) { + if ((getStackInSlot(i) != null) && (getStackInSlot(i).getItem() != null) && + (getStackInSlot(i).getItem() == i1)) { + return i; + } + } + + return -1; + } + + public static boolean isBestSword(ItemStack itemSword, int slot) { + if ((itemSword != null) && ((itemSword.getItem() instanceof ItemSword))) { + for (int i = 0; i < mcthePlayer.inventory.getSizeInventory(); i++) { + ItemStack iStack = mcthePlayer.inventory.getStackInSlot(i); + if ((iStack != null) && ((iStack.getItem() instanceof ItemSword)) && (getItemDamage(iStack) >= getItemDamage(itemSword)) && (slot != i)) { + return false; + } + } + } + + return true; + } +} diff --git a/src/minecraft/com/enjoytheban/utils/TimerUtil.java b/src/minecraft/com/enjoytheban/utils/TimerUtil.java new file mode 100644 index 0000000..7eb4fe0 --- /dev/null +++ b/src/minecraft/com/enjoytheban/utils/TimerUtil.java @@ -0,0 +1,39 @@ +package com.enjoytheban.utils; + + + + +public class TimerUtil +{ + private long lastMS; + + + + public TimerUtil() {} + + + + private long getCurrentMS() + { + return System.nanoTime() / 1000000L; + } + + public boolean hasReached(double milliseconds) + { + return getCurrentMS() - lastMS >= milliseconds; + } + + public void reset() + { + lastMS = getCurrentMS(); + } + + public boolean delay(float milliSec) { + return (float)(getTime() - lastMS) >= milliSec; + } + + public long getTime() + { + return System.nanoTime() / 1000000L; + } +} diff --git a/src/minecraft/com/enjoytheban/utils/math/MathUtil.java b/src/minecraft/com/enjoytheban/utils/math/MathUtil.java new file mode 100644 index 0000000..a4f7c8a --- /dev/null +++ b/src/minecraft/com/enjoytheban/utils/math/MathUtil.java @@ -0,0 +1,122 @@ +package com.enjoytheban.utils.math; + +import com.enjoytheban.utils.Helper; +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.potion.Potion; +import net.minecraft.potion.PotionEffect; + +public class MathUtil +{ + public static Random random = new Random(); + + public MathUtil() {} + + public static double toDecimalLength(double in, int places) { + return Double.parseDouble(String.format("%." + places + "f", new Object[] { Double.valueOf(in) })); + } + + + + public static double round(double in, int places) + { + places = (int)net.minecraft.util.MathHelper.clamp_double(places, 0.0D, 2.147483647E9D); + return Double.parseDouble(String.format("%." + places + "f", new Object[] { Double.valueOf(in) })); + } + + + public static boolean parsable(String s, byte type) + { + try + { + switch (type) { + case 0: + Short.parseShort(s); + break; + case 1: + Byte.parseByte(s); + break; + case 2: + Integer.parseInt(s); + break; + case 3: + Float.parseFloat(s); + break; + case 4: + Double.parseDouble(s); + break; + case 5: + Long.parseLong(s); + } + } + catch (NumberFormatException e) { + e.printStackTrace(); + return false; + } + return true; + } + + + + public static double square(double in) { return in * in; } + + public static class NumberType { + public static final byte SHORT = 0; + public static final byte BYTE = 1; + public static final byte INT = 2; + + public NumberType() {} + + public static byte getByType(Class cls) { + if (cls == Short.class) + return 0; + if (cls == Byte.class) + return 1; + if (cls == Integer.class) + return 2; + if (cls == Float.class) + return 3; + if (cls == Double.class) + return 4; + if (cls == Long.class) { + return 5; + } + return -1; + } + + public static final byte FLOAT = 3; + public static final byte DOUBLE = 4; + public static final byte LONG = 5; + } + + public static double randomDouble(double min, double max) { + return ThreadLocalRandom.current().nextDouble(min, max); + } + + public static double getBaseMovementSpeed() + { + double baseSpeed = 0.2873D; + if (mcthePlayer.isPotionActive(Potion.moveSpeed)) { + int amplifier = mcthePlayer.getActivePotionEffect(Potion.moveSpeed).getAmplifier(); + baseSpeed *= (1.0D + 0.2D * (amplifier + 1)); + } + return baseSpeed; + } + + public static double getHighestOffset(double max) + { + for (double i = 0.0D; i < max; i += 0.01D) { + for (int offset : new int[] { -2, -1, 0, 1, 2 }) + { + + + if (mctheWorld.getCollidingBoundingBoxes(mcthePlayer, mcthePlayer.getEntityBoundingBox().offset(mcthePlayer.motionX * offset, i, mcthePlayer.motionZ * offset)).size() > 0) { + return i - 0.01D; + } + } + } + return max; + } +} diff --git a/src/minecraft/com/enjoytheban/utils/math/RotationUtil.java b/src/minecraft/com/enjoytheban/utils/math/RotationUtil.java new file mode 100644 index 0000000..1863958 --- /dev/null +++ b/src/minecraft/com/enjoytheban/utils/math/RotationUtil.java @@ -0,0 +1,167 @@ +package com.enjoytheban.utils.math; + +import com.enjoytheban.utils.Helper; +import java.util.Random; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; +import net.minecraft.util.MathHelper; +import net.minecraft.util.Vec3; + + + + +public class RotationUtil +{ + public RotationUtil() {} + + public static float pitch() + { + return mcthePlayer.rotationPitch; + } + + public static void pitch(float pitch) { + mcthePlayer.rotationPitch = pitch; + } + + public static float yaw() + { + return mcthePlayer.rotationYaw; + } + + public static void yaw(float yaw) { + mcthePlayer.rotationYaw = yaw; + } + + public static float[] faceTarget(Entity target, float p_706252, float p_706253, boolean miss) + { + double var4 = posX - mcthePlayer.posX; + double var8 = posZ - mcthePlayer.posZ; + double var6; + double var6; if ((target instanceof EntityLivingBase)) { + EntityLivingBase var10 = (EntityLivingBase)target; + var6 = posY + var10.getEyeHeight() - ( + mcthePlayer.posY + mcthePlayer.getEyeHeight()); + } else { + var6 = (getEntityBoundingBoxminY + getEntityBoundingBoxmaxY) / 2.0D - ( + mcthePlayer.posY + mcthePlayer.getEyeHeight()); + } + Random rnd = new Random(); + double var14 = MathHelper.sqrt_double(var4 * var4 + var8 * var8); + float var12 = (float)(Math.atan2(var8, var4) * 180.0D / 3.141592653589793D) - 90.0F; + float var13 = (float)-(Math.atan2(var6 - ((target instanceof EntityPlayer) ? 0.25D : 0.0D), var14) * 180.0D / + 3.141592653589793D); + float pitch = changeRotation(mcthePlayer.rotationPitch, var13, p_706253); + float yaw = changeRotation(mcthePlayer.rotationYaw, var12, p_706252); + return new float[] { yaw, pitch }; + } + + public static float changeRotation(float p_706631, float p_706632, float p_706633) { + float var4 = MathHelper.wrapAngleTo180_float(p_706632 - p_706631); + if (var4 > p_706633) + var4 = p_706633; + if (var4 < -p_706633) + var4 = -p_706633; + return p_706631 + var4; + } + + public static double[] getRotationToEntity(Entity entity) { + double pX = mcthePlayer.posX; + double pY = mcthePlayer.posY + mcthePlayer.getEyeHeight(); + double pZ = mcthePlayer.posZ; + + double eX = posX; + double eY = posY + height / 2.0F; + double eZ = posZ; + + double dX = pX - eX; + double dY = pY - eY; + double dZ = pZ - eZ; + double dH = Math.sqrt(Math.pow(dX, 2.0D) + Math.pow(dZ, 2.0D)); + + double yaw = Math.toDegrees(Math.atan2(dZ, dX)) + 90.0D; + double pitch = Math.toDegrees(Math.atan2(dH, dY)); + + return new double[] { yaw, 90.0D - pitch }; + } + + + public static float[] getRotations(Entity entity) + { + if (mcbreakTheGame) + return new float[] { 0.0F, -90.0F }; + if (entity == null) { + return null; + } + + + double diffX = posX - mcthePlayer.posX; + double diffZ = posZ - mcthePlayer.posZ; + + double diffY; + + double diffY; + if ((entity instanceof EntityLivingBase)) + { + EntityLivingBase elb = (EntityLivingBase)entity; + + diffY = posY + (elb.getEyeHeight() - 0.4D) - ( + mcthePlayer.posY + mcthePlayer.getEyeHeight()); + } else { + diffY = (boundingBox.minY + boundingBox.maxY) / 2.0D - ( + mcthePlayer.posY + mcthePlayer.getEyeHeight()); + } + + + double dist = MathHelper.sqrt_double(diffX * diffX + diffZ * diffZ); + float yaw = (float)(Math.atan2(diffZ, diffX) * 180.0D / 3.141592653589793D) - 90.0F; + float pitch = (float)-(Math.atan2(diffY, dist) * 180.0D / 3.141592653589793D); + return new float[] { yaw, pitch }; + } + + + public static float getDistanceBetweenAngles(float angle1, float angle2) + { + float angle3 = Math.abs(angle1 - angle2) % 360.0F; + + if (angle3 > 180.0F) { + angle3 = 0.0F; + } + return angle3; + } + + public static float[] grabBlockRotations(BlockPos pos) + { + return + getVecRotation( + mcthePlayer.getPositionVector().addVector(0.0D, + mcthePlayer.getEyeHeight(), 0.0D), + new Vec3(pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D)); + } + + public static float[] getVecRotation(Vec3 position) { + return getVecRotation(mcthePlayer.getPositionVector().addVector(0.0D, + mcthePlayer.getEyeHeight(), 0.0D), position); + } + + public static float[] getVecRotation(Vec3 origin, Vec3 position) { + Vec3 difference = position.subtract(origin); + double distance = difference.flat().lengthVector(); + float yaw = (float)Math.toDegrees(Math.atan2(zCoord, xCoord)) - 90.0F; + float pitch = (float)-Math.toDegrees(Math.atan2(yCoord, distance)); + return new float[] { yaw, pitch }; + } + + public static int wrapAngleToDirection(float yaw, int zones) + { + int angle = (int)(yaw + 360 / (2 * zones) + 0.5D) % 360; + if (angle < 0) { + angle += 360; + } + return angle / (360 / zones); + } +} diff --git a/src/minecraft/com/enjoytheban/utils/math/Vec2f.java b/src/minecraft/com/enjoytheban/utils/math/Vec2f.java new file mode 100644 index 0000000..e35fbe5 --- /dev/null +++ b/src/minecraft/com/enjoytheban/utils/math/Vec2f.java @@ -0,0 +1,202 @@ +package com.enjoytheban.utils.math; + +import com.enjoytheban.utils.render.gl.GLUtils; + + + + + + + + +public final class Vec2f +{ + private float x; + private float y; + + public Vec2f() + { + this(0.0F, 0.0F); + } + + public Vec2f(Vec2f vec) { + this(x, y); + } + + public Vec2f(double x, double y) { + this((float)x, (float)y); + } + + public Vec2f(float x, float y) { + this.x = x; + this.y = y; + } + + + + + + + public final Vec2f setX(float x) + { + this.x = x; + return this; + } + + + + + + + public final Vec2f setY(float y) + { + this.y = y; + return this; + } + + + + public final float getX() + { + return x; + } + + + + public final float getY() + { + return y; + } + + + + + + + public final Vec2f add(Vec2f vec) + { + return new Vec2f(x + x, y + y); + } + + + + + + + + public final Vec2f add(double x, double y) + { + return add(new Vec2f(x, y)); + } + + + + + + + + public final Vec2f add(float x, float y) + { + return add(new Vec2f(x, y)); + } + + + + + + + public final Vec2f sub(Vec2f vec) + { + return new Vec2f(x - x, y - y); + } + + + + + + + + public final Vec2f sub(double x, double y) + { + return sub(new Vec2f(x, y)); + } + + + + + + + + public final Vec2f sub(float x, float y) + { + return sub(new Vec2f(x, y)); + } + + + + + + + public final Vec2f scale(float scale) + { + return new Vec2f(x * scale, y * scale); + } + + + + + + public final Vec3f toVec3() + { + return new Vec3f(x, y, 0.0D); + } + + + + + + public final Vec2f copy() + { + return new Vec2f(this); + } + + + + + + + public final Vec2f transfer(Vec2f vec) + { + x = x; + y = y; + return this; + } + + + + + + public final float distanceTo(Vec2f vec) + { + double dx = x - x; + double dy = y - y; + return (float)Math.sqrt(dx * dx + dy * dy); + } + + + + + + public final Vec3f toScreen() + { + return GLUtils.toWorld(toVec3()); + } + + public String toString() + { + return + + + "Vec2{x=" + x + ", y=" + y + '}'; + } +} diff --git a/src/minecraft/com/enjoytheban/utils/math/Vec3f.java b/src/minecraft/com/enjoytheban/utils/math/Vec3f.java new file mode 100644 index 0000000..3b9dd4c --- /dev/null +++ b/src/minecraft/com/enjoytheban/utils/math/Vec3f.java @@ -0,0 +1,208 @@ +package com.enjoytheban.utils.math; + +import com.enjoytheban.utils.render.gl.GLUtils; + + + + + + + +public final class Vec3f +{ + private double x; + private double y; + private double z; + + public Vec3f() + { + this(0.0D, 0.0D, 0.0D); + } + + public Vec3f(Vec3f vec) { + this(x, y, z); + } + + public Vec3f(double x, double y, double z) { + this.x = x; + this.y = y; + this.z = z; + } + + + + + + + public final Vec3f setX(double x) + { + this.x = x; + return this; + } + + + + + + + public final Vec3f setY(double y) + { + this.y = y; + return this; + } + + + + + + + public final Vec3f setZ(double z) + { + this.z = z; + return this; + } + + + + public final double getX() + { + return x; + } + + + + public final double getY() + { + return y; + } + + + + public final double getZ() + { + return z; + } + + + + + + + public final Vec3f add(Vec3f vec) + { + return add(x, y, z); + } + + + + + + + + + public final Vec3f add(double x, double y, double z) + { + return new Vec3f(this.x + x, this.y + y, this.z + z); + } + + + + + + + public final Vec3f sub(Vec3f vec) + { + return new Vec3f(x - x, y - y, z - z); + } + + + + + + + + + public final Vec3f sub(double x, double y, double z) + { + return new Vec3f(this.x - x, this.y - y, this.z - z); + } + + + + + + + public final Vec3f scale(float scale) + { + return new Vec3f(x * scale, y * scale, z * scale); + } + + + + + + public final Vec3f copy() + { + return new Vec3f(this); + } + + + + + + + public final Vec3f transfer(Vec3f vec) + { + x = x; + y = y; + z = z; + return this; + } + + + + + + public final double distanceTo(Vec3f vec) + { + double dx = x - x; + double dy = y - y; + double dz = z - z; + return Math.sqrt(dx * dx + dy * dy + dz * dz); + } + + + + + + + + + public final Vec2f rotationsTo(Vec3f vec) + { + double[] diff = { x - x, y - y, z - z }; + double hDist = Math.sqrt(diff[0] * diff[0] + diff[2] * diff[2]); + return new Vec2f( + Math.toDegrees(Math.atan2(diff[2], diff[0])) - 90.0D, + -Math.toDegrees(Math.atan2(diff[1], hDist))); + } + + + + + + + public final Vec3f toScreen() + { + return GLUtils.toScreen(this); + } + + public String toString() + { + return + + + + "Vec3{x=" + x + ", y=" + y + ", z=" + z + '}'; + } +} diff --git a/src/minecraft/com/enjoytheban/utils/math/Vec4f.java b/src/minecraft/com/enjoytheban/utils/math/Vec4f.java new file mode 100644 index 0000000..8e23f96 --- /dev/null +++ b/src/minecraft/com/enjoytheban/utils/math/Vec4f.java @@ -0,0 +1,47 @@ +package com.enjoytheban.utils.math; + +public class Vec4f { + public float x; + public float y; + public float w; + public float h; + + public float getX() { + return x; + } + + public float getY() { + return y; + } + + public float getW() { + return w; + } + + public float getH() { + return h; + } + + public void setX(float x) { + this.x = x; + } + + public void setY(float y) { + this.y = y; + } + + public void setW(float w) { + this.w = w; + } + + public void setH(float h) { + this.h = h; + } + + public Vec4f(float x, float y, float w, float h) { + this.x = x; + this.y = y; + this.w = w; + this.h = h; + } +} diff --git a/src/minecraft/com/enjoytheban/utils/proxy/ConnectionInfo.java b/src/minecraft/com/enjoytheban/utils/proxy/ConnectionInfo.java new file mode 100644 index 0000000..1dcf192 --- /dev/null +++ b/src/minecraft/com/enjoytheban/utils/proxy/ConnectionInfo.java @@ -0,0 +1,9 @@ +package com.enjoytheban.utils.proxy; + +public class ConnectionInfo +{ + public String ip; + public int port; + + public ConnectionInfo() {} +} diff --git a/src/minecraft/com/enjoytheban/utils/proxy/GuiProxy.java b/src/minecraft/com/enjoytheban/utils/proxy/GuiProxy.java new file mode 100644 index 0000000..83f9b67 --- /dev/null +++ b/src/minecraft/com/enjoytheban/utils/proxy/GuiProxy.java @@ -0,0 +1,125 @@ +package com.enjoytheban.utils.proxy; + +import java.io.IOException; +import java.util.List; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiMultiplayer; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.GuiTextField; +import org.lwjgl.input.Keyboard; + + +public class GuiProxy + extends GuiScreen +{ + private GuiMultiplayer prevMenu; + private GuiTextField proxyBox; + private String error = ""; + + public static boolean connected = false; + + public GuiProxy(GuiMultiplayer guiMultiplayer) { + prevMenu = guiMultiplayer; + } + + public void updateScreen() + { + proxyBox.updateCursorCounter(); + } + + public void initGui() + { + Keyboard.enableRepeatEvents(true); + buttonList.clear(); + buttonList.add(new GuiButton(0, width / 2 - 100, height / 4 + 120 + 12, "Back")); + buttonList.add(new GuiButton(1, width / 2 - 100, height / 4 + 72 + 12, "Connect")); + buttonList.add(new GuiButton(2, width / 2 - 100, height / 4 + 96 + 12, "Disconnect")); + proxyBox = new GuiTextField(0, fontRendererObj, width / 2 - 100, 60, 200, 20); + proxyBox.setFocused(true); + } + + public void onGuiClosed() + { + Keyboard.enableRepeatEvents(false); + } + + protected void actionPerformed(GuiButton clickedButton) + { + if (enabled) { + if (id == 0) { + mc.displayGuiScreen(prevMenu); + } else if (id == 1) { + if ((!proxyBox.getText().contains(":")) || (proxyBox.getText().split(":").length != 2)) { + error = "Not a proxy!"; + return; + } + String[] parts = proxyBox.getText().split(":"); + + if ((isInteger(parts[1])) && (Integer.parseInt(parts[1]) <= 65536)) Integer.parseInt(parts[1]); + try + { + ProxyConfig.proxyAddr = new ConnectionInfo(); + proxyAddrip = parts[0]; + proxyAddrport = Integer.parseInt(parts[1]); + connected = true; + } catch (Exception e) { + error = e.toString(); + return; + } + if (error.isEmpty()) {} + + + } + else if (id == 2) { + ProxyConfig.stop(); + connected = false; + } + } + } + + protected void keyTyped(char par1, int par2) + { + proxyBox.textboxKeyTyped(par1, par2); + + if ((par2 == 28) || (par2 == 156)) { + actionPerformed((GuiButton)buttonList.get(1)); + } + } + + protected void mouseClicked(int par1, int par2, int par3) throws IOException { + super.mouseClicked(par1, par2, par3); + proxyBox.mouseClicked(par1, par2, par3); + if (proxyBox.isFocused()) { + error = ""; + } + } + + public void drawScreen(int par1, int par2, float par3) { + drawDefaultBackground(); + mc.fontRendererObj.drawCenteredString("Proxies Reloaded", width / 2, 20, 16777215); + mc.fontRendererObj.drawCenteredString("(SOCKS5 Proxies only)", width / 2, 30, 16777215); + mc.fontRendererObj.drawStringWithShadow("IP:Port", width / 2 - 100, 47.0F, 10526880); + mc.fontRendererObj.drawCenteredString(error, width / 2, 95, 16711680); + String currentProxy = ""; + if (connected) { + currentProxy = "§a" + proxyAddrip + ":" + proxyAddrport; + } + if (!connected) { + currentProxy = "§cN/A"; + } + mc.fontRendererObj.drawStringWithShadow("Current proxy: " + currentProxy, 1.0F, 3.0F, -1); + proxyBox.drawTextBox(); + super.drawScreen(par1, par2, par3); + } + + public static boolean isInteger(String s) { + try { + Integer.parseInt(s); + } catch (NumberFormatException e) { + return false; + } + return true; + } +} diff --git a/src/minecraft/com/enjoytheban/utils/proxy/ProxyConfig.java b/src/minecraft/com/enjoytheban/utils/proxy/ProxyConfig.java new file mode 100644 index 0000000..66d87a2 --- /dev/null +++ b/src/minecraft/com/enjoytheban/utils/proxy/ProxyConfig.java @@ -0,0 +1,108 @@ +package com.enjoytheban.utils.proxy; + +import com.enjoytheban.api.EventHandler; +import com.enjoytheban.api.events.world.EventTick; +import com.enjoytheban.utils.Helper; +import java.net.ServerSocket; +import java.util.Random; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiDisconnected; +import net.minecraft.client.gui.GuiMainMenu; +import net.minecraft.client.gui.GuiMultiplayer; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.realms.RealmsBridge; +import net.minecraft.util.ChatComponentText; + + + + + + + +public class ProxyConfig +{ + public ProxyConfig() {} + + public static int listenerPort = findFreePort(29999); + public static TransparentProxy proxy = null; + public static ConnectionInfo proxyAddr = null; + + public static ConnectionInfo connect(String ip, int port) { + if (proxyAddr != null) { + if (proxy == null) { + proxy = new TransparentProxy(listenerPort); + } + if (proxy.isRunning()) { + proxy.stop(); + } + try { + proxy.start(proxyAddrip, proxyAddrport, ip, port); + while ((!proxy.isReady()) && (!proxy.hasFailed())) { + Thread.sleep(50L); + } + if (proxy.hasFailed()) { + throw proxy.getFailReason(); + } + ConnectionInfo returnment = new ConnectionInfo(); + ip = "127.0.0.1"; + port = listenerPort; + return returnment; + } catch (Exception e) { + e.printStackTrace(); + ConnectionInfo returnment = new ConnectionInfo(); + ip = ip; + port = port; + return returnment; + } + } + ConnectionInfo returnment = new ConnectionInfo(); + ip = ip; + port = port; + return returnment; + } + + @EventHandler + public void onGlobalGameLoop(EventTick e) { + if ((proxy != null) && (proxy.isRunning()) && (proxy.hasFailed())) { + boolean flag = Helper.mc.isIntegratedServerRunning(); + boolean flag1 = Helper.mc.isSingleplayer(); + mctheWorld.sendQuittingDisconnectingPacket(); + Helper.mc.loadWorld(null); + if (flag) { + Helper.mc.displayGuiScreen(new GuiDisconnected(new GuiMultiplayer(new GuiMainMenu()), "disconnect.closed", new ChatComponentText("[AC-Proxy] Lost Connection to server!"))); + } else if (flag1) { + RealmsBridge realmsbridge = new RealmsBridge(); + realmsbridge.switchToRealms(new GuiDisconnected(new GuiMultiplayer(new GuiMainMenu()), "disconnect.closed", new ChatComponentText("[AC-Proxy] Lost Connection to server!"))); + } else { + Helper.mc.displayGuiScreen(new GuiDisconnected(new GuiMultiplayer(new GuiMainMenu()), "disconnect.closed", new ChatComponentText("[AC-Proxy] Lost Connection to server!"))); + } + } + } + + + + + + + public static void stop() + { + if (proxy != null) { + proxy.stop(); + } + } + + private static int findFreePort(int start) + { + int cur = new Random().nextInt(10000) + start - 1; + for (;;) + { + try { + ServerSocket sock = new ServerSocket(cur, 1); + sock.close(); + return cur; + } catch (Exception var3) { + cur = new Random().nextInt(10000) + start - 1; + } + } + } +} diff --git a/src/minecraft/com/enjoytheban/utils/proxy/ProxySocket.java b/src/minecraft/com/enjoytheban/utils/proxy/ProxySocket.java new file mode 100644 index 0000000..ce91cc1 --- /dev/null +++ b/src/minecraft/com/enjoytheban/utils/proxy/ProxySocket.java @@ -0,0 +1,17 @@ +package com.enjoytheban.utils.proxy; + +import java.net.Socket; + +public class ProxySocket +{ + public ProxySocket() {} + + public static Socket connectOverProxy(String proxyAdress, int proxyPort, String destAddress, int destPort) throws Exception + { + java.net.Proxy proxy = new java.net.Proxy(java.net.Proxy.Type.SOCKS, new java.net.InetSocketAddress(proxyAdress, proxyPort)); + Socket returnment = new Socket(proxy); + returnment.setTcpNoDelay(true); + returnment.connect(new java.net.InetSocketAddress(destAddress, destPort)); + return returnment; + } +} diff --git a/src/minecraft/com/enjoytheban/utils/proxy/TransparentProxy.java b/src/minecraft/com/enjoytheban/utils/proxy/TransparentProxy.java new file mode 100644 index 0000000..ec747fa --- /dev/null +++ b/src/minecraft/com/enjoytheban/utils/proxy/TransparentProxy.java @@ -0,0 +1 @@ +null \ No newline at end of file diff --git a/src/minecraft/com/enjoytheban/utils/render/ColorUtils.java b/src/minecraft/com/enjoytheban/utils/render/ColorUtils.java new file mode 100644 index 0000000..c74dc79 --- /dev/null +++ b/src/minecraft/com/enjoytheban/utils/render/ColorUtils.java @@ -0,0 +1,166 @@ +package com.enjoytheban.utils.render; + +import java.awt.Color; + +public class ColorUtils { + public ColorUtils() {} + + public static int randomColor() { return 0xFF000000 | (int)(Math.random() * 1.6777215E7D); } + + public static int transparency(int color, double alpha) + { + Color c = new Color(color); + float r = 0.003921569F * c.getRed(); + float g = 0.003921569F * c.getGreen(); + float b = 0.003921569F * c.getBlue(); + return new Color(r, g, b, (float)alpha).getRGB(); + } + + public static int transparency(Color color, double alpha) { + return new Color(color.getRed(), color.getGreen(), color.getBlue(), (float)alpha).getRGB(); + } + + public static Color rainbow(long offset, float fade) { + float hue = (float)(System.nanoTime() + offset) / 1.0E10F % 1.0F; + long color = Long.parseLong(Integer.toHexString(Integer.valueOf(Color.HSBtoRGB(hue, 1.0F, 1.0F)).intValue()), 16); + Color c = new Color((int)color); + return new Color(c.getRed() / 255.0F * fade, c.getGreen() / 255.0F * fade, c.getBlue() / 255.0F * fade, c.getAlpha() / 255.0F); + } + + public static float[] getRGBA(int color) { + float a = (color >> 24 & 0xFF) / 255.0F; + float r = (color >> 16 & 0xFF) / 255.0F; + float g = (color >> 8 & 0xFF) / 255.0F; + float b = (color & 0xFF) / 255.0F; + return new float[] { r, g, b, a }; + } + + public static int intFromHex(String hex) { + try { + if (hex.equalsIgnoreCase("rainbow")) { + return rainbow(0L, 1.0F).getRGB(); + } + return Integer.parseInt(hex, 16); + } + catch (NumberFormatException e) {} + return -1; + } + + public static String hexFromInt(int color) + { + return hexFromInt(new Color(color)); + } + + public static String hexFromInt(Color color) { + return Integer.toHexString(color.getRGB()).substring(2); + } + + public static Color blend(Color color1, Color color2, double ratio) { + float r = (float)ratio; + float ir = 1.0F - r; + float[] rgb1 = new float[3]; + float[] rgb2 = new float[3]; + color1.getColorComponents(rgb1); + color2.getColorComponents(rgb2); + Color color3 = new Color(rgb1[0] * r + rgb2[0] * ir, rgb1[1] * r + rgb2[1] * ir, rgb1[2] * r + rgb2[2] * ir); + return color3; + } + + public static Color blend(Color color1, Color color2) { + return blend(color1, color2, 0.5D); + } + + public static Color darker(Color color, double fraction) { + int red = (int)Math.round(color.getRed() * (1.0D - fraction)); + int green = (int)Math.round(color.getGreen() * (1.0D - fraction)); + int blue = (int)Math.round(color.getBlue() * (1.0D - fraction)); + if (red < 0) { + red = 0; + } + else if (red > 255) { + red = 255; + } + if (green < 0) { + green = 0; + } + else if (green > 255) { + green = 255; + } + if (blue < 0) { + blue = 0; + } + else if (blue > 255) { + blue = 255; + } + int alpha = color.getAlpha(); + return new Color(red, green, blue, alpha); + } + + public static Color lighter(Color color, double fraction) { + int red = (int)Math.round(color.getRed() * (1.0D + fraction)); + int green = (int)Math.round(color.getGreen() * (1.0D + fraction)); + int blue = (int)Math.round(color.getBlue() * (1.0D + fraction)); + if (red < 0) { + red = 0; + } + else if (red > 255) { + red = 255; + } + if (green < 0) { + green = 0; + } + else if (green > 255) { + green = 255; + } + if (blue < 0) { + blue = 0; + } + else if (blue > 255) { + blue = 255; + } + int alpha = color.getAlpha(); + return new Color(red, green, blue, alpha); + } + + public static String getHexName(Color color) { + int r = color.getRed(); + int g = color.getGreen(); + int b = color.getBlue(); + String rHex = Integer.toString(r, 16); + String gHex = Integer.toString(g, 16); + String bHex = Integer.toString(b, 16); + return String.valueOf(rHex.length() == 2 ? rHex : new StringBuilder("0").append(rHex).toString()) + (gHex.length() == 2 ? gHex : new StringBuilder("0").append(gHex).toString()) + (bHex.length() == 2 ? bHex : new StringBuilder("0").append(bHex).toString()); + } + + public static double colorDistance(double r1, double g1, double b1, double r2, double g2, double b2) { + double a = r2 - r1; + double b3 = g2 - g1; + double c = b2 - b1; + return Math.sqrt(a * a + b3 * b3 + c * c); + } + + public static double colorDistance(double[] color1, double[] color2) { + return colorDistance(color1[0], color1[1], color1[2], color2[0], color2[1], color2[2]); + } + + public static double colorDistance(Color color1, Color color2) { + float[] rgb1 = new float[3]; + float[] rgb2 = new float[3]; + color1.getColorComponents(rgb1); + color2.getColorComponents(rgb2); + return colorDistance(rgb1[0], rgb1[1], rgb1[2], rgb2[0], rgb2[1], rgb2[2]); + } + + public static boolean isDark(double r, double g, double b) { + double dWhite = colorDistance(r, g, b, 1.0D, 1.0D, 1.0D); + double dBlack = colorDistance(r, g, b, 0.0D, 0.0D, 0.0D); + return dBlack < dWhite; + } + + public static boolean isDark(Color color) { + float r = color.getRed() / 255.0F; + float g = color.getGreen() / 255.0F; + float b = color.getBlue() / 255.0F; + return isDark(r, g, b); + } +} diff --git a/src/minecraft/com/enjoytheban/utils/render/GLUProjection.java b/src/minecraft/com/enjoytheban/utils/render/GLUProjection.java new file mode 100644 index 0000000..48a5afb --- /dev/null +++ b/src/minecraft/com/enjoytheban/utils/render/GLUProjection.java @@ -0,0 +1,557 @@ +package com.enjoytheban.utils.render; + +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import org.lwjgl.BufferUtils; +import org.lwjgl.util.glu.GLU; +import org.lwjgl.util.vector.Matrix4f; + + +public final class GLUProjection +{ + private static GLUProjection instance; + private final FloatBuffer coords = BufferUtils.createFloatBuffer(3); + private IntBuffer viewport; + private FloatBuffer modelview; + private FloatBuffer projection; + private Vector3D frustumPos; + private Vector3D[] frustum; + private Vector3D[] invFrustum; + private Vector3D viewVec; + private double displayWidth; + private double displayHeight; + private double widthScale; + private double heightScale; + private double bra; + private double bla; + private double tra; + private double tla; + private Line tb; + private Line bb; + private Line lb; + private Line rb; + private float fovY; + private float fovX; + private Vector3D lookVec; + + public GLUProjection() {} + + public static GLUProjection getInstance() { if (instance == null) { + instance = new GLUProjection(); + } + return instance; + } + + public void updateMatrices(IntBuffer viewport, FloatBuffer modelview, FloatBuffer projection, double widthScale, double heightScale) + { + this.viewport = viewport; + this.modelview = modelview; + this.projection = projection; + this.widthScale = widthScale; + this.heightScale = heightScale; + + float fov = (float)Math.toDegrees(Math.atan(1.0D / this.projection.get(5)) * 2.0D); + fovY = fov; + displayWidth = this.viewport.get(2); + displayHeight = this.viewport.get(3); + fovX = ((float)Math.toDegrees(2.0D * Math.atan(displayWidth / displayHeight * Math.tan(Math.toRadians(fovY) / 2.0D)))); + + Vector3D ft = new Vector3D(this.modelview.get(12), this.modelview.get(13), this.modelview.get(14)); + Vector3D lv = new Vector3D(this.modelview.get(0), this.modelview.get(1), this.modelview.get(2)); + Vector3D uv = new Vector3D(this.modelview.get(4), this.modelview.get(5), this.modelview.get(6)); + Vector3D fv = new Vector3D(this.modelview.get(8), this.modelview.get(9), this.modelview.get(10)); + + Vector3D nuv = new Vector3D(0.0D, 1.0D, 0.0D); + Vector3D nlv = new Vector3D(1.0D, 0.0D, 0.0D); + Vector3D nfv = new Vector3D(0.0D, 0.0D, 1.0D); + + double yaw = Math.toDegrees(Math.atan2(nlv.cross(lv).length(), nlv.dot(lv))) + 180.0D; + if (x < 0.0D) { + yaw = 360.0D - yaw; + } + double pitch = 0.0D; + if (((-y > 0.0D) && (yaw >= 90.0D) && (yaw < 270.0D)) || ((y > 0.0D) && ((yaw < 90.0D) || (yaw >= 270.0D)))) { + pitch = Math.toDegrees(Math.atan2(nuv.cross(uv).length(), nuv.dot(uv))); + } else { + pitch = -Math.toDegrees(Math.atan2(nuv.cross(uv).length(), nuv.dot(uv))); + } + lookVec = getRotationVector(yaw, pitch); + + Matrix4f modelviewMatrix = new Matrix4f(); + modelviewMatrix.load(this.modelview.asReadOnlyBuffer()); + modelviewMatrix.invert(); + + frustumPos = new Vector3D(m30, m31, m32); + frustum = getFrustum(frustumPos.x, frustumPos.y, frustumPos.z, yaw, pitch, fov, 1.0D, displayWidth / displayHeight); + invFrustum = getFrustum(frustumPos.x, frustumPos.y, frustumPos.z, yaw - 180.0D, -pitch, fov, 1.0D, displayWidth / displayHeight); + + viewVec = getRotationVector(yaw, pitch).normalized(); + + bra = Math.toDegrees(Math.acos(displayHeight * heightScale / Math.sqrt(displayWidth * widthScale * displayWidth * widthScale + displayHeight * heightScale * displayHeight * heightScale))); + bla = (360.0D - bra); + tra = (bla - 180.0D); + tla = (bra + 180.0D); + + rb = new Line(displayWidth * this.widthScale, 0.0D, 0.0D, 0.0D, 1.0D, 0.0D); + tb = new Line(0.0D, 0.0D, 0.0D, 1.0D, 0.0D, 0.0D); + lb = new Line(0.0D, 0.0D, 0.0D, 0.0D, 1.0D, 0.0D); + bb = new Line(0.0D, displayHeight * this.heightScale, 0.0D, 1.0D, 0.0D, 0.0D); + } + + public Projection project(double x, double y, double z, ClampMode clampModeOutside, boolean extrudeInverted) + { + if ((viewport != null) && (modelview != null) && (projection != null)) + { + Vector3D posVec = new Vector3D(x, y, z); + boolean[] frustum = doFrustumCheck(this.frustum, frustumPos, x, y, z); + boolean outsideFrustum = (frustum[0] != 0) || (frustum[1] != 0) || (frustum[2] != 0) || (frustum[3] != 0); + if (outsideFrustum) + { + boolean opposite = posVec.sub(frustumPos).dot(viewVec) <= 0.0D; + + boolean[] invFrustum = doFrustumCheck(this.invFrustum, frustumPos, x, y, z); + boolean outsideInvertedFrustum = (invFrustum[0] != 0) || (invFrustum[1] != 0) || (invFrustum[2] != 0) || (invFrustum[3] != 0); if (((extrudeInverted) && (!outsideInvertedFrustum)) || ((outsideInvertedFrustum) && (clampModeOutside != ClampMode.NONE))) + { + if (((extrudeInverted) && (!outsideInvertedFrustum)) || ((clampModeOutside == ClampMode.DIRECT) && (outsideInvertedFrustum))) + { + double vecX = 0.0D; + double vecY = 0.0D; + if (GLU.gluProject((float)x, (float)y, (float)z, modelview, projection, viewport, coords)) + { + if (opposite) + { + vecX = displayWidth * widthScale - coords.get(0) * widthScale - displayWidth * widthScale / 2.0D; + vecY = displayHeight * heightScale - (displayHeight - coords.get(1)) * heightScale - displayHeight * heightScale / 2.0D; + } + else + { + vecX = coords.get(0) * widthScale - displayWidth * widthScale / 2.0D; + vecY = (displayHeight - coords.get(1)) * heightScale - displayHeight * heightScale / 2.0D; + } + } + else { + return new Projection(0.0D, 0.0D, GLUProjection.Projection.Type.FAIL); + } + Vector3D vec = new Vector3D(vecX, vecY, 0.0D).snormalize(); + vecX = x; + vecY = y; + + Line vectorLine = new Line(displayWidth * widthScale / 2.0D, displayHeight * heightScale / 2.0D, 0.0D, vecX, vecY, 0.0D); + + double angle = Math.toDegrees(Math.acos(y / Math.sqrt(x * x + y * y))); + if (vecX < 0.0D) { + angle = 360.0D - angle; + } + Vector3D intersect = new Vector3D(0.0D, 0.0D, 0.0D); + if ((angle >= bra) && (angle < tra)) { + intersect = rb.intersect(vectorLine); + } else if ((angle >= tra) && (angle < tla)) { + intersect = tb.intersect(vectorLine); + } else if ((angle >= tla) && (angle < bla)) { + intersect = lb.intersect(vectorLine); + } else { + intersect = bb.intersect(vectorLine); + } + return new Projection(x, y, outsideInvertedFrustum ? GLUProjection.Projection.Type.OUTSIDE : GLUProjection.Projection.Type.INVERTED); + } + if ((clampModeOutside == ClampMode.ORTHOGONAL) && (outsideInvertedFrustum)) + { + if (GLU.gluProject((float)x, (float)y, (float)z, modelview, projection, viewport, coords)) + { + double guiX = coords.get(0) * widthScale; + double guiY = (displayHeight - coords.get(1)) * heightScale; + if (opposite) + { + guiX = displayWidth * widthScale - guiX; + guiY = displayHeight * heightScale - guiY; + } + if (guiX < 0.0D) { + guiX = 0.0D; + } else if (guiX > displayWidth * widthScale) { + guiX = displayWidth * widthScale; + } + if (guiY < 0.0D) { + guiY = 0.0D; + } else if (guiY > displayHeight * heightScale) { + guiY = displayHeight * heightScale; + } + return new Projection(guiX, guiY, outsideInvertedFrustum ? GLUProjection.Projection.Type.OUTSIDE : GLUProjection.Projection.Type.INVERTED); + } + return new Projection(0.0D, 0.0D, GLUProjection.Projection.Type.FAIL); + } + } + else + { + if (GLU.gluProject((float)x, (float)y, (float)z, modelview, projection, viewport, coords)) + { + double guiX = coords.get(0) * widthScale; + double guiY = (displayHeight - coords.get(1)) * heightScale; + if (opposite) + { + guiX = displayWidth * widthScale - guiX; + guiY = displayHeight * heightScale - guiY; + } + return new Projection(guiX, guiY, outsideInvertedFrustum ? GLUProjection.Projection.Type.OUTSIDE : GLUProjection.Projection.Type.INVERTED); + } + return new Projection(0.0D, 0.0D, GLUProjection.Projection.Type.FAIL); + } + } + else + { + if (GLU.gluProject((float)x, (float)y, (float)z, modelview, projection, viewport, coords)) + { + double guiX = coords.get(0) * widthScale; + double guiY = (displayHeight - coords.get(1)) * heightScale; + return new Projection(guiX, guiY, GLUProjection.Projection.Type.INSIDE); + } + return new Projection(0.0D, 0.0D, GLUProjection.Projection.Type.FAIL); + } + } + return new Projection(0.0D, 0.0D, GLUProjection.Projection.Type.FAIL); + } + + public boolean[] doFrustumCheck(Vector3D[] frustumCorners, Vector3D frustumPos, double x, double y, double z) + { + Vector3D point = new Vector3D(x, y, z); + boolean c1 = crossPlane(new Vector3D[] { frustumPos, frustumCorners[3], frustumCorners[0] }, point); + boolean c2 = crossPlane(new Vector3D[] { frustumPos, frustumCorners[0], frustumCorners[1] }, point); + boolean c3 = crossPlane(new Vector3D[] { frustumPos, frustumCorners[1], frustumCorners[2] }, point); + boolean c4 = crossPlane(new Vector3D[] { frustumPos, frustumCorners[2], frustumCorners[3] }, point); + return new boolean[] { c1, c2, c3, c4 }; + } + + public boolean crossPlane(Vector3D[] plane, Vector3D point) + { + Vector3D z = new Vector3D(0.0D, 0.0D, 0.0D); + Vector3D e0 = plane[1].sub(plane[0]); + Vector3D e1 = plane[2].sub(plane[0]); + Vector3D normal = e0.cross(e1).snormalize(); + double D = z.sub(normal).dot(plane[2]); + double dist = normal.dot(point) + D; + return dist >= 0.0D; + } + + public Vector3D[] getFrustum(double x, double y, double z, double rotationYaw, double rotationPitch, double fov, double farDistance, double aspectRatio) + { + Vector3D viewVec = getRotationVector(rotationYaw, rotationPitch).snormalize(); + double hFar = 2.0D * Math.tan(Math.toRadians(fov / 2.0D)) * farDistance; + double wFar = hFar * aspectRatio; + Vector3D view = getRotationVector(rotationYaw, rotationPitch).snormalize(); + Vector3D up = getRotationVector(rotationYaw, rotationPitch - 90.0D).snormalize(); + Vector3D right = getRotationVector(rotationYaw + 90.0D, 0.0D).snormalize(); + Vector3D camPos = new Vector3D(x, y, z); + Vector3D view_camPos_product = view.add(camPos); + Vector3D fc = new Vector3D(x * farDistance, y * farDistance, z * farDistance); + Vector3D topLeftfrustum = new Vector3D(x + x * hFar / 2.0D - x * wFar / 2.0D, y + y * hFar / 2.0D - y * wFar / 2.0D, z + z * hFar / 2.0D - z * wFar / 2.0D); + Vector3D downLeftfrustum = new Vector3D(x - x * hFar / 2.0D - x * wFar / 2.0D, y - y * hFar / 2.0D - y * wFar / 2.0D, z - z * hFar / 2.0D - z * wFar / 2.0D); + Vector3D topRightfrustum = new Vector3D(x + x * hFar / 2.0D + x * wFar / 2.0D, y + y * hFar / 2.0D + y * wFar / 2.0D, z + z * hFar / 2.0D + z * wFar / 2.0D); + Vector3D downRightfrustum = new Vector3D(x - x * hFar / 2.0D + x * wFar / 2.0D, y - y * hFar / 2.0D + y * wFar / 2.0D, z - z * hFar / 2.0D + z * wFar / 2.0D); + return new Vector3D[] { topLeftfrustum, downLeftfrustum, downRightfrustum, topRightfrustum }; + } + + public Vector3D[] getFrustum() + { + return frustum; + } + + public float getFovX() + { + return fovX; + } + + public float getFovY() + { + return fovY; + } + + public Vector3D getLookVector() + { + return lookVec; + } + + public Vector3D getRotationVector(double rotYaw, double rotPitch) + { + double c = Math.cos(-rotYaw * 0.01745329238474369D - 3.141592653589793D); + double s = Math.sin(-rotYaw * 0.01745329238474369D - 3.141592653589793D); + double nc = -Math.cos(-rotPitch * 0.01745329238474369D); + double ns = Math.sin(-rotPitch * 0.01745329238474369D); + return new Vector3D(s * nc, ns, c * nc); + } + + public static enum ClampMode + { + ORTHOGONAL, DIRECT, NONE; + } + + + + public static class Line + { + public GLUProjection.Vector3D sourcePoint = new GLUProjection.Vector3D(0.0D, 0.0D, 0.0D); + public GLUProjection.Vector3D direction = new GLUProjection.Vector3D(0.0D, 0.0D, 0.0D); + + public Line(double sx, double sy, double sz, double dx, double dy, double dz) + { + sourcePoint.x = sx; + sourcePoint.y = sy; + sourcePoint.z = sz; + direction.x = dx; + direction.y = dy; + direction.z = dz; + } + + public GLUProjection.Vector3D intersect(Line line) + { + double a = sourcePoint.x; + double b = direction.x; + double c = sourcePoint.x; + double d = direction.x; + double e = sourcePoint.y; + double f = direction.y; + double g = sourcePoint.y; + double h = direction.y; + double te = -(a * h - c * h - d * (e - g)); + double be = b * h - d * f; + if (be == 0.0D) { + return intersectXZ(line); + } + double t = te / be; + GLUProjection.Vector3D result = new GLUProjection.Vector3D(0.0D, 0.0D, 0.0D); + x = (sourcePoint.x + direction.x * t); + y = (sourcePoint.y + direction.y * t); + z = (sourcePoint.z + direction.z * t); + return result; + } + + private GLUProjection.Vector3D intersectXZ(Line line) + { + double a = sourcePoint.x; + double b = direction.x; + double c = sourcePoint.x; + double d = direction.x; + double e = sourcePoint.z; + double f = direction.z; + double g = sourcePoint.z; + double h = direction.z; + double te = -(a * h - c * h - d * (e - g)); + double be = b * h - d * f; + if (be == 0.0D) { + return intersectYZ(line); + } + double t = te / be; + GLUProjection.Vector3D result = new GLUProjection.Vector3D(0.0D, 0.0D, 0.0D); + x = (sourcePoint.x + direction.x * t); + y = (sourcePoint.y + direction.y * t); + z = (sourcePoint.z + direction.z * t); + return result; + } + + private GLUProjection.Vector3D intersectYZ(Line line) + { + double a = sourcePoint.y; + double b = direction.y; + double c = sourcePoint.y; + double d = direction.y; + double e = sourcePoint.z; + double f = direction.z; + double g = sourcePoint.z; + double h = direction.z; + double te = -(a * h - c * h - d * (e - g)); + double be = b * h - d * f; + if (be == 0.0D) { + return null; + } + double t = te / be; + GLUProjection.Vector3D result = new GLUProjection.Vector3D(0.0D, 0.0D, 0.0D); + x = (sourcePoint.x + direction.x * t); + y = (sourcePoint.y + direction.y * t); + z = (sourcePoint.z + direction.z * t); + return result; + } + + public GLUProjection.Vector3D intersectPlane(GLUProjection.Vector3D pointOnPlane, GLUProjection.Vector3D planeNormal) + { + GLUProjection.Vector3D result = new GLUProjection.Vector3D(sourcePoint.x, sourcePoint.y, sourcePoint.z); + double d = pointOnPlane.sub(sourcePoint).dot(planeNormal) / direction.dot(planeNormal); + result.sadd(direction.mul(d)); + if (direction.dot(planeNormal) == 0.0D) { + return null; + } + return result; + } + } + + public static class Vector3D + { + public double x; + public double y; + public double z; + + public Vector3D(double x, double y, double z) + { + this.x = x; + this.y = y; + this.z = z; + } + + public Vector3D add(Vector3D v) + { + return new Vector3D(x + x, y + y, z + z); + } + + public Vector3D add(double x, double y, double z) + { + return new Vector3D(this.x + x, this.y + y, this.z + z); + } + + public Vector3D sub(Vector3D v) + { + return new Vector3D(x - x, y - y, z - z); + } + + public Vector3D sub(double x, double y, double z) + { + return new Vector3D(this.x - x, this.y - y, this.z - z); + } + + public Vector3D normalized() + { + double len = Math.sqrt(x * x + y * y + z * z); + return new Vector3D(x / len, y / len, z / len); + } + + public double dot(Vector3D v) + { + return x * x + y * y + z * z; + } + + public Vector3D cross(Vector3D v) + { + return new Vector3D(y * z - z * y, z * x - x * z, x * y - y * x); + } + + public Vector3D mul(double m) + { + return new Vector3D(x * m, y * m, z * m); + } + + public Vector3D div(double d) + { + return new Vector3D(x / d, y / d, z / d); + } + + public double length() + { + return Math.sqrt(x * x + y * y + z * z); + } + + public Vector3D sadd(Vector3D v) + { + x += x; + y += y; + z += z; + return this; + } + + public Vector3D sadd(double x, double y, double z) + { + this.x += x; + this.y += y; + this.z += z; + return this; + } + + public Vector3D ssub(Vector3D v) + { + x -= x; + y -= y; + z -= z; + return this; + } + + public Vector3D ssub(double x, double y, double z) + { + this.x -= x; + this.y -= y; + this.z -= z; + return this; + } + + public Vector3D snormalize() + { + double len = Math.sqrt(x * x + y * y + z * z); + x /= len; + y /= len; + z /= len; + return this; + } + + public Vector3D scross(Vector3D v) + { + x = (y * z - z * y); + y = (z * x - x * z); + z = (x * y - y * x); + return this; + } + + public Vector3D smul(double m) + { + x *= m; + y *= m; + z *= m; + return this; + } + + public Vector3D sdiv(double d) + { + x /= d; + y /= d; + z /= d; + return this; + } + + public String toString() + { + return "(X: " + x + " Y: " + y + " Z: " + z + ")"; + } + } + + public static class Projection + { + private final double x; + private final double y; + private final Type t; + + public Projection(double x, double y, Type t) + { + this.x = x; + this.y = y; + this.t = t; + } + + public double getX() + { + return x; + } + + public double getY() + { + return y; + } + + public Type getType() + { + return t; + } + + public boolean isType(Type type) + { + return t == type; + } + + public static enum Type + { + INSIDE, OUTSIDE, INVERTED, FAIL; + } + } +} diff --git a/src/minecraft/com/enjoytheban/utils/render/OutlineUtils.java b/src/minecraft/com/enjoytheban/utils/render/OutlineUtils.java new file mode 100644 index 0000000..1501184 --- /dev/null +++ b/src/minecraft/com/enjoytheban/utils/render/OutlineUtils.java @@ -0,0 +1,127 @@ +package com.enjoytheban.utils.render; + +import java.awt.Color; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.shader.Framebuffer; +import org.lwjgl.opengl.EXTFramebufferObject; +import org.lwjgl.opengl.GL11; + + +public class OutlineUtils +{ + public OutlineUtils() {} + + public static void renderOne() + { + checkSetupFBO(); + GL11.glPushAttrib(1048575); + GL11.glDisable(3008); + GL11.glDisable(3553); + GL11.glDisable(2896); + GL11.glEnable(3042); + GL11.glBlendFunc(770, 771); + GL11.glLineWidth(3.0F); + GL11.glEnable(2848); + GL11.glEnable(2960); + GL11.glClear(1024); + GL11.glClearStencil(15); + GL11.glStencilFunc(512, 1, 15); + GL11.glStencilOp(7681, 7681, 7681); + GL11.glPolygonMode(1032, 6913); + } + + public static void renderTwo() + { + GL11.glStencilFunc(512, 0, 15); + GL11.glStencilOp(7681, 7681, 7681); + GL11.glPolygonMode(1032, 6914); + } + + public static void renderThree() + { + GL11.glStencilFunc(514, 1, 15); + GL11.glStencilOp(7680, 7680, 7680); + GL11.glPolygonMode(1032, 6913); + } + + public static void renderFour() + { + setColor(new Color(255, 255, 255)); + GL11.glDepthMask(false); + GL11.glDisable(2929); + GL11.glEnable(10754); + GL11.glPolygonOffset(1.0F, -2000000.0F); + OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240.0F, 240.0F); + } + + public static void renderFive() + { + GL11.glPolygonOffset(1.0F, 2000000.0F); + GL11.glDisable(10754); + GL11.glEnable(2929); + GL11.glDepthMask(true); + GL11.glDisable(2960); + GL11.glDisable(2848); + GL11.glHint(3154, 4352); + GL11.glEnable(3042); + GL11.glEnable(2896); + GL11.glEnable(3553); + GL11.glEnable(3008); + GL11.glPopAttrib(); + } + + public static void setColor(Color c) + { + GL11.glColor4d(c.getRed() / 255.0F, c.getGreen() / 255.0F, c.getBlue() / 255.0F, c.getAlpha() / 255.0F); + } + + + public static void checkSetupFBO() + { + Framebuffer fbo = Minecraft.getMinecraft().getFramebuffer(); + + + if (fbo != null) + { + + if (depthBuffer > -1) + { + + setupFBO(fbo); + + depthBuffer = -1; + } + } + } + + + + + + + + + + public static void setupFBO(Framebuffer fbo) + { + EXTFramebufferObject.glDeleteRenderbuffersEXT(depthBuffer); + + int stencil_depth_buffer_ID = EXTFramebufferObject.glGenRenderbuffersEXT(); + + + EXTFramebufferObject.glBindRenderbufferEXT(36161, stencil_depth_buffer_ID); + + + + EXTFramebufferObject.glRenderbufferStorageEXT(36161, 34041, getMinecraftdisplayWidth, getMinecraftdisplayHeight); + + + + EXTFramebufferObject.glFramebufferRenderbufferEXT(36160, 36128, 36161, stencil_depth_buffer_ID); + + + + EXTFramebufferObject.glFramebufferRenderbufferEXT(36160, 36096, 36161, stencil_depth_buffer_ID); + } +} diff --git a/src/minecraft/com/enjoytheban/utils/render/RenderUtil.java b/src/minecraft/com/enjoytheban/utils/render/RenderUtil.java new file mode 100644 index 0000000..ec747fa --- /dev/null +++ b/src/minecraft/com/enjoytheban/utils/render/RenderUtil.java @@ -0,0 +1 @@ +null \ No newline at end of file diff --git a/src/minecraft/com/enjoytheban/utils/render/gl/GLClientState.java b/src/minecraft/com/enjoytheban/utils/render/gl/GLClientState.java new file mode 100644 index 0000000..12a3c2a --- /dev/null +++ b/src/minecraft/com/enjoytheban/utils/render/gl/GLClientState.java @@ -0,0 +1,41 @@ +package com.enjoytheban.utils.render.gl; + + + + + + + + + + +public enum GLClientState + implements GLenum +{ + COLOR("GL_COLOR_ARRAY", 32886), + EDGE("GL_EDGE_FLAG_ARRAY", 32889), + FOG("GL_FOG_COORD_ARRAY", 33879), + INDEX("GL_INDEX_ARRAY", 32887), + NORMAL("GL_NORMAL_ARRAY", 32885), + SECONDARY_COLOR("GL_SECONDARY_COLOR_ARRAY", 33886), + TEXTURE("GL_TEXTURE_COORD_ARRAY", 32888), + VERTEX("GL_VERTEX_ARRAY", 32884); + + private final String name; + private final int cap; + + private GLClientState(String name, int cap) { + this.name = name; + this.cap = cap; + } + + public String getName() + { + return name; + } + + public int getCap() + { + return cap; + } +} diff --git a/src/minecraft/com/enjoytheban/utils/render/gl/GLColor.java b/src/minecraft/com/enjoytheban/utils/render/gl/GLColor.java new file mode 100644 index 0000000..13f44fb --- /dev/null +++ b/src/minecraft/com/enjoytheban/utils/render/gl/GLColor.java @@ -0,0 +1,24 @@ +package com.enjoytheban.utils.render.gl; + +import org.lwjgl.opengl.GL11; + + + + + + + + +public class GLColor +{ + public GLColor() {} + + public static void color(int color) + { + float alpha = (color >> 24 & 0xFF) / 255.0F; + float red = (color >> 16 & 0xFF) / 255.0F; + float green = (color >> 8 & 0xFF) / 255.0F; + float blue = (color & 0xFF) / 255.0F; + GL11.glColor4f(red, green, blue, alpha); + } +} diff --git a/src/minecraft/com/enjoytheban/utils/render/gl/GLUtils.java b/src/minecraft/com/enjoytheban/utils/render/gl/GLUtils.java new file mode 100644 index 0000000..41c247c --- /dev/null +++ b/src/minecraft/com/enjoytheban/utils/render/gl/GLUtils.java @@ -0,0 +1,187 @@ +package com.enjoytheban.utils.render.gl; + +import com.enjoytheban.utils.math.Vec3f; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import net.minecraft.client.renderer.GlStateManager; +import org.lwjgl.BufferUtils; +import org.lwjgl.opengl.Display; +import org.lwjgl.util.glu.GLU; + + + + + + + + + + + + + + + +public final class GLUtils +{ + public static final FloatBuffer MODELVIEW = BufferUtils.createFloatBuffer(16); + public static final FloatBuffer PROJECTION = BufferUtils.createFloatBuffer(16); + public static final IntBuffer VIEWPORT = BufferUtils.createIntBuffer(16); + public static final FloatBuffer TO_SCREEN_BUFFER = BufferUtils.createFloatBuffer(3); + public static final FloatBuffer TO_WORLD_BUFFER = BufferUtils.createFloatBuffer(3); + + + + private GLUtils() {} + + + public static void init() {} + + + public static float[] getColor(int hex) + { + return new float[] { + (hex >> 16 & 0xFF) / 255.0F, + (hex >> 8 & 0xFF) / 255.0F, + (hex & 0xFF) / 255.0F, + (hex >> 24 & 0xFF) / 255.0F }; + } + + + + + + + public static void glColor(int hex) + { + float[] color = getColor(hex); + GlStateManager.color(color[0], color[1], color[2], color[3]); + } + + + + + + + + + + public static void rotateX(float angle, double x, double y, double z) + { + GlStateManager.translate(x, y, z); + GlStateManager.rotate(angle, 1.0F, 0.0F, 0.0F); + GlStateManager.translate(-x, -y, -z); + } + + + + + + + + + + public static void rotateY(float angle, double x, double y, double z) + { + GlStateManager.translate(x, y, z); + GlStateManager.rotate(angle, 0.0F, 1.0F, 0.0F); + GlStateManager.translate(-x, -y, -z); + } + + + + + + + + + + public static void rotateZ(float angle, double x, double y, double z) + { + GlStateManager.translate(x, y, z); + GlStateManager.rotate(angle, 0.0F, 0.0F, 1.0F); + GlStateManager.translate(-x, -y, -z); + } + + + + + + + + public static Vec3f toScreen(Vec3f pos) + { + return toScreen(pos.getX(), pos.getY(), pos.getZ()); + } + + + + + + + + + + public static Vec3f toScreen(double x, double y, double z) + { + boolean result = GLU.gluProject((float)x, (float)y, (float)z, MODELVIEW, PROJECTION, VIEWPORT, (FloatBuffer)TO_SCREEN_BUFFER.clear()); + if (result) { + return new Vec3f(TO_SCREEN_BUFFER.get(0), Display.getHeight() - TO_SCREEN_BUFFER.get(1), TO_SCREEN_BUFFER.get(2)); + } + return null; + } + + + + + + + + public static Vec3f toWorld(Vec3f pos) + { + return toWorld(pos.getX(), pos.getY(), pos.getZ()); + } + + + + + + + + + public static Vec3f toWorld(double x, double y, double z) + { + boolean result = GLU.gluUnProject((float)x, (float)y, (float)z, MODELVIEW, PROJECTION, VIEWPORT, (FloatBuffer)TO_WORLD_BUFFER.clear()); + if (result) { + return new Vec3f(TO_WORLD_BUFFER.get(0), TO_WORLD_BUFFER.get(1), TO_WORLD_BUFFER.get(2)); + } + return null; + } + + + + + + public static FloatBuffer getModelview() + { + return MODELVIEW; + } + + + + + + public static FloatBuffer getProjection() + { + return PROJECTION; + } + + + + + + public static IntBuffer getViewport() + { + return VIEWPORT; + } +} diff --git a/src/minecraft/com/enjoytheban/utils/render/gl/GLenum.java b/src/minecraft/com/enjoytheban/utils/render/gl/GLenum.java new file mode 100644 index 0000000..e750521 --- /dev/null +++ b/src/minecraft/com/enjoytheban/utils/render/gl/GLenum.java @@ -0,0 +1,8 @@ +package com.enjoytheban.utils.render.gl; + +public abstract interface GLenum +{ + public abstract String getName(); + + public abstract int getCap(); +} diff --git a/src/minecraft/com/google/common/annotations/Beta.java b/src/minecraft/com/google/common/annotations/Beta.java new file mode 100644 index 0000000..87ecd03 --- /dev/null +++ b/src/minecraft/com/google/common/annotations/Beta.java @@ -0,0 +1,13 @@ +package com.google.common.annotations; + +import java.lang.annotation.Annotation; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.CLASS) +@Target({java.lang.annotation.ElementType.ANNOTATION_TYPE, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.TYPE}) +@Documented +@GwtCompatible +public @interface Beta {} diff --git a/src/minecraft/com/google/common/annotations/GwtCompatible.java b/src/minecraft/com/google/common/annotations/GwtCompatible.java new file mode 100644 index 0000000..7ea6710 --- /dev/null +++ b/src/minecraft/com/google/common/annotations/GwtCompatible.java @@ -0,0 +1,18 @@ +package com.google.common.annotations; + +import java.lang.annotation.Annotation; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.CLASS) +@Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.METHOD}) +@Documented +@GwtCompatible +public @interface GwtCompatible +{ + boolean serializable() default false; + + boolean emulated() default false; +} diff --git a/src/minecraft/com/google/common/annotations/GwtIncompatible.java b/src/minecraft/com/google/common/annotations/GwtIncompatible.java new file mode 100644 index 0000000..321d5c5 --- /dev/null +++ b/src/minecraft/com/google/common/annotations/GwtIncompatible.java @@ -0,0 +1,16 @@ +package com.google.common.annotations; + +import java.lang.annotation.Annotation; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.CLASS) +@Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.FIELD}) +@Documented +@GwtCompatible +public @interface GwtIncompatible +{ + String value(); +} diff --git a/src/minecraft/com/google/common/annotations/VisibleForTesting.java b/src/minecraft/com/google/common/annotations/VisibleForTesting.java new file mode 100644 index 0000000..86df0c7 --- /dev/null +++ b/src/minecraft/com/google/common/annotations/VisibleForTesting.java @@ -0,0 +1,6 @@ +package com.google.common.annotations; + +import java.lang.annotation.Annotation; + +@GwtCompatible +public @interface VisibleForTesting {} diff --git a/src/minecraft/com/google/common/base/Absent.java b/src/minecraft/com/google/common/base/Absent.java new file mode 100644 index 0000000..9dddc37 --- /dev/null +++ b/src/minecraft/com/google/common/base/Absent.java @@ -0,0 +1,92 @@ +package com.google.common.base; + +import com.google.common.annotations.GwtCompatible; +import java.util.Collections; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +final class Absent + extends Optional +{ + static final Absent INSTANCE = new Absent(); + private static final long serialVersionUID = 0L; + + static Optional withType() { + return INSTANCE; + } + + private Absent() {} + + public boolean isPresent() { + return false; + } + + public T get() { + throw new IllegalStateException("Optional.get() cannot be called on an absent value"); + } + + public T or(T defaultValue) { + return Preconditions.checkNotNull(defaultValue, "use Optional.orNull() instead of Optional.or(null)"); + } + + public Optional or(Optional secondChoice) + { + return (Optional)Preconditions.checkNotNull(secondChoice); + } + + public T or(Supplier supplier) { + return Preconditions.checkNotNull(supplier.get(), "use Optional.orNull() instead of a Supplier that returns null"); + } + + @Nullable + public T orNull() { + return null; + } + + public Set asSet() { + return Collections.emptySet(); + } + + public Optional transform(Function function) { + Preconditions.checkNotNull(function); + return Optional.absent(); + } + + public boolean equals(@Nullable Object object) { + return object == this; + } + + public int hashCode() { + return 1502476572; + } + + public String toString() { + return "Optional.absent()"; + } + + private Object readResolve() { + return INSTANCE; + } +} diff --git a/src/minecraft/com/google/common/base/AbstractIterator.java b/src/minecraft/com/google/common/base/AbstractIterator.java new file mode 100644 index 0000000..b91724e --- /dev/null +++ b/src/minecraft/com/google/common/base/AbstractIterator.java @@ -0,0 +1,86 @@ +package com.google.common.base; + +import com.google.common.annotations.GwtCompatible; +import java.util.Iterator; +import java.util.NoSuchElementException; + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +abstract class AbstractIterator + implements Iterator +{ + private State state = State.NOT_READY; + private T next; + protected AbstractIterator() {} + + private static enum State { + READY, NOT_READY, DONE, FAILED; + + private State() {} + } + + protected abstract T computeNext(); + + protected final T endOfData() { + state = State.DONE; + return null; + } + + public final boolean hasNext() + { + Preconditions.checkState(state != State.FAILED); + switch (1.$SwitchMap$com$google$common$base$AbstractIterator$State[state.ordinal()]) { + case 1: + return false; + case 2: + return true; + } + + return tryToComputeNext(); + } + + private boolean tryToComputeNext() { + state = State.FAILED; + next = computeNext(); + if (state != State.DONE) { + state = State.READY; + return true; + } + return false; + } + + public final T next() + { + if (!hasNext()) { + throw new NoSuchElementException(); + } + state = State.NOT_READY; + T result = next; + next = null; + return result; + } + + public final void remove() { + throw new UnsupportedOperationException(); + } +} diff --git a/src/minecraft/com/google/common/base/Ascii.java b/src/minecraft/com/google/common/base/Ascii.java new file mode 100644 index 0000000..b9abb78 --- /dev/null +++ b/src/minecraft/com/google/common/base/Ascii.java @@ -0,0 +1,667 @@ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import javax.annotation.CheckReturnValue; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public final class Ascii +{ + public static final byte NUL = 0; + public static final byte SOH = 1; + public static final byte STX = 2; + public static final byte ETX = 3; + public static final byte EOT = 4; + public static final byte ENQ = 5; + public static final byte ACK = 6; + public static final byte BEL = 7; + public static final byte BS = 8; + public static final byte HT = 9; + public static final byte LF = 10; + public static final byte NL = 10; + public static final byte VT = 11; + public static final byte FF = 12; + public static final byte CR = 13; + public static final byte SO = 14; + public static final byte SI = 15; + public static final byte DLE = 16; + public static final byte DC1 = 17; + public static final byte XON = 17; + public static final byte DC2 = 18; + public static final byte DC3 = 19; + public static final byte XOFF = 19; + public static final byte DC4 = 20; + public static final byte NAK = 21; + public static final byte SYN = 22; + public static final byte ETB = 23; + public static final byte CAN = 24; + public static final byte EM = 25; + public static final byte SUB = 26; + public static final byte ESC = 27; + public static final byte FS = 28; + public static final byte GS = 29; + public static final byte RS = 30; + public static final byte US = 31; + public static final byte SP = 32; + public static final byte SPACE = 32; + public static final byte DEL = 127; + public static final char MIN = '\000'; + public static final char MAX = ''; + + private Ascii() {} + + public static String toLowerCase(String string) + { + int length = string.length(); + for (int i = 0; i < length; i++) { + if (isUpperCase(string.charAt(i))) { + char[] chars = string.toCharArray(); + for (; i < length; i++) { + char c = chars[i]; + if (isUpperCase(c)) { + chars[i] = ((char)(c ^ 0x20)); + } + } + return String.valueOf(chars); + } + } + return string; + } + + + + + + + + public static String toLowerCase(CharSequence chars) + { + if ((chars instanceof String)) { + return toLowerCase((String)chars); + } + int length = chars.length(); + StringBuilder builder = new StringBuilder(length); + for (int i = 0; i < length; i++) { + builder.append(toLowerCase(chars.charAt(i))); + } + return builder.toString(); + } + + + + + public static char toLowerCase(char c) + { + return isUpperCase(c) ? (char)(c ^ 0x20) : c; + } + + + + + + public static String toUpperCase(String string) + { + int length = string.length(); + for (int i = 0; i < length; i++) { + if (isLowerCase(string.charAt(i))) { + char[] chars = string.toCharArray(); + for (; i < length; i++) { + char c = chars[i]; + if (isLowerCase(c)) { + chars[i] = ((char)(c & 0x5F)); + } + } + return String.valueOf(chars); + } + } + return string; + } + + + + + + + + public static String toUpperCase(CharSequence chars) + { + if ((chars instanceof String)) { + return toUpperCase((String)chars); + } + int length = chars.length(); + StringBuilder builder = new StringBuilder(length); + for (int i = 0; i < length; i++) { + builder.append(toUpperCase(chars.charAt(i))); + } + return builder.toString(); + } + + + + + public static char toUpperCase(char c) + { + return isLowerCase(c) ? (char)(c & 0x5F) : c; + } + + + + + + + + public static boolean isLowerCase(char c) + { + return (c >= 'a') && (c <= 'z'); + } + + + + + + public static boolean isUpperCase(char c) + { + return (c >= 'A') && (c <= 'Z'); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @CheckReturnValue + @Beta + public static String truncate(CharSequence seq, int maxLength, String truncationIndicator) + { + Preconditions.checkNotNull(seq); + + + int truncationLength = maxLength - truncationIndicator.length(); + + + + Preconditions.checkArgument(truncationLength >= 0, "maxLength (%s) must be >= length of the truncation indicator (%s)", new Object[] { Integer.valueOf(maxLength), Integer.valueOf(truncationIndicator.length()) }); + + + + if (seq.length() <= maxLength) { + String string = seq.toString(); + if (string.length() <= maxLength) { + return string; + } + + seq = string; + } + + return truncationIndicator; + } + + + + + + + + + + + + + + + + + + + + + + + + + @Beta + public static boolean equalsIgnoreCase(CharSequence s1, CharSequence s2) + { + int length = s1.length(); + if (s1 == s2) { + return true; + } + if (length != s2.length()) { + return false; + } + for (int i = 0; i < length; i++) { + char c1 = s1.charAt(i); + char c2 = s2.charAt(i); + if (c1 != c2) + { + + int alphaIndex = getAlphaIndex(c1); + + + if ((alphaIndex >= 26) || (alphaIndex != getAlphaIndex(c2))) + { + + return false; } + } } + return true; + } + + + + + + + private static int getAlphaIndex(char c) + { + return (char)((c | 0x20) - 'a'); + } +} diff --git a/src/minecraft/com/google/common/base/CaseFormat.java b/src/minecraft/com/google/common/base/CaseFormat.java new file mode 100644 index 0000000..ff56c10 --- /dev/null +++ b/src/minecraft/com/google/common/base/CaseFormat.java @@ -0,0 +1,212 @@ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import java.io.Serializable; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public enum CaseFormat +{ + LOWER_HYPHEN(CharMatcher.is('-'), "-"), + + + + + + + + + + + + + + + + + + LOWER_UNDERSCORE(CharMatcher.is('_'), "_"), + + + + + + + + + + + + + + + + + + LOWER_CAMEL(CharMatcher.inRange('A', 'Z'), ""), + + + + + + + + + UPPER_CAMEL(CharMatcher.inRange('A', 'Z'), ""), + + + + + + + + + UPPER_UNDERSCORE(CharMatcher.is('_'), "_"); + + + + + + private final CharMatcher wordBoundary; + + + + + private final String wordSeparator; + + + + + + private CaseFormat(CharMatcher wordBoundary, String wordSeparator) + { + this.wordBoundary = wordBoundary; + this.wordSeparator = wordSeparator; + } + + + + + + public final String to(CaseFormat format, String str) + { + Preconditions.checkNotNull(format); + Preconditions.checkNotNull(str); + return format == this ? str : convert(format, str); + } + + + + + String convert(CaseFormat format, String s) + { + StringBuilder out = null; + int i = 0; + int j = -1; + while ((j = wordBoundary.indexIn(s, ++j)) != -1) { + if (i == 0) + { + out = new StringBuilder(s.length() + 4 * wordSeparator.length()); + out.append(format.normalizeFirstWord(s.substring(i, j))); + } else { + out.append(format.normalizeWord(s.substring(i, j))); + } + out.append(wordSeparator); + i = j + wordSeparator.length(); + } + return format.normalizeWord(s.substring(i)); + } + + + + + + + + + + @Beta + public Converter converterTo(CaseFormat targetFormat) { return new StringConverter(this, targetFormat); } + + abstract String normalizeWord(String paramString); + + private static final class StringConverter extends Converter implements Serializable { + private final CaseFormat sourceFormat; + private final CaseFormat targetFormat; + private static final long serialVersionUID = 0L; + + StringConverter(CaseFormat sourceFormat, CaseFormat targetFormat) { + this.sourceFormat = ((CaseFormat)Preconditions.checkNotNull(sourceFormat)); + this.targetFormat = ((CaseFormat)Preconditions.checkNotNull(targetFormat)); + } + + protected String doForward(String s) + { + return s == null ? null : sourceFormat.to(targetFormat, s); + } + + protected String doBackward(String s) + { + return s == null ? null : targetFormat.to(sourceFormat, s); + } + + public boolean equals(@Nullable Object object) { + if ((object instanceof StringConverter)) { + StringConverter that = (StringConverter)object; + return (sourceFormat.equals(sourceFormat)) && (targetFormat.equals(targetFormat)); + } + + return false; + } + + public int hashCode() { + return sourceFormat.hashCode() ^ targetFormat.hashCode(); + } + + public String toString() { + return sourceFormat + ".converterTo(" + targetFormat + ")"; + } + } + + + + + private String normalizeFirstWord(String word) + { + return this == LOWER_CAMEL ? Ascii.toLowerCase(word) : normalizeWord(word); + } + + private static String firstCharOnlyToUpper(String word) { + return word.length() + Ascii.toUpperCase(word.charAt(0)) + Ascii.toLowerCase(word.substring(1)); + } +} diff --git a/src/minecraft/com/google/common/base/CharMatcher.java b/src/minecraft/com/google/common/base/CharMatcher.java new file mode 100644 index 0000000..18f6a6e --- /dev/null +++ b/src/minecraft/com/google/common/base/CharMatcher.java @@ -0,0 +1,1387 @@ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import java.util.Arrays; +import java.util.BitSet; +import javax.annotation.CheckReturnValue; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible(emulated=true) +public abstract class CharMatcher + implements Predicate +{ + public static final CharMatcher BREAKING_WHITESPACE = new CharMatcher() + { + public boolean matches(char c) { + switch (c) { + case '\t': + case '\n': + case '\013': + case '\f': + case '\r': + case ' ': + case '…': + case ' ': + case '
': + case '
': + case ' ': + case ' ': + return true; + case ' ': + return false; + } + return (c >= ' ') && (c <= ' '); + } + + + public String toString() + { + return "CharMatcher.BREAKING_WHITESPACE"; + } + }; + + + + + public static final CharMatcher ASCII = inRange('\000', '', "CharMatcher.ASCII"); + private static final String ZEROES = "0٠۰߀०০੦૦୦௦౦೦൦๐໐༠၀႐០᠐᥆᧐᭐᮰᱀᱐꘠꣐꤀꩐0"; + private static final String NINES; + + private static class RangesMatcher extends CharMatcher { private final char[] rangeStarts; + private final char[] rangeEnds; + + RangesMatcher(String description, char[] rangeStarts, char[] rangeEnds) { super(); + this.rangeStarts = rangeStarts; + this.rangeEnds = rangeEnds; + Preconditions.checkArgument(rangeStarts.length == rangeEnds.length); + for (int i = 0; i < rangeStarts.length; i++) { + Preconditions.checkArgument(rangeStarts[i] <= rangeEnds[i]); + if (i + 1 < rangeStarts.length) { + Preconditions.checkArgument(rangeEnds[i] < rangeStarts[(i + 1)]); + } + } + } + + public boolean matches(char c) + { + int index = Arrays.binarySearch(rangeStarts, c); + if (index >= 0) { + return true; + } + index = (index ^ 0xFFFFFFFF) - 1; + return (index >= 0) && (c <= rangeEnds[index]); + } + } + + + + + + + + static + { + StringBuilder builder = new StringBuilder("0٠۰߀०০੦૦୦௦౦೦൦๐໐༠၀႐០᠐᥆᧐᭐᮰᱀᱐꘠꣐꤀꩐0".length()); + for (int i = 0; i < "0٠۰߀०০੦૦୦௦౦೦൦๐໐༠၀႐០᠐᥆᧐᭐᮰᱀᱐꘠꣐꤀꩐0".length(); i++) { + builder.append((char)("0٠۰߀०০੦૦୦௦౦೦൦๐໐༠၀႐០᠐᥆᧐᭐᮰᱀᱐꘠꣐꤀꩐0".charAt(i) + '\t')); + } + NINES = builder.toString(); + } + + + + + + + public static final CharMatcher DIGIT = new RangesMatcher("CharMatcher.DIGIT", "0٠۰߀०০੦૦୦௦౦೦൦๐໐༠၀႐០᠐᥆᧐᭐᮰᱀᱐꘠꣐꤀꩐0".toCharArray(), NINES.toCharArray()); + + + + + + + + public static final CharMatcher JAVA_DIGIT = new CharMatcher("CharMatcher.JAVA_DIGIT") { + public boolean matches(char c) { + return Character.isDigit(c); + } + }; + + + + + + + public static final CharMatcher JAVA_LETTER = new CharMatcher("CharMatcher.JAVA_LETTER") { + public boolean matches(char c) { + return Character.isLetter(c); + } + }; + + + + + + public static final CharMatcher JAVA_LETTER_OR_DIGIT = new CharMatcher("CharMatcher.JAVA_LETTER_OR_DIGIT") + { + public boolean matches(char c) { + return Character.isLetterOrDigit(c); + } + }; + + + + + + public static final CharMatcher JAVA_UPPER_CASE = new CharMatcher("CharMatcher.JAVA_UPPER_CASE") + { + public boolean matches(char c) { + return Character.isUpperCase(c); + } + }; + + + + + + public static final CharMatcher JAVA_LOWER_CASE = new CharMatcher("CharMatcher.JAVA_LOWER_CASE") + { + public boolean matches(char c) { + return Character.isLowerCase(c); + } + }; + + + + + + public static final CharMatcher JAVA_ISO_CONTROL = inRange('\000', '\037').or(inRange('', 'Ÿ')).withToString("CharMatcher.JAVA_ISO_CONTROL"); + + + + + + + + + + public static final CharMatcher INVISIBLE = new RangesMatcher("CharMatcher.INVISIBLE", "\000­؀؜۝܏ ᠎ 
 ⁦⁧⁨⁩ ?".toCharArray(), "  ­؄؜۝܏ ᠎‏ ⁤⁦⁧⁨⁩ ".toCharArray()); + + + + + private static String showCharacter(char c) + { + String hex = "0123456789ABCDEF"; + char[] tmp = { '\\', 'u', '\000', '\000', '\000', '\000' }; + for (int i = 0; i < 4; i++) { + tmp[(5 - i)] = hex.charAt(c & 0xF); + c = (char)(c >> '\004'); + } + return String.copyValueOf(tmp); + } + + + + + + + + + + + public static final CharMatcher SINGLE_WIDTH = new RangesMatcher("CharMatcher.SINGLE_WIDTH", "\000־א׳؀ݐ฀Ḁ℀ﭐﹰ。".toCharArray(), "ӹ־ת״ۿݿ๿₯℺﷿ᅵ".toCharArray()); + + + + + public static final CharMatcher ANY = new FastMatcher("CharMatcher.ANY") + { + public boolean matches(char c) { + return true; + } + + public int indexIn(CharSequence sequence) { + return sequence.length() == 0 ? -1 : 0; + } + + public int indexIn(CharSequence sequence, int start) { + int length = sequence.length(); + Preconditions.checkPositionIndex(start, length); + return start == length ? -1 : start; + } + + public int lastIndexIn(CharSequence sequence) { + return sequence.length() - 1; + } + + public boolean matchesAllOf(CharSequence sequence) { + Preconditions.checkNotNull(sequence); + return true; + } + + public boolean matchesNoneOf(CharSequence sequence) { + return sequence.length() == 0; + } + + public String removeFrom(CharSequence sequence) { + Preconditions.checkNotNull(sequence); + return ""; + } + + public String replaceFrom(CharSequence sequence, char replacement) { + char[] array = new char[sequence.length()]; + Arrays.fill(array, replacement); + return new String(array); + } + + public String replaceFrom(CharSequence sequence, CharSequence replacement) { + StringBuilder retval = new StringBuilder(sequence.length() * replacement.length()); + for (int i = 0; i < sequence.length(); i++) { + retval.append(replacement); + } + return retval.toString(); + } + + public String collapseFrom(CharSequence sequence, char replacement) { + return sequence.length() == 0 ? "" : String.valueOf(replacement); + } + + public String trimFrom(CharSequence sequence) { + Preconditions.checkNotNull(sequence); + return ""; + } + + public int countIn(CharSequence sequence) { + return sequence.length(); + } + + public CharMatcher and(CharMatcher other) { + return (CharMatcher)Preconditions.checkNotNull(other); + } + + public CharMatcher or(CharMatcher other) { + Preconditions.checkNotNull(other); + return this; + } + + public CharMatcher negate() { + return NONE; + } + }; + + + public static final CharMatcher NONE = new FastMatcher("CharMatcher.NONE") + { + public boolean matches(char c) { + return false; + } + + public int indexIn(CharSequence sequence) { + Preconditions.checkNotNull(sequence); + return -1; + } + + public int indexIn(CharSequence sequence, int start) { + int length = sequence.length(); + Preconditions.checkPositionIndex(start, length); + return -1; + } + + public int lastIndexIn(CharSequence sequence) { + Preconditions.checkNotNull(sequence); + return -1; + } + + public boolean matchesAllOf(CharSequence sequence) { + return sequence.length() == 0; + } + + public boolean matchesNoneOf(CharSequence sequence) { + Preconditions.checkNotNull(sequence); + return true; + } + + public String removeFrom(CharSequence sequence) { + return sequence.toString(); + } + + public String replaceFrom(CharSequence sequence, char replacement) { + return sequence.toString(); + } + + public String replaceFrom(CharSequence sequence, CharSequence replacement) { + Preconditions.checkNotNull(replacement); + return sequence.toString(); + } + + public String collapseFrom(CharSequence sequence, char replacement) { + return sequence.toString(); + } + + public String trimFrom(CharSequence sequence) { + return sequence.toString(); + } + + public String trimLeadingFrom(CharSequence sequence) + { + return sequence.toString(); + } + + public String trimTrailingFrom(CharSequence sequence) + { + return sequence.toString(); + } + + public int countIn(CharSequence sequence) { + Preconditions.checkNotNull(sequence); + return 0; + } + + public CharMatcher and(CharMatcher other) { + Preconditions.checkNotNull(other); + return this; + } + + public CharMatcher or(CharMatcher other) { + return (CharMatcher)Preconditions.checkNotNull(other); + } + + public CharMatcher negate() { + return ANY; + } + }; + final String description; + private static final int DISTINCT_CHARS = 65536; + static final String WHITESPACE_TABLE = "  \r…    
\013      \t     \f     
\n  "; + static final int WHITESPACE_MULTIPLIER = 1682554634; + + public static CharMatcher is(final char match) + { + String description = "CharMatcher.is('" + showCharacter(match) + "')"; + new FastMatcher(description) { + public boolean matches(char c) { + return c == match; + } + + public String replaceFrom(CharSequence sequence, char replacement) { + return sequence.toString().replace(match, replacement); + } + + public CharMatcher and(CharMatcher other) { + return other.matches(match) ? this : NONE; + } + + public CharMatcher or(CharMatcher other) { + return other.matches(match) ? other : super.or(other); + } + + public CharMatcher negate() { + return isNot(match); + } + + @GwtIncompatible("java.util.BitSet") + void setBits(BitSet table) + { + table.set(match); + } + }; + } + + + + + + public static CharMatcher isNot(final char match) + { + String description = "CharMatcher.isNot('" + showCharacter(match) + "')"; + new FastMatcher(description) { + public boolean matches(char c) { + return c != match; + } + + public CharMatcher and(CharMatcher other) { + return other.matches(match) ? super.and(other) : other; + } + + public CharMatcher or(CharMatcher other) { + return other.matches(match) ? ANY : this; + } + + @GwtIncompatible("java.util.BitSet") + void setBits(BitSet table) + { + table.set(0, match); + table.set(match + '\001', 65536); + } + + public CharMatcher negate() { + return is(match); + } + }; + } + + + + + public static CharMatcher anyOf(CharSequence sequence) + { + switch (sequence.length()) { + case 0: + return NONE; + case 1: + return is(sequence.charAt(0)); + case 2: + return isEither(sequence.charAt(0), sequence.charAt(1)); + } + + + + final char[] chars = sequence.toString().toCharArray(); + Arrays.sort(chars); + StringBuilder description = new StringBuilder("CharMatcher.anyOf(\""); + for (char c : chars) { + description.append(showCharacter(c)); + } + description.append("\")"); + new CharMatcher(description.toString()) { + public boolean matches(char c) { + return Arrays.binarySearch(chars, c) >= 0; + } + + @GwtIncompatible("java.util.BitSet") + void setBits(BitSet table) + { + for (char c : chars) { + table.set(c); + } + } + }; + } + + + private static CharMatcher isEither(final char match1, final char match2) + { + String description = "CharMatcher.anyOf(\"" + showCharacter(match1) + showCharacter(match2) + "\")"; + + new FastMatcher(description) { + public boolean matches(char c) { + return (c == match1) || (c == match2); + } + + @GwtIncompatible("java.util.BitSet") + void setBits(BitSet table) { + table.set(match1); + table.set(match2); + } + }; + } + + + + + public static CharMatcher noneOf(CharSequence sequence) + { + return anyOf(sequence).negate(); + } + + + + + + + + public static CharMatcher inRange(char startInclusive, char endInclusive) + { + Preconditions.checkArgument(endInclusive >= startInclusive); + String description = "CharMatcher.inRange('" + showCharacter(startInclusive) + "', '" + showCharacter(endInclusive) + "')"; + + + return inRange(startInclusive, endInclusive, description); + } + + static CharMatcher inRange(final char startInclusive, final char endInclusive, String description) + { + new FastMatcher(description) { + public boolean matches(char c) { + return (startInclusive <= c) && (c <= endInclusive); + } + + @GwtIncompatible("java.util.BitSet") + void setBits(BitSet table) { + table.set(startInclusive, endInclusive + '\001'); + } + }; + } + + + + + public static CharMatcher forPredicate(final Predicate predicate) + { + Preconditions.checkNotNull(predicate); + if ((predicate instanceof CharMatcher)) { + return (CharMatcher)predicate; + } + String description = "CharMatcher.forPredicate(" + predicate + ")"; + new CharMatcher(description) { + public boolean matches(char c) { + return predicate.apply(Character.valueOf(c)); + } + + public boolean apply(Character character) { + return predicate.apply(Preconditions.checkNotNull(character)); + } + }; + } + + + + + + + + + CharMatcher(String description) + { + this.description = description; + } + + + + + protected CharMatcher() + { + description = super.toString(); + } + + + + + + + + + + + public CharMatcher negate() + { + return new NegatedMatcher(this); + } + + private static class NegatedMatcher extends CharMatcher { + final CharMatcher original; + + NegatedMatcher(String toString, CharMatcher original) { + super(); + this.original = original; + } + + NegatedMatcher(CharMatcher original) { + this(original + ".negate()", original); + } + + public boolean matches(char c) { + return !original.matches(c); + } + + public boolean matchesAllOf(CharSequence sequence) { + return original.matchesNoneOf(sequence); + } + + public boolean matchesNoneOf(CharSequence sequence) { + return original.matchesAllOf(sequence); + } + + public int countIn(CharSequence sequence) { + return sequence.length() - original.countIn(sequence); + } + + @GwtIncompatible("java.util.BitSet") + void setBits(BitSet table) + { + BitSet tmp = new BitSet(); + original.setBits(tmp); + tmp.flip(0, 65536); + table.or(tmp); + } + + public CharMatcher negate() { + return original; + } + + CharMatcher withToString(String description) + { + return new NegatedMatcher(description, original); + } + } + + + + public CharMatcher and(CharMatcher other) + { + return new And(this, (CharMatcher)Preconditions.checkNotNull(other)); + } + + private static class And extends CharMatcher { + final CharMatcher first; + final CharMatcher second; + + And(CharMatcher a, CharMatcher b) { + this(a, b, "CharMatcher.and(" + a + ", " + b + ")"); + } + + And(CharMatcher a, CharMatcher b, String description) { + super(); + first = ((CharMatcher)Preconditions.checkNotNull(a)); + second = ((CharMatcher)Preconditions.checkNotNull(b)); + } + + public boolean matches(char c) + { + return (first.matches(c)) && (second.matches(c)); + } + + @GwtIncompatible("java.util.BitSet") + void setBits(BitSet table) + { + BitSet tmp1 = new BitSet(); + first.setBits(tmp1); + BitSet tmp2 = new BitSet(); + second.setBits(tmp2); + tmp1.and(tmp2); + table.or(tmp1); + } + + CharMatcher withToString(String description) + { + return new And(first, second, description); + } + } + + + + public CharMatcher or(CharMatcher other) + { + return new Or(this, (CharMatcher)Preconditions.checkNotNull(other)); + } + + private static class Or extends CharMatcher { + final CharMatcher first; + final CharMatcher second; + + Or(CharMatcher a, CharMatcher b, String description) { + super(); + first = ((CharMatcher)Preconditions.checkNotNull(a)); + second = ((CharMatcher)Preconditions.checkNotNull(b)); + } + + Or(CharMatcher a, CharMatcher b) { + this(a, b, "CharMatcher.or(" + a + ", " + b + ")"); + } + + @GwtIncompatible("java.util.BitSet") + void setBits(BitSet table) + { + first.setBits(table); + second.setBits(table); + } + + public boolean matches(char c) + { + return (first.matches(c)) || (second.matches(c)); + } + + CharMatcher withToString(String description) + { + return new Or(first, second, description); + } + } + + + + + + + + + + public CharMatcher precomputed() + { + return Platform.precomputeCharMatcher(this); + } + + + + + + + CharMatcher withToString(String description) + { + throw new UnsupportedOperationException(); + } + + + + + + + + + + + + + @GwtIncompatible("java.util.BitSet") + CharMatcher precomputedInternal() + { + BitSet table = new BitSet(); + setBits(table); + int totalCharacters = table.cardinality(); + if (totalCharacters * 2 <= 65536) { + return precomputedPositive(totalCharacters, table, description); + } + + table.flip(0, 65536); + int negatedCharacters = 65536 - totalCharacters; + String suffix = ".negate()"; + String negatedDescription = description + suffix; + + + return new NegatedFastMatcher(toString(), precomputedPositive(negatedCharacters, table, negatedDescription)); + } + + + + static abstract class FastMatcher + extends CharMatcher + { + FastMatcher() {} + + + + FastMatcher(String description) + { + super(); + } + + public final CharMatcher precomputed() + { + return this; + } + + public CharMatcher negate() + { + return new CharMatcher.NegatedFastMatcher(this); + } + } + + static final class NegatedFastMatcher extends CharMatcher.NegatedMatcher { + NegatedFastMatcher(CharMatcher original) { + super(); + } + + NegatedFastMatcher(String toString, CharMatcher original) { + super(original); + } + + public final CharMatcher precomputed() + { + return this; + } + + CharMatcher withToString(String description) + { + return new NegatedFastMatcher(description, original); + } + } + + + + + + + @GwtIncompatible("java.util.BitSet") + private static CharMatcher precomputedPositive(int totalCharacters, BitSet table, String description) + { + switch (totalCharacters) { + case 0: + return NONE; + case 1: + return is((char)table.nextSetBit(0)); + case 2: + char c1 = (char)table.nextSetBit(0); + char c2 = (char)table.nextSetBit(c1 + '\001'); + return isEither(c1, c2); + } + return isSmall(totalCharacters, table.length()) ? SmallCharMatcher.from(table, description) : new BitSetMatcher(table, description, null); + } + + + + @GwtIncompatible("SmallCharMatcher") + private static boolean isSmall(int totalCharacters, int tableLength) + { + return (totalCharacters <= 1023) && (tableLength > totalCharacters * 4 * 16); + } + + @GwtIncompatible("java.util.BitSet") + private static class BitSetMatcher extends CharMatcher.FastMatcher + { + private final BitSet table; + + private BitSetMatcher(BitSet table, String description) + { + super(); + if (table.length() + 64 < table.size()) { + table = (BitSet)table.clone(); + } + + this.table = table; + } + + public boolean matches(char c) { + return table.get(c); + } + + void setBits(BitSet bitSet) + { + bitSet.or(table); + } + } + + + + @GwtIncompatible("java.util.BitSet") + void setBits(BitSet table) + { + for (int c = 65535; c >= 0; c--) { + if (matches((char)c)) { + table.set(c); + } + } + } + + + + + + + + + + + + + + public boolean matchesAnyOf(CharSequence sequence) + { + return !matchesNoneOf(sequence); + } + + + + + + + + + + + public boolean matchesAllOf(CharSequence sequence) + { + for (int i = sequence.length() - 1; i >= 0; i--) { + if (!matches(sequence.charAt(i))) { + return false; + } + } + return true; + } + + + + + + + + + + + + public boolean matchesNoneOf(CharSequence sequence) + { + return indexIn(sequence) == -1; + } + + + + + + + + + + + public int indexIn(CharSequence sequence) + { + int length = sequence.length(); + for (int i = 0; i < length; i++) { + if (matches(sequence.charAt(i))) { + return i; + } + } + return -1; + } + + + + + + + + + + + + + + + + public int indexIn(CharSequence sequence, int start) + { + int length = sequence.length(); + Preconditions.checkPositionIndex(start, length); + for (int i = start; i < length; i++) { + if (matches(sequence.charAt(i))) { + return i; + } + } + return -1; + } + + + + + + + + + + + public int lastIndexIn(CharSequence sequence) + { + for (int i = sequence.length() - 1; i >= 0; i--) { + if (matches(sequence.charAt(i))) { + return i; + } + } + return -1; + } + + + + public int countIn(CharSequence sequence) + { + int count = 0; + for (int i = 0; i < sequence.length(); i++) { + if (matches(sequence.charAt(i))) { + count++; + } + } + return count; + } + + + + + + + + + @CheckReturnValue + public String removeFrom(CharSequence sequence) + { + String string = sequence.toString(); + int pos = indexIn(string); + if (pos == -1) { + return string; + } + + char[] chars = string.toCharArray(); + int spread = 1; + + for (;;) + { + pos++; + for (;;) { + if (pos == chars.length) { + break label79; + } + if (matches(chars[pos])) { + break; + } + chars[(pos - spread)] = chars[pos]; + pos++; + } + spread++; } + label79: + return new String(chars, 0, pos - spread); + } + + + + + + + + + @CheckReturnValue + public String retainFrom(CharSequence sequence) + { + return negate().removeFrom(sequence); + } + + + + + + + + + + + + + + + + + + @CheckReturnValue + public String replaceFrom(CharSequence sequence, char replacement) + { + String string = sequence.toString(); + int pos = indexIn(string); + if (pos == -1) { + return string; + } + char[] chars = string.toCharArray(); + chars[pos] = replacement; + for (int i = pos + 1; i < chars.length; i++) { + if (matches(chars[i])) { + chars[i] = replacement; + } + } + return new String(chars); + } + + + + + + + + + + + + + + + + + @CheckReturnValue + public String replaceFrom(CharSequence sequence, CharSequence replacement) + { + int replacementLen = replacement.length(); + if (replacementLen == 0) { + return removeFrom(sequence); + } + if (replacementLen == 1) { + return replaceFrom(sequence, replacement.charAt(0)); + } + + String string = sequence.toString(); + int pos = indexIn(string); + if (pos == -1) { + return string; + } + + int len = string.length(); + StringBuilder buf = new StringBuilder(len * 3 / 2 + 16); + + int oldpos = 0; + do { + buf.append(string, oldpos, pos); + buf.append(replacement); + oldpos = pos + 1; + pos = indexIn(string, oldpos); + } while (pos != -1); + + buf.append(string, oldpos, len); + return buf.toString(); + } + + + + + + + + + + + + + + + @CheckReturnValue + public String trimFrom(CharSequence sequence) + { + int len = sequence.length(); + + + + for (int first = 0; first < len; first++) { + if (!matches(sequence.charAt(first))) { + break; + } + } + for (int last = len - 1; last > first; last--) { + if (!matches(sequence.charAt(last))) { + break; + } + } + + return sequence.subSequence(first, last + 1).toString(); + } + + + + + + + + + @CheckReturnValue + public String trimLeadingFrom(CharSequence sequence) + { + int len = sequence.length(); + for (int first = 0; first < len; first++) { + if (!matches(sequence.charAt(first))) { + return sequence.subSequence(first, len).toString(); + } + } + return ""; + } + + + + + + + + + @CheckReturnValue + public String trimTrailingFrom(CharSequence sequence) + { + int len = sequence.length(); + for (int last = len - 1; last >= 0; last--) { + if (!matches(sequence.charAt(last))) { + return sequence.subSequence(0, last + 1).toString(); + } + } + return ""; + } + + + + + + + + + + + + + + + + + + + + @CheckReturnValue + public String collapseFrom(CharSequence sequence, char replacement) + { + int len = sequence.length(); + for (int i = 0; i < len; i++) { + char c = sequence.charAt(i); + if (matches(c)) { + if ((c == replacement) && ((i == len - 1) || (!matches(sequence.charAt(i + 1))))) + { + + i++; + } else { + StringBuilder builder = new StringBuilder(len).append(sequence.subSequence(0, i)).append(replacement); + + + return finishCollapseFrom(sequence, i + 1, len, replacement, builder, true); + } + } + } + + return sequence.toString(); + } + + + + + + + @CheckReturnValue + public String trimAndCollapseFrom(CharSequence sequence, char replacement) + { + int len = sequence.length(); + + + + for (int first = 0; (first < len) && (matches(sequence.charAt(first))); first++) {} + for (int last = len - 1; (last > first) && (matches(sequence.charAt(last))); last--) {} + + return (first == 0) && (last == len - 1) ? collapseFrom(sequence, replacement) : finishCollapseFrom(sequence, first, last + 1, replacement, new StringBuilder(last + 1 - first), false); + } + + + + + + + + private String finishCollapseFrom(CharSequence sequence, int start, int end, char replacement, StringBuilder builder, boolean inMatchingGroup) + { + for (int i = start; i < end; i++) { + char c = sequence.charAt(i); + if (matches(c)) { + if (!inMatchingGroup) { + builder.append(replacement); + inMatchingGroup = true; + } + } else { + builder.append(c); + inMatchingGroup = false; + } + } + return builder.toString(); + } + + + + + + @Deprecated + public boolean apply(Character character) + { + return matches(character.charValue()); + } + + + + + + public String toString() + { + return description; + } + + + + + + + + static final int WHITESPACE_SHIFT = Integer.numberOfLeadingZeros("  \r…    
\013      \t     \f     
\n  ".length() - 1); + + + + + + + + + + + + + public static final CharMatcher WHITESPACE = new FastMatcher("WHITESPACE") + { + public boolean matches(char c) { + return "  \r…    
\013      \t     \f     
\n  ".charAt(1682554634 * c >>> WHITESPACE_SHIFT) == c; + } + + @GwtIncompatible("java.util.BitSet") + void setBits(BitSet table) + { + for (int i = 0; i < "  \r…    
\013      \t     \f     
\n  ".length(); i++) { + table.set("  \r…    
\013      \t     \f     
\n  ".charAt(i)); + } + } + }; + + public abstract boolean matches(char paramChar); +} diff --git a/src/minecraft/com/google/common/base/Charsets.java b/src/minecraft/com/google/common/base/Charsets.java new file mode 100644 index 0000000..51169df --- /dev/null +++ b/src/minecraft/com/google/common/base/Charsets.java @@ -0,0 +1,84 @@ +package com.google.common.base; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import java.nio.charset.Charset; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public final class Charsets +{ + @GwtIncompatible("Non-UTF-8 Charset") + public static final Charset US_ASCII = Charset.forName("US-ASCII"); + + + + + + @GwtIncompatible("Non-UTF-8 Charset") + public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1"); + + + + + + public static final Charset UTF_8 = Charset.forName("UTF-8"); + + + + + + @GwtIncompatible("Non-UTF-8 Charset") + public static final Charset UTF_16BE = Charset.forName("UTF-16BE"); + + + + + + @GwtIncompatible("Non-UTF-8 Charset") + public static final Charset UTF_16LE = Charset.forName("UTF-16LE"); + + + + + + + @GwtIncompatible("Non-UTF-8 Charset") + public static final Charset UTF_16 = Charset.forName("UTF-16"); + + private Charsets() {} +} diff --git a/src/minecraft/com/google/common/base/Converter.java b/src/minecraft/com/google/common/base/Converter.java new file mode 100644 index 0000000..ffd2574 --- /dev/null +++ b/src/minecraft/com/google/common/base/Converter.java @@ -0,0 +1,493 @@ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import java.io.Serializable; +import java.util.Iterator; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +public abstract class Converter + implements Function +{ + private final boolean handleNullAutomatically; + private transient Converter reverse; + + protected Converter() + { + this(true); + } + + + + Converter(boolean handleNullAutomatically) + { + this.handleNullAutomatically = handleNullAutomatically; + } + + + + + + + + + + + protected abstract B doForward(A paramA); + + + + + + + + + + + protected abstract A doBackward(B paramB); + + + + + + + + + + + @Nullable + public final B convert(@Nullable A a) + { + return correctedDoForward(a); + } + + @Nullable + B correctedDoForward(@Nullable A a) { + if (handleNullAutomatically) + { + return a == null ? null : Preconditions.checkNotNull(doForward(a)); + } + return doForward(a); + } + + @Nullable + A correctedDoBackward(@Nullable B b) + { + if (handleNullAutomatically) + { + return b == null ? null : Preconditions.checkNotNull(doBackward(b)); + } + return doBackward(b); + } + + + + + + + + + + public Iterable convertAll(final Iterable fromIterable) + { + Preconditions.checkNotNull(fromIterable, "fromIterable"); + new Iterable() { + public Iterator iterator() { + new Iterator() { + private final Iterator fromIterator = val$fromIterable.iterator(); + + public boolean hasNext() + { + return fromIterator.hasNext(); + } + + public B next() + { + return convert(fromIterator.next()); + } + + public void remove() + { + fromIterator.remove(); + } + }; + } + }; + } + + + + + + + + public Converter reverse() + { + Converter result = reverse; + return result == null ? (this.reverse = new ReverseConverter(this)) : result; + } + + private static final class ReverseConverter extends Converter implements Serializable { + final Converter original; + private static final long serialVersionUID = 0L; + + ReverseConverter(Converter original) { + this.original = original; + } + + + + + + + + + protected A doForward(B b) + { + throw new AssertionError(); + } + + protected B doBackward(A a) + { + throw new AssertionError(); + } + + @Nullable + A correctedDoForward(@Nullable B b) + { + return original.correctedDoBackward(b); + } + + @Nullable + B correctedDoBackward(@Nullable A a) + { + return original.correctedDoForward(a); + } + + public Converter reverse() + { + return original; + } + + public boolean equals(@Nullable Object object) + { + if ((object instanceof ReverseConverter)) { + ReverseConverter that = (ReverseConverter)object; + return original.equals(original); + } + return false; + } + + public int hashCode() + { + return original.hashCode() ^ 0xFFFFFFFF; + } + + public String toString() + { + return original + ".reverse()"; + } + } + + + + + + + + + + public Converter andThen(Converter secondConverter) + { + return new ConverterComposition(this, (Converter)Preconditions.checkNotNull(secondConverter)); + } + + private static final class ConverterComposition extends Converter implements Serializable { + final Converter first; + final Converter second; + private static final long serialVersionUID = 0L; + + ConverterComposition(Converter first, Converter second) { + this.first = first; + this.second = second; + } + + + + + + + + + protected C doForward(A a) + { + throw new AssertionError(); + } + + protected A doBackward(C c) + { + throw new AssertionError(); + } + + @Nullable + C correctedDoForward(@Nullable A a) + { + return second.correctedDoForward(first.correctedDoForward(a)); + } + + @Nullable + A correctedDoBackward(@Nullable C c) + { + return first.correctedDoBackward(second.correctedDoBackward(c)); + } + + public boolean equals(@Nullable Object object) + { + if ((object instanceof ConverterComposition)) { + ConverterComposition that = (ConverterComposition)object; + return (first.equals(first)) && (second.equals(second)); + } + + return false; + } + + public int hashCode() + { + return 31 * first.hashCode() + second.hashCode(); + } + + public String toString() + { + return first + ".andThen(" + second + ")"; + } + } + + + + + + + @Deprecated + @Nullable + public final B apply(@Nullable A a) + { + return convert(a); + } + + + + + + + + + + + + + public boolean equals(@Nullable Object object) + { + return super.equals(object); + } + + + + + + + + + + + + + + + + + + + public static Converter from(Function forwardFunction, Function backwardFunction) + { + return new FunctionBasedConverter(forwardFunction, backwardFunction, null); + } + + private static final class FunctionBasedConverter + extends Converter implements Serializable + { + private final Function forwardFunction; + private final Function backwardFunction; + + private FunctionBasedConverter(Function forwardFunction, Function backwardFunction) + { + this.forwardFunction = ((Function)Preconditions.checkNotNull(forwardFunction)); + this.backwardFunction = ((Function)Preconditions.checkNotNull(backwardFunction)); + } + + protected B doForward(A a) + { + return forwardFunction.apply(a); + } + + protected A doBackward(B b) + { + return backwardFunction.apply(b); + } + + public boolean equals(@Nullable Object object) + { + if ((object instanceof FunctionBasedConverter)) { + FunctionBasedConverter that = (FunctionBasedConverter)object; + return (forwardFunction.equals(forwardFunction)) && (backwardFunction.equals(backwardFunction)); + } + + return false; + } + + public int hashCode() + { + return forwardFunction.hashCode() * 31 + backwardFunction.hashCode(); + } + + public String toString() + { + return "Converter.from(" + forwardFunction + ", " + backwardFunction + ")"; + } + } + + + + + public static Converter identity() + { + return IdentityConverter.INSTANCE; + } + + + private static final class IdentityConverter + extends Converter + implements Serializable + { + static final IdentityConverter INSTANCE = new IdentityConverter(); + + private IdentityConverter() {} + + protected T doForward(T t) { return t; } + + + protected T doBackward(T t) + { + return t; + } + + public IdentityConverter reverse() + { + return this; + } + + public Converter andThen(Converter otherConverter) + { + return (Converter)Preconditions.checkNotNull(otherConverter, "otherConverter"); + } + + + + private static final long serialVersionUID = 0L; + + + public String toString() + { + return "Converter.identity()"; + } + + private Object readResolve() { + return INSTANCE; + } + } +} diff --git a/src/minecraft/com/google/common/base/Defaults.java b/src/minecraft/com/google/common/base/Defaults.java new file mode 100644 index 0000000..bb9396e --- /dev/null +++ b/src/minecraft/com/google/common/base/Defaults.java @@ -0,0 +1,67 @@ +package com.google.common.base; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + + + + + + + + + + + + + + + + + + + + + + + + + + +public final class Defaults +{ + private static final Map, Object> DEFAULTS; + + static + { + Map, Object> map = new HashMap(); + put(map, Boolean.TYPE, Boolean.valueOf(false)); + put(map, Character.TYPE, Character.valueOf('\000')); + put(map, Byte.TYPE, Byte.valueOf((byte)0)); + put(map, Short.TYPE, Short.valueOf((short)0)); + put(map, Integer.TYPE, Integer.valueOf(0)); + put(map, Long.TYPE, Long.valueOf(0L)); + put(map, Float.TYPE, Float.valueOf(0.0F)); + put(map, Double.TYPE, Double.valueOf(0.0D)); + DEFAULTS = Collections.unmodifiableMap(map); + } + + private static void put(Map, Object> map, Class type, T value) { + map.put(type, value); + } + + + + + + + + public static T defaultValue(Class type) + { + T t = DEFAULTS.get(Preconditions.checkNotNull(type)); + return t; + } + + private Defaults() {} +} diff --git a/src/minecraft/com/google/common/base/Enums.java b/src/minecraft/com/google/common/base/Enums.java new file mode 100644 index 0000000..5c3480d --- /dev/null +++ b/src/minecraft/com/google/common/base/Enums.java @@ -0,0 +1,215 @@ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import java.io.Serializable; +import java.lang.ref.WeakReference; +import java.lang.reflect.Field; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; +import java.util.WeakHashMap; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +@Beta +public final class Enums +{ + private Enums() {} + + @GwtIncompatible("reflection") + public static Field getField(Enum enumValue) + { + Class clazz = enumValue.getDeclaringClass(); + try { + return clazz.getDeclaredField(enumValue.name()); + } catch (NoSuchFieldException impossible) { + throw new AssertionError(impossible); + } + } + + + + + + + + + + + + + + @Deprecated + public static > Function valueOfFunction(Class enumClass) + { + return new ValueOfFunction(enumClass, null); + } + + + private static final class ValueOfFunction> + implements Function, Serializable + { + private final Class enumClass; + + private static final long serialVersionUID = 0L; + + private ValueOfFunction(Class enumClass) + { + this.enumClass = ((Class)Preconditions.checkNotNull(enumClass)); + } + + public T apply(String value) + { + try { + return Enum.valueOf(enumClass, value); + } catch (IllegalArgumentException e) {} + return null; + } + + public boolean equals(@Nullable Object obj) + { + return ((obj instanceof ValueOfFunction)) && (enumClass.equals(enumClass)); + } + + public int hashCode() { + return enumClass.hashCode(); + } + + public String toString() { + return "Enums.valueOf(" + enumClass + ")"; + } + } + + + + + + + + + + + + public static > Optional getIfPresent(Class enumClass, String value) + { + Preconditions.checkNotNull(enumClass); + Preconditions.checkNotNull(value); + return Platform.getEnumIfPresent(enumClass, value); + } + + + @GwtIncompatible("java.lang.ref.WeakReference") + private static final Map>, Map>>> enumConstantCache = new WeakHashMap(); + + + @GwtIncompatible("java.lang.ref.WeakReference") + private static > Map>> populateCache(Class enumClass) + { + Map>> result = new HashMap(); + + for (T enumInstance : EnumSet.allOf(enumClass)) { + result.put(enumInstance.name(), new WeakReference(enumInstance)); + } + enumConstantCache.put(enumClass, result); + return result; + } + + @GwtIncompatible("java.lang.ref.WeakReference") + static > Map>> getEnumConstants(Class enumClass) + { + synchronized (enumConstantCache) { + Map>> constants = (Map)enumConstantCache.get(enumClass); + + if (constants == null) { + constants = populateCache(enumClass); + } + return constants; + } + } + + + + + + + + + public static > Converter stringConverter(Class enumClass) + { + return new StringConverter(enumClass); + } + + private static final class StringConverter> extends Converter implements Serializable + { + private final Class enumClass; + private static final long serialVersionUID = 0L; + + StringConverter(Class enumClass) { + this.enumClass = ((Class)Preconditions.checkNotNull(enumClass)); + } + + protected T doForward(String value) + { + return Enum.valueOf(enumClass, value); + } + + protected String doBackward(T enumValue) + { + return enumValue.name(); + } + + public boolean equals(@Nullable Object object) + { + if ((object instanceof StringConverter)) { + StringConverter that = (StringConverter)object; + return enumClass.equals(enumClass); + } + return false; + } + + public int hashCode() + { + return enumClass.hashCode(); + } + + public String toString() + { + return "Enums.stringConverter(" + enumClass.getName() + ".class)"; + } + } +} diff --git a/src/minecraft/com/google/common/base/Equivalence.java b/src/minecraft/com/google/common/base/Equivalence.java new file mode 100644 index 0000000..ddf9ecd --- /dev/null +++ b/src/minecraft/com/google/common/base/Equivalence.java @@ -0,0 +1,356 @@ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import java.io.Serializable; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public abstract class Equivalence +{ + protected Equivalence() {} + + public final boolean equivalent(@Nullable T a, @Nullable T b) + { + if (a == b) { + return true; + } + if ((a == null) || (b == null)) { + return false; + } + return doEquivalent(a, b); + } + + + + + + + + + + + + + + protected abstract boolean doEquivalent(T paramT1, T paramT2); + + + + + + + + + + + + + public final int hash(@Nullable T t) + { + if (t == null) { + return 0; + } + return doHash(t); + } + + + + + + + + + + + + + + + + + protected abstract int doHash(T paramT); + + + + + + + + + + + + + + + + public final Equivalence onResultOf(Function function) + { + return new FunctionalEquivalence(function, this); + } + + + + + + + + public final Wrapper wrap(@Nullable S reference) + { + return new Wrapper(this, reference, null); + } + + + + + + public static final class Wrapper + implements Serializable + { + private final Equivalence equivalence; + + + + @Nullable + private final T reference; + + + + private static final long serialVersionUID = 0L; + + + + + private Wrapper(Equivalence equivalence, @Nullable T reference) + { + this.equivalence = ((Equivalence)Preconditions.checkNotNull(equivalence)); + this.reference = reference; + } + + @Nullable + public T get() { + return reference; + } + + + + + + public boolean equals(@Nullable Object obj) + { + if (obj == this) { + return true; + } + if ((obj instanceof Wrapper)) { + Wrapper that = (Wrapper)obj; + + if (this.equivalence.equals(equivalence)) + { + + + + + Equivalence equivalence = this.equivalence; + return equivalence.equivalent(reference, reference); + } + } + return false; + } + + + + public int hashCode() + { + return equivalence.hash(reference); + } + + + + + public String toString() + { + return equivalence + ".wrap(" + reference + ")"; + } + } + + + + + + + + + + + + + + + + @GwtCompatible(serializable=true) + public final Equivalence> pairwise() + { + return new PairwiseEquivalence(this); + } + + + + + + + + + @Beta + public final Predicate equivalentTo(@Nullable T target) { return new EquivalentToPredicate(this, target); } + + private static final class EquivalentToPredicate implements Predicate, Serializable { + private final Equivalence equivalence; + @Nullable + private final T target; + private static final long serialVersionUID = 0L; + + EquivalentToPredicate(Equivalence equivalence, @Nullable T target) { + this.equivalence = ((Equivalence)Preconditions.checkNotNull(equivalence)); + this.target = target; + } + + public boolean apply(@Nullable T input) { + return equivalence.equivalent(input, target); + } + + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + if ((obj instanceof EquivalentToPredicate)) { + EquivalentToPredicate that = (EquivalentToPredicate)obj; + return (equivalence.equals(equivalence)) && (Objects.equal(target, target)); + } + + return false; + } + + public int hashCode() { + return Objects.hashCode(new Object[] { equivalence, target }); + } + + public String toString() { + return equivalence + ".equivalentTo(" + target + ")"; + } + } + + + + + + + + + + + + + public static Equivalence equals() + { + return Equals.INSTANCE; + } + + + + + + + + + public static Equivalence identity() + { + return Identity.INSTANCE; + } + + static final class Equals extends Equivalence implements Serializable { + Equals() {} + + static final Equals INSTANCE = new Equals(); + + + protected boolean doEquivalent(Object a, Object b) { return a.equals(b); } + + private static final long serialVersionUID = 1L; + public int doHash(Object o) { return o.hashCode(); } + + private Object readResolve() + { + return INSTANCE; + } + } + + static final class Identity extends Equivalence implements Serializable + { + Identity() {} + + static final Identity INSTANCE = new Identity(); + + protected boolean doEquivalent(Object a, Object b) { + return false; + } + + private static final long serialVersionUID = 1L; + protected int doHash(Object o) { return System.identityHashCode(o); } + + private Object readResolve() + { + return INSTANCE; + } + } +} diff --git a/src/minecraft/com/google/common/base/FinalizablePhantomReference.java b/src/minecraft/com/google/common/base/FinalizablePhantomReference.java new file mode 100644 index 0000000..3c57b2e --- /dev/null +++ b/src/minecraft/com/google/common/base/FinalizablePhantomReference.java @@ -0,0 +1,44 @@ +package com.google.common.base; + +import java.lang.ref.PhantomReference; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class FinalizablePhantomReference + extends PhantomReference + implements FinalizableReference +{ + protected FinalizablePhantomReference(T referent, FinalizableReferenceQueue queue) + { + super(referent, queue); + queue.cleanUp(); + } +} diff --git a/src/minecraft/com/google/common/base/FinalizableReference.java b/src/minecraft/com/google/common/base/FinalizableReference.java new file mode 100644 index 0000000..d2a27d1 --- /dev/null +++ b/src/minecraft/com/google/common/base/FinalizableReference.java @@ -0,0 +1,6 @@ +package com.google.common.base; + +public abstract interface FinalizableReference +{ + public abstract void finalizeReferent(); +} diff --git a/src/minecraft/com/google/common/base/FinalizableReferenceQueue.java b/src/minecraft/com/google/common/base/FinalizableReferenceQueue.java new file mode 100644 index 0000000..28daed4 --- /dev/null +++ b/src/minecraft/com/google/common/base/FinalizableReferenceQueue.java @@ -0,0 +1,358 @@ +package com.google.common.base; + +import com.google.common.annotations.VisibleForTesting; +import java.io.Closeable; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.lang.ref.PhantomReference; +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.logging.Level; +import java.util.logging.Logger; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class FinalizableReferenceQueue + implements Closeable +{ + private static final Logger logger = Logger.getLogger(FinalizableReferenceQueue.class.getName()); + private static final String FINALIZER_CLASS_NAME = "com.google.common.base.internal.Finalizer"; + private static final Method startFinalizer; + final ReferenceQueue queue; + final PhantomReference frqRef; + final boolean threadStarted; + + static { Class finalizer = loadFinalizer(new FinalizerLoader[] { new SystemLoader(), new DecoupledLoader(), new DirectLoader() }); + + startFinalizer = getStartFinalizer(finalizer); + } + + + + + + + + + + + + + + + + + public FinalizableReferenceQueue() + { + queue = new ReferenceQueue(); + frqRef = new PhantomReference(this, queue); + boolean threadStarted = false; + try { + startFinalizer.invoke(null, new Object[] { FinalizableReference.class, queue, frqRef }); + threadStarted = true; + } catch (IllegalAccessException impossible) { + throw new AssertionError(impossible); + } catch (Throwable t) { + logger.log(Level.INFO, "Failed to start reference finalizer thread. Reference cleanup will only occur when new references are created.", t); + } + + + this.threadStarted = threadStarted; + } + + public void close() + { + frqRef.enqueue(); + cleanUp(); + } + + + + + + void cleanUp() + { + if (threadStarted) { + return; + } + + Reference reference; + while ((reference = queue.poll()) != null) + { + + + + reference.clear(); + try { + ((FinalizableReference)reference).finalizeReferent(); + } catch (Throwable t) { + logger.log(Level.SEVERE, "Error cleaning up after reference.", t); + } + } + } + + + + + + private static Class loadFinalizer(FinalizerLoader... loaders) + { + for (FinalizerLoader loader : loaders) { + Class finalizer = loader.loadFinalizer(); + if (finalizer != null) { + return finalizer; + } + } + + throw new AssertionError(); + } + + + + + static abstract interface FinalizerLoader + { + public abstract Class loadFinalizer(); + } + + + + + static class SystemLoader + implements FinalizableReferenceQueue.FinalizerLoader + { + @VisibleForTesting + static boolean disabled; + + + + SystemLoader() {} + + + + public Class loadFinalizer() + { + if (disabled) { + return null; + } + ClassLoader systemLoader; + try { + systemLoader = ClassLoader.getSystemClassLoader(); + } catch (SecurityException e) { + FinalizableReferenceQueue.logger.info("Not allowed to access system class loader."); + return null; + } + if (systemLoader != null) { + try { + return systemLoader.loadClass("com.google.common.base.internal.Finalizer"); + } + catch (ClassNotFoundException e) { + return null; + } + } + return null; + } + } + + + + + + + static class DecoupledLoader + implements FinalizableReferenceQueue.FinalizerLoader + { + private static final String LOADING_ERROR = "Could not load Finalizer in its own class loader.Loading Finalizer in the current class loader instead. As a result, you will not be ableto garbage collect this class loader. To support reclaiming this class loader, eitherresolve the underlying issue, or move Google Collections to your system class path."; + + + + + + DecoupledLoader() {} + + + + + + public Class loadFinalizer() + { + try + { + ClassLoader finalizerLoader = newLoader(getBaseUrl()); + return finalizerLoader.loadClass("com.google.common.base.internal.Finalizer"); + } catch (Exception e) { + FinalizableReferenceQueue.logger.log(Level.WARNING, "Could not load Finalizer in its own class loader.Loading Finalizer in the current class loader instead. As a result, you will not be ableto garbage collect this class loader. To support reclaiming this class loader, eitherresolve the underlying issue, or move Google Collections to your system class path.", e); } + return null; + } + + + + + URL getBaseUrl() + throws IOException + { + String finalizerPath = "com.google.common.base.internal.Finalizer".replace('.', '/') + ".class"; + URL finalizerUrl = getClass().getClassLoader().getResource(finalizerPath); + if (finalizerUrl == null) { + throw new FileNotFoundException(finalizerPath); + } + + + String urlString = finalizerUrl.toString(); + if (!urlString.endsWith(finalizerPath)) { + throw new IOException("Unsupported path style: " + urlString); + } + urlString = urlString.substring(0, urlString.length() - finalizerPath.length()); + return new URL(finalizerUrl, urlString); + } + + + + + URLClassLoader newLoader(URL base) + { + return new URLClassLoader(new URL[] { base }, null); + } + } + + static class DirectLoader implements FinalizableReferenceQueue.FinalizerLoader + { + DirectLoader() {} + + public Class loadFinalizer() + { + try + { + return Class.forName("com.google.common.base.internal.Finalizer"); + } catch (ClassNotFoundException e) { + throw new AssertionError(e); + } + } + } + + + static Method getStartFinalizer(Class finalizer) + { + try + { + return finalizer.getMethod("startFinalizer", new Class[] { Class.class, ReferenceQueue.class, PhantomReference.class }); + + } + catch (NoSuchMethodException e) + { + + throw new AssertionError(e); + } + } +} diff --git a/src/minecraft/com/google/common/base/FinalizableSoftReference.java b/src/minecraft/com/google/common/base/FinalizableSoftReference.java new file mode 100644 index 0000000..f5b5329 --- /dev/null +++ b/src/minecraft/com/google/common/base/FinalizableSoftReference.java @@ -0,0 +1,42 @@ +package com.google.common.base; + +import java.lang.ref.SoftReference; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class FinalizableSoftReference + extends SoftReference + implements FinalizableReference +{ + protected FinalizableSoftReference(T referent, FinalizableReferenceQueue queue) + { + super(referent, queue); + queue.cleanUp(); + } +} diff --git a/src/minecraft/com/google/common/base/FinalizableWeakReference.java b/src/minecraft/com/google/common/base/FinalizableWeakReference.java new file mode 100644 index 0000000..97f1ff5 --- /dev/null +++ b/src/minecraft/com/google/common/base/FinalizableWeakReference.java @@ -0,0 +1,42 @@ +package com.google.common.base; + +import java.lang.ref.WeakReference; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class FinalizableWeakReference + extends WeakReference + implements FinalizableReference +{ + protected FinalizableWeakReference(T referent, FinalizableReferenceQueue queue) + { + super(referent, queue); + queue.cleanUp(); + } +} diff --git a/src/minecraft/com/google/common/base/Function.java b/src/minecraft/com/google/common/base/Function.java new file mode 100644 index 0000000..33d18a6 --- /dev/null +++ b/src/minecraft/com/google/common/base/Function.java @@ -0,0 +1,13 @@ +package com.google.common.base; + +import com.google.common.annotations.GwtCompatible; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract interface Function +{ + @Nullable + public abstract T apply(@Nullable F paramF); + + public abstract boolean equals(@Nullable Object paramObject); +} diff --git a/src/minecraft/com/google/common/base/FunctionalEquivalence.java b/src/minecraft/com/google/common/base/FunctionalEquivalence.java new file mode 100644 index 0000000..4bb54fd --- /dev/null +++ b/src/minecraft/com/google/common/base/FunctionalEquivalence.java @@ -0,0 +1,77 @@ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import java.io.Serializable; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +final class FunctionalEquivalence + extends Equivalence + implements Serializable +{ + private static final long serialVersionUID = 0L; + private final Function function; + private final Equivalence resultEquivalence; + + FunctionalEquivalence(Function function, Equivalence resultEquivalence) + { + this.function = ((Function)Preconditions.checkNotNull(function)); + this.resultEquivalence = ((Equivalence)Preconditions.checkNotNull(resultEquivalence)); + } + + protected boolean doEquivalent(F a, F b) { + return resultEquivalence.equivalent(function.apply(a), function.apply(b)); + } + + protected int doHash(F a) { + return resultEquivalence.hash(function.apply(a)); + } + + public boolean equals(@Nullable Object obj) { + if (obj == this) { + return true; + } + if ((obj instanceof FunctionalEquivalence)) { + FunctionalEquivalence that = (FunctionalEquivalence)obj; + return (function.equals(function)) && (resultEquivalence.equals(resultEquivalence)); + } + + return false; + } + + public int hashCode() { + return Objects.hashCode(new Object[] { function, resultEquivalence }); + } + + public String toString() { + return resultEquivalence + ".onResultOf(" + function + ")"; + } +} diff --git a/src/minecraft/com/google/common/base/Functions.java b/src/minecraft/com/google/common/base/Functions.java new file mode 100644 index 0000000..5eb2fbc --- /dev/null +++ b/src/minecraft/com/google/common/base/Functions.java @@ -0,0 +1,361 @@ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import java.io.Serializable; +import java.util.Map; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public final class Functions +{ + private Functions() {} + + public static Function toStringFunction() + { + return ToStringFunction.INSTANCE; + } + + private static enum ToStringFunction implements Function + { + INSTANCE; + + private ToStringFunction() {} + + public String apply(Object o) { Preconditions.checkNotNull(o); + return o.toString(); + } + + public String toString() { + return "toString"; + } + } + + + + + + public static Function identity() + { + return IdentityFunction.INSTANCE; + } + + private static enum IdentityFunction implements Function + { + INSTANCE; + + private IdentityFunction() {} + + @Nullable + public Object apply(@Nullable Object o) { return o; } + + public String toString() + { + return "identity"; + } + } + + + + + + + + + + public static Function forMap(Map map) + { + return new FunctionForMapNoDefault(map); + } + + private static class FunctionForMapNoDefault implements Function, Serializable { + final Map map; + private static final long serialVersionUID = 0L; + + FunctionForMapNoDefault(Map map) { this.map = ((Map)Preconditions.checkNotNull(map)); } + + + public V apply(@Nullable K key) + { + V result = map.get(key); + Preconditions.checkArgument((result != null) || (map.containsKey(key)), "Key '%s' not present in map", new Object[] { key }); + return result; + } + + public boolean equals(@Nullable Object o) { + if ((o instanceof FunctionForMapNoDefault)) { + FunctionForMapNoDefault that = (FunctionForMapNoDefault)o; + return map.equals(map); + } + return false; + } + + public int hashCode() { + return map.hashCode(); + } + + public String toString() { + return "forMap(" + map + ")"; + } + } + + + + + + + + + + + + + + + public static Function forMap(Map map, @Nullable V defaultValue) { return new ForMapWithDefault(map, defaultValue); } + + private static class ForMapWithDefault implements Function, Serializable { + final Map map; + final V defaultValue; + private static final long serialVersionUID = 0L; + + ForMapWithDefault(Map map, @Nullable V defaultValue) { + this.map = ((Map)Preconditions.checkNotNull(map)); + this.defaultValue = defaultValue; + } + + public V apply(@Nullable K key) + { + V result = map.get(key); + return (result != null) || (map.containsKey(key)) ? result : defaultValue; + } + + public boolean equals(@Nullable Object o) { + if ((o instanceof ForMapWithDefault)) { + ForMapWithDefault that = (ForMapWithDefault)o; + return (map.equals(map)) && (Objects.equal(defaultValue, defaultValue)); + } + return false; + } + + public int hashCode() { + return Objects.hashCode(new Object[] { map, defaultValue }); + } + + public String toString() { + return "forMap(" + map + ", defaultValue=" + defaultValue + ")"; + } + } + + + + + + + + + + + + + + public static Function compose(Function g, Function f) { return new FunctionComposition(g, f); } + + private static class FunctionComposition implements Function, Serializable { + private final Function g; + private final Function f; + private static final long serialVersionUID = 0L; + + public FunctionComposition(Function g, Function f) { + this.g = ((Function)Preconditions.checkNotNull(g)); + this.f = ((Function)Preconditions.checkNotNull(f)); + } + + public C apply(@Nullable A a) + { + return g.apply(f.apply(a)); + } + + public boolean equals(@Nullable Object obj) { + if ((obj instanceof FunctionComposition)) { + FunctionComposition that = (FunctionComposition)obj; + return (f.equals(f)) && (g.equals(g)); + } + return false; + } + + public int hashCode() { + return f.hashCode() ^ g.hashCode(); + } + + public String toString() { + return g + "(" + f + ")"; + } + } + + + + + + + + + public static Function forPredicate(Predicate predicate) + { + return new PredicateFunction(predicate, null); + } + + private static class PredicateFunction implements Function, Serializable { + private final Predicate predicate; + private static final long serialVersionUID = 0L; + + private PredicateFunction(Predicate predicate) { + this.predicate = ((Predicate)Preconditions.checkNotNull(predicate)); + } + + public Boolean apply(@Nullable T t) + { + return Boolean.valueOf(predicate.apply(t)); + } + + public boolean equals(@Nullable Object obj) { + if ((obj instanceof PredicateFunction)) { + PredicateFunction that = (PredicateFunction)obj; + return predicate.equals(predicate); + } + return false; + } + + public int hashCode() { + return predicate.hashCode(); + } + + public String toString() { + return "forPredicate(" + predicate + ")"; + } + } + + + + + + + + + public static Function constant(@Nullable E value) + { + return new ConstantFunction(value); + } + + private static class ConstantFunction implements Function, Serializable { + private final E value; + private static final long serialVersionUID = 0L; + + public ConstantFunction(@Nullable E value) { this.value = value; } + + + public E apply(@Nullable Object from) + { + return value; + } + + public boolean equals(@Nullable Object obj) { + if ((obj instanceof ConstantFunction)) { + ConstantFunction that = (ConstantFunction)obj; + return Objects.equal(value, value); + } + return false; + } + + public int hashCode() { + return value == null ? 0 : value.hashCode(); + } + + public String toString() { + return "constant(" + value + ")"; + } + } + + + + + + + + + @Beta + public static Function forSupplier(Supplier supplier) + { + return new SupplierFunction(supplier, null); + } + + private static class SupplierFunction implements Function, Serializable + { + private final Supplier supplier; + private static final long serialVersionUID = 0L; + + private SupplierFunction(Supplier supplier) { + this.supplier = ((Supplier)Preconditions.checkNotNull(supplier)); + } + + public T apply(@Nullable Object input) { + return supplier.get(); + } + + public boolean equals(@Nullable Object obj) { + if ((obj instanceof SupplierFunction)) { + SupplierFunction that = (SupplierFunction)obj; + return supplier.equals(supplier); + } + return false; + } + + public int hashCode() { + return supplier.hashCode(); + } + + public String toString() { + return "forSupplier(" + supplier + ")"; + } + } +} diff --git a/src/minecraft/com/google/common/base/Joiner.java b/src/minecraft/com/google/common/base/Joiner.java new file mode 100644 index 0000000..ec747fa --- /dev/null +++ b/src/minecraft/com/google/common/base/Joiner.java @@ -0,0 +1 @@ +null \ No newline at end of file diff --git a/src/minecraft/com/google/common/base/Objects.java b/src/minecraft/com/google/common/base/Objects.java new file mode 100644 index 0000000..8b5ce1f --- /dev/null +++ b/src/minecraft/com/google/common/base/Objects.java @@ -0,0 +1,435 @@ +package com.google.common.base; + +import com.google.common.annotations.GwtCompatible; +import java.util.Arrays; +import javax.annotation.CheckReturnValue; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public final class Objects +{ + private Objects() {} + + @CheckReturnValue + public static boolean equal(@Nullable Object a, @Nullable Object b) + { + return (a == b) || ((a != null) && (a.equals(b))); + } + + + + + + + + + + + + + + + + + + public static int hashCode(@Nullable Object... objects) + { + return Arrays.hashCode(objects); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static ToStringHelper toStringHelper(Object self) + { + return new ToStringHelper(simpleName(self.getClass()), null); + } + + + + + + + + + + + public static ToStringHelper toStringHelper(Class clazz) + { + return new ToStringHelper(simpleName(clazz), null); + } + + + + + + + + + public static ToStringHelper toStringHelper(String className) + { + return new ToStringHelper(className, null); + } + + + + + private static String simpleName(Class clazz) + { + String name = clazz.getName(); + + + + name = name.replaceAll("\\$[0-9]+", "\\$"); + + + int start = name.lastIndexOf('$'); + + + + if (start == -1) { + start = name.lastIndexOf('.'); + } + return name.substring(start + 1); + } + + + + + + + + + + + + + + + + + + public static T firstNonNull(@Nullable T first, @Nullable T second) + { + return first != null ? first : Preconditions.checkNotNull(second); + } + + + + + public static final class ToStringHelper + { + private final String className; + + + private ValueHolder holderHead = new ValueHolder(null); + private ValueHolder holderTail = holderHead; + private boolean omitNullValues = false; + + + + private ToStringHelper(String className) + { + this.className = ((String)Preconditions.checkNotNull(className)); + } + + + + + + + + public ToStringHelper omitNullValues() + { + omitNullValues = true; + return this; + } + + + + + + + public ToStringHelper add(String name, @Nullable Object value) + { + return addHolder(name, value); + } + + + + + + + public ToStringHelper add(String name, boolean value) + { + return addHolder(name, String.valueOf(value)); + } + + + + + + + public ToStringHelper add(String name, char value) + { + return addHolder(name, String.valueOf(value)); + } + + + + + + + public ToStringHelper add(String name, double value) + { + return addHolder(name, String.valueOf(value)); + } + + + + + + + public ToStringHelper add(String name, float value) + { + return addHolder(name, String.valueOf(value)); + } + + + + + + + public ToStringHelper add(String name, int value) + { + return addHolder(name, String.valueOf(value)); + } + + + + + + + public ToStringHelper add(String name, long value) + { + return addHolder(name, String.valueOf(value)); + } + + + + + + + public ToStringHelper addValue(@Nullable Object value) + { + return addHolder(value); + } + + + + + + + + + public ToStringHelper addValue(boolean value) + { + return addHolder(String.valueOf(value)); + } + + + + + + + + + public ToStringHelper addValue(char value) + { + return addHolder(String.valueOf(value)); + } + + + + + + + + + public ToStringHelper addValue(double value) + { + return addHolder(String.valueOf(value)); + } + + + + + + + + + public ToStringHelper addValue(float value) + { + return addHolder(String.valueOf(value)); + } + + + + + + + + + public ToStringHelper addValue(int value) + { + return addHolder(String.valueOf(value)); + } + + + + + + + + + public ToStringHelper addValue(long value) + { + return addHolder(String.valueOf(value)); + } + + + + + + + + + + + + public String toString() + { + boolean omitNullValuesSnapshot = omitNullValues; + String nextSeparator = ""; + StringBuilder builder = new StringBuilder(32).append(className).append('{'); + + for (ValueHolder valueHolder = holderHead.next; valueHolder != null; + valueHolder = next) { + if ((!omitNullValuesSnapshot) || (value != null)) { + builder.append(nextSeparator); + nextSeparator = ", "; + + if (name != null) { + builder.append(name).append('='); + } + builder.append(value); + } + } + return '}'; + } + + private ValueHolder addHolder() { + ValueHolder valueHolder = new ValueHolder(null); + holderTail = (holderTail.next = valueHolder); + return valueHolder; + } + + private ToStringHelper addHolder(@Nullable Object value) { + ValueHolder valueHolder = addHolder(); + value = value; + return this; + } + + private ToStringHelper addHolder(String name, @Nullable Object value) { + ValueHolder valueHolder = addHolder(); + value = value; + name = ((String)Preconditions.checkNotNull(name)); + return this; + } + + private static final class ValueHolder + { + String name; + Object value; + ValueHolder next; + + private ValueHolder() {} + } + } +} diff --git a/src/minecraft/com/google/common/base/Optional.java b/src/minecraft/com/google/common/base/Optional.java new file mode 100644 index 0000000..a7cb675 --- /dev/null +++ b/src/minecraft/com/google/common/base/Optional.java @@ -0,0 +1,240 @@ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import java.io.Serializable; +import java.util.Iterator; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true) +public abstract class Optional + implements Serializable +{ + private static final long serialVersionUID = 0L; + + public static Optional absent() + { + return Absent.withType(); + } + + + + public static Optional of(T reference) + { + return new Present(Preconditions.checkNotNull(reference)); + } + + + + + public static Optional fromNullable(@Nullable T nullableReference) + { + return nullableReference == null ? absent() : new Present(nullableReference); + } + + + + + + + + + + Optional() {} + + + + + + + + + + public abstract boolean isPresent(); + + + + + + + + + public abstract T get(); + + + + + + + + + public abstract T or(T paramT); + + + + + + + + + public abstract Optional or(Optional paramOptional); + + + + + + + + + @Beta + public abstract T or(Supplier paramSupplier); + + + + + + + + + @Nullable + public abstract T orNull(); + + + + + + + + + public abstract Set asSet(); + + + + + + + + + public abstract Optional transform(Function paramFunction); + + + + + + + + + public abstract boolean equals(@Nullable Object paramObject); + + + + + + + + + public abstract int hashCode(); + + + + + + + + + public abstract String toString(); + + + + + + + + + @Beta + public static Iterable presentInstances(Iterable> optionals) + { + Preconditions.checkNotNull(optionals); + new Iterable() + { + public Iterator iterator() { + new AbstractIterator() { + private final Iterator> iterator = (Iterator)Preconditions.checkNotNull(val$optionals.iterator()); + + + protected T computeNext() + { + while (iterator.hasNext()) { + Optional optional = (Optional)iterator.next(); + if (optional.isPresent()) { + return optional.get(); + } + } + return endOfData(); + } + }; + } + }; + } +} diff --git a/src/minecraft/com/google/common/base/PairwiseEquivalence.java b/src/minecraft/com/google/common/base/PairwiseEquivalence.java new file mode 100644 index 0000000..2f1a129 --- /dev/null +++ b/src/minecraft/com/google/common/base/PairwiseEquivalence.java @@ -0,0 +1,78 @@ +package com.google.common.base; + +import com.google.common.annotations.GwtCompatible; +import java.io.Serializable; +import java.util.Iterator; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true) +final class PairwiseEquivalence + extends Equivalence> + implements Serializable +{ + final Equivalence elementEquivalence; + private static final long serialVersionUID = 1L; + + PairwiseEquivalence(Equivalence elementEquivalence) + { + this.elementEquivalence = ((Equivalence)Preconditions.checkNotNull(elementEquivalence)); + } + + protected boolean doEquivalent(Iterable iterableA, Iterable iterableB) + { + Iterator iteratorA = iterableA.iterator(); + Iterator iteratorB = iterableB.iterator(); + + while ((iteratorA.hasNext()) && (iteratorB.hasNext())) { + if (!elementEquivalence.equivalent(iteratorA.next(), iteratorB.next())) { + return false; + } + } + + return (!iteratorA.hasNext()) && (!iteratorB.hasNext()); + } + + protected int doHash(Iterable iterable) + { + int hash = 78721; + for (T element : iterable) { + hash = hash * 24943 + elementEquivalence.hash(element); + } + return hash; + } + + public boolean equals(@Nullable Object object) + { + if ((object instanceof PairwiseEquivalence)) { + PairwiseEquivalence that = (PairwiseEquivalence)object; + return elementEquivalence.equals(elementEquivalence); + } + + return false; + } + + public int hashCode() + { + return elementEquivalence.hashCode() ^ 0x46A3EB07; + } + + public String toString() + { + return elementEquivalence + ".pairwise()"; + } +} diff --git a/src/minecraft/com/google/common/base/Platform.java b/src/minecraft/com/google/common/base/Platform.java new file mode 100644 index 0000000..34ff62e --- /dev/null +++ b/src/minecraft/com/google/common/base/Platform.java @@ -0,0 +1,45 @@ +package com.google.common.base; + +import com.google.common.annotations.GwtCompatible; +import java.lang.ref.WeakReference; +import java.util.Map; + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +final class Platform +{ + private Platform() {} + + static long systemNanoTime() + { + return System.nanoTime(); + } + + static CharMatcher precomputeCharMatcher(CharMatcher matcher) { + return matcher.precomputedInternal(); + } + + static > Optional getEnumIfPresent(Class enumClass, String value) { + WeakReference> ref = (WeakReference)Enums.getEnumConstants(enumClass).get(value); + return ref == null ? Optional.absent() : Optional.of(enumClass.cast(ref.get())); + } +} diff --git a/src/minecraft/com/google/common/base/Preconditions.java b/src/minecraft/com/google/common/base/Preconditions.java new file mode 100644 index 0000000..0f80e1e --- /dev/null +++ b/src/minecraft/com/google/common/base/Preconditions.java @@ -0,0 +1,443 @@ +package com.google.common.base; + +import com.google.common.annotations.GwtCompatible; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public final class Preconditions +{ + private Preconditions() {} + + public static void checkArgument(boolean expression) + { + if (!expression) { + throw new IllegalArgumentException(); + } + } + + + + + + + + + public static void checkArgument(boolean expression, @Nullable Object errorMessage) + { + if (!expression) { + throw new IllegalArgumentException(String.valueOf(errorMessage)); + } + } + + + + + + + + + + + + + + + + + + public static void checkArgument(boolean expression, @Nullable String errorMessageTemplate, @Nullable Object... errorMessageArgs) + { + if (!expression) { + throw new IllegalArgumentException(format(errorMessageTemplate, errorMessageArgs)); + } + } + + + + + + + + public static void checkState(boolean expression) + { + if (!expression) { + throw new IllegalStateException(); + } + } + + + + + + + + + + public static void checkState(boolean expression, @Nullable Object errorMessage) + { + if (!expression) { + throw new IllegalStateException(String.valueOf(errorMessage)); + } + } + + + + + + + + + + + + + + + + + + + public static void checkState(boolean expression, @Nullable String errorMessageTemplate, @Nullable Object... errorMessageArgs) + { + if (!expression) { + throw new IllegalStateException(format(errorMessageTemplate, errorMessageArgs)); + } + } + + + + + + + + public static T checkNotNull(T reference) + { + if (reference == null) { + throw new NullPointerException(); + } + return reference; + } + + + + + + + + + + public static T checkNotNull(T reference, @Nullable Object errorMessage) + { + if (reference == null) { + throw new NullPointerException(String.valueOf(errorMessage)); + } + return reference; + } + + + + + + + + + + + + + + + + + public static T checkNotNull(T reference, @Nullable String errorMessageTemplate, @Nullable Object... errorMessageArgs) + { + if (reference == null) + { + throw new NullPointerException(format(errorMessageTemplate, errorMessageArgs)); + } + return reference; + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static int checkElementIndex(int index, int size) + { + return checkElementIndex(index, size, "index"); + } + + + + + + + + + + + + + + public static int checkElementIndex(int index, int size, @Nullable String desc) + { + if ((index < 0) || (index >= size)) { + throw new IndexOutOfBoundsException(badElementIndex(index, size, desc)); + } + return index; + } + + private static String badElementIndex(int index, int size, String desc) { + if (index < 0) + return format("%s (%s) must not be negative", new Object[] { desc, Integer.valueOf(index) }); + if (size < 0) { + throw new IllegalArgumentException("negative size: " + size); + } + return format("%s (%s) must be less than size (%s)", new Object[] { desc, Integer.valueOf(index), Integer.valueOf(size) }); + } + + + + + + + + + + + + public static int checkPositionIndex(int index, int size) + { + return checkPositionIndex(index, size, "index"); + } + + + + + + + + + + + + + public static int checkPositionIndex(int index, int size, @Nullable String desc) + { + if ((index < 0) || (index > size)) { + throw new IndexOutOfBoundsException(badPositionIndex(index, size, desc)); + } + return index; + } + + private static String badPositionIndex(int index, int size, String desc) { + if (index < 0) + return format("%s (%s) must not be negative", new Object[] { desc, Integer.valueOf(index) }); + if (size < 0) { + throw new IllegalArgumentException("negative size: " + size); + } + return format("%s (%s) must not be greater than size (%s)", new Object[] { desc, Integer.valueOf(index), Integer.valueOf(size) }); + } + + + + + + + + + + + + + + + public static void checkPositionIndexes(int start, int end, int size) + { + if ((start < 0) || (end < start) || (end > size)) { + throw new IndexOutOfBoundsException(badPositionIndexes(start, end, size)); + } + } + + private static String badPositionIndexes(int start, int end, int size) { + if ((start < 0) || (start > size)) { + return badPositionIndex(start, size, "start index"); + } + if ((end < 0) || (end > size)) { + return badPositionIndex(end, size, "end index"); + } + + return format("end index (%s) must not be less than start index (%s)", new Object[] { Integer.valueOf(end), Integer.valueOf(start) }); + } + + + + + + + + + + + + static String format(String template, @Nullable Object... args) + { + template = String.valueOf(template); + + + StringBuilder builder = new StringBuilder(template.length() + 16 * args.length); + int templateStart = 0; + int i = 0; + while (i < args.length) { + int placeholderStart = template.indexOf("%s", templateStart); + if (placeholderStart == -1) { + break; + } + builder.append(template.substring(templateStart, placeholderStart)); + builder.append(args[(i++)]); + templateStart = placeholderStart + 2; + } + builder.append(template.substring(templateStart)); + + + if (i < args.length) { + builder.append(" ["); + builder.append(args[(i++)]); + while (i < args.length) { + builder.append(", "); + builder.append(args[(i++)]); + } + builder.append(']'); + } + + return builder.toString(); + } +} diff --git a/src/minecraft/com/google/common/base/Predicate.java b/src/minecraft/com/google/common/base/Predicate.java new file mode 100644 index 0000000..cd3ea93 --- /dev/null +++ b/src/minecraft/com/google/common/base/Predicate.java @@ -0,0 +1,12 @@ +package com.google.common.base; + +import com.google.common.annotations.GwtCompatible; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract interface Predicate +{ + public abstract boolean apply(@Nullable T paramT); + + public abstract boolean equals(@Nullable Object paramObject); +} diff --git a/src/minecraft/com/google/common/base/Predicates.java b/src/minecraft/com/google/common/base/Predicates.java new file mode 100644 index 0000000..af890d3 --- /dev/null +++ b/src/minecraft/com/google/common/base/Predicates.java @@ -0,0 +1,652 @@ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public final class Predicates +{ + private Predicates() {} + + @GwtCompatible(serializable=true) + public static Predicate alwaysTrue() + { + return ObjectPredicate.ALWAYS_TRUE.withNarrowedType(); + } + + + + @GwtCompatible(serializable=true) + public static Predicate alwaysFalse() + { + return ObjectPredicate.ALWAYS_FALSE.withNarrowedType(); + } + + + + + @GwtCompatible(serializable=true) + public static Predicate isNull() + { + return ObjectPredicate.IS_NULL.withNarrowedType(); + } + + + + + @GwtCompatible(serializable=true) + public static Predicate notNull() + { + return ObjectPredicate.NOT_NULL.withNarrowedType(); + } + + + + + public static Predicate not(Predicate predicate) + { + return new NotPredicate(predicate); + } + + + + + + + + + + + public static Predicate and(Iterable> components) + { + return new AndPredicate(defensiveCopy(components), null); + } + + + + + + + + + + public static Predicate and(Predicate... components) + { + return new AndPredicate(defensiveCopy(components), null); + } + + + + + + + + public static Predicate and(Predicate first, Predicate second) + { + return new AndPredicate(asList((Predicate)Preconditions.checkNotNull(first), (Predicate)Preconditions.checkNotNull(second)), null); + } + + + + + + + + + + + + public static Predicate or(Iterable> components) + { + return new OrPredicate(defensiveCopy(components), null); + } + + + + + + + + + + public static Predicate or(Predicate... components) + { + return new OrPredicate(defensiveCopy(components), null); + } + + + + + + + + public static Predicate or(Predicate first, Predicate second) + { + return new OrPredicate(asList((Predicate)Preconditions.checkNotNull(first), (Predicate)Preconditions.checkNotNull(second)), null); + } + + + + + + public static Predicate equalTo(@Nullable T target) + { + return target == null ? isNull() : new IsEqualToPredicate(target, null); + } + + + + + + + + + + + + + + + + + + @GwtIncompatible("Class.isInstance") + public static Predicate instanceOf(Class clazz) + { + return new InstanceOfPredicate(clazz, null); + } + + + + + + + + @GwtIncompatible("Class.isAssignableFrom") + @Beta + public static Predicate> assignableFrom(Class clazz) + { + return new AssignableFromPredicate(clazz, null); + } + + + + + + + + + + + + + + public static Predicate in(Collection target) + { + return new InPredicate(target, null); + } + + + + + + + + public static Predicate compose(Predicate predicate, Function function) + { + return new CompositionPredicate(predicate, function, null); + } + + + + + + + + + + @GwtIncompatible("java.util.regex.Pattern") + public static Predicate containsPattern(String pattern) + { + return new ContainsPatternFromStringPredicate(pattern); + } + + + + + + + + + @GwtIncompatible("java.util.regex.Pattern") + public static Predicate contains(Pattern pattern) + { + return new ContainsPatternPredicate(pattern); + } + + + + static abstract enum ObjectPredicate + implements Predicate + { + ALWAYS_TRUE, + + + + + + + + + ALWAYS_FALSE, + + + + + + + + + IS_NULL, + + + + + + + + + NOT_NULL; + + + + + private ObjectPredicate() {} + + + + Predicate withNarrowedType() + { + return this; + } + } + + private static class NotPredicate implements Predicate, Serializable { + final Predicate predicate; + private static final long serialVersionUID = 0L; + + NotPredicate(Predicate predicate) { + this.predicate = ((Predicate)Preconditions.checkNotNull(predicate)); + } + + public boolean apply(@Nullable T t) { + return !predicate.apply(t); + } + + public int hashCode() { return predicate.hashCode() ^ 0xFFFFFFFF; } + + public boolean equals(@Nullable Object obj) { + if ((obj instanceof NotPredicate)) { + NotPredicate that = (NotPredicate)obj; + return predicate.equals(predicate); + } + return false; + } + + public String toString() { return "Predicates.not(" + predicate.toString() + ")"; } + } + + + + private static final Joiner COMMA_JOINER = Joiner.on(','); + + private static class AndPredicate implements Predicate, Serializable { + private final List> components; + private static final long serialVersionUID = 0L; + + private AndPredicate(List> components) { + this.components = components; + } + + public boolean apply(@Nullable T t) + { + for (int i = 0; i < components.size(); i++) { + if (!((Predicate)components.get(i)).apply(t)) { + return false; + } + } + return true; + } + + + public int hashCode() { return components.hashCode() + 306654252; } + + public boolean equals(@Nullable Object obj) { + if ((obj instanceof AndPredicate)) { + AndPredicate that = (AndPredicate)obj; + return components.equals(components); + } + return false; + } + + public String toString() { return "Predicates.and(" + Predicates.COMMA_JOINER.join(components) + ")"; } + } + + private static class OrPredicate implements Predicate, Serializable + { + private final List> components; + private static final long serialVersionUID = 0L; + + private OrPredicate(List> components) + { + this.components = components; + } + + public boolean apply(@Nullable T t) + { + for (int i = 0; i < components.size(); i++) { + if (((Predicate)components.get(i)).apply(t)) { + return true; + } + } + return false; + } + + + public int hashCode() { return components.hashCode() + 87855567; } + + public boolean equals(@Nullable Object obj) { + if ((obj instanceof OrPredicate)) { + OrPredicate that = (OrPredicate)obj; + return components.equals(components); + } + return false; + } + + public String toString() { return "Predicates.or(" + Predicates.COMMA_JOINER.join(components) + ")"; } + } + + private static class IsEqualToPredicate + implements Predicate, Serializable + { + private final T target; + private static final long serialVersionUID = 0L; + + private IsEqualToPredicate(T target) + { + this.target = target; + } + + public boolean apply(T t) { + return target.equals(t); + } + + public int hashCode() { return target.hashCode(); } + + public boolean equals(@Nullable Object obj) { + if ((obj instanceof IsEqualToPredicate)) { + IsEqualToPredicate that = (IsEqualToPredicate)obj; + return target.equals(target); + } + return false; + } + + public String toString() { return "Predicates.equalTo(" + target + ")"; } + } + + @GwtIncompatible("Class.isInstance") + private static class InstanceOfPredicate + implements Predicate, Serializable + { + private final Class clazz; + private static final long serialVersionUID = 0L; + + private InstanceOfPredicate(Class clazz) + { + this.clazz = ((Class)Preconditions.checkNotNull(clazz)); + } + + public boolean apply(@Nullable Object o) { + return clazz.isInstance(o); + } + + public int hashCode() { return clazz.hashCode(); } + + public boolean equals(@Nullable Object obj) { + if ((obj instanceof InstanceOfPredicate)) { + InstanceOfPredicate that = (InstanceOfPredicate)obj; + return clazz == clazz; + } + return false; + } + + public String toString() { return "Predicates.instanceOf(" + clazz.getName() + ")"; } + } + + @GwtIncompatible("Class.isAssignableFrom") + private static class AssignableFromPredicate + implements Predicate>, Serializable + { + private final Class clazz; + private static final long serialVersionUID = 0L; + + private AssignableFromPredicate(Class clazz) + { + this.clazz = ((Class)Preconditions.checkNotNull(clazz)); + } + + public boolean apply(Class input) { + return clazz.isAssignableFrom(input); + } + + public int hashCode() { return clazz.hashCode(); } + + public boolean equals(@Nullable Object obj) { + if ((obj instanceof AssignableFromPredicate)) { + AssignableFromPredicate that = (AssignableFromPredicate)obj; + return clazz == clazz; + } + return false; + } + + public String toString() { return "Predicates.assignableFrom(" + clazz.getName() + ")"; } + } + + private static class InPredicate implements Predicate, Serializable + { + private final Collection target; + private static final long serialVersionUID = 0L; + + private InPredicate(Collection target) + { + this.target = ((Collection)Preconditions.checkNotNull(target)); + } + + public boolean apply(@Nullable T t) + { + try { + return target.contains(t); + } catch (NullPointerException e) { + return false; + } catch (ClassCastException e) {} + return false; + } + + public boolean equals(@Nullable Object obj) + { + if ((obj instanceof InPredicate)) { + InPredicate that = (InPredicate)obj; + return target.equals(target); + } + return false; + } + + public int hashCode() { + return target.hashCode(); + } + + public String toString() { + return "Predicates.in(" + target + ")"; + } + } + + private static class CompositionPredicate implements Predicate, Serializable + { + final Predicate p; + final Function f; + private static final long serialVersionUID = 0L; + + private CompositionPredicate(Predicate p, Function f) + { + this.p = ((Predicate)Preconditions.checkNotNull(p)); + this.f = ((Function)Preconditions.checkNotNull(f)); + } + + public boolean apply(@Nullable A a) + { + return p.apply(f.apply(a)); + } + + public boolean equals(@Nullable Object obj) { + if ((obj instanceof CompositionPredicate)) { + CompositionPredicate that = (CompositionPredicate)obj; + return (f.equals(f)) && (p.equals(p)); + } + return false; + } + + public int hashCode() { + return f.hashCode() ^ p.hashCode(); + } + + public String toString() { + return p.toString() + "(" + f.toString() + ")"; + } + } + + @GwtIncompatible("Only used by other GWT-incompatible code.") + private static class ContainsPatternPredicate + implements Predicate, Serializable + { + final Pattern pattern; + private static final long serialVersionUID = 0L; + + ContainsPatternPredicate(Pattern pattern) + { + this.pattern = ((Pattern)Preconditions.checkNotNull(pattern)); + } + + public boolean apply(CharSequence t) + { + return pattern.matcher(t).find(); + } + + + + public int hashCode() + { + return Objects.hashCode(new Object[] { pattern.pattern(), Integer.valueOf(pattern.flags()) }); + } + + public boolean equals(@Nullable Object obj) { + if ((obj instanceof ContainsPatternPredicate)) { + ContainsPatternPredicate that = (ContainsPatternPredicate)obj; + + + + return (Objects.equal(pattern.pattern(), pattern.pattern())) && (Objects.equal(Integer.valueOf(pattern.flags()), Integer.valueOf(pattern.flags()))); + } + + return false; + } + + public String toString() { + String patternString = Objects.toStringHelper(pattern).add("pattern", pattern.pattern()).add("pattern.flags", pattern.flags()).toString(); + + + + return "Predicates.contains(" + patternString + ")"; + } + } + + @GwtIncompatible("Only used by other GWT-incompatible code.") + private static class ContainsPatternFromStringPredicate + extends Predicates.ContainsPatternPredicate + { + private static final long serialVersionUID = 0L; + + ContainsPatternFromStringPredicate(String string) + { + super(); + } + + public String toString() { + return "Predicates.containsPattern(" + pattern.pattern() + ")"; + } + } + + + + + private static List> asList(Predicate first, Predicate second) + { + return Arrays.asList(new Predicate[] { first, second }); + } + + private static List defensiveCopy(T... array) { + return defensiveCopy(Arrays.asList(array)); + } + + static List defensiveCopy(Iterable iterable) { + ArrayList list = new ArrayList(); + for (T element : iterable) { + list.add(Preconditions.checkNotNull(element)); + } + return list; + } +} diff --git a/src/minecraft/com/google/common/base/Present.java b/src/minecraft/com/google/common/base/Present.java new file mode 100644 index 0000000..69e5788 --- /dev/null +++ b/src/minecraft/com/google/common/base/Present.java @@ -0,0 +1,90 @@ +package com.google.common.base; + +import com.google.common.annotations.GwtCompatible; +import java.util.Collections; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +final class Present + extends Optional +{ + private final T reference; + private static final long serialVersionUID = 0L; + + Present(T reference) + { + this.reference = reference; + } + + public boolean isPresent() { + return true; + } + + public T get() { + return reference; + } + + public T or(T defaultValue) { + Preconditions.checkNotNull(defaultValue, "use Optional.orNull() instead of Optional.or(null)"); + return reference; + } + + public Optional or(Optional secondChoice) { + Preconditions.checkNotNull(secondChoice); + return this; + } + + public T or(Supplier supplier) { + Preconditions.checkNotNull(supplier); + return reference; + } + + public T orNull() { + return reference; + } + + public Set asSet() { + return Collections.singleton(reference); + } + + public Optional transform(Function function) { + return new Present(Preconditions.checkNotNull(function.apply(reference), "the Function passed to Optional.transform() must not return null.")); + } + + public boolean equals(@Nullable Object object) + { + if ((object instanceof Present)) { + Present other = (Present)object; + return reference.equals(reference); + } + return false; + } + + public int hashCode() { + return 1502476572 + reference.hashCode(); + } + + public String toString() { + return "Optional.of(" + reference + ")"; + } +} diff --git a/src/minecraft/com/google/common/base/SmallCharMatcher.java b/src/minecraft/com/google/common/base/SmallCharMatcher.java new file mode 100644 index 0000000..54e3889 --- /dev/null +++ b/src/minecraft/com/google/common/base/SmallCharMatcher.java @@ -0,0 +1,153 @@ +package com.google.common.base; + +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; +import java.util.BitSet; + + + + + + + + + + + + + + + + + + + + +@GwtIncompatible("no precomputation is done in GWT") +final class SmallCharMatcher + extends CharMatcher.FastMatcher +{ + static final int MAX_SIZE = 1023; + private final char[] table; + private final boolean containsZero; + private final long filter; + private static final int C1 = -862048943; + private static final int C2 = 461845907; + private static final double DESIRED_LOAD_FACTOR = 0.5D; + + private SmallCharMatcher(char[] table, long filter, boolean containsZero, String description) + { + super(description); + this.table = table; + this.filter = filter; + this.containsZero = containsZero; + } + + + + + + + + + + + + static int smear(int hashCode) + { + return 461845907 * Integer.rotateLeft(hashCode * -862048943, 15); + } + + private boolean checkFilter(int c) { + return 1L == (1L & filter >> c); + } + + + + + + + + + + + + @VisibleForTesting + static int chooseTableSize(int setSize) + { + if (setSize == 1) { + return 2; + } + + + int tableSize = Integer.highestOneBit(setSize - 1) << 1; + while (tableSize * 0.5D < setSize) { + tableSize <<= 1; + } + return tableSize; + } + + static CharMatcher from(BitSet chars, String description) + { + long filter = 0L; + int size = chars.cardinality(); + boolean containsZero = chars.get(0); + + char[] table = new char[chooseTableSize(size)]; + int mask = table.length - 1; + for (int c = chars.nextSetBit(0); c != -1; c = chars.nextSetBit(c + 1)) + { + filter |= 1L << c; + int index = smear(c) & mask; + for (;;) + { + if (table[index] == 0) { + table[index] = ((char)c); + break; + } + + index = index + 1 & mask; + } + } + return new SmallCharMatcher(table, filter, containsZero, description); + } + + public boolean matches(char c) + { + if (c == 0) { + return containsZero; + } + if (!checkFilter(c)) { + return false; + } + int mask = table.length - 1; + int startingIndex = smear(c) & mask; + int index = startingIndex; + do + { + if (table[index] == 0) { + return false; + } + if (table[index] == c) { + return true; + } + + index = index + 1 & mask; + + } + while (index != startingIndex); + return false; + } + + void setBits(BitSet table) + { + if (containsZero) { + table.set(0); + } + for (char c : this.table) { + if (c != 0) { + table.set(c); + } + } + } +} diff --git a/src/minecraft/com/google/common/base/Splitter.java b/src/minecraft/com/google/common/base/Splitter.java new file mode 100644 index 0000000..6a8977b --- /dev/null +++ b/src/minecraft/com/google/common/base/Splitter.java @@ -0,0 +1,617 @@ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.annotation.CheckReturnValue; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public final class Splitter +{ + private final CharMatcher trimmer; + private final boolean omitEmptyStrings; + private final Strategy strategy; + private final int limit; + + private Splitter(Strategy strategy) + { + this(strategy, false, CharMatcher.NONE, Integer.MAX_VALUE); + } + + private Splitter(Strategy strategy, boolean omitEmptyStrings, CharMatcher trimmer, int limit) + { + this.strategy = strategy; + this.omitEmptyStrings = omitEmptyStrings; + this.trimmer = trimmer; + this.limit = limit; + } + + + + + + + + + public static Splitter on(char separator) + { + return on(CharMatcher.is(separator)); + } + + + + + + + + + + + public static Splitter on(CharMatcher separatorMatcher) + { + Preconditions.checkNotNull(separatorMatcher); + + new Splitter(new Strategy() + { + public Splitter.SplittingIterator iterator(Splitter splitter, CharSequence toSplit) { + new Splitter.SplittingIterator(splitter, toSplit) { + int separatorStart(int start) { + return val$separatorMatcher.indexIn(toSplit, start); + } + + int separatorEnd(int separatorPosition) { + return separatorPosition + 1; + } + }; + } + }); + } + + + + + + + + + public static Splitter on(String separator) + { + Preconditions.checkArgument(separator.length() != 0, "The separator may not be the empty string."); + + + new Splitter(new Strategy() + { + public Splitter.SplittingIterator iterator(Splitter splitter, CharSequence toSplit) { + new Splitter.SplittingIterator(splitter, toSplit) { + public int separatorStart(int start) { + int separatorLength = val$separator.length(); + + + int p = start;int last = toSplit.length() - separatorLength; + label80: for (; p <= last; p++) { + for (int i = 0; i < separatorLength; i++) { + if (toSplit.charAt(i + p) != val$separator.charAt(i)) { + break label80; + } + } + return p; + } + return -1; + } + + public int separatorEnd(int separatorPosition) { + return separatorPosition + val$separator.length(); + } + }; + } + }); + } + + + + + + + + + + + + + @GwtIncompatible("java.util.regex") + public static Splitter on(Pattern separatorPattern) + { + Preconditions.checkNotNull(separatorPattern); + Preconditions.checkArgument(!separatorPattern.matcher("").matches(), "The pattern may not match the empty string: %s", new Object[] { separatorPattern }); + + + new Splitter(new Strategy() + { + public Splitter.SplittingIterator iterator(Splitter splitter, CharSequence toSplit) { + final Matcher matcher = val$separatorPattern.matcher(toSplit); + new Splitter.SplittingIterator(splitter, toSplit) { + public int separatorStart(int start) { + return matcher.find(start) ? matcher.start() : -1; + } + + public int separatorEnd(int separatorPosition) { + return matcher.end(); + } + }; + } + }); + } + + + + + + + + + + + + + + + + @GwtIncompatible("java.util.regex") + public static Splitter onPattern(String separatorPattern) + { + return on(Pattern.compile(separatorPattern)); + } + + + + + + + + + + + + + + + + + + + + public static Splitter fixedLength(int length) + { + Preconditions.checkArgument(length > 0, "The length may not be less than 1"); + + new Splitter(new Strategy() + { + public Splitter.SplittingIterator iterator(Splitter splitter, CharSequence toSplit) { + new Splitter.SplittingIterator(splitter, toSplit) { + public int separatorStart(int start) { + int nextChunkStart = start + val$length; + return nextChunkStart < toSplit.length() ? nextChunkStart : -1; + } + + public int separatorEnd(int separatorPosition) { + return separatorPosition; + } + }; + } + }); + } + + + + + + + + + + + + + + + + + + + @CheckReturnValue + public Splitter omitEmptyStrings() + { + return new Splitter(strategy, true, trimmer, limit); + } + + + + + + + + + + + + + + + + + + + + @CheckReturnValue + public Splitter limit(int limit) + { + Preconditions.checkArgument(limit > 0, "must be greater than zero: %s", new Object[] { Integer.valueOf(limit) }); + return new Splitter(strategy, omitEmptyStrings, trimmer, limit); + } + + + + + + + + + + + @CheckReturnValue + public Splitter trimResults() + { + return trimResults(CharMatcher.WHITESPACE); + } + + + + + + + + + + + + + @CheckReturnValue + public Splitter trimResults(CharMatcher trimmer) + { + Preconditions.checkNotNull(trimmer); + return new Splitter(strategy, omitEmptyStrings, trimmer, limit); + } + + + + + + + + + public Iterable split(final CharSequence sequence) + { + Preconditions.checkNotNull(sequence); + + new Iterable() { + public Iterator iterator() { + return Splitter.this.splittingIterator(sequence); + } + + public String toString() { return ']'; } + }; + } + + + + + private Iterator splittingIterator(CharSequence sequence) + { + return strategy.iterator(this, sequence); + } + + + + + + + + + + @Beta + public List splitToList(CharSequence sequence) + { + Preconditions.checkNotNull(sequence); + + Iterator iterator = splittingIterator(sequence); + List result = new ArrayList(); + + while (iterator.hasNext()) { + result.add(iterator.next()); + } + + return Collections.unmodifiableList(result); + } + + + + + + + @CheckReturnValue + @Beta + public MapSplitter withKeyValueSeparator(String separator) + { + return withKeyValueSeparator(on(separator)); + } + + + + + + + @CheckReturnValue + @Beta + public MapSplitter withKeyValueSeparator(char separator) + { + return withKeyValueSeparator(on(separator)); + } + + + + + + + + @CheckReturnValue + @Beta + public MapSplitter withKeyValueSeparator(Splitter keyValueSplitter) + { + return new MapSplitter(this, keyValueSplitter, null); + } + + + + @Beta + public static final class MapSplitter + { + private static final String INVALID_ENTRY_MESSAGE = "Chunk [%s] is not a valid entry"; + + + private final Splitter outerSplitter; + + private final Splitter entrySplitter; + + + private MapSplitter(Splitter outerSplitter, Splitter entrySplitter) + { + this.outerSplitter = outerSplitter; + this.entrySplitter = ((Splitter)Preconditions.checkNotNull(entrySplitter)); + } + + + + + + + + + + + + + + + + public Map split(CharSequence sequence) + { + Map map = new LinkedHashMap(); + for (String entry : outerSplitter.split(sequence)) { + Iterator entryFields = entrySplitter.splittingIterator(entry); + + Preconditions.checkArgument(entryFields.hasNext(), "Chunk [%s] is not a valid entry", new Object[] { entry }); + String key = (String)entryFields.next(); + Preconditions.checkArgument(!map.containsKey(key), "Duplicate key [%s] found.", new Object[] { key }); + + Preconditions.checkArgument(entryFields.hasNext(), "Chunk [%s] is not a valid entry", new Object[] { entry }); + String value = (String)entryFields.next(); + map.put(key, value); + + Preconditions.checkArgument(!entryFields.hasNext(), "Chunk [%s] is not a valid entry", new Object[] { entry }); + } + return Collections.unmodifiableMap(map); + } + } + + + + private static abstract interface Strategy + { + public abstract Iterator iterator(Splitter paramSplitter, CharSequence paramCharSequence); + } + + + + private static abstract class SplittingIterator + extends AbstractIterator + { + final CharSequence toSplit; + + final CharMatcher trimmer; + + final boolean omitEmptyStrings; + + + abstract int separatorStart(int paramInt); + + + int offset = 0; + + abstract int separatorEnd(int paramInt); + + protected SplittingIterator(Splitter splitter, CharSequence toSplit) { trimmer = trimmer; + omitEmptyStrings = omitEmptyStrings; + limit = limit; + this.toSplit = toSplit; + } + + + + int limit; + + + protected String computeNext() + { + int nextStart = offset; + while (offset != -1) { + int start = nextStart; + + + int separatorPosition = separatorStart(offset); + int end; if (separatorPosition == -1) { + int end = toSplit.length(); + offset = -1; + } else { + end = separatorPosition; + offset = separatorEnd(separatorPosition); + } + if (offset == nextStart) + { + + + + + + + offset += 1; + if (offset >= toSplit.length()) { + offset = -1; + } + } + else + { + while ((start < end) && (trimmer.matches(toSplit.charAt(start)))) { + start++; + } + while ((end > start) && (trimmer.matches(toSplit.charAt(end - 1)))) { + end--; + } + + if ((omitEmptyStrings) && (start == end)) + { + nextStart = offset; + } + else + { + if (limit == 1) + { + + + end = toSplit.length(); + offset = -1; + + while ((end > start) && (trimmer.matches(toSplit.charAt(end - 1)))) { + end--; + } + } + limit -= 1; + + + return toSplit.subSequence(start, end).toString(); + } } } + return (String)endOfData(); + } + } +} diff --git a/src/minecraft/com/google/common/base/StandardSystemProperty.java b/src/minecraft/com/google/common/base/StandardSystemProperty.java new file mode 100644 index 0000000..642f3f6 --- /dev/null +++ b/src/minecraft/com/google/common/base/StandardSystemProperty.java @@ -0,0 +1,143 @@ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtIncompatible; + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtIncompatible("java.lang.System#getProperty") +public enum StandardSystemProperty +{ + JAVA_VERSION("java.version"), + + + JAVA_VENDOR("java.vendor"), + + + JAVA_VENDOR_URL("java.vendor.url"), + + + JAVA_HOME("java.home"), + + + JAVA_VM_SPECIFICATION_VERSION("java.vm.specification.version"), + + + JAVA_VM_SPECIFICATION_VENDOR("java.vm.specification.vendor"), + + + JAVA_VM_SPECIFICATION_NAME("java.vm.specification.name"), + + + JAVA_VM_VERSION("java.vm.version"), + + + JAVA_VM_VENDOR("java.vm.vendor"), + + + JAVA_VM_NAME("java.vm.name"), + + + JAVA_SPECIFICATION_VERSION("java.specification.version"), + + + JAVA_SPECIFICATION_VENDOR("java.specification.vendor"), + + + JAVA_SPECIFICATION_NAME("java.specification.name"), + + + JAVA_CLASS_VERSION("java.class.version"), + + + JAVA_CLASS_PATH("java.class.path"), + + + JAVA_LIBRARY_PATH("java.library.path"), + + + JAVA_IO_TMPDIR("java.io.tmpdir"), + + + JAVA_COMPILER("java.compiler"), + + + JAVA_EXT_DIRS("java.ext.dirs"), + + + OS_NAME("os.name"), + + + OS_ARCH("os.arch"), + + + OS_VERSION("os.version"), + + + FILE_SEPARATOR("file.separator"), + + + PATH_SEPARATOR("path.separator"), + + + LINE_SEPARATOR("line.separator"), + + + USER_NAME("user.name"), + + + USER_HOME("user.home"), + + + USER_DIR("user.dir"); + + private final String key; + + private StandardSystemProperty(String key) { + this.key = key; + } + + + + public String key() + { + return key; + } + + + + + public String value() + { + return System.getProperty(key); + } + + + + public String toString() + { + return key() + "=" + value(); + } +} diff --git a/src/minecraft/com/google/common/base/Stopwatch.java b/src/minecraft/com/google/common/base/Stopwatch.java new file mode 100644 index 0000000..1d44b61 --- /dev/null +++ b/src/minecraft/com/google/common/base/Stopwatch.java @@ -0,0 +1,266 @@ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import java.util.concurrent.TimeUnit; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible(emulated=true) +public final class Stopwatch +{ + private final Ticker ticker; + private boolean isRunning; + private long elapsedNanos; + private long startTick; + + public static Stopwatch createUnstarted() + { + return new Stopwatch(); + } + + + + + + + public static Stopwatch createUnstarted(Ticker ticker) + { + return new Stopwatch(ticker); + } + + + + + + + public static Stopwatch createStarted() + { + return new Stopwatch().start(); + } + + + + + + + public static Stopwatch createStarted(Ticker ticker) + { + return new Stopwatch(ticker).start(); + } + + + + + + + @Deprecated + Stopwatch() + { + this(Ticker.systemTicker()); + } + + + + + + + @Deprecated + Stopwatch(Ticker ticker) + { + this.ticker = ((Ticker)Preconditions.checkNotNull(ticker, "ticker")); + } + + + + + + public boolean isRunning() + { + return isRunning; + } + + + + + + + public Stopwatch start() + { + Preconditions.checkState(!isRunning, "This stopwatch is already running."); + isRunning = true; + startTick = ticker.read(); + return this; + } + + + + + + + + public Stopwatch stop() + { + long tick = ticker.read(); + Preconditions.checkState(isRunning, "This stopwatch is already stopped."); + isRunning = false; + elapsedNanos += tick - startTick; + return this; + } + + + + + + + public Stopwatch reset() + { + elapsedNanos = 0L; + isRunning = false; + return this; + } + + private long elapsedNanos() { + return isRunning ? ticker.read() - startTick + elapsedNanos : elapsedNanos; + } + + + + + + + + + + + public long elapsed(TimeUnit desiredUnit) + { + return desiredUnit.convert(elapsedNanos(), TimeUnit.NANOSECONDS); + } + + + + @GwtIncompatible("String.format()") + public String toString() + { + long nanos = elapsedNanos(); + + TimeUnit unit = chooseUnit(nanos); + double value = nanos / TimeUnit.NANOSECONDS.convert(1L, unit); + + + return String.format("%.4g %s", new Object[] { Double.valueOf(value), abbreviate(unit) }); + } + + private static TimeUnit chooseUnit(long nanos) { + if (TimeUnit.DAYS.convert(nanos, TimeUnit.NANOSECONDS) > 0L) { + return TimeUnit.DAYS; + } + if (TimeUnit.HOURS.convert(nanos, TimeUnit.NANOSECONDS) > 0L) { + return TimeUnit.HOURS; + } + if (TimeUnit.MINUTES.convert(nanos, TimeUnit.NANOSECONDS) > 0L) { + return TimeUnit.MINUTES; + } + if (TimeUnit.SECONDS.convert(nanos, TimeUnit.NANOSECONDS) > 0L) { + return TimeUnit.SECONDS; + } + if (TimeUnit.MILLISECONDS.convert(nanos, TimeUnit.NANOSECONDS) > 0L) { + return TimeUnit.MILLISECONDS; + } + if (TimeUnit.MICROSECONDS.convert(nanos, TimeUnit.NANOSECONDS) > 0L) { + return TimeUnit.MICROSECONDS; + } + return TimeUnit.NANOSECONDS; + } + + private static String abbreviate(TimeUnit unit) { + switch (1.$SwitchMap$java$util$concurrent$TimeUnit[unit.ordinal()]) { + case 1: + return "ns"; + case 2: + return "μs"; + case 3: + return "ms"; + case 4: + return "s"; + case 5: + return "min"; + case 6: + return "h"; + case 7: + return "d"; + } + throw new AssertionError(); + } +} diff --git a/src/minecraft/com/google/common/base/Strings.java b/src/minecraft/com/google/common/base/Strings.java new file mode 100644 index 0000000..cf8b983 --- /dev/null +++ b/src/minecraft/com/google/common/base/Strings.java @@ -0,0 +1,236 @@ +package com.google.common.base; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.VisibleForTesting; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public final class Strings +{ + private Strings() {} + + public static String nullToEmpty(@Nullable String string) + { + return string == null ? "" : string; + } + + + + + + + @Nullable + public static String emptyToNull(@Nullable String string) + { + return isNullOrEmpty(string) ? null : string; + } + + + + + + + + + + + + + + public static boolean isNullOrEmpty(@Nullable String string) + { + return (string == null) || (string.length() == 0); + } + + + + + + + + + + + + + + + + + + + + public static String padStart(String string, int minLength, char padChar) + { + Preconditions.checkNotNull(string); + if (string.length() >= minLength) { + return string; + } + StringBuilder sb = new StringBuilder(minLength); + for (int i = string.length(); i < minLength; i++) { + sb.append(padChar); + } + sb.append(string); + return sb.toString(); + } + + + + + + + + + + + + + + + + + + + + public static String padEnd(String string, int minLength, char padChar) + { + Preconditions.checkNotNull(string); + if (string.length() >= minLength) { + return string; + } + StringBuilder sb = new StringBuilder(minLength); + sb.append(string); + for (int i = string.length(); i < minLength; i++) { + sb.append(padChar); + } + return sb.toString(); + } + + + + + + + + + + + + public static String repeat(String string, int count) + { + Preconditions.checkNotNull(string); + + if (count <= 1) { + Preconditions.checkArgument(count >= 0, "invalid count: %s", new Object[] { Integer.valueOf(count) }); + return count == 0 ? "" : string; + } + + + int len = string.length(); + long longSize = len * count; + int size = (int)longSize; + if (size != longSize) { + throw new ArrayIndexOutOfBoundsException("Required array size too large: " + longSize); + } + + + char[] array = new char[size]; + string.getChars(0, len, array, 0); + + for (int n = len; n < size - n; n <<= 1) { + System.arraycopy(array, 0, array, n, n); + } + System.arraycopy(array, 0, array, n, size - n); + return new String(array); + } + + + + + + + + + public static String commonPrefix(CharSequence a, CharSequence b) + { + Preconditions.checkNotNull(a); + Preconditions.checkNotNull(b); + + int maxPrefixLength = Math.min(a.length(), b.length()); + int p = 0; + while ((p < maxPrefixLength) && (a.charAt(p) == b.charAt(p))) { + p++; + } + if ((validSurrogatePairAt(a, p - 1)) || (validSurrogatePairAt(b, p - 1))) { + p--; + } + return a.subSequence(0, p).toString(); + } + + + + + + + + + public static String commonSuffix(CharSequence a, CharSequence b) + { + Preconditions.checkNotNull(a); + Preconditions.checkNotNull(b); + + int maxSuffixLength = Math.min(a.length(), b.length()); + int s = 0; + + while ((s < maxSuffixLength) && (a.charAt(a.length() - s - 1) == b.charAt(b.length() - s - 1))) { + s++; + } + if ((validSurrogatePairAt(a, a.length() - s - 1)) || (validSurrogatePairAt(b, b.length() - s - 1))) + { + s--; + } + return a.subSequence(a.length() - s, a.length()).toString(); + } + + + + + @VisibleForTesting + static boolean validSurrogatePairAt(CharSequence string, int index) + { + return (index >= 0) && (index <= string.length() - 2) && (Character.isHighSurrogate(string.charAt(index))) && (Character.isLowSurrogate(string.charAt(index + 1))); + } +} diff --git a/src/minecraft/com/google/common/base/Supplier.java b/src/minecraft/com/google/common/base/Supplier.java new file mode 100644 index 0000000..df9a264 --- /dev/null +++ b/src/minecraft/com/google/common/base/Supplier.java @@ -0,0 +1,9 @@ +package com.google.common.base; + +import com.google.common.annotations.GwtCompatible; + +@GwtCompatible +public abstract interface Supplier +{ + public abstract T get(); +} diff --git a/src/minecraft/com/google/common/base/Suppliers.java b/src/minecraft/com/google/common/base/Suppliers.java new file mode 100644 index 0000000..4bf1e19 --- /dev/null +++ b/src/minecraft/com/google/common/base/Suppliers.java @@ -0,0 +1,309 @@ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.VisibleForTesting; +import java.io.Serializable; +import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public final class Suppliers +{ + private Suppliers() {} + + public static Supplier compose(Function function, Supplier supplier) + { + Preconditions.checkNotNull(function); + Preconditions.checkNotNull(supplier); + return new SupplierComposition(function, supplier); + } + + private static class SupplierComposition implements Supplier, Serializable { + final Function function; + final Supplier supplier; + private static final long serialVersionUID = 0L; + + SupplierComposition(Function function, Supplier supplier) { + this.function = function; + this.supplier = supplier; + } + + public T get() { + return function.apply(supplier.get()); + } + + public boolean equals(@Nullable Object obj) { + if ((obj instanceof SupplierComposition)) { + SupplierComposition that = (SupplierComposition)obj; + return (function.equals(function)) && (supplier.equals(supplier)); + } + return false; + } + + public int hashCode() { + return Objects.hashCode(new Object[] { function, supplier }); + } + + public String toString() { + return "Suppliers.compose(" + function + ", " + supplier + ")"; + } + } + + + + + + + + + + + + + + + + public static Supplier memoize(Supplier delegate) + { + return (delegate instanceof MemoizingSupplier) ? delegate : new MemoizingSupplier((Supplier)Preconditions.checkNotNull(delegate)); + } + + @VisibleForTesting + static class MemoizingSupplier + implements Supplier, Serializable + { + final Supplier delegate; + volatile transient boolean initialized; + transient T value; + private static final long serialVersionUID = 0L; + + MemoizingSupplier(Supplier delegate) + { + this.delegate = delegate; + } + + public T get() + { + if (!initialized) { + synchronized (this) { + if (!initialized) { + T t = delegate.get(); + value = t; + initialized = true; + return t; + } + } + } + return value; + } + + public String toString() { + return "Suppliers.memoize(" + delegate + ")"; + } + } + + + + + + + + + + + + + + + + + + + + + + public static Supplier memoizeWithExpiration(Supplier delegate, long duration, TimeUnit unit) + { + return new ExpiringMemoizingSupplier(delegate, duration, unit); + } + + @VisibleForTesting + static class ExpiringMemoizingSupplier implements Supplier, Serializable + { + final Supplier delegate; + final long durationNanos; + volatile transient T value; + volatile transient long expirationNanos; + private static final long serialVersionUID = 0L; + + ExpiringMemoizingSupplier(Supplier delegate, long duration, TimeUnit unit) { + this.delegate = ((Supplier)Preconditions.checkNotNull(delegate)); + durationNanos = unit.toNanos(duration); + Preconditions.checkArgument(duration > 0L); + } + + + + + + + public T get() + { + long nanos = expirationNanos; + long now = Platform.systemNanoTime(); + if ((nanos == 0L) || (now - nanos >= 0L)) { + synchronized (this) { + if (nanos == expirationNanos) { + T t = delegate.get(); + value = t; + nanos = now + durationNanos; + + + expirationNanos = (nanos == 0L ? 1L : nanos); + return t; + } + } + } + return value; + } + + + public String toString() + { + return "Suppliers.memoizeWithExpiration(" + delegate + ", " + durationNanos + ", NANOS)"; + } + } + + + + + + + public static Supplier ofInstance(@Nullable T instance) + { + return new SupplierOfInstance(instance); + } + + private static class SupplierOfInstance implements Supplier, Serializable { + final T instance; + private static final long serialVersionUID = 0L; + + SupplierOfInstance(@Nullable T instance) { + this.instance = instance; + } + + public T get() { + return instance; + } + + public boolean equals(@Nullable Object obj) { + if ((obj instanceof SupplierOfInstance)) { + SupplierOfInstance that = (SupplierOfInstance)obj; + return Objects.equal(instance, instance); + } + return false; + } + + public int hashCode() { + return Objects.hashCode(new Object[] { instance }); + } + + public String toString() { + return "Suppliers.ofInstance(" + instance + ")"; + } + } + + + + + + + public static Supplier synchronizedSupplier(Supplier delegate) + { + return new ThreadSafeSupplier((Supplier)Preconditions.checkNotNull(delegate)); + } + + private static class ThreadSafeSupplier implements Supplier, Serializable { + final Supplier delegate; + private static final long serialVersionUID = 0L; + + ThreadSafeSupplier(Supplier delegate) { + this.delegate = delegate; + } + + public T get() { + synchronized (delegate) { + return delegate.get(); + } + } + + public String toString() { + return "Suppliers.synchronizedSupplier(" + delegate + ")"; + } + } + + + + + + + + + + @Beta + public static Function, T> supplierFunction() + { + SupplierFunction sf = SupplierFunctionImpl.INSTANCE; + return sf; + } + + private static abstract interface SupplierFunction extends Function, T> + {} + + private static enum SupplierFunctionImpl implements Suppliers.SupplierFunction { INSTANCE; + + private SupplierFunctionImpl() {} + + public Object apply(Supplier input) { return input.get(); } + + public String toString() + { + return "Suppliers.supplierFunction()"; + } + } +} diff --git a/src/minecraft/com/google/common/base/Throwables.java b/src/minecraft/com/google/common/base/Throwables.java new file mode 100644 index 0000000..3fd5fb4 --- /dev/null +++ b/src/minecraft/com/google/common/base/Throwables.java @@ -0,0 +1,220 @@ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public final class Throwables +{ + private Throwables() {} + + public static void propagateIfInstanceOf(@Nullable Throwable throwable, Class declaredType) + throws Throwable + { + if ((throwable != null) && (declaredType.isInstance(throwable))) { + throw ((Throwable)declaredType.cast(throwable)); + } + } + + + + + + + + + + + + + + + public static void propagateIfPossible(@Nullable Throwable throwable) + { + propagateIfInstanceOf(throwable, Error.class); + propagateIfInstanceOf(throwable, RuntimeException.class); + } + + + + + + + + + + + + + + + + + + + + public static void propagateIfPossible(@Nullable Throwable throwable, Class declaredType) + throws Throwable + { + propagateIfInstanceOf(throwable, declaredType); + propagateIfPossible(throwable); + } + + + + + + + + + + + + + + + + public static void propagateIfPossible(@Nullable Throwable throwable, Class declaredType1, Class declaredType2) + throws Throwable, Throwable + { + Preconditions.checkNotNull(declaredType2); + propagateIfInstanceOf(throwable, declaredType1); + propagateIfPossible(throwable, declaredType2); + } + + + + + + + + + + + + + + + + + + + + + + + + + public static RuntimeException propagate(Throwable throwable) + { + propagateIfPossible((Throwable)Preconditions.checkNotNull(throwable)); + throw new RuntimeException(throwable); + } + + + + + + public static Throwable getRootCause(Throwable throwable) + { + Throwable cause; + + + + + while ((cause = throwable.getCause()) != null) { + throwable = cause; + } + return throwable; + } + + + + + + + + + + + + + + + + + + @Beta + public static List getCausalChain(Throwable throwable) + { + Preconditions.checkNotNull(throwable); + List causes = new ArrayList(4); + while (throwable != null) { + causes.add(throwable); + throwable = throwable.getCause(); + } + return Collections.unmodifiableList(causes); + } + + + + + + + + public static String getStackTraceAsString(Throwable throwable) + { + StringWriter stringWriter = new StringWriter(); + throwable.printStackTrace(new PrintWriter(stringWriter)); + return stringWriter.toString(); + } +} diff --git a/src/minecraft/com/google/common/base/Ticker.java b/src/minecraft/com/google/common/base/Ticker.java new file mode 100644 index 0000000..7ef7f16 --- /dev/null +++ b/src/minecraft/com/google/common/base/Ticker.java @@ -0,0 +1,63 @@ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +public abstract class Ticker +{ + protected Ticker() {} + + public abstract long read(); + + public static Ticker systemTicker() + { + return SYSTEM_TICKER; + } + + private static final Ticker SYSTEM_TICKER = new Ticker() + { + public long read() { + return Platform.systemNanoTime(); + } + }; +} diff --git a/src/minecraft/com/google/common/base/Utf8.java b/src/minecraft/com/google/common/base/Utf8.java new file mode 100644 index 0000000..492a42e --- /dev/null +++ b/src/minecraft/com/google/common/base/Utf8.java @@ -0,0 +1,197 @@ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +public final class Utf8 +{ + public static int encodedLength(CharSequence sequence) + { + int utf16Length = sequence.length(); + int utf8Length = utf16Length; + int i = 0; + + + while ((i < utf16Length) && (sequence.charAt(i) < '€')) { + i++; + } + for (; + + i < utf16Length; i++) { + char c = sequence.charAt(i); + if (c < 'ࠀ') { + utf8Length += ('' - c >>> 31); + } else { + utf8Length += encodedLengthGeneral(sequence, i); + break; + } + } + + if (utf8Length < utf16Length) + { + throw new IllegalArgumentException("UTF-8 length does not fit in int: " + (utf8Length + 4294967296L)); + } + + return utf8Length; + } + + private static int encodedLengthGeneral(CharSequence sequence, int start) { + int utf16Length = sequence.length(); + int utf8Length = 0; + for (int i = start; i < utf16Length; i++) { + char c = sequence.charAt(i); + if (c < 'ࠀ') { + utf8Length += ('' - c >>> 31); + } else { + utf8Length += 2; + + if ((55296 <= c) && (c <= 57343)) + { + int cp = Character.codePointAt(sequence, i); + if (cp < 65536) { + throw new IllegalArgumentException("Unpaired surrogate at index " + i); + } + i++; + } + } + } + return utf8Length; + } + + + + + + + + + + + public static boolean isWellFormed(byte[] bytes) + { + return isWellFormed(bytes, 0, bytes.length); + } + + + + + + + + + + public static boolean isWellFormed(byte[] bytes, int off, int len) + { + int end = off + len; + Preconditions.checkPositionIndexes(off, end, bytes.length); + + for (int i = off; i < end; i++) { + if (bytes[i] < 0) { + return isWellFormedSlowPath(bytes, i, end); + } + } + return true; + } + + private static boolean isWellFormedSlowPath(byte[] bytes, int off, int end) { + int index = off; + + + + for (;;) + { + if (index >= end) + return true; + int byte1; + if ((byte1 = bytes[(index++)]) < 0) + { + if (byte1 < -32) + { + if (index == end) { + return false; + } + + + if ((byte1 < -62) || (bytes[(index++)] > -65)) { + return false; + } + } else if (byte1 < -16) + { + if (index + 1 >= end) { + return false; + } + int byte2 = bytes[(index++)]; + if ((byte2 > -65) || ((byte1 == -32) && (byte2 < -96)) || ((byte1 == -19) && (-96 <= byte2)) || (bytes[(index++)] > -65)) + { + + + + + + return false; + } + } + else { + if (index + 2 >= end) { + return false; + } + int byte2 = bytes[(index++)]; + if ((byte2 > -65) || ((byte1 << 28) + (byte2 - -112) >> 30 != 0) || (bytes[(index++)] > -65) || (bytes[(index++)] > -65)) + { + + + + + + + + + return false; + } + } + } + } + } + + private Utf8() {} +} diff --git a/src/minecraft/com/google/common/base/Verify.java b/src/minecraft/com/google/common/base/Verify.java new file mode 100644 index 0000000..88579f6 --- /dev/null +++ b/src/minecraft/com/google/common/base/Verify.java @@ -0,0 +1,161 @@ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +public final class Verify +{ + public static void verify(boolean expression) + { + if (!expression) { + throw new VerifyException(); + } + } + + + + + + + + + + + + + + + + + + + + public static void verify(boolean expression, @Nullable String errorMessageTemplate, @Nullable Object... errorMessageArgs) + { + if (!expression) { + throw new VerifyException(Preconditions.format(errorMessageTemplate, errorMessageArgs)); + } + } + + + + + + + public static T verifyNotNull(@Nullable T reference) + { + return verifyNotNull(reference, "expected a non-null reference", new Object[0]); + } + + + + + + + + + + + + + + + + + + + public static T verifyNotNull(@Nullable T reference, @Nullable String errorMessageTemplate, @Nullable Object... errorMessageArgs) + { + verify(reference != null, errorMessageTemplate, errorMessageArgs); + return reference; + } + + private Verify() {} +} diff --git a/src/minecraft/com/google/common/base/VerifyException.java b/src/minecraft/com/google/common/base/VerifyException.java new file mode 100644 index 0000000..b34c2d8 --- /dev/null +++ b/src/minecraft/com/google/common/base/VerifyException.java @@ -0,0 +1,39 @@ +package com.google.common.base; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +public class VerifyException + extends RuntimeException +{ + public VerifyException() {} + + public VerifyException(@Nullable String message) + { + super(message); + } +} diff --git a/src/minecraft/com/google/common/base/internal/Finalizer.java b/src/minecraft/com/google/common/base/internal/Finalizer.java new file mode 100644 index 0000000..c355831 --- /dev/null +++ b/src/minecraft/com/google/common/base/internal/Finalizer.java @@ -0,0 +1,213 @@ +package com.google.common.base.internal; + +import java.lang.ref.PhantomReference; +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.logging.Level; +import java.util.logging.Logger; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class Finalizer + implements Runnable +{ + private static final Logger logger = Logger.getLogger(Finalizer.class.getName()); + + + + + + private static final String FINALIZABLE_REFERENCE = "com.google.common.base.FinalizableReference"; + + + + + private final WeakReference> finalizableReferenceClassReference; + + + + + private final PhantomReference frqReference; + + + + + private final ReferenceQueue queue; + + + + + + public static void startFinalizer(Class finalizableReferenceClass, ReferenceQueue queue, PhantomReference frqReference) + { + if (!finalizableReferenceClass.getName().equals("com.google.common.base.FinalizableReference")) { + throw new IllegalArgumentException("Expected com.google.common.base.FinalizableReference."); + } + + + Finalizer finalizer = new Finalizer(finalizableReferenceClass, queue, frqReference); + Thread thread = new Thread(finalizer); + thread.setName(Finalizer.class.getName()); + thread.setDaemon(true); + try + { + if (inheritableThreadLocals != null) { + inheritableThreadLocals.set(thread, null); + } + } catch (Throwable t) { + logger.log(Level.INFO, "Failed to clear thread local values inherited by reference finalizer thread.", t); + } + + + thread.start(); + } + + + + + + private static final Field inheritableThreadLocals = getInheritableThreadLocalsField(); + + + + + + private Finalizer(Class finalizableReferenceClass, ReferenceQueue queue, PhantomReference frqReference) + { + this.queue = queue; + + finalizableReferenceClassReference = new WeakReference(finalizableReferenceClass); + + + + this.frqReference = frqReference; + } + + + + + + public void run() + { + try + { + while (cleanUp(queue.remove())) {} + } + catch (InterruptedException e) {} + } + + + + + + + + private boolean cleanUp(Reference reference) + { + Method finalizeReferentMethod = getFinalizeReferentMethod(); + if (finalizeReferentMethod == null) { + return false; + } + + + + do + { + reference.clear(); + + if (reference == frqReference) + { + + + + return false; + } + try + { + finalizeReferentMethod.invoke(reference, new Object[0]); + } catch (Throwable t) { + logger.log(Level.SEVERE, "Error cleaning up after reference.", t); + + + } + + + } + while ((reference = queue.poll()) != null); + return true; + } + + + + private Method getFinalizeReferentMethod() + { + Class finalizableReferenceClass = (Class)finalizableReferenceClassReference.get(); + + if (finalizableReferenceClass == null) + { + + + + + + + + return null; + } + try { + return finalizableReferenceClass.getMethod("finalizeReferent", new Class[0]); + } catch (NoSuchMethodException e) { + throw new AssertionError(e); + } + } + + public static Field getInheritableThreadLocalsField() { + try { + Field inheritableThreadLocals = Thread.class.getDeclaredField("inheritableThreadLocals"); + + inheritableThreadLocals.setAccessible(true); + return inheritableThreadLocals; + } catch (Throwable t) { + logger.log(Level.INFO, "Couldn't access Thread.inheritableThreadLocals. Reference finalizer threads will inherit thread local values."); + } + + return null; + } +} diff --git a/src/minecraft/com/google/common/base/package-info.java b/src/minecraft/com/google/common/base/package-info.java new file mode 100644 index 0000000..67ce0f6 --- /dev/null +++ b/src/minecraft/com/google/common/base/package-info.java @@ -0,0 +1,6 @@ +package com.google.common.base; + +import javax.annotation.ParametersAreNonnullByDefault; + +@ParametersAreNonnullByDefault +abstract interface package-info {} diff --git a/src/minecraft/com/google/common/cache/AbstractCache.java b/src/minecraft/com/google/common/cache/AbstractCache.java new file mode 100644 index 0000000..dafb52f --- /dev/null +++ b/src/minecraft/com/google/common/cache/AbstractCache.java @@ -0,0 +1,291 @@ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +public abstract class AbstractCache + implements Cache +{ + protected AbstractCache() {} + + public V get(K key, Callable valueLoader) + throws ExecutionException + { + throw new UnsupportedOperationException(); + } + + + + + + + + + + + public ImmutableMap getAllPresent(Iterable keys) + { + Map result = Maps.newLinkedHashMap(); + for (Object key : keys) { + if (!result.containsKey(key)) + { + K castKey = key; + result.put(castKey, getIfPresent(key)); + } + } + return ImmutableMap.copyOf(result); + } + + + + + public void put(K key, V value) + { + throw new UnsupportedOperationException(); + } + + + + + public void putAll(Map m) + { + for (Map.Entry entry : m.entrySet()) { + put(entry.getKey(), entry.getValue()); + } + } + + + public void cleanUp() {} + + public long size() + { + throw new UnsupportedOperationException(); + } + + public void invalidate(Object key) + { + throw new UnsupportedOperationException(); + } + + + + + public void invalidateAll(Iterable keys) + { + for (Object key : keys) { + invalidate(key); + } + } + + public void invalidateAll() + { + throw new UnsupportedOperationException(); + } + + public CacheStats stats() + { + throw new UnsupportedOperationException(); + } + + public ConcurrentMap asMap() + { + throw new UnsupportedOperationException(); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @Beta + public static final class SimpleStatsCounter + implements AbstractCache.StatsCounter + { + private final LongAddable hitCount = LongAddables.create(); + private final LongAddable missCount = LongAddables.create(); + private final LongAddable loadSuccessCount = LongAddables.create(); + private final LongAddable loadExceptionCount = LongAddables.create(); + private final LongAddable totalLoadTime = LongAddables.create(); + private final LongAddable evictionCount = LongAddables.create(); + + + + + public SimpleStatsCounter() {} + + + + + public void recordHits(int count) + { + hitCount.add(count); + } + + + + + public void recordMisses(int count) + { + missCount.add(count); + } + + public void recordLoadSuccess(long loadTime) + { + loadSuccessCount.increment(); + totalLoadTime.add(loadTime); + } + + public void recordLoadException(long loadTime) + { + loadExceptionCount.increment(); + totalLoadTime.add(loadTime); + } + + public void recordEviction() + { + evictionCount.increment(); + } + + public CacheStats snapshot() + { + return new CacheStats(hitCount.sum(), missCount.sum(), loadSuccessCount.sum(), loadExceptionCount.sum(), totalLoadTime.sum(), evictionCount.sum()); + } + + + + + + + + + + public void incrementBy(AbstractCache.StatsCounter other) + { + CacheStats otherStats = other.snapshot(); + hitCount.add(otherStats.hitCount()); + missCount.add(otherStats.missCount()); + loadSuccessCount.add(otherStats.loadSuccessCount()); + loadExceptionCount.add(otherStats.loadExceptionCount()); + totalLoadTime.add(otherStats.totalLoadTime()); + evictionCount.add(otherStats.evictionCount()); + } + } + + @Beta + public static abstract interface StatsCounter + { + public abstract void recordHits(int paramInt); + + public abstract void recordMisses(int paramInt); + + public abstract void recordLoadSuccess(long paramLong); + + public abstract void recordLoadException(long paramLong); + + public abstract void recordEviction(); + + public abstract CacheStats snapshot(); + } +} diff --git a/src/minecraft/com/google/common/cache/AbstractLoadingCache.java b/src/minecraft/com/google/common/cache/AbstractLoadingCache.java new file mode 100644 index 0000000..07376d8 --- /dev/null +++ b/src/minecraft/com/google/common/cache/AbstractLoadingCache.java @@ -0,0 +1,79 @@ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import com.google.common.util.concurrent.UncheckedExecutionException; +import java.util.Map; +import java.util.concurrent.ExecutionException; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public abstract class AbstractLoadingCache + extends AbstractCache + implements LoadingCache +{ + protected AbstractLoadingCache() {} + + public V getUnchecked(K key) + { + try + { + return get(key); + } catch (ExecutionException e) { + throw new UncheckedExecutionException(e.getCause()); + } + } + + public ImmutableMap getAll(Iterable keys) throws ExecutionException + { + Map result = Maps.newLinkedHashMap(); + for (K key : keys) { + if (!result.containsKey(key)) { + result.put(key, get(key)); + } + } + return ImmutableMap.copyOf(result); + } + + public final V apply(K key) + { + return getUnchecked(key); + } + + public void refresh(K key) + { + throw new UnsupportedOperationException(); + } +} diff --git a/src/minecraft/com/google/common/cache/Cache.java b/src/minecraft/com/google/common/cache/Cache.java new file mode 100644 index 0000000..01bc162 --- /dev/null +++ b/src/minecraft/com/google/common/cache/Cache.java @@ -0,0 +1,41 @@ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.collect.ImmutableMap; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; +import javax.annotation.Nullable; + +@Beta +@GwtCompatible +public abstract interface Cache +{ + @Nullable + public abstract V getIfPresent(Object paramObject); + + public abstract V get(K paramK, Callable paramCallable) + throws ExecutionException; + + public abstract ImmutableMap getAllPresent(Iterable paramIterable); + + public abstract void put(K paramK, V paramV); + + public abstract void putAll(Map paramMap); + + public abstract void invalidate(Object paramObject); + + public abstract void invalidateAll(Iterable paramIterable); + + public abstract void invalidateAll(); + + public abstract long size(); + + public abstract CacheStats stats(); + + public abstract ConcurrentMap asMap(); + + public abstract void cleanUp(); +} diff --git a/src/minecraft/com/google/common/cache/CacheBuilder.java b/src/minecraft/com/google/common/cache/CacheBuilder.java new file mode 100644 index 0000000..f1e762f --- /dev/null +++ b/src/minecraft/com/google/common/cache/CacheBuilder.java @@ -0,0 +1,891 @@ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Ascii; +import com.google.common.base.Equivalence; +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import com.google.common.base.Ticker; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.CheckReturnValue; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public final class CacheBuilder +{ + private static final int DEFAULT_INITIAL_CAPACITY = 16; + private static final int DEFAULT_CONCURRENCY_LEVEL = 4; + private static final int DEFAULT_EXPIRATION_NANOS = 0; + private static final int DEFAULT_REFRESH_NANOS = 0; + static final Supplier NULL_STATS_COUNTER = Suppliers.ofInstance(new AbstractCache.StatsCounter() + { + public void recordHits(int count) {} + + + public void recordMisses(int count) {} + + + public void recordLoadSuccess(long loadTime) {} + + + public void recordLoadException(long loadTime) {} + + + public void recordEviction() {} + + + public CacheStats snapshot() + { + return CacheBuilder.EMPTY_STATS; + } + }); + + + + + + + + + + + + + + + + + + + + + + static final CacheStats EMPTY_STATS = new CacheStats(0L, 0L, 0L, 0L, 0L, 0L); + + static final Supplier CACHE_STATS_COUNTER = new Supplier() + { + + public AbstractCache.StatsCounter get() { + return new AbstractCache.SimpleStatsCounter(); } + }; + CacheBuilder() {} + + static enum NullListener implements RemovalListener { + INSTANCE; + + private NullListener() {} + + public void onRemoval(RemovalNotification notification) {} + } + + static enum OneWeigher implements Weigher { INSTANCE; + + private OneWeigher() {} + + public int weigh(Object key, Object value) { return 1; } + } + + + static final Ticker NULL_TICKER = new Ticker() + { + public long read() { + return 0L; + } + }; + + private static final Logger logger = Logger.getLogger(CacheBuilder.class.getName()); + + static final int UNSET_INT = -1; + + boolean strictParsing = true; + + int initialCapacity = -1; + int concurrencyLevel = -1; + long maximumSize = -1L; + long maximumWeight = -1L; + + Weigher weigher; + + LocalCache.Strength keyStrength; + LocalCache.Strength valueStrength; + long expireAfterWriteNanos = -1L; + long expireAfterAccessNanos = -1L; + long refreshNanos = -1L; + + Equivalence keyEquivalence; + + Equivalence valueEquivalence; + + RemovalListener removalListener; + Ticker ticker; + Supplier statsCounterSupplier = NULL_STATS_COUNTER; + + + + + + + + public static CacheBuilder newBuilder() + { + return new CacheBuilder(); + } + + + + + + @Beta + @GwtIncompatible("To be supported") + public static CacheBuilder from(CacheBuilderSpec spec) + { + return spec.toCacheBuilder().lenientParsing(); + } + + + + + + + + + @Beta + @GwtIncompatible("To be supported") + public static CacheBuilder from(String spec) + { + return from(CacheBuilderSpec.parse(spec)); + } + + + + @GwtIncompatible("To be supported") + CacheBuilder lenientParsing() + { + strictParsing = false; + return this; + } + + + + + + + @GwtIncompatible("To be supported") + CacheBuilder keyEquivalence(Equivalence equivalence) + { + Preconditions.checkState(keyEquivalence == null, "key equivalence was already set to %s", new Object[] { keyEquivalence }); + keyEquivalence = ((Equivalence)Preconditions.checkNotNull(equivalence)); + return this; + } + + Equivalence getKeyEquivalence() { + return (Equivalence)Objects.firstNonNull(keyEquivalence, getKeyStrength().defaultEquivalence()); + } + + + + + + + + @GwtIncompatible("To be supported") + CacheBuilder valueEquivalence(Equivalence equivalence) + { + Preconditions.checkState(valueEquivalence == null, "value equivalence was already set to %s", new Object[] { valueEquivalence }); + + valueEquivalence = ((Equivalence)Preconditions.checkNotNull(equivalence)); + return this; + } + + Equivalence getValueEquivalence() { + return (Equivalence)Objects.firstNonNull(valueEquivalence, getValueStrength().defaultEquivalence()); + } + + + + + + + + + + + public CacheBuilder initialCapacity(int initialCapacity) + { + Preconditions.checkState(this.initialCapacity == -1, "initial capacity was already set to %s", new Object[] { Integer.valueOf(this.initialCapacity) }); + + Preconditions.checkArgument(initialCapacity >= 0); + this.initialCapacity = initialCapacity; + return this; + } + + int getInitialCapacity() { + return initialCapacity == -1 ? 16 : initialCapacity; + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public CacheBuilder concurrencyLevel(int concurrencyLevel) + { + Preconditions.checkState(this.concurrencyLevel == -1, "concurrency level was already set to %s", new Object[] { Integer.valueOf(this.concurrencyLevel) }); + + Preconditions.checkArgument(concurrencyLevel > 0); + this.concurrencyLevel = concurrencyLevel; + return this; + } + + int getConcurrencyLevel() { + return concurrencyLevel == -1 ? 4 : concurrencyLevel; + } + + + + + + + + + + + + + + + + public CacheBuilder maximumSize(long size) + { + Preconditions.checkState(maximumSize == -1L, "maximum size was already set to %s", new Object[] { Long.valueOf(maximumSize) }); + + Preconditions.checkState(maximumWeight == -1L, "maximum weight was already set to %s", new Object[] { Long.valueOf(maximumWeight) }); + + Preconditions.checkState(weigher == null, "maximum size can not be combined with weigher"); + Preconditions.checkArgument(size >= 0L, "maximum size must not be negative"); + maximumSize = size; + return this; + } + + + + + + + + + + + + + + + + + + + + + + + + + @GwtIncompatible("To be supported") + public CacheBuilder maximumWeight(long weight) + { + Preconditions.checkState(maximumWeight == -1L, "maximum weight was already set to %s", new Object[] { Long.valueOf(maximumWeight) }); + + Preconditions.checkState(maximumSize == -1L, "maximum size was already set to %s", new Object[] { Long.valueOf(maximumSize) }); + + maximumWeight = weight; + Preconditions.checkArgument(weight >= 0L, "maximum weight must not be negative"); + return this; + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @GwtIncompatible("To be supported") + public CacheBuilder weigher(Weigher weigher) + { + Preconditions.checkState(this.weigher == null); + if (strictParsing) { + Preconditions.checkState(maximumSize == -1L, "weigher can not be combined with maximum size", new Object[] { Long.valueOf(maximumSize) }); + } + + + + + CacheBuilder me = this; + weigher = ((Weigher)Preconditions.checkNotNull(weigher)); + return me; + } + + long getMaximumWeight() { + if ((expireAfterWriteNanos == 0L) || (expireAfterAccessNanos == 0L)) { + return 0L; + } + return weigher == null ? maximumSize : maximumWeight; + } + + + Weigher getWeigher() + { + return (Weigher)Objects.firstNonNull(weigher, OneWeigher.INSTANCE); + } + + + + + + + + + + + + + + @GwtIncompatible("java.lang.ref.WeakReference") + public CacheBuilder weakKeys() + { + return setKeyStrength(LocalCache.Strength.WEAK); + } + + CacheBuilder setKeyStrength(LocalCache.Strength strength) { + Preconditions.checkState(keyStrength == null, "Key strength was already set to %s", new Object[] { keyStrength }); + keyStrength = ((LocalCache.Strength)Preconditions.checkNotNull(strength)); + return this; + } + + LocalCache.Strength getKeyStrength() { + return (LocalCache.Strength)Objects.firstNonNull(keyStrength, LocalCache.Strength.STRONG); + } + + + + + + + + + + + + + + + + + @GwtIncompatible("java.lang.ref.WeakReference") + public CacheBuilder weakValues() + { + return setValueStrength(LocalCache.Strength.WEAK); + } + + + + + + + + + + + + + + + + + + + + @GwtIncompatible("java.lang.ref.SoftReference") + public CacheBuilder softValues() + { + return setValueStrength(LocalCache.Strength.SOFT); + } + + CacheBuilder setValueStrength(LocalCache.Strength strength) { + Preconditions.checkState(valueStrength == null, "Value strength was already set to %s", new Object[] { valueStrength }); + valueStrength = ((LocalCache.Strength)Preconditions.checkNotNull(strength)); + return this; + } + + LocalCache.Strength getValueStrength() { + return (LocalCache.Strength)Objects.firstNonNull(valueStrength, LocalCache.Strength.STRONG); + } + + + + + + + + + + + + + + + + + + + + public CacheBuilder expireAfterWrite(long duration, TimeUnit unit) + { + Preconditions.checkState(expireAfterWriteNanos == -1L, "expireAfterWrite was already set to %s ns", new Object[] { Long.valueOf(expireAfterWriteNanos) }); + + Preconditions.checkArgument(duration >= 0L, "duration cannot be negative: %s %s", new Object[] { Long.valueOf(duration), unit }); + expireAfterWriteNanos = unit.toNanos(duration); + return this; + } + + long getExpireAfterWriteNanos() { + return expireAfterWriteNanos == -1L ? 0L : expireAfterWriteNanos; + } + + + + + + + + + + + + + + + + + + + + + + + public CacheBuilder expireAfterAccess(long duration, TimeUnit unit) + { + Preconditions.checkState(expireAfterAccessNanos == -1L, "expireAfterAccess was already set to %s ns", new Object[] { Long.valueOf(expireAfterAccessNanos) }); + + Preconditions.checkArgument(duration >= 0L, "duration cannot be negative: %s %s", new Object[] { Long.valueOf(duration), unit }); + expireAfterAccessNanos = unit.toNanos(duration); + return this; + } + + long getExpireAfterAccessNanos() { + return expireAfterAccessNanos == -1L ? 0L : expireAfterAccessNanos; + } + + + + + + + + + + + + + + + + + + + + + + + + + + + @Beta + @GwtIncompatible("To be supported (synchronously).") + public CacheBuilder refreshAfterWrite(long duration, TimeUnit unit) + { + Preconditions.checkNotNull(unit); + Preconditions.checkState(refreshNanos == -1L, "refresh was already set to %s ns", new Object[] { Long.valueOf(refreshNanos) }); + Preconditions.checkArgument(duration > 0L, "duration must be positive: %s %s", new Object[] { Long.valueOf(duration), unit }); + refreshNanos = unit.toNanos(duration); + return this; + } + + long getRefreshNanos() { + return refreshNanos == -1L ? 0L : refreshNanos; + } + + + + + + + + + + public CacheBuilder ticker(Ticker ticker) + { + Preconditions.checkState(this.ticker == null); + this.ticker = ((Ticker)Preconditions.checkNotNull(ticker)); + return this; + } + + Ticker getTicker(boolean recordsTime) { + if (ticker != null) { + return ticker; + } + return recordsTime ? Ticker.systemTicker() : NULL_TICKER; + } + + + + + + + + + + + + + + + + + + + + + + + @CheckReturnValue + public CacheBuilder removalListener(RemovalListener listener) + { + Preconditions.checkState(removalListener == null); + + + + CacheBuilder me = this; + removalListener = ((RemovalListener)Preconditions.checkNotNull(listener)); + return me; + } + + + RemovalListener getRemovalListener() + { + return (RemovalListener)Objects.firstNonNull(removalListener, NullListener.INSTANCE); + } + + + + + + + + + public CacheBuilder recordStats() + { + statsCounterSupplier = CACHE_STATS_COUNTER; + return this; + } + + boolean isRecordingStats() { + return statsCounterSupplier == CACHE_STATS_COUNTER; + } + + Supplier getStatsCounterSupplier() { + return statsCounterSupplier; + } + + + + + + + + + + + + + + public LoadingCache build(CacheLoader loader) + { + checkWeightWithWeigher(); + return new LocalCache.LocalLoadingCache(this, loader); + } + + + + + + + + + + + + + public Cache build() + { + checkWeightWithWeigher(); + checkNonLoadingCache(); + return new LocalCache.LocalManualCache(this); + } + + private void checkNonLoadingCache() { + Preconditions.checkState(refreshNanos == -1L, "refreshAfterWrite requires a LoadingCache"); + } + + private void checkWeightWithWeigher() { + if (weigher == null) { + Preconditions.checkState(maximumWeight == -1L, "maximumWeight requires weigher"); + } + else if (strictParsing) { + Preconditions.checkState(maximumWeight != -1L, "weigher requires maximumWeight"); + } + else if (maximumWeight == -1L) { + logger.log(Level.WARNING, "ignoring weigher specified without maximumWeight"); + } + } + + + + + + + + public String toString() + { + Objects.ToStringHelper s = Objects.toStringHelper(this); + if (initialCapacity != -1) { + s.add("initialCapacity", initialCapacity); + } + if (concurrencyLevel != -1) { + s.add("concurrencyLevel", concurrencyLevel); + } + if (maximumSize != -1L) { + s.add("maximumSize", maximumSize); + } + if (maximumWeight != -1L) { + s.add("maximumWeight", maximumWeight); + } + if (expireAfterWriteNanos != -1L) { + s.add("expireAfterWrite", expireAfterWriteNanos + "ns"); + } + if (expireAfterAccessNanos != -1L) { + s.add("expireAfterAccess", expireAfterAccessNanos + "ns"); + } + if (keyStrength != null) { + s.add("keyStrength", Ascii.toLowerCase(keyStrength.toString())); + } + if (valueStrength != null) { + s.add("valueStrength", Ascii.toLowerCase(valueStrength.toString())); + } + if (keyEquivalence != null) { + s.addValue("keyEquivalence"); + } + if (valueEquivalence != null) { + s.addValue("valueEquivalence"); + } + if (removalListener != null) { + s.addValue("removalListener"); + } + return s.toString(); + } +} diff --git a/src/minecraft/com/google/common/cache/CacheBuilderSpec.java b/src/minecraft/com/google/common/cache/CacheBuilderSpec.java new file mode 100644 index 0000000..4403e39 --- /dev/null +++ b/src/minecraft/com/google/common/cache/CacheBuilderSpec.java @@ -0,0 +1,474 @@ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; +import com.google.common.base.Preconditions; +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMap.Builder; +import java.util.List; +import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class CacheBuilderSpec +{ + private static final Splitter KEYS_SPLITTER = Splitter.on(',').trimResults(); + + + private static final Splitter KEY_VALUE_SPLITTER = Splitter.on('=').trimResults(); + + + private static final ImmutableMap VALUE_PARSERS = ImmutableMap.builder().put("initialCapacity", new InitialCapacityParser()).put("maximumSize", new MaximumSizeParser()).put("maximumWeight", new MaximumWeightParser()).put("concurrencyLevel", new ConcurrencyLevelParser()).put("weakKeys", new KeyStrengthParser(LocalCache.Strength.WEAK)).put("softValues", new ValueStrengthParser(LocalCache.Strength.SOFT)).put("weakValues", new ValueStrengthParser(LocalCache.Strength.WEAK)).put("recordStats", new RecordStatsParser()).put("expireAfterAccess", new AccessDurationParser()).put("expireAfterWrite", new WriteDurationParser()).put("refreshAfterWrite", new RefreshDurationParser()).put("refreshInterval", new RefreshDurationParser()).build(); + + @VisibleForTesting + Integer initialCapacity; + + @VisibleForTesting + Long maximumSize; + @VisibleForTesting + Long maximumWeight; + @VisibleForTesting + Integer concurrencyLevel; + @VisibleForTesting + LocalCache.Strength keyStrength; + @VisibleForTesting + LocalCache.Strength valueStrength; + @VisibleForTesting + Boolean recordStats; + @VisibleForTesting + long writeExpirationDuration; + @VisibleForTesting + TimeUnit writeExpirationTimeUnit; + @VisibleForTesting + long accessExpirationDuration; + @VisibleForTesting + TimeUnit accessExpirationTimeUnit; + @VisibleForTesting + long refreshDuration; + @VisibleForTesting + TimeUnit refreshTimeUnit; + private final String specification; + + private CacheBuilderSpec(String specification) + { + this.specification = specification; + } + + + + + + public static CacheBuilderSpec parse(String cacheBuilderSpecification) + { + CacheBuilderSpec spec = new CacheBuilderSpec(cacheBuilderSpecification); + if (!cacheBuilderSpecification.isEmpty()) { + for (String keyValuePair : KEYS_SPLITTER.split(cacheBuilderSpecification)) { + List keyAndValue = ImmutableList.copyOf(KEY_VALUE_SPLITTER.split(keyValuePair)); + Preconditions.checkArgument(!keyAndValue.isEmpty(), "blank key-value pair"); + Preconditions.checkArgument(keyAndValue.size() <= 2, "key-value pair %s with more than one equals sign", new Object[] { keyValuePair }); + + + + String key = (String)keyAndValue.get(0); + ValueParser valueParser = (ValueParser)VALUE_PARSERS.get(key); + Preconditions.checkArgument(valueParser != null, "unknown key %s", new Object[] { key }); + + String value = keyAndValue.size() == 1 ? null : (String)keyAndValue.get(1); + valueParser.parse(spec, key, value); + } + } + + return spec; + } + + + + + public static CacheBuilderSpec disableCaching() + { + return parse("maximumSize=0"); + } + + + + CacheBuilder toCacheBuilder() + { + CacheBuilder builder = CacheBuilder.newBuilder(); + if (initialCapacity != null) { + builder.initialCapacity(initialCapacity.intValue()); + } + if (maximumSize != null) { + builder.maximumSize(maximumSize.longValue()); + } + if (maximumWeight != null) { + builder.maximumWeight(maximumWeight.longValue()); + } + if (concurrencyLevel != null) { + builder.concurrencyLevel(concurrencyLevel.intValue()); + } + if (keyStrength != null) { + switch (1.$SwitchMap$com$google$common$cache$LocalCache$Strength[keyStrength.ordinal()]) { + case 1: + builder.weakKeys(); + break; + default: + throw new AssertionError(); + } + } + if (valueStrength != null) { + switch (1.$SwitchMap$com$google$common$cache$LocalCache$Strength[valueStrength.ordinal()]) { + case 2: + builder.softValues(); + break; + case 1: + builder.weakValues(); + break; + default: + throw new AssertionError(); + } + } + if ((recordStats != null) && (recordStats.booleanValue())) { + builder.recordStats(); + } + if (writeExpirationTimeUnit != null) { + builder.expireAfterWrite(writeExpirationDuration, writeExpirationTimeUnit); + } + if (accessExpirationTimeUnit != null) { + builder.expireAfterAccess(accessExpirationDuration, accessExpirationTimeUnit); + } + if (refreshTimeUnit != null) { + builder.refreshAfterWrite(refreshDuration, refreshTimeUnit); + } + + return builder; + } + + + + + + + public String toParsableString() + { + return specification; + } + + + + + + public String toString() + { + return Objects.toStringHelper(this).addValue(toParsableString()).toString(); + } + + public int hashCode() + { + return Objects.hashCode(new Object[] { initialCapacity, maximumSize, maximumWeight, concurrencyLevel, keyStrength, valueStrength, recordStats, durationInNanos(writeExpirationDuration, writeExpirationTimeUnit), durationInNanos(accessExpirationDuration, accessExpirationTimeUnit), durationInNanos(refreshDuration, refreshTimeUnit) }); + } + + + + + + + + + + + + public boolean equals(@Nullable Object obj) + { + if (this == obj) { + return true; + } + if (!(obj instanceof CacheBuilderSpec)) { + return false; + } + CacheBuilderSpec that = (CacheBuilderSpec)obj; + return (Objects.equal(initialCapacity, initialCapacity)) && (Objects.equal(maximumSize, maximumSize)) && (Objects.equal(maximumWeight, maximumWeight)) && (Objects.equal(concurrencyLevel, concurrencyLevel)) && (Objects.equal(keyStrength, keyStrength)) && (Objects.equal(valueStrength, valueStrength)) && (Objects.equal(recordStats, recordStats)) && (Objects.equal(durationInNanos(writeExpirationDuration, writeExpirationTimeUnit), durationInNanos(writeExpirationDuration, writeExpirationTimeUnit))) && (Objects.equal(durationInNanos(accessExpirationDuration, accessExpirationTimeUnit), durationInNanos(accessExpirationDuration, accessExpirationTimeUnit))) && (Objects.equal(durationInNanos(refreshDuration, refreshTimeUnit), durationInNanos(refreshDuration, refreshTimeUnit))); + } + + + + + + + + + + + + + + + + + + @Nullable + private static Long durationInNanos(long duration, @Nullable TimeUnit unit) { return unit == null ? null : Long.valueOf(unit.toNanos(duration)); } + + private static abstract interface ValueParser { public abstract void parse(CacheBuilderSpec paramCacheBuilderSpec, String paramString1, @Nullable String paramString2); + } + + static abstract class IntegerParser implements CacheBuilderSpec.ValueParser { IntegerParser() {} + + protected abstract void parseInteger(CacheBuilderSpec paramCacheBuilderSpec, int paramInt); + + public void parse(CacheBuilderSpec spec, String key, String value) { Preconditions.checkArgument((value != null) && (!value.isEmpty()), "value of key %s omitted", new Object[] { key }); + try { + parseInteger(spec, Integer.parseInt(value)); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(String.format("key %s value set to %s, must be integer", new Object[] { key, value }), e); + } + } + } + + static abstract class LongParser implements CacheBuilderSpec.ValueParser + { + LongParser() {} + + protected abstract void parseLong(CacheBuilderSpec paramCacheBuilderSpec, long paramLong); + + public void parse(CacheBuilderSpec spec, String key, String value) { + Preconditions.checkArgument((value != null) && (!value.isEmpty()), "value of key %s omitted", new Object[] { key }); + try { + parseLong(spec, Long.parseLong(value)); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(String.format("key %s value set to %s, must be integer", new Object[] { key, value }), e); + } + } + } + + static class InitialCapacityParser extends CacheBuilderSpec.IntegerParser + { + InitialCapacityParser() {} + + protected void parseInteger(CacheBuilderSpec spec, int value) { + Preconditions.checkArgument(initialCapacity == null, "initial capacity was already set to ", new Object[] { initialCapacity }); + + initialCapacity = Integer.valueOf(value); + } + } + + static class MaximumSizeParser extends CacheBuilderSpec.LongParser { + MaximumSizeParser() {} + + protected void parseLong(CacheBuilderSpec spec, long value) { + Preconditions.checkArgument(maximumSize == null, "maximum size was already set to ", new Object[] { maximumSize }); + + Preconditions.checkArgument(maximumWeight == null, "maximum weight was already set to ", new Object[] { maximumWeight }); + + maximumSize = Long.valueOf(value); + } + } + + static class MaximumWeightParser extends CacheBuilderSpec.LongParser { + MaximumWeightParser() {} + + protected void parseLong(CacheBuilderSpec spec, long value) { + Preconditions.checkArgument(maximumWeight == null, "maximum weight was already set to ", new Object[] { maximumWeight }); + + Preconditions.checkArgument(maximumSize == null, "maximum size was already set to ", new Object[] { maximumSize }); + + maximumWeight = Long.valueOf(value); + } + } + + static class ConcurrencyLevelParser extends CacheBuilderSpec.IntegerParser { + ConcurrencyLevelParser() {} + + protected void parseInteger(CacheBuilderSpec spec, int value) { + Preconditions.checkArgument(concurrencyLevel == null, "concurrency level was already set to ", new Object[] { concurrencyLevel }); + + concurrencyLevel = Integer.valueOf(value); + } + } + + static class KeyStrengthParser implements CacheBuilderSpec.ValueParser + { + private final LocalCache.Strength strength; + + public KeyStrengthParser(LocalCache.Strength strength) { + this.strength = strength; + } + + public void parse(CacheBuilderSpec spec, String key, @Nullable String value) + { + Preconditions.checkArgument(value == null, "key %s does not take values", new Object[] { key }); + Preconditions.checkArgument(keyStrength == null, "%s was already set to %s", new Object[] { key, keyStrength }); + keyStrength = strength; + } + } + + static class ValueStrengthParser implements CacheBuilderSpec.ValueParser + { + private final LocalCache.Strength strength; + + public ValueStrengthParser(LocalCache.Strength strength) { + this.strength = strength; + } + + public void parse(CacheBuilderSpec spec, String key, @Nullable String value) + { + Preconditions.checkArgument(value == null, "key %s does not take values", new Object[] { key }); + Preconditions.checkArgument(valueStrength == null, "%s was already set to %s", new Object[] { key, valueStrength }); + + + valueStrength = strength; + } + } + + static class RecordStatsParser implements CacheBuilderSpec.ValueParser + { + RecordStatsParser() {} + + public void parse(CacheBuilderSpec spec, String key, @Nullable String value) { + Preconditions.checkArgument(value == null, "recordStats does not take values"); + Preconditions.checkArgument(recordStats == null, "recordStats already set"); + recordStats = Boolean.valueOf(true); + } + } + + static abstract class DurationParser + implements CacheBuilderSpec.ValueParser + { + DurationParser() {} + + protected abstract void parseDuration(CacheBuilderSpec paramCacheBuilderSpec, long paramLong, TimeUnit paramTimeUnit); + + public void parse(CacheBuilderSpec spec, String key, String value) + { + Preconditions.checkArgument((value != null) && (!value.isEmpty()), "value of key %s omitted", new Object[] { key }); + try { + char lastChar = value.charAt(value.length() - 1); + TimeUnit timeUnit; + switch (lastChar) { + case 'd': + timeUnit = TimeUnit.DAYS; + break; + case 'h': + timeUnit = TimeUnit.HOURS; + break; + case 'm': + timeUnit = TimeUnit.MINUTES; + break; + case 's': + timeUnit = TimeUnit.SECONDS; + break; + default: + throw new IllegalArgumentException(String.format("key %s invalid format. was %s, must end with one of [dDhHmMsS]", new Object[] { key, value })); + } + + + + long duration = Long.parseLong(value.substring(0, value.length() - 1)); + parseDuration(spec, duration, timeUnit); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(String.format("key %s value set to %s, must be integer", new Object[] { key, value })); + } + } + } + + static class AccessDurationParser extends CacheBuilderSpec.DurationParser { + AccessDurationParser() {} + + protected void parseDuration(CacheBuilderSpec spec, long duration, TimeUnit unit) { + Preconditions.checkArgument(accessExpirationTimeUnit == null, "expireAfterAccess already set"); + accessExpirationDuration = duration; + accessExpirationTimeUnit = unit; + } + } + + static class WriteDurationParser extends CacheBuilderSpec.DurationParser { + WriteDurationParser() {} + + protected void parseDuration(CacheBuilderSpec spec, long duration, TimeUnit unit) { Preconditions.checkArgument(writeExpirationTimeUnit == null, "expireAfterWrite already set"); + writeExpirationDuration = duration; + writeExpirationTimeUnit = unit; + } + } + + static class RefreshDurationParser extends CacheBuilderSpec.DurationParser { + RefreshDurationParser() {} + + protected void parseDuration(CacheBuilderSpec spec, long duration, TimeUnit unit) { Preconditions.checkArgument(refreshTimeUnit == null, "refreshAfterWrite already set"); + refreshDuration = duration; + refreshTimeUnit = unit; + } + } +} diff --git a/src/minecraft/com/google/common/cache/CacheLoader.java b/src/minecraft/com/google/common/cache/CacheLoader.java new file mode 100644 index 0000000..8de03f1 --- /dev/null +++ b/src/minecraft/com/google/common/cache/CacheLoader.java @@ -0,0 +1,240 @@ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListenableFutureTask; +import java.io.Serializable; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.Executor; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public abstract class CacheLoader +{ + protected CacheLoader() {} + + public abstract V load(K paramK) + throws Exception; + + @GwtIncompatible("Futures") + public ListenableFuture reload(K key, V oldValue) + throws Exception + { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(oldValue); + return Futures.immediateFuture(load(key)); + } + + + + + + + + + + + + + + + + + + + + + + + + public Map loadAll(Iterable keys) + throws Exception + { + throw new UnsupportedLoadingOperationException(); + } + + + + + + + + + @Beta + public static CacheLoader from(Function function) + { + return new FunctionToCacheLoader(function); + } + + private static final class FunctionToCacheLoader extends CacheLoader implements Serializable { + private final Function computingFunction; + private static final long serialVersionUID = 0L; + + public FunctionToCacheLoader(Function computingFunction) { + this.computingFunction = ((Function)Preconditions.checkNotNull(computingFunction)); + } + + public V load(K key) + { + return computingFunction.apply(Preconditions.checkNotNull(key)); + } + } + + + + + + + + + + + + @Beta + public static CacheLoader from(Supplier supplier) + { + return new SupplierToCacheLoader(supplier); + } + + + + + + + + + + + @Beta + @GwtIncompatible("Executor + Futures") + public static CacheLoader asyncReloading(CacheLoader loader, final Executor executor) + { + Preconditions.checkNotNull(loader); + Preconditions.checkNotNull(executor); + new CacheLoader() + { + public V load(K key) throws Exception { + return val$loader.load(key); + } + + public ListenableFuture reload(final K key, final V oldValue) throws Exception + { + ListenableFutureTask task = ListenableFutureTask.create(new Callable() + { + public V call() throws Exception { + return val$loader.reload(key, oldValue).get(); + } + }); + executor.execute(task); + return task; + } + + public Map loadAll(Iterable keys) throws Exception + { + return val$loader.loadAll(keys); + } + }; + } + + private static final class SupplierToCacheLoader extends CacheLoader implements Serializable { + private final Supplier computingSupplier; + private static final long serialVersionUID = 0L; + + public SupplierToCacheLoader(Supplier computingSupplier) { + this.computingSupplier = ((Supplier)Preconditions.checkNotNull(computingSupplier)); + } + + public V load(Object key) + { + Preconditions.checkNotNull(key); + return computingSupplier.get(); + } + } + + static final class UnsupportedLoadingOperationException + extends UnsupportedOperationException + { + UnsupportedLoadingOperationException() {} + } + + public static final class InvalidCacheLoadException + extends RuntimeException + { + public InvalidCacheLoadException(String message) + { + super(); + } + } +} diff --git a/src/minecraft/com/google/common/cache/CacheStats.java b/src/minecraft/com/google/common/cache/CacheStats.java new file mode 100644 index 0000000..94772cf --- /dev/null +++ b/src/minecraft/com/google/common/cache/CacheStats.java @@ -0,0 +1,269 @@ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; +import com.google.common.base.Preconditions; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +public final class CacheStats +{ + private final long hitCount; + private final long missCount; + private final long loadSuccessCount; + private final long loadExceptionCount; + private final long totalLoadTime; + private final long evictionCount; + + public CacheStats(long hitCount, long missCount, long loadSuccessCount, long loadExceptionCount, long totalLoadTime, long evictionCount) + { + Preconditions.checkArgument(hitCount >= 0L); + Preconditions.checkArgument(missCount >= 0L); + Preconditions.checkArgument(loadSuccessCount >= 0L); + Preconditions.checkArgument(loadExceptionCount >= 0L); + Preconditions.checkArgument(totalLoadTime >= 0L); + Preconditions.checkArgument(evictionCount >= 0L); + + this.hitCount = hitCount; + this.missCount = missCount; + this.loadSuccessCount = loadSuccessCount; + this.loadExceptionCount = loadExceptionCount; + this.totalLoadTime = totalLoadTime; + this.evictionCount = evictionCount; + } + + + + + public long requestCount() + { + return hitCount + missCount; + } + + + + public long hitCount() + { + return hitCount; + } + + + + + + public double hitRate() + { + long requestCount = requestCount(); + return requestCount == 0L ? 1.0D : hitCount / requestCount; + } + + + + + + + public long missCount() + { + return missCount; + } + + + + + + + + + + public double missRate() + { + long requestCount = requestCount(); + return requestCount == 0L ? 0.0D : missCount / requestCount; + } + + + + + + public long loadCount() + { + return loadSuccessCount + loadExceptionCount; + } + + + + + + + + public long loadSuccessCount() + { + return loadSuccessCount; + } + + + + + + + + public long loadExceptionCount() + { + return loadExceptionCount; + } + + + + + + public double loadExceptionRate() + { + long totalLoadCount = loadSuccessCount + loadExceptionCount; + return totalLoadCount == 0L ? 0.0D : loadExceptionCount / totalLoadCount; + } + + + + + + + + public long totalLoadTime() + { + return totalLoadTime; + } + + + + + public double averageLoadPenalty() + { + long totalLoadCount = loadSuccessCount + loadExceptionCount; + return totalLoadCount == 0L ? 0.0D : totalLoadTime / totalLoadCount; + } + + + + + + + public long evictionCount() + { + return evictionCount; + } + + + + + + public CacheStats minus(CacheStats other) + { + return new CacheStats(Math.max(0L, hitCount - hitCount), Math.max(0L, missCount - missCount), Math.max(0L, loadSuccessCount - loadSuccessCount), Math.max(0L, loadExceptionCount - loadExceptionCount), Math.max(0L, totalLoadTime - totalLoadTime), Math.max(0L, evictionCount - evictionCount)); + } + + + + + + + + + + + + + public CacheStats plus(CacheStats other) + { + return new CacheStats(hitCount + hitCount, missCount + missCount, loadSuccessCount + loadSuccessCount, loadExceptionCount + loadExceptionCount, totalLoadTime + totalLoadTime, evictionCount + evictionCount); + } + + + + + + + + public int hashCode() + { + return Objects.hashCode(new Object[] { Long.valueOf(hitCount), Long.valueOf(missCount), Long.valueOf(loadSuccessCount), Long.valueOf(loadExceptionCount), Long.valueOf(totalLoadTime), Long.valueOf(evictionCount) }); + } + + + public boolean equals(@Nullable Object object) + { + if ((object instanceof CacheStats)) { + CacheStats other = (CacheStats)object; + return (hitCount == hitCount) && (missCount == missCount) && (loadSuccessCount == loadSuccessCount) && (loadExceptionCount == loadExceptionCount) && (totalLoadTime == totalLoadTime) && (evictionCount == evictionCount); + } + + + + + + return false; + } + + public String toString() + { + return Objects.toStringHelper(this).add("hitCount", hitCount).add("missCount", missCount).add("loadSuccessCount", loadSuccessCount).add("loadExceptionCount", loadExceptionCount).add("totalLoadTime", totalLoadTime).add("evictionCount", evictionCount).toString(); + } +} diff --git a/src/minecraft/com/google/common/cache/ForwardingCache.java b/src/minecraft/com/google/common/cache/ForwardingCache.java new file mode 100644 index 0000000..8a4a35f --- /dev/null +++ b/src/minecraft/com/google/common/cache/ForwardingCache.java @@ -0,0 +1,146 @@ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.collect.ForwardingObject; +import com.google.common.collect.ImmutableMap; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public abstract class ForwardingCache + extends ForwardingObject + implements Cache +{ + protected ForwardingCache() {} + + protected abstract Cache delegate(); + + @Nullable + public V getIfPresent(Object key) + { + return delegate().getIfPresent(key); + } + + + + public V get(K key, Callable valueLoader) + throws ExecutionException + { + return delegate().get(key, valueLoader); + } + + + + + public ImmutableMap getAllPresent(Iterable keys) + { + return delegate().getAllPresent(keys); + } + + + + + public void put(K key, V value) + { + delegate().put(key, value); + } + + + + + public void putAll(Map m) + { + delegate().putAll(m); + } + + public void invalidate(Object key) + { + delegate().invalidate(key); + } + + + + + public void invalidateAll(Iterable keys) + { + delegate().invalidateAll(keys); + } + + public void invalidateAll() + { + delegate().invalidateAll(); + } + + public long size() + { + return delegate().size(); + } + + public CacheStats stats() + { + return delegate().stats(); + } + + public ConcurrentMap asMap() + { + return delegate().asMap(); + } + + public void cleanUp() + { + delegate().cleanUp(); + } + + + + @Beta + public static abstract class SimpleForwardingCache + extends ForwardingCache + { + private final Cache delegate; + + + protected SimpleForwardingCache(Cache delegate) + { + this.delegate = ((Cache)Preconditions.checkNotNull(delegate)); + } + + protected final Cache delegate() + { + return delegate; + } + } +} diff --git a/src/minecraft/com/google/common/cache/ForwardingLoadingCache.java b/src/minecraft/com/google/common/cache/ForwardingLoadingCache.java new file mode 100644 index 0000000..07e12c4 --- /dev/null +++ b/src/minecraft/com/google/common/cache/ForwardingLoadingCache.java @@ -0,0 +1,91 @@ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import java.util.concurrent.ExecutionException; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public abstract class ForwardingLoadingCache + extends ForwardingCache + implements LoadingCache +{ + protected ForwardingLoadingCache() {} + + protected abstract LoadingCache delegate(); + + public V get(K key) + throws ExecutionException + { + return delegate().get(key); + } + + public V getUnchecked(K key) + { + return delegate().getUnchecked(key); + } + + public ImmutableMap getAll(Iterable keys) throws ExecutionException + { + return delegate().getAll(keys); + } + + public V apply(K key) + { + return delegate().apply(key); + } + + public void refresh(K key) + { + delegate().refresh(key); + } + + + + @Beta + public static abstract class SimpleForwardingLoadingCache + extends ForwardingLoadingCache + { + private final LoadingCache delegate; + + + + protected SimpleForwardingLoadingCache(LoadingCache delegate) + { + this.delegate = ((LoadingCache)Preconditions.checkNotNull(delegate)); + } + + protected final LoadingCache delegate() + { + return delegate; + } + } +} diff --git a/src/minecraft/com/google/common/cache/LoadingCache.java b/src/minecraft/com/google/common/cache/LoadingCache.java new file mode 100644 index 0000000..f7621d6 --- /dev/null +++ b/src/minecraft/com/google/common/cache/LoadingCache.java @@ -0,0 +1,29 @@ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; +import com.google.common.collect.ImmutableMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; + +@Beta +@GwtCompatible +public abstract interface LoadingCache + extends Cache, Function +{ + public abstract V get(K paramK) + throws ExecutionException; + + public abstract V getUnchecked(K paramK); + + public abstract ImmutableMap getAll(Iterable paramIterable) + throws ExecutionException; + + @Deprecated + public abstract V apply(K paramK); + + public abstract void refresh(K paramK); + + public abstract ConcurrentMap asMap(); +} diff --git a/src/minecraft/com/google/common/cache/LocalCache.java b/src/minecraft/com/google/common/cache/LocalCache.java new file mode 100644 index 0000000..8b98bb3 --- /dev/null +++ b/src/minecraft/com/google/common/cache/LocalCache.java @@ -0,0 +1,4873 @@ +package com.google.common.cache; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Equivalence; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.base.Stopwatch; +import com.google.common.base.Supplier; +import com.google.common.base.Ticker; +import com.google.common.collect.AbstractSequentialIterator; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterators; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import com.google.common.primitives.Ints; +import com.google.common.util.concurrent.ExecutionError; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; +import com.google.common.util.concurrent.SettableFuture; +import com.google.common.util.concurrent.UncheckedExecutionException; +import com.google.common.util.concurrent.Uninterruptibles; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.Serializable; +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.SoftReference; +import java.lang.ref.WeakReference; +import java.util.AbstractCollection; +import java.util.AbstractMap; +import java.util.AbstractQueue; +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NoSuchElementException; +import java.util.Queue; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReferenceArray; +import java.util.concurrent.locks.ReentrantLock; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; +import javax.annotation.concurrent.GuardedBy; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +class LocalCache + extends AbstractMap + implements ConcurrentMap +{ + static final int MAXIMUM_CAPACITY = 1073741824; + static final int MAX_SEGMENTS = 65536; + static final int CONTAINS_VALUE_RETRIES = 3; + static final int DRAIN_THRESHOLD = 63; + static final int DRAIN_MAX = 16; + static final Logger logger = Logger.getLogger(LocalCache.class.getName()); + + static final ListeningExecutorService sameThreadExecutor = MoreExecutors.sameThreadExecutor(); + + + + final int segmentMask; + + + + final int segmentShift; + + + + final Segment[] segments; + + + + final int concurrencyLevel; + + + + final Equivalence keyEquivalence; + + + + final Equivalence valueEquivalence; + + + + final Strength keyStrength; + + + + final Strength valueStrength; + + + + final long maxWeight; + + + + final Weigher weigher; + + + + final long expireAfterAccessNanos; + + + + final long expireAfterWriteNanos; + + + + final long refreshNanos; + + + + final Queue> removalNotificationQueue; + + + + final RemovalListener removalListener; + + + + final Ticker ticker; + + + final EntryFactory entryFactory; + + + final AbstractCache.StatsCounter globalStatsCounter; + + + @Nullable + final CacheLoader defaultLoader; + + + + LocalCache(CacheBuilder builder, @Nullable CacheLoader loader) + { + concurrencyLevel = Math.min(builder.getConcurrencyLevel(), 65536); + + keyStrength = builder.getKeyStrength(); + valueStrength = builder.getValueStrength(); + + keyEquivalence = builder.getKeyEquivalence(); + valueEquivalence = builder.getValueEquivalence(); + + maxWeight = builder.getMaximumWeight(); + weigher = builder.getWeigher(); + expireAfterAccessNanos = builder.getExpireAfterAccessNanos(); + expireAfterWriteNanos = builder.getExpireAfterWriteNanos(); + refreshNanos = builder.getRefreshNanos(); + + removalListener = builder.getRemovalListener(); + removalNotificationQueue = (removalListener == CacheBuilder.NullListener.INSTANCE ? discardingQueue() : new ConcurrentLinkedQueue()); + + + + ticker = builder.getTicker(recordsTime()); + entryFactory = EntryFactory.getFactory(keyStrength, usesAccessEntries(), usesWriteEntries()); + globalStatsCounter = ((AbstractCache.StatsCounter)builder.getStatsCounterSupplier().get()); + defaultLoader = loader; + + int initialCapacity = Math.min(builder.getInitialCapacity(), 1073741824); + if ((evictsBySize()) && (!customWeigher())) { + initialCapacity = Math.min(initialCapacity, (int)maxWeight); + } + + + + + + + int segmentShift = 0; + int segmentCount = 1; + + while ((segmentCount < concurrencyLevel) && ((!evictsBySize()) || (segmentCount * 20 <= maxWeight))) { + segmentShift++; + segmentCount <<= 1; + } + this.segmentShift = (32 - segmentShift); + segmentMask = (segmentCount - 1); + + segments = newSegmentArray(segmentCount); + + int segmentCapacity = initialCapacity / segmentCount; + if (segmentCapacity * segmentCount < initialCapacity) { + segmentCapacity++; + } + + int segmentSize = 1; + while (segmentSize < segmentCapacity) { + segmentSize <<= 1; + } + + if (evictsBySize()) + { + long maxSegmentWeight = maxWeight / segmentCount + 1L; + long remainder = maxWeight % segmentCount; + for (int i = 0; i < segments.length; i++) { + if (i == remainder) { + maxSegmentWeight -= 1L; + } + segments[i] = createSegment(segmentSize, maxSegmentWeight, (AbstractCache.StatsCounter)builder.getStatsCounterSupplier().get()); + } + } + else { + for (int i = 0; i < segments.length; i++) { + segments[i] = createSegment(segmentSize, -1L, (AbstractCache.StatsCounter)builder.getStatsCounterSupplier().get()); + } + } + } + + boolean evictsBySize() + { + return maxWeight >= 0L; + } + + boolean customWeigher() { + return weigher != CacheBuilder.OneWeigher.INSTANCE; + } + + boolean expires() { + return (expiresAfterWrite()) || (expiresAfterAccess()); + } + + boolean expiresAfterWrite() { + return expireAfterWriteNanos > 0L; + } + + boolean expiresAfterAccess() { + return expireAfterAccessNanos > 0L; + } + + boolean refreshes() { + return refreshNanos > 0L; + } + + boolean usesAccessQueue() { + return (expiresAfterAccess()) || (evictsBySize()); + } + + boolean usesWriteQueue() { + return expiresAfterWrite(); + } + + boolean recordsWrite() { + return (expiresAfterWrite()) || (refreshes()); + } + + boolean recordsAccess() { + return expiresAfterAccess(); + } + + boolean recordsTime() { + return (recordsWrite()) || (recordsAccess()); + } + + boolean usesWriteEntries() { + return (usesWriteQueue()) || (recordsWrite()); + } + + boolean usesAccessEntries() { + return (usesAccessQueue()) || (recordsAccess()); + } + + boolean usesKeyReferences() { + return keyStrength != Strength.STRONG; + } + + boolean usesValueReferences() { + return valueStrength != Strength.STRONG; + } + + + + + + static abstract enum Strength + { + STRONG, + + + + + + + + + + + + + + + SOFT, + + + + + + + + + + + + + + + + WEAK; + + + + + + + + private Strength() {} + + + + + + + + abstract LocalCache.ValueReference referenceValue(LocalCache.Segment paramSegment, LocalCache.ReferenceEntry paramReferenceEntry, V paramV, int paramInt); + + + + + + + + abstract Equivalence defaultEquivalence(); + } + + + + + + + static abstract enum EntryFactory + { + STRONG, + + + + + + + STRONG_ACCESS, + + + + + + + + + + + + + + + STRONG_WRITE, + + + + + + + + + + + + + + + STRONG_ACCESS_WRITE, + + + + + + + + + + + + + + + + + WEAK, + + + + + + + WEAK_ACCESS, + + + + + + + + + + + + + + + WEAK_WRITE, + + + + + + + + + + + + + + + WEAK_ACCESS_WRITE; + + + + + + + + static final int ACCESS_MASK = 1; + + + + + + + static final int WRITE_MASK = 2; + + + + + + static final int WEAK_MASK = 4; + + + + + + static final EntryFactory[] factories = { STRONG, STRONG_ACCESS, STRONG_WRITE, STRONG_ACCESS_WRITE, WEAK, WEAK_ACCESS, WEAK_WRITE, WEAK_ACCESS_WRITE }; + + + private EntryFactory() {} + + static EntryFactory getFactory(LocalCache.Strength keyStrength, boolean usesAccessQueue, boolean usesWriteQueue) + { + int flags = (keyStrength == LocalCache.Strength.WEAK ? 4 : 0) | (usesAccessQueue ? 1 : 0) | (usesWriteQueue ? 2 : 0); + + + return factories[flags]; + } + + + + + + + + + + abstract LocalCache.ReferenceEntry newEntry(LocalCache.Segment paramSegment, K paramK, int paramInt, @Nullable LocalCache.ReferenceEntry paramReferenceEntry); + + + + + + + + + @GuardedBy("Segment.this") + LocalCache.ReferenceEntry copyEntry(LocalCache.Segment segment, LocalCache.ReferenceEntry original, LocalCache.ReferenceEntry newNext) + { + return newEntry(segment, original.getKey(), original.getHash(), newNext); + } + + + @GuardedBy("Segment.this") + void copyAccessEntry(LocalCache.ReferenceEntry original, LocalCache.ReferenceEntry newEntry) + { + newEntry.setAccessTime(original.getAccessTime()); + + LocalCache.connectAccessOrder(original.getPreviousInAccessQueue(), newEntry); + LocalCache.connectAccessOrder(newEntry, original.getNextInAccessQueue()); + + LocalCache.nullifyAccessOrder(original); + } + + + @GuardedBy("Segment.this") + void copyWriteEntry(LocalCache.ReferenceEntry original, LocalCache.ReferenceEntry newEntry) + { + newEntry.setWriteTime(original.getWriteTime()); + + LocalCache.connectWriteOrder(original.getPreviousInWriteQueue(), newEntry); + LocalCache.connectWriteOrder(newEntry, original.getNextInWriteQueue()); + + LocalCache.nullifyWriteOrder(original); + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + static final ValueReference UNSET = new ValueReference() + { + public Object get() { + return null; + } + + public int getWeight() + { + return 0; + } + + public LocalCache.ReferenceEntry getEntry() + { + return null; + } + + + public LocalCache.ValueReference copyFor(ReferenceQueue queue, @Nullable Object value, LocalCache.ReferenceEntry entry) + { + return this; + } + + public boolean isLoading() + { + return false; + } + + public boolean isActive() + { + return false; + } + + public Object waitForValue() + { + return null; + } + + + + public void notifyNewValue(Object newValue) {} + }; + + + + static ValueReference unset() + { + return UNSET; + } + + + + static abstract interface ValueReference + { + @Nullable + public abstract V get(); + + + + public abstract V waitForValue() + throws ExecutionException; + + + + public abstract int getWeight(); + + + + @Nullable + public abstract LocalCache.ReferenceEntry getEntry(); + + + + public abstract ValueReference copyFor(ReferenceQueue paramReferenceQueue, @Nullable V paramV, LocalCache.ReferenceEntry paramReferenceEntry); + + + + public abstract void notifyNewValue(@Nullable V paramV); + + + + public abstract boolean isLoading(); + + + + public abstract boolean isActive(); + } + + + + static abstract interface ReferenceEntry + { + public abstract LocalCache.ValueReference getValueReference(); + + + + public abstract void setValueReference(LocalCache.ValueReference paramValueReference); + + + + @Nullable + public abstract ReferenceEntry getNext(); + + + + public abstract int getHash(); + + + + @Nullable + public abstract K getKey(); + + + + public abstract long getAccessTime(); + + + + public abstract void setAccessTime(long paramLong); + + + + public abstract ReferenceEntry getNextInAccessQueue(); + + + + public abstract void setNextInAccessQueue(ReferenceEntry paramReferenceEntry); + + + + public abstract ReferenceEntry getPreviousInAccessQueue(); + + + + public abstract void setPreviousInAccessQueue(ReferenceEntry paramReferenceEntry); + + + + public abstract long getWriteTime(); + + + + public abstract void setWriteTime(long paramLong); + + + + public abstract ReferenceEntry getNextInWriteQueue(); + + + + public abstract void setNextInWriteQueue(ReferenceEntry paramReferenceEntry); + + + + public abstract ReferenceEntry getPreviousInWriteQueue(); + + + + public abstract void setPreviousInWriteQueue(ReferenceEntry paramReferenceEntry); + } + + + + private static enum NullEntry + implements LocalCache.ReferenceEntry + { + INSTANCE; + + private NullEntry() {} + + public LocalCache.ValueReference getValueReference() { return null; } + + + public void setValueReference(LocalCache.ValueReference valueReference) {} + + + public LocalCache.ReferenceEntry getNext() + { + return null; + } + + public int getHash() + { + return 0; + } + + public Object getKey() + { + return null; + } + + public long getAccessTime() + { + return 0L; + } + + + public void setAccessTime(long time) {} + + public LocalCache.ReferenceEntry getNextInAccessQueue() + { + return this; + } + + + public void setNextInAccessQueue(LocalCache.ReferenceEntry next) {} + + public LocalCache.ReferenceEntry getPreviousInAccessQueue() + { + return this; + } + + + public void setPreviousInAccessQueue(LocalCache.ReferenceEntry previous) {} + + public long getWriteTime() + { + return 0L; + } + + + public void setWriteTime(long time) {} + + public LocalCache.ReferenceEntry getNextInWriteQueue() + { + return this; + } + + + public void setNextInWriteQueue(LocalCache.ReferenceEntry next) {} + + public LocalCache.ReferenceEntry getPreviousInWriteQueue() + { + return this; + } + + public void setPreviousInWriteQueue(LocalCache.ReferenceEntry previous) {} + } + + static abstract class AbstractReferenceEntry implements LocalCache.ReferenceEntry { + AbstractReferenceEntry() {} + + public LocalCache.ValueReference getValueReference() { + throw new UnsupportedOperationException(); + } + + public void setValueReference(LocalCache.ValueReference valueReference) + { + throw new UnsupportedOperationException(); + } + + public LocalCache.ReferenceEntry getNext() + { + throw new UnsupportedOperationException(); + } + + public int getHash() + { + throw new UnsupportedOperationException(); + } + + public K getKey() + { + throw new UnsupportedOperationException(); + } + + public long getAccessTime() + { + throw new UnsupportedOperationException(); + } + + public void setAccessTime(long time) + { + throw new UnsupportedOperationException(); + } + + public LocalCache.ReferenceEntry getNextInAccessQueue() + { + throw new UnsupportedOperationException(); + } + + public void setNextInAccessQueue(LocalCache.ReferenceEntry next) + { + throw new UnsupportedOperationException(); + } + + public LocalCache.ReferenceEntry getPreviousInAccessQueue() + { + throw new UnsupportedOperationException(); + } + + public void setPreviousInAccessQueue(LocalCache.ReferenceEntry previous) + { + throw new UnsupportedOperationException(); + } + + public long getWriteTime() + { + throw new UnsupportedOperationException(); + } + + public void setWriteTime(long time) + { + throw new UnsupportedOperationException(); + } + + public LocalCache.ReferenceEntry getNextInWriteQueue() + { + throw new UnsupportedOperationException(); + } + + public void setNextInWriteQueue(LocalCache.ReferenceEntry next) + { + throw new UnsupportedOperationException(); + } + + public LocalCache.ReferenceEntry getPreviousInWriteQueue() + { + throw new UnsupportedOperationException(); + } + + public void setPreviousInWriteQueue(LocalCache.ReferenceEntry previous) + { + throw new UnsupportedOperationException(); + } + } + + static ReferenceEntry nullEntry() + { + return NullEntry.INSTANCE; + } + + static final Queue DISCARDING_QUEUE = new AbstractQueue() + { + public boolean offer(Object o) { + return true; + } + + public Object peek() + { + return null; + } + + public Object poll() + { + return null; + } + + public int size() + { + return 0; + } + + public Iterator iterator() + { + return Iterators.emptyIterator(); + } + }; + Set keySet; + Collection values; + Set> entrySet; + + static Queue discardingQueue() + { + return DISCARDING_QUEUE; + } + + + + static class StrongEntry + extends LocalCache.AbstractReferenceEntry + { + final K key; + + + final int hash; + + final LocalCache.ReferenceEntry next; + + + StrongEntry(K key, int hash, @Nullable LocalCache.ReferenceEntry next) + { + this.key = key; + this.hash = hash; + this.next = next; + } + + public K getKey() + { + return key; + } + + + + + + volatile LocalCache.ValueReference valueReference = LocalCache.unset(); + + public LocalCache.ValueReference getValueReference() + { + return valueReference; + } + + public void setValueReference(LocalCache.ValueReference valueReference) + { + this.valueReference = valueReference; + } + + public int getHash() + { + return hash; + } + + public LocalCache.ReferenceEntry getNext() + { + return next; + } + } + + static final class StrongAccessEntry extends LocalCache.StrongEntry { + StrongAccessEntry(K key, int hash, @Nullable LocalCache.ReferenceEntry next) { + super(hash, next); + } + + + + volatile long accessTime = Long.MAX_VALUE; + + public long getAccessTime() + { + return accessTime; + } + + + + public void setAccessTime(long time) { accessTime = time; } + + @GuardedBy("Segment.this") + LocalCache.ReferenceEntry nextAccess = LocalCache.nullEntry(); + + + public LocalCache.ReferenceEntry getNextInAccessQueue() + { + return nextAccess; + } + + + + public void setNextInAccessQueue(LocalCache.ReferenceEntry next) { nextAccess = next; } + + @GuardedBy("Segment.this") + LocalCache.ReferenceEntry previousAccess = LocalCache.nullEntry(); + + + public LocalCache.ReferenceEntry getPreviousInAccessQueue() + { + return previousAccess; + } + + public void setPreviousInAccessQueue(LocalCache.ReferenceEntry previous) + { + previousAccess = previous; + } + } + + static final class StrongWriteEntry extends LocalCache.StrongEntry { + StrongWriteEntry(K key, int hash, @Nullable LocalCache.ReferenceEntry next) { + super(hash, next); + } + + + + volatile long writeTime = Long.MAX_VALUE; + + public long getWriteTime() + { + return writeTime; + } + + + + public void setWriteTime(long time) { writeTime = time; } + + @GuardedBy("Segment.this") + LocalCache.ReferenceEntry nextWrite = LocalCache.nullEntry(); + + + public LocalCache.ReferenceEntry getNextInWriteQueue() + { + return nextWrite; + } + + + + public void setNextInWriteQueue(LocalCache.ReferenceEntry next) { nextWrite = next; } + + @GuardedBy("Segment.this") + LocalCache.ReferenceEntry previousWrite = LocalCache.nullEntry(); + + + public LocalCache.ReferenceEntry getPreviousInWriteQueue() + { + return previousWrite; + } + + public void setPreviousInWriteQueue(LocalCache.ReferenceEntry previous) + { + previousWrite = previous; + } + } + + static final class StrongAccessWriteEntry extends LocalCache.StrongEntry { + StrongAccessWriteEntry(K key, int hash, @Nullable LocalCache.ReferenceEntry next) { + super(hash, next); + } + + + + volatile long accessTime = Long.MAX_VALUE; + + public long getAccessTime() + { + return accessTime; + } + + + + public void setAccessTime(long time) { accessTime = time; } + + @GuardedBy("Segment.this") + LocalCache.ReferenceEntry nextAccess = LocalCache.nullEntry(); + + + public LocalCache.ReferenceEntry getNextInAccessQueue() + { + return nextAccess; + } + + + + public void setNextInAccessQueue(LocalCache.ReferenceEntry next) { nextAccess = next; } + + @GuardedBy("Segment.this") + LocalCache.ReferenceEntry previousAccess = LocalCache.nullEntry(); + + + public LocalCache.ReferenceEntry getPreviousInAccessQueue() + { + return previousAccess; + } + + public void setPreviousInAccessQueue(LocalCache.ReferenceEntry previous) + { + previousAccess = previous; + } + + + + volatile long writeTime = Long.MAX_VALUE; + + public long getWriteTime() + { + return writeTime; + } + + + + public void setWriteTime(long time) { writeTime = time; } + + @GuardedBy("Segment.this") + LocalCache.ReferenceEntry nextWrite = LocalCache.nullEntry(); + + + public LocalCache.ReferenceEntry getNextInWriteQueue() + { + return nextWrite; + } + + + + public void setNextInWriteQueue(LocalCache.ReferenceEntry next) { nextWrite = next; } + + @GuardedBy("Segment.this") + LocalCache.ReferenceEntry previousWrite = LocalCache.nullEntry(); + + + public LocalCache.ReferenceEntry getPreviousInWriteQueue() + { + return previousWrite; + } + + public void setPreviousInWriteQueue(LocalCache.ReferenceEntry previous) + { + previousWrite = previous; + } + } + + static class WeakEntry extends WeakReference implements LocalCache.ReferenceEntry { + final int hash; + final LocalCache.ReferenceEntry next; + + WeakEntry(ReferenceQueue queue, K key, int hash, @Nullable LocalCache.ReferenceEntry next) { + super(queue); + this.hash = hash; + this.next = next; + } + + public K getKey() + { + return get(); + } + + + + + + + + + public long getAccessTime() + { + throw new UnsupportedOperationException(); + } + + public void setAccessTime(long time) + { + throw new UnsupportedOperationException(); + } + + public LocalCache.ReferenceEntry getNextInAccessQueue() + { + throw new UnsupportedOperationException(); + } + + public void setNextInAccessQueue(LocalCache.ReferenceEntry next) + { + throw new UnsupportedOperationException(); + } + + public LocalCache.ReferenceEntry getPreviousInAccessQueue() + { + throw new UnsupportedOperationException(); + } + + public void setPreviousInAccessQueue(LocalCache.ReferenceEntry previous) + { + throw new UnsupportedOperationException(); + } + + + + public long getWriteTime() + { + throw new UnsupportedOperationException(); + } + + public void setWriteTime(long time) + { + throw new UnsupportedOperationException(); + } + + public LocalCache.ReferenceEntry getNextInWriteQueue() + { + throw new UnsupportedOperationException(); + } + + public void setNextInWriteQueue(LocalCache.ReferenceEntry next) + { + throw new UnsupportedOperationException(); + } + + public LocalCache.ReferenceEntry getPreviousInWriteQueue() + { + throw new UnsupportedOperationException(); + } + + public void setPreviousInWriteQueue(LocalCache.ReferenceEntry previous) + { + throw new UnsupportedOperationException(); + } + + + + + + volatile LocalCache.ValueReference valueReference = LocalCache.unset(); + + public LocalCache.ValueReference getValueReference() + { + return valueReference; + } + + public void setValueReference(LocalCache.ValueReference valueReference) + { + this.valueReference = valueReference; + } + + public int getHash() + { + return hash; + } + + public LocalCache.ReferenceEntry getNext() + { + return next; + } + } + + static final class WeakAccessEntry extends LocalCache.WeakEntry + { + WeakAccessEntry(ReferenceQueue queue, K key, int hash, @Nullable LocalCache.ReferenceEntry next) { + super(key, hash, next); + } + + + + volatile long accessTime = Long.MAX_VALUE; + + public long getAccessTime() + { + return accessTime; + } + + + + public void setAccessTime(long time) { accessTime = time; } + + @GuardedBy("Segment.this") + LocalCache.ReferenceEntry nextAccess = LocalCache.nullEntry(); + + + public LocalCache.ReferenceEntry getNextInAccessQueue() + { + return nextAccess; + } + + + + public void setNextInAccessQueue(LocalCache.ReferenceEntry next) { nextAccess = next; } + + @GuardedBy("Segment.this") + LocalCache.ReferenceEntry previousAccess = LocalCache.nullEntry(); + + + public LocalCache.ReferenceEntry getPreviousInAccessQueue() + { + return previousAccess; + } + + public void setPreviousInAccessQueue(LocalCache.ReferenceEntry previous) + { + previousAccess = previous; + } + } + + static final class WeakWriteEntry extends LocalCache.WeakEntry + { + WeakWriteEntry(ReferenceQueue queue, K key, int hash, @Nullable LocalCache.ReferenceEntry next) { + super(key, hash, next); + } + + + + volatile long writeTime = Long.MAX_VALUE; + + public long getWriteTime() + { + return writeTime; + } + + + + public void setWriteTime(long time) { writeTime = time; } + + @GuardedBy("Segment.this") + LocalCache.ReferenceEntry nextWrite = LocalCache.nullEntry(); + + + public LocalCache.ReferenceEntry getNextInWriteQueue() + { + return nextWrite; + } + + + + public void setNextInWriteQueue(LocalCache.ReferenceEntry next) { nextWrite = next; } + + @GuardedBy("Segment.this") + LocalCache.ReferenceEntry previousWrite = LocalCache.nullEntry(); + + + public LocalCache.ReferenceEntry getPreviousInWriteQueue() + { + return previousWrite; + } + + public void setPreviousInWriteQueue(LocalCache.ReferenceEntry previous) + { + previousWrite = previous; + } + } + + static final class WeakAccessWriteEntry extends LocalCache.WeakEntry + { + WeakAccessWriteEntry(ReferenceQueue queue, K key, int hash, @Nullable LocalCache.ReferenceEntry next) { + super(key, hash, next); + } + + + + volatile long accessTime = Long.MAX_VALUE; + + public long getAccessTime() + { + return accessTime; + } + + + + public void setAccessTime(long time) { accessTime = time; } + + @GuardedBy("Segment.this") + LocalCache.ReferenceEntry nextAccess = LocalCache.nullEntry(); + + + public LocalCache.ReferenceEntry getNextInAccessQueue() + { + return nextAccess; + } + + + + public void setNextInAccessQueue(LocalCache.ReferenceEntry next) { nextAccess = next; } + + @GuardedBy("Segment.this") + LocalCache.ReferenceEntry previousAccess = LocalCache.nullEntry(); + + + public LocalCache.ReferenceEntry getPreviousInAccessQueue() + { + return previousAccess; + } + + public void setPreviousInAccessQueue(LocalCache.ReferenceEntry previous) + { + previousAccess = previous; + } + + + + volatile long writeTime = Long.MAX_VALUE; + + public long getWriteTime() + { + return writeTime; + } + + + + public void setWriteTime(long time) { writeTime = time; } + + @GuardedBy("Segment.this") + LocalCache.ReferenceEntry nextWrite = LocalCache.nullEntry(); + + + public LocalCache.ReferenceEntry getNextInWriteQueue() + { + return nextWrite; + } + + + + public void setNextInWriteQueue(LocalCache.ReferenceEntry next) { nextWrite = next; } + + @GuardedBy("Segment.this") + LocalCache.ReferenceEntry previousWrite = LocalCache.nullEntry(); + + + public LocalCache.ReferenceEntry getPreviousInWriteQueue() + { + return previousWrite; + } + + public void setPreviousInWriteQueue(LocalCache.ReferenceEntry previous) + { + previousWrite = previous; + } + } + + static class WeakValueReference + extends WeakReference + implements LocalCache.ValueReference + { + final LocalCache.ReferenceEntry entry; + + WeakValueReference(ReferenceQueue queue, V referent, LocalCache.ReferenceEntry entry) + { + super(queue); + this.entry = entry; + } + + public int getWeight() + { + return 1; + } + + public LocalCache.ReferenceEntry getEntry() + { + return entry; + } + + + public void notifyNewValue(V newValue) {} + + + public LocalCache.ValueReference copyFor(ReferenceQueue queue, V value, LocalCache.ReferenceEntry entry) + { + return new WeakValueReference(queue, value, entry); + } + + public boolean isLoading() + { + return false; + } + + public boolean isActive() + { + return true; + } + + public V waitForValue() + { + return get(); + } + } + + static class SoftValueReference + extends SoftReference + implements LocalCache.ValueReference + { + final LocalCache.ReferenceEntry entry; + + SoftValueReference(ReferenceQueue queue, V referent, LocalCache.ReferenceEntry entry) + { + super(queue); + this.entry = entry; + } + + public int getWeight() + { + return 1; + } + + public LocalCache.ReferenceEntry getEntry() + { + return entry; + } + + + public void notifyNewValue(V newValue) {} + + + public LocalCache.ValueReference copyFor(ReferenceQueue queue, V value, LocalCache.ReferenceEntry entry) + { + return new SoftValueReference(queue, value, entry); + } + + public boolean isLoading() + { + return false; + } + + public boolean isActive() + { + return true; + } + + public V waitForValue() + { + return get(); + } + } + + static class StrongValueReference + implements LocalCache.ValueReference + { + final V referent; + + StrongValueReference(V referent) + { + this.referent = referent; + } + + public V get() + { + return referent; + } + + public int getWeight() + { + return 1; + } + + public LocalCache.ReferenceEntry getEntry() + { + return null; + } + + + public LocalCache.ValueReference copyFor(ReferenceQueue queue, V value, LocalCache.ReferenceEntry entry) + { + return this; + } + + public boolean isLoading() + { + return false; + } + + public boolean isActive() + { + return true; + } + + public V waitForValue() + { + return get(); + } + + + public void notifyNewValue(V newValue) {} + } + + + static final class WeightedWeakValueReference + extends LocalCache.WeakValueReference + { + final int weight; + + WeightedWeakValueReference(ReferenceQueue queue, V referent, LocalCache.ReferenceEntry entry, int weight) + { + super(referent, entry); + this.weight = weight; + } + + public int getWeight() + { + return weight; + } + + + public LocalCache.ValueReference copyFor(ReferenceQueue queue, V value, LocalCache.ReferenceEntry entry) + { + return new WeightedWeakValueReference(queue, value, entry, weight); + } + } + + + static final class WeightedSoftValueReference + extends LocalCache.SoftValueReference + { + final int weight; + + WeightedSoftValueReference(ReferenceQueue queue, V referent, LocalCache.ReferenceEntry entry, int weight) + { + super(referent, entry); + this.weight = weight; + } + + public int getWeight() + { + return weight; + } + + public LocalCache.ValueReference copyFor(ReferenceQueue queue, V value, LocalCache.ReferenceEntry entry) + { + return new WeightedSoftValueReference(queue, value, entry, weight); + } + } + + + static final class WeightedStrongValueReference + extends LocalCache.StrongValueReference + { + final int weight; + + WeightedStrongValueReference(V referent, int weight) + { + super(); + this.weight = weight; + } + + public int getWeight() + { + return weight; + } + } + + + + + + + + + + + + static int rehash(int h) + { + h += (h << 15 ^ 0xCD7D); + h ^= h >>> 10; + h += (h << 3); + h ^= h >>> 6; + h += (h << 2) + (h << 14); + return h ^ h >>> 16; + } + + + + @GuardedBy("Segment.this") + @VisibleForTesting + ReferenceEntry newEntry(K key, int hash, @Nullable ReferenceEntry next) + { + return segmentFor(hash).newEntry(key, hash, next); + } + + + + @GuardedBy("Segment.this") + @VisibleForTesting + ReferenceEntry copyEntry(ReferenceEntry original, ReferenceEntry newNext) + { + int hash = original.getHash(); + return segmentFor(hash).copyEntry(original, newNext); + } + + + + @GuardedBy("Segment.this") + @VisibleForTesting + ValueReference newValueReference(ReferenceEntry entry, V value, int weight) + { + int hash = entry.getHash(); + return valueStrength.referenceValue(segmentFor(hash), entry, Preconditions.checkNotNull(value), weight); + } + + int hash(@Nullable Object key) { + int h = keyEquivalence.hash(key); + return rehash(h); + } + + void reclaimValue(ValueReference valueReference) { + ReferenceEntry entry = valueReference.getEntry(); + int hash = entry.getHash(); + segmentFor(hash).reclaimValue(entry.getKey(), hash, valueReference); + } + + void reclaimKey(ReferenceEntry entry) { + int hash = entry.getHash(); + segmentFor(hash).reclaimKey(entry, hash); + } + + + + + @VisibleForTesting + boolean isLive(ReferenceEntry entry, long now) + { + return segmentFor(entry.getHash()).getLiveValue(entry, now) != null; + } + + + + + + + + Segment segmentFor(int hash) + { + return segments[(hash >>> segmentShift & segmentMask)]; + } + + Segment createSegment(int initialCapacity, long maxSegmentWeight, AbstractCache.StatsCounter statsCounter) + { + return new Segment(this, initialCapacity, maxSegmentWeight, statsCounter); + } + + + + + + + @Nullable + V getLiveValue(ReferenceEntry entry, long now) + { + if (entry.getKey() == null) { + return null; + } + V value = entry.getValueReference().get(); + if (value == null) { + return null; + } + + if (isExpired(entry, now)) { + return null; + } + return value; + } + + + + + + boolean isExpired(ReferenceEntry entry, long now) + { + Preconditions.checkNotNull(entry); + if ((expiresAfterAccess()) && (now - entry.getAccessTime() >= expireAfterAccessNanos)) + { + return true; + } + if ((expiresAfterWrite()) && (now - entry.getWriteTime() >= expireAfterWriteNanos)) + { + return true; + } + return false; + } + + + @GuardedBy("Segment.this") + static void connectAccessOrder(ReferenceEntry previous, ReferenceEntry next) + { + previous.setNextInAccessQueue(next); + next.setPreviousInAccessQueue(previous); + } + + @GuardedBy("Segment.this") + static void nullifyAccessOrder(ReferenceEntry nulled) { + ReferenceEntry nullEntry = nullEntry(); + nulled.setNextInAccessQueue(nullEntry); + nulled.setPreviousInAccessQueue(nullEntry); + } + + @GuardedBy("Segment.this") + static void connectWriteOrder(ReferenceEntry previous, ReferenceEntry next) { + previous.setNextInWriteQueue(next); + next.setPreviousInWriteQueue(previous); + } + + @GuardedBy("Segment.this") + static void nullifyWriteOrder(ReferenceEntry nulled) { + ReferenceEntry nullEntry = nullEntry(); + nulled.setNextInWriteQueue(nullEntry); + nulled.setPreviousInWriteQueue(nullEntry); + } + + + + void processPendingNotifications() + { + RemovalNotification notification; + + + while ((notification = (RemovalNotification)removalNotificationQueue.poll()) != null) { + try { + removalListener.onRemoval(notification); + } catch (Throwable e) { + logger.log(Level.WARNING, "Exception thrown by removal listener", e); + } + } + } + + final Segment[] newSegmentArray(int ssize) + { + return new Segment[ssize]; + } + + + + + + + + + + static class Segment + extends ReentrantLock + { + final LocalCache map; + + + + + + + + + volatile int count; + + + + + + + + + @GuardedBy("Segment.this") + int totalWeight; + + + + + + + + + int modCount; + + + + + + + + + int threshold; + + + + + + + + + volatile AtomicReferenceArray> table; + + + + + + + + + final long maxSegmentWeight; + + + + + + + + + final ReferenceQueue keyReferenceQueue; + + + + + + + + + final ReferenceQueue valueReferenceQueue; + + + + + + + + + final Queue> recencyQueue; + + + + + + + + + final AtomicInteger readCount = new AtomicInteger(); + + + + @GuardedBy("Segment.this") + final Queue> writeQueue; + + + + @GuardedBy("Segment.this") + final Queue> accessQueue; + + + + final AbstractCache.StatsCounter statsCounter; + + + + + Segment(LocalCache map, int initialCapacity, long maxSegmentWeight, AbstractCache.StatsCounter statsCounter) + { + this.map = map; + this.maxSegmentWeight = maxSegmentWeight; + this.statsCounter = ((AbstractCache.StatsCounter)Preconditions.checkNotNull(statsCounter)); + initTable(newEntryArray(initialCapacity)); + + keyReferenceQueue = (map.usesKeyReferences() ? new ReferenceQueue() : null); + + + valueReferenceQueue = (map.usesValueReferences() ? new ReferenceQueue() : null); + + + recencyQueue = (map.usesAccessQueue() ? new ConcurrentLinkedQueue() : LocalCache.discardingQueue()); + + + + writeQueue = (map.usesWriteQueue() ? new LocalCache.WriteQueue() : LocalCache.discardingQueue()); + + + + accessQueue = (map.usesAccessQueue() ? new LocalCache.AccessQueue() : LocalCache.discardingQueue()); + } + + + AtomicReferenceArray> newEntryArray(int size) + { + return new AtomicReferenceArray(size); + } + + void initTable(AtomicReferenceArray> newTable) { + threshold = (newTable.length() * 3 / 4); + if ((!map.customWeigher()) && (threshold == maxSegmentWeight)) + { + threshold += 1; + } + table = newTable; + } + + @GuardedBy("Segment.this") + LocalCache.ReferenceEntry newEntry(K key, int hash, @Nullable LocalCache.ReferenceEntry next) { + return map.entryFactory.newEntry(this, Preconditions.checkNotNull(key), hash, next); + } + + + + + @GuardedBy("Segment.this") + LocalCache.ReferenceEntry copyEntry(LocalCache.ReferenceEntry original, LocalCache.ReferenceEntry newNext) + { + if (original.getKey() == null) + { + return null; + } + + LocalCache.ValueReference valueReference = original.getValueReference(); + V value = valueReference.get(); + if ((value == null) && (valueReference.isActive())) + { + return null; + } + + LocalCache.ReferenceEntry newEntry = map.entryFactory.copyEntry(this, original, newNext); + newEntry.setValueReference(valueReference.copyFor(valueReferenceQueue, value, newEntry)); + return newEntry; + } + + + + @GuardedBy("Segment.this") + void setValue(LocalCache.ReferenceEntry entry, K key, V value, long now) + { + LocalCache.ValueReference previous = entry.getValueReference(); + int weight = map.weigher.weigh(key, value); + Preconditions.checkState(weight >= 0, "Weights must be non-negative"); + + LocalCache.ValueReference valueReference = map.valueStrength.referenceValue(this, entry, value, weight); + + entry.setValueReference(valueReference); + recordWrite(entry, weight, now); + previous.notifyNewValue(value); + } + + V get(K key, int hash, CacheLoader loader) + throws ExecutionException + { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(loader); + try { LocalCache.ReferenceEntry e; + if (count != 0) + { + e = getEntry(key, hash); + if (e != null) { + long now = map.ticker.read(); + V value = getLiveValue(e, now); + if (value != null) { + recordRead(e, now); + statsCounter.recordHits(1); + return scheduleRefresh(e, key, hash, value, now, loader); + } + Object valueReference = e.getValueReference(); + if (((LocalCache.ValueReference)valueReference).isLoading()) { + return waitForLoadingValue(e, key, (LocalCache.ValueReference)valueReference); + } + } + } + + + return lockedGetOrLoad(key, hash, loader); + } catch (ExecutionException ee) { + Throwable cause = ee.getCause(); + if ((cause instanceof Error)) + throw new ExecutionError((Error)cause); + if ((cause instanceof RuntimeException)) { + throw new UncheckedExecutionException(cause); + } + throw ee; + } finally { + postReadCleanup(); + } + } + + V lockedGetOrLoad(K key, int hash, CacheLoader loader) + throws ExecutionException + { + valueReference = null; + LocalCache.LoadingValueReference loadingValueReference = null; + boolean createNewEntry = true; + + lock(); + try + { + long now = map.ticker.read(); + preWriteCleanup(now); + + int newCount = count - 1; + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + LocalCache.ReferenceEntry first = (LocalCache.ReferenceEntry)table.get(index); + + for (e = first; e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if ((e.getHash() == hash) && (entryKey != null) && (map.keyEquivalence.equivalent(key, entryKey))) + { + valueReference = e.getValueReference(); + if (valueReference.isLoading()) { + createNewEntry = false; break; + } + V value = valueReference.get(); + if (value == null) { + enqueueNotification(entryKey, hash, valueReference, RemovalCause.COLLECTED); + } else if (map.isExpired(e, now)) + { + + enqueueNotification(entryKey, hash, valueReference, RemovalCause.EXPIRED); + } else { + recordLockedRead(e, now); + statsCounter.recordHits(1); + + return value; + } + + + writeQueue.remove(e); + accessQueue.remove(e); + count = newCount; + + break; + } + } + + if (createNewEntry) { + loadingValueReference = new LocalCache.LoadingValueReference(); + + if (e == null) { + e = newEntry(key, hash, first); + e.setValueReference(loadingValueReference); + table.set(index, e); + } else { + e.setValueReference(loadingValueReference); + } + } + } finally { + unlock(); + postWriteCleanup(); + } + + if (createNewEntry) + { + try + { + + synchronized (e) { + return loadSync(key, hash, loadingValueReference, loader); + } + + + + + + return waitForLoadingValue(e, key, valueReference); + } + finally + { + statsCounter.recordMisses(1); + } + } + } + + + + V waitForLoadingValue(LocalCache.ReferenceEntry e, K key, LocalCache.ValueReference valueReference) + throws ExecutionException + { + if (!valueReference.isLoading()) { + throw new AssertionError(); + } + + Preconditions.checkState(!Thread.holdsLock(e), "Recursive load of: %s", new Object[] { key }); + try + { + V value = valueReference.waitForValue(); + if (value == null) { + throw new CacheLoader.InvalidCacheLoadException("CacheLoader returned null for key " + key + "."); + } + + long now = map.ticker.read(); + recordRead(e, now); + return value; + } finally { + statsCounter.recordMisses(1); + } + } + + + V loadSync(K key, int hash, LocalCache.LoadingValueReference loadingValueReference, CacheLoader loader) + throws ExecutionException + { + ListenableFuture loadingFuture = loadingValueReference.loadFuture(key, loader); + return getAndRecordStats(key, hash, loadingValueReference, loadingFuture); + } + + ListenableFuture loadAsync(final K key, final int hash, final LocalCache.LoadingValueReference loadingValueReference, CacheLoader loader) + { + final ListenableFuture loadingFuture = loadingValueReference.loadFuture(key, loader); + loadingFuture.addListener(new Runnable() + { + public void run() + { + try { + newValue = getAndRecordStats(key, hash, loadingValueReference, loadingFuture); + } catch (Throwable t) { V newValue; + LocalCache.logger.log(Level.WARNING, "Exception thrown during refresh", t); + loadingValueReference.setException(t); } } }, LocalCache.sameThreadExecutor); + + + + return loadingFuture; + } + + + + V getAndRecordStats(K key, int hash, LocalCache.LoadingValueReference loadingValueReference, ListenableFuture newValue) + throws ExecutionException + { + V value = null; + try { + value = Uninterruptibles.getUninterruptibly(newValue); + if (value == null) { + throw new CacheLoader.InvalidCacheLoadException("CacheLoader returned null for key " + key + "."); + } + statsCounter.recordLoadSuccess(loadingValueReference.elapsedNanos()); + storeLoadedValue(key, hash, loadingValueReference, value); + return value; + } finally { + if (value == null) { + statsCounter.recordLoadException(loadingValueReference.elapsedNanos()); + removeLoadingValue(key, hash, loadingValueReference); + } + } + } + + V scheduleRefresh(LocalCache.ReferenceEntry entry, K key, int hash, V oldValue, long now, CacheLoader loader) + { + if ((map.refreshes()) && (now - entry.getWriteTime() > map.refreshNanos) && (!entry.getValueReference().isLoading())) + { + V newValue = refresh(key, hash, loader, true); + if (newValue != null) { + return newValue; + } + } + return oldValue; + } + + + + + + + @Nullable + V refresh(K key, int hash, CacheLoader loader, boolean checkTime) + { + LocalCache.LoadingValueReference loadingValueReference = insertLoadingValueReference(key, hash, checkTime); + + if (loadingValueReference == null) { + return null; + } + + ListenableFuture result = loadAsync(key, hash, loadingValueReference, loader); + if (result.isDone()) { + try { + return Uninterruptibles.getUninterruptibly(result); + } + catch (Throwable t) {} + } + + return null; + } + + + + + + @Nullable + LocalCache.LoadingValueReference insertLoadingValueReference(K key, int hash, boolean checkTime) + { + LocalCache.ReferenceEntry e = null; + lock(); + try { + long now = map.ticker.read(); + preWriteCleanup(now); + + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + LocalCache.ReferenceEntry first = (LocalCache.ReferenceEntry)table.get(index); + + LocalCache.ValueReference valueReference; + for (e = first; e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if ((e.getHash() == hash) && (entryKey != null) && (map.keyEquivalence.equivalent(key, entryKey))) + { + + + valueReference = e.getValueReference(); + if ((valueReference.isLoading()) || ((checkTime) && (now - e.getWriteTime() < map.refreshNanos))) + { + + + + return null; + } + + + modCount += 1; + Object loadingValueReference = new LocalCache.LoadingValueReference(valueReference); + + e.setValueReference((LocalCache.ValueReference)loadingValueReference); + return loadingValueReference; + } + } + + modCount += 1; + LocalCache.LoadingValueReference loadingValueReference = new LocalCache.LoadingValueReference(); + e = newEntry(key, hash, first); + e.setValueReference(loadingValueReference); + table.set(index, e); + return loadingValueReference; + } finally { + unlock(); + postWriteCleanup(); + } + } + + + + + + void tryDrainReferenceQueues() + { + if (tryLock()) { + try { + drainReferenceQueues(); + } finally { + unlock(); + } + } + } + + + + + @GuardedBy("Segment.this") + void drainReferenceQueues() + { + if (map.usesKeyReferences()) { + drainKeyReferenceQueue(); + } + if (map.usesValueReferences()) { + drainValueReferenceQueue(); + } + } + + @GuardedBy("Segment.this") + void drainKeyReferenceQueue() + { + int i = 0; + Reference ref; for (; (ref = keyReferenceQueue.poll()) != null; + + + + i == 16) + { + LocalCache.ReferenceEntry entry = (LocalCache.ReferenceEntry)ref; + map.reclaimKey(entry); + i++; + } + } + + + + @GuardedBy("Segment.this") + void drainValueReferenceQueue() + { + int i = 0; + Reference ref; for (; (ref = valueReferenceQueue.poll()) != null; + + + + i == 16) + { + LocalCache.ValueReference valueReference = (LocalCache.ValueReference)ref; + map.reclaimValue(valueReference); + i++; + } + } + + + + + + void clearReferenceQueues() + { + if (map.usesKeyReferences()) { + clearKeyReferenceQueue(); + } + if (map.usesValueReferences()) { + clearValueReferenceQueue(); + } + } + + void clearKeyReferenceQueue() { + while (keyReferenceQueue.poll() != null) {} + } + + void clearValueReferenceQueue() { + while (valueReferenceQueue.poll() != null) {} + } + + + + + + + + + + void recordRead(LocalCache.ReferenceEntry entry, long now) + { + if (map.recordsAccess()) { + entry.setAccessTime(now); + } + recencyQueue.add(entry); + } + + + + + + + + @GuardedBy("Segment.this") + void recordLockedRead(LocalCache.ReferenceEntry entry, long now) + { + if (map.recordsAccess()) { + entry.setAccessTime(now); + } + accessQueue.add(entry); + } + + + + + + @GuardedBy("Segment.this") + void recordWrite(LocalCache.ReferenceEntry entry, int weight, long now) + { + drainRecencyQueue(); + totalWeight += weight; + + if (map.recordsAccess()) { + entry.setAccessTime(now); + } + if (map.recordsWrite()) { + entry.setWriteTime(now); + } + accessQueue.add(entry); + writeQueue.add(entry); + } + + + + + @GuardedBy("Segment.this") + void drainRecencyQueue() + { + LocalCache.ReferenceEntry e; + + + while ((e = (LocalCache.ReferenceEntry)recencyQueue.poll()) != null) + { + + + + if (accessQueue.contains(e)) { + accessQueue.add(e); + } + } + } + + + + + + void tryExpireEntries(long now) + { + if (tryLock()) { + try { + expireEntries(now); + } finally { + unlock(); + } + } + } + + @GuardedBy("Segment.this") + void expireEntries(long now) + { + drainRecencyQueue(); + + LocalCache.ReferenceEntry e; + while (((e = (LocalCache.ReferenceEntry)writeQueue.peek()) != null) && (map.isExpired(e, now))) { + if (!removeEntry(e, e.getHash(), RemovalCause.EXPIRED)) { + throw new AssertionError(); + } + } + while (((e = (LocalCache.ReferenceEntry)accessQueue.peek()) != null) && (map.isExpired(e, now))) { + if (!removeEntry(e, e.getHash(), RemovalCause.EXPIRED)) { + throw new AssertionError(); + } + } + } + + + @GuardedBy("Segment.this") + void enqueueNotification(LocalCache.ReferenceEntry entry, RemovalCause cause) + { + enqueueNotification(entry.getKey(), entry.getHash(), entry.getValueReference(), cause); + } + + @GuardedBy("Segment.this") + void enqueueNotification(@Nullable K key, int hash, LocalCache.ValueReference valueReference, RemovalCause cause) + { + totalWeight -= valueReference.getWeight(); + if (cause.wasEvicted()) { + statsCounter.recordEviction(); + } + if (map.removalNotificationQueue != LocalCache.DISCARDING_QUEUE) { + V value = valueReference.get(); + RemovalNotification notification = new RemovalNotification(key, value, cause); + map.removalNotificationQueue.offer(notification); + } + } + + + + + @GuardedBy("Segment.this") + void evictEntries() + { + if (!map.evictsBySize()) { + return; + } + + drainRecencyQueue(); + while (totalWeight > maxSegmentWeight) { + LocalCache.ReferenceEntry e = getNextEvictable(); + if (!removeEntry(e, e.getHash(), RemovalCause.SIZE)) { + throw new AssertionError(); + } + } + } + + LocalCache.ReferenceEntry getNextEvictable() + { + for (LocalCache.ReferenceEntry e : accessQueue) { + int weight = e.getValueReference().getWeight(); + if (weight > 0) { + return e; + } + } + throw new AssertionError(); + } + + + + + LocalCache.ReferenceEntry getFirst(int hash) + { + AtomicReferenceArray> table = this.table; + return (LocalCache.ReferenceEntry)table.get(hash & table.length() - 1); + } + + + @Nullable + LocalCache.ReferenceEntry getEntry(Object key, int hash) + { + for (LocalCache.ReferenceEntry e = getFirst(hash); e != null; e = e.getNext()) { + if (e.getHash() == hash) + { + + + K entryKey = e.getKey(); + if (entryKey == null) { + tryDrainReferenceQueues(); + + + } + else if (map.keyEquivalence.equivalent(key, entryKey)) { + return e; + } + } + } + return null; + } + + @Nullable + LocalCache.ReferenceEntry getLiveEntry(Object key, int hash, long now) { + LocalCache.ReferenceEntry e = getEntry(key, hash); + if (e == null) + return null; + if (map.isExpired(e, now)) { + tryExpireEntries(now); + return null; + } + return e; + } + + + + + V getLiveValue(LocalCache.ReferenceEntry entry, long now) + { + if (entry.getKey() == null) { + tryDrainReferenceQueues(); + return null; + } + V value = entry.getValueReference().get(); + if (value == null) { + tryDrainReferenceQueues(); + return null; + } + + if (map.isExpired(entry, now)) { + tryExpireEntries(now); + return null; + } + return value; + } + + @Nullable + V get(Object key, int hash) { + try { long now; + if (count != 0) { + now = map.ticker.read(); + LocalCache.ReferenceEntry e = getLiveEntry(key, hash, now); + if (e == null) { + return null; + } + + Object value = e.getValueReference().get(); + if (value != null) { + recordRead(e, now); + return scheduleRefresh(e, e.getKey(), hash, value, now, map.defaultLoader); + } + tryDrainReferenceQueues(); + } + return null; + } finally { + postReadCleanup(); + } + } + + boolean containsKey(Object key, int hash) { + try { long now; + if (count != 0) { + now = map.ticker.read(); + LocalCache.ReferenceEntry e = getLiveEntry(key, hash, now); + boolean bool; if (e == null) { + return false; + } + return e.getValueReference().get() != null; + } + + return 0; + } finally { + postReadCleanup(); + } + } + + + @VisibleForTesting + boolean containsValue(Object value) + { + try + { + long now; + if (count != 0) { + now = map.ticker.read(); + AtomicReferenceArray> table = this.table; + int length = table.length(); + for (int i = 0; i < length; i++) { + for (LocalCache.ReferenceEntry e = (LocalCache.ReferenceEntry)table.get(i); e != null; e = e.getNext()) { + V entryValue = getLiveValue(e, now); + if (entryValue != null) + { + + if (map.valueEquivalence.equivalent(value, entryValue)) { + return true; + } + } + } + } + } + return 0; + } finally { + postReadCleanup(); + } + } + + @Nullable + V put(K key, int hash, V value, boolean onlyIfAbsent) { + lock(); + try { + long now = map.ticker.read(); + preWriteCleanup(now); + + int newCount = count + 1; + if (newCount > threshold) { + expand(); + newCount = count + 1; + } + + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + LocalCache.ReferenceEntry first = (LocalCache.ReferenceEntry)table.get(index); + + K entryKey; + for (LocalCache.ReferenceEntry e = first; e != null; e = e.getNext()) { + entryKey = e.getKey(); + if ((e.getHash() == hash) && (entryKey != null) && (map.keyEquivalence.equivalent(key, entryKey))) + { + + + LocalCache.ValueReference valueReference = e.getValueReference(); + V entryValue = valueReference.get(); + V ?; + if (entryValue == null) { + modCount += 1; + if (valueReference.isActive()) { + enqueueNotification(key, hash, valueReference, RemovalCause.COLLECTED); + setValue(e, key, value, now); + newCount = count; + } else { + setValue(e, key, value, now); + newCount = count + 1; + } + count = newCount; + evictEntries(); + return null; } + if (onlyIfAbsent) + { + + + recordLockedRead(e, now); + return entryValue; + } + + modCount += 1; + enqueueNotification(key, hash, valueReference, RemovalCause.REPLACED); + setValue(e, key, value, now); + evictEntries(); + return entryValue; + } + } + + + + modCount += 1; + LocalCache.ReferenceEntry newEntry = newEntry(key, hash, first); + setValue(newEntry, key, value, now); + table.set(index, newEntry); + newCount = count + 1; + count = newCount; + evictEntries(); + return null; + } finally { + unlock(); + postWriteCleanup(); + } + } + + + + @GuardedBy("Segment.this") + void expand() + { + AtomicReferenceArray> oldTable = table; + int oldCapacity = oldTable.length(); + if (oldCapacity >= 1073741824) { + return; + } + + + + + + + + + + + + int newCount = count; + AtomicReferenceArray> newTable = newEntryArray(oldCapacity << 1); + threshold = (newTable.length() * 3 / 4); + int newMask = newTable.length() - 1; + for (int oldIndex = 0; oldIndex < oldCapacity; oldIndex++) + { + + LocalCache.ReferenceEntry head = (LocalCache.ReferenceEntry)oldTable.get(oldIndex); + + if (head != null) { + LocalCache.ReferenceEntry next = head.getNext(); + int headIndex = head.getHash() & newMask; + + + if (next == null) { + newTable.set(headIndex, head); + + } + else + { + LocalCache.ReferenceEntry tail = head; + int tailIndex = headIndex; + for (LocalCache.ReferenceEntry e = next; e != null; e = e.getNext()) { + int newIndex = e.getHash() & newMask; + if (newIndex != tailIndex) + { + tailIndex = newIndex; + tail = e; + } + } + newTable.set(tailIndex, tail); + + + for (LocalCache.ReferenceEntry e = head; e != tail; e = e.getNext()) { + int newIndex = e.getHash() & newMask; + LocalCache.ReferenceEntry newNext = (LocalCache.ReferenceEntry)newTable.get(newIndex); + LocalCache.ReferenceEntry newFirst = copyEntry(e, newNext); + if (newFirst != null) { + newTable.set(newIndex, newFirst); + } else { + removeCollectedEntry(e); + newCount--; + } + } + } + } + } + table = newTable; + count = newCount; + } + + boolean replace(K key, int hash, V oldValue, V newValue) { + lock(); + try { + long now = map.ticker.read(); + preWriteCleanup(now); + + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + LocalCache.ReferenceEntry first = (LocalCache.ReferenceEntry)table.get(index); + + for (LocalCache.ReferenceEntry e = first; e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if ((e.getHash() == hash) && (entryKey != null) && (map.keyEquivalence.equivalent(key, entryKey))) + { + LocalCache.ValueReference valueReference = e.getValueReference(); + V entryValue = valueReference.get(); + int newCount; if (entryValue == null) { + if (valueReference.isActive()) + { + newCount = count - 1; + modCount += 1; + LocalCache.ReferenceEntry newFirst = removeValueFromChain(first, e, entryKey, hash, valueReference, RemovalCause.COLLECTED); + + newCount = count - 1; + table.set(index, newFirst); + count = newCount; + } + return 0; + } + + if (map.valueEquivalence.equivalent(oldValue, entryValue)) { + modCount += 1; + enqueueNotification(key, hash, valueReference, RemovalCause.REPLACED); + setValue(e, key, newValue, now); + evictEntries(); + return 1; + } + + + recordLockedRead(e, now); + return 0; + } + } + + + return 0; + } finally { + unlock(); + postWriteCleanup(); + } + } + + @Nullable + V replace(K key, int hash, V newValue) { + lock(); + try { + long now = map.ticker.read(); + preWriteCleanup(now); + + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + LocalCache.ReferenceEntry first = (LocalCache.ReferenceEntry)table.get(index); + + for (LocalCache.ReferenceEntry e = first; e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if ((e.getHash() == hash) && (entryKey != null) && (map.keyEquivalence.equivalent(key, entryKey))) + { + LocalCache.ValueReference valueReference = e.getValueReference(); + V entryValue = valueReference.get(); + int newCount; if (entryValue == null) { + if (valueReference.isActive()) + { + newCount = count - 1; + modCount += 1; + LocalCache.ReferenceEntry newFirst = removeValueFromChain(first, e, entryKey, hash, valueReference, RemovalCause.COLLECTED); + + newCount = count - 1; + table.set(index, newFirst); + count = newCount; + } + return null; + } + + modCount += 1; + enqueueNotification(key, hash, valueReference, RemovalCause.REPLACED); + setValue(e, key, newValue, now); + evictEntries(); + return entryValue; + } + } + + return null; + } finally { + unlock(); + postWriteCleanup(); + } + } + + @Nullable + V remove(Object key, int hash) { + lock(); + try { + long now = map.ticker.read(); + preWriteCleanup(now); + + int newCount = count - 1; + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + LocalCache.ReferenceEntry first = (LocalCache.ReferenceEntry)table.get(index); + + for (LocalCache.ReferenceEntry e = first; e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if ((e.getHash() == hash) && (entryKey != null) && (map.keyEquivalence.equivalent(key, entryKey))) + { + LocalCache.ValueReference valueReference = e.getValueReference(); + V entryValue = valueReference.get(); + + RemovalCause cause; + if (entryValue != null) { + cause = RemovalCause.EXPLICIT; } else { RemovalCause cause; + if (valueReference.isActive()) { + cause = RemovalCause.COLLECTED; + } + else + return null; + } + RemovalCause cause; + modCount += 1; + Object newFirst = removeValueFromChain(first, e, entryKey, hash, valueReference, cause); + + newCount = count - 1; + table.set(index, newFirst); + count = newCount; + return entryValue; + } + } + + return null; + } finally { + unlock(); + postWriteCleanup(); + } + } + + boolean storeLoadedValue(K key, int hash, LocalCache.LoadingValueReference oldValueReference, V newValue) + { + lock(); + try { + long now = map.ticker.read(); + preWriteCleanup(now); + + int newCount = count + 1; + if (newCount > threshold) { + expand(); + newCount = count + 1; + } + + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + LocalCache.ReferenceEntry first = (LocalCache.ReferenceEntry)table.get(index); + K entryKey; + for (LocalCache.ReferenceEntry e = first; e != null; e = e.getNext()) { + entryKey = e.getKey(); + if ((e.getHash() == hash) && (entryKey != null) && (map.keyEquivalence.equivalent(key, entryKey))) + { + LocalCache.ValueReference valueReference = e.getValueReference(); + V entryValue = valueReference.get(); + + RemovalCause cause; + if ((oldValueReference == valueReference) || ((entryValue == null) && (valueReference != LocalCache.UNSET))) + { + modCount += 1; + if (oldValueReference.isActive()) { + cause = entryValue == null ? RemovalCause.COLLECTED : RemovalCause.REPLACED; + + enqueueNotification(key, hash, oldValueReference, cause); + newCount--; + } + setValue(e, key, newValue, now); + count = newCount; + evictEntries(); + return 1; + } + + + valueReference = new LocalCache.WeightedStrongValueReference(newValue, 0); + enqueueNotification(key, hash, valueReference, RemovalCause.REPLACED); + return 0; + } + } + + modCount += 1; + LocalCache.ReferenceEntry newEntry = newEntry(key, hash, first); + setValue(newEntry, key, newValue, now); + table.set(index, newEntry); + count = newCount; + evictEntries(); + return 1; + } finally { + unlock(); + postWriteCleanup(); + } + } + + boolean remove(Object key, int hash, Object value) { + lock(); + try { + long now = map.ticker.read(); + preWriteCleanup(now); + + int newCount = count - 1; + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + LocalCache.ReferenceEntry first = (LocalCache.ReferenceEntry)table.get(index); + + for (LocalCache.ReferenceEntry e = first; e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if ((e.getHash() == hash) && (entryKey != null) && (map.keyEquivalence.equivalent(key, entryKey))) + { + LocalCache.ValueReference valueReference = e.getValueReference(); + V entryValue = valueReference.get(); + + RemovalCause cause; + if (map.valueEquivalence.equivalent(value, entryValue)) { + cause = RemovalCause.EXPLICIT; } else { RemovalCause cause; + if ((entryValue == null) && (valueReference.isActive())) { + cause = RemovalCause.COLLECTED; + } + else + return false; + } + RemovalCause cause; + modCount += 1; + Object newFirst = removeValueFromChain(first, e, entryKey, hash, valueReference, cause); + + newCount = count - 1; + table.set(index, newFirst); + count = newCount; + return cause == RemovalCause.EXPLICIT; + } + } + + return 0; + } finally { + unlock(); + postWriteCleanup(); + } + } + + void clear() { + if (count != 0) { + lock(); + try { + AtomicReferenceArray> table = this.table; + for (int i = 0; i < table.length(); i++) { + for (LocalCache.ReferenceEntry e = (LocalCache.ReferenceEntry)table.get(i); e != null; e = e.getNext()) + { + if (e.getValueReference().isActive()) { + enqueueNotification(e, RemovalCause.EXPLICIT); + } + } + } + for (int i = 0; i < table.length(); i++) { + table.set(i, null); + } + clearReferenceQueues(); + writeQueue.clear(); + accessQueue.clear(); + readCount.set(0); + + modCount += 1; + count = 0; + } finally { + unlock(); + postWriteCleanup(); + } + } + } + + + @Nullable + @GuardedBy("Segment.this") + LocalCache.ReferenceEntry removeValueFromChain(LocalCache.ReferenceEntry first, LocalCache.ReferenceEntry entry, @Nullable K key, int hash, LocalCache.ValueReference valueReference, RemovalCause cause) + { + enqueueNotification(key, hash, valueReference, cause); + writeQueue.remove(entry); + accessQueue.remove(entry); + + if (valueReference.isLoading()) { + valueReference.notifyNewValue(null); + return first; + } + return removeEntryFromChain(first, entry); + } + + + @Nullable + @GuardedBy("Segment.this") + LocalCache.ReferenceEntry removeEntryFromChain(LocalCache.ReferenceEntry first, LocalCache.ReferenceEntry entry) + { + int newCount = count; + LocalCache.ReferenceEntry newFirst = entry.getNext(); + for (LocalCache.ReferenceEntry e = first; e != entry; e = e.getNext()) { + LocalCache.ReferenceEntry next = copyEntry(e, newFirst); + if (next != null) { + newFirst = next; + } else { + removeCollectedEntry(e); + newCount--; + } + } + count = newCount; + return newFirst; + } + + @GuardedBy("Segment.this") + void removeCollectedEntry(LocalCache.ReferenceEntry entry) { + enqueueNotification(entry, RemovalCause.COLLECTED); + writeQueue.remove(entry); + accessQueue.remove(entry); + } + + + + boolean reclaimKey(LocalCache.ReferenceEntry entry, int hash) + { + lock(); + try { + int newCount = count - 1; + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + LocalCache.ReferenceEntry first = (LocalCache.ReferenceEntry)table.get(index); + + for (LocalCache.ReferenceEntry e = first; e != null; e = e.getNext()) { + if (e == entry) { + modCount += 1; + LocalCache.ReferenceEntry newFirst = removeValueFromChain(first, e, e.getKey(), hash, e.getValueReference(), RemovalCause.COLLECTED); + + newCount = count - 1; + table.set(index, newFirst); + count = newCount; + return true; + } + } + + return 0; + } finally { + unlock(); + postWriteCleanup(); + } + } + + + + boolean reclaimValue(K key, int hash, LocalCache.ValueReference valueReference) + { + lock(); + try { + int newCount = count - 1; + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + LocalCache.ReferenceEntry first = (LocalCache.ReferenceEntry)table.get(index); + + for (LocalCache.ReferenceEntry e = first; e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if ((e.getHash() == hash) && (entryKey != null) && (map.keyEquivalence.equivalent(key, entryKey))) + { + LocalCache.ValueReference v = e.getValueReference(); + LocalCache.ReferenceEntry newFirst; if (v == valueReference) { + modCount += 1; + newFirst = removeValueFromChain(first, e, entryKey, hash, valueReference, RemovalCause.COLLECTED); + + newCount = count - 1; + table.set(index, newFirst); + count = newCount; + return true; + } + return 0; + } + } + + return 0; + } finally { + unlock(); + if (!isHeldByCurrentThread()) { + postWriteCleanup(); + } + } + } + + boolean removeLoadingValue(K key, int hash, LocalCache.LoadingValueReference valueReference) { + lock(); + try { + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + LocalCache.ReferenceEntry first = (LocalCache.ReferenceEntry)table.get(index); + + for (LocalCache.ReferenceEntry e = first; e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if ((e.getHash() == hash) && (entryKey != null) && (map.keyEquivalence.equivalent(key, entryKey))) + { + LocalCache.ValueReference v = e.getValueReference(); + LocalCache.ReferenceEntry newFirst; if (v == valueReference) { + if (valueReference.isActive()) { + e.setValueReference(valueReference.getOldValue()); + } else { + newFirst = removeEntryFromChain(first, e); + table.set(index, newFirst); + } + return 1; + } + return 0; + } + } + + return 0; + } finally { + unlock(); + postWriteCleanup(); + } + } + + @GuardedBy("Segment.this") + boolean removeEntry(LocalCache.ReferenceEntry entry, int hash, RemovalCause cause) { + int newCount = count - 1; + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + LocalCache.ReferenceEntry first = (LocalCache.ReferenceEntry)table.get(index); + + for (LocalCache.ReferenceEntry e = first; e != null; e = e.getNext()) { + if (e == entry) { + modCount += 1; + LocalCache.ReferenceEntry newFirst = removeValueFromChain(first, e, e.getKey(), hash, e.getValueReference(), cause); + + newCount = count - 1; + table.set(index, newFirst); + count = newCount; + return true; + } + } + + return false; + } + + + + + void postReadCleanup() + { + if ((readCount.incrementAndGet() & 0x3F) == 0) { + cleanUp(); + } + } + + + + + + + @GuardedBy("Segment.this") + void preWriteCleanup(long now) + { + runLockedCleanup(now); + } + + + + void postWriteCleanup() + { + runUnlockedCleanup(); + } + + void cleanUp() { + long now = map.ticker.read(); + runLockedCleanup(now); + runUnlockedCleanup(); + } + + void runLockedCleanup(long now) { + if (tryLock()) { + try { + drainReferenceQueues(); + expireEntries(now); + readCount.set(0); + } finally { + unlock(); + } + } + } + + void runUnlockedCleanup() + { + if (!isHeldByCurrentThread()) { + map.processPendingNotifications(); + } + } + } + + + static class LoadingValueReference + implements LocalCache.ValueReference + { + volatile LocalCache.ValueReference oldValue; + final SettableFuture futureValue = SettableFuture.create(); + final Stopwatch stopwatch = Stopwatch.createUnstarted(); + + public LoadingValueReference() { + this(LocalCache.unset()); + } + + public LoadingValueReference(LocalCache.ValueReference oldValue) { + this.oldValue = oldValue; + } + + public boolean isLoading() + { + return true; + } + + public boolean isActive() + { + return oldValue.isActive(); + } + + public int getWeight() + { + return oldValue.getWeight(); + } + + public boolean set(@Nullable V newValue) { + return futureValue.set(newValue); + } + + public boolean setException(Throwable t) { + return futureValue.setException(t); + } + + private ListenableFuture fullyFailedFuture(Throwable t) { + return Futures.immediateFailedFuture(t); + } + + public void notifyNewValue(@Nullable V newValue) + { + if (newValue != null) + { + + set(newValue); + } + else { + oldValue = LocalCache.unset(); + } + } + + + public ListenableFuture loadFuture(K key, CacheLoader loader) + { + stopwatch.start(); + V previousValue = oldValue.get(); + try { + if (previousValue == null) { + V newValue = loader.load(key); + return set(newValue) ? futureValue : Futures.immediateFuture(newValue); + } + ListenableFuture newValue = loader.reload(key, previousValue); + if (newValue == null) { + return Futures.immediateFuture(null); + } + + + Futures.transform(newValue, new Function() + { + public V apply(V newValue) { + set(newValue); + return newValue; + } + }); + } catch (Throwable t) { + if ((t instanceof InterruptedException)) { + Thread.currentThread().interrupt(); + } + return setException(t) ? futureValue : fullyFailedFuture(t); + } + } + + public long elapsedNanos() { + return stopwatch.elapsed(TimeUnit.NANOSECONDS); + } + + public V waitForValue() throws ExecutionException + { + return Uninterruptibles.getUninterruptibly(futureValue); + } + + public V get() + { + return oldValue.get(); + } + + public LocalCache.ValueReference getOldValue() { + return oldValue; + } + + public LocalCache.ReferenceEntry getEntry() + { + return null; + } + + + public LocalCache.ValueReference copyFor(ReferenceQueue queue, @Nullable V value, LocalCache.ReferenceEntry entry) + { + return this; + } + } + + + + + + + + + + + + + static final class WriteQueue + extends AbstractQueue> + { + final LocalCache.ReferenceEntry head = new LocalCache.AbstractReferenceEntry() + { + public long getWriteTime() + { + return Long.MAX_VALUE; + } + + + + + LocalCache.ReferenceEntry nextWrite = this; + + public void setWriteTime(long time) {} + + public LocalCache.ReferenceEntry getNextInWriteQueue() { return nextWrite; } + + + public void setNextInWriteQueue(LocalCache.ReferenceEntry next) + { + nextWrite = next; + } + + LocalCache.ReferenceEntry previousWrite = this; + + public LocalCache.ReferenceEntry getPreviousInWriteQueue() + { + return previousWrite; + } + + public void setPreviousInWriteQueue(LocalCache.ReferenceEntry previous) + { + previousWrite = previous; + } + }; + + + WriteQueue() {} + + public boolean offer(LocalCache.ReferenceEntry entry) + { + LocalCache.connectWriteOrder(entry.getPreviousInWriteQueue(), entry.getNextInWriteQueue()); + + + LocalCache.connectWriteOrder(head.getPreviousInWriteQueue(), entry); + LocalCache.connectWriteOrder(entry, head); + + return true; + } + + public LocalCache.ReferenceEntry peek() + { + LocalCache.ReferenceEntry next = head.getNextInWriteQueue(); + return next == head ? null : next; + } + + public LocalCache.ReferenceEntry poll() + { + LocalCache.ReferenceEntry next = head.getNextInWriteQueue(); + if (next == head) { + return null; + } + + remove(next); + return next; + } + + + public boolean remove(Object o) + { + LocalCache.ReferenceEntry e = (LocalCache.ReferenceEntry)o; + LocalCache.ReferenceEntry previous = e.getPreviousInWriteQueue(); + LocalCache.ReferenceEntry next = e.getNextInWriteQueue(); + LocalCache.connectWriteOrder(previous, next); + LocalCache.nullifyWriteOrder(e); + + return next != LocalCache.NullEntry.INSTANCE; + } + + + public boolean contains(Object o) + { + LocalCache.ReferenceEntry e = (LocalCache.ReferenceEntry)o; + return e.getNextInWriteQueue() != LocalCache.NullEntry.INSTANCE; + } + + public boolean isEmpty() + { + return head.getNextInWriteQueue() == head; + } + + public int size() + { + int size = 0; + for (LocalCache.ReferenceEntry e = head.getNextInWriteQueue(); e != head; + e = e.getNextInWriteQueue()) { + size++; + } + return size; + } + + public void clear() + { + LocalCache.ReferenceEntry e = head.getNextInWriteQueue(); + while (e != head) { + LocalCache.ReferenceEntry next = e.getNextInWriteQueue(); + LocalCache.nullifyWriteOrder(e); + e = next; + } + + head.setNextInWriteQueue(head); + head.setPreviousInWriteQueue(head); + } + + public Iterator> iterator() + { + new AbstractSequentialIterator(peek()) + { + protected LocalCache.ReferenceEntry computeNext(LocalCache.ReferenceEntry previous) { + LocalCache.ReferenceEntry next = previous.getNextInWriteQueue(); + return next == head ? null : next; + } + }; + } + } + + + + + + + + + + + static final class AccessQueue + extends AbstractQueue> + { + final LocalCache.ReferenceEntry head = new LocalCache.AbstractReferenceEntry() + { + public long getAccessTime() + { + return Long.MAX_VALUE; + } + + + + + LocalCache.ReferenceEntry nextAccess = this; + + public void setAccessTime(long time) {} + + public LocalCache.ReferenceEntry getNextInAccessQueue() { return nextAccess; } + + + public void setNextInAccessQueue(LocalCache.ReferenceEntry next) + { + nextAccess = next; + } + + LocalCache.ReferenceEntry previousAccess = this; + + public LocalCache.ReferenceEntry getPreviousInAccessQueue() + { + return previousAccess; + } + + public void setPreviousInAccessQueue(LocalCache.ReferenceEntry previous) + { + previousAccess = previous; + } + }; + + + AccessQueue() {} + + public boolean offer(LocalCache.ReferenceEntry entry) + { + LocalCache.connectAccessOrder(entry.getPreviousInAccessQueue(), entry.getNextInAccessQueue()); + + + LocalCache.connectAccessOrder(head.getPreviousInAccessQueue(), entry); + LocalCache.connectAccessOrder(entry, head); + + return true; + } + + public LocalCache.ReferenceEntry peek() + { + LocalCache.ReferenceEntry next = head.getNextInAccessQueue(); + return next == head ? null : next; + } + + public LocalCache.ReferenceEntry poll() + { + LocalCache.ReferenceEntry next = head.getNextInAccessQueue(); + if (next == head) { + return null; + } + + remove(next); + return next; + } + + + public boolean remove(Object o) + { + LocalCache.ReferenceEntry e = (LocalCache.ReferenceEntry)o; + LocalCache.ReferenceEntry previous = e.getPreviousInAccessQueue(); + LocalCache.ReferenceEntry next = e.getNextInAccessQueue(); + LocalCache.connectAccessOrder(previous, next); + LocalCache.nullifyAccessOrder(e); + + return next != LocalCache.NullEntry.INSTANCE; + } + + + public boolean contains(Object o) + { + LocalCache.ReferenceEntry e = (LocalCache.ReferenceEntry)o; + return e.getNextInAccessQueue() != LocalCache.NullEntry.INSTANCE; + } + + public boolean isEmpty() + { + return head.getNextInAccessQueue() == head; + } + + public int size() + { + int size = 0; + for (LocalCache.ReferenceEntry e = head.getNextInAccessQueue(); e != head; + e = e.getNextInAccessQueue()) { + size++; + } + return size; + } + + public void clear() + { + LocalCache.ReferenceEntry e = head.getNextInAccessQueue(); + while (e != head) { + LocalCache.ReferenceEntry next = e.getNextInAccessQueue(); + LocalCache.nullifyAccessOrder(e); + e = next; + } + + head.setNextInAccessQueue(head); + head.setPreviousInAccessQueue(head); + } + + public Iterator> iterator() + { + new AbstractSequentialIterator(peek()) + { + protected LocalCache.ReferenceEntry computeNext(LocalCache.ReferenceEntry previous) { + LocalCache.ReferenceEntry next = previous.getNextInAccessQueue(); + return next == head ? null : next; + } + }; + } + } + + + public void cleanUp() + { + for (Segment segment : segments) { + segment.cleanUp(); + } + } + + + + + + + + + + + public boolean isEmpty() + { + long sum = 0L; + Segment[] segments = this.segments; + for (int i = 0; i < segments.length; i++) { + if (count != 0) { + return false; + } + sum += modCount; + } + + if (sum != 0L) { + for (int i = 0; i < segments.length; i++) { + if (count != 0) { + return false; + } + sum -= modCount; + } + if (sum != 0L) { + return false; + } + } + return true; + } + + long longSize() { + Segment[] segments = this.segments; + long sum = 0L; + for (int i = 0; i < segments.length; i++) { + sum += count; + } + return sum; + } + + public int size() + { + return Ints.saturatedCast(longSize()); + } + + @Nullable + public V get(@Nullable Object key) + { + if (key == null) { + return null; + } + int hash = hash(key); + return segmentFor(hash).get(key, hash); + } + + @Nullable + public V getIfPresent(Object key) { + int hash = hash(Preconditions.checkNotNull(key)); + V value = segmentFor(hash).get(key, hash); + if (value == null) { + globalStatsCounter.recordMisses(1); + } else { + globalStatsCounter.recordHits(1); + } + return value; + } + + V get(K key, CacheLoader loader) throws ExecutionException { + int hash = hash(Preconditions.checkNotNull(key)); + return segmentFor(hash).get(key, hash, loader); + } + + V getOrLoad(K key) throws ExecutionException { + return get(key, defaultLoader); + } + + ImmutableMap getAllPresent(Iterable keys) { + int hits = 0; + int misses = 0; + + Map result = Maps.newLinkedHashMap(); + for (Object key : keys) { + V value = get(key); + if (value == null) { + misses++; + } + else + { + K castKey = key; + result.put(castKey, value); + hits++; + } + } + globalStatsCounter.recordHits(hits); + globalStatsCounter.recordMisses(misses); + return ImmutableMap.copyOf(result); + } + + ImmutableMap getAll(Iterable keys) throws ExecutionException { + int hits = 0; + int misses = 0; + + Map result = Maps.newLinkedHashMap(); + Set keysToLoad = Sets.newLinkedHashSet(); + for (K key : keys) { + V value = get(key); + if (!result.containsKey(key)) { + result.put(key, value); + if (value == null) { + misses++; + keysToLoad.add(key); + } else { + hits++; + } + } + } + try + { + if (!keysToLoad.isEmpty()) { + Iterator i$; + try { newEntries = loadAll(keysToLoad, defaultLoader); + for (K key : keysToLoad) { + V value = newEntries.get(key); + if (value == null) { + throw new CacheLoader.InvalidCacheLoadException("loadAll failed to return a value for " + key); + } + result.put(key, value); + } + } catch (CacheLoader.UnsupportedLoadingOperationException e) { + Map newEntries; + i$ = keysToLoad.iterator(); } while (i$.hasNext()) { K key = i$.next(); + misses--; + result.put(key, get(key, defaultLoader)); + } + } + + return ImmutableMap.copyOf(result); + } finally { + globalStatsCounter.recordHits(hits); + globalStatsCounter.recordMisses(misses); + } + } + + + + + @Nullable + Map loadAll(Set keys, CacheLoader loader) + throws ExecutionException + { + Preconditions.checkNotNull(loader); + Preconditions.checkNotNull(keys); + Stopwatch stopwatch = Stopwatch.createStarted(); + + boolean success = false; + Map result; + try { + Map map = loader.loadAll(keys); + result = map; + success = true; + } catch (CacheLoader.UnsupportedLoadingOperationException e) { + success = true; + throw e; + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ExecutionException(e); + } catch (RuntimeException e) { + throw new UncheckedExecutionException(e); + } catch (Exception e) { + throw new ExecutionException(e); + } catch (Error e) { + throw new ExecutionError(e); + } finally { + if (!success) { + globalStatsCounter.recordLoadException(stopwatch.elapsed(TimeUnit.NANOSECONDS)); + } + } + + if (result == null) { + globalStatsCounter.recordLoadException(stopwatch.elapsed(TimeUnit.NANOSECONDS)); + throw new CacheLoader.InvalidCacheLoadException(loader + " returned null map from loadAll"); + } + + stopwatch.stop(); + + boolean nullsPresent = false; + for (Map.Entry entry : result.entrySet()) { + K key = entry.getKey(); + V value = entry.getValue(); + if ((key == null) || (value == null)) + { + nullsPresent = true; + } else { + put(key, value); + } + } + + if (nullsPresent) { + globalStatsCounter.recordLoadException(stopwatch.elapsed(TimeUnit.NANOSECONDS)); + throw new CacheLoader.InvalidCacheLoadException(loader + " returned null keys or values from loadAll"); + } + + + globalStatsCounter.recordLoadSuccess(stopwatch.elapsed(TimeUnit.NANOSECONDS)); + return result; + } + + + + + + ReferenceEntry getEntry(@Nullable Object key) + { + if (key == null) { + return null; + } + int hash = hash(key); + return segmentFor(hash).getEntry(key, hash); + } + + void refresh(K key) { + int hash = hash(Preconditions.checkNotNull(key)); + segmentFor(hash).refresh(key, hash, defaultLoader, false); + } + + + public boolean containsKey(@Nullable Object key) + { + if (key == null) { + return false; + } + int hash = hash(key); + return segmentFor(hash).containsKey(key, hash); + } + + + public boolean containsValue(@Nullable Object value) + { + if (value == null) { + return false; + } + + + + + + + long now = ticker.read(); + Segment[] segments = this.segments; + long last = -1L; + for (int i = 0; i < 3; i++) { + long sum = 0L; + for (Segment segment : segments) + { + + int c = count; + + AtomicReferenceArray> table = table; + for (int j = 0; j < table.length(); j++) { + for (ReferenceEntry e = (ReferenceEntry)table.get(j); e != null; e = e.getNext()) { + V v = segment.getLiveValue(e, now); + if ((v != null) && (valueEquivalence.equivalent(value, v))) { + return true; + } + } + } + sum += modCount; + } + if (sum == last) { + break; + } + last = sum; + } + return false; + } + + public V put(K key, V value) + { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(value); + int hash = hash(key); + return segmentFor(hash).put(key, hash, value, false); + } + + public V putIfAbsent(K key, V value) + { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(value); + int hash = hash(key); + return segmentFor(hash).put(key, hash, value, true); + } + + public void putAll(Map m) + { + for (Map.Entry e : m.entrySet()) { + put(e.getKey(), e.getValue()); + } + } + + public V remove(@Nullable Object key) + { + if (key == null) { + return null; + } + int hash = hash(key); + return segmentFor(hash).remove(key, hash); + } + + public boolean remove(@Nullable Object key, @Nullable Object value) + { + if ((key == null) || (value == null)) { + return false; + } + int hash = hash(key); + return segmentFor(hash).remove(key, hash, value); + } + + public boolean replace(K key, @Nullable V oldValue, V newValue) + { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(newValue); + if (oldValue == null) { + return false; + } + int hash = hash(key); + return segmentFor(hash).replace(key, hash, oldValue, newValue); + } + + public V replace(K key, V value) + { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(value); + int hash = hash(key); + return segmentFor(hash).replace(key, hash, value); + } + + public void clear() + { + for (Segment segment : segments) { + segment.clear(); + } + } + + void invalidateAll(Iterable keys) + { + for (Object key : keys) { + remove(key); + } + } + + + + + public Set keySet() + { + Set ks = keySet; + return this.keySet = new KeySet(this); + } + + + + + public Collection values() + { + Collection vs = values; + return this.values = new Values(this); + } + + + + + @GwtIncompatible("Not supported.") + public Set> entrySet() + { + Set> es = entrySet; + return this.entrySet = new EntrySet(this); + } + + abstract class HashIterator + implements Iterator + { + int nextSegmentIndex; + int nextTableIndex; + LocalCache.Segment currentSegment; + AtomicReferenceArray> currentTable; + LocalCache.ReferenceEntry nextEntry; + LocalCache.WriteThroughEntry nextExternal; + LocalCache.WriteThroughEntry lastReturned; + + HashIterator() + { + nextSegmentIndex = (segments.length - 1); + nextTableIndex = -1; + advance(); + } + + public abstract T next(); + + final void advance() + { + nextExternal = null; + + if (nextInChain()) { + return; + } + + if (nextInTable()) { + return; + } + + while (nextSegmentIndex >= 0) { + currentSegment = segments[(nextSegmentIndex--)]; + if (currentSegment.count != 0) { + currentTable = currentSegment.table; + nextTableIndex = (currentTable.length() - 1); + if (nextInTable()) {} + } + } + } + + + + + + boolean nextInChain() + { + if (nextEntry != null) { + for (nextEntry = nextEntry.getNext(); nextEntry != null; nextEntry = nextEntry.getNext()) { + if (advanceTo(nextEntry)) { + return true; + } + } + } + return false; + } + + + + boolean nextInTable() + { + while (nextTableIndex >= 0) { + if (((this.nextEntry = (LocalCache.ReferenceEntry)currentTable.get(nextTableIndex--)) != null) && ( + (advanceTo(nextEntry)) || (nextInChain()))) { + return true; + } + } + + return false; + } + + + + boolean advanceTo(LocalCache.ReferenceEntry entry) + { + try + { + long now = ticker.read(); + K key = entry.getKey(); + V value = getLiveValue(entry, now); + boolean bool; if (value != null) { + nextExternal = new LocalCache.WriteThroughEntry(LocalCache.this, key, value); + return true; + } + + return false; + } + finally { + currentSegment.postReadCleanup(); + } + } + + public boolean hasNext() + { + return nextExternal != null; + } + + LocalCache.WriteThroughEntry nextEntry() { + if (nextExternal == null) { + throw new NoSuchElementException(); + } + lastReturned = nextExternal; + advance(); + return lastReturned; + } + + public void remove() + { + Preconditions.checkState(lastReturned != null); + remove(lastReturned.getKey()); + lastReturned = null; + } + } + + final class KeyIterator extends LocalCache.HashIterator { KeyIterator() { super(); } + + + + public K next() { return nextEntry().getKey(); } + } + + final class ValueIterator extends LocalCache.HashIterator { + ValueIterator() { super(); } + + public V next() + { + return nextEntry().getValue(); + } + } + + + final class WriteThroughEntry + implements Map.Entry + { + final K key; + V value; + + WriteThroughEntry(V key) + { + this.key = key; + this.value = value; + } + + public K getKey() + { + return key; + } + + public V getValue() + { + return value; + } + + + public boolean equals(@Nullable Object object) + { + if ((object instanceof Map.Entry)) { + Map.Entry that = (Map.Entry)object; + return (key.equals(that.getKey())) && (value.equals(that.getValue())); + } + return false; + } + + + public int hashCode() + { + return key.hashCode() ^ value.hashCode(); + } + + public V setValue(V newValue) + { + throw new UnsupportedOperationException(); + } + + + + + + public String toString() { return getKey() + "=" + getValue(); } + } + + final class EntryIterator extends LocalCache.HashIterator> { + EntryIterator() { super(); } + + public Map.Entry next() + { + return nextEntry(); + } + } + + abstract class AbstractCacheSet extends AbstractSet { + final ConcurrentMap map; + + AbstractCacheSet() { + this.map = map; + } + + public int size() + { + return map.size(); + } + + public boolean isEmpty() + { + return map.isEmpty(); + } + + public void clear() + { + map.clear(); + } + } + + final class KeySet extends LocalCache.AbstractCacheSet + { + KeySet() { + super(map); + } + + public Iterator iterator() + { + return new LocalCache.KeyIterator(LocalCache.this); + } + + public boolean contains(Object o) + { + return map.containsKey(o); + } + + public boolean remove(Object o) + { + return map.remove(o) != null; + } + } + + final class Values extends AbstractCollection { + private final ConcurrentMap map; + + Values() { + this.map = map; + } + + public int size() { + return map.size(); + } + + public boolean isEmpty() { + return map.isEmpty(); + } + + public void clear() { + map.clear(); + } + + public Iterator iterator() + { + return new LocalCache.ValueIterator(LocalCache.this); + } + + public boolean contains(Object o) + { + return map.containsValue(o); + } + } + + final class EntrySet extends LocalCache.AbstractCacheSet> + { + EntrySet() { + super(map); + } + + public Iterator> iterator() + { + return new LocalCache.EntryIterator(LocalCache.this); + } + + public boolean contains(Object o) + { + if (!(o instanceof Map.Entry)) { + return false; + } + Map.Entry e = (Map.Entry)o; + Object key = e.getKey(); + if (key == null) { + return false; + } + V v = get(key); + + return (v != null) && (valueEquivalence.equivalent(e.getValue(), v)); + } + + public boolean remove(Object o) + { + if (!(o instanceof Map.Entry)) { + return false; + } + Map.Entry e = (Map.Entry)o; + Object key = e.getKey(); + return (key != null) && (remove(key, e.getValue())); + } + } + + + static class ManualSerializationProxy + extends ForwardingCache + implements Serializable + { + private static final long serialVersionUID = 1L; + + final LocalCache.Strength keyStrength; + + final LocalCache.Strength valueStrength; + + final Equivalence keyEquivalence; + + final Equivalence valueEquivalence; + + final long expireAfterWriteNanos; + + final long expireAfterAccessNanos; + + final long maxWeight; + + final Weigher weigher; + final int concurrencyLevel; + final RemovalListener removalListener; + final Ticker ticker; + final CacheLoader loader; + transient Cache delegate; + + ManualSerializationProxy(LocalCache cache) + { + this(keyStrength, valueStrength, keyEquivalence, valueEquivalence, expireAfterWriteNanos, expireAfterAccessNanos, maxWeight, weigher, concurrencyLevel, removalListener, ticker, defaultLoader); + } + + + + + + + + + + + + + + + + + + + private ManualSerializationProxy(LocalCache.Strength keyStrength, LocalCache.Strength valueStrength, Equivalence keyEquivalence, Equivalence valueEquivalence, long expireAfterWriteNanos, long expireAfterAccessNanos, long maxWeight, Weigher weigher, int concurrencyLevel, RemovalListener removalListener, Ticker ticker, CacheLoader loader) + { + this.keyStrength = keyStrength; + this.valueStrength = valueStrength; + this.keyEquivalence = keyEquivalence; + this.valueEquivalence = valueEquivalence; + this.expireAfterWriteNanos = expireAfterWriteNanos; + this.expireAfterAccessNanos = expireAfterAccessNanos; + this.maxWeight = maxWeight; + this.weigher = weigher; + this.concurrencyLevel = concurrencyLevel; + this.removalListener = removalListener; + this.ticker = ((ticker == Ticker.systemTicker()) || (ticker == CacheBuilder.NULL_TICKER) ? null : ticker); + + this.loader = loader; + } + + CacheBuilder recreateCacheBuilder() { + CacheBuilder builder = CacheBuilder.newBuilder().setKeyStrength(keyStrength).setValueStrength(valueStrength).keyEquivalence(keyEquivalence).valueEquivalence(valueEquivalence).concurrencyLevel(concurrencyLevel).removalListener(removalListener); + + + + + + + strictParsing = false; + if (expireAfterWriteNanos > 0L) { + builder.expireAfterWrite(expireAfterWriteNanos, TimeUnit.NANOSECONDS); + } + if (expireAfterAccessNanos > 0L) { + builder.expireAfterAccess(expireAfterAccessNanos, TimeUnit.NANOSECONDS); + } + if (weigher != CacheBuilder.OneWeigher.INSTANCE) { + builder.weigher(weigher); + if (maxWeight != -1L) { + builder.maximumWeight(maxWeight); + } + } + else if (maxWeight != -1L) { + builder.maximumSize(maxWeight); + } + + if (ticker != null) { + builder.ticker(ticker); + } + return builder; + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + CacheBuilder builder = recreateCacheBuilder(); + delegate = builder.build(); + } + + private Object readResolve() { + return delegate; + } + + protected Cache delegate() + { + return delegate; + } + } + + + + static final class LoadingSerializationProxy + extends LocalCache.ManualSerializationProxy + implements LoadingCache, Serializable + { + private static final long serialVersionUID = 1L; + + + transient LoadingCache autoDelegate; + + + + LoadingSerializationProxy(LocalCache cache) + { + super(); + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + CacheBuilder builder = recreateCacheBuilder(); + autoDelegate = builder.build(loader); + } + + public V get(K key) throws ExecutionException + { + return autoDelegate.get(key); + } + + public V getUnchecked(K key) + { + return autoDelegate.getUnchecked(key); + } + + public ImmutableMap getAll(Iterable keys) throws ExecutionException + { + return autoDelegate.getAll(keys); + } + + public final V apply(K key) + { + return autoDelegate.apply(key); + } + + public void refresh(K key) + { + autoDelegate.refresh(key); + } + + private Object readResolve() { + return autoDelegate; + } + } + + static class LocalManualCache implements Cache, Serializable { + final LocalCache localCache; + private static final long serialVersionUID = 1L; + + LocalManualCache(CacheBuilder builder) { this(new LocalCache(builder, null)); } + + private LocalManualCache(LocalCache localCache) + { + this.localCache = localCache; + } + + + + @Nullable + public V getIfPresent(Object key) + { + return localCache.getIfPresent(key); + } + + public V get(K key, final Callable valueLoader) throws ExecutionException + { + Preconditions.checkNotNull(valueLoader); + localCache.get(key, new CacheLoader() + { + public V load(Object key) throws Exception { + return valueLoader.call(); + } + }); + } + + public ImmutableMap getAllPresent(Iterable keys) + { + return localCache.getAllPresent(keys); + } + + public void put(K key, V value) + { + localCache.put(key, value); + } + + public void putAll(Map m) + { + localCache.putAll(m); + } + + public void invalidate(Object key) + { + Preconditions.checkNotNull(key); + localCache.remove(key); + } + + public void invalidateAll(Iterable keys) + { + localCache.invalidateAll(keys); + } + + public void invalidateAll() + { + localCache.clear(); + } + + public long size() + { + return localCache.longSize(); + } + + public ConcurrentMap asMap() + { + return localCache; + } + + public CacheStats stats() + { + AbstractCache.SimpleStatsCounter aggregator = new AbstractCache.SimpleStatsCounter(); + aggregator.incrementBy(localCache.globalStatsCounter); + for (LocalCache.Segment segment : localCache.segments) { + aggregator.incrementBy(statsCounter); + } + return aggregator.snapshot(); + } + + public void cleanUp() + { + localCache.cleanUp(); + } + + + + + Object writeReplace() + { + return new LocalCache.ManualSerializationProxy(localCache); + } + } + + static class LocalLoadingCache extends LocalCache.LocalManualCache implements LoadingCache + { + private static final long serialVersionUID = 1L; + + LocalLoadingCache(CacheBuilder builder, CacheLoader loader) { + super(null); + } + + + public V get(K key) + throws ExecutionException + { + return localCache.getOrLoad(key); + } + + public V getUnchecked(K key) + { + try { + return get(key); + } catch (ExecutionException e) { + throw new UncheckedExecutionException(e.getCause()); + } + } + + public ImmutableMap getAll(Iterable keys) throws ExecutionException + { + return localCache.getAll(keys); + } + + public void refresh(K key) + { + localCache.refresh(key); + } + + public final V apply(K key) + { + return getUnchecked(key); + } + + + + + + Object writeReplace() + { + return new LocalCache.LoadingSerializationProxy(localCache); + } + } +} diff --git a/src/minecraft/com/google/common/cache/LongAddable.java b/src/minecraft/com/google/common/cache/LongAddable.java new file mode 100644 index 0000000..8251a55 --- /dev/null +++ b/src/minecraft/com/google/common/cache/LongAddable.java @@ -0,0 +1,13 @@ +package com.google.common.cache; + +import com.google.common.annotations.GwtCompatible; + +@GwtCompatible +abstract interface LongAddable +{ + public abstract void increment(); + + public abstract void add(long paramLong); + + public abstract long sum(); +} diff --git a/src/minecraft/com/google/common/cache/LongAddables.java b/src/minecraft/com/google/common/cache/LongAddables.java new file mode 100644 index 0000000..faf58e2 --- /dev/null +++ b/src/minecraft/com/google/common/cache/LongAddables.java @@ -0,0 +1,75 @@ +package com.google.common.cache; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Supplier; +import java.util.concurrent.atomic.AtomicLong; + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +final class LongAddables +{ + private static final Supplier SUPPLIER; + + static + { + Supplier supplier; + try + { + new LongAdder(); + supplier = new Supplier() + { + public LongAddable get() { + return new LongAdder(); + } + }; + } catch (Throwable t) { + supplier = new Supplier() + { + public LongAddable get() { + return new LongAddables.PureJavaLongAddable(null); + } + }; + } + SUPPLIER = supplier; + } + + + public static LongAddable create() { return (LongAddable)SUPPLIER.get(); } + + LongAddables() {} + + private static final class PureJavaLongAddable extends AtomicLong implements LongAddable { private PureJavaLongAddable() {} + + public void increment() { getAndIncrement(); } + + + public void add(long x) + { + getAndAdd(x); + } + + public long sum() + { + return get(); + } + } +} diff --git a/src/minecraft/com/google/common/cache/LongAdder.java b/src/minecraft/com/google/common/cache/LongAdder.java new file mode 100644 index 0000000..f632cf1 --- /dev/null +++ b/src/minecraft/com/google/common/cache/LongAdder.java @@ -0,0 +1,210 @@ +package com.google.common.cache; + +import com.google.common.annotations.GwtCompatible; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +final class LongAdder + extends Striped64 + implements Serializable, LongAddable +{ + private static final long serialVersionUID = 7249069246863182397L; + + final long fn(long v, long x) + { + return v + x; + } + + + + public LongAdder() {} + + + + public void add(long x) + { + Striped64.Cell[] as; + + long b; + + if (((as = cells) != null) || (!casBase(b = base, b + x))) { + boolean uncontended = true; + Striped64.HashCode hc; int h = threadHashCodegetcode; + int n; Striped64.Cell a; long v; if ((as == null) || ((n = as.length) < 1) || ((a = as[(n - 1 & h)]) == null) || (!(uncontended = a.cas(v = value, v + x)))) + { + + retryUpdate(x, hc, uncontended); + } + } + } + + + public void increment() + { + add(1L); + } + + + + public void decrement() + { + add(-1L); + } + + + + + + + + + + public long sum() + { + long sum = base; + Striped64.Cell[] as = cells; + if (as != null) { + int n = as.length; + for (int i = 0; i < n; i++) { + Striped64.Cell a = as[i]; + if (a != null) + sum += value; + } + } + return sum; + } + + + + + + + + public void reset() + { + internalReset(0L); + } + + + + + + + + + + + public long sumThenReset() + { + long sum = base; + Striped64.Cell[] as = cells; + base = 0L; + if (as != null) { + int n = as.length; + for (int i = 0; i < n; i++) { + Striped64.Cell a = as[i]; + if (a != null) { + sum += value; + value = 0L; + } + } + } + return sum; + } + + + + + public String toString() + { + return Long.toString(sum()); + } + + + + + + public long longValue() + { + return sum(); + } + + + + + public int intValue() + { + return (int)sum(); + } + + + + + public float floatValue() + { + return (float)sum(); + } + + + + + public double doubleValue() + { + return sum(); + } + + private void writeObject(ObjectOutputStream s) throws IOException + { + s.defaultWriteObject(); + s.writeLong(sum()); + } + + private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException + { + s.defaultReadObject(); + busy = 0; + cells = null; + base = s.readLong(); + } +} diff --git a/src/minecraft/com/google/common/cache/RemovalCause.java b/src/minecraft/com/google/common/cache/RemovalCause.java new file mode 100644 index 0000000..6db1ab1 --- /dev/null +++ b/src/minecraft/com/google/common/cache/RemovalCause.java @@ -0,0 +1,15 @@ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; + +@Beta +@GwtCompatible +public enum RemovalCause +{ + EXPLICIT, REPLACED, COLLECTED, EXPIRED, SIZE; + + private RemovalCause() {} + + abstract boolean wasEvicted(); +} diff --git a/src/minecraft/com/google/common/cache/RemovalListener.java b/src/minecraft/com/google/common/cache/RemovalListener.java new file mode 100644 index 0000000..ca51142 --- /dev/null +++ b/src/minecraft/com/google/common/cache/RemovalListener.java @@ -0,0 +1,11 @@ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; + +@Beta +@GwtCompatible +public abstract interface RemovalListener +{ + public abstract void onRemoval(RemovalNotification paramRemovalNotification); +} diff --git a/src/minecraft/com/google/common/cache/RemovalListeners.java b/src/minecraft/com/google/common/cache/RemovalListeners.java new file mode 100644 index 0000000..4a83946 --- /dev/null +++ b/src/minecraft/com/google/common/cache/RemovalListeners.java @@ -0,0 +1,60 @@ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import java.util.concurrent.Executor; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class RemovalListeners +{ + private RemovalListeners() {} + + public static RemovalListener asynchronous(final RemovalListener listener, Executor executor) + { + Preconditions.checkNotNull(listener); + Preconditions.checkNotNull(executor); + new RemovalListener() + { + public void onRemoval(final RemovalNotification notification) { + val$executor.execute(new Runnable() + { + public void run() { + val$listener.onRemoval(notification); + } + }); + } + }; + } +} diff --git a/src/minecraft/com/google/common/cache/RemovalNotification.java b/src/minecraft/com/google/common/cache/RemovalNotification.java new file mode 100644 index 0000000..f767942 --- /dev/null +++ b/src/minecraft/com/google/common/cache/RemovalNotification.java @@ -0,0 +1,101 @@ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import java.util.Map.Entry; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +public final class RemovalNotification + implements Map.Entry +{ + @Nullable + private final K key; + @Nullable + private final V value; + private final RemovalCause cause; + private static final long serialVersionUID = 0L; + + RemovalNotification(@Nullable K key, @Nullable V value, RemovalCause cause) + { + this.key = key; + this.value = value; + this.cause = ((RemovalCause)Preconditions.checkNotNull(cause)); + } + + + + public RemovalCause getCause() + { + return cause; + } + + + + + public boolean wasEvicted() + { + return cause.wasEvicted(); + } + + @Nullable + public K getKey() { return key; } + + @Nullable + public V getValue() { + return value; + } + + public final V setValue(V value) { + throw new UnsupportedOperationException(); + } + + public boolean equals(@Nullable Object object) { + if ((object instanceof Map.Entry)) { + Map.Entry that = (Map.Entry)object; + return (Objects.equal(getKey(), that.getKey())) && (Objects.equal(getValue(), that.getValue())); + } + + return false; + } + + public int hashCode() { + K k = getKey(); + V v = getValue(); + return (k == null ? 0 : k.hashCode()) ^ (v == null ? 0 : v.hashCode()); + } + + + + public String toString() + { + return getKey() + "=" + getValue(); + } +} diff --git a/src/minecraft/com/google/common/cache/Striped64.java b/src/minecraft/com/google/common/cache/Striped64.java new file mode 100644 index 0000000..2f3b125 --- /dev/null +++ b/src/minecraft/com/google/common/cache/Striped64.java @@ -0,0 +1,350 @@ +package com.google.common.cache; + +import java.lang.reflect.Field; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.Random; +import sun.misc.Unsafe; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +abstract class Striped64 + extends Number +{ + static final class Cell + { + volatile long p0; + volatile long p1; + volatile long p2; + volatile long p3; + volatile long p4; + volatile long p5; + volatile long p6; + volatile long value; + volatile long q0; + volatile long q1; + volatile long q2; + volatile long q3; + volatile long q4; + volatile long q5; + volatile long q6; + private static final Unsafe UNSAFE; + private static final long valueOffset; + + Cell(long x) + { + value = x; + } + + final boolean cas(long cmp, long val) { return UNSAFE.compareAndSwapLong(this, valueOffset, cmp, val); } + + + + static + { + try + { + UNSAFE = Striped64.access$000(); + Class ak = Cell.class; + valueOffset = UNSAFE.objectFieldOffset(ak.getDeclaredField("value")); + } + catch (Exception e) { + throw new Error(e); + } + } + } + + + + + + static final class HashCode + { + static final Random rng = new Random(); + int code; + + HashCode() { int h = rng.nextInt(); + code = (h == 0 ? 1 : h); + } + } + + static final class ThreadHashCode extends ThreadLocal { + ThreadHashCode() {} + + public Striped64.HashCode initialValue() { + return new Striped64.HashCode(); + } + } + + + + + + + static final ThreadHashCode threadHashCode = new ThreadHashCode(); + + + static final int NCPU = Runtime.getRuntime().availableProcessors(); + + + + volatile transient Cell[] cells; + + + + volatile transient long base; + + + + volatile transient int busy; + + + + private static final Unsafe UNSAFE; + + + private static final long baseOffset; + + + private static final long busyOffset; + + + + final boolean casBase(long cmp, long val) + { + return UNSAFE.compareAndSwapLong(this, baseOffset, cmp, val); + } + + + + final boolean casBusy() + { + return UNSAFE.compareAndSwapInt(this, busyOffset, 0, 1); + } + + + + + + + + + + + + + + + + + + + + + + + final void retryUpdate(long x, HashCode hc, boolean wasUncontended) + { + int h = code; + boolean collide = false; + for (;;) { Cell[] as; + int n; + if (((as = cells) != null) && ((n = as.length) > 0)) { Cell a; + if ((a = as[(n - 1 & h)]) == null) { + if (busy == 0) { + Cell r = new Cell(x); + if ((busy == 0) && (casBusy())) { + boolean created = false; + try { Cell[] rs; + int m; + int j; if (((rs = cells) != null) && ((m = rs.length) > 0) && (rs[(j = m - 1 & h)] == null)) + { + + rs[j] = r; + created = true; + } + } finally { + busy = 0; + } + if (!created) continue; + break; + } + } + + collide = false; + } + else if (!wasUncontended) { + wasUncontended = true; } else { long v; + if (a.cas(v = value, fn(v, x))) + break; + if ((n >= NCPU) || (cells != as)) { + collide = false; + } else if (!collide) { + collide = true; + } else if ((busy == 0) && (casBusy())) { + try { + if (cells == as) { + Cell[] rs = new Cell[n << 1]; + for (int i = 0; i < n; i++) + rs[i] = as[i]; + cells = rs; + } + } finally { + busy = 0; + } + collide = false; + continue; + } } + h ^= h << 13; + h ^= h >>> 17; + h ^= h << 5; + } + else if ((busy == 0) && (cells == as) && (casBusy())) { + boolean init = false; + try { + if (cells == as) { + Cell[] rs = new Cell[2]; + rs[(h & 0x1)] = new Cell(x); + cells = rs; + init = true; + } + } finally { + busy = 0; + } + if (init) + break; + } else { long v; + if (casBase(v = base, fn(v, x))) break; + } + } + code = h; + } + + + + final void internalReset(long initialValue) + { + Cell[] as = cells; + base = initialValue; + if (as != null) { + int n = as.length; + for (int i = 0; i < n; i++) { + Cell a = as[i]; + if (a != null) { + value = initialValue; + } + } + } + } + + + static + { + try + { + UNSAFE = getUnsafe(); + Class sk = Striped64.class; + baseOffset = UNSAFE.objectFieldOffset(sk.getDeclaredField("base")); + + busyOffset = UNSAFE.objectFieldOffset(sk.getDeclaredField("busy")); + } + catch (Exception e) { + throw new Error(e); + } + } + + + + + + + private static Unsafe getUnsafe() + { + try + { + return Unsafe.getUnsafe(); + } catch (SecurityException tryReflectionInstead) { + try { + (Unsafe)AccessController.doPrivileged(new PrivilegedExceptionAction() + { + public Unsafe run() throws Exception { + Class k = Unsafe.class; + for (Field f : k.getDeclaredFields()) { + f.setAccessible(true); + Object x = f.get(null); + if (k.isInstance(x)) + return (Unsafe)k.cast(x); + } + throw new NoSuchFieldError("the Unsafe"); + } + }); + } catch (PrivilegedActionException e) { throw new RuntimeException("Could not initialize intrinsics", e.getCause()); + } + } + } + + Striped64() {} + + abstract long fn(long paramLong1, long paramLong2); +} diff --git a/src/minecraft/com/google/common/cache/Weigher.java b/src/minecraft/com/google/common/cache/Weigher.java new file mode 100644 index 0000000..2d7aabc --- /dev/null +++ b/src/minecraft/com/google/common/cache/Weigher.java @@ -0,0 +1,11 @@ +package com.google.common.cache; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; + +@Beta +@GwtCompatible +public abstract interface Weigher +{ + public abstract int weigh(K paramK, V paramV); +} diff --git a/src/minecraft/com/google/common/cache/package-info.java b/src/minecraft/com/google/common/cache/package-info.java new file mode 100644 index 0000000..bc2e1e5 --- /dev/null +++ b/src/minecraft/com/google/common/cache/package-info.java @@ -0,0 +1,6 @@ +package com.google.common.cache; + +import javax.annotation.ParametersAreNonnullByDefault; + +@ParametersAreNonnullByDefault +abstract interface package-info {} diff --git a/src/minecraft/com/google/common/collect/AbstractBiMap.java b/src/minecraft/com/google/common/collect/AbstractBiMap.java new file mode 100644 index 0000000..d22896b --- /dev/null +++ b/src/minecraft/com/google/common/collect/AbstractBiMap.java @@ -0,0 +1,399 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +abstract class AbstractBiMap + extends ForwardingMap + implements BiMap, Serializable +{ + private transient Map delegate; + transient AbstractBiMap inverse; + private transient Set keySet; + private transient Set valueSet; + private transient Set> entrySet; + @GwtIncompatible("Not needed in emulated source.") + private static final long serialVersionUID = 0L; + + AbstractBiMap(Map forward, Map backward) + { + setDelegates(forward, backward); + } + + private AbstractBiMap(Map backward, AbstractBiMap forward) + { + delegate = backward; + inverse = forward; + } + + protected Map delegate() { + return delegate; + } + + + + K checkKey(@Nullable K key) + { + return key; + } + + + + V checkValue(@Nullable V value) + { + return value; + } + + + + + void setDelegates(Map forward, Map backward) + { + Preconditions.checkState(delegate == null); + Preconditions.checkState(inverse == null); + Preconditions.checkArgument(forward.isEmpty()); + Preconditions.checkArgument(backward.isEmpty()); + Preconditions.checkArgument(forward != backward); + delegate = forward; + inverse = new Inverse(backward, this, null); + } + + void setInverse(AbstractBiMap inverse) { + this.inverse = inverse; + } + + + public boolean containsValue(@Nullable Object value) + { + return inverse.containsKey(value); + } + + + public V put(@Nullable K key, @Nullable V value) + { + return putInBothMaps(key, value, false); + } + + public V forcePut(@Nullable K key, @Nullable V value) + { + return putInBothMaps(key, value, true); + } + + private V putInBothMaps(@Nullable K key, @Nullable V value, boolean force) { + checkKey(key); + checkValue(value); + boolean containedKey = containsKey(key); + if ((containedKey) && (Objects.equal(value, get(key)))) { + return value; + } + if (force) { + inverse().remove(value); + } else { + Preconditions.checkArgument(!containsValue(value), "value already present: %s", new Object[] { value }); + } + V oldValue = delegate.put(key, value); + updateInverseMap(key, containedKey, oldValue, value); + return oldValue; + } + + private void updateInverseMap(K key, boolean containedKey, V oldValue, V newValue) + { + if (containedKey) { + removeFromInverseMap(oldValue); + } + inverse.delegate.put(newValue, key); + } + + public V remove(@Nullable Object key) { + return containsKey(key) ? removeFromBothMaps(key) : null; + } + + private V removeFromBothMaps(Object key) { + V oldValue = delegate.remove(key); + removeFromInverseMap(oldValue); + return oldValue; + } + + private void removeFromInverseMap(V oldValue) { + inverse.delegate.remove(oldValue); + } + + + public void putAll(Map map) + { + for (Map.Entry entry : map.entrySet()) { + put(entry.getKey(), entry.getValue()); + } + } + + public void clear() { + delegate.clear(); + inverse.delegate.clear(); + } + + + + public BiMap inverse() + { + return inverse; + } + + + public Set keySet() + { + Set result = keySet; + return result == null ? (this.keySet = new KeySet(null)) : result; + } + + private class KeySet extends ForwardingSet { private KeySet() {} + + protected Set delegate() { return delegate.keySet(); } + + public void clear() + { + AbstractBiMap.this.clear(); + } + + public boolean remove(Object key) { + if (!contains(key)) { + return false; + } + AbstractBiMap.this.removeFromBothMaps(key); + return true; + } + + public boolean removeAll(Collection keysToRemove) { + return standardRemoveAll(keysToRemove); + } + + public boolean retainAll(Collection keysToRetain) { + return standardRetainAll(keysToRetain); + } + + public Iterator iterator() { + return Maps.keyIterator(entrySet().iterator()); + } + } + + + + + + + public Set values() + { + Set result = valueSet; + return result == null ? (this.valueSet = new ValueSet(null)) : result; } + + private class ValueSet extends ForwardingSet { private ValueSet() {} + + final Set valuesDelegate = inverse.keySet(); + + protected Set delegate() { + return valuesDelegate; + } + + public Iterator iterator() { + return Maps.valueIterator(entrySet().iterator()); + } + + public Object[] toArray() { + return standardToArray(); + } + + public T[] toArray(T[] array) { + return standardToArray(array); + } + + public String toString() { + return standardToString(); + } + } + + + public Set> entrySet() + { + Set> result = entrySet; + return result == null ? (this.entrySet = new EntrySet(null)) : result; } + + private class EntrySet extends ForwardingSet> { private EntrySet() {} + + final Set> esDelegate = delegate.entrySet(); + + protected Set> delegate() { + return esDelegate; + } + + public void clear() { + AbstractBiMap.this.clear(); + } + + public boolean remove(Object object) { + if (!esDelegate.contains(object)) { + return false; + } + + + Map.Entry entry = (Map.Entry)object; + inverse.delegate.remove(entry.getValue()); + + + + + + esDelegate.remove(entry); + return true; + } + + public Iterator> iterator() { + final Iterator> iterator = esDelegate.iterator(); + new Iterator() { + Map.Entry entry; + + public boolean hasNext() { + return iterator.hasNext(); + } + + public Map.Entry next() { + entry = ((Map.Entry)iterator.next()); + final Map.Entry finalEntry = entry; + + new ForwardingMapEntry() { + protected Map.Entry delegate() { + return finalEntry; + } + + public V setValue(V value) + { + Preconditions.checkState(contains(this), "entry no longer in map"); + + if (Objects.equal(value, getValue())) { + return value; + } + Preconditions.checkArgument(!containsValue(value), "value already present: %s", new Object[] { value }); + + V oldValue = finalEntry.setValue(value); + Preconditions.checkState(Objects.equal(value, get(getKey())), "entry no longer in map"); + + AbstractBiMap.this.updateInverseMap(getKey(), true, oldValue, value); + return oldValue; + } + }; + } + + public void remove() { + CollectPreconditions.checkRemove(entry != null); + V value = entry.getValue(); + iterator.remove(); + AbstractBiMap.this.removeFromInverseMap(value); + } + }; + } + + + public Object[] toArray() + { + return standardToArray(); + } + + public T[] toArray(T[] array) { return standardToArray(array); } + + public boolean contains(Object o) { + return Maps.containsEntryImpl(delegate(), o); + } + + public boolean containsAll(Collection c) { return standardContainsAll(c); } + + public boolean removeAll(Collection c) { + return standardRemoveAll(c); + } + + public boolean retainAll(Collection c) { return standardRetainAll(c); } + } + + private static class Inverse extends AbstractBiMap { + @GwtIncompatible("Not needed in emulated source.") + private static final long serialVersionUID = 0L; + + private Inverse(Map backward, AbstractBiMap forward) { super(forward, null); } + + + + + + + + + + + + K checkKey(K key) + { + return inverse.checkValue(key); + } + + V checkValue(V value) + { + return inverse.checkKey(value); + } + + + @GwtIncompatible("java.io.ObjectOuputStream") + private void writeObject(ObjectOutputStream stream) + throws IOException + { + stream.defaultWriteObject(); + stream.writeObject(inverse()); + } + + @GwtIncompatible("java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException + { + stream.defaultReadObject(); + setInverse((AbstractBiMap)stream.readObject()); + } + + @GwtIncompatible("Not needed in the emulated source.") + Object readResolve() { + return inverse().inverse(); + } + } +} diff --git a/src/minecraft/com/google/common/collect/AbstractIndexedListIterator.java b/src/minecraft/com/google/common/collect/AbstractIndexedListIterator.java new file mode 100644 index 0000000..61a2272 --- /dev/null +++ b/src/minecraft/com/google/common/collect/AbstractIndexedListIterator.java @@ -0,0 +1,109 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.NoSuchElementException; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +abstract class AbstractIndexedListIterator + extends UnmodifiableListIterator +{ + private final int size; + private int position; + + protected abstract E get(int paramInt); + + protected AbstractIndexedListIterator(int size) + { + this(size, 0); + } + + + + + + + + + + + + protected AbstractIndexedListIterator(int size, int position) + { + Preconditions.checkPositionIndex(position, size); + this.size = size; + this.position = position; + } + + public final boolean hasNext() + { + return position < size; + } + + public final E next() + { + if (!hasNext()) { + throw new NoSuchElementException(); + } + return get(position++); + } + + public final int nextIndex() + { + return position; + } + + public final boolean hasPrevious() + { + return position > 0; + } + + public final E previous() + { + if (!hasPrevious()) { + throw new NoSuchElementException(); + } + return get(--position); + } + + public final int previousIndex() + { + return position - 1; + } +} diff --git a/src/minecraft/com/google/common/collect/AbstractIterator.java b/src/minecraft/com/google/common/collect/AbstractIterator.java new file mode 100644 index 0000000..2805b7e --- /dev/null +++ b/src/minecraft/com/google/common/collect/AbstractIterator.java @@ -0,0 +1,175 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.NoSuchElementException; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public abstract class AbstractIterator + extends UnmodifiableIterator +{ + private State state = State.NOT_READY; + private T next; + protected AbstractIterator() {} + + protected abstract T computeNext(); + + private static enum State { + READY, + + + NOT_READY, + + + DONE, + + + FAILED; + + + + + + + + + + + + + + + + + + + + private State() {} + } + + + + + + + + + + + + + + + + + + + + protected final T endOfData() + { + state = State.DONE; + return null; + } + + public final boolean hasNext() + { + Preconditions.checkState(state != State.FAILED); + switch (1.$SwitchMap$com$google$common$collect$AbstractIterator$State[state.ordinal()]) { + case 1: + return false; + case 2: + return true; + } + + return tryToComputeNext(); + } + + private boolean tryToComputeNext() { + state = State.FAILED; + next = computeNext(); + if (state != State.DONE) { + state = State.READY; + return true; + } + return false; + } + + public final T next() + { + if (!hasNext()) { + throw new NoSuchElementException(); + } + state = State.NOT_READY; + T result = next; + next = null; + return result; + } + + + + + + + + public final T peek() + { + if (!hasNext()) { + throw new NoSuchElementException(); + } + return next; + } +} diff --git a/src/minecraft/com/google/common/collect/AbstractListMultimap.java b/src/minecraft/com/google/common/collect/AbstractListMultimap.java new file mode 100644 index 0000000..01b6d82 --- /dev/null +++ b/src/minecraft/com/google/common/collect/AbstractListMultimap.java @@ -0,0 +1,123 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +abstract class AbstractListMultimap + extends AbstractMapBasedMultimap + implements ListMultimap +{ + private static final long serialVersionUID = 6588350623831699109L; + + protected AbstractListMultimap(Map> map) + { + super(map); + } + + abstract List createCollection(); + + List createUnmodifiableEmptyCollection() + { + return ImmutableList.of(); + } + + + + + + + + + + public List get(@Nullable K key) + { + return (List)super.get(key); + } + + + + + + + + public List removeAll(@Nullable Object key) + { + return (List)super.removeAll(key); + } + + + + + + + + + public List replaceValues(@Nullable K key, Iterable values) + { + return (List)super.replaceValues(key, values); + } + + + + + + + + public boolean put(@Nullable K key, @Nullable V value) + { + return super.put(key, value); + } + + + + + + + public Map> asMap() + { + return super.asMap(); + } + + + + + + + + public boolean equals(@Nullable Object object) + { + return super.equals(object); + } +} diff --git a/src/minecraft/com/google/common/collect/AbstractMapBasedMultimap.java b/src/minecraft/com/google/common/collect/AbstractMapBasedMultimap.java new file mode 100644 index 0000000..ec747fa --- /dev/null +++ b/src/minecraft/com/google/common/collect/AbstractMapBasedMultimap.java @@ -0,0 +1 @@ +null \ No newline at end of file diff --git a/src/minecraft/com/google/common/collect/AbstractMapBasedMultiset.java b/src/minecraft/com/google/common/collect/AbstractMapBasedMultiset.java new file mode 100644 index 0000000..5e58057 --- /dev/null +++ b/src/minecraft/com/google/common/collect/AbstractMapBasedMultiset.java @@ -0,0 +1,298 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import com.google.common.primitives.Ints; +import java.io.InvalidObjectException; +import java.io.ObjectStreamException; +import java.io.Serializable; +import java.util.ConcurrentModificationException; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +abstract class AbstractMapBasedMultiset + extends AbstractMultiset + implements Serializable +{ + private transient Map backingMap; + private transient long size; + @GwtIncompatible("not needed in emulated source.") + private static final long serialVersionUID = -2250766705698539974L; + + protected AbstractMapBasedMultiset(Map backingMap) + { + this.backingMap = ((Map)Preconditions.checkNotNull(backingMap)); + size = super.size(); + } + + void setBackingMap(Map backingMap) + { + this.backingMap = backingMap; + } + + + + + + + + + + + public Set> entrySet() + { + return super.entrySet(); + } + + Iterator> entryIterator() + { + final Iterator> backingEntries = backingMap.entrySet().iterator(); + + new Iterator() + { + Map.Entry toRemove; + + public boolean hasNext() { + return backingEntries.hasNext(); + } + + public Multiset.Entry next() + { + final Map.Entry mapEntry = (Map.Entry)backingEntries.next(); + toRemove = mapEntry; + new Multisets.AbstractEntry() + { + public E getElement() { + return mapEntry.getKey(); + } + + public int getCount() { + Count count = (Count)mapEntry.getValue(); + if ((count == null) || (count.get() == 0)) { + Count frequency = (Count)backingMap.get(getElement()); + if (frequency != null) { + return frequency.get(); + } + } + return count == null ? 0 : count.get(); + } + }; + } + + public void remove() + { + CollectPreconditions.checkRemove(toRemove != null); + AbstractMapBasedMultiset.access$122(AbstractMapBasedMultiset.this, ((Count)toRemove.getValue()).getAndSet(0)); + backingEntries.remove(); + toRemove = null; + } + }; + } + + public void clear() + { + for (Count frequency : backingMap.values()) { + frequency.set(0); + } + backingMap.clear(); + size = 0L; + } + + int distinctElements() + { + return backingMap.size(); + } + + + public int size() + { + return Ints.saturatedCast(size); + } + + public Iterator iterator() { + return new MapBasedMultisetIterator(); + } + + + private class MapBasedMultisetIterator + implements Iterator + { + final Iterator> entryIterator; + + Map.Entry currentEntry; + int occurrencesLeft; + boolean canRemove; + + MapBasedMultisetIterator() + { + entryIterator = backingMap.entrySet().iterator(); + } + + public boolean hasNext() + { + return (occurrencesLeft > 0) || (entryIterator.hasNext()); + } + + public E next() + { + if (occurrencesLeft == 0) { + currentEntry = ((Map.Entry)entryIterator.next()); + occurrencesLeft = ((Count)currentEntry.getValue()).get(); + } + occurrencesLeft -= 1; + canRemove = true; + return currentEntry.getKey(); + } + + public void remove() + { + CollectPreconditions.checkRemove(canRemove); + int frequency = ((Count)currentEntry.getValue()).get(); + if (frequency <= 0) { + throw new ConcurrentModificationException(); + } + if (((Count)currentEntry.getValue()).addAndGet(-1) == 0) { + entryIterator.remove(); + } + AbstractMapBasedMultiset.access$110(AbstractMapBasedMultiset.this); + canRemove = false; + } + } + + public int count(@Nullable Object element) { + Count frequency = (Count)Maps.safeGet(backingMap, element); + return frequency == null ? 0 : frequency.get(); + } + + + + + + + + + + public int add(@Nullable E element, int occurrences) + { + if (occurrences == 0) { + return count(element); + } + Preconditions.checkArgument(occurrences > 0, "occurrences cannot be negative: %s", new Object[] { Integer.valueOf(occurrences) }); + + Count frequency = (Count)backingMap.get(element); + int oldCount; + if (frequency == null) { + int oldCount = 0; + backingMap.put(element, new Count(occurrences)); + } else { + oldCount = frequency.get(); + long newCount = oldCount + occurrences; + Preconditions.checkArgument(newCount <= 2147483647L, "too many occurrences: %s", new Object[] { Long.valueOf(newCount) }); + + frequency.getAndAdd(occurrences); + } + size += occurrences; + return oldCount; + } + + public int remove(@Nullable Object element, int occurrences) { + if (occurrences == 0) { + return count(element); + } + Preconditions.checkArgument(occurrences > 0, "occurrences cannot be negative: %s", new Object[] { Integer.valueOf(occurrences) }); + + Count frequency = (Count)backingMap.get(element); + if (frequency == null) { + return 0; + } + + int oldCount = frequency.get(); + int numberRemoved; + int numberRemoved; + if (oldCount > occurrences) { + numberRemoved = occurrences; + } else { + numberRemoved = oldCount; + backingMap.remove(element); + } + + frequency.addAndGet(-numberRemoved); + size -= numberRemoved; + return oldCount; + } + + public int setCount(@Nullable E element, int count) + { + CollectPreconditions.checkNonnegative(count, "count"); + + int oldCount; + int oldCount; + if (count == 0) { + Count existingCounter = (Count)backingMap.remove(element); + oldCount = getAndSet(existingCounter, count); + } else { + Count existingCounter = (Count)backingMap.get(element); + oldCount = getAndSet(existingCounter, count); + + if (existingCounter == null) { + backingMap.put(element, new Count(count)); + } + } + + size += count - oldCount; + return oldCount; + } + + private static int getAndSet(Count i, int count) { + if (i == null) { + return 0; + } + + return i.getAndSet(count); + } + + @GwtIncompatible("java.io.ObjectStreamException") + private void readObjectNoData() + throws ObjectStreamException + { + throw new InvalidObjectException("Stream data required"); + } +} diff --git a/src/minecraft/com/google/common/collect/AbstractMapEntry.java b/src/minecraft/com/google/common/collect/AbstractMapEntry.java new file mode 100644 index 0000000..409560e --- /dev/null +++ b/src/minecraft/com/google/common/collect/AbstractMapEntry.java @@ -0,0 +1,67 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Objects; +import java.util.Map.Entry; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +abstract class AbstractMapEntry + implements Map.Entry +{ + AbstractMapEntry() {} + + public abstract K getKey(); + + public abstract V getValue(); + + public V setValue(V value) + { + throw new UnsupportedOperationException(); + } + + public boolean equals(@Nullable Object object) { + if ((object instanceof Map.Entry)) { + Map.Entry that = (Map.Entry)object; + return (Objects.equal(getKey(), that.getKey())) && (Objects.equal(getValue(), that.getValue())); + } + + return false; + } + + public int hashCode() { + K k = getKey(); + V v = getValue(); + return (k == null ? 0 : k.hashCode()) ^ (v == null ? 0 : v.hashCode()); + } + + + + public String toString() + { + return getKey() + "=" + getValue(); + } +} diff --git a/src/minecraft/com/google/common/collect/AbstractMultimap.java b/src/minecraft/com/google/common/collect/AbstractMultimap.java new file mode 100644 index 0000000..f9cb824 --- /dev/null +++ b/src/minecraft/com/google/common/collect/AbstractMultimap.java @@ -0,0 +1,241 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.AbstractCollection; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + +@GwtCompatible +abstract class AbstractMultimap + implements Multimap +{ + private transient Collection> entries; + private transient Set keySet; + private transient Multiset keys; + private transient Collection values; + private transient Map> asMap; + + AbstractMultimap() {} + + public boolean isEmpty() + { + return size() == 0; + } + + public boolean containsValue(@Nullable Object value) + { + for (Collection collection : asMap().values()) { + if (collection.contains(value)) { + return true; + } + } + + return false; + } + + public boolean containsEntry(@Nullable Object key, @Nullable Object value) + { + Collection collection = (Collection)asMap().get(key); + return (collection != null) && (collection.contains(value)); + } + + public boolean remove(@Nullable Object key, @Nullable Object value) + { + Collection collection = (Collection)asMap().get(key); + return (collection != null) && (collection.remove(value)); + } + + public boolean put(@Nullable K key, @Nullable V value) + { + return get(key).add(value); + } + + public boolean putAll(@Nullable K key, Iterable values) + { + Preconditions.checkNotNull(values); + + + if ((values instanceof Collection)) { + Collection valueCollection = (Collection)values; + return (!valueCollection.isEmpty()) && (get(key).addAll(valueCollection)); + } + Iterator valueItr = values.iterator(); + return (valueItr.hasNext()) && (Iterators.addAll(get(key), valueItr)); + } + + + public boolean putAll(Multimap multimap) + { + boolean changed = false; + for (Map.Entry entry : multimap.entries()) { + changed |= put(entry.getKey(), entry.getValue()); + } + return changed; + } + + public Collection replaceValues(@Nullable K key, Iterable values) + { + Preconditions.checkNotNull(values); + Collection result = removeAll(key); + putAll(key, values); + return result; + } + + + + public Collection> entries() + { + Collection> result = entries; + return result == null ? (this.entries = createEntries()) : result; + } + + Collection> createEntries() { + if ((this instanceof SetMultimap)) { + return new EntrySet(null); + } + return new Entries(null); + } + + abstract Iterator> entryIterator(); + + private class Entries extends Multimaps.Entries { private Entries() {} + + Multimap multimap() { return AbstractMultimap.this; } + + + + + public Iterator> iterator() { return entryIterator(); } + } + + private class EntrySet extends AbstractMultimap.Entries implements Set> { + private EntrySet() { super(null); } + + public int hashCode() { + return Sets.hashCodeImpl(this); + } + + public boolean equals(@Nullable Object obj) + { + return Sets.equalsImpl(this, obj); + } + } + + + + + + public Set keySet() + { + Set result = keySet; + return result == null ? (this.keySet = createKeySet()) : result; + } + + Set createKeySet() { + return new Maps.KeySet(asMap()); + } + + + + public Multiset keys() + { + Multiset result = keys; + return result == null ? (this.keys = createKeys()) : result; + } + + Multiset createKeys() { + return new Multimaps.Keys(this); + } + + + + public Collection values() + { + Collection result = values; + return result == null ? (this.values = createValues()) : result; + } + + + Collection createValues() { return new Values(); } + + class Values extends AbstractCollection { + Values() {} + + public Iterator iterator() { return valueIterator(); } + + public int size() + { + return AbstractMultimap.this.size(); + } + + public boolean contains(@Nullable Object o) { + return containsValue(o); + } + + public void clear() { + AbstractMultimap.this.clear(); + } + } + + Iterator valueIterator() { + return Maps.valueIterator(entries().iterator()); + } + + + + public Map> asMap() + { + Map> result = asMap; + return result == null ? (this.asMap = createAsMap()) : result; + } + + + abstract Map> createAsMap(); + + public boolean equals(@Nullable Object object) + { + return Multimaps.equalsImpl(this, object); + } + + + + + + + + + public int hashCode() + { + return asMap().hashCode(); + } + + + + + + + + public String toString() + { + return asMap().toString(); + } +} diff --git a/src/minecraft/com/google/common/collect/AbstractMultiset.java b/src/minecraft/com/google/common/collect/AbstractMultiset.java new file mode 100644 index 0000000..519f6c4 --- /dev/null +++ b/src/minecraft/com/google/common/collect/AbstractMultiset.java @@ -0,0 +1,221 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Objects; +import java.util.AbstractCollection; +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +abstract class AbstractMultiset + extends AbstractCollection + implements Multiset +{ + private transient Set elementSet; + private transient Set> entrySet; + + AbstractMultiset() {} + + public int size() + { + return Multisets.sizeImpl(this); + } + + public boolean isEmpty() { + return entrySet().isEmpty(); + } + + public boolean contains(@Nullable Object element) { + return count(element) > 0; + } + + public Iterator iterator() { + return Multisets.iteratorImpl(this); + } + + public int count(@Nullable Object element) + { + for (Multiset.Entry entry : entrySet()) { + if (Objects.equal(entry.getElement(), element)) { + return entry.getCount(); + } + } + return 0; + } + + + public boolean add(@Nullable E element) + { + add(element, 1); + return true; + } + + public int add(@Nullable E element, int occurrences) + { + throw new UnsupportedOperationException(); + } + + public boolean remove(@Nullable Object element) { + return remove(element, 1) > 0; + } + + public int remove(@Nullable Object element, int occurrences) + { + throw new UnsupportedOperationException(); + } + + public int setCount(@Nullable E element, int count) + { + return Multisets.setCountImpl(this, element, count); + } + + public boolean setCount(@Nullable E element, int oldCount, int newCount) + { + return Multisets.setCountImpl(this, element, oldCount, newCount); + } + + + + + + + + + public boolean addAll(Collection elementsToAdd) + { + return Multisets.addAllImpl(this, elementsToAdd); + } + + public boolean removeAll(Collection elementsToRemove) { + return Multisets.removeAllImpl(this, elementsToRemove); + } + + public boolean retainAll(Collection elementsToRetain) { + return Multisets.retainAllImpl(this, elementsToRetain); + } + + public void clear() { + Iterators.clear(entryIterator()); + } + + + + + + public Set elementSet() + { + Set result = elementSet; + if (result == null) { + elementSet = (result = createElementSet()); + } + return result; + } + + + + + + + Set createElementSet() { return new ElementSet(); } + + abstract Iterator> entryIterator(); + + class ElementSet extends Multisets.ElementSet { ElementSet() {} + + Multiset multiset() { return AbstractMultiset.this; } + } + + + + abstract int distinctElements(); + + + + public Set> entrySet() + { + Set> result = entrySet; + return result == null ? (this.entrySet = createEntrySet()) : result; + } + + class EntrySet extends Multisets.EntrySet { EntrySet() {} + + Multiset multiset() { return AbstractMultiset.this; } + + public Iterator> iterator() + { + return entryIterator(); + } + + public int size() { + return distinctElements(); + } + } + + Set> createEntrySet() { + return new EntrySet(); + } + + + + + + + + + + public boolean equals(@Nullable Object object) + { + return Multisets.equalsImpl(this, object); + } + + + + + + + public int hashCode() + { + return entrySet().hashCode(); + } + + + + + + + public String toString() + { + return entrySet().toString(); + } +} diff --git a/src/minecraft/com/google/common/collect/AbstractNavigableMap.java b/src/minecraft/com/google/common/collect/AbstractNavigableMap.java new file mode 100644 index 0000000..3aaa835 --- /dev/null +++ b/src/minecraft/com/google/common/collect/AbstractNavigableMap.java @@ -0,0 +1,197 @@ +package com.google.common.collect; + +import java.util.AbstractMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NavigableMap; +import java.util.NavigableSet; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.SortedMap; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + +abstract class AbstractNavigableMap + extends AbstractMap + implements NavigableMap +{ + AbstractNavigableMap() {} + + @Nullable + public abstract V get(@Nullable Object paramObject); + + @Nullable + public Map.Entry firstEntry() + { + return (Map.Entry)Iterators.getNext(entryIterator(), null); + } + + @Nullable + public Map.Entry lastEntry() + { + return (Map.Entry)Iterators.getNext(descendingEntryIterator(), null); + } + + @Nullable + public Map.Entry pollFirstEntry() + { + return (Map.Entry)Iterators.pollNext(entryIterator()); + } + + @Nullable + public Map.Entry pollLastEntry() + { + return (Map.Entry)Iterators.pollNext(descendingEntryIterator()); + } + + public K firstKey() + { + Map.Entry entry = firstEntry(); + if (entry == null) { + throw new NoSuchElementException(); + } + return entry.getKey(); + } + + + public K lastKey() + { + Map.Entry entry = lastEntry(); + if (entry == null) { + throw new NoSuchElementException(); + } + return entry.getKey(); + } + + + @Nullable + public Map.Entry lowerEntry(K key) + { + return headMap(key, false).lastEntry(); + } + + @Nullable + public Map.Entry floorEntry(K key) + { + return headMap(key, true).lastEntry(); + } + + @Nullable + public Map.Entry ceilingEntry(K key) + { + return tailMap(key, true).firstEntry(); + } + + @Nullable + public Map.Entry higherEntry(K key) + { + return tailMap(key, false).firstEntry(); + } + + public K lowerKey(K key) + { + return Maps.keyOrNull(lowerEntry(key)); + } + + public K floorKey(K key) + { + return Maps.keyOrNull(floorEntry(key)); + } + + public K ceilingKey(K key) + { + return Maps.keyOrNull(ceilingEntry(key)); + } + + public K higherKey(K key) + { + return Maps.keyOrNull(higherEntry(key)); + } + + abstract Iterator> entryIterator(); + + abstract Iterator> descendingEntryIterator(); + + public SortedMap subMap(K fromKey, K toKey) + { + return subMap(fromKey, true, toKey, false); + } + + public SortedMap headMap(K toKey) + { + return headMap(toKey, false); + } + + public SortedMap tailMap(K fromKey) + { + return tailMap(fromKey, true); + } + + public NavigableSet navigableKeySet() + { + return new Maps.NavigableKeySet(this); + } + + public Set keySet() + { + return navigableKeySet(); + } + + + public abstract int size(); + + public Set> entrySet() + { + new Maps.EntrySet() + { + Map map() { + return AbstractNavigableMap.this; + } + + public Iterator> iterator() + { + return entryIterator(); + } + }; + } + + public NavigableSet descendingKeySet() + { + return descendingMap().navigableKeySet(); + } + + public NavigableMap descendingMap() + { + return new DescendingMap(null); + } + + private final class DescendingMap extends Maps.DescendingMap { + private DescendingMap() {} + + NavigableMap forward() { return AbstractNavigableMap.this; } + + + Iterator> entryIterator() + { + return descendingEntryIterator(); + } + } +} diff --git a/src/minecraft/com/google/common/collect/AbstractRangeSet.java b/src/minecraft/com/google/common/collect/AbstractRangeSet.java new file mode 100644 index 0000000..76c0fd1 --- /dev/null +++ b/src/minecraft/com/google/common/collect/AbstractRangeSet.java @@ -0,0 +1,102 @@ +package com.google.common.collect; + +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + +abstract class AbstractRangeSet + implements RangeSet +{ + AbstractRangeSet() {} + + public boolean contains(C value) + { + return rangeContaining(value) != null; + } + + + public abstract Range rangeContaining(C paramC); + + public boolean isEmpty() + { + return asRanges().isEmpty(); + } + + public void add(Range range) + { + throw new UnsupportedOperationException(); + } + + public void remove(Range range) + { + throw new UnsupportedOperationException(); + } + + public void clear() + { + remove(Range.all()); + } + + public boolean enclosesAll(RangeSet other) + { + for (Range range : other.asRanges()) { + if (!encloses(range)) { + return false; + } + } + return true; + } + + public void addAll(RangeSet other) + { + for (Range range : other.asRanges()) { + add(range); + } + } + + public void removeAll(RangeSet other) + { + for (Range range : other.asRanges()) { + remove(range); + } + } + + + public abstract boolean encloses(Range paramRange); + + public boolean equals(@Nullable Object obj) + { + if (obj == this) + return true; + if ((obj instanceof RangeSet)) { + RangeSet other = (RangeSet)obj; + return asRanges().equals(other.asRanges()); + } + return false; + } + + public final int hashCode() + { + return asRanges().hashCode(); + } + + public final String toString() + { + return asRanges().toString(); + } +} diff --git a/src/minecraft/com/google/common/collect/AbstractSequentialIterator.java b/src/minecraft/com/google/common/collect/AbstractSequentialIterator.java new file mode 100644 index 0000000..a98baf1 --- /dev/null +++ b/src/minecraft/com/google/common/collect/AbstractSequentialIterator.java @@ -0,0 +1,80 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.NoSuchElementException; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public abstract class AbstractSequentialIterator + extends UnmodifiableIterator +{ + private T nextOrNull; + + protected AbstractSequentialIterator(@Nullable T firstOrNull) + { + nextOrNull = firstOrNull; + } + + + + + protected abstract T computeNext(T paramT); + + + + + public final boolean hasNext() + { + return nextOrNull != null; + } + + public final T next() + { + if (!hasNext()) { + throw new NoSuchElementException(); + } + try { + return nextOrNull; + } finally { + nextOrNull = computeNext(nextOrNull); + } + } +} diff --git a/src/minecraft/com/google/common/collect/AbstractSetMultimap.java b/src/minecraft/com/google/common/collect/AbstractSetMultimap.java new file mode 100644 index 0000000..857fa5c --- /dev/null +++ b/src/minecraft/com/google/common/collect/AbstractSetMultimap.java @@ -0,0 +1,134 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Collection; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +abstract class AbstractSetMultimap + extends AbstractMapBasedMultimap + implements SetMultimap +{ + private static final long serialVersionUID = 7431625294878419160L; + + protected AbstractSetMultimap(Map> map) + { + super(map); + } + + abstract Set createCollection(); + + Set createUnmodifiableEmptyCollection() { + return ImmutableSet.of(); + } + + + + + + + + + + public Set get(@Nullable K key) + { + return (Set)super.get(key); + } + + + + + + + + public Set> entries() + { + return (Set)super.entries(); + } + + + + + + + + public Set removeAll(@Nullable Object key) + { + return (Set)super.removeAll(key); + } + + + + + + + + + + + public Set replaceValues(@Nullable K key, Iterable values) + { + return (Set)super.replaceValues(key, values); + } + + + + + + + public Map> asMap() + { + return super.asMap(); + } + + + + + + + + + public boolean put(@Nullable K key, @Nullable V value) + { + return super.put(key, value); + } + + + + + + + + public boolean equals(@Nullable Object object) + { + return super.equals(object); + } +} diff --git a/src/minecraft/com/google/common/collect/AbstractSortedKeySortedSetMultimap.java b/src/minecraft/com/google/common/collect/AbstractSortedKeySortedSetMultimap.java new file mode 100644 index 0000000..35743aa --- /dev/null +++ b/src/minecraft/com/google/common/collect/AbstractSortedKeySortedSetMultimap.java @@ -0,0 +1,55 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Collection; +import java.util.SortedMap; +import java.util.SortedSet; + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +abstract class AbstractSortedKeySortedSetMultimap + extends AbstractSortedSetMultimap +{ + AbstractSortedKeySortedSetMultimap(SortedMap> map) + { + super(map); + } + + public SortedMap> asMap() + { + return (SortedMap)super.asMap(); + } + + SortedMap> backingMap() + { + return (SortedMap)super.backingMap(); + } + + public SortedSet keySet() + { + return (SortedSet)super.keySet(); + } +} diff --git a/src/minecraft/com/google/common/collect/AbstractSortedMultiset.java b/src/minecraft/com/google/common/collect/AbstractSortedMultiset.java new file mode 100644 index 0000000..f7409b4 --- /dev/null +++ b/src/minecraft/com/google/common/collect/AbstractSortedMultiset.java @@ -0,0 +1,142 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NavigableSet; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +abstract class AbstractSortedMultiset + extends AbstractMultiset + implements SortedMultiset +{ + @GwtTransient + final Comparator comparator; + private transient SortedMultiset descendingMultiset; + + AbstractSortedMultiset() + { + this(Ordering.natural()); + } + + AbstractSortedMultiset(Comparator comparator) { + this.comparator = ((Comparator)Preconditions.checkNotNull(comparator)); + } + + public NavigableSet elementSet() + { + return (NavigableSet)super.elementSet(); + } + + NavigableSet createElementSet() + { + return new SortedMultisets.NavigableElementSet(this); + } + + public Comparator comparator() + { + return comparator; + } + + public Multiset.Entry firstEntry() + { + Iterator> entryIterator = entryIterator(); + return entryIterator.hasNext() ? (Multiset.Entry)entryIterator.next() : null; + } + + public Multiset.Entry lastEntry() + { + Iterator> entryIterator = descendingEntryIterator(); + return entryIterator.hasNext() ? (Multiset.Entry)entryIterator.next() : null; + } + + public Multiset.Entry pollFirstEntry() + { + Iterator> entryIterator = entryIterator(); + if (entryIterator.hasNext()) { + Multiset.Entry result = (Multiset.Entry)entryIterator.next(); + result = Multisets.immutableEntry(result.getElement(), result.getCount()); + entryIterator.remove(); + return result; + } + return null; + } + + public Multiset.Entry pollLastEntry() + { + Iterator> entryIterator = descendingEntryIterator(); + if (entryIterator.hasNext()) { + Multiset.Entry result = (Multiset.Entry)entryIterator.next(); + result = Multisets.immutableEntry(result.getElement(), result.getCount()); + entryIterator.remove(); + return result; + } + return null; + } + + + + public SortedMultiset subMultiset(@Nullable E fromElement, BoundType fromBoundType, @Nullable E toElement, BoundType toBoundType) + { + Preconditions.checkNotNull(fromBoundType); + Preconditions.checkNotNull(toBoundType); + return tailMultiset(fromElement, fromBoundType).headMultiset(toElement, toBoundType); + } + + abstract Iterator> descendingEntryIterator(); + + Iterator descendingIterator() { + return Multisets.iteratorImpl(descendingMultiset()); + } + + + + public SortedMultiset descendingMultiset() + { + SortedMultiset result = descendingMultiset; + return result == null ? (this.descendingMultiset = createDescendingMultiset()) : result; + } + + SortedMultiset createDescendingMultiset() { + new DescendingMultiset() + { + SortedMultiset forwardMultiset() { + return AbstractSortedMultiset.this; + } + + Iterator> entryIterator() + { + return descendingEntryIterator(); + } + + public Iterator iterator() + { + return descendingIterator(); + } + }; + } +} diff --git a/src/minecraft/com/google/common/collect/AbstractSortedSetMultimap.java b/src/minecraft/com/google/common/collect/AbstractSortedSetMultimap.java new file mode 100644 index 0000000..88112b9 --- /dev/null +++ b/src/minecraft/com/google/common/collect/AbstractSortedSetMultimap.java @@ -0,0 +1,135 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Map; +import java.util.SortedSet; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +abstract class AbstractSortedSetMultimap + extends AbstractSetMultimap + implements SortedSetMultimap +{ + private static final long serialVersionUID = 430848587173315748L; + + protected AbstractSortedSetMultimap(Map> map) + { + super(map); + } + + + abstract SortedSet createCollection(); + + SortedSet createUnmodifiableEmptyCollection() + { + Comparator comparator = valueComparator(); + if (comparator == null) { + return Collections.unmodifiableSortedSet(createCollection()); + } + return ImmutableSortedSet.emptySet(valueComparator()); + } + + + + + + + + + + + + + + + + public SortedSet get(@Nullable K key) + { + return (SortedSet)super.get(key); + } + + + + + + + + + public SortedSet removeAll(@Nullable Object key) + { + return (SortedSet)super.removeAll(key); + } + + + + + + + + + + + + public SortedSet replaceValues(@Nullable K key, Iterable values) + { + return (SortedSet)super.replaceValues(key, values); + } + + + + + + + + + + + + + + + public Map> asMap() + { + return super.asMap(); + } + + + + + + + public Collection values() + { + return super.values(); + } +} diff --git a/src/minecraft/com/google/common/collect/AbstractTable.java b/src/minecraft/com/google/common/collect/AbstractTable.java new file mode 100644 index 0000000..2de9dd1 --- /dev/null +++ b/src/minecraft/com/google/common/collect/AbstractTable.java @@ -0,0 +1,216 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.AbstractCollection; +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + +@GwtCompatible +abstract class AbstractTable + implements Table +{ + private transient Set> cellSet; + private transient Collection values; + + AbstractTable() {} + + public boolean containsRow(@Nullable Object rowKey) + { + return Maps.safeContainsKey(rowMap(), rowKey); + } + + public boolean containsColumn(@Nullable Object columnKey) + { + return Maps.safeContainsKey(columnMap(), columnKey); + } + + public Set rowKeySet() + { + return rowMap().keySet(); + } + + public Set columnKeySet() + { + return columnMap().keySet(); + } + + public boolean containsValue(@Nullable Object value) + { + for (Map row : rowMap().values()) { + if (row.containsValue(value)) { + return true; + } + } + return false; + } + + public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) + { + Map row = (Map)Maps.safeGet(rowMap(), rowKey); + return (row != null) && (Maps.safeContainsKey(row, columnKey)); + } + + public V get(@Nullable Object rowKey, @Nullable Object columnKey) + { + Map row = (Map)Maps.safeGet(rowMap(), rowKey); + return row == null ? null : Maps.safeGet(row, columnKey); + } + + public boolean isEmpty() + { + return size() == 0; + } + + public void clear() + { + Iterators.clear(cellSet().iterator()); + } + + public V remove(@Nullable Object rowKey, @Nullable Object columnKey) + { + Map row = (Map)Maps.safeGet(rowMap(), rowKey); + return row == null ? null : Maps.safeRemove(row, columnKey); + } + + public V put(R rowKey, C columnKey, V value) + { + return row(rowKey).put(columnKey, value); + } + + public void putAll(Table table) + { + for (Table.Cell cell : table.cellSet()) { + put(cell.getRowKey(), cell.getColumnKey(), cell.getValue()); + } + } + + + + public Set> cellSet() + { + Set> result = cellSet; + return result == null ? (this.cellSet = createCellSet()) : result; + } + + + Set> createCellSet() { return new CellSet(); } + + abstract Iterator> cellIterator(); + + class CellSet extends AbstractSet> { + CellSet() {} + + public boolean contains(Object o) { + if ((o instanceof Table.Cell)) { + Table.Cell cell = (Table.Cell)o; + Map row = (Map)Maps.safeGet(rowMap(), cell.getRowKey()); + return (row != null) && (Collections2.safeContains(row.entrySet(), Maps.immutableEntry(cell.getColumnKey(), cell.getValue()))); + } + + return false; + } + + public boolean remove(@Nullable Object o) + { + if ((o instanceof Table.Cell)) { + Table.Cell cell = (Table.Cell)o; + Map row = (Map)Maps.safeGet(rowMap(), cell.getRowKey()); + return (row != null) && (Collections2.safeRemove(row.entrySet(), Maps.immutableEntry(cell.getColumnKey(), cell.getValue()))); + } + + return false; + } + + public void clear() + { + AbstractTable.this.clear(); + } + + public Iterator> iterator() + { + return cellIterator(); + } + + public int size() + { + return AbstractTable.this.size(); + } + } + + + + public Collection values() + { + Collection result = values; + return result == null ? (this.values = createValues()) : result; + } + + Collection createValues() { + return new Values(); + } + + Iterator valuesIterator() { + new TransformedIterator(cellSet().iterator()) + { + V transform(Table.Cell cell) { + return cell.getValue(); + } + }; + } + + class Values extends AbstractCollection { + Values() {} + + public Iterator iterator() { return valuesIterator(); } + + + public boolean contains(Object o) + { + return containsValue(o); + } + + public void clear() + { + AbstractTable.this.clear(); + } + + public int size() + { + return AbstractTable.this.size(); + } + } + + public boolean equals(@Nullable Object obj) { + return Tables.equalsImpl(this, obj); + } + + public int hashCode() { + return cellSet().hashCode(); + } + + + + public String toString() + { + return rowMap().toString(); + } +} diff --git a/src/minecraft/com/google/common/collect/AllEqualOrdering.java b/src/minecraft/com/google/common/collect/AllEqualOrdering.java new file mode 100644 index 0000000..c918295 --- /dev/null +++ b/src/minecraft/com/google/common/collect/AllEqualOrdering.java @@ -0,0 +1,64 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.io.Serializable; +import java.util.List; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true) +final class AllEqualOrdering + extends Ordering + implements Serializable +{ + static final AllEqualOrdering INSTANCE = new AllEqualOrdering(); + + AllEqualOrdering() {} + + public int compare(@Nullable Object left, @Nullable Object right) { return 0; } + + private static final long serialVersionUID = 0L; + public List sortedCopy(Iterable iterable) + { + return Lists.newArrayList(iterable); + } + + public ImmutableList immutableSortedCopy(Iterable iterable) + { + return ImmutableList.copyOf(iterable); + } + + + public Ordering reverse() + { + return this; + } + + private Object readResolve() { + return INSTANCE; + } + + public String toString() + { + return "Ordering.allEqual()"; + } +} diff --git a/src/minecraft/com/google/common/collect/ArrayListMultimap.java b/src/minecraft/com/google/common/collect/ArrayListMultimap.java new file mode 100644 index 0000000..ef02829 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ArrayListMultimap.java @@ -0,0 +1,165 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +public final class ArrayListMultimap + extends AbstractListMultimap +{ + private static final int DEFAULT_VALUES_PER_KEY = 3; + @VisibleForTesting + transient int expectedValuesPerKey; + @GwtIncompatible("Not needed in emulated source.") + private static final long serialVersionUID = 0L; + + public static ArrayListMultimap create() + { + return new ArrayListMultimap(); + } + + + + + + + + + + + public static ArrayListMultimap create(int expectedKeys, int expectedValuesPerKey) + { + return new ArrayListMultimap(expectedKeys, expectedValuesPerKey); + } + + + + + + + + public static ArrayListMultimap create(Multimap multimap) + { + return new ArrayListMultimap(multimap); + } + + private ArrayListMultimap() { + super(new HashMap()); + expectedValuesPerKey = 3; + } + + private ArrayListMultimap(int expectedKeys, int expectedValuesPerKey) { + super(Maps.newHashMapWithExpectedSize(expectedKeys)); + CollectPreconditions.checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey"); + this.expectedValuesPerKey = expectedValuesPerKey; + } + + private ArrayListMultimap(Multimap multimap) { + this(multimap.keySet().size(), (multimap instanceof ArrayListMultimap) ? expectedValuesPerKey : 3); + + + + putAll(multimap); + } + + + + + List createCollection() + { + return new ArrayList(expectedValuesPerKey); + } + + + + public void trimToSize() + { + for (Collection collection : backingMap().values()) { + ArrayList arrayList = (ArrayList)collection; + arrayList.trimToSize(); + } + } + + + + + @GwtIncompatible("java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) + throws IOException + { + stream.defaultWriteObject(); + stream.writeInt(expectedValuesPerKey); + Serialization.writeMultimap(this, stream); + } + + @GwtIncompatible("java.io.ObjectOutputStream") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException + { + stream.defaultReadObject(); + expectedValuesPerKey = stream.readInt(); + int distinctKeys = Serialization.readCount(stream); + Map> map = Maps.newHashMapWithExpectedSize(distinctKeys); + setMap(map); + Serialization.populateMultimap(this, stream, distinctKeys); + } +} diff --git a/src/minecraft/com/google/common/collect/ArrayTable.java b/src/minecraft/com/google/common/collect/ArrayTable.java new file mode 100644 index 0000000..c07e8f4 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ArrayTable.java @@ -0,0 +1,771 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.lang.reflect.Array; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible(emulated=true) +public final class ArrayTable + extends AbstractTable + implements Serializable +{ + private final ImmutableList rowList; + private final ImmutableList columnList; + private final ImmutableMap rowKeyToIndex; + private final ImmutableMap columnKeyToIndex; + private final V[][] array; + private transient ArrayTable.ColumnMap columnMap; + private transient ArrayTable.RowMap rowMap; + private static final long serialVersionUID = 0L; + + public static ArrayTable create(Iterable rowKeys, Iterable columnKeys) + { + return new ArrayTable(rowKeys, columnKeys); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static ArrayTable create(Table table) + { + return (table instanceof ArrayTable) ? new ArrayTable((ArrayTable)table) : new ArrayTable(table); + } + + + + + + + + + + + + private ArrayTable(Iterable rowKeys, Iterable columnKeys) + { + rowList = ImmutableList.copyOf(rowKeys); + columnList = ImmutableList.copyOf(columnKeys); + Preconditions.checkArgument(!rowList.isEmpty()); + Preconditions.checkArgument(!columnList.isEmpty()); + + + + + + + rowKeyToIndex = index(rowList); + columnKeyToIndex = index(columnList); + + + V[][] tmpArray = (Object[][])new Object[rowList.size()][columnList.size()]; + + array = tmpArray; + + eraseAll(); + } + + private static ImmutableMap index(List list) { + ImmutableMap.Builder columnBuilder = ImmutableMap.builder(); + for (int i = 0; i < list.size(); i++) { + columnBuilder.put(list.get(i), Integer.valueOf(i)); + } + return columnBuilder.build(); + } + + private ArrayTable(Table table) { + this(table.rowKeySet(), table.columnKeySet()); + putAll(table); + } + + private ArrayTable(ArrayTable table) { + rowList = rowList; + columnList = columnList; + rowKeyToIndex = rowKeyToIndex; + columnKeyToIndex = columnKeyToIndex; + + V[][] copy = (Object[][])new Object[rowList.size()][columnList.size()]; + array = copy; + + eraseAll(); + for (int i = 0; i < rowList.size(); i++) { + System.arraycopy(array[i], 0, copy[i], 0, array[i].length); + } + } + + private static abstract class ArrayMap extends Maps.ImprovedAbstractMap { + private final ImmutableMap keyIndex; + + private ArrayMap(ImmutableMap keyIndex) { + this.keyIndex = keyIndex; + } + + public Set keySet() + { + return keyIndex.keySet(); + } + + K getKey(int index) { + return keyIndex.keySet().asList().get(index); + } + + abstract String getKeyRole(); + + @Nullable + abstract V getValue(int paramInt); + + @Nullable + abstract V setValue(int paramInt, V paramV); + + public int size() { return keyIndex.size(); } + + + public boolean isEmpty() + { + return keyIndex.isEmpty(); + } + + protected Set> createEntrySet() + { + new Maps.EntrySet() + { + Map map() { + return ArrayTable.ArrayMap.this; + } + + public Iterator> iterator() + { + new AbstractIndexedListIterator(size()) + { + protected Map.Entry get(final int index) { + new AbstractMapEntry() + { + public K getKey() { + return getKey(index); + } + + public V getValue() + { + return getValue(index); + } + + public V setValue(V value) + { + return setValue(index, value); + } + }; + } + }; + } + }; + } + + + + public boolean containsKey(@Nullable Object key) + { + return keyIndex.containsKey(key); + } + + public V get(@Nullable Object key) + { + Integer index = (Integer)keyIndex.get(key); + if (index == null) { + return null; + } + return getValue(index.intValue()); + } + + + public V put(K key, V value) + { + Integer index = (Integer)keyIndex.get(key); + if (index == null) { + throw new IllegalArgumentException(getKeyRole() + " " + key + " not in " + keyIndex.keySet()); + } + + return setValue(index.intValue(), value); + } + + public V remove(Object key) + { + throw new UnsupportedOperationException(); + } + + public void clear() + { + throw new UnsupportedOperationException(); + } + } + + + + + public ImmutableList rowKeyList() + { + return rowList; + } + + + + + public ImmutableList columnKeyList() + { + return columnList; + } + + + + + + + + + + + + + + + + public V at(int rowIndex, int columnIndex) + { + Preconditions.checkElementIndex(rowIndex, rowList.size()); + Preconditions.checkElementIndex(columnIndex, columnList.size()); + return array[rowIndex][columnIndex]; + } + + + + + + + + + + + + + + + + + public V set(int rowIndex, int columnIndex, @Nullable V value) + { + Preconditions.checkElementIndex(rowIndex, rowList.size()); + Preconditions.checkElementIndex(columnIndex, columnList.size()); + V oldValue = array[rowIndex][columnIndex]; + array[rowIndex][columnIndex] = value; + return oldValue; + } + + + + + + + + + + + + + @GwtIncompatible("reflection") + public V[][] toArray(Class valueClass) + { + V[][] copy = (Object[][])Array.newInstance(valueClass, new int[] { rowList.size(), columnList.size() }); + + for (int i = 0; i < rowList.size(); i++) { + System.arraycopy(array[i], 0, copy[i], 0, array[i].length); + } + return copy; + } + + + + + + + @Deprecated + public void clear() + { + throw new UnsupportedOperationException(); + } + + + + + public void eraseAll() + { + for (V[] row : array) { + Arrays.fill(row, null); + } + } + + + + + + public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) + { + return (containsRow(rowKey)) && (containsColumn(columnKey)); + } + + + + + + public boolean containsColumn(@Nullable Object columnKey) + { + return columnKeyToIndex.containsKey(columnKey); + } + + + + + + public boolean containsRow(@Nullable Object rowKey) + { + return rowKeyToIndex.containsKey(rowKey); + } + + public boolean containsValue(@Nullable Object value) + { + for (V[] row : array) { + for (V element : row) { + if (Objects.equal(value, element)) { + return true; + } + } + } + return false; + } + + public V get(@Nullable Object rowKey, @Nullable Object columnKey) + { + Integer rowIndex = (Integer)rowKeyToIndex.get(rowKey); + Integer columnIndex = (Integer)columnKeyToIndex.get(columnKey); + return (rowIndex == null) || (columnIndex == null) ? null : at(rowIndex.intValue(), columnIndex.intValue()); + } + + + + + + public boolean isEmpty() + { + return false; + } + + + + + + + + public V put(R rowKey, C columnKey, @Nullable V value) + { + Preconditions.checkNotNull(rowKey); + Preconditions.checkNotNull(columnKey); + Integer rowIndex = (Integer)rowKeyToIndex.get(rowKey); + Preconditions.checkArgument(rowIndex != null, "Row %s not in %s", new Object[] { rowKey, rowList }); + Integer columnIndex = (Integer)columnKeyToIndex.get(columnKey); + Preconditions.checkArgument(columnIndex != null, "Column %s not in %s", new Object[] { columnKey, columnList }); + + return set(rowIndex.intValue(), columnIndex.intValue(), value); + } + + + + + + + + + + + + + + + + + + public void putAll(Table table) + { + super.putAll(table); + } + + + + + + + @Deprecated + public V remove(Object rowKey, Object columnKey) + { + throw new UnsupportedOperationException(); + } + + + + + + + + + + + + + + public V erase(@Nullable Object rowKey, @Nullable Object columnKey) + { + Integer rowIndex = (Integer)rowKeyToIndex.get(rowKey); + Integer columnIndex = (Integer)columnKeyToIndex.get(columnKey); + if ((rowIndex == null) || (columnIndex == null)) { + return null; + } + return set(rowIndex.intValue(), columnIndex.intValue(), null); + } + + + + public int size() + { + return rowList.size() * columnList.size(); + } + + + + + + + + + + + + + + + public Set> cellSet() + { + return super.cellSet(); + } + + Iterator> cellIterator() + { + new AbstractIndexedListIterator(size()) { + protected Table.Cell get(final int index) { + new Tables.AbstractCell() { + final int rowIndex = index / columnList.size(); + final int columnIndex = index % columnList.size(); + + public R getRowKey() { + return rowList.get(rowIndex); + } + + public C getColumnKey() { + return columnList.get(columnIndex); + } + + public V getValue() { + return at(rowIndex, columnIndex); + } + }; + } + }; + } + + + + + + + + + + + + + + public Map column(C columnKey) + { + Preconditions.checkNotNull(columnKey); + Integer columnIndex = (Integer)columnKeyToIndex.get(columnKey); + return columnIndex == null ? ImmutableMap.of() : new Column(columnIndex.intValue()); + } + + private class Column extends ArrayTable.ArrayMap + { + final int columnIndex; + + Column(int columnIndex) { + super(null); + this.columnIndex = columnIndex; + } + + String getKeyRole() + { + return "Row"; + } + + V getValue(int index) + { + return at(index, columnIndex); + } + + V setValue(int index, V newValue) + { + return set(index, columnIndex, newValue); + } + } + + + + + + + + public ImmutableSet columnKeySet() + { + return columnKeyToIndex.keySet(); + } + + + + public Map> columnMap() + { + ArrayTable.ColumnMap map = columnMap; + return map == null ? (this.columnMap = new ColumnMap(null)) : map; + } + + private class ColumnMap extends ArrayTable.ArrayMap> { + private ColumnMap() { + super(null); + } + + String getKeyRole() + { + return "Column"; + } + + Map getValue(int index) + { + return new ArrayTable.Column(ArrayTable.this, index); + } + + Map setValue(int index, Map newValue) + { + throw new UnsupportedOperationException(); + } + + public Map put(C key, Map value) + { + throw new UnsupportedOperationException(); + } + } + + + + + + + + + + + + + + + public Map row(R rowKey) + { + Preconditions.checkNotNull(rowKey); + Integer rowIndex = (Integer)rowKeyToIndex.get(rowKey); + return rowIndex == null ? ImmutableMap.of() : new Row(rowIndex.intValue()); + } + + private class Row extends ArrayTable.ArrayMap { + final int rowIndex; + + Row(int rowIndex) { + super(null); + this.rowIndex = rowIndex; + } + + String getKeyRole() + { + return "Column"; + } + + V getValue(int index) + { + return at(rowIndex, index); + } + + V setValue(int index, V newValue) + { + return set(rowIndex, index, newValue); + } + } + + + + + + + + public ImmutableSet rowKeySet() + { + return rowKeyToIndex.keySet(); + } + + + + public Map> rowMap() + { + ArrayTable.RowMap map = rowMap; + return map == null ? (this.rowMap = new RowMap(null)) : map; + } + + private class RowMap extends ArrayTable.ArrayMap> { + private RowMap() { + super(null); + } + + String getKeyRole() + { + return "Row"; + } + + Map getValue(int index) + { + return new ArrayTable.Row(ArrayTable.this, index); + } + + Map setValue(int index, Map newValue) + { + throw new UnsupportedOperationException(); + } + + public Map put(R key, Map value) + { + throw new UnsupportedOperationException(); + } + } + + + + + + + + + + + public Collection values() + { + return super.values(); + } +} diff --git a/src/minecraft/com/google/common/collect/BiMap.java b/src/minecraft/com/google/common/collect/BiMap.java new file mode 100644 index 0000000..6e48942 --- /dev/null +++ b/src/minecraft/com/google/common/collect/BiMap.java @@ -0,0 +1,21 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract interface BiMap + extends Map +{ + public abstract V put(@Nullable K paramK, @Nullable V paramV); + + public abstract V forcePut(@Nullable K paramK, @Nullable V paramV); + + public abstract void putAll(Map paramMap); + + public abstract Set values(); + + public abstract BiMap inverse(); +} diff --git a/src/minecraft/com/google/common/collect/BinaryTreeTraverser.java b/src/minecraft/com/google/common/collect/BinaryTreeTraverser.java new file mode 100644 index 0000000..fa30d9a --- /dev/null +++ b/src/minecraft/com/google/common/collect/BinaryTreeTraverser.java @@ -0,0 +1,212 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import java.util.ArrayDeque; +import java.util.BitSet; +import java.util.Deque; +import java.util.Iterator; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible(emulated=true) +public abstract class BinaryTreeTraverser + extends TreeTraverser +{ + public BinaryTreeTraverser() {} + + public abstract Optional leftChild(T paramT); + + public abstract Optional rightChild(T paramT); + + public final Iterable children(final T root) + { + Preconditions.checkNotNull(root); + new FluentIterable() + { + public Iterator iterator() { + new AbstractIterator() + { + boolean doneLeft; + boolean doneRight; + + protected T computeNext() { + if (!doneLeft) { + doneLeft = true; + Optional left = leftChild(val$root); + if (left.isPresent()) { + return left.get(); + } + } + if (!doneRight) { + doneRight = true; + Optional right = rightChild(val$root); + if (right.isPresent()) { + return right.get(); + } + } + return endOfData(); + } + }; + } + }; + } + + UnmodifiableIterator preOrderIterator(T root) + { + return new PreOrderIterator(root); + } + + private final class PreOrderIterator + extends UnmodifiableIterator + implements PeekingIterator + { + private final Deque stack; + + PreOrderIterator() + { + stack = new ArrayDeque(); + stack.addLast(root); + } + + public boolean hasNext() + { + return !stack.isEmpty(); + } + + public T next() + { + T result = stack.removeLast(); + BinaryTreeTraverser.pushIfPresent(stack, rightChild(result)); + BinaryTreeTraverser.pushIfPresent(stack, leftChild(result)); + return result; + } + + public T peek() + { + return stack.getLast(); + } + } + + UnmodifiableIterator postOrderIterator(T root) + { + return new PostOrderIterator(root); + } + + private final class PostOrderIterator + extends UnmodifiableIterator + { + private final Deque stack; + private final BitSet hasExpanded; + + PostOrderIterator() + { + stack = new ArrayDeque(); + stack.addLast(root); + hasExpanded = new BitSet(); + } + + public boolean hasNext() + { + return !stack.isEmpty(); + } + + public T next() + { + for (;;) { + T node = stack.getLast(); + boolean expandedNode = hasExpanded.get(stack.size() - 1); + if (expandedNode) { + stack.removeLast(); + hasExpanded.clear(stack.size()); + return node; + } + hasExpanded.set(stack.size() - 1); + BinaryTreeTraverser.pushIfPresent(stack, rightChild(node)); + BinaryTreeTraverser.pushIfPresent(stack, leftChild(node)); + } + } + } + + + + public final FluentIterable inOrderTraversal(final T root) + { + Preconditions.checkNotNull(root); + new FluentIterable() + { + public UnmodifiableIterator iterator() { + return new BinaryTreeTraverser.InOrderIterator(BinaryTreeTraverser.this, root); + } + }; + } + + private final class InOrderIterator extends AbstractIterator { + private final Deque stack; + private final BitSet hasExpandedLeft; + + InOrderIterator() { + stack = new ArrayDeque(); + hasExpandedLeft = new BitSet(); + stack.addLast(root); + } + + protected T computeNext() + { + while (!stack.isEmpty()) { + T node = stack.getLast(); + if (hasExpandedLeft.get(stack.size() - 1)) { + stack.removeLast(); + hasExpandedLeft.clear(stack.size()); + BinaryTreeTraverser.pushIfPresent(stack, rightChild(node)); + return node; + } + hasExpandedLeft.set(stack.size() - 1); + BinaryTreeTraverser.pushIfPresent(stack, leftChild(node)); + } + + return endOfData(); + } + } + + private static void pushIfPresent(Deque stack, Optional node) { + if (node.isPresent()) { + stack.addLast(node.get()); + } + } +} diff --git a/src/minecraft/com/google/common/collect/BoundType.java b/src/minecraft/com/google/common/collect/BoundType.java new file mode 100644 index 0000000..9ff526e --- /dev/null +++ b/src/minecraft/com/google/common/collect/BoundType.java @@ -0,0 +1,55 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public enum BoundType +{ + OPEN, + + + + + + + + + CLOSED; + + + + + private BoundType() {} + + + + static BoundType forBoolean(boolean inclusive) + { + return inclusive ? CLOSED : OPEN; + } + + abstract BoundType flip(); +} diff --git a/src/minecraft/com/google/common/collect/ByFunctionOrdering.java b/src/minecraft/com/google/common/collect/ByFunctionOrdering.java new file mode 100644 index 0000000..48c2dfd --- /dev/null +++ b/src/minecraft/com/google/common/collect/ByFunctionOrdering.java @@ -0,0 +1,68 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true) +final class ByFunctionOrdering + extends Ordering + implements Serializable +{ + final Function function; + final Ordering ordering; + private static final long serialVersionUID = 0L; + + ByFunctionOrdering(Function function, Ordering ordering) + { + this.function = ((Function)Preconditions.checkNotNull(function)); + this.ordering = ((Ordering)Preconditions.checkNotNull(ordering)); + } + + public int compare(F left, F right) { + return ordering.compare(function.apply(left), function.apply(right)); + } + + public boolean equals(@Nullable Object object) { + if (object == this) { + return true; + } + if ((object instanceof ByFunctionOrdering)) { + ByFunctionOrdering that = (ByFunctionOrdering)object; + return (function.equals(function)) && (ordering.equals(ordering)); + } + + return false; + } + + public int hashCode() { + return Objects.hashCode(new Object[] { function, ordering }); + } + + public String toString() { + return ordering + ".onResultOf(" + function + ")"; + } +} diff --git a/src/minecraft/com/google/common/collect/CartesianList.java b/src/minecraft/com/google/common/collect/CartesianList.java new file mode 100644 index 0000000..12ee3f8 --- /dev/null +++ b/src/minecraft/com/google/common/collect/CartesianList.java @@ -0,0 +1,120 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.math.IntMath; +import java.util.AbstractList; +import java.util.List; +import java.util.ListIterator; +import java.util.RandomAccess; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +final class CartesianList + extends AbstractList> + implements RandomAccess +{ + private final transient ImmutableList> axes; + private final transient int[] axesSizeProduct; + + static List> create(List> lists) + { + ImmutableList.Builder> axesBuilder = new ImmutableList.Builder(lists.size()); + + for (List list : lists) { + List copy = ImmutableList.copyOf(list); + if (copy.isEmpty()) { + return ImmutableList.of(); + } + axesBuilder.add(copy); + } + return new CartesianList(axesBuilder.build()); + } + + CartesianList(ImmutableList> axes) { + this.axes = axes; + int[] axesSizeProduct = new int[axes.size() + 1]; + axesSizeProduct[axes.size()] = 1; + try { + for (int i = axes.size() - 1; i >= 0; i--) { + axesSizeProduct[i] = IntMath.checkedMultiply(axesSizeProduct[(i + 1)], ((List)axes.get(i)).size()); + } + } + catch (ArithmeticException e) { + throw new IllegalArgumentException("Cartesian product too large; must have size at most Integer.MAX_VALUE"); + } + + this.axesSizeProduct = axesSizeProduct; + } + + private int getAxisIndexForProductIndex(int index, int axis) { + return index / axesSizeProduct[(axis + 1)] % ((List)axes.get(axis)).size(); + } + + public ImmutableList get(final int index) + { + Preconditions.checkElementIndex(index, size()); + new ImmutableList() + { + public int size() + { + return axes.size(); + } + + public E get(int axis) + { + Preconditions.checkElementIndex(axis, size()); + int axisIndex = CartesianList.this.getAxisIndexForProductIndex(index, axis); + return ((List)axes.get(axis)).get(axisIndex); + } + + boolean isPartialView() + { + return true; + } + }; + } + + public int size() + { + return axesSizeProduct[0]; + } + + public boolean contains(@Nullable Object o) + { + if (!(o instanceof List)) { + return false; + } + List list = (List)o; + if (list.size() != axes.size()) { + return false; + } + ListIterator itr = list.listIterator(); + while (itr.hasNext()) { + int index = itr.nextIndex(); + if (!((List)axes.get(index)).contains(itr.next())) { + return false; + } + } + return true; + } +} diff --git a/src/minecraft/com/google/common/collect/ClassToInstanceMap.java b/src/minecraft/com/google/common/collect/ClassToInstanceMap.java new file mode 100644 index 0000000..e2b11e7 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ClassToInstanceMap.java @@ -0,0 +1,14 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract interface ClassToInstanceMap + extends Map, B> +{ + public abstract T getInstance(Class paramClass); + + public abstract T putInstance(Class paramClass, @Nullable T paramT); +} diff --git a/src/minecraft/com/google/common/collect/CollectPreconditions.java b/src/minecraft/com/google/common/collect/CollectPreconditions.java new file mode 100644 index 0000000..204d444 --- /dev/null +++ b/src/minecraft/com/google/common/collect/CollectPreconditions.java @@ -0,0 +1,51 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; + + + + + + + + + + + + + + + + + + +@GwtCompatible +final class CollectPreconditions +{ + CollectPreconditions() {} + + static void checkEntryNotNull(Object key, Object value) + { + if (key == null) + throw new NullPointerException("null key in entry: null=" + value); + if (value == null) { + throw new NullPointerException("null value in entry: " + key + "=null"); + } + } + + static int checkNonnegative(int value, String name) { + if (value < 0) { + throw new IllegalArgumentException(name + " cannot be negative but was: " + value); + } + return value; + } + + + + + static void checkRemove(boolean canRemove) + { + Preconditions.checkState(canRemove, "no calls to next() since the last call to remove()"); + } +} diff --git a/src/minecraft/com/google/common/collect/Collections2.java b/src/minecraft/com/google/common/collect/Collections2.java new file mode 100644 index 0000000..4e1f752 --- /dev/null +++ b/src/minecraft/com/google/common/collect/Collections2.java @@ -0,0 +1,674 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.math.IntMath; +import com.google.common.math.LongMath; +import java.util.AbstractCollection; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public final class Collections2 +{ + private Collections2() {} + + public static Collection filter(Collection unfiltered, Predicate predicate) + { + if ((unfiltered instanceof FilteredCollection)) + { + + return ((FilteredCollection)unfiltered).createCombined(predicate); + } + + return new FilteredCollection((Collection)Preconditions.checkNotNull(unfiltered), (Predicate)Preconditions.checkNotNull(predicate)); + } + + + + + + + + static boolean safeContains(Collection collection, @Nullable Object object) + { + Preconditions.checkNotNull(collection); + try { + return collection.contains(object); + } catch (ClassCastException e) { + return false; + } catch (NullPointerException e) {} + return false; + } + + + + + + + static boolean safeRemove(Collection collection, @Nullable Object object) + { + Preconditions.checkNotNull(collection); + try { + return collection.remove(object); + } catch (ClassCastException e) { + return false; + } catch (NullPointerException e) {} + return false; + } + + static class FilteredCollection extends AbstractCollection + { + final Collection unfiltered; + final Predicate predicate; + + FilteredCollection(Collection unfiltered, Predicate predicate) + { + this.unfiltered = unfiltered; + this.predicate = predicate; + } + + FilteredCollection createCombined(Predicate newPredicate) { + return new FilteredCollection(unfiltered, Predicates.and(predicate, newPredicate)); + } + + + + public boolean add(E element) + { + Preconditions.checkArgument(predicate.apply(element)); + return unfiltered.add(element); + } + + public boolean addAll(Collection collection) + { + for (E element : collection) { + Preconditions.checkArgument(predicate.apply(element)); + } + return unfiltered.addAll(collection); + } + + public void clear() + { + Iterables.removeIf(unfiltered, predicate); + } + + public boolean contains(@Nullable Object element) + { + if (Collections2.safeContains(unfiltered, element)) + { + E e = element; + return predicate.apply(e); + } + return false; + } + + public boolean containsAll(Collection collection) + { + return Collections2.containsAllImpl(this, collection); + } + + public boolean isEmpty() + { + return !Iterables.any(unfiltered, predicate); + } + + public Iterator iterator() + { + return Iterators.filter(unfiltered.iterator(), predicate); + } + + public boolean remove(Object element) + { + return (contains(element)) && (unfiltered.remove(element)); + } + + public boolean removeAll(Collection collection) + { + return Iterables.removeIf(unfiltered, Predicates.and(predicate, Predicates.in(collection))); + } + + public boolean retainAll(Collection collection) + { + return Iterables.removeIf(unfiltered, Predicates.and(predicate, Predicates.not(Predicates.in(collection)))); + } + + public int size() + { + return Iterators.size(iterator()); + } + + + public Object[] toArray() + { + return Lists.newArrayList(iterator()).toArray(); + } + + public T[] toArray(T[] array) + { + return Lists.newArrayList(iterator()).toArray(array); + } + } + + + + + + + + + + + + + + + + + + + + + public static Collection transform(Collection fromCollection, Function function) + { + return new TransformedCollection(fromCollection, function); + } + + static class TransformedCollection extends AbstractCollection + { + final Collection fromCollection; + final Function function; + + TransformedCollection(Collection fromCollection, Function function) { + this.fromCollection = ((Collection)Preconditions.checkNotNull(fromCollection)); + this.function = ((Function)Preconditions.checkNotNull(function)); + } + + public void clear() { + fromCollection.clear(); + } + + public boolean isEmpty() { + return fromCollection.isEmpty(); + } + + public Iterator iterator() { + return Iterators.transform(fromCollection.iterator(), function); + } + + public int size() { + return fromCollection.size(); + } + } + + + + + + + + + + + + + static boolean containsAllImpl(Collection self, Collection c) + { + return Iterables.all(c, Predicates.in(self)); + } + + + + static String toStringImpl(Collection collection) + { + StringBuilder sb = newStringBuilderForCollection(collection.size()).append('['); + + STANDARD_JOINER.appendTo(sb, Iterables.transform(collection, new Function() + { + public Object apply(Object input) { + return input == val$collection ? "(this Collection)" : input; + } + })); + return ']'; + } + + + + static StringBuilder newStringBuilderForCollection(int size) + { + CollectPreconditions.checkNonnegative(size, "size"); + return new StringBuilder((int)Math.min(size * 8L, 1073741824L)); + } + + + + static Collection cast(Iterable iterable) + { + return (Collection)iterable; + } + + static final Joiner STANDARD_JOINER = Joiner.on(", ").useForNull("null"); + + + + + + + + + + + + + + + + + + + + + + + + + + + + @Beta + public static > Collection> orderedPermutations(Iterable elements) + { + return orderedPermutations(elements, Ordering.natural()); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @Beta + public static Collection> orderedPermutations(Iterable elements, Comparator comparator) + { + return new OrderedPermutationCollection(elements, comparator); + } + + private static final class OrderedPermutationCollection extends AbstractCollection> + { + final ImmutableList inputList; + final Comparator comparator; + final int size; + + OrderedPermutationCollection(Iterable input, Comparator comparator) + { + inputList = Ordering.from(comparator).immutableSortedCopy(input); + this.comparator = comparator; + size = calculateSize(inputList, comparator); + } + + + + + + + + + + + private static int calculateSize(List sortedInputList, Comparator comparator) + { + long permutations = 1L; + int n = 1; + int r = 1; + while (n < sortedInputList.size()) { + int comparison = comparator.compare(sortedInputList.get(n - 1), sortedInputList.get(n)); + + if (comparison < 0) + { + permutations *= LongMath.binomial(n, r); + r = 0; + if (!Collections2.isPositiveInt(permutations)) { + return Integer.MAX_VALUE; + } + } + n++; + r++; + } + permutations *= LongMath.binomial(n, r); + if (!Collections2.isPositiveInt(permutations)) { + return Integer.MAX_VALUE; + } + return (int)permutations; + } + + public int size() { + return size; + } + + public boolean isEmpty() { + return false; + } + + public Iterator> iterator() { + return new Collections2.OrderedPermutationIterator(inputList, comparator); + } + + public boolean contains(@Nullable Object obj) { + if ((obj instanceof List)) { + List list = (List)obj; + return Collections2.isPermutation(inputList, list); + } + return false; + } + + public String toString() { + return "orderedPermutationCollection(" + inputList + ")"; + } + } + + private static final class OrderedPermutationIterator + extends AbstractIterator> + { + List nextPermutation; + final Comparator comparator; + + OrderedPermutationIterator(List list, Comparator comparator) + { + nextPermutation = Lists.newArrayList(list); + this.comparator = comparator; + } + + protected List computeNext() { + if (nextPermutation == null) { + return (List)endOfData(); + } + ImmutableList next = ImmutableList.copyOf(nextPermutation); + calculateNextPermutation(); + return next; + } + + void calculateNextPermutation() { + int j = findNextJ(); + if (j == -1) { + nextPermutation = null; + return; + } + + int l = findNextL(j); + Collections.swap(nextPermutation, j, l); + int n = nextPermutation.size(); + Collections.reverse(nextPermutation.subList(j + 1, n)); + } + + int findNextJ() { + for (int k = nextPermutation.size() - 2; k >= 0; k--) { + if (comparator.compare(nextPermutation.get(k), nextPermutation.get(k + 1)) < 0) + { + return k; + } + } + return -1; + } + + int findNextL(int j) { + E ak = nextPermutation.get(j); + for (int l = nextPermutation.size() - 1; l > j; l--) { + if (comparator.compare(ak, nextPermutation.get(l)) < 0) { + return l; + } + } + throw new AssertionError("this statement should be unreachable"); + } + } + + + + + + + + + + + + + + + + + + + + + @Beta + public static Collection> permutations(Collection elements) + { + return new PermutationCollection(ImmutableList.copyOf(elements)); + } + + private static final class PermutationCollection extends AbstractCollection> + { + final ImmutableList inputList; + + PermutationCollection(ImmutableList input) { + inputList = input; + } + + public int size() { + return IntMath.factorial(inputList.size()); + } + + public boolean isEmpty() { + return false; + } + + public Iterator> iterator() { + return new Collections2.PermutationIterator(inputList); + } + + public boolean contains(@Nullable Object obj) { + if ((obj instanceof List)) { + List list = (List)obj; + return Collections2.isPermutation(inputList, list); + } + return false; + } + + public String toString() { + return "permutations(" + inputList + ")"; + } + } + + private static class PermutationIterator extends AbstractIterator> + { + final List list; + final int[] c; + final int[] o; + int j; + + PermutationIterator(List list) { + this.list = new ArrayList(list); + int n = list.size(); + c = new int[n]; + o = new int[n]; + Arrays.fill(c, 0); + Arrays.fill(o, 1); + j = Integer.MAX_VALUE; + } + + protected List computeNext() { + if (j <= 0) { + return (List)endOfData(); + } + ImmutableList next = ImmutableList.copyOf(list); + calculateNextPermutation(); + return next; + } + + void calculateNextPermutation() { + j = (list.size() - 1); + int s = 0; + + + + if (j == -1) { + return; + } + int q; + for (;;) { + q = c[j] + o[j]; + if (q < 0) { + switchDirection(); + } + else { + if (q != j + 1) break; + if (j == 0) { + return; + } + s++; + switchDirection(); + } + } + + Collections.swap(list, j - c[j] + s, j - q + s); + c[j] = q; + } + + + void switchDirection() + { + o[j] = (-o[j]); + j -= 1; + } + } + + + + + private static boolean isPermutation(List first, List second) + { + if (first.size() != second.size()) { + return false; + } + Multiset firstMultiset = HashMultiset.create(first); + Multiset secondMultiset = HashMultiset.create(second); + return firstMultiset.equals(secondMultiset); + } + + private static boolean isPositiveInt(long n) { + return (n >= 0L) && (n <= 2147483647L); + } +} diff --git a/src/minecraft/com/google/common/collect/ComparatorOrdering.java b/src/minecraft/com/google/common/collect/ComparatorOrdering.java new file mode 100644 index 0000000..3f49c01 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ComparatorOrdering.java @@ -0,0 +1,59 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.Comparator; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true) +final class ComparatorOrdering + extends Ordering + implements Serializable +{ + final Comparator comparator; + private static final long serialVersionUID = 0L; + + ComparatorOrdering(Comparator comparator) + { + this.comparator = ((Comparator)Preconditions.checkNotNull(comparator)); + } + + public int compare(T a, T b) { + return comparator.compare(a, b); + } + + public boolean equals(@Nullable Object object) { + if (object == this) { + return true; + } + if ((object instanceof ComparatorOrdering)) { + ComparatorOrdering that = (ComparatorOrdering)object; + return comparator.equals(comparator); + } + return false; + } + + public int hashCode() { + return comparator.hashCode(); + } + + public String toString() { + return comparator.toString(); + } +} diff --git a/src/minecraft/com/google/common/collect/ComparisonChain.java b/src/minecraft/com/google/common/collect/ComparisonChain.java new file mode 100644 index 0000000..ec747fa --- /dev/null +++ b/src/minecraft/com/google/common/collect/ComparisonChain.java @@ -0,0 +1 @@ +null \ No newline at end of file diff --git a/src/minecraft/com/google/common/collect/CompoundOrdering.java b/src/minecraft/com/google/common/collect/CompoundOrdering.java new file mode 100644 index 0000000..65e891e --- /dev/null +++ b/src/minecraft/com/google/common/collect/CompoundOrdering.java @@ -0,0 +1,69 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.io.Serializable; +import java.util.Comparator; + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true) +final class CompoundOrdering + extends Ordering + implements Serializable +{ + final ImmutableList> comparators; + private static final long serialVersionUID = 0L; + + CompoundOrdering(Comparator primary, Comparator secondary) + { + comparators = ImmutableList.of(primary, secondary); + } + + CompoundOrdering(Iterable> comparators) + { + this.comparators = ImmutableList.copyOf(comparators); + } + + public int compare(T left, T right) + { + int size = comparators.size(); + for (int i = 0; i < size; i++) { + int result = ((Comparator)comparators.get(i)).compare(left, right); + if (result != 0) { + return result; + } + } + return 0; + } + + public boolean equals(Object object) { + if (object == this) { + return true; + } + if ((object instanceof CompoundOrdering)) { + CompoundOrdering that = (CompoundOrdering)object; + return comparators.equals(comparators); + } + return false; + } + + public int hashCode() { + return comparators.hashCode(); + } + + public String toString() { + return "Ordering.compound(" + comparators + ")"; + } +} diff --git a/src/minecraft/com/google/common/collect/ComputationException.java b/src/minecraft/com/google/common/collect/ComputationException.java new file mode 100644 index 0000000..ccd536a --- /dev/null +++ b/src/minecraft/com/google/common/collect/ComputationException.java @@ -0,0 +1,37 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public class ComputationException + extends RuntimeException +{ + private static final long serialVersionUID = 0L; + + public ComputationException(@Nullable Throwable cause) + { + super(cause); + } +} diff --git a/src/minecraft/com/google/common/collect/ComputingConcurrentHashMap.java b/src/minecraft/com/google/common/collect/ComputingConcurrentHashMap.java new file mode 100644 index 0000000..edf50b0 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ComputingConcurrentHashMap.java @@ -0,0 +1,418 @@ +package com.google.common.collect; + +import com.google.common.base.Equivalence; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.lang.ref.ReferenceQueue; +import java.util.Queue; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.atomic.AtomicReferenceArray; +import javax.annotation.Nullable; +import javax.annotation.concurrent.GuardedBy; + + + + + + + + + + + + + + + + + + + + + + + + + + + +class ComputingConcurrentHashMap + extends MapMakerInternalMap +{ + final Function computingFunction; + private static final long serialVersionUID = 4L; + + ComputingConcurrentHashMap(MapMaker builder, Function computingFunction) + { + super(builder); + this.computingFunction = ((Function)Preconditions.checkNotNull(computingFunction)); + } + + MapMakerInternalMap.Segment createSegment(int initialCapacity, int maxSegmentSize) + { + return new ComputingSegment(this, initialCapacity, maxSegmentSize); + } + + ComputingSegment segmentFor(int hash) + { + return (ComputingSegment)super.segmentFor(hash); + } + + V getOrCompute(K key) throws ExecutionException { + int hash = hash(Preconditions.checkNotNull(key)); + return segmentFor(hash).getOrCompute(key, hash, computingFunction); + } + + static final class ComputingSegment + extends MapMakerInternalMap.Segment + { + ComputingSegment(MapMakerInternalMap map, int initialCapacity, int maxSegmentSize) { super(initialCapacity, maxSegmentSize); } + + V getOrCompute(K key, int hash, Function computingFunction) throws ExecutionException { + try { + MapMakerInternalMap.ReferenceEntry e; + Object computingValueReference; + V value; + do { + e = getEntry(key, hash); + if (e != null) { + V value = getLiveValue(e); + if (value != null) { + recordRead(e); + return value; + } + } + + + + if ((e == null) || (!e.getValueReference().isComputingReference())) { + boolean createNewEntry = true; + computingValueReference = null; + lock(); + int newCount; + try { preWriteCleanup(); + + newCount = count - 1; + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + MapMakerInternalMap.ReferenceEntry first = (MapMakerInternalMap.ReferenceEntry)table.get(index); + + for (e = first; e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if ((e.getHash() == hash) && (entryKey != null) && (map.keyEquivalence.equivalent(key, entryKey))) + { + MapMakerInternalMap.ValueReference valueReference = e.getValueReference(); + if (valueReference.isComputingReference()) { + createNewEntry = false; break; + } + V value = e.getValueReference().get(); + if (value == null) { + enqueueNotification(entryKey, hash, value, MapMaker.RemovalCause.COLLECTED); + } else if ((map.expires()) && (map.isExpired(e))) + { + + enqueueNotification(entryKey, hash, value, MapMaker.RemovalCause.EXPIRED); + } else { + recordLockedRead(e); + return value; + } + + + evictionQueue.remove(e); + expirationQueue.remove(e); + count = newCount; + + break; + } + } + + if (createNewEntry) { + computingValueReference = new ComputingConcurrentHashMap.ComputingValueReference(computingFunction); + + if (e == null) { + e = newEntry(key, hash, first); + e.setValueReference((MapMakerInternalMap.ValueReference)computingValueReference); + table.set(index, e); + } else { + e.setValueReference((MapMakerInternalMap.ValueReference)computingValueReference); + } + } + } finally { + unlock(); + } + + + if (createNewEntry) + { + return compute(key, hash, e, (ComputingConcurrentHashMap.ComputingValueReference)computingValueReference); + } + } + + + Preconditions.checkState(!Thread.holdsLock(e), "Recursive computation"); + + value = e.getValueReference().waitForValue(); + } while (value == null); + recordRead(e); + return value; + + } + finally + { + + postReadCleanup(); + } + } + + V compute(K key, int hash, MapMakerInternalMap.ReferenceEntry e, ComputingConcurrentHashMap.ComputingValueReference computingValueReference) + throws ExecutionException + { + V value = null; + long start = System.nanoTime(); + long end = 0L; + + + try + { + synchronized (e) { + value = computingValueReference.compute(key, hash); + end = System.nanoTime(); } + V oldValue; + if (value != null) + { + oldValue = put(key, hash, value, true); + if (oldValue != null) + { + enqueueNotification(key, hash, value, MapMaker.RemovalCause.REPLACED); + } + } + return value; + } finally { + if (end == 0L) { + end = System.nanoTime(); + } + if (value == null) { + clearValue(key, hash, computingValueReference); + } + } + } + } + + private static final class ComputationExceptionReference + implements MapMakerInternalMap.ValueReference + { + final Throwable t; + + ComputationExceptionReference(Throwable t) + { + this.t = t; + } + + public V get() + { + return null; + } + + public MapMakerInternalMap.ReferenceEntry getEntry() + { + return null; + } + + + public MapMakerInternalMap.ValueReference copyFor(ReferenceQueue queue, V value, MapMakerInternalMap.ReferenceEntry entry) + { + return this; + } + + public boolean isComputingReference() + { + return false; + } + + public V waitForValue() throws ExecutionException + { + throw new ExecutionException(t); + } + + + public void clear(MapMakerInternalMap.ValueReference newValue) {} + } + + private static final class ComputedReference + implements MapMakerInternalMap.ValueReference + { + final V value; + + ComputedReference(@Nullable V value) + { + this.value = value; + } + + public V get() + { + return value; + } + + public MapMakerInternalMap.ReferenceEntry getEntry() + { + return null; + } + + + public MapMakerInternalMap.ValueReference copyFor(ReferenceQueue queue, V value, MapMakerInternalMap.ReferenceEntry entry) + { + return this; + } + + public boolean isComputingReference() + { + return false; + } + + public V waitForValue() + { + return get(); + } + + public void clear(MapMakerInternalMap.ValueReference newValue) {} + } + + private static final class ComputingValueReference implements MapMakerInternalMap.ValueReference + { + final Function computingFunction; + @GuardedBy("ComputingValueReference.this") + volatile MapMakerInternalMap.ValueReference computedReference = MapMakerInternalMap.unset(); + + public ComputingValueReference(Function computingFunction) + { + this.computingFunction = computingFunction; + } + + + + public V get() + { + return null; + } + + public MapMakerInternalMap.ReferenceEntry getEntry() + { + return null; + } + + + public MapMakerInternalMap.ValueReference copyFor(ReferenceQueue queue, @Nullable V value, MapMakerInternalMap.ReferenceEntry entry) + { + return this; + } + + public boolean isComputingReference() + { + return true; + } + + + + public V waitForValue() + throws ExecutionException + { + if (computedReference == MapMakerInternalMap.UNSET) { + boolean interrupted = false; + try { + synchronized (this) { + while (computedReference == MapMakerInternalMap.UNSET) { + try { + wait(); + } catch (InterruptedException ie) { + interrupted = true; + } + } + } + } finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + return computedReference.waitForValue(); + } + + + + public void clear(MapMakerInternalMap.ValueReference newValue) + { + setValueReference(newValue); + } + + V compute(K key, int hash) throws ExecutionException + { + V value; + try + { + value = computingFunction.apply(key); + } catch (Throwable t) { + setValueReference(new ComputingConcurrentHashMap.ComputationExceptionReference(t)); + throw new ExecutionException(t); + } + + setValueReference(new ComputingConcurrentHashMap.ComputedReference(value)); + return value; + } + + void setValueReference(MapMakerInternalMap.ValueReference valueReference) { + synchronized (this) { + if (computedReference == MapMakerInternalMap.UNSET) { + computedReference = valueReference; + notifyAll(); + } + } + } + } + + + + + + Object writeReplace() + { + return new ComputingSerializationProxy(keyStrength, valueStrength, keyEquivalence, valueEquivalence, expireAfterWriteNanos, expireAfterAccessNanos, maximumSize, concurrencyLevel, removalListener, this, computingFunction); + } + + + static final class ComputingSerializationProxy + extends MapMakerInternalMap.AbstractSerializationProxy + { + final Function computingFunction; + + private static final long serialVersionUID = 4L; + + + ComputingSerializationProxy(MapMakerInternalMap.Strength keyStrength, MapMakerInternalMap.Strength valueStrength, Equivalence keyEquivalence, Equivalence valueEquivalence, long expireAfterWriteNanos, long expireAfterAccessNanos, int maximumSize, int concurrencyLevel, MapMaker.RemovalListener removalListener, ConcurrentMap delegate, Function computingFunction) + { + super(valueStrength, keyEquivalence, valueEquivalence, expireAfterWriteNanos, expireAfterAccessNanos, maximumSize, concurrencyLevel, removalListener, delegate); + + this.computingFunction = computingFunction; + } + + private void writeObject(ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + writeMapTo(out); + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException + { + in.defaultReadObject(); + MapMaker mapMaker = readMapMaker(in); + delegate = mapMaker.makeComputingMap(computingFunction); + readEntries(in); + } + + Object readResolve() { + return delegate; + } + } +} diff --git a/src/minecraft/com/google/common/collect/ConcurrentHashMultiset.java b/src/minecraft/com/google/common/collect/ConcurrentHashMultiset.java new file mode 100644 index 0000000..336f683 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ConcurrentHashMultiset.java @@ -0,0 +1,579 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.math.IntMath; +import com.google.common.primitives.Ints; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicInteger; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public final class ConcurrentHashMultiset + extends AbstractMultiset + implements Serializable +{ + private final transient ConcurrentMap countMap; + private transient ConcurrentHashMultiset.EntrySet entrySet; + private static final long serialVersionUID = 1L; + + private static class FieldSettersHolder + { + static final Serialization.FieldSetter COUNT_MAP_FIELD_SETTER = Serialization.getFieldSetter(ConcurrentHashMultiset.class, "countMap"); + + + + + private FieldSettersHolder() {} + } + + + + public static ConcurrentHashMultiset create() + { + return new ConcurrentHashMultiset(new ConcurrentHashMap()); + } + + + + + + + + + public static ConcurrentHashMultiset create(Iterable elements) + { + ConcurrentHashMultiset multiset = create(); + Iterables.addAll(multiset, elements); + return multiset; + } + + + + + + + + + + + + + + + + + + + + + + @Beta + public static ConcurrentHashMultiset create(MapMaker mapMaker) + { + return new ConcurrentHashMultiset(mapMaker.makeMap()); + } + + + + + + + + + + @VisibleForTesting + ConcurrentHashMultiset(ConcurrentMap countMap) + { + Preconditions.checkArgument(countMap.isEmpty()); + this.countMap = countMap; + } + + + + + + + + + public int count(@Nullable Object element) + { + AtomicInteger existingCounter = (AtomicInteger)Maps.safeGet(countMap, element); + return existingCounter == null ? 0 : existingCounter.get(); + } + + + + + + + public int size() + { + long sum = 0L; + for (AtomicInteger value : countMap.values()) { + sum += value.get(); + } + return Ints.saturatedCast(sum); + } + + + + + + public Object[] toArray() + { + return snapshot().toArray(); + } + + public T[] toArray(T[] array) { + return snapshot().toArray(array); + } + + + + + private List snapshot() + { + List list = Lists.newArrayListWithExpectedSize(size()); + for (Multiset.Entry entry : entrySet()) { + E element = entry.getElement(); + for (int i = entry.getCount(); i > 0; i--) { + list.add(element); + } + } + return list; + } + + + + + + + + + + + + public int add(E element, int occurrences) + { + Preconditions.checkNotNull(element); + if (occurrences == 0) { + return count(element); + } + Preconditions.checkArgument(occurrences > 0, "Invalid occurrences: %s", new Object[] { Integer.valueOf(occurrences) }); + for (;;) + { + AtomicInteger existingCounter = (AtomicInteger)Maps.safeGet(countMap, element); + if (existingCounter == null) { + existingCounter = (AtomicInteger)countMap.putIfAbsent(element, new AtomicInteger(occurrences)); + if (existingCounter == null) { + return 0; + } + } + + for (;;) + { + int oldValue = existingCounter.get(); + if (oldValue != 0) { + try { + int newValue = IntMath.checkedAdd(oldValue, occurrences); + if (existingCounter.compareAndSet(oldValue, newValue)) + { + return oldValue; + } + } catch (ArithmeticException overflow) { + throw new IllegalArgumentException("Overflow adding " + occurrences + " occurrences to a count of " + oldValue); + } + } + + + + + AtomicInteger newCounter = new AtomicInteger(occurrences); + if ((countMap.putIfAbsent(element, newCounter) != null) && (!countMap.replace(element, existingCounter, newCounter))) + break; + return 0; + } + } + } + + + + + + + + + + + + + + + + + + + + + + + + public int remove(@Nullable Object element, int occurrences) + { + if (occurrences == 0) { + return count(element); + } + Preconditions.checkArgument(occurrences > 0, "Invalid occurrences: %s", new Object[] { Integer.valueOf(occurrences) }); + + AtomicInteger existingCounter = (AtomicInteger)Maps.safeGet(countMap, element); + if (existingCounter == null) { + return 0; + } + for (;;) { + int oldValue = existingCounter.get(); + if (oldValue != 0) { + int newValue = Math.max(0, oldValue - occurrences); + if (existingCounter.compareAndSet(oldValue, newValue)) { + if (newValue == 0) + { + + countMap.remove(element, existingCounter); + } + return oldValue; + } + } else { + return 0; + } + } + } + + + + + + + + + + + + public boolean removeExactly(@Nullable Object element, int occurrences) + { + if (occurrences == 0) { + return true; + } + Preconditions.checkArgument(occurrences > 0, "Invalid occurrences: %s", new Object[] { Integer.valueOf(occurrences) }); + + AtomicInteger existingCounter = (AtomicInteger)Maps.safeGet(countMap, element); + if (existingCounter == null) { + return false; + } + for (;;) { + int oldValue = existingCounter.get(); + if (oldValue < occurrences) { + return false; + } + int newValue = oldValue - occurrences; + if (existingCounter.compareAndSet(oldValue, newValue)) { + if (newValue == 0) + { + + countMap.remove(element, existingCounter); + } + return true; + } + } + } + + + + + + + + public int setCount(E element, int count) + { + Preconditions.checkNotNull(element); + CollectPreconditions.checkNonnegative(count, "count"); + for (;;) { + AtomicInteger existingCounter = (AtomicInteger)Maps.safeGet(countMap, element); + if (existingCounter == null) { + if (count == 0) { + return 0; + } + existingCounter = (AtomicInteger)countMap.putIfAbsent(element, new AtomicInteger(count)); + if (existingCounter == null) { + return 0; + } + } + + + for (;;) + { + int oldValue = existingCounter.get(); + if (oldValue == 0) { + if (count == 0) { + return 0; + } + AtomicInteger newCounter = new AtomicInteger(count); + if ((countMap.putIfAbsent(element, newCounter) == null) || (countMap.replace(element, existingCounter, newCounter))) + { + return 0; + } + + break; + } + if (existingCounter.compareAndSet(oldValue, count)) { + if (count == 0) + { + + countMap.remove(element, existingCounter); + } + return oldValue; + } + } + } + } + + + + + + + + + + + + + public boolean setCount(E element, int expectedOldCount, int newCount) + { + Preconditions.checkNotNull(element); + CollectPreconditions.checkNonnegative(expectedOldCount, "oldCount"); + CollectPreconditions.checkNonnegative(newCount, "newCount"); + + AtomicInteger existingCounter = (AtomicInteger)Maps.safeGet(countMap, element); + if (existingCounter == null) { + if (expectedOldCount != 0) + return false; + if (newCount == 0) { + return true; + } + + return countMap.putIfAbsent(element, new AtomicInteger(newCount)) == null; + } + + int oldValue = existingCounter.get(); + if (oldValue == expectedOldCount) { + if (oldValue == 0) { + if (newCount == 0) + { + countMap.remove(element, existingCounter); + return true; + } + AtomicInteger newCounter = new AtomicInteger(newCount); + return (countMap.putIfAbsent(element, newCounter) == null) || (countMap.replace(element, existingCounter, newCounter)); + } + + + if (existingCounter.compareAndSet(oldValue, newCount)) { + if (newCount == 0) + { + + countMap.remove(element, existingCounter); + } + return true; + } + } + + return false; + } + + + Set createElementSet() + { + final Set delegate = countMap.keySet(); + new ForwardingSet() { + protected Set delegate() { + return delegate; + } + + public boolean contains(@Nullable Object object) + { + return (object != null) && (Collections2.safeContains(delegate, object)); + } + + public boolean containsAll(Collection collection) + { + return standardContainsAll(collection); + } + + public boolean remove(Object object) { + return (object != null) && (Collections2.safeRemove(delegate, object)); + } + + public boolean removeAll(Collection c) { + return standardRemoveAll(c); + } + }; + } + + + public Set> entrySet() + { + ConcurrentHashMultiset.EntrySet result = entrySet; + if (result == null) { + entrySet = (result = new EntrySet(null)); + } + return result; + } + + int distinctElements() { + return countMap.size(); + } + + public boolean isEmpty() { + return countMap.isEmpty(); + } + + + Iterator> entryIterator() + { + final Iterator> readOnlyIterator = new AbstractIterator() + { + private Iterator> mapEntries = countMap.entrySet().iterator(); + + protected Multiset.Entry computeNext() { + for (;;) { + if (!mapEntries.hasNext()) { + return (Multiset.Entry)endOfData(); + } + Map.Entry mapEntry = (Map.Entry)mapEntries.next(); + int count = ((AtomicInteger)mapEntry.getValue()).get(); + if (count != 0) { + return Multisets.immutableEntry(mapEntry.getKey(), count); + } + + } + } + }; + new ForwardingIterator() { + private Multiset.Entry last; + + protected Iterator> delegate() { + return readOnlyIterator; + } + + public Multiset.Entry next() { + last = ((Multiset.Entry)super.next()); + return last; + } + + public void remove() { + CollectPreconditions.checkRemove(last != null); + setCount(last.getElement(), 0); + last = null; + } + }; + } + + + public void clear() { countMap.clear(); } + + private class EntrySet extends AbstractMultiset.EntrySet { + private EntrySet() { super(); } + + ConcurrentHashMultiset multiset() { return ConcurrentHashMultiset.this; } + + + + + + + public Object[] toArray() + { + return snapshot().toArray(); + } + + public T[] toArray(T[] array) { + return snapshot().toArray(array); + } + + private List> snapshot() { + List> list = Lists.newArrayListWithExpectedSize(size()); + + Iterators.addAll(list, iterator()); + return list; + } + } + + + private void writeObject(ObjectOutputStream stream) + throws IOException + { + stream.defaultWriteObject(); + stream.writeObject(countMap); + } + + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + + ConcurrentMap deserializedCountMap = (ConcurrentMap)stream.readObject(); + + FieldSettersHolder.COUNT_MAP_FIELD_SETTER.set(this, deserializedCountMap); + } +} diff --git a/src/minecraft/com/google/common/collect/Constraint.java b/src/minecraft/com/google/common/collect/Constraint.java new file mode 100644 index 0000000..0296e3f --- /dev/null +++ b/src/minecraft/com/google/common/collect/Constraint.java @@ -0,0 +1,11 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; + +@GwtCompatible +abstract interface Constraint +{ + public abstract E checkElement(E paramE); + + public abstract String toString(); +} diff --git a/src/minecraft/com/google/common/collect/Constraints.java b/src/minecraft/com/google/common/collect/Constraints.java new file mode 100644 index 0000000..91595c0 --- /dev/null +++ b/src/minecraft/com/google/common/collect/Constraints.java @@ -0,0 +1,304 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.Collection; +import java.util.List; +import java.util.ListIterator; +import java.util.RandomAccess; +import java.util.Set; +import java.util.SortedSet; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +final class Constraints +{ + private Constraints() {} + + public static Collection constrainedCollection(Collection collection, Constraint constraint) + { + return new ConstrainedCollection(collection, constraint); + } + + static class ConstrainedCollection extends ForwardingCollection + { + private final Collection delegate; + private final Constraint constraint; + + public ConstrainedCollection(Collection delegate, Constraint constraint) + { + this.delegate = ((Collection)Preconditions.checkNotNull(delegate)); + this.constraint = ((Constraint)Preconditions.checkNotNull(constraint)); + } + + protected Collection delegate() { return delegate; } + + public boolean add(E element) { + constraint.checkElement(element); + return delegate.add(element); + } + + public boolean addAll(Collection elements) { return delegate.addAll(Constraints.checkElements(elements, constraint)); } + } + + + + + + + + + + + + + + + public static Set constrainedSet(Set set, Constraint constraint) + { + return new ConstrainedSet(set, constraint); + } + + static class ConstrainedSet extends ForwardingSet + { + private final Set delegate; + private final Constraint constraint; + + public ConstrainedSet(Set delegate, Constraint constraint) { + this.delegate = ((Set)Preconditions.checkNotNull(delegate)); + this.constraint = ((Constraint)Preconditions.checkNotNull(constraint)); + } + + protected Set delegate() { return delegate; } + + public boolean add(E element) { + constraint.checkElement(element); + return delegate.add(element); + } + + public boolean addAll(Collection elements) { return delegate.addAll(Constraints.checkElements(elements, constraint)); } + } + + + + + + + + + + + + + + + public static SortedSet constrainedSortedSet(SortedSet sortedSet, Constraint constraint) + { + return new ConstrainedSortedSet(sortedSet, constraint); + } + + private static class ConstrainedSortedSet extends ForwardingSortedSet + { + final SortedSet delegate; + final Constraint constraint; + + ConstrainedSortedSet(SortedSet delegate, Constraint constraint) + { + this.delegate = ((SortedSet)Preconditions.checkNotNull(delegate)); + this.constraint = ((Constraint)Preconditions.checkNotNull(constraint)); + } + + protected SortedSet delegate() { return delegate; } + + public SortedSet headSet(E toElement) { + return Constraints.constrainedSortedSet(delegate.headSet(toElement), constraint); + } + + public SortedSet subSet(E fromElement, E toElement) { return Constraints.constrainedSortedSet(delegate.subSet(fromElement, toElement), constraint); } + + + + public SortedSet tailSet(E fromElement) { return Constraints.constrainedSortedSet(delegate.tailSet(fromElement), constraint); } + + public boolean add(E element) { + constraint.checkElement(element); + return delegate.add(element); + } + + public boolean addAll(Collection elements) { return delegate.addAll(Constraints.checkElements(elements, constraint)); } + } + + + + + + + + + + + + + + + + public static List constrainedList(List list, Constraint constraint) + { + return (list instanceof RandomAccess) ? new ConstrainedRandomAccessList(list, constraint) : new ConstrainedList(list, constraint); + } + + @GwtCompatible + private static class ConstrainedList + extends ForwardingList + { + final List delegate; + final Constraint constraint; + + ConstrainedList(List delegate, Constraint constraint) + { + this.delegate = ((List)Preconditions.checkNotNull(delegate)); + this.constraint = ((Constraint)Preconditions.checkNotNull(constraint)); + } + + protected List delegate() { return delegate; } + + public boolean add(E element) + { + constraint.checkElement(element); + return delegate.add(element); + } + + public void add(int index, E element) { constraint.checkElement(element); + delegate.add(index, element); + } + + public boolean addAll(Collection elements) { return delegate.addAll(Constraints.checkElements(elements, constraint)); } + + public boolean addAll(int index, Collection elements) + { + return delegate.addAll(index, Constraints.checkElements(elements, constraint)); + } + + public ListIterator listIterator() { return Constraints.constrainedListIterator(delegate.listIterator(), constraint); } + + + public ListIterator listIterator(int index) { return Constraints.constrainedListIterator(delegate.listIterator(index), constraint); } + + public E set(int index, E element) { + constraint.checkElement(element); + return delegate.set(index, element); + } + + public List subList(int fromIndex, int toIndex) { return Constraints.constrainedList(delegate.subList(fromIndex, toIndex), constraint); } + } + + + static class ConstrainedRandomAccessList + extends Constraints.ConstrainedList + implements RandomAccess + { + ConstrainedRandomAccessList(List delegate, Constraint constraint) + { + super(constraint); + } + } + + + + + + + + + + + private static ListIterator constrainedListIterator(ListIterator listIterator, Constraint constraint) + { + return new ConstrainedListIterator(listIterator, constraint); + } + + static class ConstrainedListIterator extends ForwardingListIterator + { + private final ListIterator delegate; + private final Constraint constraint; + + public ConstrainedListIterator(ListIterator delegate, Constraint constraint) + { + this.delegate = delegate; + this.constraint = constraint; + } + + protected ListIterator delegate() { return delegate; } + + public void add(E element) + { + constraint.checkElement(element); + delegate.add(element); + } + + public void set(E element) { constraint.checkElement(element); + delegate.set(element); + } + } + + static Collection constrainedTypePreservingCollection(Collection collection, Constraint constraint) + { + if ((collection instanceof SortedSet)) + return constrainedSortedSet((SortedSet)collection, constraint); + if ((collection instanceof Set)) + return constrainedSet((Set)collection, constraint); + if ((collection instanceof List)) { + return constrainedList((List)collection, constraint); + } + return constrainedCollection(collection, constraint); + } + + + + + + + + private static Collection checkElements(Collection elements, Constraint constraint) + { + Collection copy = Lists.newArrayList(elements); + for (E element : copy) { + constraint.checkElement(element); + } + return copy; + } +} diff --git a/src/minecraft/com/google/common/collect/ContiguousSet.java b/src/minecraft/com/google/common/collect/ContiguousSet.java new file mode 100644 index 0000000..5c09096 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ContiguousSet.java @@ -0,0 +1,184 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import java.util.Comparator; +import java.util.NoSuchElementException; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible(emulated=true) +public abstract class ContiguousSet + extends ImmutableSortedSet +{ + final DiscreteDomain domain; + + public static ContiguousSet create(Range range, DiscreteDomain domain) + { + Preconditions.checkNotNull(range); + Preconditions.checkNotNull(domain); + Range effectiveRange = range; + try { + if (!range.hasLowerBound()) { + effectiveRange = effectiveRange.intersection(Range.atLeast(domain.minValue())); + } + if (!range.hasUpperBound()) { + effectiveRange = effectiveRange.intersection(Range.atMost(domain.maxValue())); + } + } catch (NoSuchElementException e) { + throw new IllegalArgumentException(e); + } + + + boolean empty = (effectiveRange.isEmpty()) || (Range.compareOrThrow(lowerBound.leastValueAbove(domain), upperBound.greatestValueBelow(domain)) > 0); + + + + + return empty ? new EmptyContiguousSet(domain) : new RegularContiguousSet(effectiveRange, domain); + } + + + + + ContiguousSet(DiscreteDomain domain) + { + super(Ordering.natural()); + this.domain = domain; + } + + public ContiguousSet headSet(C toElement) { + return headSetImpl((Comparable)Preconditions.checkNotNull(toElement), false); + } + + + + @GwtIncompatible("NavigableSet") + public ContiguousSet headSet(C toElement, boolean inclusive) + { + return headSetImpl((Comparable)Preconditions.checkNotNull(toElement), inclusive); + } + + public ContiguousSet subSet(C fromElement, C toElement) { + Preconditions.checkNotNull(fromElement); + Preconditions.checkNotNull(toElement); + Preconditions.checkArgument(comparator().compare(fromElement, toElement) <= 0); + return subSetImpl(fromElement, true, toElement, false); + } + + + + + @GwtIncompatible("NavigableSet") + public ContiguousSet subSet(C fromElement, boolean fromInclusive, C toElement, boolean toInclusive) + { + Preconditions.checkNotNull(fromElement); + Preconditions.checkNotNull(toElement); + Preconditions.checkArgument(comparator().compare(fromElement, toElement) <= 0); + return subSetImpl(fromElement, fromInclusive, toElement, toInclusive); + } + + public ContiguousSet tailSet(C fromElement) { + return tailSetImpl((Comparable)Preconditions.checkNotNull(fromElement), true); + } + + + + @GwtIncompatible("NavigableSet") + public ContiguousSet tailSet(C fromElement, boolean inclusive) + { + return tailSetImpl((Comparable)Preconditions.checkNotNull(fromElement), inclusive); + } + + + + + + abstract ContiguousSet headSetImpl(C paramC, boolean paramBoolean); + + + + + + abstract ContiguousSet subSetImpl(C paramC1, boolean paramBoolean1, C paramC2, boolean paramBoolean2); + + + + + + abstract ContiguousSet tailSetImpl(C paramC, boolean paramBoolean); + + + + + + public abstract ContiguousSet intersection(ContiguousSet paramContiguousSet); + + + + + + public abstract Range range(); + + + + + + public abstract Range range(BoundType paramBoundType1, BoundType paramBoundType2); + + + + + public String toString() + { + return range().toString(); + } + + + + + + + + @Deprecated + public static ImmutableSortedSet.Builder builder() + { + throw new UnsupportedOperationException(); + } +} diff --git a/src/minecraft/com/google/common/collect/Count.java b/src/minecraft/com/google/common/collect/Count.java new file mode 100644 index 0000000..fd97070 --- /dev/null +++ b/src/minecraft/com/google/common/collect/Count.java @@ -0,0 +1,74 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.io.Serializable; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + +@GwtCompatible +final class Count + implements Serializable +{ + private int value; + + Count(int value) + { + this.value = value; + } + + public int get() { + return value; + } + + public int getAndAdd(int delta) { + int result = value; + value = (result + delta); + return result; + } + + public int addAndGet(int delta) { + return this.value += delta; + } + + public void set(int newValue) { + value = newValue; + } + + public int getAndSet(int newValue) { + int result = value; + value = newValue; + return result; + } + + public int hashCode() + { + return value; + } + + public boolean equals(@Nullable Object obj) + { + return ((obj instanceof Count)) && (value == value); + } + + public String toString() + { + return Integer.toString(value); + } +} diff --git a/src/minecraft/com/google/common/collect/Cut.java b/src/minecraft/com/google/common/collect/Cut.java new file mode 100644 index 0000000..bad95bd --- /dev/null +++ b/src/minecraft/com/google/common/collect/Cut.java @@ -0,0 +1,358 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.primitives.Booleans; +import java.io.Serializable; +import java.util.NoSuchElementException; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +abstract class Cut + implements Comparable>, Serializable +{ + final C endpoint; + private static final long serialVersionUID = 0L; + + Cut(@Nullable C endpoint) + { + this.endpoint = endpoint; + } + + abstract boolean isLessThan(C paramC); + + abstract BoundType typeAsLowerBound(); + + abstract BoundType typeAsUpperBound(); + + abstract Cut withLowerBoundType(BoundType paramBoundType, DiscreteDomain paramDiscreteDomain); + + abstract Cut withUpperBoundType(BoundType paramBoundType, DiscreteDomain paramDiscreteDomain); + + abstract void describeAsLowerBound(StringBuilder paramStringBuilder); + + abstract void describeAsUpperBound(StringBuilder paramStringBuilder); + + abstract C leastValueAbove(DiscreteDomain paramDiscreteDomain); + + abstract C greatestValueBelow(DiscreteDomain paramDiscreteDomain); + + Cut canonical(DiscreteDomain domain) { + return this; + } + + + public int compareTo(Cut that) + { + if (that == belowAll()) { + return 1; + } + if (that == aboveAll()) { + return -1; + } + int result = Range.compareOrThrow(endpoint, endpoint); + if (result != 0) { + return result; + } + + return Booleans.compare(this instanceof AboveValue, that instanceof AboveValue); + } + + C endpoint() + { + return endpoint; + } + + public boolean equals(Object obj) + { + if ((obj instanceof Cut)) + { + Cut that = (Cut)obj; + try { + int compareResult = compareTo(that); + return compareResult == 0; + } + catch (ClassCastException ignored) {} + } + return false; + } + + + + + + static Cut belowAll() + { + return BelowAll.INSTANCE; + } + + private static final class BelowAll + extends Cut> + { + private static final BelowAll INSTANCE = new BelowAll(); + private static final long serialVersionUID = 0L; + + private BelowAll() { super(); } + + Comparable endpoint() { + throw new IllegalStateException("range unbounded on this side"); + } + + boolean isLessThan(Comparable value) { return true; } + + BoundType typeAsLowerBound() { + throw new IllegalStateException(); + } + + BoundType typeAsUpperBound() { throw new AssertionError("this statement should be unreachable"); } + + Cut> withLowerBoundType(BoundType boundType, DiscreteDomain> domain) + { + throw new IllegalStateException(); + } + + Cut> withUpperBoundType(BoundType boundType, DiscreteDomain> domain) { + throw new AssertionError("this statement should be unreachable"); + } + + void describeAsLowerBound(StringBuilder sb) { sb.append("(-∞"); } + + void describeAsUpperBound(StringBuilder sb) { + throw new AssertionError(); + } + + Comparable leastValueAbove(DiscreteDomain> domain) { + return domain.minValue(); + } + + Comparable greatestValueBelow(DiscreteDomain> domain) { + throw new AssertionError(); + } + + Cut> canonical(DiscreteDomain> domain) { + try { + return Cut.belowValue(domain.minValue()); + } catch (NoSuchElementException e) {} + return this; + } + + public int compareTo(Cut> o) { + return o == this ? 0 : -1; + } + + public String toString() { return "-∞"; } + + private Object readResolve() { + return INSTANCE; + } + } + + + + + + + static Cut aboveAll() + { + return AboveAll.INSTANCE; + } + + private static final class AboveAll extends Cut> { + private static final AboveAll INSTANCE = new AboveAll(); + private static final long serialVersionUID = 0L; + + private AboveAll() { super(); } + + Comparable endpoint() { + throw new IllegalStateException("range unbounded on this side"); + } + + boolean isLessThan(Comparable value) { return false; } + + BoundType typeAsLowerBound() { + throw new AssertionError("this statement should be unreachable"); + } + + BoundType typeAsUpperBound() { throw new IllegalStateException(); } + + Cut> withLowerBoundType(BoundType boundType, DiscreteDomain> domain) + { + throw new AssertionError("this statement should be unreachable"); + } + + Cut> withUpperBoundType(BoundType boundType, DiscreteDomain> domain) { + throw new IllegalStateException(); + } + + void describeAsLowerBound(StringBuilder sb) { throw new AssertionError(); } + + void describeAsUpperBound(StringBuilder sb) { + sb.append("+∞)"); + } + + Comparable leastValueAbove(DiscreteDomain> domain) { + throw new AssertionError(); + } + + Comparable greatestValueBelow(DiscreteDomain> domain) { + return domain.maxValue(); + } + + public int compareTo(Cut> o) { return o == this ? 0 : 1; } + + public String toString() { + return "+∞"; + } + + private Object readResolve() { return INSTANCE; } + } + + + + + static Cut belowValue(C endpoint) { return new BelowValue(endpoint); } + + private static final class BelowValue extends Cut { + private static final long serialVersionUID = 0L; + + BelowValue(C endpoint) { super(); } + + boolean isLessThan(C value) + { + return Range.compareOrThrow(endpoint, value) <= 0; + } + + BoundType typeAsLowerBound() { return BoundType.CLOSED; } + + + BoundType typeAsUpperBound() { return BoundType.OPEN; } + + Cut withLowerBoundType(BoundType boundType, DiscreteDomain domain) { + switch (Cut.1.$SwitchMap$com$google$common$collect$BoundType[boundType.ordinal()]) { + case 1: + return this; + case 2: + C previous = domain.previous(endpoint); + return previous == null ? Cut.belowAll() : new Cut.AboveValue(previous); + } + throw new AssertionError(); + } + + Cut withUpperBoundType(BoundType boundType, DiscreteDomain domain) { + switch (Cut.1.$SwitchMap$com$google$common$collect$BoundType[boundType.ordinal()]) { + case 1: + C previous = domain.previous(endpoint); + return previous == null ? Cut.aboveAll() : new Cut.AboveValue(previous); + case 2: + return this; + } + throw new AssertionError(); + } + + void describeAsLowerBound(StringBuilder sb) { + sb.append('[').append(endpoint); + } + + void describeAsUpperBound(StringBuilder sb) { sb.append(endpoint).append(')'); } + + C leastValueAbove(DiscreteDomain domain) { + return endpoint; + } + + C greatestValueBelow(DiscreteDomain domain) { return domain.previous(endpoint); } + + public int hashCode() { + return endpoint.hashCode(); + } + + public String toString() { return "\\" + endpoint + "/"; } + } + + + + + static Cut aboveValue(C endpoint) { return new AboveValue(endpoint); } + + private static final class AboveValue extends Cut { + private static final long serialVersionUID = 0L; + + AboveValue(C endpoint) { super(); } + + boolean isLessThan(C value) + { + return Range.compareOrThrow(endpoint, value) < 0; + } + + BoundType typeAsLowerBound() { return BoundType.OPEN; } + + + BoundType typeAsUpperBound() { return BoundType.CLOSED; } + + Cut withLowerBoundType(BoundType boundType, DiscreteDomain domain) { + switch (Cut.1.$SwitchMap$com$google$common$collect$BoundType[boundType.ordinal()]) { + case 2: + return this; + case 1: + C next = domain.next(endpoint); + return next == null ? Cut.belowAll() : belowValue(next); + } + throw new AssertionError(); + } + + Cut withUpperBoundType(BoundType boundType, DiscreteDomain domain) { + switch (Cut.1.$SwitchMap$com$google$common$collect$BoundType[boundType.ordinal()]) { + case 2: + C next = domain.next(endpoint); + return next == null ? Cut.aboveAll() : belowValue(next); + case 1: + return this; + } + throw new AssertionError(); + } + + void describeAsLowerBound(StringBuilder sb) { + sb.append('(').append(endpoint); + } + + void describeAsUpperBound(StringBuilder sb) { sb.append(endpoint).append(']'); } + + C leastValueAbove(DiscreteDomain domain) { + return domain.next(endpoint); + } + + C greatestValueBelow(DiscreteDomain domain) { return endpoint; } + + Cut canonical(DiscreteDomain domain) { + C next = leastValueAbove(domain); + return next != null ? belowValue(next) : Cut.aboveAll(); + } + + public int hashCode() { return endpoint.hashCode() ^ 0xFFFFFFFF; } + + public String toString() { + return "/" + endpoint + "\\"; + } + } +} diff --git a/src/minecraft/com/google/common/collect/DenseImmutableTable.java b/src/minecraft/com/google/common/collect/DenseImmutableTable.java new file mode 100644 index 0000000..9df0f55 --- /dev/null +++ b/src/minecraft/com/google/common/collect/DenseImmutableTable.java @@ -0,0 +1,278 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.Map; +import java.util.Map.Entry; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + + + + + + + + + + + + + + + + + + +@GwtCompatible +@Immutable +final class DenseImmutableTable + extends RegularImmutableTable +{ + private final ImmutableMap rowKeyToIndex; + private final ImmutableMap columnKeyToIndex; + private final ImmutableMap> rowMap; + private final ImmutableMap> columnMap; + private final int[] rowCounts; + private final int[] columnCounts; + private final V[][] values; + private final int[] iterationOrderRow; + private final int[] iterationOrderColumn; + + private static ImmutableMap makeIndex(ImmutableSet set) + { + ImmutableMap.Builder indexBuilder = ImmutableMap.builder(); + int i = 0; + for (E key : set) { + indexBuilder.put(key, Integer.valueOf(i)); + i++; + } + return indexBuilder.build(); + } + + + DenseImmutableTable(ImmutableList> cellList, ImmutableSet rowSpace, ImmutableSet columnSpace) + { + V[][] array = (Object[][])new Object[rowSpace.size()][columnSpace.size()]; + values = array; + rowKeyToIndex = makeIndex(rowSpace); + columnKeyToIndex = makeIndex(columnSpace); + rowCounts = new int[rowKeyToIndex.size()]; + columnCounts = new int[columnKeyToIndex.size()]; + int[] iterationOrderRow = new int[cellList.size()]; + int[] iterationOrderColumn = new int[cellList.size()]; + for (int i = 0; i < cellList.size(); i++) { + Table.Cell cell = (Table.Cell)cellList.get(i); + R rowKey = cell.getRowKey(); + C columnKey = cell.getColumnKey(); + int rowIndex = ((Integer)rowKeyToIndex.get(rowKey)).intValue(); + int columnIndex = ((Integer)columnKeyToIndex.get(columnKey)).intValue(); + V existingValue = values[rowIndex][columnIndex]; + Preconditions.checkArgument(existingValue == null, "duplicate key: (%s, %s)", new Object[] { rowKey, columnKey }); + values[rowIndex][columnIndex] = cell.getValue(); + rowCounts[rowIndex] += 1; + columnCounts[columnIndex] += 1; + iterationOrderRow[i] = rowIndex; + iterationOrderColumn[i] = columnIndex; + } + this.iterationOrderRow = iterationOrderRow; + this.iterationOrderColumn = iterationOrderColumn; + rowMap = new RowMap(null); + columnMap = new ColumnMap(null); + } + + private static abstract class ImmutableArrayMap + extends ImmutableMap + { + private final int size; + + ImmutableArrayMap(int size) + { + this.size = size; + } + + abstract ImmutableMap keyToIndex(); + + private boolean isFull() + { + return size == keyToIndex().size(); + } + + K getKey(int index) { + return keyToIndex().keySet().asList().get(index); + } + + @Nullable + abstract V getValue(int paramInt); + + ImmutableSet createKeySet() { + return isFull() ? keyToIndex().keySet() : super.createKeySet(); + } + + public int size() + { + return size; + } + + public V get(@Nullable Object key) + { + Integer keyIndex = (Integer)keyToIndex().get(key); + return keyIndex == null ? null : getValue(keyIndex.intValue()); + } + + ImmutableSet> createEntrySet() + { + new ImmutableMapEntrySet() { + ImmutableMap map() { + return DenseImmutableTable.ImmutableArrayMap.this; + } + + public UnmodifiableIterator> iterator() + { + new AbstractIterator() { + private int index = -1; + private final int maxIndex = keyToIndex().size(); + + protected Map.Entry computeNext() + { + for (index += 1; index < maxIndex; index += 1) { + V value = getValue(index); + if (value != null) { + return Maps.immutableEntry(getKey(index), value); + } + } + return (Map.Entry)endOfData(); + } + }; + } + }; + } + } + + private final class Row extends DenseImmutableTable.ImmutableArrayMap { + private final int rowIndex; + + Row(int rowIndex) { + super(); + this.rowIndex = rowIndex; + } + + ImmutableMap keyToIndex() + { + return columnKeyToIndex; + } + + V getValue(int keyIndex) + { + return values[rowIndex][keyIndex]; + } + + boolean isPartialView() + { + return true; + } + } + + private final class Column extends DenseImmutableTable.ImmutableArrayMap { + private final int columnIndex; + + Column(int columnIndex) { + super(); + this.columnIndex = columnIndex; + } + + ImmutableMap keyToIndex() + { + return rowKeyToIndex; + } + + V getValue(int keyIndex) + { + return values[keyIndex][columnIndex]; + } + + boolean isPartialView() + { + return true; + } + } + + private final class RowMap extends DenseImmutableTable.ImmutableArrayMap> { + private RowMap() { + super(); + } + + ImmutableMap keyToIndex() + { + return rowKeyToIndex; + } + + Map getValue(int keyIndex) + { + return new DenseImmutableTable.Row(DenseImmutableTable.this, keyIndex); + } + + boolean isPartialView() + { + return false; + } + } + + private final class ColumnMap extends DenseImmutableTable.ImmutableArrayMap> { + private ColumnMap() { + super(); + } + + ImmutableMap keyToIndex() + { + return columnKeyToIndex; + } + + Map getValue(int keyIndex) + { + return new DenseImmutableTable.Column(DenseImmutableTable.this, keyIndex); + } + + boolean isPartialView() + { + return false; + } + } + + public ImmutableMap> columnMap() { + return columnMap; + } + + public ImmutableMap> rowMap() + { + return rowMap; + } + + public V get(@Nullable Object rowKey, @Nullable Object columnKey) + { + Integer rowIndex = (Integer)rowKeyToIndex.get(rowKey); + Integer columnIndex = (Integer)columnKeyToIndex.get(columnKey); + return (rowIndex == null) || (columnIndex == null) ? null : values[rowIndex.intValue()][columnIndex.intValue()]; + } + + + public int size() + { + return iterationOrderRow.length; + } + + Table.Cell getCell(int index) + { + int rowIndex = iterationOrderRow[index]; + int columnIndex = iterationOrderColumn[index]; + R rowKey = rowKeySet().asList().get(rowIndex); + C columnKey = columnKeySet().asList().get(columnIndex); + V value = values[rowIndex][columnIndex]; + return cellOf(rowKey, columnKey, value); + } + + V getValue(int index) + { + return values[iterationOrderRow[index]][iterationOrderColumn[index]]; + } +} diff --git a/src/minecraft/com/google/common/collect/DescendingImmutableSortedMultiset.java b/src/minecraft/com/google/common/collect/DescendingImmutableSortedMultiset.java new file mode 100644 index 0000000..e34673f --- /dev/null +++ b/src/minecraft/com/google/common/collect/DescendingImmutableSortedMultiset.java @@ -0,0 +1,81 @@ +package com.google.common.collect; + +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + +final class DescendingImmutableSortedMultiset + extends ImmutableSortedMultiset +{ + private final transient ImmutableSortedMultiset forward; + + DescendingImmutableSortedMultiset(ImmutableSortedMultiset forward) + { + this.forward = forward; + } + + public int count(@Nullable Object element) + { + return forward.count(element); + } + + public Multiset.Entry firstEntry() + { + return forward.lastEntry(); + } + + public Multiset.Entry lastEntry() + { + return forward.firstEntry(); + } + + public int size() + { + return forward.size(); + } + + public ImmutableSortedSet elementSet() + { + return forward.elementSet().descendingSet(); + } + + Multiset.Entry getEntry(int index) + { + return (Multiset.Entry)forward.entrySet().asList().reverse().get(index); + } + + public ImmutableSortedMultiset descendingMultiset() + { + return forward; + } + + public ImmutableSortedMultiset headMultiset(E upperBound, BoundType boundType) + { + return forward.tailMultiset(upperBound, boundType).descendingMultiset(); + } + + public ImmutableSortedMultiset tailMultiset(E lowerBound, BoundType boundType) + { + return forward.headMultiset(lowerBound, boundType).descendingMultiset(); + } + + boolean isPartialView() + { + return forward.isPartialView(); + } +} diff --git a/src/minecraft/com/google/common/collect/DescendingImmutableSortedSet.java b/src/minecraft/com/google/common/collect/DescendingImmutableSortedSet.java new file mode 100644 index 0000000..04b4053 --- /dev/null +++ b/src/minecraft/com/google/common/collect/DescendingImmutableSortedSet.java @@ -0,0 +1,114 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtIncompatible; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + +class DescendingImmutableSortedSet + extends ImmutableSortedSet +{ + private final ImmutableSortedSet forward; + + DescendingImmutableSortedSet(ImmutableSortedSet forward) + { + super(Ordering.from(forward.comparator()).reverse()); + this.forward = forward; + } + + public int size() + { + return forward.size(); + } + + public UnmodifiableIterator iterator() + { + return forward.descendingIterator(); + } + + ImmutableSortedSet headSetImpl(E toElement, boolean inclusive) + { + return forward.tailSet(toElement, inclusive).descendingSet(); + } + + + ImmutableSortedSet subSetImpl(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) + { + return forward.subSet(toElement, toInclusive, fromElement, fromInclusive).descendingSet(); + } + + ImmutableSortedSet tailSetImpl(E fromElement, boolean inclusive) + { + return forward.headSet(fromElement, inclusive).descendingSet(); + } + + @GwtIncompatible("NavigableSet") + public ImmutableSortedSet descendingSet() + { + return forward; + } + + @GwtIncompatible("NavigableSet") + public UnmodifiableIterator descendingIterator() + { + return forward.iterator(); + } + + @GwtIncompatible("NavigableSet") + ImmutableSortedSet createDescendingSet() + { + throw new AssertionError("should never be called"); + } + + public E lower(E element) + { + return forward.higher(element); + } + + public E floor(E element) + { + return forward.ceiling(element); + } + + public E ceiling(E element) + { + return forward.floor(element); + } + + public E higher(E element) + { + return forward.lower(element); + } + + int indexOf(@Nullable Object target) + { + int index = forward.indexOf(target); + if (index == -1) { + return index; + } + return size() - 1 - index; + } + + + boolean isPartialView() + { + return forward.isPartialView(); + } +} diff --git a/src/minecraft/com/google/common/collect/DescendingMultiset.java b/src/minecraft/com/google/common/collect/DescendingMultiset.java new file mode 100644 index 0000000..d7808c9 --- /dev/null +++ b/src/minecraft/com/google/common/collect/DescendingMultiset.java @@ -0,0 +1,140 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NavigableSet; +import java.util.Set; + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +abstract class DescendingMultiset + extends ForwardingMultiset + implements SortedMultiset +{ + private transient Comparator comparator; + private transient NavigableSet elementSet; + private transient Set> entrySet; + + DescendingMultiset() {} + + abstract SortedMultiset forwardMultiset(); + + public Comparator comparator() + { + Comparator result = comparator; + if (result == null) { + return this.comparator = Ordering.from(forwardMultiset().comparator()).reverse(); + } + + return result; + } + + + public NavigableSet elementSet() + { + NavigableSet result = elementSet; + if (result == null) { + return this.elementSet = new SortedMultisets.NavigableElementSet(this); + } + return result; + } + + public Multiset.Entry pollFirstEntry() { + return forwardMultiset().pollLastEntry(); + } + + public Multiset.Entry pollLastEntry() { + return forwardMultiset().pollFirstEntry(); + } + + public SortedMultiset headMultiset(E toElement, BoundType boundType) + { + return forwardMultiset().tailMultiset(toElement, boundType).descendingMultiset(); + } + + + public SortedMultiset subMultiset(E fromElement, BoundType fromBoundType, E toElement, BoundType toBoundType) + { + return forwardMultiset().subMultiset(toElement, toBoundType, fromElement, fromBoundType).descendingMultiset(); + } + + + public SortedMultiset tailMultiset(E fromElement, BoundType boundType) + { + return forwardMultiset().headMultiset(fromElement, boundType).descendingMultiset(); + } + + protected Multiset delegate() + { + return forwardMultiset(); + } + + public SortedMultiset descendingMultiset() { + return forwardMultiset(); + } + + public Multiset.Entry firstEntry() { + return forwardMultiset().lastEntry(); + } + + public Multiset.Entry lastEntry() { + return forwardMultiset().firstEntry(); + } + + + abstract Iterator> entryIterator(); + + public Set> entrySet() + { + Set> result = entrySet; + return result == null ? (this.entrySet = createEntrySet()) : result; + } + + Set> createEntrySet() { + new Multisets.EntrySet() { + Multiset multiset() { + return DescendingMultiset.this; + } + + public Iterator> iterator() { + return entryIterator(); + } + + public int size() { + return forwardMultiset().entrySet().size(); + } + }; + } + + public Iterator iterator() { + return Multisets.iteratorImpl(this); + } + + public Object[] toArray() { + return standardToArray(); + } + + public T[] toArray(T[] array) { + return standardToArray(array); + } + + public String toString() { + return entrySet().toString(); + } +} diff --git a/src/minecraft/com/google/common/collect/DiscreteDomain.java b/src/minecraft/com/google/common/collect/DiscreteDomain.java new file mode 100644 index 0000000..190227e --- /dev/null +++ b/src/minecraft/com/google/common/collect/DiscreteDomain.java @@ -0,0 +1,262 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import java.io.Serializable; +import java.math.BigInteger; +import java.util.NoSuchElementException; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +@Beta +public abstract class DiscreteDomain +{ + public static DiscreteDomain integers() { return IntegerDomain.INSTANCE; } + + private static final class IntegerDomain extends DiscreteDomain implements Serializable { + private IntegerDomain() {} + + private static final IntegerDomain INSTANCE = new IntegerDomain(); + + public Integer next(Integer value) { + int i = value.intValue(); + return i == Integer.MAX_VALUE ? null : Integer.valueOf(i + 1); + } + + public Integer previous(Integer value) { + int i = value.intValue(); + return i == Integer.MIN_VALUE ? null : Integer.valueOf(i - 1); + } + + public long distance(Integer start, Integer end) { + return end.intValue() - start.intValue(); + } + + public Integer minValue() { + return Integer.valueOf(Integer.MIN_VALUE); + } + + public Integer maxValue() { + return Integer.valueOf(Integer.MAX_VALUE); + } + + private Object readResolve() { + return INSTANCE; + } + + public String toString() + { + return "DiscreteDomain.integers()"; + } + + + + + private static final long serialVersionUID = 0L; + } + + + + + public static DiscreteDomain longs() { return LongDomain.INSTANCE; } + + private static final class LongDomain extends DiscreteDomain implements Serializable { + private LongDomain() {} + + private static final LongDomain INSTANCE = new LongDomain(); + + public Long next(Long value) { + long l = value.longValue(); + return l == Long.MAX_VALUE ? null : Long.valueOf(l + 1L); + } + + public Long previous(Long value) { + long l = value.longValue(); + return l == Long.MIN_VALUE ? null : Long.valueOf(l - 1L); + } + + public long distance(Long start, Long end) { + long result = end.longValue() - start.longValue(); + if ((end.longValue() > start.longValue()) && (result < 0L)) { + return Long.MAX_VALUE; + } + if ((end.longValue() < start.longValue()) && (result > 0L)) { + return Long.MIN_VALUE; + } + return result; + } + + public Long minValue() { + return Long.valueOf(Long.MIN_VALUE); + } + + public Long maxValue() { + return Long.valueOf(Long.MAX_VALUE); + } + + private Object readResolve() { + return INSTANCE; + } + + public String toString() + { + return "DiscreteDomain.longs()"; + } + + + + + private static final long serialVersionUID = 0L; + } + + + + + public static DiscreteDomain bigIntegers() { return BigIntegerDomain.INSTANCE; } + + protected DiscreteDomain() {} + + private static final class BigIntegerDomain extends DiscreteDomain implements Serializable { + private static final BigIntegerDomain INSTANCE = new BigIntegerDomain(); + + private static final BigInteger MIN_LONG = BigInteger.valueOf(Long.MIN_VALUE); + + private static final BigInteger MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE); + + private BigIntegerDomain() {} + + public BigInteger next(BigInteger value) { return value.add(BigInteger.ONE); } + + public BigInteger previous(BigInteger value) + { + return value.subtract(BigInteger.ONE); + } + + public long distance(BigInteger start, BigInteger end) { + return end.subtract(start).max(MIN_LONG).min(MAX_LONG).longValue(); + } + + private Object readResolve() { + return INSTANCE; + } + + public String toString() + { + return "DiscreteDomain.bigIntegers()"; + } + + + + + + + + + + + + private static final long serialVersionUID = 0L; + } + + + + + + + + + + + public abstract C next(C paramC); + + + + + + + + + + + public abstract C previous(C paramC); + + + + + + + + + + + public abstract long distance(C paramC1, C paramC2); + + + + + + + + + + + public C minValue() + { + throw new NoSuchElementException(); + } + + + + + + + + + + + + public C maxValue() + { + throw new NoSuchElementException(); + } +} diff --git a/src/minecraft/com/google/common/collect/EmptyContiguousSet.java b/src/minecraft/com/google/common/collect/EmptyContiguousSet.java new file mode 100644 index 0000000..3724691 --- /dev/null +++ b/src/minecraft/com/google/common/collect/EmptyContiguousSet.java @@ -0,0 +1,141 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import java.io.Serializable; +import java.util.NoSuchElementException; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +final class EmptyContiguousSet + extends ContiguousSet +{ + EmptyContiguousSet(DiscreteDomain domain) + { + super(domain); + } + + public C first() { + throw new NoSuchElementException(); + } + + public C last() { + throw new NoSuchElementException(); + } + + public int size() { + return 0; + } + + public ContiguousSet intersection(ContiguousSet other) { + return this; + } + + public Range range() { + throw new NoSuchElementException(); + } + + public Range range(BoundType lowerBoundType, BoundType upperBoundType) { + throw new NoSuchElementException(); + } + + ContiguousSet headSetImpl(C toElement, boolean inclusive) { + return this; + } + + ContiguousSet subSetImpl(C fromElement, boolean fromInclusive, C toElement, boolean toInclusive) + { + return this; + } + + ContiguousSet tailSetImpl(C fromElement, boolean fromInclusive) { + return this; + } + + @GwtIncompatible("not used by GWT emulation") + int indexOf(Object target) { + return -1; + } + + public UnmodifiableIterator iterator() { + return Iterators.emptyIterator(); + } + + @GwtIncompatible("NavigableSet") + public UnmodifiableIterator descendingIterator() { + return Iterators.emptyIterator(); + } + + boolean isPartialView() { + return false; + } + + public boolean isEmpty() { + return true; + } + + public ImmutableList asList() { + return ImmutableList.of(); + } + + public String toString() { + return "[]"; + } + + public boolean equals(@Nullable Object object) { + if ((object instanceof Set)) { + Set that = (Set)object; + return that.isEmpty(); + } + return false; + } + + public int hashCode() { + return 0; + } + + @GwtIncompatible("serialization") + private static final class SerializedForm implements Serializable { + private final DiscreteDomain domain; + private static final long serialVersionUID = 0L; + + private SerializedForm(DiscreteDomain domain) { this.domain = domain; } + + private Object readResolve() + { + return new EmptyContiguousSet(domain); + } + } + + + + @GwtIncompatible("serialization") + Object writeReplace() + { + return new SerializedForm(domain, null); + } + + @GwtIncompatible("NavigableSet") + ImmutableSortedSet createDescendingSet() { + return new EmptyImmutableSortedSet(Ordering.natural().reverse()); + } +} diff --git a/src/minecraft/com/google/common/collect/EmptyImmutableBiMap.java b/src/minecraft/com/google/common/collect/EmptyImmutableBiMap.java new file mode 100644 index 0000000..6fab344 --- /dev/null +++ b/src/minecraft/com/google/common/collect/EmptyImmutableBiMap.java @@ -0,0 +1,82 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Map.Entry; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +final class EmptyImmutableBiMap + extends ImmutableBiMap +{ + static final EmptyImmutableBiMap INSTANCE = new EmptyImmutableBiMap(); + + private EmptyImmutableBiMap() {} + + public ImmutableBiMap inverse() { + return this; + } + + public int size() + { + return 0; + } + + public boolean isEmpty() + { + return true; + } + + public Object get(@Nullable Object key) + { + return null; + } + + public ImmutableSet> entrySet() + { + return ImmutableSet.of(); + } + + ImmutableSet> createEntrySet() + { + throw new AssertionError("should never be called"); + } + + public ImmutableSetMultimap asMultimap() + { + return ImmutableSetMultimap.of(); + } + + public ImmutableSet keySet() + { + return ImmutableSet.of(); + } + + boolean isPartialView() + { + return false; + } + + Object readResolve() { + return INSTANCE; + } +} diff --git a/src/minecraft/com/google/common/collect/EmptyImmutableListMultimap.java b/src/minecraft/com/google/common/collect/EmptyImmutableListMultimap.java new file mode 100644 index 0000000..76a176c --- /dev/null +++ b/src/minecraft/com/google/common/collect/EmptyImmutableListMultimap.java @@ -0,0 +1,38 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true) +class EmptyImmutableListMultimap + extends ImmutableListMultimap +{ + static final EmptyImmutableListMultimap INSTANCE = new EmptyImmutableListMultimap(); + private static final long serialVersionUID = 0L; + + private EmptyImmutableListMultimap() { + super(ImmutableMap.of(), 0); + } + + private Object readResolve() { + return INSTANCE; + } +} diff --git a/src/minecraft/com/google/common/collect/EmptyImmutableSet.java b/src/minecraft/com/google/common/collect/EmptyImmutableSet.java new file mode 100644 index 0000000..0479edf --- /dev/null +++ b/src/minecraft/com/google/common/collect/EmptyImmutableSet.java @@ -0,0 +1,95 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Collection; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +final class EmptyImmutableSet + extends ImmutableSet +{ + static final EmptyImmutableSet INSTANCE = new EmptyImmutableSet(); + private static final long serialVersionUID = 0L; + + private EmptyImmutableSet() {} + + public int size() { + return 0; + } + + public boolean isEmpty() { + return true; + } + + public boolean contains(@Nullable Object target) { + return false; + } + + public boolean containsAll(Collection targets) { + return targets.isEmpty(); + } + + public UnmodifiableIterator iterator() { + return Iterators.emptyIterator(); + } + + boolean isPartialView() { + return false; + } + + int copyIntoArray(Object[] dst, int offset) + { + return offset; + } + + public ImmutableList asList() + { + return ImmutableList.of(); + } + + public boolean equals(@Nullable Object object) { + if ((object instanceof Set)) { + Set that = (Set)object; + return that.isEmpty(); + } + return false; + } + + public final int hashCode() { + return 0; + } + + boolean isHashCodeFast() { + return true; + } + + public String toString() { + return "[]"; + } + + Object readResolve() { + return INSTANCE; + } +} diff --git a/src/minecraft/com/google/common/collect/EmptyImmutableSetMultimap.java b/src/minecraft/com/google/common/collect/EmptyImmutableSetMultimap.java new file mode 100644 index 0000000..0efef08 --- /dev/null +++ b/src/minecraft/com/google/common/collect/EmptyImmutableSetMultimap.java @@ -0,0 +1,38 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true) +class EmptyImmutableSetMultimap + extends ImmutableSetMultimap +{ + static final EmptyImmutableSetMultimap INSTANCE = new EmptyImmutableSetMultimap(); + private static final long serialVersionUID = 0L; + + private EmptyImmutableSetMultimap() { + super(ImmutableMap.of(), 0, null); + } + + private Object readResolve() { + return INSTANCE; + } +} diff --git a/src/minecraft/com/google/common/collect/EmptyImmutableSortedMap.java b/src/minecraft/com/google/common/collect/EmptyImmutableSortedMap.java new file mode 100644 index 0000000..36f7843 --- /dev/null +++ b/src/minecraft/com/google/common/collect/EmptyImmutableSortedMap.java @@ -0,0 +1,112 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.Comparator; +import java.util.Map.Entry; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +final class EmptyImmutableSortedMap + extends ImmutableSortedMap +{ + private final transient ImmutableSortedSet keySet; + + EmptyImmutableSortedMap(Comparator comparator) + { + keySet = ImmutableSortedSet.emptySet(comparator); + } + + EmptyImmutableSortedMap(Comparator comparator, ImmutableSortedMap descendingMap) + { + super(descendingMap); + keySet = ImmutableSortedSet.emptySet(comparator); + } + + public V get(@Nullable Object key) + { + return null; + } + + public ImmutableSortedSet keySet() + { + return keySet; + } + + public int size() + { + return 0; + } + + public boolean isEmpty() + { + return true; + } + + public ImmutableCollection values() + { + return ImmutableList.of(); + } + + public String toString() + { + return "{}"; + } + + boolean isPartialView() + { + return false; + } + + public ImmutableSet> entrySet() + { + return ImmutableSet.of(); + } + + ImmutableSet> createEntrySet() + { + throw new AssertionError("should never be called"); + } + + public ImmutableSetMultimap asMultimap() + { + return ImmutableSetMultimap.of(); + } + + public ImmutableSortedMap headMap(K toKey, boolean inclusive) + { + Preconditions.checkNotNull(toKey); + return this; + } + + public ImmutableSortedMap tailMap(K fromKey, boolean inclusive) + { + Preconditions.checkNotNull(fromKey); + return this; + } + + ImmutableSortedMap createDescendingMap() + { + return new EmptyImmutableSortedMap(Ordering.from(comparator()).reverse(), this); + } +} diff --git a/src/minecraft/com/google/common/collect/EmptyImmutableSortedMultiset.java b/src/minecraft/com/google/common/collect/EmptyImmutableSortedMultiset.java new file mode 100644 index 0000000..63e3b82 --- /dev/null +++ b/src/minecraft/com/google/common/collect/EmptyImmutableSortedMultiset.java @@ -0,0 +1,114 @@ +package com.google.common.collect; + +import com.google.common.base.Preconditions; +import java.util.Collection; +import java.util.Comparator; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + +final class EmptyImmutableSortedMultiset + extends ImmutableSortedMultiset +{ + private final ImmutableSortedSet elementSet; + + EmptyImmutableSortedMultiset(Comparator comparator) + { + elementSet = ImmutableSortedSet.emptySet(comparator); + } + + public Multiset.Entry firstEntry() + { + return null; + } + + public Multiset.Entry lastEntry() + { + return null; + } + + public int count(@Nullable Object element) + { + return 0; + } + + public boolean containsAll(Collection targets) + { + return targets.isEmpty(); + } + + public int size() + { + return 0; + } + + public ImmutableSortedSet elementSet() + { + return elementSet; + } + + Multiset.Entry getEntry(int index) + { + throw new AssertionError("should never be called"); + } + + public ImmutableSortedMultiset headMultiset(E upperBound, BoundType boundType) + { + Preconditions.checkNotNull(upperBound); + Preconditions.checkNotNull(boundType); + return this; + } + + public ImmutableSortedMultiset tailMultiset(E lowerBound, BoundType boundType) + { + Preconditions.checkNotNull(lowerBound); + Preconditions.checkNotNull(boundType); + return this; + } + + public UnmodifiableIterator iterator() + { + return Iterators.emptyIterator(); + } + + public boolean equals(@Nullable Object object) + { + if ((object instanceof Multiset)) { + Multiset other = (Multiset)object; + return other.isEmpty(); + } + return false; + } + + boolean isPartialView() + { + return false; + } + + int copyIntoArray(Object[] dst, int offset) + { + return offset; + } + + public ImmutableList asList() + { + return ImmutableList.of(); + } +} diff --git a/src/minecraft/com/google/common/collect/EmptyImmutableSortedSet.java b/src/minecraft/com/google/common/collect/EmptyImmutableSortedSet.java new file mode 100644 index 0000000..268550e --- /dev/null +++ b/src/minecraft/com/google/common/collect/EmptyImmutableSortedSet.java @@ -0,0 +1,130 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import java.util.Collection; +import java.util.Comparator; +import java.util.NoSuchElementException; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +class EmptyImmutableSortedSet + extends ImmutableSortedSet +{ + EmptyImmutableSortedSet(Comparator comparator) + { + super(comparator); + } + + public int size() + { + return 0; + } + + public boolean isEmpty() { + return true; + } + + public boolean contains(@Nullable Object target) { + return false; + } + + public boolean containsAll(Collection targets) { + return targets.isEmpty(); + } + + public UnmodifiableIterator iterator() { + return Iterators.emptyIterator(); + } + + @GwtIncompatible("NavigableSet") + public UnmodifiableIterator descendingIterator() { + return Iterators.emptyIterator(); + } + + boolean isPartialView() { + return false; + } + + public ImmutableList asList() { + return ImmutableList.of(); + } + + int copyIntoArray(Object[] dst, int offset) + { + return offset; + } + + public boolean equals(@Nullable Object object) { + if ((object instanceof Set)) { + Set that = (Set)object; + return that.isEmpty(); + } + return false; + } + + public int hashCode() { + return 0; + } + + public String toString() { + return "[]"; + } + + public E first() + { + throw new NoSuchElementException(); + } + + public E last() + { + throw new NoSuchElementException(); + } + + ImmutableSortedSet headSetImpl(E toElement, boolean inclusive) + { + return this; + } + + + ImmutableSortedSet subSetImpl(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) + { + return this; + } + + ImmutableSortedSet tailSetImpl(E fromElement, boolean inclusive) + { + return this; + } + + int indexOf(@Nullable Object target) { + return -1; + } + + ImmutableSortedSet createDescendingSet() + { + return new EmptyImmutableSortedSet(Ordering.from(comparator).reverse()); + } +} diff --git a/src/minecraft/com/google/common/collect/EnumBiMap.java b/src/minecraft/com/google/common/collect/EnumBiMap.java new file mode 100644 index 0000000..30abd26 --- /dev/null +++ b/src/minecraft/com/google/common/collect/EnumBiMap.java @@ -0,0 +1,148 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Collection; +import java.util.EnumMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public final class EnumBiMap, V extends Enum> + extends AbstractBiMap +{ + private transient Class keyType; + private transient Class valueType; + @GwtIncompatible("not needed in emulated source.") + private static final long serialVersionUID = 0L; + + public static , V extends Enum> EnumBiMap create(Class keyType, Class valueType) + { + return new EnumBiMap(keyType, valueType); + } + + + + + + + + + + + + public static , V extends Enum> EnumBiMap create(Map map) + { + EnumBiMap bimap = create(inferKeyType(map), inferValueType(map)); + bimap.putAll(map); + return bimap; + } + + private EnumBiMap(Class keyType, Class valueType) { + super(WellBehavedMap.wrap(new EnumMap(keyType)), WellBehavedMap.wrap(new EnumMap(valueType))); + + this.keyType = keyType; + this.valueType = valueType; + } + + static > Class inferKeyType(Map map) { + if ((map instanceof EnumBiMap)) { + return ((EnumBiMap)map).keyType(); + } + if ((map instanceof EnumHashBiMap)) { + return ((EnumHashBiMap)map).keyType(); + } + Preconditions.checkArgument(!map.isEmpty()); + return ((Enum)map.keySet().iterator().next()).getDeclaringClass(); + } + + private static > Class inferValueType(Map map) { + if ((map instanceof EnumBiMap)) { + return valueType; + } + Preconditions.checkArgument(!map.isEmpty()); + return ((Enum)map.values().iterator().next()).getDeclaringClass(); + } + + public Class keyType() + { + return keyType; + } + + public Class valueType() + { + return valueType; + } + + K checkKey(K key) + { + return (Enum)Preconditions.checkNotNull(key); + } + + V checkValue(V value) + { + return (Enum)Preconditions.checkNotNull(value); + } + + + + @GwtIncompatible("java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) + throws IOException + { + stream.defaultWriteObject(); + stream.writeObject(keyType); + stream.writeObject(valueType); + Serialization.writeMap(this, stream); + } + + @GwtIncompatible("java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException + { + stream.defaultReadObject(); + keyType = ((Class)stream.readObject()); + valueType = ((Class)stream.readObject()); + setDelegates(WellBehavedMap.wrap(new EnumMap(keyType)), WellBehavedMap.wrap(new EnumMap(valueType))); + + + Serialization.populateMap(this, stream); + } +} diff --git a/src/minecraft/com/google/common/collect/EnumHashBiMap.java b/src/minecraft/com/google/common/collect/EnumHashBiMap.java new file mode 100644 index 0000000..786f9f8 --- /dev/null +++ b/src/minecraft/com/google/common/collect/EnumHashBiMap.java @@ -0,0 +1,127 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public final class EnumHashBiMap, V> + extends AbstractBiMap +{ + private transient Class keyType; + @GwtIncompatible("only needed in emulated source.") + private static final long serialVersionUID = 0L; + + public static , V> EnumHashBiMap create(Class keyType) + { + return new EnumHashBiMap(keyType); + } + + + + + + + + + + + + public static , V> EnumHashBiMap create(Map map) + { + EnumHashBiMap bimap = create(EnumBiMap.inferKeyType(map)); + bimap.putAll(map); + return bimap; + } + + private EnumHashBiMap(Class keyType) { + super(WellBehavedMap.wrap(new EnumMap(keyType)), Maps.newHashMapWithExpectedSize(((Enum[])keyType.getEnumConstants()).length)); + + + + this.keyType = keyType; + } + + + + K checkKey(K key) + { + return (Enum)Preconditions.checkNotNull(key); + } + + public V put(K key, @Nullable V value) { + return super.put(key, value); + } + + public V forcePut(K key, @Nullable V value) { + return super.forcePut(key, value); + } + + public Class keyType() + { + return keyType; + } + + + + @GwtIncompatible("java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) + throws IOException + { + stream.defaultWriteObject(); + stream.writeObject(keyType); + Serialization.writeMap(this, stream); + } + + @GwtIncompatible("java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException + { + stream.defaultReadObject(); + keyType = ((Class)stream.readObject()); + setDelegates(WellBehavedMap.wrap(new EnumMap(keyType)), new HashMap(((Enum[])keyType.getEnumConstants()).length * 3 / 2)); + + Serialization.populateMap(this, stream); + } +} diff --git a/src/minecraft/com/google/common/collect/EnumMultiset.java b/src/minecraft/com/google/common/collect/EnumMultiset.java new file mode 100644 index 0000000..240f36f --- /dev/null +++ b/src/minecraft/com/google/common/collect/EnumMultiset.java @@ -0,0 +1,104 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.EnumMap; +import java.util.Iterator; + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public final class EnumMultiset> + extends AbstractMapBasedMultiset +{ + private transient Class type; + @GwtIncompatible("Not needed in emulated source") + private static final long serialVersionUID = 0L; + + public static > EnumMultiset create(Class type) + { + return new EnumMultiset(type); + } + + + + + + + + + + public static > EnumMultiset create(Iterable elements) + { + Iterator iterator = elements.iterator(); + Preconditions.checkArgument(iterator.hasNext(), "EnumMultiset constructor passed empty Iterable"); + EnumMultiset multiset = new EnumMultiset(((Enum)iterator.next()).getDeclaringClass()); + Iterables.addAll(multiset, elements); + return multiset; + } + + + + + + + + public static > EnumMultiset create(Iterable elements, Class type) + { + EnumMultiset result = create(type); + Iterables.addAll(result, elements); + return result; + } + + + + private EnumMultiset(Class type) + { + super(WellBehavedMap.wrap(new EnumMap(type))); + this.type = type; + } + + @GwtIncompatible("java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + stream.writeObject(type); + Serialization.writeMultiset(this, stream); + } + + + + + @GwtIncompatible("java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException + { + stream.defaultReadObject(); + + Class localType = (Class)stream.readObject(); + type = localType; + setBackingMap(WellBehavedMap.wrap(new EnumMap(type))); + Serialization.populateMultiset(this, stream); + } +} diff --git a/src/minecraft/com/google/common/collect/EvictingQueue.java b/src/minecraft/com/google/common/collect/EvictingQueue.java new file mode 100644 index 0000000..72f888c --- /dev/null +++ b/src/minecraft/com/google/common/collect/EvictingQueue.java @@ -0,0 +1,124 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.ArrayDeque; +import java.util.Collection; +import java.util.Queue; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtIncompatible("java.util.ArrayDeque") +public final class EvictingQueue + extends ForwardingQueue + implements Serializable +{ + private final Queue delegate; + @VisibleForTesting + final int maxSize; + private static final long serialVersionUID = 0L; + + private EvictingQueue(int maxSize) + { + Preconditions.checkArgument(maxSize >= 0, "maxSize (%s) must >= 0", new Object[] { Integer.valueOf(maxSize) }); + delegate = new ArrayDeque(maxSize); + this.maxSize = maxSize; + } + + + + + + + public static EvictingQueue create(int maxSize) + { + return new EvictingQueue(maxSize); + } + + + + + + + public int remainingCapacity() + { + return maxSize - size(); + } + + protected Queue delegate() { + return delegate; + } + + + + + + + public boolean offer(E e) + { + return add(e); + } + + + + + + + public boolean add(E e) + { + Preconditions.checkNotNull(e); + if (maxSize == 0) { + return true; + } + if (size() == maxSize) { + delegate.remove(); + } + delegate.add(e); + return true; + } + + public boolean addAll(Collection collection) { + return standardAddAll(collection); + } + + public boolean contains(Object object) + { + return delegate().contains(Preconditions.checkNotNull(object)); + } + + public boolean remove(Object object) + { + return delegate().remove(Preconditions.checkNotNull(object)); + } +} diff --git a/src/minecraft/com/google/common/collect/ExplicitOrdering.java b/src/minecraft/com/google/common/collect/ExplicitOrdering.java new file mode 100644 index 0000000..39c3301 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ExplicitOrdering.java @@ -0,0 +1,76 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.io.Serializable; +import java.util.List; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true) +final class ExplicitOrdering + extends Ordering + implements Serializable +{ + final ImmutableMap rankMap; + private static final long serialVersionUID = 0L; + + ExplicitOrdering(List valuesInOrder) + { + this(buildRankMap(valuesInOrder)); + } + + ExplicitOrdering(ImmutableMap rankMap) { + this.rankMap = rankMap; + } + + public int compare(T left, T right) { + return rank(left) - rank(right); + } + + private int rank(T value) { + Integer rank = (Integer)rankMap.get(value); + if (rank == null) { + throw new Ordering.IncomparableValueException(value); + } + return rank.intValue(); + } + + private static ImmutableMap buildRankMap(List valuesInOrder) + { + ImmutableMap.Builder builder = ImmutableMap.builder(); + int rank = 0; + for (T value : valuesInOrder) { + builder.put(value, Integer.valueOf(rank++)); + } + return builder.build(); + } + + public boolean equals(@Nullable Object object) { + if ((object instanceof ExplicitOrdering)) { + ExplicitOrdering that = (ExplicitOrdering)object; + return rankMap.equals(rankMap); + } + return false; + } + + public int hashCode() { + return rankMap.hashCode(); + } + + public String toString() { + return "Ordering.explicit(" + rankMap.keySet() + ")"; + } +} diff --git a/src/minecraft/com/google/common/collect/FilteredEntryMultimap.java b/src/minecraft/com/google/common/collect/FilteredEntryMultimap.java new file mode 100644 index 0000000..e9b13af --- /dev/null +++ b/src/minecraft/com/google/common/collect/FilteredEntryMultimap.java @@ -0,0 +1,402 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +class FilteredEntryMultimap + extends AbstractMultimap + implements FilteredMultimap +{ + final Multimap unfiltered; + final Predicate> predicate; + + FilteredEntryMultimap(Multimap unfiltered, Predicate> predicate) + { + this.unfiltered = ((Multimap)Preconditions.checkNotNull(unfiltered)); + this.predicate = ((Predicate)Preconditions.checkNotNull(predicate)); + } + + public Multimap unfiltered() + { + return unfiltered; + } + + public Predicate> entryPredicate() + { + return predicate; + } + + public int size() + { + return entries().size(); + } + + private boolean satisfies(K key, V value) { + return predicate.apply(Maps.immutableEntry(key, value)); + } + + final class ValuePredicate implements Predicate + { + private final K key; + + ValuePredicate() { + this.key = key; + } + + public boolean apply(@Nullable V value) + { + return FilteredEntryMultimap.this.satisfies(key, value); + } + } + + static Collection filterCollection(Collection collection, Predicate predicate) + { + if ((collection instanceof Set)) { + return Sets.filter((Set)collection, predicate); + } + return Collections2.filter(collection, predicate); + } + + + public boolean containsKey(@Nullable Object key) + { + return asMap().get(key) != null; + } + + public Collection removeAll(@Nullable Object key) + { + return (Collection)Objects.firstNonNull(asMap().remove(key), unmodifiableEmptyCollection()); + } + + Collection unmodifiableEmptyCollection() + { + return (unfiltered instanceof SetMultimap) ? Collections.emptySet() : Collections.emptyList(); + } + + + + public void clear() + { + entries().clear(); + } + + public Collection get(K key) + { + return filterCollection(unfiltered.get(key), new ValuePredicate(key)); + } + + Collection> createEntries() + { + return filterCollection(unfiltered.entries(), predicate); + } + + Collection createValues() + { + return new FilteredMultimapValues(this); + } + + Iterator> entryIterator() + { + throw new AssertionError("should never be called"); + } + + Map> createAsMap() + { + return new AsMap(); + } + + public Set keySet() + { + return asMap().keySet(); + } + + boolean removeEntriesIf(Predicate>> predicate) { + Iterator>> entryIterator = unfiltered.asMap().entrySet().iterator(); + boolean changed = false; + while (entryIterator.hasNext()) { + Map.Entry> entry = (Map.Entry)entryIterator.next(); + K key = entry.getKey(); + Collection collection = filterCollection((Collection)entry.getValue(), new ValuePredicate(key)); + if ((!collection.isEmpty()) && (predicate.apply(Maps.immutableEntry(key, collection)))) { + if (collection.size() == ((Collection)entry.getValue()).size()) { + entryIterator.remove(); + } else { + collection.clear(); + } + changed = true; + } + } + return changed; + } + + class AsMap extends Maps.ImprovedAbstractMap> { + AsMap() {} + + public boolean containsKey(@Nullable Object key) { return get(key) != null; } + + + public void clear() + { + FilteredEntryMultimap.this.clear(); + } + + public Collection get(@Nullable Object key) + { + Collection result = (Collection)unfiltered.asMap().get(key); + if (result == null) { + return null; + } + + K k = key; + result = FilteredEntryMultimap.filterCollection(result, new FilteredEntryMultimap.ValuePredicate(FilteredEntryMultimap.this, k)); + return result.isEmpty() ? null : result; + } + + public Collection remove(@Nullable Object key) + { + Collection collection = (Collection)unfiltered.asMap().get(key); + if (collection == null) { + return null; + } + + K k = key; + List result = Lists.newArrayList(); + Iterator itr = collection.iterator(); + while (itr.hasNext()) { + V v = itr.next(); + if (FilteredEntryMultimap.this.satisfies(k, v)) { + itr.remove(); + result.add(v); + } + } + if (result.isEmpty()) + return null; + if ((unfiltered instanceof SetMultimap)) { + return Collections.unmodifiableSet(Sets.newLinkedHashSet(result)); + } + return Collections.unmodifiableList(result); + } + + + Set createKeySet() + { + new Maps.KeySet(this) + { + public boolean removeAll(Collection c) { + return removeEntriesIf(Maps.keyPredicateOnEntries(Predicates.in(c))); + } + + public boolean retainAll(Collection c) + { + return removeEntriesIf(Maps.keyPredicateOnEntries(Predicates.not(Predicates.in(c)))); + } + + public boolean remove(@Nullable Object o) + { + return remove(o) != null; + } + }; + } + + Set>> createEntrySet() + { + new Maps.EntrySet() + { + Map> map() { + return FilteredEntryMultimap.AsMap.this; + } + + public Iterator>> iterator() + { + new AbstractIterator() { + final Iterator>> backingIterator = unfiltered.asMap().entrySet().iterator(); + + + protected Map.Entry> computeNext() + { + while (backingIterator.hasNext()) { + Map.Entry> entry = (Map.Entry)backingIterator.next(); + K key = entry.getKey(); + Collection collection = FilteredEntryMultimap.filterCollection((Collection)entry.getValue(), new FilteredEntryMultimap.ValuePredicate(FilteredEntryMultimap.this, key)); + + if (!collection.isEmpty()) { + return Maps.immutableEntry(key, collection); + } + } + return (Map.Entry)endOfData(); + } + }; + } + + public boolean removeAll(Collection c) + { + return removeEntriesIf(Predicates.in(c)); + } + + public boolean retainAll(Collection c) + { + return removeEntriesIf(Predicates.not(Predicates.in(c))); + } + + public int size() + { + return Iterators.size(iterator()); + } + }; + } + + Collection> createValues() + { + new Maps.Values(this) + { + public boolean remove(@Nullable Object o) { + if ((o instanceof Collection)) { + Collection c = (Collection)o; + Iterator>> entryIterator = unfiltered.asMap().entrySet().iterator(); + + while (entryIterator.hasNext()) { + Map.Entry> entry = (Map.Entry)entryIterator.next(); + K key = entry.getKey(); + Collection collection = FilteredEntryMultimap.filterCollection((Collection)entry.getValue(), new FilteredEntryMultimap.ValuePredicate(FilteredEntryMultimap.this, key)); + + if ((!collection.isEmpty()) && (c.equals(collection))) { + if (collection.size() == ((Collection)entry.getValue()).size()) { + entryIterator.remove(); + } else { + collection.clear(); + } + return true; + } + } + } + return false; + } + + public boolean removeAll(Collection c) + { + return removeEntriesIf(Maps.valuePredicateOnEntries(Predicates.in(c))); + } + + public boolean retainAll(Collection c) + { + return removeEntriesIf(Maps.valuePredicateOnEntries(Predicates.not(Predicates.in(c)))); + } + }; + } + } + + Multiset createKeys() + { + return new Keys(); + } + + class Keys extends Multimaps.Keys { + Keys() { + super(); + } + + public int remove(@Nullable Object key, int occurrences) + { + CollectPreconditions.checkNonnegative(occurrences, "occurrences"); + if (occurrences == 0) { + return count(key); + } + Collection collection = (Collection)unfiltered.asMap().get(key); + if (collection == null) { + return 0; + } + + K k = key; + int oldCount = 0; + Iterator itr = collection.iterator(); + while (itr.hasNext()) { + V v = itr.next(); + if (FilteredEntryMultimap.this.satisfies(k, v)) { + oldCount++; + if (oldCount <= occurrences) { + itr.remove(); + } + } + } + return oldCount; + } + + public Set> entrySet() + { + new Multisets.EntrySet() + { + Multiset multiset() + { + return FilteredEntryMultimap.Keys.this; + } + + public Iterator> iterator() + { + return entryIterator(); + } + + public int size() + { + return keySet().size(); + } + + private boolean removeEntriesIf(final Predicate> predicate) { + FilteredEntryMultimap.this.removeEntriesIf(new Predicate() + { + public boolean apply(Map.Entry> entry) + { + return predicate.apply(Multisets.immutableEntry(entry.getKey(), ((Collection)entry.getValue()).size())); + } + }); + } + + + public boolean removeAll(Collection c) + { + return removeEntriesIf(Predicates.in(c)); + } + + public boolean retainAll(Collection c) + { + return removeEntriesIf(Predicates.not(Predicates.in(c))); + } + }; + } + } +} diff --git a/src/minecraft/com/google/common/collect/FilteredEntrySetMultimap.java b/src/minecraft/com/google/common/collect/FilteredEntrySetMultimap.java new file mode 100644 index 0000000..3d66dc2 --- /dev/null +++ b/src/minecraft/com/google/common/collect/FilteredEntrySetMultimap.java @@ -0,0 +1,67 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Predicate; +import java.util.Map.Entry; +import java.util.Set; + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +final class FilteredEntrySetMultimap + extends FilteredEntryMultimap + implements FilteredSetMultimap +{ + FilteredEntrySetMultimap(SetMultimap unfiltered, Predicate> predicate) + { + super(unfiltered, predicate); + } + + public SetMultimap unfiltered() + { + return (SetMultimap)unfiltered; + } + + public Set get(K key) + { + return (Set)super.get(key); + } + + public Set removeAll(Object key) + { + return (Set)super.removeAll(key); + } + + public Set replaceValues(K key, Iterable values) + { + return (Set)super.replaceValues(key, values); + } + + Set> createEntries() + { + return Sets.filter(unfiltered().entries(), entryPredicate()); + } + + public Set> entries() + { + return (Set)super.entries(); + } +} diff --git a/src/minecraft/com/google/common/collect/FilteredKeyListMultimap.java b/src/minecraft/com/google/common/collect/FilteredKeyListMultimap.java new file mode 100644 index 0000000..425fabd --- /dev/null +++ b/src/minecraft/com/google/common/collect/FilteredKeyListMultimap.java @@ -0,0 +1,57 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Predicate; +import java.util.List; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +final class FilteredKeyListMultimap + extends FilteredKeyMultimap + implements ListMultimap +{ + FilteredKeyListMultimap(ListMultimap unfiltered, Predicate keyPredicate) + { + super(unfiltered, keyPredicate); + } + + public ListMultimap unfiltered() + { + return (ListMultimap)super.unfiltered(); + } + + public List get(K key) + { + return (List)super.get(key); + } + + public List removeAll(@Nullable Object key) + { + return (List)super.removeAll(key); + } + + public List replaceValues(K key, Iterable values) + { + return (List)super.replaceValues(key, values); + } +} diff --git a/src/minecraft/com/google/common/collect/FilteredKeyMultimap.java b/src/minecraft/com/google/common/collect/FilteredKeyMultimap.java new file mode 100644 index 0000000..ed35279 --- /dev/null +++ b/src/minecraft/com/google/common/collect/FilteredKeyMultimap.java @@ -0,0 +1,218 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +class FilteredKeyMultimap + extends AbstractMultimap + implements FilteredMultimap +{ + final Multimap unfiltered; + final Predicate keyPredicate; + + FilteredKeyMultimap(Multimap unfiltered, Predicate keyPredicate) + { + this.unfiltered = ((Multimap)Preconditions.checkNotNull(unfiltered)); + this.keyPredicate = ((Predicate)Preconditions.checkNotNull(keyPredicate)); + } + + public Multimap unfiltered() + { + return unfiltered; + } + + public Predicate> entryPredicate() + { + return Maps.keyPredicateOnEntries(keyPredicate); + } + + public int size() + { + int size = 0; + for (Collection collection : asMap().values()) { + size += collection.size(); + } + return size; + } + + public boolean containsKey(@Nullable Object key) + { + if (unfiltered.containsKey(key)) + { + K k = key; + return keyPredicate.apply(k); + } + return false; + } + + public Collection removeAll(Object key) + { + return containsKey(key) ? unfiltered.removeAll(key) : unmodifiableEmptyCollection(); + } + + Collection unmodifiableEmptyCollection() { + if ((unfiltered instanceof SetMultimap)) { + return ImmutableSet.of(); + } + return ImmutableList.of(); + } + + + public void clear() + { + keySet().clear(); + } + + Set createKeySet() + { + return Sets.filter(unfiltered.keySet(), keyPredicate); + } + + public Collection get(K key) + { + if (keyPredicate.apply(key)) + return unfiltered.get(key); + if ((unfiltered instanceof SetMultimap)) { + return new AddRejectingSet(key); + } + return new AddRejectingList(key); + } + + static class AddRejectingSet extends ForwardingSet + { + final K key; + + AddRejectingSet(K key) { + this.key = key; + } + + public boolean add(V element) + { + throw new IllegalArgumentException("Key does not satisfy predicate: " + key); + } + + public boolean addAll(Collection collection) + { + Preconditions.checkNotNull(collection); + throw new IllegalArgumentException("Key does not satisfy predicate: " + key); + } + + protected Set delegate() + { + return Collections.emptySet(); + } + } + + static class AddRejectingList extends ForwardingList { + final K key; + + AddRejectingList(K key) { + this.key = key; + } + + public boolean add(V v) + { + add(0, v); + return true; + } + + public boolean addAll(Collection collection) + { + addAll(0, collection); + return true; + } + + public void add(int index, V element) + { + Preconditions.checkPositionIndex(index, 0); + throw new IllegalArgumentException("Key does not satisfy predicate: " + key); + } + + public boolean addAll(int index, Collection elements) + { + Preconditions.checkNotNull(elements); + Preconditions.checkPositionIndex(index, 0); + throw new IllegalArgumentException("Key does not satisfy predicate: " + key); + } + + protected List delegate() + { + return Collections.emptyList(); + } + } + + Iterator> entryIterator() + { + throw new AssertionError("should never be called"); + } + + Collection> createEntries() + { + return new Entries(); + } + + class Entries extends ForwardingCollection> { + Entries() {} + + protected Collection> delegate() { return Collections2.filter(unfiltered.entries(), entryPredicate()); } + + + + public boolean remove(@Nullable Object o) + { + if ((o instanceof Map.Entry)) { + Map.Entry entry = (Map.Entry)o; + if ((unfiltered.containsKey(entry.getKey())) && (keyPredicate.apply(entry.getKey()))) + { + + return unfiltered.remove(entry.getKey(), entry.getValue()); + } + } + return false; + } + } + + Collection createValues() + { + return new FilteredMultimapValues(this); + } + + Map> createAsMap() + { + return Maps.filterKeys(unfiltered.asMap(), keyPredicate); + } + + Multiset createKeys() + { + return Multisets.filter(unfiltered.keys(), keyPredicate); + } +} diff --git a/src/minecraft/com/google/common/collect/FilteredKeySetMultimap.java b/src/minecraft/com/google/common/collect/FilteredKeySetMultimap.java new file mode 100644 index 0000000..f6db5a3 --- /dev/null +++ b/src/minecraft/com/google/common/collect/FilteredKeySetMultimap.java @@ -0,0 +1,81 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Predicate; +import java.util.Map.Entry; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +final class FilteredKeySetMultimap + extends FilteredKeyMultimap + implements FilteredSetMultimap +{ + FilteredKeySetMultimap(SetMultimap unfiltered, Predicate keyPredicate) + { + super(unfiltered, keyPredicate); + } + + public SetMultimap unfiltered() + { + return (SetMultimap)unfiltered; + } + + public Set get(K key) + { + return (Set)super.get(key); + } + + public Set removeAll(Object key) + { + return (Set)super.removeAll(key); + } + + public Set replaceValues(K key, Iterable values) + { + return (Set)super.replaceValues(key, values); + } + + public Set> entries() + { + return (Set)super.entries(); + } + + + + Set> createEntries() { return new EntrySet(); } + + class EntrySet extends FilteredKeyMultimap.Entries implements Set> { + EntrySet() { super(); } + + public int hashCode() { + return Sets.hashCodeImpl(this); + } + + public boolean equals(@Nullable Object o) + { + return Sets.equalsImpl(this, o); + } + } +} diff --git a/src/minecraft/com/google/common/collect/FilteredMultimap.java b/src/minecraft/com/google/common/collect/FilteredMultimap.java new file mode 100644 index 0000000..49d3f09 --- /dev/null +++ b/src/minecraft/com/google/common/collect/FilteredMultimap.java @@ -0,0 +1,14 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Predicate; +import java.util.Map.Entry; + +@GwtCompatible +abstract interface FilteredMultimap + extends Multimap +{ + public abstract Multimap unfiltered(); + + public abstract Predicate> entryPredicate(); +} diff --git a/src/minecraft/com/google/common/collect/FilteredMultimapValues.java b/src/minecraft/com/google/common/collect/FilteredMultimapValues.java new file mode 100644 index 0000000..f89a614 --- /dev/null +++ b/src/minecraft/com/google/common/collect/FilteredMultimapValues.java @@ -0,0 +1,94 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import java.util.AbstractCollection; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map.Entry; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +final class FilteredMultimapValues + extends AbstractCollection +{ + private final FilteredMultimap multimap; + + FilteredMultimapValues(FilteredMultimap multimap) + { + this.multimap = ((FilteredMultimap)Preconditions.checkNotNull(multimap)); + } + + public Iterator iterator() + { + return Maps.valueIterator(multimap.entries().iterator()); + } + + public boolean contains(@Nullable Object o) + { + return multimap.containsValue(o); + } + + public int size() + { + return multimap.size(); + } + + public boolean remove(@Nullable Object o) + { + Predicate> entryPredicate = multimap.entryPredicate(); + Iterator> unfilteredItr = multimap.unfiltered().entries().iterator(); + while (unfilteredItr.hasNext()) { + Map.Entry entry = (Map.Entry)unfilteredItr.next(); + if ((entryPredicate.apply(entry)) && (Objects.equal(entry.getValue(), o))) { + unfilteredItr.remove(); + return true; + } + } + return false; + } + + public boolean removeAll(Collection c) + { + return Iterables.removeIf(multimap.unfiltered().entries(), Predicates.and(multimap.entryPredicate(), Maps.valuePredicateOnEntries(Predicates.in(c)))); + } + + + + + public boolean retainAll(Collection c) + { + return Iterables.removeIf(multimap.unfiltered().entries(), Predicates.and(multimap.entryPredicate(), Maps.valuePredicateOnEntries(Predicates.not(Predicates.in(c))))); + } + + + + + public void clear() + { + multimap.clear(); + } +} diff --git a/src/minecraft/com/google/common/collect/FilteredSetMultimap.java b/src/minecraft/com/google/common/collect/FilteredSetMultimap.java new file mode 100644 index 0000000..53cc28f --- /dev/null +++ b/src/minecraft/com/google/common/collect/FilteredSetMultimap.java @@ -0,0 +1,10 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; + +@GwtCompatible +abstract interface FilteredSetMultimap + extends FilteredMultimap, SetMultimap +{ + public abstract SetMultimap unfiltered(); +} diff --git a/src/minecraft/com/google/common/collect/FluentIterable.java b/src/minecraft/com/google/common/collect/FluentIterable.java new file mode 100644 index 0000000..767d929 --- /dev/null +++ b/src/minecraft/com/google/common/collect/FluentIterable.java @@ -0,0 +1,481 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.SortedSet; +import javax.annotation.CheckReturnValue; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public abstract class FluentIterable + implements Iterable +{ + private final Iterable iterable; + + protected FluentIterable() + { + iterable = this; + } + + FluentIterable(Iterable iterable) { + this.iterable = ((Iterable)Preconditions.checkNotNull(iterable)); + } + + + + + public static FluentIterable from(final Iterable iterable) + { + (iterable instanceof FluentIterable) ? (FluentIterable)iterable : new FluentIterable(iterable) + { + public Iterator iterator() + { + return iterable.iterator(); + } + }; + } + + + + + + + + + @Deprecated + public static FluentIterable from(FluentIterable iterable) + { + return (FluentIterable)Preconditions.checkNotNull(iterable); + } + + + + + + public String toString() + { + return Iterables.toString(iterable); + } + + + + public final int size() + { + return Iterables.size(iterable); + } + + + + + public final boolean contains(@Nullable Object element) + { + return Iterables.contains(iterable, element); + } + + + + + + + + + + + + + + @CheckReturnValue + public final FluentIterable cycle() + { + return from(Iterables.cycle(iterable)); + } + + + + + @CheckReturnValue + public final FluentIterable filter(Predicate predicate) + { + return from(Iterables.filter(iterable, predicate)); + } + + + + + + @CheckReturnValue + @GwtIncompatible("Class.isInstance") + public final FluentIterable filter(Class type) + { + return from(Iterables.filter(iterable, type)); + } + + + + public final boolean anyMatch(Predicate predicate) + { + return Iterables.any(iterable, predicate); + } + + + + + public final boolean allMatch(Predicate predicate) + { + return Iterables.all(iterable, predicate); + } + + + + + + + + public final Optional firstMatch(Predicate predicate) + { + return Iterables.tryFind(iterable, predicate); + } + + + + + + + + + public final FluentIterable transform(Function function) + { + return from(Iterables.transform(iterable, function)); + } + + + + + + + + + + + + + public FluentIterable transformAndConcat(Function> function) + { + return from(Iterables.concat(transform(function))); + } + + + + + + + + public final Optional first() + { + Iterator iterator = iterable.iterator(); + return iterator.hasNext() ? Optional.of(iterator.next()) : Optional.absent(); + } + + + + + + + + + + + + + public final Optional last() + { + if ((iterable instanceof List)) { + List list = (List)iterable; + if (list.isEmpty()) { + return Optional.absent(); + } + return Optional.of(list.get(list.size() - 1)); + } + Iterator iterator = iterable.iterator(); + if (!iterator.hasNext()) { + return Optional.absent(); + } + + + + + + + if ((iterable instanceof SortedSet)) { + SortedSet sortedSet = (SortedSet)iterable; + return Optional.of(sortedSet.last()); + } + for (;;) + { + E current = iterator.next(); + if (!iterator.hasNext()) { + return Optional.of(current); + } + } + } + + + + + + + + + + + + + + + + + + @CheckReturnValue + public final FluentIterable skip(int numberToSkip) + { + return from(Iterables.skip(iterable, numberToSkip)); + } + + + + + + + + + + + @CheckReturnValue + public final FluentIterable limit(int size) + { + return from(Iterables.limit(iterable, size)); + } + + + + public final boolean isEmpty() + { + return !iterable.iterator().hasNext(); + } + + + + + + + public final ImmutableList toList() + { + return ImmutableList.copyOf(iterable); + } + + + + + + + + + + @Beta + public final ImmutableList toSortedList(Comparator comparator) + { + return Ordering.from(comparator).immutableSortedCopy(iterable); + } + + + + + + + public final ImmutableSet toSet() + { + return ImmutableSet.copyOf(iterable); + } + + + + + + + + + + + public final ImmutableSortedSet toSortedSet(Comparator comparator) + { + return ImmutableSortedSet.copyOf(comparator, iterable); + } + + + + + + + + + + + public final ImmutableMap toMap(Function valueFunction) + { + return Maps.toMap(iterable, valueFunction); + } + + + + + + + + + + + + + + + + + + + public final ImmutableListMultimap index(Function keyFunction) + { + return Multimaps.index(iterable, keyFunction); + } + + + + + + + + + + + + + public final ImmutableMap uniqueIndex(Function keyFunction) + { + return Maps.uniqueIndex(iterable, keyFunction); + } + + + + + + + + @GwtIncompatible("Array.newArray(Class, int)") + public final E[] toArray(Class type) + { + return Iterables.toArray(iterable, type); + } + + + + + + + + + public final > C copyInto(C collection) + { + Preconditions.checkNotNull(collection); + if ((iterable instanceof Collection)) { + collection.addAll(Collections2.cast(iterable)); + } else { + for (E item : iterable) { + collection.add(item); + } + } + return collection; + } + + + + + + + + + public final E get(int position) + { + return Iterables.get(iterable, position); + } + + private static class FromIterableFunction + implements Function, FluentIterable> + { + private FromIterableFunction() {} + + public FluentIterable apply(Iterable fromObject) + { + return FluentIterable.from(fromObject); + } + } +} diff --git a/src/minecraft/com/google/common/collect/ForwardingBlockingDeque.java b/src/minecraft/com/google/common/collect/ForwardingBlockingDeque.java new file mode 100644 index 0000000..20109e5 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingBlockingDeque.java @@ -0,0 +1,123 @@ +package com.google.common.collect; + +import java.util.Collection; +import java.util.concurrent.BlockingDeque; +import java.util.concurrent.TimeUnit; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class ForwardingBlockingDeque + extends ForwardingDeque + implements BlockingDeque +{ + protected ForwardingBlockingDeque() {} + + protected abstract BlockingDeque delegate(); + + public int remainingCapacity() + { + return delegate().remainingCapacity(); + } + + public void putFirst(E e) throws InterruptedException + { + delegate().putFirst(e); + } + + public void putLast(E e) throws InterruptedException + { + delegate().putLast(e); + } + + public boolean offerFirst(E e, long timeout, TimeUnit unit) throws InterruptedException + { + return delegate().offerFirst(e, timeout, unit); + } + + public boolean offerLast(E e, long timeout, TimeUnit unit) throws InterruptedException + { + return delegate().offerLast(e, timeout, unit); + } + + public E takeFirst() throws InterruptedException + { + return delegate().takeFirst(); + } + + public E takeLast() throws InterruptedException + { + return delegate().takeLast(); + } + + public E pollFirst(long timeout, TimeUnit unit) throws InterruptedException + { + return delegate().pollFirst(timeout, unit); + } + + public E pollLast(long timeout, TimeUnit unit) throws InterruptedException + { + return delegate().pollLast(timeout, unit); + } + + public void put(E e) throws InterruptedException + { + delegate().put(e); + } + + public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException + { + return delegate().offer(e, timeout, unit); + } + + public E take() throws InterruptedException + { + return delegate().take(); + } + + public E poll(long timeout, TimeUnit unit) throws InterruptedException + { + return delegate().poll(timeout, unit); + } + + public int drainTo(Collection c) + { + return delegate().drainTo(c); + } + + public int drainTo(Collection c, int maxElements) + { + return delegate().drainTo(c, maxElements); + } +} diff --git a/src/minecraft/com/google/common/collect/ForwardingCollection.java b/src/minecraft/com/google/common/collect/ForwardingCollection.java new file mode 100644 index 0000000..f155da1 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingCollection.java @@ -0,0 +1,255 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Objects; +import java.util.Collection; +import java.util.Iterator; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public abstract class ForwardingCollection + extends ForwardingObject + implements Collection +{ + protected ForwardingCollection() {} + + protected abstract Collection delegate(); + + public Iterator iterator() + { + return delegate().iterator(); + } + + public int size() + { + return delegate().size(); + } + + public boolean removeAll(Collection collection) + { + return delegate().removeAll(collection); + } + + public boolean isEmpty() + { + return delegate().isEmpty(); + } + + public boolean contains(Object object) + { + return delegate().contains(object); + } + + public boolean add(E element) + { + return delegate().add(element); + } + + public boolean remove(Object object) + { + return delegate().remove(object); + } + + public boolean containsAll(Collection collection) + { + return delegate().containsAll(collection); + } + + public boolean addAll(Collection collection) + { + return delegate().addAll(collection); + } + + public boolean retainAll(Collection collection) + { + return delegate().retainAll(collection); + } + + public void clear() + { + delegate().clear(); + } + + public Object[] toArray() + { + return delegate().toArray(); + } + + public T[] toArray(T[] array) + { + return delegate().toArray(array); + } + + + + + + + + protected boolean standardContains(@Nullable Object object) + { + return Iterators.contains(iterator(), object); + } + + + + + + + + protected boolean standardContainsAll(Collection collection) + { + return Collections2.containsAllImpl(this, collection); + } + + + + + + + + protected boolean standardAddAll(Collection collection) + { + return Iterators.addAll(this, collection.iterator()); + } + + + + + + + + + protected boolean standardRemove(@Nullable Object object) + { + Iterator iterator = iterator(); + while (iterator.hasNext()) { + if (Objects.equal(iterator.next(), object)) { + iterator.remove(); + return true; + } + } + return false; + } + + + + + + + + + protected boolean standardRemoveAll(Collection collection) + { + return Iterators.removeAll(iterator(), collection); + } + + + + + + + + + protected boolean standardRetainAll(Collection collection) + { + return Iterators.retainAll(iterator(), collection); + } + + + + + + + + + protected void standardClear() + { + Iterators.clear(iterator()); + } + + + + + + + + + protected boolean standardIsEmpty() + { + return !iterator().hasNext(); + } + + + + + + + + protected String standardToString() + { + return Collections2.toStringImpl(this); + } + + + + + + + + protected Object[] standardToArray() + { + Object[] newArray = new Object[size()]; + return toArray(newArray); + } + + + + + + + + protected T[] standardToArray(T[] array) + { + return ObjectArrays.toArrayImpl(this, array); + } +} diff --git a/src/minecraft/com/google/common/collect/ForwardingConcurrentMap.java b/src/minecraft/com/google/common/collect/ForwardingConcurrentMap.java new file mode 100644 index 0000000..172122f --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingConcurrentMap.java @@ -0,0 +1,60 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.concurrent.ConcurrentMap; + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public abstract class ForwardingConcurrentMap + extends ForwardingMap + implements ConcurrentMap +{ + protected ForwardingConcurrentMap() {} + + protected abstract ConcurrentMap delegate(); + + public V putIfAbsent(K key, V value) + { + return delegate().putIfAbsent(key, value); + } + + public boolean remove(Object key, Object value) + { + return delegate().remove(key, value); + } + + public V replace(K key, V value) + { + return delegate().replace(key, value); + } + + public boolean replace(K key, V oldValue, V newValue) + { + return delegate().replace(key, oldValue, newValue); + } +} diff --git a/src/minecraft/com/google/common/collect/ForwardingDeque.java b/src/minecraft/com/google/common/collect/ForwardingDeque.java new file mode 100644 index 0000000..1600de5 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingDeque.java @@ -0,0 +1,129 @@ +package com.google.common.collect; + +import java.util.Deque; +import java.util.Iterator; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class ForwardingDeque + extends ForwardingQueue + implements Deque +{ + protected ForwardingDeque() {} + + protected abstract Deque delegate(); + + public void addFirst(E e) + { + delegate().addFirst(e); + } + + public void addLast(E e) + { + delegate().addLast(e); + } + + public Iterator descendingIterator() + { + return delegate().descendingIterator(); + } + + public E getFirst() + { + return delegate().getFirst(); + } + + public E getLast() + { + return delegate().getLast(); + } + + public boolean offerFirst(E e) + { + return delegate().offerFirst(e); + } + + public boolean offerLast(E e) + { + return delegate().offerLast(e); + } + + public E peekFirst() + { + return delegate().peekFirst(); + } + + public E peekLast() + { + return delegate().peekLast(); + } + + public E pollFirst() + { + return delegate().pollFirst(); + } + + public E pollLast() + { + return delegate().pollLast(); + } + + public E pop() + { + return delegate().pop(); + } + + public void push(E e) + { + delegate().push(e); + } + + public E removeFirst() + { + return delegate().removeFirst(); + } + + public E removeLast() + { + return delegate().removeLast(); + } + + public boolean removeFirstOccurrence(Object o) + { + return delegate().removeFirstOccurrence(o); + } + + public boolean removeLastOccurrence(Object o) + { + return delegate().removeLastOccurrence(o); + } +} diff --git a/src/minecraft/com/google/common/collect/ForwardingImmutableCollection.java b/src/minecraft/com/google/common/collect/ForwardingImmutableCollection.java new file mode 100644 index 0000000..2bf4d8f --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingImmutableCollection.java @@ -0,0 +1,9 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; + +@GwtCompatible(emulated=true) +class ForwardingImmutableCollection +{ + private ForwardingImmutableCollection() {} +} diff --git a/src/minecraft/com/google/common/collect/ForwardingImmutableList.java b/src/minecraft/com/google/common/collect/ForwardingImmutableList.java new file mode 100644 index 0000000..75ef913 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingImmutableList.java @@ -0,0 +1,9 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; + +@GwtCompatible(emulated=true) +abstract class ForwardingImmutableList +{ + private ForwardingImmutableList() {} +} diff --git a/src/minecraft/com/google/common/collect/ForwardingImmutableMap.java b/src/minecraft/com/google/common/collect/ForwardingImmutableMap.java new file mode 100644 index 0000000..8a8ed63 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingImmutableMap.java @@ -0,0 +1,9 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; + +@GwtCompatible(emulated=true) +abstract class ForwardingImmutableMap +{ + private ForwardingImmutableMap() {} +} diff --git a/src/minecraft/com/google/common/collect/ForwardingImmutableSet.java b/src/minecraft/com/google/common/collect/ForwardingImmutableSet.java new file mode 100644 index 0000000..f1e7c20 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingImmutableSet.java @@ -0,0 +1,9 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; + +@GwtCompatible(emulated=true) +abstract class ForwardingImmutableSet +{ + private ForwardingImmutableSet() {} +} diff --git a/src/minecraft/com/google/common/collect/ForwardingIterator.java b/src/minecraft/com/google/common/collect/ForwardingIterator.java new file mode 100644 index 0000000..77e6c05 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingIterator.java @@ -0,0 +1,55 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Iterator; + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public abstract class ForwardingIterator + extends ForwardingObject + implements Iterator +{ + protected ForwardingIterator() {} + + protected abstract Iterator delegate(); + + public boolean hasNext() + { + return delegate().hasNext(); + } + + public T next() + { + return delegate().next(); + } + + public void remove() + { + delegate().remove(); + } +} diff --git a/src/minecraft/com/google/common/collect/ForwardingList.java b/src/minecraft/com/google/common/collect/ForwardingList.java new file mode 100644 index 0000000..ef0c2ba --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingList.java @@ -0,0 +1,239 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public abstract class ForwardingList + extends ForwardingCollection + implements List +{ + protected ForwardingList() {} + + protected abstract List delegate(); + + public void add(int index, E element) + { + delegate().add(index, element); + } + + public boolean addAll(int index, Collection elements) + { + return delegate().addAll(index, elements); + } + + public E get(int index) + { + return delegate().get(index); + } + + public int indexOf(Object element) + { + return delegate().indexOf(element); + } + + public int lastIndexOf(Object element) + { + return delegate().lastIndexOf(element); + } + + public ListIterator listIterator() + { + return delegate().listIterator(); + } + + public ListIterator listIterator(int index) + { + return delegate().listIterator(index); + } + + public E remove(int index) + { + return delegate().remove(index); + } + + public E set(int index, E element) + { + return delegate().set(index, element); + } + + public List subList(int fromIndex, int toIndex) + { + return delegate().subList(fromIndex, toIndex); + } + + public boolean equals(@Nullable Object object) { + return (object == this) || (delegate().equals(object)); + } + + public int hashCode() { + return delegate().hashCode(); + } + + + + + + + + + protected boolean standardAdd(E element) + { + add(size(), element); + return true; + } + + + + + + + + + + protected boolean standardAddAll(int index, Iterable elements) + { + return Lists.addAllImpl(this, index, elements); + } + + + + + + + + protected int standardIndexOf(@Nullable Object element) + { + return Lists.indexOfImpl(this, element); + } + + + + + + + + + protected int standardLastIndexOf(@Nullable Object element) + { + return Lists.lastIndexOfImpl(this, element); + } + + + + + + + + protected Iterator standardIterator() + { + return listIterator(); + } + + + + + + + + + protected ListIterator standardListIterator() + { + return listIterator(0); + } + + + + + + + + + @Beta + protected ListIterator standardListIterator(int start) + { + return Lists.listIteratorImpl(this, start); + } + + + + + + + @Beta + protected List standardSubList(int fromIndex, int toIndex) + { + return Lists.subListImpl(this, fromIndex, toIndex); + } + + + + + + + @Beta + protected boolean standardEquals(@Nullable Object object) + { + return Lists.equalsImpl(this, object); + } + + + + + + + @Beta + protected int standardHashCode() + { + return Lists.hashCodeImpl(this); + } +} diff --git a/src/minecraft/com/google/common/collect/ForwardingListIterator.java b/src/minecraft/com/google/common/collect/ForwardingListIterator.java new file mode 100644 index 0000000..29b4d13 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingListIterator.java @@ -0,0 +1,70 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.ListIterator; + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public abstract class ForwardingListIterator + extends ForwardingIterator + implements ListIterator +{ + protected ForwardingListIterator() {} + + protected abstract ListIterator delegate(); + + public void add(E element) + { + delegate().add(element); + } + + public boolean hasPrevious() + { + return delegate().hasPrevious(); + } + + public int nextIndex() + { + return delegate().nextIndex(); + } + + public E previous() + { + return delegate().previous(); + } + + public int previousIndex() + { + return delegate().previousIndex(); + } + + public void set(E element) + { + delegate().set(element); + } +} diff --git a/src/minecraft/com/google/common/collect/ForwardingListMultimap.java b/src/minecraft/com/google/common/collect/ForwardingListMultimap.java new file mode 100644 index 0000000..25f7ee3 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingListMultimap.java @@ -0,0 +1,54 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.List; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public abstract class ForwardingListMultimap + extends ForwardingMultimap + implements ListMultimap +{ + protected ForwardingListMultimap() {} + + protected abstract ListMultimap delegate(); + + public List get(@Nullable K key) + { + return delegate().get(key); + } + + public List removeAll(@Nullable Object key) { + return delegate().removeAll(key); + } + + public List replaceValues(K key, Iterable values) { + return delegate().replaceValues(key, values); + } +} diff --git a/src/minecraft/com/google/common/collect/ForwardingMap.java b/src/minecraft/com/google/common/collect/ForwardingMap.java new file mode 100644 index 0000000..85d5431 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingMap.java @@ -0,0 +1,309 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Objects; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public abstract class ForwardingMap + extends ForwardingObject + implements Map +{ + protected ForwardingMap() {} + + protected abstract Map delegate(); + + public int size() + { + return delegate().size(); + } + + public boolean isEmpty() + { + return delegate().isEmpty(); + } + + public V remove(Object object) + { + return delegate().remove(object); + } + + public void clear() + { + delegate().clear(); + } + + public boolean containsKey(@Nullable Object key) + { + return delegate().containsKey(key); + } + + public boolean containsValue(@Nullable Object value) + { + return delegate().containsValue(value); + } + + public V get(@Nullable Object key) + { + return delegate().get(key); + } + + public V put(K key, V value) + { + return delegate().put(key, value); + } + + public void putAll(Map map) + { + delegate().putAll(map); + } + + public Set keySet() + { + return delegate().keySet(); + } + + public Collection values() + { + return delegate().values(); + } + + public Set> entrySet() + { + return delegate().entrySet(); + } + + public boolean equals(@Nullable Object object) { + return (object == this) || (delegate().equals(object)); + } + + public int hashCode() { + return delegate().hashCode(); + } + + + + + + + + + protected void standardPutAll(Map map) + { + Maps.putAllImpl(this, map); + } + + + + + + + + + + + + @Beta + protected V standardRemove(@Nullable Object key) + { + Iterator> entryIterator = entrySet().iterator(); + while (entryIterator.hasNext()) { + Map.Entry entry = (Map.Entry)entryIterator.next(); + if (Objects.equal(entry.getKey(), key)) { + V value = entry.getValue(); + entryIterator.remove(); + return value; + } + } + return null; + } + + + + + + + + protected void standardClear() + { + Iterators.clear(entrySet().iterator()); + } + + + + + + + + + + + @Beta + protected class StandardKeySet + extends Maps.KeySet + { + public StandardKeySet() + { + super(); + } + } + + + + + + + + @Beta + protected boolean standardContainsKey(@Nullable Object key) + { + return Maps.containsKeyImpl(this, key); + } + + + + + + + + + + @Beta + protected class StandardValues + extends Maps.Values + { + public StandardValues() + { + super(); + } + } + + + + + + + + + protected boolean standardContainsValue(@Nullable Object value) + { + return Maps.containsValueImpl(this, value); + } + + + + + + + @Beta + protected abstract class StandardEntrySet + extends Maps.EntrySet + { + public StandardEntrySet() {} + + + + + + Map map() + { + return ForwardingMap.this; + } + } + + + + + + + + protected boolean standardIsEmpty() + { + return !entrySet().iterator().hasNext(); + } + + + + + + + + protected boolean standardEquals(@Nullable Object object) + { + return Maps.equalsImpl(this, object); + } + + + + + + + + protected int standardHashCode() + { + return Sets.hashCodeImpl(entrySet()); + } + + + + + + + + protected String standardToString() + { + return Maps.toStringImpl(this); + } +} diff --git a/src/minecraft/com/google/common/collect/ForwardingMapEntry.java b/src/minecraft/com/google/common/collect/ForwardingMapEntry.java new file mode 100644 index 0000000..b195313 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingMapEntry.java @@ -0,0 +1,128 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Objects; +import java.util.Map.Entry; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public abstract class ForwardingMapEntry + extends ForwardingObject + implements Map.Entry +{ + protected ForwardingMapEntry() {} + + protected abstract Map.Entry delegate(); + + public K getKey() + { + return delegate().getKey(); + } + + public V getValue() + { + return delegate().getValue(); + } + + public V setValue(V value) + { + return delegate().setValue(value); + } + + public boolean equals(@Nullable Object object) { + return delegate().equals(object); + } + + public int hashCode() { + return delegate().hashCode(); + } + + + + + + + + + protected boolean standardEquals(@Nullable Object object) + { + if ((object instanceof Map.Entry)) { + Map.Entry that = (Map.Entry)object; + return (Objects.equal(getKey(), that.getKey())) && (Objects.equal(getValue(), that.getValue())); + } + + return false; + } + + + + + + + + protected int standardHashCode() + { + K k = getKey(); + V v = getValue(); + return (k == null ? 0 : k.hashCode()) ^ (v == null ? 0 : v.hashCode()); + } + + + + + + + + @Beta + protected String standardToString() + { + return getKey() + "=" + getValue(); + } +} diff --git a/src/minecraft/com/google/common/collect/ForwardingMultimap.java b/src/minecraft/com/google/common/collect/ForwardingMultimap.java new file mode 100644 index 0000000..e2762f0 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingMultimap.java @@ -0,0 +1,143 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Collection; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public abstract class ForwardingMultimap + extends ForwardingObject + implements Multimap +{ + protected ForwardingMultimap() {} + + protected abstract Multimap delegate(); + + public Map> asMap() + { + return delegate().asMap(); + } + + public void clear() + { + delegate().clear(); + } + + public boolean containsEntry(@Nullable Object key, @Nullable Object value) + { + return delegate().containsEntry(key, value); + } + + public boolean containsKey(@Nullable Object key) + { + return delegate().containsKey(key); + } + + public boolean containsValue(@Nullable Object value) + { + return delegate().containsValue(value); + } + + public Collection> entries() + { + return delegate().entries(); + } + + public Collection get(@Nullable K key) + { + return delegate().get(key); + } + + public boolean isEmpty() + { + return delegate().isEmpty(); + } + + public Multiset keys() + { + return delegate().keys(); + } + + public Set keySet() + { + return delegate().keySet(); + } + + public boolean put(K key, V value) + { + return delegate().put(key, value); + } + + public boolean putAll(K key, Iterable values) + { + return delegate().putAll(key, values); + } + + public boolean putAll(Multimap multimap) + { + return delegate().putAll(multimap); + } + + public boolean remove(@Nullable Object key, @Nullable Object value) + { + return delegate().remove(key, value); + } + + public Collection removeAll(@Nullable Object key) + { + return delegate().removeAll(key); + } + + public Collection replaceValues(K key, Iterable values) + { + return delegate().replaceValues(key, values); + } + + public int size() + { + return delegate().size(); + } + + public Collection values() + { + return delegate().values(); + } + + public boolean equals(@Nullable Object object) { + return (object == this) || (delegate().equals(object)); + } + + public int hashCode() { + return delegate().hashCode(); + } +} diff --git a/src/minecraft/com/google/common/collect/ForwardingMultiset.java b/src/minecraft/com/google/common/collect/ForwardingMultiset.java new file mode 100644 index 0000000..66f50d2 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingMultiset.java @@ -0,0 +1,308 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Objects; +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public abstract class ForwardingMultiset + extends ForwardingCollection + implements Multiset +{ + protected ForwardingMultiset() {} + + protected abstract Multiset delegate(); + + public int count(Object element) + { + return delegate().count(element); + } + + public int add(E element, int occurrences) + { + return delegate().add(element, occurrences); + } + + public int remove(Object element, int occurrences) + { + return delegate().remove(element, occurrences); + } + + public Set elementSet() + { + return delegate().elementSet(); + } + + public Set> entrySet() + { + return delegate().entrySet(); + } + + public boolean equals(@Nullable Object object) { + return (object == this) || (delegate().equals(object)); + } + + public int hashCode() { + return delegate().hashCode(); + } + + public int setCount(E element, int count) + { + return delegate().setCount(element, count); + } + + public boolean setCount(E element, int oldCount, int newCount) + { + return delegate().setCount(element, oldCount, newCount); + } + + + + + + + + protected boolean standardContains(@Nullable Object object) + { + return count(object) > 0; + } + + + + + + + + protected void standardClear() + { + Iterators.clear(entrySet().iterator()); + } + + + + + + + @Beta + protected int standardCount(@Nullable Object object) + { + for (Multiset.Entry entry : entrySet()) { + if (Objects.equal(entry.getElement(), object)) { + return entry.getCount(); + } + } + return 0; + } + + + + + + + + protected boolean standardAdd(E element) + { + add(element, 1); + return true; + } + + + + + + + + + @Beta + protected boolean standardAddAll(Collection elementsToAdd) + { + return Multisets.addAllImpl(this, elementsToAdd); + } + + + + + + + + + protected boolean standardRemove(Object element) + { + return remove(element, 1) > 0; + } + + + + + + + + + + protected boolean standardRemoveAll(Collection elementsToRemove) + { + return Multisets.removeAllImpl(this, elementsToRemove); + } + + + + + + + + + + protected boolean standardRetainAll(Collection elementsToRetain) + { + return Multisets.retainAllImpl(this, elementsToRetain); + } + + + + + + + + + + protected int standardSetCount(E element, int count) + { + return Multisets.setCountImpl(this, element, count); + } + + + + + + + + + protected boolean standardSetCount(E element, int oldCount, int newCount) + { + return Multisets.setCountImpl(this, element, oldCount, newCount); + } + + + + + + + + @Beta + protected class StandardElementSet + extends Multisets.ElementSet + { + public StandardElementSet() {} + + + + + + + + Multiset multiset() + { + return ForwardingMultiset.this; + } + } + + + + + + + + protected Iterator standardIterator() + { + return Multisets.iteratorImpl(this); + } + + + + + + + + protected int standardSize() + { + return Multisets.sizeImpl(this); + } + + + + + + + + + protected boolean standardEquals(@Nullable Object object) + { + return Multisets.equalsImpl(this, object); + } + + + + + + + + protected int standardHashCode() + { + return entrySet().hashCode(); + } + + + + + + + + protected String standardToString() + { + return entrySet().toString(); + } +} diff --git a/src/minecraft/com/google/common/collect/ForwardingNavigableMap.java b/src/minecraft/com/google/common/collect/ForwardingNavigableMap.java new file mode 100644 index 0000000..161dbf4 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingNavigableMap.java @@ -0,0 +1,398 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.NavigableMap; +import java.util.NavigableSet; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.SortedMap; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class ForwardingNavigableMap + extends ForwardingSortedMap + implements NavigableMap +{ + protected ForwardingNavigableMap() {} + + protected abstract NavigableMap delegate(); + + public Map.Entry lowerEntry(K key) + { + return delegate().lowerEntry(key); + } + + + + + + protected Map.Entry standardLowerEntry(K key) + { + return headMap(key, false).lastEntry(); + } + + public K lowerKey(K key) + { + return delegate().lowerKey(key); + } + + + + + + protected K standardLowerKey(K key) + { + return Maps.keyOrNull(lowerEntry(key)); + } + + public Map.Entry floorEntry(K key) + { + return delegate().floorEntry(key); + } + + + + + + protected Map.Entry standardFloorEntry(K key) + { + return headMap(key, true).lastEntry(); + } + + public K floorKey(K key) + { + return delegate().floorKey(key); + } + + + + + + protected K standardFloorKey(K key) + { + return Maps.keyOrNull(floorEntry(key)); + } + + public Map.Entry ceilingEntry(K key) + { + return delegate().ceilingEntry(key); + } + + + + + + protected Map.Entry standardCeilingEntry(K key) + { + return tailMap(key, true).firstEntry(); + } + + public K ceilingKey(K key) + { + return delegate().ceilingKey(key); + } + + + + + + protected K standardCeilingKey(K key) + { + return Maps.keyOrNull(ceilingEntry(key)); + } + + public Map.Entry higherEntry(K key) + { + return delegate().higherEntry(key); + } + + + + + + protected Map.Entry standardHigherEntry(K key) + { + return tailMap(key, false).firstEntry(); + } + + public K higherKey(K key) + { + return delegate().higherKey(key); + } + + + + + + protected K standardHigherKey(K key) + { + return Maps.keyOrNull(higherEntry(key)); + } + + public Map.Entry firstEntry() + { + return delegate().firstEntry(); + } + + + + + + protected Map.Entry standardFirstEntry() + { + return (Map.Entry)Iterables.getFirst(entrySet(), null); + } + + + + + + protected K standardFirstKey() + { + Map.Entry entry = firstEntry(); + if (entry == null) { + throw new NoSuchElementException(); + } + return entry.getKey(); + } + + + public Map.Entry lastEntry() + { + return delegate().lastEntry(); + } + + + + + + protected Map.Entry standardLastEntry() + { + return (Map.Entry)Iterables.getFirst(descendingMap().entrySet(), null); + } + + + + + protected K standardLastKey() + { + Map.Entry entry = lastEntry(); + if (entry == null) { + throw new NoSuchElementException(); + } + return entry.getKey(); + } + + + public Map.Entry pollFirstEntry() + { + return delegate().pollFirstEntry(); + } + + + + + + protected Map.Entry standardPollFirstEntry() + { + return (Map.Entry)Iterators.pollNext(entrySet().iterator()); + } + + public Map.Entry pollLastEntry() + { + return delegate().pollLastEntry(); + } + + + + + + protected Map.Entry standardPollLastEntry() + { + return (Map.Entry)Iterators.pollNext(descendingMap().entrySet().iterator()); + } + + public NavigableMap descendingMap() + { + return delegate().descendingMap(); + } + + + + + + + + @Beta + protected class StandardDescendingMap + extends Maps.DescendingMap + { + public StandardDescendingMap() {} + + + + + + + NavigableMap forward() + { + return ForwardingNavigableMap.this; + } + + protected Iterator> entryIterator() + { + new Iterator() { + private Map.Entry toRemove = null; + private Map.Entry nextOrNull = forward().lastEntry(); + + public boolean hasNext() + { + return nextOrNull != null; + } + + public Map.Entry next() + { + if (!hasNext()) { + throw new NoSuchElementException(); + } + try { + return nextOrNull; + } finally { + toRemove = nextOrNull; + nextOrNull = forward().lowerEntry(nextOrNull.getKey()); + } + } + + public void remove() + { + CollectPreconditions.checkRemove(toRemove != null); + forward().remove(toRemove.getKey()); + toRemove = null; + } + }; + } + } + + public NavigableSet navigableKeySet() + { + return delegate().navigableKeySet(); + } + + + + + + + + @Beta + protected class StandardNavigableKeySet + extends Maps.NavigableKeySet + { + public StandardNavigableKeySet() + { + super(); + } + } + + public NavigableSet descendingKeySet() + { + return delegate().descendingKeySet(); + } + + + + + + + + @Beta + protected NavigableSet standardDescendingKeySet() + { + return descendingMap().navigableKeySet(); + } + + + + + + + + protected SortedMap standardSubMap(K fromKey, K toKey) + { + return subMap(fromKey, true, toKey, false); + } + + public NavigableMap subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) + { + return delegate().subMap(fromKey, fromInclusive, toKey, toInclusive); + } + + public NavigableMap headMap(K toKey, boolean inclusive) + { + return delegate().headMap(toKey, inclusive); + } + + public NavigableMap tailMap(K fromKey, boolean inclusive) + { + return delegate().tailMap(fromKey, inclusive); + } + + + + + + protected SortedMap standardHeadMap(K toKey) + { + return headMap(toKey, false); + } + + + + + + protected SortedMap standardTailMap(K fromKey) + { + return tailMap(fromKey, true); + } +} diff --git a/src/minecraft/com/google/common/collect/ForwardingNavigableSet.java b/src/minecraft/com/google/common/collect/ForwardingNavigableSet.java new file mode 100644 index 0000000..9261e2a --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingNavigableSet.java @@ -0,0 +1,238 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import java.util.Iterator; +import java.util.NavigableSet; +import java.util.SortedSet; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class ForwardingNavigableSet + extends ForwardingSortedSet + implements NavigableSet +{ + protected ForwardingNavigableSet() {} + + protected abstract NavigableSet delegate(); + + public E lower(E e) + { + return delegate().lower(e); + } + + + + + + protected E standardLower(E e) + { + return Iterators.getNext(headSet(e, false).descendingIterator(), null); + } + + public E floor(E e) + { + return delegate().floor(e); + } + + + + + + protected E standardFloor(E e) + { + return Iterators.getNext(headSet(e, true).descendingIterator(), null); + } + + public E ceiling(E e) + { + return delegate().ceiling(e); + } + + + + + + protected E standardCeiling(E e) + { + return Iterators.getNext(tailSet(e, true).iterator(), null); + } + + public E higher(E e) + { + return delegate().higher(e); + } + + + + + + protected E standardHigher(E e) + { + return Iterators.getNext(tailSet(e, false).iterator(), null); + } + + public E pollFirst() + { + return delegate().pollFirst(); + } + + + + + + protected E standardPollFirst() + { + return Iterators.pollNext(iterator()); + } + + public E pollLast() + { + return delegate().pollLast(); + } + + + + + + protected E standardPollLast() + { + return Iterators.pollNext(descendingIterator()); + } + + protected E standardFirst() { + return iterator().next(); + } + + protected E standardLast() { + return descendingIterator().next(); + } + + public NavigableSet descendingSet() + { + return delegate().descendingSet(); + } + + + + + + + + + @Beta + protected class StandardDescendingSet + extends Sets.DescendingSet + { + public StandardDescendingSet() + { + super(); + } + } + + public Iterator descendingIterator() + { + return delegate().descendingIterator(); + } + + + + + + public NavigableSet subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) + { + return delegate().subSet(fromElement, fromInclusive, toElement, toInclusive); + } + + + + + + + + + + @Beta + protected NavigableSet standardSubSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) + { + return tailSet(fromElement, fromInclusive).headSet(toElement, toInclusive); + } + + + + + + + + protected SortedSet standardSubSet(E fromElement, E toElement) + { + return subSet(fromElement, true, toElement, false); + } + + public NavigableSet headSet(E toElement, boolean inclusive) + { + return delegate().headSet(toElement, inclusive); + } + + + + + + + protected SortedSet standardHeadSet(E toElement) + { + return headSet(toElement, false); + } + + public NavigableSet tailSet(E fromElement, boolean inclusive) + { + return delegate().tailSet(fromElement, inclusive); + } + + + + + + + protected SortedSet standardTailSet(E fromElement) + { + return tailSet(fromElement, true); + } +} diff --git a/src/minecraft/com/google/common/collect/ForwardingObject.java b/src/minecraft/com/google/common/collect/ForwardingObject.java new file mode 100644 index 0000000..86394ea --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingObject.java @@ -0,0 +1,74 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public abstract class ForwardingObject +{ + protected ForwardingObject() {} + + protected abstract Object delegate(); + + public String toString() + { + return delegate().toString(); + } +} diff --git a/src/minecraft/com/google/common/collect/ForwardingQueue.java b/src/minecraft/com/google/common/collect/ForwardingQueue.java new file mode 100644 index 0000000..6192f9e --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingQueue.java @@ -0,0 +1,121 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.NoSuchElementException; +import java.util.Queue; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public abstract class ForwardingQueue + extends ForwardingCollection + implements Queue +{ + protected ForwardingQueue() {} + + protected abstract Queue delegate(); + + public boolean offer(E o) + { + return delegate().offer(o); + } + + public E poll() + { + return delegate().poll(); + } + + public E remove() + { + return delegate().remove(); + } + + public E peek() + { + return delegate().peek(); + } + + public E element() + { + return delegate().element(); + } + + + + + + + protected boolean standardOffer(E e) + { + try + { + return add(e); + } catch (IllegalStateException caught) {} + return false; + } + + + + + + + + protected E standardPeek() + { + try + { + return element(); + } catch (NoSuchElementException caught) {} + return null; + } + + + + + + + + protected E standardPoll() + { + try + { + return remove(); + } catch (NoSuchElementException caught) {} + return null; + } +} diff --git a/src/minecraft/com/google/common/collect/ForwardingSet.java b/src/minecraft/com/google/common/collect/ForwardingSet.java new file mode 100644 index 0000000..958570c --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingSet.java @@ -0,0 +1,100 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.Collection; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public abstract class ForwardingSet + extends ForwardingCollection + implements Set +{ + protected ForwardingSet() {} + + protected abstract Set delegate(); + + public boolean equals(@Nullable Object object) + { + return (object == this) || (delegate().equals(object)); + } + + public int hashCode() { + return delegate().hashCode(); + } + + + + + + + + + + protected boolean standardRemoveAll(Collection collection) + { + return Sets.removeAllImpl(this, (Collection)Preconditions.checkNotNull(collection)); + } + + + + + + + + protected boolean standardEquals(@Nullable Object object) + { + return Sets.equalsImpl(this, object); + } + + + + + + + + protected int standardHashCode() + { + return Sets.hashCodeImpl(this); + } +} diff --git a/src/minecraft/com/google/common/collect/ForwardingSetMultimap.java b/src/minecraft/com/google/common/collect/ForwardingSetMultimap.java new file mode 100644 index 0000000..a9b96db --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingSetMultimap.java @@ -0,0 +1,56 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Map.Entry; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public abstract class ForwardingSetMultimap + extends ForwardingMultimap + implements SetMultimap +{ + public ForwardingSetMultimap() {} + + protected abstract SetMultimap delegate(); + + public Set> entries() + { + return delegate().entries(); + } + + public Set get(@Nullable K key) { + return delegate().get(key); + } + + public Set removeAll(@Nullable Object key) { + return delegate().removeAll(key); + } + + public Set replaceValues(K key, Iterable values) { + return delegate().replaceValues(key, values); + } +} diff --git a/src/minecraft/com/google/common/collect/ForwardingSortedMap.java b/src/minecraft/com/google/common/collect/ForwardingSortedMap.java new file mode 100644 index 0000000..b895572 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingSortedMap.java @@ -0,0 +1,157 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.Comparator; +import java.util.NoSuchElementException; +import java.util.SortedMap; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public abstract class ForwardingSortedMap + extends ForwardingMap + implements SortedMap +{ + protected ForwardingSortedMap() {} + + protected abstract SortedMap delegate(); + + public Comparator comparator() + { + return delegate().comparator(); + } + + public K firstKey() + { + return delegate().firstKey(); + } + + public SortedMap headMap(K toKey) + { + return delegate().headMap(toKey); + } + + public K lastKey() + { + return delegate().lastKey(); + } + + public SortedMap subMap(K fromKey, K toKey) + { + return delegate().subMap(fromKey, toKey); + } + + public SortedMap tailMap(K fromKey) + { + return delegate().tailMap(fromKey); + } + + + + + + + @Beta + protected class StandardKeySet + extends Maps.SortedKeySet + { + public StandardKeySet() + { + super(); + } + } + + + private int unsafeCompare(Object k1, Object k2) + { + Comparator comparator = comparator(); + if (comparator == null) { + return ((Comparable)k1).compareTo(k2); + } + return comparator.compare(k1, k2); + } + + + + + + + + + + @Beta + protected boolean standardContainsKey(@Nullable Object key) + { + try + { + SortedMap self = this; + Object ceilingKey = self.tailMap(key).firstKey(); + return unsafeCompare(ceilingKey, key) == 0; + } catch (ClassCastException e) { + return false; + } catch (NoSuchElementException e) { + return false; + } catch (NullPointerException e) {} + return false; + } + + + + + + + + + @Beta + protected SortedMap standardSubMap(K fromKey, K toKey) + { + Preconditions.checkArgument(unsafeCompare(fromKey, toKey) <= 0, "fromKey must be <= toKey"); + return tailMap(fromKey).headMap(toKey); + } +} diff --git a/src/minecraft/com/google/common/collect/ForwardingSortedMultiset.java b/src/minecraft/com/google/common/collect/ForwardingSortedMultiset.java new file mode 100644 index 0000000..ae196b3 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingSortedMultiset.java @@ -0,0 +1,224 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NavigableSet; +import java.util.Set; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible(emulated=true) +public abstract class ForwardingSortedMultiset + extends ForwardingMultiset + implements SortedMultiset +{ + protected ForwardingSortedMultiset() {} + + protected abstract SortedMultiset delegate(); + + public NavigableSet elementSet() + { + return (NavigableSet)super.elementSet(); + } + + + + + + + + + + + protected class StandardElementSet + extends SortedMultisets.NavigableElementSet + { + public StandardElementSet() + { + super(); + } + } + + public Comparator comparator() + { + return delegate().comparator(); + } + + public SortedMultiset descendingMultiset() + { + return delegate().descendingMultiset(); + } + + + + + + + protected abstract class StandardDescendingMultiset + extends DescendingMultiset + { + public StandardDescendingMultiset() {} + + + + + + + SortedMultiset forwardMultiset() + { + return ForwardingSortedMultiset.this; + } + } + + public Multiset.Entry firstEntry() + { + return delegate().firstEntry(); + } + + + + + + + protected Multiset.Entry standardFirstEntry() + { + Iterator> entryIterator = entrySet().iterator(); + if (!entryIterator.hasNext()) { + return null; + } + Multiset.Entry entry = (Multiset.Entry)entryIterator.next(); + return Multisets.immutableEntry(entry.getElement(), entry.getCount()); + } + + public Multiset.Entry lastEntry() + { + return delegate().lastEntry(); + } + + + + + + + + protected Multiset.Entry standardLastEntry() + { + Iterator> entryIterator = descendingMultiset().entrySet().iterator(); + + + if (!entryIterator.hasNext()) { + return null; + } + Multiset.Entry entry = (Multiset.Entry)entryIterator.next(); + return Multisets.immutableEntry(entry.getElement(), entry.getCount()); + } + + public Multiset.Entry pollFirstEntry() + { + return delegate().pollFirstEntry(); + } + + + + + + + protected Multiset.Entry standardPollFirstEntry() + { + Iterator> entryIterator = entrySet().iterator(); + if (!entryIterator.hasNext()) { + return null; + } + Multiset.Entry entry = (Multiset.Entry)entryIterator.next(); + entry = Multisets.immutableEntry(entry.getElement(), entry.getCount()); + entryIterator.remove(); + return entry; + } + + public Multiset.Entry pollLastEntry() + { + return delegate().pollLastEntry(); + } + + + + + + + + protected Multiset.Entry standardPollLastEntry() + { + Iterator> entryIterator = descendingMultiset().entrySet().iterator(); + + + if (!entryIterator.hasNext()) { + return null; + } + Multiset.Entry entry = (Multiset.Entry)entryIterator.next(); + entry = Multisets.immutableEntry(entry.getElement(), entry.getCount()); + entryIterator.remove(); + return entry; + } + + public SortedMultiset headMultiset(E upperBound, BoundType boundType) + { + return delegate().headMultiset(upperBound, boundType); + } + + + public SortedMultiset subMultiset(E lowerBound, BoundType lowerBoundType, E upperBound, BoundType upperBoundType) + { + return delegate().subMultiset(lowerBound, lowerBoundType, upperBound, upperBoundType); + } + + + + + + + + + + protected SortedMultiset standardSubMultiset(E lowerBound, BoundType lowerBoundType, E upperBound, BoundType upperBoundType) + { + return tailMultiset(lowerBound, lowerBoundType).headMultiset(upperBound, upperBoundType); + } + + public SortedMultiset tailMultiset(E lowerBound, BoundType boundType) + { + return delegate().tailMultiset(lowerBound, boundType); + } +} diff --git a/src/minecraft/com/google/common/collect/ForwardingSortedSet.java b/src/minecraft/com/google/common/collect/ForwardingSortedSet.java new file mode 100644 index 0000000..52ee664 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingSortedSet.java @@ -0,0 +1,166 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.SortedSet; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public abstract class ForwardingSortedSet + extends ForwardingSet + implements SortedSet +{ + protected ForwardingSortedSet() {} + + protected abstract SortedSet delegate(); + + public Comparator comparator() + { + return delegate().comparator(); + } + + public E first() + { + return delegate().first(); + } + + public SortedSet headSet(E toElement) + { + return delegate().headSet(toElement); + } + + public E last() + { + return delegate().last(); + } + + public SortedSet subSet(E fromElement, E toElement) + { + return delegate().subSet(fromElement, toElement); + } + + public SortedSet tailSet(E fromElement) + { + return delegate().tailSet(fromElement); + } + + + private int unsafeCompare(Object o1, Object o2) + { + Comparator comparator = comparator(); + return comparator == null ? ((Comparable)o1).compareTo(o2) : comparator.compare(o1, o2); + } + + + + + + + + + + @Beta + protected boolean standardContains(@Nullable Object object) + { + try + { + SortedSet self = this; + Object ceiling = self.tailSet(object).first(); + return unsafeCompare(ceiling, object) == 0; + } catch (ClassCastException e) { + return false; + } catch (NoSuchElementException e) { + return false; + } catch (NullPointerException e) {} + return false; + } + + + + + + + + + @Beta + protected boolean standardRemove(@Nullable Object object) + { + try + { + SortedSet self = this; + Iterator iterator = self.tailSet(object).iterator(); + if (iterator.hasNext()) { + Object ceiling = iterator.next(); + if (unsafeCompare(ceiling, object) == 0) { + iterator.remove(); + return true; + } + } + } catch (ClassCastException e) { + return false; + } catch (NullPointerException e) { + return false; + } + return false; + } + + + + + + + + @Beta + protected SortedSet standardSubSet(E fromElement, E toElement) + { + return tailSet(fromElement).headSet(toElement); + } +} diff --git a/src/minecraft/com/google/common/collect/ForwardingSortedSetMultimap.java b/src/minecraft/com/google/common/collect/ForwardingSortedSetMultimap.java new file mode 100644 index 0000000..0f7fd04 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingSortedSetMultimap.java @@ -0,0 +1,60 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Comparator; +import java.util.SortedSet; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public abstract class ForwardingSortedSetMultimap + extends ForwardingSetMultimap + implements SortedSetMultimap +{ + protected ForwardingSortedSetMultimap() {} + + protected abstract SortedSetMultimap delegate(); + + public SortedSet get(@Nullable K key) + { + return delegate().get(key); + } + + public SortedSet removeAll(@Nullable Object key) { + return delegate().removeAll(key); + } + + public SortedSet replaceValues(K key, Iterable values) + { + return delegate().replaceValues(key, values); + } + + public Comparator valueComparator() { + return delegate().valueComparator(); + } +} diff --git a/src/minecraft/com/google/common/collect/ForwardingTable.java b/src/minecraft/com/google/common/collect/ForwardingTable.java new file mode 100644 index 0000000..8bebcd9 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ForwardingTable.java @@ -0,0 +1,144 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Collection; +import java.util.Map; +import java.util.Set; + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public abstract class ForwardingTable + extends ForwardingObject + implements Table +{ + protected ForwardingTable() {} + + protected abstract Table delegate(); + + public Set> cellSet() + { + return delegate().cellSet(); + } + + public void clear() + { + delegate().clear(); + } + + public Map column(C columnKey) + { + return delegate().column(columnKey); + } + + public Set columnKeySet() + { + return delegate().columnKeySet(); + } + + public Map> columnMap() + { + return delegate().columnMap(); + } + + public boolean contains(Object rowKey, Object columnKey) + { + return delegate().contains(rowKey, columnKey); + } + + public boolean containsColumn(Object columnKey) + { + return delegate().containsColumn(columnKey); + } + + public boolean containsRow(Object rowKey) + { + return delegate().containsRow(rowKey); + } + + public boolean containsValue(Object value) + { + return delegate().containsValue(value); + } + + public V get(Object rowKey, Object columnKey) + { + return delegate().get(rowKey, columnKey); + } + + public boolean isEmpty() + { + return delegate().isEmpty(); + } + + public V put(R rowKey, C columnKey, V value) + { + return delegate().put(rowKey, columnKey, value); + } + + public void putAll(Table table) + { + delegate().putAll(table); + } + + public V remove(Object rowKey, Object columnKey) + { + return delegate().remove(rowKey, columnKey); + } + + public Map row(R rowKey) + { + return delegate().row(rowKey); + } + + public Set rowKeySet() + { + return delegate().rowKeySet(); + } + + public Map> rowMap() + { + return delegate().rowMap(); + } + + public int size() + { + return delegate().size(); + } + + public Collection values() + { + return delegate().values(); + } + + public boolean equals(Object obj) { + return (obj == this) || (delegate().equals(obj)); + } + + public int hashCode() { + return delegate().hashCode(); + } +} diff --git a/src/minecraft/com/google/common/collect/GeneralRange.java b/src/minecraft/com/google/common/collect/GeneralRange.java new file mode 100644 index 0000000..40cac38 --- /dev/null +++ b/src/minecraft/com/google/common/collect/GeneralRange.java @@ -0,0 +1,283 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.Comparator; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true) +final class GeneralRange + implements Serializable +{ + private final Comparator comparator; + private final boolean hasLowerBound; + @Nullable + private final T lowerEndpoint; + private final BoundType lowerBoundType; + private final boolean hasUpperBound; + @Nullable + private final T upperEndpoint; + private final BoundType upperBoundType; + private transient GeneralRange reverse; + + static GeneralRange from(Range range) + { + T lowerEndpoint = range.hasLowerBound() ? range.lowerEndpoint() : null; + BoundType lowerBoundType = range.hasLowerBound() ? range.lowerBoundType() : BoundType.OPEN; + + + T upperEndpoint = range.hasUpperBound() ? range.upperEndpoint() : null; + BoundType upperBoundType = range.hasUpperBound() ? range.upperBoundType() : BoundType.OPEN; + return new GeneralRange(Ordering.natural(), range.hasLowerBound(), lowerEndpoint, lowerBoundType, range.hasUpperBound(), upperEndpoint, upperBoundType); + } + + + + + static GeneralRange all(Comparator comparator) + { + return new GeneralRange(comparator, false, null, BoundType.OPEN, false, null, BoundType.OPEN); + } + + + + + + static GeneralRange downTo(Comparator comparator, @Nullable T endpoint, BoundType boundType) + { + return new GeneralRange(comparator, true, endpoint, boundType, false, null, BoundType.OPEN); + } + + + + + + static GeneralRange upTo(Comparator comparator, @Nullable T endpoint, BoundType boundType) + { + return new GeneralRange(comparator, false, null, BoundType.OPEN, true, endpoint, boundType); + } + + + + + + static GeneralRange range(Comparator comparator, @Nullable T lower, BoundType lowerType, @Nullable T upper, BoundType upperType) + { + return new GeneralRange(comparator, true, lower, lowerType, true, upper, upperType); + } + + + + + + + + + + + + + private GeneralRange(Comparator comparator, boolean hasLowerBound, @Nullable T lowerEndpoint, BoundType lowerBoundType, boolean hasUpperBound, @Nullable T upperEndpoint, BoundType upperBoundType) + { + this.comparator = ((Comparator)Preconditions.checkNotNull(comparator)); + this.hasLowerBound = hasLowerBound; + this.hasUpperBound = hasUpperBound; + this.lowerEndpoint = lowerEndpoint; + this.lowerBoundType = ((BoundType)Preconditions.checkNotNull(lowerBoundType)); + this.upperEndpoint = upperEndpoint; + this.upperBoundType = ((BoundType)Preconditions.checkNotNull(upperBoundType)); + + if (hasLowerBound) { + comparator.compare(lowerEndpoint, lowerEndpoint); + } + if (hasUpperBound) { + comparator.compare(upperEndpoint, upperEndpoint); + } + if ((hasLowerBound) && (hasUpperBound)) { + int cmp = comparator.compare(lowerEndpoint, upperEndpoint); + + Preconditions.checkArgument(cmp <= 0, "lowerEndpoint (%s) > upperEndpoint (%s)", new Object[] { lowerEndpoint, upperEndpoint }); + + if (cmp == 0) { + Preconditions.checkArgument((lowerBoundType != BoundType.OPEN ? 1 : 0) | (upperBoundType != BoundType.OPEN ? 1 : 0)); + } + } + } + + Comparator comparator() { + return comparator; + } + + boolean hasLowerBound() { + return hasLowerBound; + } + + boolean hasUpperBound() { + return hasUpperBound; + } + + boolean isEmpty() { + return ((hasUpperBound()) && (tooLow(getUpperEndpoint()))) || ((hasLowerBound()) && (tooHigh(getLowerEndpoint()))); + } + + boolean tooLow(@Nullable T t) + { + if (!hasLowerBound()) { + return false; + } + T lbound = getLowerEndpoint(); + int cmp = comparator.compare(t, lbound); + return (cmp < 0 ? 1 : 0) | (cmp == 0 ? 1 : 0) & (getLowerBoundType() == BoundType.OPEN ? 1 : 0); + } + + boolean tooHigh(@Nullable T t) { + if (!hasUpperBound()) { + return false; + } + T ubound = getUpperEndpoint(); + int cmp = comparator.compare(t, ubound); + return (cmp > 0 ? 1 : 0) | (cmp == 0 ? 1 : 0) & (getUpperBoundType() == BoundType.OPEN ? 1 : 0); + } + + boolean contains(@Nullable T t) { + return (!tooLow(t)) && (!tooHigh(t)); + } + + + + GeneralRange intersect(GeneralRange other) + { + Preconditions.checkNotNull(other); + Preconditions.checkArgument(comparator.equals(comparator)); + + boolean hasLowBound = hasLowerBound; + + T lowEnd = getLowerEndpoint(); + BoundType lowType = getLowerBoundType(); + if (!hasLowerBound()) { + hasLowBound = hasLowerBound; + lowEnd = other.getLowerEndpoint(); + lowType = other.getLowerBoundType(); + } else if (other.hasLowerBound()) { + int cmp = comparator.compare(getLowerEndpoint(), other.getLowerEndpoint()); + if ((cmp < 0) || ((cmp == 0) && (other.getLowerBoundType() == BoundType.OPEN))) { + lowEnd = other.getLowerEndpoint(); + lowType = other.getLowerBoundType(); + } + } + + boolean hasUpBound = hasUpperBound; + + T upEnd = getUpperEndpoint(); + BoundType upType = getUpperBoundType(); + if (!hasUpperBound()) { + hasUpBound = hasUpperBound; + upEnd = other.getUpperEndpoint(); + upType = other.getUpperBoundType(); + } else if (other.hasUpperBound()) { + int cmp = comparator.compare(getUpperEndpoint(), other.getUpperEndpoint()); + if ((cmp > 0) || ((cmp == 0) && (other.getUpperBoundType() == BoundType.OPEN))) { + upEnd = other.getUpperEndpoint(); + upType = other.getUpperBoundType(); + } + } + + if ((hasLowBound) && (hasUpBound)) { + int cmp = comparator.compare(lowEnd, upEnd); + if ((cmp > 0) || ((cmp == 0) && (lowType == BoundType.OPEN) && (upType == BoundType.OPEN))) + { + lowEnd = upEnd; + lowType = BoundType.OPEN; + upType = BoundType.CLOSED; + } + } + + return new GeneralRange(comparator, hasLowBound, lowEnd, lowType, hasUpBound, upEnd, upType); + } + + public boolean equals(@Nullable Object obj) + { + if ((obj instanceof GeneralRange)) { + GeneralRange r = (GeneralRange)obj; + return (comparator.equals(comparator)) && (hasLowerBound == hasLowerBound) && (hasUpperBound == hasUpperBound) && (getLowerBoundType().equals(r.getLowerBoundType())) && (getUpperBoundType().equals(r.getUpperBoundType())) && (Objects.equal(getLowerEndpoint(), r.getLowerEndpoint())) && (Objects.equal(getUpperEndpoint(), r.getUpperEndpoint())); + } + + + + + return false; + } + + public int hashCode() + { + return Objects.hashCode(new Object[] { comparator, getLowerEndpoint(), getLowerBoundType(), getUpperEndpoint(), getUpperBoundType() }); + } + + + + + + + GeneralRange reverse() + { + GeneralRange result = reverse; + if (result == null) { + result = new GeneralRange(Ordering.from(comparator).reverse(), hasUpperBound, getUpperEndpoint(), getUpperBoundType(), hasLowerBound, getLowerEndpoint(), getLowerBoundType()); + + + reverse = this; + return this.reverse = result; + } + return result; + } + + public String toString() + { + return comparator + ":" + (lowerBoundType == BoundType.CLOSED ? '[' : '(') + (hasLowerBound ? lowerEndpoint : "-∞") + ',' + (hasUpperBound ? upperEndpoint : "∞") + (upperBoundType == BoundType.CLOSED ? ']' : ')'); + } + + + + + + + + + T getLowerEndpoint() + { + return lowerEndpoint; + } + + BoundType getLowerBoundType() { + return lowerBoundType; + } + + T getUpperEndpoint() { + return upperEndpoint; + } + + BoundType getUpperBoundType() { + return upperBoundType; + } +} diff --git a/src/minecraft/com/google/common/collect/GenericMapMaker.java b/src/minecraft/com/google/common/collect/GenericMapMaker.java new file mode 100644 index 0000000..b67bc94 --- /dev/null +++ b/src/minecraft/com/google/common/collect/GenericMapMaker.java @@ -0,0 +1,141 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Equivalence; +import com.google.common.base.Function; +import com.google.common.base.Objects; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.TimeUnit; + + + + + +@Deprecated +@Beta +@GwtCompatible(emulated=true) +abstract class GenericMapMaker +{ + @GwtIncompatible("To be supported") + MapMaker.RemovalListener removalListener; + GenericMapMaker() {} + + @GwtIncompatible("To be supported") + abstract GenericMapMaker keyEquivalence(Equivalence paramEquivalence); + + public abstract GenericMapMaker initialCapacity(int paramInt); + + abstract GenericMapMaker maximumSize(int paramInt); + + public abstract GenericMapMaker concurrencyLevel(int paramInt); + + @GwtIncompatible("java.lang.ref.WeakReference") + public abstract GenericMapMaker weakKeys(); + + @GwtIncompatible("java.lang.ref.WeakReference") + public abstract GenericMapMaker weakValues(); + + @Deprecated + @GwtIncompatible("java.lang.ref.SoftReference") + public abstract GenericMapMaker softValues(); + + abstract GenericMapMaker expireAfterWrite(long paramLong, TimeUnit paramTimeUnit); + + @GwtIncompatible("To be supported") + abstract GenericMapMaker expireAfterAccess(long paramLong, TimeUnit paramTimeUnit); + + @GwtIncompatible("To be supported") + static enum NullListener + implements MapMaker.RemovalListener + { + INSTANCE; + + + + + + + + + + + + + + + + + + + + + + + + + private NullListener() {} + + + + + + + + + + + + + + + + + + + + + + + + + public void onRemoval(MapMaker.RemovalNotification notification) {} + } + + + + + + + + + + + + + + + + + + + + + + + + @GwtIncompatible("To be supported") + MapMaker.RemovalListener getRemovalListener() + { + return (MapMaker.RemovalListener)Objects.firstNonNull(removalListener, NullListener.INSTANCE); + } + + public abstract ConcurrentMap makeMap(); + + @GwtIncompatible("MapMakerInternalMap") + abstract MapMakerInternalMap makeCustomMap(); + + @Deprecated + abstract ConcurrentMap makeComputingMap(Function paramFunction); +} diff --git a/src/minecraft/com/google/common/collect/GwtTransient.java b/src/minecraft/com/google/common/collect/GwtTransient.java new file mode 100644 index 0000000..d515b4d --- /dev/null +++ b/src/minecraft/com/google/common/collect/GwtTransient.java @@ -0,0 +1,14 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.lang.annotation.Annotation; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({java.lang.annotation.ElementType.FIELD}) +@GwtCompatible +@interface GwtTransient {} diff --git a/src/minecraft/com/google/common/collect/HashBasedTable.java b/src/minecraft/com/google/common/collect/HashBasedTable.java new file mode 100644 index 0000000..c28ce7f --- /dev/null +++ b/src/minecraft/com/google/common/collect/HashBasedTable.java @@ -0,0 +1,146 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Supplier; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true) +public class HashBasedTable + extends StandardTable +{ + private static final long serialVersionUID = 0L; + + private static class Factory + implements Supplier>, Serializable + { + final int expectedSize; + private static final long serialVersionUID = 0L; + + Factory(int expectedSize) + { + this.expectedSize = expectedSize; + } + + public Map get() { + return Maps.newHashMapWithExpectedSize(expectedSize); + } + } + + + + + public static HashBasedTable create() + { + return new HashBasedTable(new HashMap(), new Factory(0)); + } + + + + + + + + + + + + public static HashBasedTable create(int expectedRows, int expectedCellsPerRow) + { + CollectPreconditions.checkNonnegative(expectedCellsPerRow, "expectedCellsPerRow"); + Map> backingMap = Maps.newHashMapWithExpectedSize(expectedRows); + + return new HashBasedTable(backingMap, new Factory(expectedCellsPerRow)); + } + + + + + + + + + + + public static HashBasedTable create(Table table) + { + HashBasedTable result = create(); + result.putAll(table); + return result; + } + + HashBasedTable(Map> backingMap, Factory factory) { + super(backingMap, factory); + } + + + + public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) + { + return super.contains(rowKey, columnKey); + } + + public boolean containsColumn(@Nullable Object columnKey) { + return super.containsColumn(columnKey); + } + + public boolean containsRow(@Nullable Object rowKey) { + return super.containsRow(rowKey); + } + + public boolean containsValue(@Nullable Object value) { + return super.containsValue(value); + } + + public V get(@Nullable Object rowKey, @Nullable Object columnKey) { + return super.get(rowKey, columnKey); + } + + public boolean equals(@Nullable Object obj) { + return super.equals(obj); + } + + public V remove(@Nullable Object rowKey, @Nullable Object columnKey) + { + return super.remove(rowKey, columnKey); + } +} diff --git a/src/minecraft/com/google/common/collect/HashBiMap.java b/src/minecraft/com/google/common/collect/HashBiMap.java new file mode 100644 index 0000000..ec747fa --- /dev/null +++ b/src/minecraft/com/google/common/collect/HashBiMap.java @@ -0,0 +1 @@ +null \ No newline at end of file diff --git a/src/minecraft/com/google/common/collect/HashMultimap.java b/src/minecraft/com/google/common/collect/HashMultimap.java new file mode 100644 index 0000000..4bbba93 --- /dev/null +++ b/src/minecraft/com/google/common/collect/HashMultimap.java @@ -0,0 +1,139 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +public final class HashMultimap + extends AbstractSetMultimap +{ + private static final int DEFAULT_VALUES_PER_KEY = 2; + @VisibleForTesting + transient int expectedValuesPerKey = 2; + + @GwtIncompatible("Not needed in emulated source") + private static final long serialVersionUID = 0L; + + + public static HashMultimap create() + { + return new HashMultimap(); + } + + + + + + + + + + + public static HashMultimap create(int expectedKeys, int expectedValuesPerKey) + { + return new HashMultimap(expectedKeys, expectedValuesPerKey); + } + + + + + + + + + public static HashMultimap create(Multimap multimap) + { + return new HashMultimap(multimap); + } + + private HashMultimap() { + super(new HashMap()); + } + + private HashMultimap(int expectedKeys, int expectedValuesPerKey) { + super(Maps.newHashMapWithExpectedSize(expectedKeys)); + Preconditions.checkArgument(expectedValuesPerKey >= 0); + this.expectedValuesPerKey = expectedValuesPerKey; + } + + private HashMultimap(Multimap multimap) { + super(Maps.newHashMapWithExpectedSize(multimap.keySet().size())); + + putAll(multimap); + } + + + + + + + + Set createCollection() + { + return Sets.newHashSetWithExpectedSize(expectedValuesPerKey); + } + + + + + @GwtIncompatible("java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) + throws IOException + { + stream.defaultWriteObject(); + stream.writeInt(expectedValuesPerKey); + Serialization.writeMultimap(this, stream); + } + + @GwtIncompatible("java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException + { + stream.defaultReadObject(); + expectedValuesPerKey = stream.readInt(); + int distinctKeys = Serialization.readCount(stream); + Map> map = Maps.newHashMapWithExpectedSize(distinctKeys); + setMap(map); + Serialization.populateMultimap(this, stream, distinctKeys); + } +} diff --git a/src/minecraft/com/google/common/collect/HashMultiset.java b/src/minecraft/com/google/common/collect/HashMultiset.java new file mode 100644 index 0000000..051276a --- /dev/null +++ b/src/minecraft/com/google/common/collect/HashMultiset.java @@ -0,0 +1,98 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.HashMap; + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +public final class HashMultiset + extends AbstractMapBasedMultiset +{ + @GwtIncompatible("Not needed in emulated source.") + private static final long serialVersionUID = 0L; + + public static HashMultiset create() + { + return new HashMultiset(); + } + + + + + + + + public static HashMultiset create(int distinctElements) + { + return new HashMultiset(distinctElements); + } + + + + + + + + + public static HashMultiset create(Iterable elements) + { + HashMultiset multiset = create(Multisets.inferDistinctElements(elements)); + + Iterables.addAll(multiset, elements); + return multiset; + } + + private HashMultiset() { + super(new HashMap()); + } + + private HashMultiset(int distinctElements) { + super(Maps.newHashMapWithExpectedSize(distinctElements)); + } + + + + @GwtIncompatible("java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) + throws IOException + { + stream.defaultWriteObject(); + Serialization.writeMultiset(this, stream); + } + + @GwtIncompatible("java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException + { + stream.defaultReadObject(); + int distinctElements = Serialization.readCount(stream); + setBackingMap(Maps.newHashMapWithExpectedSize(distinctElements)); + + Serialization.populateMultiset(this, stream, distinctElements); + } +} diff --git a/src/minecraft/com/google/common/collect/Hashing.java b/src/minecraft/com/google/common/collect/Hashing.java new file mode 100644 index 0000000..6dc869d --- /dev/null +++ b/src/minecraft/com/google/common/collect/Hashing.java @@ -0,0 +1,72 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +final class Hashing +{ + private static final int C1 = -862048943; + private static final int C2 = 461845907; + + private Hashing() {} + + static int smear(int hashCode) + { + return 461845907 * Integer.rotateLeft(hashCode * -862048943, 15); + } + + static int smearedHash(@Nullable Object o) { + return smear(o == null ? 0 : o.hashCode()); + } + + private static int MAX_TABLE_SIZE = 1073741824; + + + static int closedTableSize(int expectedEntries, double loadFactor) + { + expectedEntries = Math.max(expectedEntries, 2); + int tableSize = Integer.highestOneBit(expectedEntries); + + if (expectedEntries > (int)(loadFactor * tableSize)) { + tableSize <<= 1; + return tableSize > 0 ? tableSize : MAX_TABLE_SIZE; + } + return tableSize; + } + + static boolean needsResizing(int size, int tableSize, double loadFactor) { + return (size > loadFactor * tableSize) && (tableSize < MAX_TABLE_SIZE); + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableAsList.java b/src/minecraft/com/google/common/collect/ImmutableAsList.java new file mode 100644 index 0000000..66e24f4 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableAsList.java @@ -0,0 +1,84 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.io.Serializable; + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +abstract class ImmutableAsList + extends ImmutableList +{ + ImmutableAsList() {} + + abstract ImmutableCollection delegateCollection(); + + public boolean contains(Object target) + { + return delegateCollection().contains(target); + } + + public int size() + { + return delegateCollection().size(); + } + + public boolean isEmpty() + { + return delegateCollection().isEmpty(); + } + + boolean isPartialView() + { + return delegateCollection().isPartialView(); + } + + @GwtIncompatible("serialization") + static class SerializedForm implements Serializable + { + final ImmutableCollection collection; + private static final long serialVersionUID = 0L; + + SerializedForm(ImmutableCollection collection) { + this.collection = collection; + } + + Object readResolve() { return collection.asList(); } + } + + + @GwtIncompatible("serialization") + private void readObject(ObjectInputStream stream) + throws InvalidObjectException + { + throw new InvalidObjectException("Use SerializedForm"); + } + + @GwtIncompatible("serialization") + Object writeReplace() { + return new SerializedForm(delegateCollection()); + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableBiMap.java b/src/minecraft/com/google/common/collect/ImmutableBiMap.java new file mode 100644 index 0000000..6b73129 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableBiMap.java @@ -0,0 +1,270 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +public abstract class ImmutableBiMap + extends ImmutableMap + implements BiMap +{ + public static ImmutableBiMap of() + { + return EmptyImmutableBiMap.INSTANCE; + } + + + + public static ImmutableBiMap of(K k1, V v1) + { + return new SingletonImmutableBiMap(k1, v1); + } + + + + + + public static ImmutableBiMap of(K k1, V v1, K k2, V v2) + { + return new RegularImmutableBiMap(new ImmutableMapEntry.TerminalEntry[] { entryOf(k1, v1), entryOf(k2, v2) }); + } + + + + + + + public static ImmutableBiMap of(K k1, V v1, K k2, V v2, K k3, V v3) + { + return new RegularImmutableBiMap(new ImmutableMapEntry.TerminalEntry[] { entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3) }); + } + + + + + + + public static ImmutableBiMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) + { + return new RegularImmutableBiMap(new ImmutableMapEntry.TerminalEntry[] { entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4) }); + } + + + + + + + + public static ImmutableBiMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) + { + return new RegularImmutableBiMap(new ImmutableMapEntry.TerminalEntry[] { entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4), entryOf(k5, v5) }); + } + + + + + + + + public static Builder builder() + { + return new Builder(); + } + + + + + + + + + + + + + + + public static final class Builder + extends ImmutableMap.Builder + { + public Builder() {} + + + + + + + + + + + + + + + public Builder put(K key, V value) + { + super.put(key, value); + return this; + } + + + + + + + + public Builder putAll(Map map) + { + super.putAll(map); + return this; + } + + + + + + public ImmutableBiMap build() + { + switch (size) { + case 0: + return ImmutableBiMap.of(); + case 1: + return ImmutableBiMap.of(entries[0].getKey(), entries[0].getValue()); + } + return new RegularImmutableBiMap(size, entries); + } + } + + + + + + + + + + + + + + + + public static ImmutableBiMap copyOf(Map map) + { + if ((map instanceof ImmutableBiMap)) + { + ImmutableBiMap bimap = (ImmutableBiMap)map; + + + if (!bimap.isPartialView()) { + return bimap; + } + } + Map.Entry[] entries = (Map.Entry[])map.entrySet().toArray(EMPTY_ENTRY_ARRAY); + switch (entries.length) { + case 0: + return of(); + + case 1: + Map.Entry entry = entries[0]; + return of(entry.getKey(), entry.getValue()); + } + return new RegularImmutableBiMap(entries); + } + + + private static final Map.Entry[] EMPTY_ENTRY_ARRAY = new Map.Entry[0]; + + + + + + ImmutableBiMap() {} + + + + + public abstract ImmutableBiMap inverse(); + + + + + public ImmutableSet values() + { + return inverse().keySet(); + } + + + + + + + + @Deprecated + public V forcePut(K key, V value) + { + throw new UnsupportedOperationException(); + } + + + + + private static class SerializedForm + extends ImmutableMap.SerializedForm + { + private static final long serialVersionUID = 0L; + + + + + SerializedForm(ImmutableBiMap bimap) { super(); } + + Object readResolve() { + ImmutableBiMap.Builder builder = new ImmutableBiMap.Builder(); + return createMap(builder); + } + } + + Object writeReplace() + { + return new SerializedForm(this); + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableClassToInstanceMap.java b/src/minecraft/com/google/common/collect/ImmutableClassToInstanceMap.java new file mode 100644 index 0000000..2026f73 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableClassToInstanceMap.java @@ -0,0 +1,164 @@ +package com.google.common.collect; + +import com.google.common.base.Preconditions; +import com.google.common.primitives.Primitives; +import java.io.Serializable; +import java.util.Map; +import java.util.Map.Entry; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + +public final class ImmutableClassToInstanceMap + extends ForwardingMap, B> + implements ClassToInstanceMap, Serializable +{ + private final ImmutableMap, B> delegate; + + public static Builder builder() + { + return new Builder(); + } + + + + + + + + + + + + + + + + + + public static final class Builder + { + private final ImmutableMap.Builder, B> mapBuilder = ImmutableMap.builder(); + + + public Builder() {} + + + public Builder put(Class key, T value) + { + mapBuilder.put(key, value); + return this; + } + + + + + + + + + + + public Builder putAll(Map, ? extends T> map) + { + for (Map.Entry, ? extends T> entry : map.entrySet()) { + Class type = (Class)entry.getKey(); + T value = entry.getValue(); + mapBuilder.put(type, cast(type, value)); + } + return this; + } + + private static T cast(Class type, B value) { + return Primitives.wrap(type).cast(value); + } + + + + + + + public ImmutableClassToInstanceMap build() + { + return new ImmutableClassToInstanceMap(mapBuilder.build(), null); + } + } + + + + + + + + + + + + + + + public static ImmutableClassToInstanceMap copyOf(Map, ? extends S> map) + { + if ((map instanceof ImmutableClassToInstanceMap)) + { + + ImmutableClassToInstanceMap cast = (ImmutableClassToInstanceMap)map; + return cast; + } + return new Builder().putAll(map).build(); + } + + + + private ImmutableClassToInstanceMap(ImmutableMap, B> delegate) + { + this.delegate = delegate; + } + + protected Map, B> delegate() { + return delegate; + } + + + @Nullable + public T getInstance(Class type) + { + return delegate.get(Preconditions.checkNotNull(type)); + } + + + + + + + + @Deprecated + public T putInstance(Class type, T value) + { + throw new UnsupportedOperationException(); + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableCollection.java b/src/minecraft/com/google/common/collect/ImmutableCollection.java new file mode 100644 index 0000000..bbe975a --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableCollection.java @@ -0,0 +1,364 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.AbstractCollection; +import java.util.Collection; +import java.util.Iterator; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public abstract class ImmutableCollection + extends AbstractCollection + implements Serializable +{ + private transient ImmutableList asList; + + ImmutableCollection() {} + + public abstract UnmodifiableIterator iterator(); + + public final Object[] toArray() + { + int size = size(); + if (size == 0) { + return ObjectArrays.EMPTY_ARRAY; + } + Object[] result = new Object[size()]; + copyIntoArray(result, 0); + return result; + } + + public final T[] toArray(T[] other) + { + Preconditions.checkNotNull(other); + int size = size(); + if (other.length < size) { + other = ObjectArrays.newArray(other, size); + } else if (other.length > size) { + other[size] = null; + } + copyIntoArray(other, 0); + return other; + } + + public boolean contains(@Nullable Object object) + { + return (object != null) && (super.contains(object)); + } + + + + + + + + @Deprecated + public final boolean add(E e) + { + throw new UnsupportedOperationException(); + } + + + + + + + + @Deprecated + public final boolean remove(Object object) + { + throw new UnsupportedOperationException(); + } + + + + + + + + @Deprecated + public final boolean addAll(Collection newElements) + { + throw new UnsupportedOperationException(); + } + + + + + + + + @Deprecated + public final boolean removeAll(Collection oldElements) + { + throw new UnsupportedOperationException(); + } + + + + + + + + @Deprecated + public final boolean retainAll(Collection elementsToKeep) + { + throw new UnsupportedOperationException(); + } + + + + + + + + @Deprecated + public final void clear() + { + throw new UnsupportedOperationException(); + } + + + + + + + + + + + + public ImmutableList asList() + { + ImmutableList list = asList; + return list == null ? (this.asList = createAsList()) : list; + } + + ImmutableList createAsList() { + switch (size()) { + case 0: + return ImmutableList.of(); + case 1: + return ImmutableList.of(iterator().next()); + } + return new RegularImmutableAsList(this, toArray()); + } + + + + + + + abstract boolean isPartialView(); + + + + + + + int copyIntoArray(Object[] dst, int offset) + { + for (E e : this) { + dst[(offset++)] = e; + } + return offset; + } + + Object writeReplace() + { + return new ImmutableList.SerializedForm(toArray()); + } + + + + public static abstract class Builder + { + static final int DEFAULT_INITIAL_CAPACITY = 4; + + + static int expandedCapacity(int oldCapacity, int minCapacity) + { + if (minCapacity < 0) { + throw new AssertionError("cannot store more than MAX_VALUE elements"); + } + + int newCapacity = oldCapacity + (oldCapacity >> 1) + 1; + if (newCapacity < minCapacity) { + newCapacity = Integer.highestOneBit(minCapacity - 1) << 1; + } + if (newCapacity < 0) { + newCapacity = Integer.MAX_VALUE; + } + + return newCapacity; + } + + + + + + + + + + Builder() {} + + + + + + + + + public abstract Builder add(E paramE); + + + + + + + + + public Builder add(E... elements) + { + for (E element : elements) { + add(element); + } + return this; + } + + + + + + + + + + + + + public Builder addAll(Iterable elements) + { + for (E element : elements) { + add(element); + } + return this; + } + + + + + + + + + + + + + public Builder addAll(Iterator elements) + { + while (elements.hasNext()) { + add(elements.next()); + } + return this; + } + + + public abstract ImmutableCollection build(); + } + + + static abstract class ArrayBasedBuilder + extends ImmutableCollection.Builder + { + Object[] contents; + + int size; + + + ArrayBasedBuilder(int initialCapacity) + { + CollectPreconditions.checkNonnegative(initialCapacity, "initialCapacity"); + contents = new Object[initialCapacity]; + size = 0; + } + + + + + private void ensureCapacity(int minCapacity) + { + if (contents.length < minCapacity) { + contents = ObjectArrays.arraysCopyOf(contents, expandedCapacity(contents.length, minCapacity)); + } + } + + + public ArrayBasedBuilder add(E element) + { + Preconditions.checkNotNull(element); + ensureCapacity(size + 1); + contents[(size++)] = element; + return this; + } + + public ImmutableCollection.Builder add(E... elements) + { + ObjectArrays.checkElementsNotNull(elements); + ensureCapacity(size + elements.length); + System.arraycopy(elements, 0, contents, size, elements.length); + size += elements.length; + return this; + } + + public ImmutableCollection.Builder addAll(Iterable elements) + { + if ((elements instanceof Collection)) { + Collection collection = (Collection)elements; + ensureCapacity(size + collection.size()); + } + super.addAll(elements); + return this; + } + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableEntry.java b/src/minecraft/com/google/common/collect/ImmutableEntry.java new file mode 100644 index 0000000..57b6eec --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableEntry.java @@ -0,0 +1,50 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.io.Serializable; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true) +class ImmutableEntry + extends AbstractMapEntry + implements Serializable +{ + final K key; + final V value; + private static final long serialVersionUID = 0L; + + ImmutableEntry(@Nullable K key, @Nullable V value) + { + this.key = key; + this.value = value; + } + + @Nullable + public final K getKey() { return key; } + + @Nullable + public final V getValue() { + return value; + } + + public final V setValue(V value) { + throw new UnsupportedOperationException(); + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableEnumMap.java b/src/minecraft/com/google/common/collect/ImmutableEnumMap.java new file mode 100644 index 0000000..b9c7beb --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableEnumMap.java @@ -0,0 +1,149 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.EnumMap; +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +final class ImmutableEnumMap, V> + extends ImmutableMap +{ + private final transient EnumMap delegate; + + static , V> ImmutableMap asImmutable(EnumMap map) + { + switch (map.size()) { + case 0: + return ImmutableMap.of(); + case 1: + Map.Entry entry = (Map.Entry)Iterables.getOnlyElement(map.entrySet()); + return ImmutableMap.of(entry.getKey(), entry.getValue()); + } + + return new ImmutableEnumMap(map); + } + + + + private ImmutableEnumMap(EnumMap delegate) + { + this.delegate = delegate; + Preconditions.checkArgument(!delegate.isEmpty()); + } + + ImmutableSet createKeySet() + { + new ImmutableSet() + { + public boolean contains(Object object) + { + return delegate.containsKey(object); + } + + public int size() + { + return ImmutableEnumMap.this.size(); + } + + public UnmodifiableIterator iterator() + { + return Iterators.unmodifiableIterator(delegate.keySet().iterator()); + } + + boolean isPartialView() + { + return true; + } + }; + } + + public int size() + { + return delegate.size(); + } + + public boolean containsKey(@Nullable Object key) + { + return delegate.containsKey(key); + } + + public V get(Object key) + { + return delegate.get(key); + } + + ImmutableSet> createEntrySet() + { + new ImmutableMapEntrySet() + { + ImmutableMap map() + { + return ImmutableEnumMap.this; + } + + public UnmodifiableIterator> iterator() + { + new UnmodifiableIterator() { + private final Iterator> backingIterator = delegate.entrySet().iterator(); + + public boolean hasNext() + { + return backingIterator.hasNext(); + } + + public Map.Entry next() + { + Map.Entry entry = (Map.Entry)backingIterator.next(); + return Maps.immutableEntry(entry.getKey(), entry.getValue()); + } + }; + } + }; + } + + boolean isPartialView() + { + return false; + } + + Object writeReplace() + { + return new EnumSerializedForm(delegate); + } + + private static class EnumSerializedForm, V> implements Serializable + { + final EnumMap delegate; + private static final long serialVersionUID = 0L; + + EnumSerializedForm(EnumMap delegate) + { + this.delegate = delegate; + } + + Object readResolve() { return new ImmutableEnumMap(delegate, null); } + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableEnumSet.java b/src/minecraft/com/google/common/collect/ImmutableEnumSet.java new file mode 100644 index 0000000..f86c0b1 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableEnumSet.java @@ -0,0 +1,118 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.io.Serializable; +import java.util.Collection; +import java.util.EnumSet; + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +final class ImmutableEnumSet> + extends ImmutableSet +{ + private final transient EnumSet delegate; + private transient int hashCode; + + static > ImmutableSet asImmutable(EnumSet set) + { + switch (set.size()) { + case 0: + return ImmutableSet.of(); + case 1: + return ImmutableSet.of(Iterables.getOnlyElement(set)); + } + return new ImmutableEnumSet(set); + } + + + + + + + + + + + + private ImmutableEnumSet(EnumSet delegate) + { + this.delegate = delegate; + } + + boolean isPartialView() { + return false; + } + + public UnmodifiableIterator iterator() { + return Iterators.unmodifiableIterator(delegate.iterator()); + } + + public int size() + { + return delegate.size(); + } + + public boolean contains(Object object) { + return delegate.contains(object); + } + + public boolean containsAll(Collection collection) { + return delegate.containsAll(collection); + } + + public boolean isEmpty() { + return delegate.isEmpty(); + } + + public boolean equals(Object object) { + return (object == this) || (delegate.equals(object)); + } + + + public int hashCode() + { + int result = hashCode; + return result == 0 ? (this.hashCode = delegate.hashCode()) : result; + } + + public String toString() { + return delegate.toString(); + } + + Object writeReplace() + { + return new EnumSerializedForm(delegate); + } + + private static class EnumSerializedForm> implements Serializable + { + final EnumSet delegate; + private static final long serialVersionUID = 0L; + + EnumSerializedForm(EnumSet delegate) + { + this.delegate = delegate; + } + + Object readResolve() { + return new ImmutableEnumSet(delegate.clone(), null); + } + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableList.java b/src/minecraft/com/google/common/collect/ImmutableList.java new file mode 100644 index 0000000..e6cfd06 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableList.java @@ -0,0 +1,703 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.io.Serializable; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.RandomAccess; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +public abstract class ImmutableList + extends ImmutableCollection + implements List, RandomAccess +{ + private static final ImmutableList EMPTY = new RegularImmutableList(ObjectArrays.EMPTY_ARRAY); + + + + + + + + + public static ImmutableList of() + { + return EMPTY; + } + + + + + + + + + public static ImmutableList of(E element) + { + return new SingletonImmutableList(element); + } + + + + + + public static ImmutableList of(E e1, E e2) + { + return construct(new Object[] { e1, e2 }); + } + + + + + + public static ImmutableList of(E e1, E e2, E e3) + { + return construct(new Object[] { e1, e2, e3 }); + } + + + + + + public static ImmutableList of(E e1, E e2, E e3, E e4) + { + return construct(new Object[] { e1, e2, e3, e4 }); + } + + + + + + public static ImmutableList of(E e1, E e2, E e3, E e4, E e5) + { + return construct(new Object[] { e1, e2, e3, e4, e5 }); + } + + + + + + public static ImmutableList of(E e1, E e2, E e3, E e4, E e5, E e6) + { + return construct(new Object[] { e1, e2, e3, e4, e5, e6 }); + } + + + + + + + public static ImmutableList of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) + { + return construct(new Object[] { e1, e2, e3, e4, e5, e6, e7 }); + } + + + + + + + public static ImmutableList of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) + { + return construct(new Object[] { e1, e2, e3, e4, e5, e6, e7, e8 }); + } + + + + + + + public static ImmutableList of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) + { + return construct(new Object[] { e1, e2, e3, e4, e5, e6, e7, e8, e9 }); + } + + + + + + + public static ImmutableList of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) + { + return construct(new Object[] { e1, e2, e3, e4, e5, e6, e7, e8, e9, e10 }); + } + + + + + + + public static ImmutableList of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11) + { + return construct(new Object[] { e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11 }); + } + + + + + + + + + + + + public static ImmutableList of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11, E e12, E... others) + { + Object[] array = new Object[12 + others.length]; + array[0] = e1; + array[1] = e2; + array[2] = e3; + array[3] = e4; + array[4] = e5; + array[5] = e6; + array[6] = e7; + array[7] = e8; + array[8] = e9; + array[9] = e10; + array[10] = e11; + array[11] = e12; + System.arraycopy(others, 0, array, 12, others.length); + return construct(array); + } + + + + + + + + + public static ImmutableList copyOf(Iterable elements) + { + Preconditions.checkNotNull(elements); + return (elements instanceof Collection) ? copyOf(Collections2.cast(elements)) : copyOf(elements.iterator()); + } + + + + + + + + + + + + + + + + + + + + + + public static ImmutableList copyOf(Collection elements) + { + if ((elements instanceof ImmutableCollection)) + { + ImmutableList list = ((ImmutableCollection)elements).asList(); + return list.isPartialView() ? asImmutableList(list.toArray()) : list; + } + + + return construct(elements.toArray()); + } + + + + + + + public static ImmutableList copyOf(Iterator elements) + { + if (!elements.hasNext()) { + return of(); + } + E first = elements.next(); + if (!elements.hasNext()) { + return of(first); + } + return new Builder().add(first).addAll(elements).build(); + } + + + + + + + + + + + public static ImmutableList copyOf(E[] elements) + { + switch (elements.length) { + case 0: + return of(); + case 1: + return new SingletonImmutableList(elements[0]); + } + return new RegularImmutableList(ObjectArrays.checkElementsNotNull((Object[])elements.clone())); + } + + + + + private static ImmutableList construct(Object... elements) + { + return asImmutableList(ObjectArrays.checkElementsNotNull(elements)); + } + + + + + + static ImmutableList asImmutableList(Object[] elements) + { + return asImmutableList(elements, elements.length); + } + + + + + static ImmutableList asImmutableList(Object[] elements, int length) + { + switch (length) { + case 0: + return of(); + + case 1: + ImmutableList list = new SingletonImmutableList(elements[0]); + return list; + } + if (length < elements.length) { + elements = ObjectArrays.arraysCopyOf(elements, length); + } + return new RegularImmutableList(elements); + } + + + ImmutableList() {} + + + public UnmodifiableIterator iterator() + { + return listIterator(); + } + + public UnmodifiableListIterator listIterator() { + return listIterator(0); + } + + public UnmodifiableListIterator listIterator(int index) { + new AbstractIndexedListIterator(size(), index) + { + protected E get(int index) { + return ImmutableList.this.get(index); + } + }; + } + + public int indexOf(@Nullable Object object) + { + return object == null ? -1 : Lists.indexOfImpl(this, object); + } + + public int lastIndexOf(@Nullable Object object) + { + return object == null ? -1 : Lists.lastIndexOfImpl(this, object); + } + + public boolean contains(@Nullable Object object) + { + return indexOf(object) >= 0; + } + + + + + + + + + + public ImmutableList subList(int fromIndex, int toIndex) + { + Preconditions.checkPositionIndexes(fromIndex, toIndex, size()); + int length = toIndex - fromIndex; + switch (length) { + case 0: + return of(); + case 1: + return of(get(fromIndex)); + } + return subListUnchecked(fromIndex, toIndex); + } + + + + + + + ImmutableList subListUnchecked(int fromIndex, int toIndex) + { + return new SubList(fromIndex, toIndex - fromIndex); + } + + class SubList extends ImmutableList { + final transient int offset; + final transient int length; + + SubList(int offset, int length) { + this.offset = offset; + this.length = length; + } + + public int size() + { + return length; + } + + public E get(int index) + { + Preconditions.checkElementIndex(index, length); + return ImmutableList.this.get(index + offset); + } + + public ImmutableList subList(int fromIndex, int toIndex) + { + Preconditions.checkPositionIndexes(fromIndex, toIndex, length); + return ImmutableList.this.subList(fromIndex + offset, toIndex + offset); + } + + boolean isPartialView() + { + return true; + } + } + + + + + + + + @Deprecated + public final boolean addAll(int index, Collection newElements) + { + throw new UnsupportedOperationException(); + } + + + + + + + + @Deprecated + public final E set(int index, E element) + { + throw new UnsupportedOperationException(); + } + + + + + + + + @Deprecated + public final void add(int index, E element) + { + throw new UnsupportedOperationException(); + } + + + + + + + + @Deprecated + public final E remove(int index) + { + throw new UnsupportedOperationException(); + } + + + + + + public final ImmutableList asList() + { + return this; + } + + + int copyIntoArray(Object[] dst, int offset) + { + int size = size(); + for (int i = 0; i < size; i++) { + dst[(offset + i)] = get(i); + } + return offset + size; + } + + + + + + + + + public ImmutableList reverse() + { + return new ReverseImmutableList(this); + } + + private static class ReverseImmutableList extends ImmutableList { + private final transient ImmutableList forwardList; + + ReverseImmutableList(ImmutableList backingList) { + forwardList = backingList; + } + + private int reverseIndex(int index) { + return size() - 1 - index; + } + + private int reversePosition(int index) { + return size() - index; + } + + public ImmutableList reverse() { + return forwardList; + } + + public boolean contains(@Nullable Object object) { + return forwardList.contains(object); + } + + public int indexOf(@Nullable Object object) { + int index = forwardList.lastIndexOf(object); + return index >= 0 ? reverseIndex(index) : -1; + } + + public int lastIndexOf(@Nullable Object object) { + int index = forwardList.indexOf(object); + return index >= 0 ? reverseIndex(index) : -1; + } + + public ImmutableList subList(int fromIndex, int toIndex) { + Preconditions.checkPositionIndexes(fromIndex, toIndex, size()); + return forwardList.subList(reversePosition(toIndex), reversePosition(fromIndex)).reverse(); + } + + public E get(int index) + { + Preconditions.checkElementIndex(index, size()); + return forwardList.get(reverseIndex(index)); + } + + public int size() { + return forwardList.size(); + } + + boolean isPartialView() { + return forwardList.isPartialView(); + } + } + + public boolean equals(@Nullable Object obj) { + return Lists.equalsImpl(this, obj); + } + + public int hashCode() { + int hashCode = 1; + int n = size(); + for (int i = 0; i < n; i++) { + hashCode = 31 * hashCode + get(i).hashCode(); + + hashCode = hashCode ^ 0xFFFFFFFF ^ 0xFFFFFFFF; + } + + return hashCode; + } + + static class SerializedForm implements Serializable + { + final Object[] elements; + private static final long serialVersionUID = 0L; + + SerializedForm(Object[] elements) + { + this.elements = elements; + } + + Object readResolve() { return ImmutableList.copyOf(elements); } + } + + + private void readObject(ObjectInputStream stream) + throws InvalidObjectException + { + throw new InvalidObjectException("Use SerializedForm"); + } + + Object writeReplace() { + return new SerializedForm(toArray()); + } + + + + + public static Builder builder() + { + return new Builder(); + } + + + + + + + + + + + + + + + + + + + public static final class Builder + extends ImmutableCollection.ArrayBasedBuilder + { + public Builder() + { + this(4); + } + + Builder(int capacity) + { + super(); + } + + + + + + + + public Builder add(E element) + { + super.add(element); + return this; + } + + + + + + + + + public Builder addAll(Iterable elements) + { + super.addAll(elements); + return this; + } + + + + + + + + + public Builder add(E... elements) + { + super.add(elements); + return this; + } + + + + + + + + + public Builder addAll(Iterator elements) + { + super.addAll(elements); + return this; + } + + + + + public ImmutableList build() + { + return ImmutableList.asImmutableList(contents, size); + } + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableListMultimap.java b/src/minecraft/com/google/common/collect/ImmutableListMultimap.java new file mode 100644 index 0000000..598adb2 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableListMultimap.java @@ -0,0 +1,386 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Collection; +import java.util.Comparator; +import java.util.Map; +import java.util.Map.Entry; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +public class ImmutableListMultimap + extends ImmutableMultimap + implements ListMultimap +{ + private transient ImmutableListMultimap inverse; + @GwtIncompatible("Not needed in emulated source") + private static final long serialVersionUID = 0L; + + public static ImmutableListMultimap of() + { + return EmptyImmutableListMultimap.INSTANCE; + } + + + + public static ImmutableListMultimap of(K k1, V v1) + { + Builder builder = builder(); + + builder.put(k1, v1); + return builder.build(); + } + + + + public static ImmutableListMultimap of(K k1, V v1, K k2, V v2) + { + Builder builder = builder(); + + builder.put(k1, v1); + builder.put(k2, v2); + return builder.build(); + } + + + + + public static ImmutableListMultimap of(K k1, V v1, K k2, V v2, K k3, V v3) + { + Builder builder = builder(); + + builder.put(k1, v1); + builder.put(k2, v2); + builder.put(k3, v3); + return builder.build(); + } + + + + + public static ImmutableListMultimap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) + { + Builder builder = builder(); + + builder.put(k1, v1); + builder.put(k2, v2); + builder.put(k3, v3); + builder.put(k4, v4); + return builder.build(); + } + + + + + public static ImmutableListMultimap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) + { + Builder builder = builder(); + + builder.put(k1, v1); + builder.put(k2, v2); + builder.put(k3, v3); + builder.put(k4, v4); + builder.put(k5, v5); + return builder.build(); + } + + + + + + + public static Builder builder() + { + return new Builder(); + } + + + + + + + + + + + + public static final class Builder + extends ImmutableMultimap.Builder + { + public Builder() {} + + + + + + + + + + + + public Builder put(K key, V value) + { + super.put(key, value); + return this; + } + + + + + + + public Builder put(Map.Entry entry) + { + super.put(entry); + return this; + } + + public Builder putAll(K key, Iterable values) { + super.putAll(key, values); + return this; + } + + public Builder putAll(K key, V... values) { + super.putAll(key, values); + return this; + } + + public Builder putAll(Multimap multimap) + { + super.putAll(multimap); + return this; + } + + + + + + + public Builder orderKeysBy(Comparator keyComparator) + { + super.orderKeysBy(keyComparator); + return this; + } + + + + + + + public Builder orderValuesBy(Comparator valueComparator) + { + super.orderValuesBy(valueComparator); + return this; + } + + + + public ImmutableListMultimap build() + { + return (ImmutableListMultimap)super.build(); + } + } + + + + + + + + + + + + + + public static ImmutableListMultimap copyOf(Multimap multimap) + { + if (multimap.isEmpty()) { + return of(); + } + + + if ((multimap instanceof ImmutableListMultimap)) + { + ImmutableListMultimap kvMultimap = (ImmutableListMultimap)multimap; + + if (!kvMultimap.isPartialView()) { + return kvMultimap; + } + } + + ImmutableMap.Builder> builder = ImmutableMap.builder(); + int size = 0; + + + for (Map.Entry> entry : multimap.asMap().entrySet()) { + ImmutableList list = ImmutableList.copyOf((Collection)entry.getValue()); + if (!list.isEmpty()) { + builder.put(entry.getKey(), list); + size += list.size(); + } + } + + return new ImmutableListMultimap(builder.build(), size); + } + + ImmutableListMultimap(ImmutableMap> map, int size) { + super(map, size); + } + + + + + + + + + + public ImmutableList get(@Nullable K key) + { + ImmutableList list = (ImmutableList)map.get(key); + return list == null ? ImmutableList.of() : list; + } + + + + + + + + + + + + + + public ImmutableListMultimap inverse() + { + ImmutableListMultimap result = inverse; + return result == null ? (this.inverse = invert()) : result; + } + + private ImmutableListMultimap invert() { + Builder builder = builder(); + for (Map.Entry entry : entries()) { + builder.put(entry.getValue(), entry.getKey()); + } + ImmutableListMultimap invertedMultimap = builder.build(); + inverse = this; + return invertedMultimap; + } + + + + + + @Deprecated + public ImmutableList removeAll(Object key) + { + throw new UnsupportedOperationException(); + } + + + + + + + @Deprecated + public ImmutableList replaceValues(K key, Iterable values) + { + throw new UnsupportedOperationException(); + } + + + + @GwtIncompatible("java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) + throws IOException + { + stream.defaultWriteObject(); + Serialization.writeMultimap(this, stream); + } + + @GwtIncompatible("java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException + { + stream.defaultReadObject(); + int keyCount = stream.readInt(); + if (keyCount < 0) { + throw new InvalidObjectException("Invalid key count " + keyCount); + } + ImmutableMap.Builder> builder = ImmutableMap.builder(); + + int tmpSize = 0; + + for (int i = 0; i < keyCount; i++) { + Object key = stream.readObject(); + int valueCount = stream.readInt(); + if (valueCount <= 0) { + throw new InvalidObjectException("Invalid value count " + valueCount); + } + + Object[] array = new Object[valueCount]; + for (int j = 0; j < valueCount; j++) { + array[j] = stream.readObject(); + } + builder.put(key, ImmutableList.copyOf(array)); + tmpSize += valueCount; + } + ImmutableMap> tmpMap; + try + { + tmpMap = builder.build(); + } catch (IllegalArgumentException e) { + throw ((InvalidObjectException)new InvalidObjectException(e.getMessage()).initCause(e)); + } + + + ImmutableMultimap.FieldSettersHolder.MAP_FIELD_SETTER.set(this, tmpMap); + ImmutableMultimap.FieldSettersHolder.SIZE_FIELD_SETTER.set(this, tmpSize); + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableMap.java b/src/minecraft/com/google/common/collect/ImmutableMap.java new file mode 100644 index 0000000..020e957 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableMap.java @@ -0,0 +1,556 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.EnumMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +public abstract class ImmutableMap + implements Map, Serializable +{ + public static ImmutableMap of() + { + return ImmutableBiMap.of(); + } + + + + + + + public static ImmutableMap of(K k1, V v1) + { + return ImmutableBiMap.of(k1, v1); + } + + + + + + public static ImmutableMap of(K k1, V v1, K k2, V v2) + { + return new RegularImmutableMap(new ImmutableMapEntry.TerminalEntry[] { entryOf(k1, v1), entryOf(k2, v2) }); + } + + + + + + + public static ImmutableMap of(K k1, V v1, K k2, V v2, K k3, V v3) + { + return new RegularImmutableMap(new ImmutableMapEntry.TerminalEntry[] { entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3) }); + } + + + + + + + + public static ImmutableMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) + { + return new RegularImmutableMap(new ImmutableMapEntry.TerminalEntry[] { entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4) }); + } + + + + + + + + public static ImmutableMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) + { + return new RegularImmutableMap(new ImmutableMapEntry.TerminalEntry[] { entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4), entryOf(k5, v5) }); + } + + + + + + + + + + + static ImmutableMapEntry.TerminalEntry entryOf(K key, V value) + { + CollectPreconditions.checkEntryNotNull(key, value); + return new ImmutableMapEntry.TerminalEntry(key, value); + } + + + + + public static Builder builder() + { + return new Builder(); + } + + static void checkNoConflict(boolean safe, String conflictDescription, Map.Entry entry1, Map.Entry entry2) + { + if (!safe) { + throw new IllegalArgumentException("Multiple entries with same " + conflictDescription + ": " + entry1 + " and " + entry2); + } + } + + + + + + + + + + public static class Builder + { + ImmutableMapEntry.TerminalEntry[] entries; + + + + + + + + + int size; + + + + + + + + + public Builder() + { + this(4); + } + + Builder(int initialCapacity) + { + entries = new ImmutableMapEntry.TerminalEntry[initialCapacity]; + size = 0; + } + + private void ensureCapacity(int minCapacity) { + if (minCapacity > entries.length) { + entries = ((ImmutableMapEntry.TerminalEntry[])ObjectArrays.arraysCopyOf(entries, ImmutableCollection.Builder.expandedCapacity(entries.length, minCapacity))); + } + } + + + + + + public Builder put(K key, V value) + { + ensureCapacity(size + 1); + ImmutableMapEntry.TerminalEntry entry = ImmutableMap.entryOf(key, value); + + entries[(size++)] = entry; + return this; + } + + + + + + + + public Builder put(Map.Entry entry) + { + return put(entry.getKey(), entry.getValue()); + } + + + + + + + public Builder putAll(Map map) + { + ensureCapacity(size + map.size()); + for (Map.Entry entry : map.entrySet()) { + put(entry); + } + return this; + } + + + + + + + + + + + public ImmutableMap build() + { + switch (size) { + case 0: + return ImmutableMap.of(); + case 1: + return ImmutableMap.of(entries[0].getKey(), entries[0].getValue()); + } + return new RegularImmutableMap(size, entries); + } + } + + + + + + + + + + + + + + + public static ImmutableMap copyOf(Map map) + { + if (((map instanceof ImmutableMap)) && (!(map instanceof ImmutableSortedMap))) + { + + + + ImmutableMap kvMap = (ImmutableMap)map; + if (!kvMap.isPartialView()) { + return kvMap; + } + } else if ((map instanceof EnumMap)) { + return copyOfEnumMapUnsafe(map); + } + Map.Entry[] entries = (Map.Entry[])map.entrySet().toArray(EMPTY_ENTRY_ARRAY); + switch (entries.length) { + case 0: + return of(); + + case 1: + Map.Entry onlyEntry = entries[0]; + return of(onlyEntry.getKey(), onlyEntry.getValue()); + } + return new RegularImmutableMap(entries); + } + + + + private static ImmutableMap copyOfEnumMapUnsafe(Map map) + { + return copyOfEnumMap((EnumMap)map); + } + + private static , V> ImmutableMap copyOfEnumMap(Map original) + { + EnumMap copy = new EnumMap(original); + for (Map.Entry entry : copy.entrySet()) { + CollectPreconditions.checkEntryNotNull(entry.getKey(), entry.getValue()); + } + return ImmutableEnumMap.asImmutable(copy); + } + + private static final Map.Entry[] EMPTY_ENTRY_ARRAY = new Map.Entry[0]; + + private transient ImmutableSet> entrySet; + + private transient ImmutableSet keySet; + private transient ImmutableCollection values; + private transient ImmutableSetMultimap multimapView; + + ImmutableMap() {} + + @Deprecated + public final V put(K k, V v) + { + throw new UnsupportedOperationException(); + } + + + + + + + + @Deprecated + public final V remove(Object o) + { + throw new UnsupportedOperationException(); + } + + + + + + + + @Deprecated + public final void putAll(Map map) + { + throw new UnsupportedOperationException(); + } + + + + + + + + @Deprecated + public final void clear() + { + throw new UnsupportedOperationException(); + } + + public boolean isEmpty() + { + return size() == 0; + } + + public boolean containsKey(@Nullable Object key) + { + return get(key) != null; + } + + public boolean containsValue(@Nullable Object value) + { + return values().contains(value); + } + + + + + + public abstract V get(@Nullable Object paramObject); + + + + + + public ImmutableSet> entrySet() + { + ImmutableSet> result = entrySet; + return result == null ? (this.entrySet = createEntrySet()) : result; + } + + + + + abstract ImmutableSet> createEntrySet(); + + + + + public ImmutableSet keySet() + { + ImmutableSet result = keySet; + return result == null ? (this.keySet = createKeySet()) : result; + } + + ImmutableSet createKeySet() { + return new ImmutableMapKeySet(this); + } + + + + + + + + public ImmutableCollection values() + { + ImmutableCollection result = values; + return result == null ? (this.values = new ImmutableMapValues(this)) : result; + } + + + + + + + + + @Beta + public ImmutableSetMultimap asMultimap() + { + ImmutableSetMultimap result = multimapView; + return result == null ? (this.multimapView = createMultimapView()) : result; + } + + private ImmutableSetMultimap createMultimapView() { + ImmutableMap> map = viewMapValuesAsSingletonSets(); + return new ImmutableSetMultimap(map, map.size(), null); + } + + private ImmutableMap> viewMapValuesAsSingletonSets() { + return new MapViewOfValuesAsSingletonSets(this); + } + + private static final class MapViewOfValuesAsSingletonSets extends ImmutableMap> + { + private final ImmutableMap delegate; + + MapViewOfValuesAsSingletonSets(ImmutableMap delegate) { + this.delegate = ((ImmutableMap)Preconditions.checkNotNull(delegate)); + } + + public int size() { + return delegate.size(); + } + + public boolean containsKey(@Nullable Object key) { + return delegate.containsKey(key); + } + + public ImmutableSet get(@Nullable Object key) { + V outerValue = delegate.get(key); + return outerValue == null ? null : ImmutableSet.of(outerValue); + } + + boolean isPartialView() { + return false; + } + + ImmutableSet>> createEntrySet() { + new ImmutableMapEntrySet() { + ImmutableMap> map() { + return ImmutableMap.MapViewOfValuesAsSingletonSets.this; + } + + public UnmodifiableIterator>> iterator() + { + final Iterator> backingIterator = entrySet().iterator(); + new UnmodifiableIterator() { + public boolean hasNext() { + return backingIterator.hasNext(); + } + + public Map.Entry> next() { + final Map.Entry backingEntry = (Map.Entry)backingIterator.next(); + new AbstractMapEntry() { + public K getKey() { + return backingEntry.getKey(); + } + + public ImmutableSet getValue() { + return ImmutableSet.of(backingEntry.getValue()); + } + }; + } + }; + } + }; + } + } + + public boolean equals(@Nullable Object object) { + return Maps.equalsImpl(this, object); + } + + + abstract boolean isPartialView(); + + public int hashCode() + { + return entrySet().hashCode(); + } + + public String toString() { + return Maps.toStringImpl(this); + } + + static class SerializedForm + implements Serializable + { + private final Object[] keys; + private final Object[] values; + private static final long serialVersionUID = 0L; + + SerializedForm(ImmutableMap map) + { + keys = new Object[map.size()]; + values = new Object[map.size()]; + int i = 0; + for (Map.Entry entry : map.entrySet()) { + keys[i] = entry.getKey(); + values[i] = entry.getValue(); + i++; + } + } + + Object readResolve() { ImmutableMap.Builder builder = new ImmutableMap.Builder(); + return createMap(builder); + } + + Object createMap(ImmutableMap.Builder builder) { for (int i = 0; i < keys.length; i++) { + builder.put(keys[i], values[i]); + } + return builder.build(); + } + } + + Object writeReplace() + { + return new SerializedForm(this); + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableMapEntry.java b/src/minecraft/com/google/common/collect/ImmutableMapEntry.java new file mode 100644 index 0000000..a8eb842 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableMapEntry.java @@ -0,0 +1,72 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtIncompatible; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtIncompatible("unnecessary") +abstract class ImmutableMapEntry + extends ImmutableEntry +{ + ImmutableMapEntry(K key, V value) + { + super(key, value); + CollectPreconditions.checkEntryNotNull(key, value); + } + + ImmutableMapEntry(ImmutableMapEntry contents) { + super(contents.getKey(), contents.getValue()); + } + + @Nullable + abstract ImmutableMapEntry getNextInKeyBucket(); + + @Nullable + abstract ImmutableMapEntry getNextInValueBucket(); + + static final class TerminalEntry extends ImmutableMapEntry + { + TerminalEntry(ImmutableMapEntry contents) { + super(); + } + + TerminalEntry(K key, V value) { + super(value); + } + + @Nullable + ImmutableMapEntry getNextInKeyBucket() + { + return null; + } + + @Nullable + ImmutableMapEntry getNextInValueBucket() + { + return null; + } + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableMapEntrySet.java b/src/minecraft/com/google/common/collect/ImmutableMapEntrySet.java new file mode 100644 index 0000000..ab31151 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableMapEntrySet.java @@ -0,0 +1,75 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import java.io.Serializable; +import java.util.Map.Entry; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +abstract class ImmutableMapEntrySet + extends ImmutableSet> +{ + ImmutableMapEntrySet() {} + + abstract ImmutableMap map(); + + public int size() + { + return map().size(); + } + + public boolean contains(@Nullable Object object) + { + if ((object instanceof Map.Entry)) { + Map.Entry entry = (Map.Entry)object; + V value = map().get(entry.getKey()); + return (value != null) && (value.equals(entry.getValue())); + } + return false; + } + + boolean isPartialView() + { + return map().isPartialView(); + } + + + + @GwtIncompatible("serialization") + Object writeReplace() { return new EntrySetSerializedForm(map()); } + + @GwtIncompatible("serialization") + private static class EntrySetSerializedForm implements Serializable { + final ImmutableMap map; + private static final long serialVersionUID = 0L; + + EntrySetSerializedForm(ImmutableMap map) { this.map = map; } + + Object readResolve() { + return map.entrySet(); + } + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableMapKeySet.java b/src/minecraft/com/google/common/collect/ImmutableMapKeySet.java new file mode 100644 index 0000000..91299c1 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableMapKeySet.java @@ -0,0 +1,94 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import java.io.Serializable; +import java.util.Map.Entry; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +final class ImmutableMapKeySet + extends ImmutableSet +{ + private final ImmutableMap map; + + ImmutableMapKeySet(ImmutableMap map) + { + this.map = map; + } + + public int size() + { + return map.size(); + } + + public UnmodifiableIterator iterator() + { + return asList().iterator(); + } + + public boolean contains(@Nullable Object object) + { + return map.containsKey(object); + } + + ImmutableList createAsList() + { + final ImmutableList> entryList = map.entrySet().asList(); + new ImmutableAsList() + { + public K get(int index) + { + return ((Map.Entry)entryList.get(index)).getKey(); + } + + ImmutableCollection delegateCollection() + { + return ImmutableMapKeySet.this; + } + }; + } + + + boolean isPartialView() + { + return true; + } + + + @GwtIncompatible("serialization") + Object writeReplace() { return new KeySetSerializedForm(map); } + + @GwtIncompatible("serialization") + private static class KeySetSerializedForm implements Serializable { + final ImmutableMap map; + private static final long serialVersionUID = 0L; + + KeySetSerializedForm(ImmutableMap map) { this.map = map; } + + Object readResolve() { + return map.keySet(); + } + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableMapValues.java b/src/minecraft/com/google/common/collect/ImmutableMapValues.java new file mode 100644 index 0000000..3c3c8aa --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableMapValues.java @@ -0,0 +1,92 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import java.io.Serializable; +import java.util.Map.Entry; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +final class ImmutableMapValues + extends ImmutableCollection +{ + private final ImmutableMap map; + + ImmutableMapValues(ImmutableMap map) + { + this.map = map; + } + + public int size() + { + return map.size(); + } + + public UnmodifiableIterator iterator() + { + return Maps.valueIterator(map.entrySet().iterator()); + } + + public boolean contains(@Nullable Object object) + { + return (object != null) && (Iterators.contains(iterator(), object)); + } + + boolean isPartialView() + { + return true; + } + + ImmutableList createAsList() + { + final ImmutableList> entryList = map.entrySet().asList(); + new ImmutableAsList() + { + public V get(int index) { + return ((Map.Entry)entryList.get(index)).getValue(); + } + + ImmutableCollection delegateCollection() + { + return ImmutableMapValues.this; + } + }; + } + + + @GwtIncompatible("serialization") + Object writeReplace() { return new SerializedForm(map); } + + @GwtIncompatible("serialization") + private static class SerializedForm implements Serializable { + final ImmutableMap map; + private static final long serialVersionUID = 0L; + + SerializedForm(ImmutableMap map) { this.map = map; } + + Object readResolve() { + return map.values(); + } + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableMultimap.java b/src/minecraft/com/google/common/collect/ImmutableMultimap.java new file mode 100644 index 0000000..ec747fa --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableMultimap.java @@ -0,0 +1 @@ +null \ No newline at end of file diff --git a/src/minecraft/com/google/common/collect/ImmutableMultiset.java b/src/minecraft/com/google/common/collect/ImmutableMultiset.java new file mode 100644 index 0000000..0679a1a --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableMultiset.java @@ -0,0 +1,602 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import com.google.common.primitives.Ints; +import java.io.Serializable; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +public abstract class ImmutableMultiset + extends ImmutableCollection + implements Multiset +{ + private static final ImmutableMultiset EMPTY = new RegularImmutableMultiset(ImmutableMap.of(), 0); + + + private transient ImmutableSet> entrySet; + + + public static ImmutableMultiset of() + { + return EMPTY; + } + + + + + + + + public static ImmutableMultiset of(E element) + { + return copyOfInternal(new Object[] { element }); + } + + + + + + + + public static ImmutableMultiset of(E e1, E e2) + { + return copyOfInternal(new Object[] { e1, e2 }); + } + + + + + + + + public static ImmutableMultiset of(E e1, E e2, E e3) + { + return copyOfInternal(new Object[] { e1, e2, e3 }); + } + + + + + + + + public static ImmutableMultiset of(E e1, E e2, E e3, E e4) + { + return copyOfInternal(new Object[] { e1, e2, e3, e4 }); + } + + + + + + + + public static ImmutableMultiset of(E e1, E e2, E e3, E e4, E e5) + { + return copyOfInternal(new Object[] { e1, e2, e3, e4, e5 }); + } + + + + + + + + + public static ImmutableMultiset of(E e1, E e2, E e3, E e4, E e5, E e6, E... others) + { + return new Builder().add(e1).add(e2).add(e3).add(e4).add(e5).add(e6).add(others).build(); + } + + + + + + + + + + + + + + + + + + + public static ImmutableMultiset copyOf(E[] elements) + { + return copyOf(Arrays.asList(elements)); + } + + + + + + + + + + + + + + + + + + + public static ImmutableMultiset copyOf(Iterable elements) + { + if ((elements instanceof ImmutableMultiset)) + { + ImmutableMultiset result = (ImmutableMultiset)elements; + if (!result.isPartialView()) { + return result; + } + } + + Multiset multiset = (elements instanceof Multiset) ? Multisets.cast(elements) : LinkedHashMultiset.create(elements); + + + + return copyOfInternal(multiset); + } + + private static ImmutableMultiset copyOfInternal(E... elements) { + return copyOf(Arrays.asList(elements)); + } + + private static ImmutableMultiset copyOfInternal(Multiset multiset) + { + return copyFromEntries(multiset.entrySet()); + } + + static ImmutableMultiset copyFromEntries(Collection> entries) + { + long size = 0L; + ImmutableMap.Builder builder = ImmutableMap.builder(); + for (Multiset.Entry entry : entries) { + int count = entry.getCount(); + if (count > 0) + { + + builder.put(entry.getElement(), Integer.valueOf(count)); + size += count; + } + } + + if (size == 0L) { + return of(); + } + return new RegularImmutableMultiset(builder.build(), Ints.saturatedCast(size)); + } + + + + + + + + + + + + + public static ImmutableMultiset copyOf(Iterator elements) + { + Multiset multiset = LinkedHashMultiset.create(); + Iterators.addAll(multiset, elements); + return copyOfInternal(multiset); + } + + ImmutableMultiset() {} + + public UnmodifiableIterator iterator() { + final Iterator> entryIterator = entrySet().iterator(); + new UnmodifiableIterator() + { + int remaining; + E element; + + public boolean hasNext() { + return (remaining > 0) || (entryIterator.hasNext()); + } + + public E next() + { + if (remaining <= 0) { + Multiset.Entry entry = (Multiset.Entry)entryIterator.next(); + element = entry.getElement(); + remaining = entry.getCount(); + } + remaining -= 1; + return element; + } + }; + } + + public boolean contains(@Nullable Object object) + { + return count(object) > 0; + } + + public boolean containsAll(Collection targets) + { + return elementSet().containsAll(targets); + } + + + + + + + + @Deprecated + public final int add(E element, int occurrences) + { + throw new UnsupportedOperationException(); + } + + + + + + + + @Deprecated + public final int remove(Object element, int occurrences) + { + throw new UnsupportedOperationException(); + } + + + + + + + + @Deprecated + public final int setCount(E element, int count) + { + throw new UnsupportedOperationException(); + } + + + + + + + + @Deprecated + public final boolean setCount(E element, int oldCount, int newCount) + { + throw new UnsupportedOperationException(); + } + + @GwtIncompatible("not present in emulated superclass") + int copyIntoArray(Object[] dst, int offset) + { + for (Multiset.Entry entry : entrySet()) { + Arrays.fill(dst, offset, offset + entry.getCount(), entry.getElement()); + offset += entry.getCount(); + } + return offset; + } + + public boolean equals(@Nullable Object object) { + return Multisets.equalsImpl(this, object); + } + + public int hashCode() { + return Sets.hashCodeImpl(entrySet()); + } + + public String toString() { + return entrySet().toString(); + } + + + + public ImmutableSet> entrySet() + { + ImmutableSet> es = entrySet; + return es == null ? (this.entrySet = createEntrySet()) : es; + } + + + private final ImmutableSet> createEntrySet() { return isEmpty() ? ImmutableSet.of() : new EntrySet(null); } + + abstract Multiset.Entry getEntry(int paramInt); + + private final class EntrySet extends ImmutableSet> { private static final long serialVersionUID = 0L; + + private EntrySet() {} + + boolean isPartialView() { return ImmutableMultiset.this.isPartialView(); } + + + public UnmodifiableIterator> iterator() + { + return asList().iterator(); + } + + ImmutableList> createAsList() + { + new ImmutableAsList() + { + public Multiset.Entry get(int index) { + return getEntry(index); + } + + ImmutableCollection> delegateCollection() + { + return ImmutableMultiset.EntrySet.this; + } + }; + } + + public int size() + { + return elementSet().size(); + } + + public boolean contains(Object o) + { + if ((o instanceof Multiset.Entry)) { + Multiset.Entry entry = (Multiset.Entry)o; + if (entry.getCount() <= 0) { + return false; + } + int count = count(entry.getElement()); + return count == entry.getCount(); + } + return false; + } + + public int hashCode() + { + return ImmutableMultiset.this.hashCode(); + } + + + + Object writeReplace() + { + return new ImmutableMultiset.EntrySetSerializedForm(ImmutableMultiset.this); + } + } + + static class EntrySetSerializedForm implements Serializable + { + final ImmutableMultiset multiset; + + EntrySetSerializedForm(ImmutableMultiset multiset) + { + this.multiset = multiset; + } + + + Object readResolve() { return multiset.entrySet(); } + } + + private static class SerializedForm implements Serializable { + final Object[] elements; + final int[] counts; + private static final long serialVersionUID = 0L; + + SerializedForm(Multiset multiset) { + int distinct = multiset.entrySet().size(); + elements = new Object[distinct]; + counts = new int[distinct]; + int i = 0; + for (Multiset.Entry entry : multiset.entrySet()) { + elements[i] = entry.getElement(); + counts[i] = entry.getCount(); + i++; + } + } + + Object readResolve() { + LinkedHashMultiset multiset = LinkedHashMultiset.create(elements.length); + + for (int i = 0; i < elements.length; i++) { + multiset.add(elements[i], counts[i]); + } + return ImmutableMultiset.copyOf(multiset); + } + } + + + + + Object writeReplace() + { + return new SerializedForm(this); + } + + + + + public static Builder builder() + { + return new Builder(); + } + + + + + + + + + + + + public static class Builder + extends ImmutableCollection.Builder + { + final Multiset contents; + + + + + + + + + + + public Builder() + { + this(LinkedHashMultiset.create()); + } + + Builder(Multiset contents) { + this.contents = contents; + } + + + + + + + + public Builder add(E element) + { + contents.add(Preconditions.checkNotNull(element)); + return this; + } + + + + + + + + + + + + + + public Builder addCopies(E element, int occurrences) + { + contents.add(Preconditions.checkNotNull(element), occurrences); + return this; + } + + + + + + + + + + + public Builder setCount(E element, int count) + { + contents.setCount(Preconditions.checkNotNull(element), count); + return this; + } + + + + + + + + + public Builder add(E... elements) + { + super.add(elements); + return this; + } + + + + + + + + + + public Builder addAll(Iterable elements) + { + if ((elements instanceof Multiset)) { + Multiset multiset = Multisets.cast(elements); + for (Multiset.Entry entry : multiset.entrySet()) { + addCopies(entry.getElement(), entry.getCount()); + } + } else { + super.addAll(elements); + } + return this; + } + + + + + + + + + public Builder addAll(Iterator elements) + { + super.addAll(elements); + return this; + } + + + + + public ImmutableMultiset build() + { + return ImmutableMultiset.copyOf(contents); + } + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableRangeMap.java b/src/minecraft/com/google/common/collect/ImmutableRangeMap.java new file mode 100644 index 0000000..079fdf7 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableRangeMap.java @@ -0,0 +1,299 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NoSuchElementException; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtIncompatible("NavigableMap") +public class ImmutableRangeMap, V> + implements RangeMap +{ + private static final ImmutableRangeMap, Object> EMPTY = new ImmutableRangeMap(ImmutableList.of(), ImmutableList.of()); + + private final ImmutableList> ranges; + + private final ImmutableList values; + + + public static , V> ImmutableRangeMap of() + { + return EMPTY; + } + + + + + public static , V> ImmutableRangeMap of(Range range, V value) + { + return new ImmutableRangeMap(ImmutableList.of(range), ImmutableList.of(value)); + } + + + public static , V> ImmutableRangeMap copyOf(RangeMap rangeMap) + { + if ((rangeMap instanceof ImmutableRangeMap)) { + return (ImmutableRangeMap)rangeMap; + } + Map, ? extends V> map = rangeMap.asMapOfRanges(); + ImmutableList.Builder> rangesBuilder = new ImmutableList.Builder(map.size()); + ImmutableList.Builder valuesBuilder = new ImmutableList.Builder(map.size()); + for (Map.Entry, ? extends V> entry : map.entrySet()) { + rangesBuilder.add(entry.getKey()); + valuesBuilder.add(entry.getValue()); + } + return new ImmutableRangeMap(rangesBuilder.build(), valuesBuilder.build()); + } + + + + public static , V> Builder builder() + { + return new Builder(); + } + + + public static final class Builder, V> + { + private final RangeSet keyRanges; + private final RangeMap rangeMap; + + public Builder() + { + keyRanges = TreeRangeSet.create(); + rangeMap = TreeRangeMap.create(); + } + + + + + + + public Builder put(Range range, V value) + { + Preconditions.checkNotNull(range); + Preconditions.checkNotNull(value); + Preconditions.checkArgument(!range.isEmpty(), "Range must not be empty, but was %s", new Object[] { range }); + if (!keyRanges.complement().encloses(range)) + { + for (Map.Entry, V> entry : rangeMap.asMapOfRanges().entrySet()) { + Range key = (Range)entry.getKey(); + if ((key.isConnected(range)) && (!key.intersection(range).isEmpty())) { + throw new IllegalArgumentException("Overlapping ranges: range " + range + " overlaps with entry " + entry); + } + } + } + + keyRanges.add(range); + rangeMap.put(range, value); + return this; + } + + + + + + + public Builder putAll(RangeMap rangeMap) + { + for (Map.Entry, ? extends V> entry : rangeMap.asMapOfRanges().entrySet()) { + put((Range)entry.getKey(), entry.getValue()); + } + return this; + } + + + + + public ImmutableRangeMap build() + { + Map, V> map = rangeMap.asMapOfRanges(); + ImmutableList.Builder> rangesBuilder = new ImmutableList.Builder(map.size()); + + ImmutableList.Builder valuesBuilder = new ImmutableList.Builder(map.size()); + for (Map.Entry, V> entry : map.entrySet()) { + rangesBuilder.add(entry.getKey()); + valuesBuilder.add(entry.getValue()); + } + return new ImmutableRangeMap(rangesBuilder.build(), valuesBuilder.build()); + } + } + + + + ImmutableRangeMap(ImmutableList> ranges, ImmutableList values) + { + this.ranges = ranges; + this.values = values; + } + + @Nullable + public V get(K key) + { + int index = SortedLists.binarySearch(ranges, Range.lowerBoundFn(), Cut.belowValue(key), SortedLists.KeyPresentBehavior.ANY_PRESENT, SortedLists.KeyAbsentBehavior.NEXT_LOWER); + + if (index == -1) { + return null; + } + Range range = (Range)ranges.get(index); + return range.contains(key) ? values.get(index) : null; + } + + + @Nullable + public Map.Entry, V> getEntry(K key) + { + int index = SortedLists.binarySearch(ranges, Range.lowerBoundFn(), Cut.belowValue(key), SortedLists.KeyPresentBehavior.ANY_PRESENT, SortedLists.KeyAbsentBehavior.NEXT_LOWER); + + if (index == -1) { + return null; + } + Range range = (Range)ranges.get(index); + return range.contains(key) ? Maps.immutableEntry(range, values.get(index)) : null; + } + + + public Range span() + { + if (ranges.isEmpty()) { + throw new NoSuchElementException(); + } + Range firstRange = (Range)ranges.get(0); + Range lastRange = (Range)ranges.get(ranges.size() - 1); + return Range.create(lowerBound, upperBound); + } + + public void put(Range range, V value) + { + throw new UnsupportedOperationException(); + } + + public void putAll(RangeMap rangeMap) + { + throw new UnsupportedOperationException(); + } + + public void clear() + { + throw new UnsupportedOperationException(); + } + + public void remove(Range range) + { + throw new UnsupportedOperationException(); + } + + public ImmutableMap, V> asMapOfRanges() + { + if (ranges.isEmpty()) { + return ImmutableMap.of(); + } + RegularImmutableSortedSet> rangeSet = new RegularImmutableSortedSet(ranges, Range.RANGE_LEX_ORDERING); + + return new RegularImmutableSortedMap(rangeSet, values); + } + + public ImmutableRangeMap subRangeMap(final Range range) + { + if (((Range)Preconditions.checkNotNull(range)).isEmpty()) + return of(); + if ((ranges.isEmpty()) || (range.encloses(span()))) { + return this; + } + int lowerIndex = SortedLists.binarySearch(ranges, Range.upperBoundFn(), lowerBound, SortedLists.KeyPresentBehavior.FIRST_AFTER, SortedLists.KeyAbsentBehavior.NEXT_HIGHER); + + + int upperIndex = SortedLists.binarySearch(ranges, Range.lowerBoundFn(), upperBound, SortedLists.KeyPresentBehavior.ANY_PRESENT, SortedLists.KeyAbsentBehavior.NEXT_HIGHER); + + + if (lowerIndex >= upperIndex) { + return of(); + } + final int off = lowerIndex; + final int len = upperIndex - lowerIndex; + ImmutableList> subRanges = new ImmutableList() + { + public int size() { + return len; + } + + public Range get(int index) + { + Preconditions.checkElementIndex(index, len); + if ((index == 0) || (index == len - 1)) { + return ((Range)ranges.get(index + off)).intersection(range); + } + return (Range)ranges.get(index + off); + } + + + boolean isPartialView() + { + return true; + } + }; + final ImmutableRangeMap outer = this; + new ImmutableRangeMap(subRanges, values.subList(lowerIndex, upperIndex)) + { + public ImmutableRangeMap subRangeMap(Range subRange) + { + if (range.isConnected(subRange)) { + return outer.subRangeMap(subRange.intersection(range)); + } + return ImmutableRangeMap.of(); + } + }; + } + + + public int hashCode() + { + return asMapOfRanges().hashCode(); + } + + public boolean equals(@Nullable Object o) + { + if ((o instanceof RangeMap)) { + RangeMap rangeMap = (RangeMap)o; + return asMapOfRanges().equals(rangeMap.asMapOfRanges()); + } + return false; + } + + public String toString() + { + return asMapOfRanges().toString(); + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableRangeSet.java b/src/minecraft/com/google/common/collect/ImmutableRangeSet.java new file mode 100644 index 0000000..e4a2620 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableRangeSet.java @@ -0,0 +1,614 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import com.google.common.primitives.Ints; +import java.io.Serializable; +import java.util.Iterator; +import java.util.NoSuchElementException; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class ImmutableRangeSet + extends AbstractRangeSet + implements Serializable +{ + private static final ImmutableRangeSet> EMPTY = new ImmutableRangeSet(ImmutableList.of()); + + + private static final ImmutableRangeSet> ALL = new ImmutableRangeSet(ImmutableList.of(Range.all())); + + private final transient ImmutableList> ranges; + + private transient ImmutableRangeSet complement; + + public static ImmutableRangeSet of() + { + return EMPTY; + } + + + + + static ImmutableRangeSet all() + { + return ALL; + } + + + + + public static ImmutableRangeSet of(Range range) + { + Preconditions.checkNotNull(range); + if (range.isEmpty()) + return of(); + if (range.equals(Range.all())) { + return all(); + } + return new ImmutableRangeSet(ImmutableList.of(range)); + } + + + + + public static ImmutableRangeSet copyOf(RangeSet rangeSet) + { + Preconditions.checkNotNull(rangeSet); + if (rangeSet.isEmpty()) + return of(); + if (rangeSet.encloses(Range.all())) { + return all(); + } + + if ((rangeSet instanceof ImmutableRangeSet)) { + ImmutableRangeSet immutableRangeSet = (ImmutableRangeSet)rangeSet; + if (!immutableRangeSet.isPartialView()) { + return immutableRangeSet; + } + } + return new ImmutableRangeSet(ImmutableList.copyOf(rangeSet.asRanges())); + } + + ImmutableRangeSet(ImmutableList> ranges) { + this.ranges = ranges; + } + + private ImmutableRangeSet(ImmutableList> ranges, ImmutableRangeSet complement) { + this.ranges = ranges; + this.complement = complement; + } + + + + public boolean encloses(Range otherRange) + { + int index = SortedLists.binarySearch(ranges, Range.lowerBoundFn(), lowerBound, Ordering.natural(), SortedLists.KeyPresentBehavior.ANY_PRESENT, SortedLists.KeyAbsentBehavior.NEXT_LOWER); + + + + + + return (index != -1) && (((Range)ranges.get(index)).encloses(otherRange)); + } + + public Range rangeContaining(C value) + { + int index = SortedLists.binarySearch(ranges, Range.lowerBoundFn(), Cut.belowValue(value), Ordering.natural(), SortedLists.KeyPresentBehavior.ANY_PRESENT, SortedLists.KeyAbsentBehavior.NEXT_LOWER); + + + + + + if (index != -1) { + Range range = (Range)ranges.get(index); + return range.contains(value) ? range : null; + } + return null; + } + + public Range span() + { + if (ranges.isEmpty()) { + throw new NoSuchElementException(); + } + return Range.create(ranges.get(0)).lowerBound, ranges.get(ranges.size() - 1)).upperBound); + } + + + + public boolean isEmpty() + { + return ranges.isEmpty(); + } + + public void add(Range range) + { + throw new UnsupportedOperationException(); + } + + public void addAll(RangeSet other) + { + throw new UnsupportedOperationException(); + } + + public void remove(Range range) + { + throw new UnsupportedOperationException(); + } + + public void removeAll(RangeSet other) + { + throw new UnsupportedOperationException(); + } + + public ImmutableSet> asRanges() + { + if (ranges.isEmpty()) { + return ImmutableSet.of(); + } + return new RegularImmutableSortedSet(ranges, Range.RANGE_LEX_ORDERING); + } + + + private final class ComplementRanges + extends ImmutableList> + { + private final boolean positiveBoundedBelow; + + private final boolean positiveBoundedAbove; + + private final int size; + + ComplementRanges() + { + positiveBoundedBelow = ((Range)ranges.get(0)).hasLowerBound(); + positiveBoundedAbove = ((Range)Iterables.getLast(ranges)).hasUpperBound(); + + int size = ranges.size() - 1; + if (positiveBoundedBelow) { + size++; + } + if (positiveBoundedAbove) { + size++; + } + this.size = size; + } + + public int size() + { + return size; + } + + public Range get(int index) + { + Preconditions.checkElementIndex(index, size); + Cut lowerBound; + Cut lowerBound; + if (positiveBoundedBelow) { + lowerBound = index == 0 ? Cut.belowAll() : ranges.get(index - 1)).upperBound; + } else { + lowerBound = ranges.get(index)).upperBound; + } + Cut upperBound; + Cut upperBound; + if ((positiveBoundedAbove) && (index == size - 1)) { + upperBound = Cut.aboveAll(); + } else { + upperBound = ranges.get(index + (positiveBoundedBelow ? 0 : 1))).lowerBound; + } + + return Range.create(lowerBound, upperBound); + } + + boolean isPartialView() + { + return true; + } + } + + public ImmutableRangeSet complement() + { + ImmutableRangeSet result = complement; + if (result != null) + return result; + if (ranges.isEmpty()) + return this.complement = all(); + if ((ranges.size() == 1) && (((Range)ranges.get(0)).equals(Range.all()))) { + return this.complement = of(); + } + ImmutableList> complementRanges = new ComplementRanges(); + result = this.complement = new ImmutableRangeSet(complementRanges, this); + + return result; + } + + + + + private ImmutableList> intersectRanges(final Range range) + { + if ((ranges.isEmpty()) || (range.isEmpty())) + return ImmutableList.of(); + if (range.encloses(span())) { + return ranges; + } + int fromIndex; + final int fromIndex; + if (range.hasLowerBound()) { + fromIndex = SortedLists.binarySearch(ranges, Range.upperBoundFn(), lowerBound, SortedLists.KeyPresentBehavior.FIRST_AFTER, SortedLists.KeyAbsentBehavior.NEXT_HIGHER); + } + else + { + fromIndex = 0; + } + int toIndex; + int toIndex; + if (range.hasUpperBound()) { + toIndex = SortedLists.binarySearch(ranges, Range.lowerBoundFn(), upperBound, SortedLists.KeyPresentBehavior.FIRST_PRESENT, SortedLists.KeyAbsentBehavior.NEXT_HIGHER); + } + else + { + toIndex = ranges.size(); + } + final int length = toIndex - fromIndex; + if (length == 0) { + return ImmutableList.of(); + } + new ImmutableList() + { + public int size() { + return length; + } + + public Range get(int index) + { + Preconditions.checkElementIndex(index, length); + if ((index == 0) || (index == length - 1)) { + return ((Range)ranges.get(index + fromIndex)).intersection(range); + } + return (Range)ranges.get(index + fromIndex); + } + + + boolean isPartialView() + { + return true; + } + }; + } + + + + + + public ImmutableRangeSet subRangeSet(Range range) + { + if (!isEmpty()) { + Range span = span(); + if (range.encloses(span)) + return this; + if (range.isConnected(span)) { + return new ImmutableRangeSet(intersectRanges(range)); + } + } + return of(); + } + + + + + + + + + + + + + + + + + + + + public ImmutableSortedSet asSet(DiscreteDomain domain) + { + Preconditions.checkNotNull(domain); + if (isEmpty()) { + return ImmutableSortedSet.of(); + } + Range span = span().canonical(domain); + if (!span.hasLowerBound()) + { + + throw new IllegalArgumentException("Neither the DiscreteDomain nor this range set are bounded below"); + } + if (!span.hasUpperBound()) { + try { + domain.maxValue(); + } catch (NoSuchElementException e) { + throw new IllegalArgumentException("Neither the DiscreteDomain nor this range set are bounded above"); + } + } + + + return new AsSet(domain); + } + + private final class AsSet extends ImmutableSortedSet { + private final DiscreteDomain domain; + private transient Integer size; + + AsSet() { super(); + this.domain = domain; + } + + + + + public int size() + { + Integer result = size; + if (result == null) { + long total = 0L; + for (Range range : ranges) { + total += ContiguousSet.create(range, domain).size(); + if (total >= 2147483647L) { + break; + } + } + result = this.size = Integer.valueOf(Ints.saturatedCast(total)); + } + return result.intValue(); + } + + public UnmodifiableIterator iterator() + { + new AbstractIterator() { + final Iterator> rangeItr = ranges.iterator(); + Iterator elemItr = Iterators.emptyIterator(); + + protected C computeNext() + { + while (!elemItr.hasNext()) { + if (rangeItr.hasNext()) { + elemItr = ContiguousSet.create((Range)rangeItr.next(), domain).iterator(); + } else { + return (Comparable)endOfData(); + } + } + return (Comparable)elemItr.next(); + } + }; + } + + @GwtIncompatible("NavigableSet") + public UnmodifiableIterator descendingIterator() + { + new AbstractIterator() { + final Iterator> rangeItr = ranges.reverse().iterator(); + Iterator elemItr = Iterators.emptyIterator(); + + protected C computeNext() + { + while (!elemItr.hasNext()) { + if (rangeItr.hasNext()) { + elemItr = ContiguousSet.create((Range)rangeItr.next(), domain).descendingIterator(); + } else { + return (Comparable)endOfData(); + } + } + return (Comparable)elemItr.next(); + } + }; + } + + ImmutableSortedSet subSet(Range range) { + return subRangeSet(range).asSet(domain); + } + + ImmutableSortedSet headSetImpl(C toElement, boolean inclusive) + { + return subSet(Range.upTo(toElement, BoundType.forBoolean(inclusive))); + } + + + ImmutableSortedSet subSetImpl(C fromElement, boolean fromInclusive, C toElement, boolean toInclusive) + { + if ((!fromInclusive) && (!toInclusive) && (Range.compareOrThrow(fromElement, toElement) == 0)) { + return ImmutableSortedSet.of(); + } + return subSet(Range.range(fromElement, BoundType.forBoolean(fromInclusive), toElement, BoundType.forBoolean(toInclusive))); + } + + + + ImmutableSortedSet tailSetImpl(C fromElement, boolean inclusive) + { + return subSet(Range.downTo(fromElement, BoundType.forBoolean(inclusive))); + } + + public boolean contains(@Nullable Object o) + { + if (o == null) { + return false; + } + try + { + C c = (Comparable)o; + return contains(c); + } catch (ClassCastException e) {} + return false; + } + + + int indexOf(Object target) + { + if (contains(target)) + { + C c = (Comparable)target; + long total = 0L; + for (Range range : ranges) { + if (range.contains(c)) { + return Ints.saturatedCast(total + ContiguousSet.create(range, domain).indexOf(c)); + } + total += ContiguousSet.create(range, domain).size(); + } + + throw new AssertionError("impossible"); + } + return -1; + } + + boolean isPartialView() + { + return ranges.isPartialView(); + } + + public String toString() + { + return ranges.toString(); + } + + Object writeReplace() + { + return new ImmutableRangeSet.AsSetSerializedForm(ranges, domain); + } + } + + private static class AsSetSerializedForm implements Serializable { + private final ImmutableList> ranges; + private final DiscreteDomain domain; + + AsSetSerializedForm(ImmutableList> ranges, DiscreteDomain domain) { + this.ranges = ranges; + this.domain = domain; + } + + Object readResolve() { + return new ImmutableRangeSet(ranges).asSet(domain); + } + } + + + + + + + boolean isPartialView() + { + return ranges.isPartialView(); + } + + + + public static > Builder builder() + { + return new Builder(); + } + + + public static class Builder> + { + private final RangeSet rangeSet; + + public Builder() + { + rangeSet = TreeRangeSet.create(); + } + + + + + + + + public Builder add(Range range) + { + if (range.isEmpty()) + throw new IllegalArgumentException("range must not be empty, but was " + range); + if (!rangeSet.complement().encloses(range)) { + for (Range currentRange : rangeSet.asRanges()) { + Preconditions.checkArgument((!currentRange.isConnected(range)) || (currentRange.intersection(range).isEmpty()), "Ranges may not overlap, but received %s and %s", new Object[] { currentRange, range }); + } + + + throw new AssertionError("should have thrown an IAE above"); + } + rangeSet.add(range); + return this; + } + + + + + public Builder addAll(RangeSet ranges) + { + for (Range range : ranges.asRanges()) { + add(range); + } + return this; + } + + + + public ImmutableRangeSet build() + { + return ImmutableRangeSet.copyOf(rangeSet); + } + } + + private static final class SerializedForm implements Serializable { + private final ImmutableList> ranges; + + SerializedForm(ImmutableList> ranges) { + this.ranges = ranges; + } + + Object readResolve() { + if (ranges.isEmpty()) + return ImmutableRangeSet.of(); + if (ranges.equals(ImmutableList.of(Range.all()))) { + return ImmutableRangeSet.all(); + } + return new ImmutableRangeSet(ranges); + } + } + + Object writeReplace() + { + return new SerializedForm(ranges); + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableSet.java b/src/minecraft/com/google/common/collect/ImmutableSet.java new file mode 100644 index 0000000..8e3f616 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableSet.java @@ -0,0 +1,538 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.Arrays; +import java.util.Collection; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +public abstract class ImmutableSet + extends ImmutableCollection + implements Set +{ + static final int MAX_TABLE_SIZE = 1073741824; + private static final double DESIRED_LOAD_FACTOR = 0.7D; + private static final int CUTOFF = 751619276; + + public static ImmutableSet of() + { + return EmptyImmutableSet.INSTANCE; + } + + + + + + + public static ImmutableSet of(E element) + { + return new SingletonImmutableSet(element); + } + + + + + + + + public static ImmutableSet of(E e1, E e2) + { + return construct(2, new Object[] { e1, e2 }); + } + + + + + + + + public static ImmutableSet of(E e1, E e2, E e3) + { + return construct(3, new Object[] { e1, e2, e3 }); + } + + + + + + + + public static ImmutableSet of(E e1, E e2, E e3, E e4) + { + return construct(4, new Object[] { e1, e2, e3, e4 }); + } + + + + + + + + public static ImmutableSet of(E e1, E e2, E e3, E e4, E e5) + { + return construct(5, new Object[] { e1, e2, e3, e4, e5 }); + } + + + + + + + + + + public static ImmutableSet of(E e1, E e2, E e3, E e4, E e5, E e6, E... others) + { + int paramCount = 6; + Object[] elements = new Object[6 + others.length]; + elements[0] = e1; + elements[1] = e2; + elements[2] = e3; + elements[3] = e4; + elements[4] = e5; + elements[5] = e6; + System.arraycopy(others, 0, elements, 6, others.length); + return construct(elements.length, elements); + } + + + + + + + + + + + + + + + + private static ImmutableSet construct(int n, Object... elements) + { + switch (n) { + case 0: + return of(); + + case 1: + E elem = elements[0]; + return of(elem); + } + + + int tableSize = chooseTableSize(n); + Object[] table = new Object[tableSize]; + int mask = tableSize - 1; + int hashCode = 0; + int uniques = 0; + for (int i = 0; i < n; i++) { + Object element = ObjectArrays.checkElementNotNull(elements[i], i); + int hash = element.hashCode(); + for (int j = Hashing.smear(hash);; j++) { + int index = j & mask; + Object value = table[index]; + if (value == null) + { + elements[(uniques++)] = element; + table[index] = element; + hashCode += hash; + } else { + if (value.equals(element)) + break; + } + } + } + Arrays.fill(elements, uniques, n, null); + if (uniques == 1) + { + + E element = elements[0]; + return new SingletonImmutableSet(element, hashCode); } + if (tableSize != chooseTableSize(uniques)) + { + + return construct(uniques, elements); + } + Object[] uniqueElements = uniques < elements.length ? ObjectArrays.arraysCopyOf(elements, uniques) : elements; + + + return new RegularImmutableSet(uniqueElements, hashCode, table, mask); + } + + + + + + + + + + + + + + + + + + + + @VisibleForTesting + static int chooseTableSize(int setSize) + { + if (setSize < 751619276) + { + int tableSize = Integer.highestOneBit(setSize - 1) << 1; + while (tableSize * 0.7D < setSize) { + tableSize <<= 1; + } + return tableSize; + } + + + Preconditions.checkArgument(setSize < 1073741824, "collection too large"); + return 1073741824; + } + + + + + + + + + public static ImmutableSet copyOf(E[] elements) + { + switch (elements.length) { + case 0: + return of(); + case 1: + return of(elements[0]); + } + return construct(elements.length, (Object[])elements.clone()); + } + + + + + + + + + + + + + + + + + + + public static ImmutableSet copyOf(Iterable elements) + { + return (elements instanceof Collection) ? copyOf(Collections2.cast(elements)) : copyOf(elements.iterator()); + } + + + + + + + + + + + public static ImmutableSet copyOf(Iterator elements) + { + if (!elements.hasNext()) { + return of(); + } + E first = elements.next(); + if (!elements.hasNext()) { + return of(first); + } + return new Builder().add(first).addAll(elements).build(); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static ImmutableSet copyOf(Collection elements) + { + if (((elements instanceof ImmutableSet)) && (!(elements instanceof ImmutableSortedSet))) + { + + ImmutableSet set = (ImmutableSet)elements; + if (!set.isPartialView()) { + return set; + } + } else if ((elements instanceof EnumSet)) { + return copyOfEnumSet((EnumSet)elements); + } + Object[] array = elements.toArray(); + return construct(array.length, array); + } + + private static > ImmutableSet copyOfEnumSet(EnumSet enumSet) + { + return ImmutableEnumSet.asImmutable(EnumSet.copyOf(enumSet)); + } + + ImmutableSet() {} + + boolean isHashCodeFast() + { + return false; + } + + public boolean equals(@Nullable Object object) { + if (object == this) + return true; + if (((object instanceof ImmutableSet)) && (isHashCodeFast()) && (((ImmutableSet)object).isHashCodeFast()) && (hashCode() != object.hashCode())) + { + + + return false; + } + return Sets.equalsImpl(this, object); + } + + public int hashCode() { + return Sets.hashCodeImpl(this); + } + + + public abstract UnmodifiableIterator iterator(); + + + private static class SerializedForm + implements Serializable + { + final Object[] elements; + + private static final long serialVersionUID = 0L; + + + SerializedForm(Object[] elements) + { + this.elements = elements; + } + + Object readResolve() { return ImmutableSet.copyOf(elements); } + } + + + Object writeReplace() + { + return new SerializedForm(toArray()); + } + + + + + public static Builder builder() + { + return new Builder(); + } + + + + + + + + + + + + + + + + + + + + public static class Builder + extends ImmutableCollection.ArrayBasedBuilder + { + public Builder() + { + this(4); + } + + Builder(int capacity) { + super(); + } + + + + + + + + + + public Builder add(E element) + { + super.add(element); + return this; + } + + + + + + + + + + public Builder add(E... elements) + { + super.add(elements); + return this; + } + + + + + + + + + + public Builder addAll(Iterable elements) + { + super.addAll(elements); + return this; + } + + + + + + + + + + public Builder addAll(Iterator elements) + { + super.addAll(elements); + return this; + } + + + + + public ImmutableSet build() + { + ImmutableSet result = ImmutableSet.construct(size, contents); + + + size = result.size(); + return result; + } + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableSetMultimap.java b/src/minecraft/com/google/common/collect/ImmutableSetMultimap.java new file mode 100644 index 0000000..7379be1 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableSetMultimap.java @@ -0,0 +1,537 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +public class ImmutableSetMultimap + extends ImmutableMultimap + implements SetMultimap +{ + private final transient ImmutableSet emptySet; + private transient ImmutableSetMultimap inverse; + private transient ImmutableSet> entries; + @GwtIncompatible("not needed in emulated source.") + private static final long serialVersionUID = 0L; + + public static ImmutableSetMultimap of() + { + return EmptyImmutableSetMultimap.INSTANCE; + } + + + + public static ImmutableSetMultimap of(K k1, V v1) + { + Builder builder = builder(); + builder.put(k1, v1); + return builder.build(); + } + + + + + + public static ImmutableSetMultimap of(K k1, V v1, K k2, V v2) + { + Builder builder = builder(); + builder.put(k1, v1); + builder.put(k2, v2); + return builder.build(); + } + + + + + + + public static ImmutableSetMultimap of(K k1, V v1, K k2, V v2, K k3, V v3) + { + Builder builder = builder(); + builder.put(k1, v1); + builder.put(k2, v2); + builder.put(k3, v3); + return builder.build(); + } + + + + + + + public static ImmutableSetMultimap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) + { + Builder builder = builder(); + builder.put(k1, v1); + builder.put(k2, v2); + builder.put(k3, v3); + builder.put(k4, v4); + return builder.build(); + } + + + + + + + public static ImmutableSetMultimap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) + { + Builder builder = builder(); + builder.put(k1, v1); + builder.put(k2, v2); + builder.put(k3, v3); + builder.put(k4, v4); + builder.put(k5, v5); + return builder.build(); + } + + + + + + public static Builder builder() + { + return new Builder(); + } + + private static class BuilderMultimap extends AbstractMapBasedMultimap + { + private static final long serialVersionUID = 0L; + + BuilderMultimap() + { + super(); + } + + Collection createCollection() { return Sets.newLinkedHashSet(); } + } + + + + + + + + + + + + + + + + + + + + + + + + public static final class Builder + extends ImmutableMultimap.Builder + { + public Builder() + { + builderMultimap = new ImmutableSetMultimap.BuilderMultimap(); + } + + + + + public Builder put(K key, V value) + { + builderMultimap.put(Preconditions.checkNotNull(key), Preconditions.checkNotNull(value)); + return this; + } + + + + + + public Builder put(Map.Entry entry) + { + builderMultimap.put(Preconditions.checkNotNull(entry.getKey()), Preconditions.checkNotNull(entry.getValue())); + + return this; + } + + public Builder putAll(K key, Iterable values) { + Collection collection = builderMultimap.get(Preconditions.checkNotNull(key)); + for (V value : values) { + collection.add(Preconditions.checkNotNull(value)); + } + return this; + } + + public Builder putAll(K key, V... values) { + return putAll(key, Arrays.asList(values)); + } + + + public Builder putAll(Multimap multimap) + { + for (Map.Entry> entry : multimap.asMap().entrySet()) { + putAll(entry.getKey(), (Iterable)entry.getValue()); + } + return this; + } + + + + + + + public Builder orderKeysBy(Comparator keyComparator) + { + this.keyComparator = ((Comparator)Preconditions.checkNotNull(keyComparator)); + return this; + } + + + + + + + + + + + + + + public Builder orderValuesBy(Comparator valueComparator) + { + super.orderValuesBy(valueComparator); + return this; + } + + + + public ImmutableSetMultimap build() + { + if (keyComparator != null) { + Multimap sortedCopy = new ImmutableSetMultimap.BuilderMultimap(); + List>> entries = Lists.newArrayList(builderMultimap.asMap().entrySet()); + + Collections.sort(entries, Ordering.from(keyComparator).onKeys()); + + + for (Map.Entry> entry : entries) { + sortedCopy.putAll(entry.getKey(), (Iterable)entry.getValue()); + } + builderMultimap = sortedCopy; + } + return ImmutableSetMultimap.copyOf(builderMultimap, valueComparator); + } + } + + + + + + + + + + + + + + + + public static ImmutableSetMultimap copyOf(Multimap multimap) + { + return copyOf(multimap, null); + } + + + private static ImmutableSetMultimap copyOf(Multimap multimap, Comparator valueComparator) + { + Preconditions.checkNotNull(multimap); + if ((multimap.isEmpty()) && (valueComparator == null)) { + return of(); + } + + if ((multimap instanceof ImmutableSetMultimap)) + { + ImmutableSetMultimap kvMultimap = (ImmutableSetMultimap)multimap; + + if (!kvMultimap.isPartialView()) { + return kvMultimap; + } + } + + ImmutableMap.Builder> builder = ImmutableMap.builder(); + int size = 0; + + + for (Map.Entry> entry : multimap.asMap().entrySet()) { + K key = entry.getKey(); + Collection values = (Collection)entry.getValue(); + ImmutableSet set = valueSet(valueComparator, values); + if (!set.isEmpty()) { + builder.put(key, set); + size += set.size(); + } + } + + return new ImmutableSetMultimap(builder.build(), size, valueComparator); + } + + + + + + + + + ImmutableSetMultimap(ImmutableMap> map, int size, @Nullable Comparator valueComparator) + { + super(map, size); + emptySet = emptySet(valueComparator); + } + + + + + + + + + + public ImmutableSet get(@Nullable K key) + { + ImmutableSet set = (ImmutableSet)map.get(key); + return (ImmutableSet)Objects.firstNonNull(set, emptySet); + } + + + + + + + + + + + + + public ImmutableSetMultimap inverse() + { + ImmutableSetMultimap result = inverse; + return result == null ? (this.inverse = invert()) : result; + } + + private ImmutableSetMultimap invert() { + Builder builder = builder(); + for (Map.Entry entry : entries()) { + builder.put(entry.getValue(), entry.getKey()); + } + ImmutableSetMultimap invertedMultimap = builder.build(); + inverse = this; + return invertedMultimap; + } + + + + + + @Deprecated + public ImmutableSet removeAll(Object key) + { + throw new UnsupportedOperationException(); + } + + + + + + + @Deprecated + public ImmutableSet replaceValues(K key, Iterable values) + { + throw new UnsupportedOperationException(); + } + + + + + + + + public ImmutableSet> entries() + { + ImmutableSet> result = entries; + return result == null ? (this.entries = new EntrySet(this)) : result; + } + + private static final class EntrySet extends ImmutableSet> + { + private final transient ImmutableSetMultimap multimap; + + EntrySet(ImmutableSetMultimap multimap) + { + this.multimap = multimap; + } + + public boolean contains(@Nullable Object object) + { + if ((object instanceof Map.Entry)) { + Map.Entry entry = (Map.Entry)object; + return multimap.containsEntry(entry.getKey(), entry.getValue()); + } + return false; + } + + public int size() + { + return multimap.size(); + } + + public UnmodifiableIterator> iterator() + { + return multimap.entryIterator(); + } + + boolean isPartialView() + { + return false; + } + } + + + private static ImmutableSet valueSet(@Nullable Comparator valueComparator, Collection values) + { + return valueComparator == null ? ImmutableSet.copyOf(values) : ImmutableSortedSet.copyOf(valueComparator, values); + } + + + + private static ImmutableSet emptySet(@Nullable Comparator valueComparator) + { + return valueComparator == null ? ImmutableSet.of() : ImmutableSortedSet.emptySet(valueComparator); + } + + + + + + @GwtIncompatible("java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) + throws IOException + { + stream.defaultWriteObject(); + stream.writeObject(valueComparator()); + Serialization.writeMultimap(this, stream); + } + + @Nullable + Comparator valueComparator() { return (emptySet instanceof ImmutableSortedSet) ? ((ImmutableSortedSet)emptySet).comparator() : null; } + + + + + + @GwtIncompatible("java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException + { + stream.defaultReadObject(); + Comparator valueComparator = (Comparator)stream.readObject(); + + int keyCount = stream.readInt(); + if (keyCount < 0) { + throw new InvalidObjectException("Invalid key count " + keyCount); + } + ImmutableMap.Builder> builder = ImmutableMap.builder(); + + int tmpSize = 0; + + for (int i = 0; i < keyCount; i++) { + Object key = stream.readObject(); + int valueCount = stream.readInt(); + if (valueCount <= 0) { + throw new InvalidObjectException("Invalid value count " + valueCount); + } + + Object[] array = new Object[valueCount]; + for (int j = 0; j < valueCount; j++) { + array[j] = stream.readObject(); + } + ImmutableSet valueSet = valueSet(valueComparator, Arrays.asList(array)); + if (valueSet.size() != array.length) { + throw new InvalidObjectException("Duplicate key-value pairs exist for key " + key); + } + + builder.put(key, valueSet); + tmpSize += valueCount; + } + ImmutableMap> tmpMap; + try + { + tmpMap = builder.build(); + } catch (IllegalArgumentException e) { + throw ((InvalidObjectException)new InvalidObjectException(e.getMessage()).initCause(e)); + } + + + ImmutableMultimap.FieldSettersHolder.MAP_FIELD_SETTER.set(this, tmpMap); + ImmutableMultimap.FieldSettersHolder.SIZE_FIELD_SETTER.set(this, tmpSize); + ImmutableMultimap.FieldSettersHolder.EMPTY_SET_FIELD_SETTER.set(this, emptySet(valueComparator)); + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableSortedAsList.java b/src/minecraft/com/google/common/collect/ImmutableSortedAsList.java new file mode 100644 index 0000000..509c6bb --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableSortedAsList.java @@ -0,0 +1,84 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import java.util.Comparator; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +final class ImmutableSortedAsList + extends RegularImmutableAsList + implements SortedIterable +{ + ImmutableSortedAsList(ImmutableSortedSet backingSet, ImmutableList backingList) + { + super(backingSet, backingList); + } + + ImmutableSortedSet delegateCollection() + { + return (ImmutableSortedSet)super.delegateCollection(); + } + + public Comparator comparator() { + return delegateCollection().comparator(); + } + + + + @GwtIncompatible("ImmutableSortedSet.indexOf") + public int indexOf(@Nullable Object target) + { + int index = delegateCollection().indexOf(target); + + + + + + + return (index >= 0) && (get(index).equals(target)) ? index : -1; + } + + @GwtIncompatible("ImmutableSortedSet.indexOf") + public int lastIndexOf(@Nullable Object target) { + return indexOf(target); + } + + + public boolean contains(Object target) + { + return indexOf(target) >= 0; + } + + + + + + + @GwtIncompatible("super.subListUnchecked does not exist; inherited subList is valid if slow") + ImmutableList subListUnchecked(int fromIndex, int toIndex) + { + return new RegularImmutableSortedSet(super.subListUnchecked(fromIndex, toIndex), comparator()).asList(); + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableSortedMap.java b/src/minecraft/com/google/common/collect/ImmutableSortedMap.java new file mode 100644 index 0000000..88926c7 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableSortedMap.java @@ -0,0 +1,696 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NavigableMap; +import java.util.Set; +import java.util.SortedMap; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +public abstract class ImmutableSortedMap + extends ImmutableSortedMapFauxverideShim + implements NavigableMap +{ + private static final Comparator NATURAL_ORDER = ; + + private static final ImmutableSortedMap NATURAL_EMPTY_MAP = new EmptyImmutableSortedMap(NATURAL_ORDER); + private transient ImmutableSortedMap descendingMap; + private static final long serialVersionUID = 0L; + + static ImmutableSortedMap emptyMap(Comparator comparator) { if (Ordering.natural().equals(comparator)) { + return of(); + } + return new EmptyImmutableSortedMap(comparator); + } + + + + + static ImmutableSortedMap fromSortedEntries(Comparator comparator, int size, Map.Entry[] entries) + { + if (size == 0) { + return emptyMap(comparator); + } + + ImmutableList.Builder keyBuilder = ImmutableList.builder(); + ImmutableList.Builder valueBuilder = ImmutableList.builder(); + for (int i = 0; i < size; i++) { + Map.Entry entry = entries[i]; + keyBuilder.add(entry.getKey()); + valueBuilder.add(entry.getValue()); + } + + return new RegularImmutableSortedMap(new RegularImmutableSortedSet(keyBuilder.build(), comparator), valueBuilder.build()); + } + + + + static ImmutableSortedMap from(ImmutableSortedSet keySet, ImmutableList valueList) + { + if (keySet.isEmpty()) { + return emptyMap(keySet.comparator()); + } + return new RegularImmutableSortedMap((RegularImmutableSortedSet)keySet, valueList); + } + + + + + + + + + + public static ImmutableSortedMap of() + { + return NATURAL_EMPTY_MAP; + } + + + + + public static , V> ImmutableSortedMap of(K k1, V v1) + { + return from(ImmutableSortedSet.of(k1), ImmutableList.of(v1)); + } + + + + + + + + + + public static , V> ImmutableSortedMap of(K k1, V v1, K k2, V v2) + { + return fromEntries(Ordering.natural(), false, 2, new Map.Entry[] { entryOf(k1, v1), entryOf(k2, v2) }); + } + + + + + + + + + + public static , V> ImmutableSortedMap of(K k1, V v1, K k2, V v2, K k3, V v3) + { + return fromEntries(Ordering.natural(), false, 3, new Map.Entry[] { entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3) }); + } + + + + + + + + + + + public static , V> ImmutableSortedMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) + { + return fromEntries(Ordering.natural(), false, 4, new Map.Entry[] { entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4) }); + } + + + + + + + + + + + public static , V> ImmutableSortedMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) + { + return fromEntries(Ordering.natural(), false, 5, new Map.Entry[] { entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4), entryOf(k5, v5) }); + } + + + + + + + + + + + + + + + + + + + + + + + public static ImmutableSortedMap copyOf(Map map) + { + Ordering naturalOrder = Ordering.natural(); + return copyOfInternal(map, naturalOrder); + } + + + + + + + + + + + + + + public static ImmutableSortedMap copyOf(Map map, Comparator comparator) + { + return copyOfInternal(map, (Comparator)Preconditions.checkNotNull(comparator)); + } + + + + + + + + + + + + + public static ImmutableSortedMap copyOfSorted(SortedMap map) + { + Comparator comparator = map.comparator(); + if (comparator == null) + { + + comparator = NATURAL_ORDER; + } + return copyOfInternal(map, comparator); + } + + private static ImmutableSortedMap copyOfInternal(Map map, Comparator comparator) + { + boolean sameComparator = false; + if ((map instanceof SortedMap)) { + SortedMap sortedMap = (SortedMap)map; + Comparator comparator2 = sortedMap.comparator(); + sameComparator = comparator2 == null ? false : comparator == NATURAL_ORDER ? true : comparator.equals(comparator2); + } + + + + if ((sameComparator) && ((map instanceof ImmutableSortedMap))) + { + + + ImmutableSortedMap kvMap = (ImmutableSortedMap)map; + if (!kvMap.isPartialView()) { + return kvMap; + } + } + + + + + + Map.Entry[] entries = (Map.Entry[])map.entrySet().toArray(new Map.Entry[0]); + + return fromEntries(comparator, sameComparator, entries.length, entries); + } + + static ImmutableSortedMap fromEntries(Comparator comparator, boolean sameComparator, int size, Map.Entry... entries) + { + for (int i = 0; i < size; i++) { + Map.Entry entry = entries[i]; + entries[i] = entryOf(entry.getKey(), entry.getValue()); + } + if (!sameComparator) { + sortEntries(comparator, size, entries); + validateEntries(size, entries, comparator); + } + + return fromSortedEntries(comparator, size, entries); + } + + private static void sortEntries(Comparator comparator, int size, Map.Entry[] entries) + { + Arrays.sort(entries, 0, size, Ordering.from(comparator).onKeys()); + } + + private static void validateEntries(int size, Map.Entry[] entries, Comparator comparator) + { + for (int i = 1; i < size; i++) { + checkNoConflict(comparator.compare(entries[(i - 1)].getKey(), entries[i].getKey()) != 0, "key", entries[(i - 1)], entries[i]); + } + } + + + + + + + public static , V> Builder naturalOrder() + { + return new Builder(Ordering.natural()); + } + + + + + + + + + public static Builder orderedBy(Comparator comparator) + { + return new Builder(comparator); + } + + + + + public static , V> Builder reverseOrder() + { + return new Builder(Ordering.natural().reverse()); + } + + + + + + + + + ImmutableSortedMap() {} + + + + + + + + + public static class Builder + extends ImmutableMap.Builder + { + private final Comparator comparator; + + + + + + + + public Builder(Comparator comparator) + { + this.comparator = ((Comparator)Preconditions.checkNotNull(comparator)); + } + + + + + + public Builder put(K key, V value) + { + super.put(key, value); + return this; + } + + + + + + + + + public Builder put(Map.Entry entry) + { + super.put(entry); + return this; + } + + + + + + + + public Builder putAll(Map map) + { + super.putAll(map); + return this; + } + + + + + + + public ImmutableSortedMap build() + { + return ImmutableSortedMap.fromEntries(comparator, false, size, entries); + } + } + + + + ImmutableSortedMap(ImmutableSortedMap descendingMap) + { + this.descendingMap = descendingMap; + } + + public int size() + { + return values().size(); + } + + public boolean containsValue(@Nullable Object value) { + return values().contains(value); + } + + boolean isPartialView() { + return (keySet().isPartialView()) || (values().isPartialView()); + } + + + + + public ImmutableSet> entrySet() + { + return super.entrySet(); + } + + + + + + + public abstract ImmutableSortedSet keySet(); + + + + + + public abstract ImmutableCollection values(); + + + + + + public Comparator comparator() + { + return keySet().comparator(); + } + + public K firstKey() + { + return keySet().first(); + } + + public K lastKey() + { + return keySet().last(); + } + + + + + + + + + + + + public ImmutableSortedMap headMap(K toKey) + { + return headMap(toKey, false); + } + + + + + + + + + + + + + + + public abstract ImmutableSortedMap headMap(K paramK, boolean paramBoolean); + + + + + + + + + + + + + + + public ImmutableSortedMap subMap(K fromKey, K toKey) + { + return subMap(fromKey, true, toKey, false); + } + + + + + + + + + + + + + + + + + + public ImmutableSortedMap subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) + { + Preconditions.checkNotNull(fromKey); + Preconditions.checkNotNull(toKey); + Preconditions.checkArgument(comparator().compare(fromKey, toKey) <= 0, "expected fromKey <= toKey but %s > %s", new Object[] { fromKey, toKey }); + + return headMap(toKey, toInclusive).tailMap(fromKey, fromInclusive); + } + + + + + + + + + + + + public ImmutableSortedMap tailMap(K fromKey) + { + return tailMap(fromKey, true); + } + + + + + + + + + public abstract ImmutableSortedMap tailMap(K paramK, boolean paramBoolean); + + + + + + + + + public Map.Entry lowerEntry(K key) + { + return headMap(key, false).lastEntry(); + } + + public K lowerKey(K key) + { + return Maps.keyOrNull(lowerEntry(key)); + } + + public Map.Entry floorEntry(K key) + { + return headMap(key, true).lastEntry(); + } + + public K floorKey(K key) + { + return Maps.keyOrNull(floorEntry(key)); + } + + public Map.Entry ceilingEntry(K key) + { + return tailMap(key, true).firstEntry(); + } + + public K ceilingKey(K key) + { + return Maps.keyOrNull(ceilingEntry(key)); + } + + public Map.Entry higherEntry(K key) + { + return tailMap(key, false).firstEntry(); + } + + public K higherKey(K key) + { + return Maps.keyOrNull(higherEntry(key)); + } + + public Map.Entry firstEntry() + { + return isEmpty() ? null : (Map.Entry)entrySet().asList().get(0); + } + + public Map.Entry lastEntry() + { + return isEmpty() ? null : (Map.Entry)entrySet().asList().get(size() - 1); + } + + + + + + + + @Deprecated + public final Map.Entry pollFirstEntry() + { + throw new UnsupportedOperationException(); + } + + + + + + + + @Deprecated + public final Map.Entry pollLastEntry() + { + throw new UnsupportedOperationException(); + } + + + + public ImmutableSortedMap descendingMap() + { + ImmutableSortedMap result = descendingMap; + if (result == null) { + result = this.descendingMap = createDescendingMap(); + } + return result; + } + + abstract ImmutableSortedMap createDescendingMap(); + + public ImmutableSortedSet navigableKeySet() + { + return keySet(); + } + + public ImmutableSortedSet descendingKeySet() + { + return keySet().descendingSet(); + } + + + private static class SerializedForm + extends ImmutableMap.SerializedForm + { + private final Comparator comparator; + + private static final long serialVersionUID = 0L; + + SerializedForm(ImmutableSortedMap sortedMap) + { + super(); + comparator = sortedMap.comparator(); + } + + Object readResolve() { ImmutableSortedMap.Builder builder = new ImmutableSortedMap.Builder(comparator); + return createMap(builder); + } + } + + Object writeReplace() + { + return new SerializedForm(this); + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableSortedMapFauxverideShim.java b/src/minecraft/com/google/common/collect/ImmutableSortedMapFauxverideShim.java new file mode 100644 index 0000000..000ae6b --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableSortedMapFauxverideShim.java @@ -0,0 +1,112 @@ +package com.google.common.collect; + + + + + + + + + + + + + + + +abstract class ImmutableSortedMapFauxverideShim + extends ImmutableMap +{ + ImmutableSortedMapFauxverideShim() {} + + + + + + + + + + + + + + + @Deprecated + public static ImmutableSortedMap.Builder builder() + { + throw new UnsupportedOperationException(); + } + + + + + + + + + @Deprecated + public static ImmutableSortedMap of(K k1, V v1) + { + throw new UnsupportedOperationException(); + } + + + + + + + + + + @Deprecated + public static ImmutableSortedMap of(K k1, V v1, K k2, V v2) + { + throw new UnsupportedOperationException(); + } + + + + + + + + + + + @Deprecated + public static ImmutableSortedMap of(K k1, V v1, K k2, V v2, K k3, V v3) + { + throw new UnsupportedOperationException(); + } + + + + + + + + + + + @Deprecated + public static ImmutableSortedMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) + { + throw new UnsupportedOperationException(); + } + + + + + + + + + + + @Deprecated + public static ImmutableSortedMap of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) + { + throw new UnsupportedOperationException(); + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableSortedMultiset.java b/src/minecraft/com/google/common/collect/ImmutableSortedMultiset.java new file mode 100644 index 0000000..230f062 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableSortedMultiset.java @@ -0,0 +1,575 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtIncompatible("hasn't been tested yet") +public abstract class ImmutableSortedMultiset + extends ImmutableSortedMultisetFauxverideShim + implements SortedMultiset +{ + private static final Comparator NATURAL_ORDER = ; + + private static final ImmutableSortedMultiset NATURAL_EMPTY_MULTISET = new EmptyImmutableSortedMultiset(NATURAL_ORDER); + + + transient ImmutableSortedMultiset descendingMultiset; + + + public static ImmutableSortedMultiset of() + { + return NATURAL_EMPTY_MULTISET; + } + + + + public static > ImmutableSortedMultiset of(E element) + { + RegularImmutableSortedSet elementSet = (RegularImmutableSortedSet)ImmutableSortedSet.of(element); + + int[] counts = { 1 }; + long[] cumulativeCounts = { 0L, 1L }; + return new RegularImmutableSortedMultiset(elementSet, counts, cumulativeCounts, 0, 1); + } + + + + + + + + public static > ImmutableSortedMultiset of(E e1, E e2) + { + return copyOf(Ordering.natural(), Arrays.asList(new Comparable[] { e1, e2 })); + } + + + + + + + + public static > ImmutableSortedMultiset of(E e1, E e2, E e3) + { + return copyOf(Ordering.natural(), Arrays.asList(new Comparable[] { e1, e2, e3 })); + } + + + + + + + + + public static > ImmutableSortedMultiset of(E e1, E e2, E e3, E e4) + { + return copyOf(Ordering.natural(), Arrays.asList(new Comparable[] { e1, e2, e3, e4 })); + } + + + + + + + + + public static > ImmutableSortedMultiset of(E e1, E e2, E e3, E e4, E e5) + { + return copyOf(Ordering.natural(), Arrays.asList(new Comparable[] { e1, e2, e3, e4, e5 })); + } + + + + + + + + + public static > ImmutableSortedMultiset of(E e1, E e2, E e3, E e4, E e5, E e6, E... remaining) + { + int size = remaining.length + 6; + List all = Lists.newArrayListWithCapacity(size); + Collections.addAll(all, new Comparable[] { e1, e2, e3, e4, e5, e6 }); + Collections.addAll(all, remaining); + return copyOf(Ordering.natural(), all); + } + + + + + + + public static > ImmutableSortedMultiset copyOf(E[] elements) + { + return copyOf(Ordering.natural(), Arrays.asList(elements)); + } + + + + + + + + + + + + + + + + + + + + + + + + + + public static ImmutableSortedMultiset copyOf(Iterable elements) + { + Ordering naturalOrder = Ordering.natural(); + return copyOf(naturalOrder, elements); + } + + + + + + + + + + + + + + public static ImmutableSortedMultiset copyOf(Iterator elements) + { + Ordering naturalOrder = Ordering.natural(); + return copyOf(naturalOrder, elements); + } + + + + + + + + public static ImmutableSortedMultiset copyOf(Comparator comparator, Iterator elements) + { + Preconditions.checkNotNull(comparator); + return new Builder(comparator).addAll(elements).build(); + } + + + + + + + + + + + + public static ImmutableSortedMultiset copyOf(Comparator comparator, Iterable elements) + { + if ((elements instanceof ImmutableSortedMultiset)) + { + ImmutableSortedMultiset multiset = (ImmutableSortedMultiset)elements; + if (comparator.equals(multiset.comparator())) { + if (multiset.isPartialView()) { + return copyOfSortedEntries(comparator, multiset.entrySet().asList()); + } + return multiset; + } + } + + elements = Lists.newArrayList(elements); + TreeMultiset sortedCopy = TreeMultiset.create((Comparator)Preconditions.checkNotNull(comparator)); + Iterables.addAll(sortedCopy, elements); + return copyOfSortedEntries(comparator, sortedCopy.entrySet()); + } + + + + + + + + + + + + + + + public static ImmutableSortedMultiset copyOfSorted(SortedMultiset sortedMultiset) + { + return copyOfSortedEntries(sortedMultiset.comparator(), Lists.newArrayList(sortedMultiset.entrySet())); + } + + + private static ImmutableSortedMultiset copyOfSortedEntries(Comparator comparator, Collection> entries) + { + if (entries.isEmpty()) { + return emptyMultiset(comparator); + } + ImmutableList.Builder elementsBuilder = new ImmutableList.Builder(entries.size()); + int[] counts = new int[entries.size()]; + long[] cumulativeCounts = new long[entries.size() + 1]; + int i = 0; + for (Multiset.Entry entry : entries) { + elementsBuilder.add(entry.getElement()); + counts[i] = entry.getCount(); + cumulativeCounts[(i + 1)] = (cumulativeCounts[i] + counts[i]); + i++; + } + return new RegularImmutableSortedMultiset(new RegularImmutableSortedSet(elementsBuilder.build(), comparator), counts, cumulativeCounts, 0, entries.size()); + } + + + + static ImmutableSortedMultiset emptyMultiset(Comparator comparator) + { + if (NATURAL_ORDER.equals(comparator)) { + return NATURAL_EMPTY_MULTISET; + } + return new EmptyImmutableSortedMultiset(comparator); + } + + ImmutableSortedMultiset() {} + + public final Comparator comparator() + { + return elementSet().comparator(); + } + + + + public abstract ImmutableSortedSet elementSet(); + + + public ImmutableSortedMultiset descendingMultiset() + { + ImmutableSortedMultiset result = descendingMultiset; + if (result == null) { + return this.descendingMultiset = new DescendingImmutableSortedMultiset(this); + } + return result; + } + + + + + + + + + + @Deprecated + public final Multiset.Entry pollFirstEntry() + { + throw new UnsupportedOperationException(); + } + + + + + + + + + + @Deprecated + public final Multiset.Entry pollLastEntry() + { + throw new UnsupportedOperationException(); + } + + + public abstract ImmutableSortedMultiset headMultiset(E paramE, BoundType paramBoundType); + + + public ImmutableSortedMultiset subMultiset(E lowerBound, BoundType lowerBoundType, E upperBound, BoundType upperBoundType) + { + Preconditions.checkArgument(comparator().compare(lowerBound, upperBound) <= 0, "Expected lowerBound <= upperBound but %s > %s", new Object[] { lowerBound, upperBound }); + + return tailMultiset(lowerBound, lowerBoundType).headMultiset(upperBound, upperBoundType); + } + + + + + + public abstract ImmutableSortedMultiset tailMultiset(E paramE, BoundType paramBoundType); + + + + + + public static Builder orderedBy(Comparator comparator) + { + return new Builder(comparator); + } + + + + + + + + + public static > Builder reverseOrder() + { + return new Builder(Ordering.natural().reverse()); + } + + + + + + + + + + + public static > Builder naturalOrder() + { + return new Builder(Ordering.natural()); + } + + + + + + + + + + + + + + + + + + + + + + public static class Builder + extends ImmutableMultiset.Builder + { + public Builder(Comparator comparator) + { + super(); + } + + + + + + + + + public Builder add(E element) + { + super.add(element); + return this; + } + + + + + + + + + + + + + public Builder addCopies(E element, int occurrences) + { + super.addCopies(element, occurrences); + return this; + } + + + + + + + + + + + + public Builder setCount(E element, int count) + { + super.setCount(element, count); + return this; + } + + + + + + + + + public Builder add(E... elements) + { + super.add(elements); + return this; + } + + + + + + + + + public Builder addAll(Iterable elements) + { + super.addAll(elements); + return this; + } + + + + + + + + + public Builder addAll(Iterator elements) + { + super.addAll(elements); + return this; + } + + + + + + public ImmutableSortedMultiset build() + { + return ImmutableSortedMultiset.copyOfSorted((SortedMultiset)contents); + } + } + + private static final class SerializedForm implements Serializable + { + Comparator comparator; + E[] elements; + int[] counts; + + SerializedForm(SortedMultiset multiset) { + comparator = multiset.comparator(); + int n = multiset.entrySet().size(); + elements = ((Object[])new Object[n]); + counts = new int[n]; + int i = 0; + for (Multiset.Entry entry : multiset.entrySet()) { + elements[i] = entry.getElement(); + counts[i] = entry.getCount(); + i++; + } + } + + Object readResolve() { + int n = elements.length; + ImmutableSortedMultiset.Builder builder = new ImmutableSortedMultiset.Builder(comparator); + for (int i = 0; i < n; i++) { + builder.addCopies(elements[i], counts[i]); + } + return builder.build(); + } + } + + Object writeReplace() + { + return new SerializedForm(this); + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableSortedMultisetFauxverideShim.java b/src/minecraft/com/google/common/collect/ImmutableSortedMultisetFauxverideShim.java new file mode 100644 index 0000000..b3a547a --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableSortedMultisetFauxverideShim.java @@ -0,0 +1,154 @@ +package com.google.common.collect; + + + + + + + + + + + + + + + + + + +abstract class ImmutableSortedMultisetFauxverideShim + extends ImmutableMultiset +{ + ImmutableSortedMultisetFauxverideShim() {} + + + + + + + + + + + + + + + + + + + @Deprecated + public static ImmutableSortedMultiset.Builder builder() + { + throw new UnsupportedOperationException(); + } + + + + + + + + + + @Deprecated + public static ImmutableSortedMultiset of(E element) + { + throw new UnsupportedOperationException(); + } + + + + + + + + + + @Deprecated + public static ImmutableSortedMultiset of(E e1, E e2) + { + throw new UnsupportedOperationException(); + } + + + + + + + + + + @Deprecated + public static ImmutableSortedMultiset of(E e1, E e2, E e3) + { + throw new UnsupportedOperationException(); + } + + + + + + + + + + @Deprecated + public static ImmutableSortedMultiset of(E e1, E e2, E e3, E e4) + { + throw new UnsupportedOperationException(); + } + + + + + + + + + + + @Deprecated + public static ImmutableSortedMultiset of(E e1, E e2, E e3, E e4, E e5) + { + throw new UnsupportedOperationException(); + } + + + + + + + + + + + + + + + + + + @Deprecated + public static ImmutableSortedMultiset of(E e1, E e2, E e3, E e4, E e5, E e6, E... remaining) + { + throw new UnsupportedOperationException(); + } + + + + + + + + + + @Deprecated + public static ImmutableSortedMultiset copyOf(E[] elements) + { + throw new UnsupportedOperationException(); + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableSortedSet.java b/src/minecraft/com/google/common/collect/ImmutableSortedSet.java new file mode 100644 index 0000000..147c489 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableSortedSet.java @@ -0,0 +1,835 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.io.Serializable; +import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NavigableSet; +import java.util.SortedSet; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +public abstract class ImmutableSortedSet + extends ImmutableSortedSetFauxverideShim + implements NavigableSet, SortedIterable +{ + private static final Comparator NATURAL_ORDER = ; + + + private static final ImmutableSortedSet NATURAL_EMPTY_SET = new EmptyImmutableSortedSet(NATURAL_ORDER); + final transient Comparator comparator; + @GwtIncompatible("NavigableSet") + transient ImmutableSortedSet descendingSet; + + private static ImmutableSortedSet emptySet() { return NATURAL_EMPTY_SET; } + + + static ImmutableSortedSet emptySet(Comparator comparator) + { + if (NATURAL_ORDER.equals(comparator)) { + return emptySet(); + } + return new EmptyImmutableSortedSet(comparator); + } + + + + + public static ImmutableSortedSet of() + { + return emptySet(); + } + + + + + public static > ImmutableSortedSet of(E element) + { + return new RegularImmutableSortedSet(ImmutableList.of(element), Ordering.natural()); + } + + + + + + + + + + + public static > ImmutableSortedSet of(E e1, E e2) + { + return construct(Ordering.natural(), 2, new Comparable[] { e1, e2 }); + } + + + + + + + + + + public static > ImmutableSortedSet of(E e1, E e2, E e3) + { + return construct(Ordering.natural(), 3, new Comparable[] { e1, e2, e3 }); + } + + + + + + + + + + public static > ImmutableSortedSet of(E e1, E e2, E e3, E e4) + { + return construct(Ordering.natural(), 4, new Comparable[] { e1, e2, e3, e4 }); + } + + + + + + + + + + public static > ImmutableSortedSet of(E e1, E e2, E e3, E e4, E e5) + { + return construct(Ordering.natural(), 5, new Comparable[] { e1, e2, e3, e4, e5 }); + } + + + + + + + + + + + public static > ImmutableSortedSet of(E e1, E e2, E e3, E e4, E e5, E e6, E... remaining) + { + Comparable[] contents = new Comparable[6 + remaining.length]; + contents[0] = e1; + contents[1] = e2; + contents[2] = e3; + contents[3] = e4; + contents[4] = e5; + contents[5] = e6; + System.arraycopy(remaining, 0, contents, 6, remaining.length); + return construct(Ordering.natural(), contents.length, (Comparable[])contents); + } + + + + + + + + + + + + public static > ImmutableSortedSet copyOf(E[] elements) + { + return construct(Ordering.natural(), elements.length, (Object[])elements.clone()); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static ImmutableSortedSet copyOf(Iterable elements) + { + Ordering naturalOrder = Ordering.natural(); + return copyOf(naturalOrder, elements); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static ImmutableSortedSet copyOf(Collection elements) + { + Ordering naturalOrder = Ordering.natural(); + return copyOf(naturalOrder, elements); + } + + + + + + + + + + + + + + + + public static ImmutableSortedSet copyOf(Iterator elements) + { + Ordering naturalOrder = Ordering.natural(); + return copyOf(naturalOrder, elements); + } + + + + + + + + + + + public static ImmutableSortedSet copyOf(Comparator comparator, Iterator elements) + { + return new Builder(comparator).addAll(elements).build(); + } + + + + + + + + + + + + + + + public static ImmutableSortedSet copyOf(Comparator comparator, Iterable elements) + { + Preconditions.checkNotNull(comparator); + boolean hasSameComparator = SortedIterables.hasSameComparator(comparator, elements); + + + if ((hasSameComparator) && ((elements instanceof ImmutableSortedSet))) + { + ImmutableSortedSet original = (ImmutableSortedSet)elements; + if (!original.isPartialView()) { + return original; + } + } + + E[] array = (Object[])Iterables.toArray(elements); + return construct(comparator, array.length, array); + } + + + + + + + + + + + + + + + + + + + + public static ImmutableSortedSet copyOf(Comparator comparator, Collection elements) + { + return copyOf(comparator, elements); + } + + + + + + + + + + + + + + + + + + public static ImmutableSortedSet copyOfSorted(SortedSet sortedSet) + { + Comparator comparator = SortedIterables.comparator(sortedSet); + ImmutableList list = ImmutableList.copyOf(sortedSet); + if (list.isEmpty()) { + return emptySet(comparator); + } + return new RegularImmutableSortedSet(list, comparator); + } + + + + + + + + + + + + + + + static ImmutableSortedSet construct(Comparator comparator, int n, E... contents) + { + if (n == 0) { + return emptySet(comparator); + } + ObjectArrays.checkElementsNotNull(contents, n); + Arrays.sort(contents, 0, n, comparator); + int uniques = 1; + for (int i = 1; i < n; i++) { + E cur = contents[i]; + E prev = contents[(uniques - 1)]; + if (comparator.compare(cur, prev) != 0) { + contents[(uniques++)] = cur; + } + } + Arrays.fill(contents, uniques, n, null); + return new RegularImmutableSortedSet(ImmutableList.asImmutableList(contents, uniques), comparator); + } + + + + + + + + + + public static Builder orderedBy(Comparator comparator) + { + return new Builder(comparator); + } + + + + + public static > Builder reverseOrder() + { + return new Builder(Ordering.natural().reverse()); + } + + + + + + + + public static > Builder naturalOrder() + { + return new Builder(Ordering.natural()); + } + + + + + + + + + + + public static final class Builder + extends ImmutableSet.Builder + { + private final Comparator comparator; + + + + + + + + + + + public Builder(Comparator comparator) + { + this.comparator = ((Comparator)Preconditions.checkNotNull(comparator)); + } + + + + + + + + + + + public Builder add(E element) + { + super.add(element); + return this; + } + + + + + + + + + public Builder add(E... elements) + { + super.add(elements); + return this; + } + + + + + + + + + public Builder addAll(Iterable elements) + { + super.addAll(elements); + return this; + } + + + + + + + + + public Builder addAll(Iterator elements) + { + super.addAll(elements); + return this; + } + + + + + + public ImmutableSortedSet build() + { + E[] contentsArray = (Object[])contents; + ImmutableSortedSet result = ImmutableSortedSet.construct(comparator, size, contentsArray); + size = result.size(); + return result; + } + } + + int unsafeCompare(Object a, Object b) { + return unsafeCompare(comparator, a, b); + } + + + + + + static int unsafeCompare(Comparator comparator, Object a, Object b) + { + Comparator unsafeComparator = comparator; + return unsafeComparator.compare(a, b); + } + + + ImmutableSortedSet(Comparator comparator) + { + this.comparator = comparator; + } + + + + + + + + + public Comparator comparator() + { + return comparator; + } + + + + + + + + public abstract UnmodifiableIterator iterator(); + + + + + + + + public ImmutableSortedSet headSet(E toElement) + { + return headSet(toElement, false); + } + + + + + @GwtIncompatible("NavigableSet") + public ImmutableSortedSet headSet(E toElement, boolean inclusive) + { + return headSetImpl(Preconditions.checkNotNull(toElement), inclusive); + } + + + + + + + + + + + + + + + public ImmutableSortedSet subSet(E fromElement, E toElement) + { + return subSet(fromElement, true, toElement, false); + } + + + + + + @GwtIncompatible("NavigableSet") + public ImmutableSortedSet subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) + { + Preconditions.checkNotNull(fromElement); + Preconditions.checkNotNull(toElement); + Preconditions.checkArgument(comparator.compare(fromElement, toElement) <= 0); + return subSetImpl(fromElement, fromInclusive, toElement, toInclusive); + } + + + + + + + + + + + + + public ImmutableSortedSet tailSet(E fromElement) + { + return tailSet(fromElement, true); + } + + + + + @GwtIncompatible("NavigableSet") + public ImmutableSortedSet tailSet(E fromElement, boolean inclusive) + { + return tailSetImpl(Preconditions.checkNotNull(fromElement), inclusive); + } + + + + abstract ImmutableSortedSet headSetImpl(E paramE, boolean paramBoolean); + + + + abstract ImmutableSortedSet subSetImpl(E paramE1, boolean paramBoolean1, E paramE2, boolean paramBoolean2); + + + + abstract ImmutableSortedSet tailSetImpl(E paramE, boolean paramBoolean); + + + + @GwtIncompatible("NavigableSet") + public E lower(E e) + { + return Iterators.getNext(headSet(e, false).descendingIterator(), null); + } + + + + + @GwtIncompatible("NavigableSet") + public E floor(E e) + { + return Iterators.getNext(headSet(e, true).descendingIterator(), null); + } + + + + + @GwtIncompatible("NavigableSet") + public E ceiling(E e) + { + return Iterables.getFirst(tailSet(e, true), null); + } + + + + + @GwtIncompatible("NavigableSet") + public E higher(E e) + { + return Iterables.getFirst(tailSet(e, false), null); + } + + public E first() + { + return iterator().next(); + } + + public E last() + { + return descendingIterator().next(); + } + + + + + + + + + @Deprecated + @GwtIncompatible("NavigableSet") + public final E pollFirst() + { + throw new UnsupportedOperationException(); + } + + + + + + + + + @Deprecated + @GwtIncompatible("NavigableSet") + public final E pollLast() + { + throw new UnsupportedOperationException(); + } + + + + + + + + + @GwtIncompatible("NavigableSet") + public ImmutableSortedSet descendingSet() + { + ImmutableSortedSet result = descendingSet; + if (result == null) { + result = this.descendingSet = createDescendingSet(); + descendingSet = this; + } + return result; + } + + @GwtIncompatible("NavigableSet") + ImmutableSortedSet createDescendingSet() { + return new DescendingImmutableSortedSet(this); + } + + + + @GwtIncompatible("NavigableSet") + public abstract UnmodifiableIterator descendingIterator(); + + + + abstract int indexOf(@Nullable Object paramObject); + + + + private static class SerializedForm + implements Serializable + { + final Comparator comparator; + + final Object[] elements; + + private static final long serialVersionUID = 0L; + + + public SerializedForm(Comparator comparator, Object[] elements) + { + this.comparator = comparator; + this.elements = elements; + } + + Object readResolve() + { + return new ImmutableSortedSet.Builder(comparator).add((Object[])elements).build(); + } + } + + + private void readObject(ObjectInputStream stream) + throws InvalidObjectException + { + throw new InvalidObjectException("Use SerializedForm"); + } + + Object writeReplace() { + return new SerializedForm(comparator, toArray()); + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableSortedSetFauxverideShim.java b/src/minecraft/com/google/common/collect/ImmutableSortedSetFauxverideShim.java new file mode 100644 index 0000000..daf2d7f --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableSortedSetFauxverideShim.java @@ -0,0 +1,145 @@ +package com.google.common.collect; + + + + + + + + + + + + + + + + + + + +abstract class ImmutableSortedSetFauxverideShim + extends ImmutableSet +{ + ImmutableSortedSetFauxverideShim() {} + + + + + + + + + + + + + + + + + + + @Deprecated + public static ImmutableSortedSet.Builder builder() + { + throw new UnsupportedOperationException(); + } + + + + + + + + + @Deprecated + public static ImmutableSortedSet of(E element) + { + throw new UnsupportedOperationException(); + } + + + + + + + + + @Deprecated + public static ImmutableSortedSet of(E e1, E e2) + { + throw new UnsupportedOperationException(); + } + + + + + + + + + @Deprecated + public static ImmutableSortedSet of(E e1, E e2, E e3) + { + throw new UnsupportedOperationException(); + } + + + + + + + + + + + @Deprecated + public static ImmutableSortedSet of(E e1, E e2, E e3, E e4) + { + throw new UnsupportedOperationException(); + } + + + + + + + + + + + @Deprecated + public static ImmutableSortedSet of(E e1, E e2, E e3, E e4, E e5) + { + throw new UnsupportedOperationException(); + } + + + + + + + + + + + @Deprecated + public static ImmutableSortedSet of(E e1, E e2, E e3, E e4, E e5, E e6, E... remaining) + { + throw new UnsupportedOperationException(); + } + + + + + + + + + @Deprecated + public static ImmutableSortedSet copyOf(E[] elements) + { + throw new UnsupportedOperationException(); + } +} diff --git a/src/minecraft/com/google/common/collect/ImmutableTable.java b/src/minecraft/com/google/common/collect/ImmutableTable.java new file mode 100644 index 0000000..9b916e4 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ImmutableTable.java @@ -0,0 +1,375 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public abstract class ImmutableTable + extends AbstractTable +{ + private static final ImmutableTable EMPTY = new SparseImmutableTable(ImmutableList.of(), ImmutableSet.of(), ImmutableSet.of()); + + + + + + public static ImmutableTable of() + { + return EMPTY; + } + + + public static ImmutableTable of(R rowKey, C columnKey, V value) + { + return new SingletonImmutableTable(rowKey, columnKey, value); + } + + + + + + + + + + + + + + + + public static ImmutableTable copyOf(Table table) + { + if ((table instanceof ImmutableTable)) + { + ImmutableTable parameterizedTable = (ImmutableTable)table; + + return parameterizedTable; + } + int size = table.size(); + switch (size) { + case 0: + return of(); + case 1: + Table.Cell onlyCell = (Table.Cell)Iterables.getOnlyElement(table.cellSet()); + + return of(onlyCell.getRowKey(), onlyCell.getColumnKey(), onlyCell.getValue()); + } + + ImmutableSet.Builder> cellSetBuilder = ImmutableSet.builder(); + + + for (Table.Cell cell : table.cellSet()) + { + + + + cellSetBuilder.add(cellOf(cell.getRowKey(), cell.getColumnKey(), cell.getValue())); + } + + return RegularImmutableTable.forCells(cellSetBuilder.build()); + } + + + + + + + public static Builder builder() + { + return new Builder(); + } + + + + + static Table.Cell cellOf(R rowKey, C columnKey, V value) + { + return Tables.immutableCell(Preconditions.checkNotNull(rowKey), Preconditions.checkNotNull(columnKey), Preconditions.checkNotNull(value)); + } + + + + + + + + + + + + + + ImmutableTable() {} + + + + + + + + + + + + + + public static final class Builder + { + private final List> cells = Lists.newArrayList(); + + + private Comparator rowComparator; + + + private Comparator columnComparator; + + + public Builder() {} + + + public Builder orderRowsBy(Comparator rowComparator) + { + this.rowComparator = ((Comparator)Preconditions.checkNotNull(rowComparator)); + return this; + } + + + + + public Builder orderColumnsBy(Comparator columnComparator) + { + this.columnComparator = ((Comparator)Preconditions.checkNotNull(columnComparator)); + return this; + } + + + + + + public Builder put(R rowKey, C columnKey, V value) + { + cells.add(ImmutableTable.cellOf(rowKey, columnKey, value)); + return this; + } + + + + + + + public Builder put(Table.Cell cell) + { + if ((cell instanceof Tables.ImmutableCell)) { + Preconditions.checkNotNull(cell.getRowKey()); + Preconditions.checkNotNull(cell.getColumnKey()); + Preconditions.checkNotNull(cell.getValue()); + + Table.Cell immutableCell = cell; + cells.add(immutableCell); + } else { + put(cell.getRowKey(), cell.getColumnKey(), cell.getValue()); + } + return this; + } + + + + + + + + + public Builder putAll(Table table) + { + for (Table.Cell cell : table.cellSet()) { + put(cell); + } + return this; + } + + + + + + public ImmutableTable build() + { + int size = cells.size(); + switch (size) { + case 0: + return ImmutableTable.of(); + case 1: + return new SingletonImmutableTable((Table.Cell)Iterables.getOnlyElement(cells)); + } + + return RegularImmutableTable.forCells(cells, rowComparator, columnComparator); + } + } + + + + + public ImmutableSet> cellSet() + { + return (ImmutableSet)super.cellSet(); + } + + + abstract ImmutableSet> createCellSet(); + + final UnmodifiableIterator> cellIterator() + { + throw new AssertionError("should never be called"); + } + + public ImmutableCollection values() + { + return (ImmutableCollection)super.values(); + } + + + abstract ImmutableCollection createValues(); + + final Iterator valuesIterator() + { + throw new AssertionError("should never be called"); + } + + + + + + public ImmutableMap column(C columnKey) + { + Preconditions.checkNotNull(columnKey); + return (ImmutableMap)Objects.firstNonNull((ImmutableMap)columnMap().get(columnKey), ImmutableMap.of()); + } + + + public ImmutableSet columnKeySet() + { + return columnMap().keySet(); + } + + + + + + + public abstract ImmutableMap> columnMap(); + + + + + + + public ImmutableMap row(R rowKey) + { + Preconditions.checkNotNull(rowKey); + return (ImmutableMap)Objects.firstNonNull((ImmutableMap)rowMap().get(rowKey), ImmutableMap.of()); + } + + + public ImmutableSet rowKeySet() + { + return rowMap().keySet(); + } + + + + + public abstract ImmutableMap> rowMap(); + + + + + public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) + { + return get(rowKey, columnKey) != null; + } + + public boolean containsValue(@Nullable Object value) + { + return values().contains(value); + } + + + + + + @Deprecated + public final void clear() + { + throw new UnsupportedOperationException(); + } + + + + + + @Deprecated + public final V put(R rowKey, C columnKey, V value) + { + throw new UnsupportedOperationException(); + } + + + + + + + @Deprecated + public final void putAll(Table table) + { + throw new UnsupportedOperationException(); + } + + + + + + @Deprecated + public final V remove(Object rowKey, Object columnKey) + { + throw new UnsupportedOperationException(); + } +} diff --git a/src/minecraft/com/google/common/collect/Interner.java b/src/minecraft/com/google/common/collect/Interner.java new file mode 100644 index 0000000..d331967 --- /dev/null +++ b/src/minecraft/com/google/common/collect/Interner.java @@ -0,0 +1,9 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; + +@Beta +public abstract interface Interner +{ + public abstract E intern(E paramE); +} diff --git a/src/minecraft/com/google/common/collect/Interners.java b/src/minecraft/com/google/common/collect/Interners.java new file mode 100644 index 0000000..887a7cd --- /dev/null +++ b/src/minecraft/com/google/common/collect/Interners.java @@ -0,0 +1,136 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Equivalence; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import java.util.concurrent.ConcurrentMap; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class Interners +{ + private Interners() {} + + public static Interner newStrongInterner() + { + ConcurrentMap map = new MapMaker().makeMap(); + new Interner() { + public E intern(E sample) { + E canonical = val$map.putIfAbsent(Preconditions.checkNotNull(sample), sample); + return canonical == null ? sample : canonical; + } + }; + } + + + + + + + + + + @GwtIncompatible("java.lang.ref.WeakReference") + public static Interner newWeakInterner() { return new WeakInterner(null); } + + private static class WeakInterner implements Interner { + private final MapMakerInternalMap map; + + private WeakInterner() { map = new MapMaker().weakKeys().keyEquivalence(Equivalence.equals()).makeCustomMap(); } + + + + public E intern(E sample) + { + for (;;) + { + MapMakerInternalMap.ReferenceEntry entry = map.getEntry(sample); + if (entry != null) { + E canonical = entry.getKey(); + if (canonical != null) { + return canonical; + } + } + + + Dummy sneaky = (Dummy)map.putIfAbsent(sample, Dummy.VALUE); + if (sneaky == null) { + return sample; + } + } + } + + + + + + + private static enum Dummy + { + VALUE; + + + private Dummy() {} + } + } + + public static Function asFunction(Interner interner) + { + return new InternerFunction((Interner)Preconditions.checkNotNull(interner)); + } + + private static class InternerFunction implements Function + { + private final Interner interner; + + public InternerFunction(Interner interner) { + this.interner = interner; + } + + public E apply(E input) { + return interner.intern(input); + } + + public int hashCode() { + return interner.hashCode(); + } + + public boolean equals(Object other) { + if ((other instanceof InternerFunction)) { + InternerFunction that = (InternerFunction)other; + return interner.equals(interner); + } + + return false; + } + } +} diff --git a/src/minecraft/com/google/common/collect/Iterables.java b/src/minecraft/com/google/common/collect/Iterables.java new file mode 100644 index 0000000..f311392 --- /dev/null +++ b/src/minecraft/com/google/common/collect/Iterables.java @@ -0,0 +1,1044 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Queue; +import java.util.RandomAccess; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public final class Iterables +{ + private Iterables() {} + + public static Iterable unmodifiableIterable(Iterable iterable) + { + Preconditions.checkNotNull(iterable); + if (((iterable instanceof UnmodifiableIterable)) || ((iterable instanceof ImmutableCollection))) + { + return iterable; + } + return new UnmodifiableIterable(iterable, null); + } + + + + + + + @Deprecated + public static Iterable unmodifiableIterable(ImmutableCollection iterable) + { + return (Iterable)Preconditions.checkNotNull(iterable); + } + + private static final class UnmodifiableIterable extends FluentIterable { + private final Iterable iterable; + + private UnmodifiableIterable(Iterable iterable) { + this.iterable = iterable; + } + + public Iterator iterator() + { + return Iterators.unmodifiableIterator(iterable.iterator()); + } + + public String toString() + { + return iterable.toString(); + } + } + + + + + public static int size(Iterable iterable) + { + return (iterable instanceof Collection) ? ((Collection)iterable).size() : Iterators.size(iterable.iterator()); + } + + + + + + + public static boolean contains(Iterable iterable, @Nullable Object element) + { + if ((iterable instanceof Collection)) { + Collection collection = (Collection)iterable; + return Collections2.safeContains(collection, element); + } + return Iterators.contains(iterable.iterator(), element); + } + + + + + + + + + + + + + public static boolean removeAll(Iterable removeFrom, Collection elementsToRemove) + { + return (removeFrom instanceof Collection) ? ((Collection)removeFrom).removeAll((Collection)Preconditions.checkNotNull(elementsToRemove)) : Iterators.removeAll(removeFrom.iterator(), elementsToRemove); + } + + + + + + + + + + + + + + + public static boolean retainAll(Iterable removeFrom, Collection elementsToRetain) + { + return (removeFrom instanceof Collection) ? ((Collection)removeFrom).retainAll((Collection)Preconditions.checkNotNull(elementsToRetain)) : Iterators.retainAll(removeFrom.iterator(), elementsToRetain); + } + + + + + + + + + + + + + + + + + public static boolean removeIf(Iterable removeFrom, Predicate predicate) + { + if (((removeFrom instanceof RandomAccess)) && ((removeFrom instanceof List))) { + return removeIfFromRandomAccessList((List)removeFrom, (Predicate)Preconditions.checkNotNull(predicate)); + } + + return Iterators.removeIf(removeFrom.iterator(), predicate); + } + + + + private static boolean removeIfFromRandomAccessList(List list, Predicate predicate) + { + int from = 0; + int to = 0; + for (; + from < list.size(); from++) { + T element = list.get(from); + if (!predicate.apply(element)) { + if (from > to) { + try { + list.set(to, element); + } catch (UnsupportedOperationException e) { + slowRemoveIfForRemainingElements(list, predicate, to, from); + return true; + } + } + to++; + } + } + + + list.subList(to, list.size()).clear(); + return from != to; + } + + + + + + + + + + + + private static void slowRemoveIfForRemainingElements(List list, Predicate predicate, int to, int from) + { + for (int n = list.size() - 1; n > from; n--) { + if (predicate.apply(list.get(n))) { + list.remove(n); + } + } + + for (int n = from - 1; n >= to; n--) { + list.remove(n); + } + } + + + + @Nullable + static T removeFirstMatching(Iterable removeFrom, Predicate predicate) + { + Preconditions.checkNotNull(predicate); + Iterator iterator = removeFrom.iterator(); + while (iterator.hasNext()) { + T next = iterator.next(); + if (predicate.apply(next)) { + iterator.remove(); + return next; + } + } + return null; + } + + + + + + + + + public static boolean elementsEqual(Iterable iterable1, Iterable iterable2) + { + if (((iterable1 instanceof Collection)) && ((iterable2 instanceof Collection))) { + Collection collection1 = (Collection)iterable1; + Collection collection2 = (Collection)iterable2; + if (collection1.size() != collection2.size()) { + return false; + } + } + return Iterators.elementsEqual(iterable1.iterator(), iterable2.iterator()); + } + + + + + + + + + public static String toString(Iterable iterable) + { + return Iterators.toString(iterable.iterator()); + } + + + + + + + + public static T getOnlyElement(Iterable iterable) + { + return Iterators.getOnlyElement(iterable.iterator()); + } + + + + + + + + + @Nullable + public static T getOnlyElement(Iterable iterable, @Nullable T defaultValue) + { + return Iterators.getOnlyElement(iterable.iterator(), defaultValue); + } + + + + + + + + + @GwtIncompatible("Array.newInstance(Class, int)") + public static T[] toArray(Iterable iterable, Class type) + { + Collection collection = toCollection(iterable); + T[] array = ObjectArrays.newArray(type, collection.size()); + return collection.toArray(array); + } + + + + + + + + static Object[] toArray(Iterable iterable) + { + return toCollection(iterable).toArray(); + } + + + + + + private static Collection toCollection(Iterable iterable) + { + return (iterable instanceof Collection) ? (Collection)iterable : Lists.newArrayList(iterable.iterator()); + } + + + + + + + + + + public static boolean addAll(Collection addTo, Iterable elementsToAdd) + { + if ((elementsToAdd instanceof Collection)) { + Collection c = Collections2.cast(elementsToAdd); + return addTo.addAll(c); + } + return Iterators.addAll(addTo, ((Iterable)Preconditions.checkNotNull(elementsToAdd)).iterator()); + } + + + + + + + + public static int frequency(Iterable iterable, @Nullable Object element) + { + if ((iterable instanceof Multiset)) + return ((Multiset)iterable).count(element); + if ((iterable instanceof Set)) { + return ((Set)iterable).contains(element) ? 1 : 0; + } + return Iterators.frequency(iterable.iterator(), element); + } + + + + + + + + + + + + + + + + + + public static Iterable cycle(Iterable iterable) + { + Preconditions.checkNotNull(iterable); + new FluentIterable() + { + public Iterator iterator() { + return Iterators.cycle(val$iterable); + } + + public String toString() { return val$iterable.toString() + " (cycled)"; } + }; + } + + + + + + + + + + + + + + + + + + + + public static Iterable cycle(T... elements) + { + return cycle(Lists.newArrayList(elements)); + } + + + + + + + + + + public static Iterable concat(Iterable a, Iterable b) + { + return concat(ImmutableList.of(a, b)); + } + + + + + + + + + + + public static Iterable concat(Iterable a, Iterable b, Iterable c) + { + return concat(ImmutableList.of(a, b, c)); + } + + + + + + + + + + + + + public static Iterable concat(Iterable a, Iterable b, Iterable c, Iterable d) + { + return concat(ImmutableList.of(a, b, c, d)); + } + + + + + + + + + + + public static Iterable concat(Iterable... inputs) + { + return concat(ImmutableList.copyOf(inputs)); + } + + + + + + + + + + + + public static Iterable concat(Iterable> inputs) + { + Preconditions.checkNotNull(inputs); + new FluentIterable() + { + public Iterator iterator() { + return Iterators.concat(Iterables.iterators(val$inputs)); + } + }; + } + + + + + private static Iterator> iterators(Iterable> iterables) + { + new TransformedIterator(iterables.iterator()) + { + Iterator transform(Iterable from) + { + return from.iterator(); + } + }; + } + + + + + + + + + + + + + + + + + + + + + + public static Iterable> partition(Iterable iterable, final int size) + { + Preconditions.checkNotNull(iterable); + Preconditions.checkArgument(size > 0); + new FluentIterable() + { + public Iterator> iterator() { + return Iterators.partition(val$iterable.iterator(), size); + } + }; + } + + + + + + + + + + + + + + + + + + + public static Iterable> paddedPartition(Iterable iterable, final int size) + { + Preconditions.checkNotNull(iterable); + Preconditions.checkArgument(size > 0); + new FluentIterable() + { + public Iterator> iterator() { + return Iterators.paddedPartition(val$iterable.iterator(), size); + } + }; + } + + + + + + public static Iterable filter(Iterable unfiltered, final Predicate predicate) + { + Preconditions.checkNotNull(unfiltered); + Preconditions.checkNotNull(predicate); + new FluentIterable() + { + public Iterator iterator() { + return Iterators.filter(val$unfiltered.iterator(), predicate); + } + }; + } + + + + + + + + + + + + + @GwtIncompatible("Class.isInstance") + public static Iterable filter(Iterable unfiltered, final Class type) + { + Preconditions.checkNotNull(unfiltered); + Preconditions.checkNotNull(type); + new FluentIterable() + { + public Iterator iterator() { + return Iterators.filter(val$unfiltered.iterator(), type); + } + }; + } + + + + + public static boolean any(Iterable iterable, Predicate predicate) + { + return Iterators.any(iterable.iterator(), predicate); + } + + + + + + public static boolean all(Iterable iterable, Predicate predicate) + { + return Iterators.all(iterable.iterator(), predicate); + } + + + + + + + + + + + public static T find(Iterable iterable, Predicate predicate) + { + return Iterators.find(iterable.iterator(), predicate); + } + + + + + + + + + + @Nullable + public static T find(Iterable iterable, Predicate predicate, @Nullable T defaultValue) + { + return Iterators.find(iterable.iterator(), predicate, defaultValue); + } + + + + + + + + + + + + public static Optional tryFind(Iterable iterable, Predicate predicate) + { + return Iterators.tryFind(iterable.iterator(), predicate); + } + + + + + + + + + + + + + public static int indexOf(Iterable iterable, Predicate predicate) + { + return Iterators.indexOf(iterable.iterator(), predicate); + } + + + + + + + + + + + + + + public static Iterable transform(Iterable fromIterable, final Function function) + { + Preconditions.checkNotNull(fromIterable); + Preconditions.checkNotNull(function); + new FluentIterable() + { + public Iterator iterator() { + return Iterators.transform(val$fromIterable.iterator(), function); + } + }; + } + + + + + + + + + public static T get(Iterable iterable, int position) + { + Preconditions.checkNotNull(iterable); + return (iterable instanceof List) ? ((List)iterable).get(position) : Iterators.get(iterable.iterator(), position); + } + + + + + + + + + + + + + + + + @Nullable + public static T get(Iterable iterable, int position, @Nullable T defaultValue) + { + Preconditions.checkNotNull(iterable); + Iterators.checkNonnegative(position); + if ((iterable instanceof List)) { + List list = Lists.cast(iterable); + return position < list.size() ? list.get(position) : defaultValue; + } + Iterator iterator = iterable.iterator(); + Iterators.advance(iterator, position); + return Iterators.getNext(iterator, defaultValue); + } + + + + + + + + + + + + + + + @Nullable + public static T getFirst(Iterable iterable, @Nullable T defaultValue) + { + return Iterators.getNext(iterable.iterator(), defaultValue); + } + + + + + + + + public static T getLast(Iterable iterable) + { + if ((iterable instanceof List)) { + List list = (List)iterable; + if (list.isEmpty()) { + throw new NoSuchElementException(); + } + return getLastInNonemptyList(list); + } + + return Iterators.getLast(iterable.iterator()); + } + + + + + + + + + @Nullable + public static T getLast(Iterable iterable, @Nullable T defaultValue) + { + if ((iterable instanceof Collection)) { + Collection c = Collections2.cast(iterable); + if (c.isEmpty()) + return defaultValue; + if ((iterable instanceof List)) { + return getLastInNonemptyList(Lists.cast(iterable)); + } + } + + return Iterators.getLast(iterable.iterator(), defaultValue); + } + + private static T getLastInNonemptyList(List list) { + return list.get(list.size() - 1); + } + + + + + + + + + + + + + + + + + + + + + + public static Iterable skip(Iterable iterable, final int numberToSkip) + { + Preconditions.checkNotNull(iterable); + Preconditions.checkArgument(numberToSkip >= 0, "number to skip cannot be negative"); + + if ((iterable instanceof List)) { + List list = (List)iterable; + new FluentIterable() + { + public Iterator iterator() + { + int toSkip = Math.min(val$list.size(), numberToSkip); + return val$list.subList(toSkip, val$list.size()).iterator(); + } + }; + } + + new FluentIterable() + { + public Iterator iterator() { + final Iterator iterator = val$iterable.iterator(); + + Iterators.advance(iterator, numberToSkip); + + + + + + + new Iterator() { + boolean atStart = true; + + public boolean hasNext() + { + return iterator.hasNext(); + } + + public T next() + { + T result = iterator.next(); + atStart = false; + return result; + } + + public void remove() + { + CollectPreconditions.checkRemove(!atStart); + iterator.remove(); + } + }; + } + }; + } + + + + + + + + + + + + + + public static Iterable limit(Iterable iterable, final int limitSize) + { + Preconditions.checkNotNull(iterable); + Preconditions.checkArgument(limitSize >= 0, "limit is negative"); + new FluentIterable() + { + public Iterator iterator() { + return Iterators.limit(val$iterable.iterator(), limitSize); + } + }; + } + + + + + + + + + + + + + + + + + + + + public static Iterable consumingIterable(Iterable iterable) + { + if ((iterable instanceof Queue)) { + new FluentIterable() + { + public Iterator iterator() { + return new Iterables.ConsumingQueueIterator((Queue)val$iterable, null); + } + + public String toString() + { + return "Iterables.consumingIterable(...)"; + } + }; + } + + Preconditions.checkNotNull(iterable); + + new FluentIterable() + { + public Iterator iterator() { + return Iterators.consumingIterator(val$iterable.iterator()); + } + + public String toString() + { + return "Iterables.consumingIterable(...)"; + } + }; + } + + private static class ConsumingQueueIterator extends AbstractIterator { + private final Queue queue; + + private ConsumingQueueIterator(Queue queue) { + this.queue = queue; + } + + public T computeNext() { + try { + return queue.remove(); + } catch (NoSuchElementException e) {} + return endOfData(); + } + } + + + + + + + + + + + + + public static boolean isEmpty(Iterable iterable) + { + if ((iterable instanceof Collection)) { + return ((Collection)iterable).isEmpty(); + } + return !iterable.iterator().hasNext(); + } + + + + + + + + + + + + + + + @Beta + public static Iterable mergeSorted(Iterable> iterables, final Comparator comparator) + { + Preconditions.checkNotNull(iterables, "iterables"); + Preconditions.checkNotNull(comparator, "comparator"); + Iterable iterable = new FluentIterable() + { + public Iterator iterator() { + return Iterators.mergeSorted(Iterables.transform(val$iterables, Iterables.access$300()), comparator); + } + + + }; + return new UnmodifiableIterable(iterable, null); + } + + + + private static Function, Iterator> toIterator() + { + new Function() + { + public Iterator apply(Iterable iterable) { + return iterable.iterator(); + } + }; + } +} diff --git a/src/minecraft/com/google/common/collect/Iterators.java b/src/minecraft/com/google/common/collect/Iterators.java new file mode 100644 index 0000000..4c633d8 --- /dev/null +++ b/src/minecraft/com/google/common/collect/Iterators.java @@ -0,0 +1,1313 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Function; +import com.google.common.base.Objects; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.NoSuchElementException; +import java.util.PriorityQueue; +import java.util.Queue; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public final class Iterators +{ + static final UnmodifiableListIterator EMPTY_LIST_ITERATOR = new UnmodifiableListIterator() + { + public boolean hasNext() + { + return false; + } + + public Object next() { + throw new NoSuchElementException(); + } + + public boolean hasPrevious() { + return false; + } + + public Object previous() { + throw new NoSuchElementException(); + } + + public int nextIndex() { + return 0; + } + + public int previousIndex() { + return -1; + } + }; + + + + private Iterators() {} + + + public static UnmodifiableIterator emptyIterator() + { + return emptyListIterator(); + } + + + + + + + + + static UnmodifiableListIterator emptyListIterator() + { + return EMPTY_LIST_ITERATOR; + } + + private static final Iterator EMPTY_MODIFIABLE_ITERATOR = new Iterator() + { + public boolean hasNext() { + return false; + } + + public Object next() { + throw new NoSuchElementException(); + } + + public void remove() { + CollectPreconditions.checkRemove(false); + } + }; + + + + + + + + + static Iterator emptyModifiableIterator() + { + return EMPTY_MODIFIABLE_ITERATOR; + } + + + public static UnmodifiableIterator unmodifiableIterator(Iterator iterator) + { + Preconditions.checkNotNull(iterator); + if ((iterator instanceof UnmodifiableIterator)) { + return (UnmodifiableIterator)iterator; + } + new UnmodifiableIterator() + { + public boolean hasNext() { + return val$iterator.hasNext(); + } + + public T next() { + return val$iterator.next(); + } + }; + } + + + + + + + @Deprecated + public static UnmodifiableIterator unmodifiableIterator(UnmodifiableIterator iterator) + { + return (UnmodifiableIterator)Preconditions.checkNotNull(iterator); + } + + + + + + public static int size(Iterator iterator) + { + int count = 0; + while (iterator.hasNext()) { + iterator.next(); + count++; + } + return count; + } + + + + public static boolean contains(Iterator iterator, @Nullable Object element) + { + return any(iterator, Predicates.equalTo(element)); + } + + + + + + + + + + + public static boolean removeAll(Iterator removeFrom, Collection elementsToRemove) + { + return removeIf(removeFrom, Predicates.in(elementsToRemove)); + } + + + + + + + + + + + + + public static boolean removeIf(Iterator removeFrom, Predicate predicate) + { + Preconditions.checkNotNull(predicate); + boolean modified = false; + while (removeFrom.hasNext()) { + if (predicate.apply(removeFrom.next())) { + removeFrom.remove(); + modified = true; + } + } + return modified; + } + + + + + + + + + + + public static boolean retainAll(Iterator removeFrom, Collection elementsToRetain) + { + return removeIf(removeFrom, Predicates.not(Predicates.in(elementsToRetain))); + } + + + + + + + + + + + + public static boolean elementsEqual(Iterator iterator1, Iterator iterator2) + { + while (iterator1.hasNext()) { + if (!iterator2.hasNext()) { + return false; + } + Object o1 = iterator1.next(); + Object o2 = iterator2.next(); + if (!Objects.equal(o1, o2)) { + return false; + } + } + return !iterator2.hasNext(); + } + + + + + + public static String toString(Iterator iterator) + { + return ']'; + } + + + + + + + + + + + public static T getOnlyElement(Iterator iterator) + { + T first = iterator.next(); + if (!iterator.hasNext()) { + return first; + } + + StringBuilder sb = new StringBuilder(); + sb.append("expected one element but was: <" + first); + for (int i = 0; (i < 4) && (iterator.hasNext()); i++) { + sb.append(", " + iterator.next()); + } + if (iterator.hasNext()) { + sb.append(", ..."); + } + sb.append('>'); + + throw new IllegalArgumentException(sb.toString()); + } + + + + + + + + @Nullable + public static T getOnlyElement(Iterator iterator, @Nullable T defaultValue) + { + return iterator.hasNext() ? getOnlyElement(iterator) : defaultValue; + } + + + + + + + + + + + @GwtIncompatible("Array.newInstance(Class, int)") + public static T[] toArray(Iterator iterator, Class type) + { + List list = Lists.newArrayList(iterator); + return Iterables.toArray(list, type); + } + + + + + + + + + + public static boolean addAll(Collection addTo, Iterator iterator) + { + Preconditions.checkNotNull(addTo); + Preconditions.checkNotNull(iterator); + boolean wasModified = false; + while (iterator.hasNext()) { + wasModified |= addTo.add(iterator.next()); + } + return wasModified; + } + + + + + + + + public static int frequency(Iterator iterator, @Nullable Object element) + { + return size(filter(iterator, Predicates.equalTo(element))); + } + + + + + + + + + + + + + + + public static Iterator cycle(Iterable iterable) + { + Preconditions.checkNotNull(iterable); + new Iterator() { + Iterator iterator = Iterators.emptyIterator(); + Iterator removeFrom; + + public boolean hasNext() + { + if (!iterator.hasNext()) { + iterator = val$iterable.iterator(); + } + return iterator.hasNext(); + } + + public T next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + removeFrom = iterator; + return iterator.next(); + } + + public void remove() { + CollectPreconditions.checkRemove(removeFrom != null); + removeFrom.remove(); + removeFrom = null; + } + }; + } + + + + + + + + + + + + + + public static Iterator cycle(T... elements) + { + return cycle(Lists.newArrayList(elements)); + } + + + + + + + + + + + + + + + public static Iterator concat(Iterator a, Iterator b) + { + return concat(ImmutableList.of(a, b).iterator()); + } + + + + + + + + + + + + + + + + public static Iterator concat(Iterator a, Iterator b, Iterator c) + { + return concat(ImmutableList.of(a, b, c).iterator()); + } + + + + + + + + + + + + + + + + + public static Iterator concat(Iterator a, Iterator b, Iterator c, Iterator d) + { + return concat(ImmutableList.of(a, b, c, d).iterator()); + } + + + + + + + + + + + + + + + + public static Iterator concat(Iterator... inputs) + { + return concat(ImmutableList.copyOf(inputs).iterator()); + } + + + + + + + + + + + + + + + + public static Iterator concat(Iterator> inputs) + { + Preconditions.checkNotNull(inputs); + new Iterator() { + Iterator current = Iterators.emptyIterator(); + + + + Iterator removeFrom; + + + + + public boolean hasNext() + { + boolean currentHasNext; + + + while ((!(currentHasNext = ((Iterator)Preconditions.checkNotNull(current)).hasNext())) && (val$inputs.hasNext())) { + current = ((Iterator)val$inputs.next()); + } + return currentHasNext; + } + + public T next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + removeFrom = current; + return current.next(); + } + + public void remove() { + CollectPreconditions.checkRemove(removeFrom != null); + removeFrom.remove(); + removeFrom = null; + } + }; + } + + + + + + + + + + + + + + + + + public static UnmodifiableIterator> partition(Iterator iterator, int size) + { + return partitionImpl(iterator, size, false); + } + + + + + + + + + + + + + + + + + + public static UnmodifiableIterator> paddedPartition(Iterator iterator, int size) + { + return partitionImpl(iterator, size, true); + } + + private static UnmodifiableIterator> partitionImpl(Iterator iterator, final int size, final boolean pad) + { + Preconditions.checkNotNull(iterator); + Preconditions.checkArgument(size > 0); + new UnmodifiableIterator() + { + public boolean hasNext() { + return val$iterator.hasNext(); + } + + public List next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + Object[] array = new Object[size]; + for (int count = 0; + (count < size) && (val$iterator.hasNext()); count++) { + array[count] = val$iterator.next(); + } + for (int i = count; i < size; i++) { + array[i] = null; + } + + + List list = Collections.unmodifiableList(Arrays.asList(array)); + + return (pad) || (count == size) ? list : list.subList(0, count); + } + }; + } + + + + + public static UnmodifiableIterator filter(Iterator unfiltered, final Predicate predicate) + { + Preconditions.checkNotNull(unfiltered); + Preconditions.checkNotNull(predicate); + new AbstractIterator() { + protected T computeNext() { + while (val$unfiltered.hasNext()) { + T element = val$unfiltered.next(); + if (predicate.apply(element)) { + return element; + } + } + return endOfData(); + } + }; + } + + + + + + + + + + + + + @GwtIncompatible("Class.isInstance") + public static UnmodifiableIterator filter(Iterator unfiltered, Class type) + { + return filter(unfiltered, Predicates.instanceOf(type)); + } + + + + + + public static boolean any(Iterator iterator, Predicate predicate) + { + return indexOf(iterator, predicate) != -1; + } + + + + + + + public static boolean all(Iterator iterator, Predicate predicate) + { + Preconditions.checkNotNull(predicate); + while (iterator.hasNext()) { + T element = iterator.next(); + if (!predicate.apply(element)) { + return false; + } + } + return true; + } + + + + + + + + + + + + + public static T find(Iterator iterator, Predicate predicate) + { + return filter(iterator, predicate).next(); + } + + + + + + + + + + + + @Nullable + public static T find(Iterator iterator, Predicate predicate, @Nullable T defaultValue) + { + return getNext(filter(iterator, predicate), defaultValue); + } + + + + + + + + + + + + + + + public static Optional tryFind(Iterator iterator, Predicate predicate) + { + UnmodifiableIterator filteredIterator = filter(iterator, predicate); + return filteredIterator.hasNext() ? Optional.of(filteredIterator.next()) : Optional.absent(); + } + + + + + + + + + + + + + + + + + + + + public static int indexOf(Iterator iterator, Predicate predicate) + { + Preconditions.checkNotNull(predicate, "predicate"); + for (int i = 0; iterator.hasNext(); i++) { + T current = iterator.next(); + if (predicate.apply(current)) { + return i; + } + } + return -1; + } + + + + + + + + + + public static Iterator transform(Iterator fromIterator, final Function function) + { + Preconditions.checkNotNull(function); + new TransformedIterator(fromIterator) + { + T transform(F from) { + return function.apply(from); + } + }; + } + + + + + + + + + + + public static T get(Iterator iterator, int position) + { + checkNonnegative(position); + int skipped = advance(iterator, position); + if (!iterator.hasNext()) { + throw new IndexOutOfBoundsException("position (" + position + ") must be less than the number of elements that remained (" + skipped + ")"); + } + + + return iterator.next(); + } + + static void checkNonnegative(int position) { + if (position < 0) { + throw new IndexOutOfBoundsException("position (" + position + ") must not be negative"); + } + } + + + + + + + + + + + + + + + + + @Nullable + public static T get(Iterator iterator, int position, @Nullable T defaultValue) + { + checkNonnegative(position); + advance(iterator, position); + return getNext(iterator, defaultValue); + } + + + + + + + + + + @Nullable + public static T getNext(Iterator iterator, @Nullable T defaultValue) + { + return iterator.hasNext() ? iterator.next() : defaultValue; + } + + + + + + public static T getLast(Iterator iterator) + { + for (;;) + { + T current = iterator.next(); + if (!iterator.hasNext()) { + return current; + } + } + } + + + + + + + + + @Nullable + public static T getLast(Iterator iterator, @Nullable T defaultValue) + { + return iterator.hasNext() ? getLast(iterator) : defaultValue; + } + + + + + + + + public static int advance(Iterator iterator, int numberToAdvance) + { + Preconditions.checkNotNull(iterator); + Preconditions.checkArgument(numberToAdvance >= 0, "numberToAdvance must be nonnegative"); + + + for (int i = 0; (i < numberToAdvance) && (iterator.hasNext()); i++) { + iterator.next(); + } + return i; + } + + + + + + + + + + + + + + public static Iterator limit(final Iterator iterator, int limitSize) + { + Preconditions.checkNotNull(iterator); + Preconditions.checkArgument(limitSize >= 0, "limit is negative"); + new Iterator() + { + private int count; + + public boolean hasNext() { + return (count < val$limitSize) && (iterator.hasNext()); + } + + public T next() + { + if (!hasNext()) { + throw new NoSuchElementException(); + } + count += 1; + return iterator.next(); + } + + public void remove() + { + iterator.remove(); + } + }; + } + + + + + + + + + + + + + + public static Iterator consumingIterator(Iterator iterator) + { + Preconditions.checkNotNull(iterator); + new UnmodifiableIterator() + { + public boolean hasNext() { + return val$iterator.hasNext(); + } + + public T next() + { + T next = val$iterator.next(); + val$iterator.remove(); + return next; + } + + public String toString() + { + return "Iterators.consumingIterator(...)"; + } + }; + } + + + + + @Nullable + static T pollNext(Iterator iterator) + { + if (iterator.hasNext()) { + T result = iterator.next(); + iterator.remove(); + return result; + } + return null; + } + + + + + + + static void clear(Iterator iterator) + { + Preconditions.checkNotNull(iterator); + while (iterator.hasNext()) { + iterator.next(); + iterator.remove(); + } + } + + + + + + + + + + + + + + public static UnmodifiableIterator forArray(T... array) + { + return forArray(array, 0, array.length, 0); + } + + + + + + + + + static UnmodifiableListIterator forArray(final T[] array, final int offset, int length, int index) + { + Preconditions.checkArgument(length >= 0); + int end = offset + length; + + + Preconditions.checkPositionIndexes(offset, end, array.length); + Preconditions.checkPositionIndex(index, length); + if (length == 0) { + return emptyListIterator(); + } + + + + + + + new AbstractIndexedListIterator(length, index) { + protected T get(int index) { + return array[(offset + index)]; + } + }; + } + + + + + + + + public static UnmodifiableIterator singletonIterator(@Nullable T value) + { + new UnmodifiableIterator() { + boolean done; + + public boolean hasNext() { + return !done; + } + + public T next() { + if (done) { + throw new NoSuchElementException(); + } + done = true; + return val$value; + } + }; + } + + + + + + + + + + public static UnmodifiableIterator forEnumeration(Enumeration enumeration) + { + Preconditions.checkNotNull(enumeration); + new UnmodifiableIterator() + { + public boolean hasNext() { + return val$enumeration.hasMoreElements(); + } + + public T next() { + return val$enumeration.nextElement(); + } + }; + } + + + + + + + + public static Enumeration asEnumeration(Iterator iterator) + { + Preconditions.checkNotNull(iterator); + new Enumeration() + { + public boolean hasMoreElements() { + return val$iterator.hasNext(); + } + + public T nextElement() { + return val$iterator.next(); + } + }; + } + + + private static class PeekingImpl + implements PeekingIterator + { + private final Iterator iterator; + private boolean hasPeeked; + private E peekedElement; + + public PeekingImpl(Iterator iterator) + { + this.iterator = ((Iterator)Preconditions.checkNotNull(iterator)); + } + + public boolean hasNext() + { + return (hasPeeked) || (iterator.hasNext()); + } + + public E next() + { + if (!hasPeeked) { + return iterator.next(); + } + E result = peekedElement; + hasPeeked = false; + peekedElement = null; + return result; + } + + public void remove() + { + Preconditions.checkState(!hasPeeked, "Can't remove after you've peeked at next"); + iterator.remove(); + } + + public E peek() + { + if (!hasPeeked) { + peekedElement = iterator.next(); + hasPeeked = true; + } + return peekedElement; + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static PeekingIterator peekingIterator(Iterator iterator) + { + if ((iterator instanceof PeekingImpl)) + { + + + PeekingImpl peeking = (PeekingImpl)iterator; + return peeking; + } + return new PeekingImpl(iterator); + } + + + + + + + @Deprecated + public static PeekingIterator peekingIterator(PeekingIterator iterator) + { + return (PeekingIterator)Preconditions.checkNotNull(iterator); + } + + + + + + + + + + + + + + + + @Beta + public static UnmodifiableIterator mergeSorted(Iterable> iterators, Comparator comparator) + { + Preconditions.checkNotNull(iterators, "iterators"); + Preconditions.checkNotNull(comparator, "comparator"); + + return new MergingIterator(iterators, comparator); + } + + + + + + + private static class MergingIterator + extends UnmodifiableIterator + { + final Queue> queue; + + + + + + public MergingIterator(Iterable> iterators, final Comparator itemComparator) + { + Comparator> heapComparator = new Comparator() + { + public int compare(PeekingIterator o1, PeekingIterator o2) + { + return itemComparator.compare(o1.peek(), o2.peek()); + } + + }; + queue = new PriorityQueue(2, heapComparator); + + for (Iterator iterator : iterators) { + if (iterator.hasNext()) { + queue.add(Iterators.peekingIterator(iterator)); + } + } + } + + public boolean hasNext() + { + return !queue.isEmpty(); + } + + public T next() + { + PeekingIterator nextIter = (PeekingIterator)queue.remove(); + T next = nextIter.next(); + if (nextIter.hasNext()) { + queue.add(nextIter); + } + return next; + } + } + + + + static ListIterator cast(Iterator iterator) + { + return (ListIterator)iterator; + } +} diff --git a/src/minecraft/com/google/common/collect/LexicographicalOrdering.java b/src/minecraft/com/google/common/collect/LexicographicalOrdering.java new file mode 100644 index 0000000..bd0c621 --- /dev/null +++ b/src/minecraft/com/google/common/collect/LexicographicalOrdering.java @@ -0,0 +1,76 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.io.Serializable; +import java.util.Iterator; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true) +final class LexicographicalOrdering + extends Ordering> + implements Serializable +{ + final Ordering elementOrder; + private static final long serialVersionUID = 0L; + + LexicographicalOrdering(Ordering elementOrder) + { + this.elementOrder = elementOrder; + } + + public int compare(Iterable leftIterable, Iterable rightIterable) + { + Iterator left = leftIterable.iterator(); + Iterator right = rightIterable.iterator(); + while (left.hasNext()) { + if (!right.hasNext()) { + return 1; + } + int result = elementOrder.compare(left.next(), right.next()); + if (result != 0) { + return result; + } + } + if (right.hasNext()) { + return -1; + } + return 0; + } + + public boolean equals(@Nullable Object object) { + if (object == this) { + return true; + } + if ((object instanceof LexicographicalOrdering)) { + LexicographicalOrdering that = (LexicographicalOrdering)object; + return elementOrder.equals(elementOrder); + } + return false; + } + + public int hashCode() { + return elementOrder.hashCode() ^ 0x7BB78CF5; + } + + public String toString() { + return elementOrder + ".lexicographical()"; + } +} diff --git a/src/minecraft/com/google/common/collect/LinkedHashMultimap.java b/src/minecraft/com/google/common/collect/LinkedHashMultimap.java new file mode 100644 index 0000000..89cd223 --- /dev/null +++ b/src/minecraft/com/google/common/collect/LinkedHashMultimap.java @@ -0,0 +1,592 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Objects; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Arrays; +import java.util.Collection; +import java.util.ConcurrentModificationException; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NoSuchElementException; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +public final class LinkedHashMultimap + extends AbstractSetMultimap +{ + private static final int DEFAULT_KEY_CAPACITY = 16; + private static final int DEFAULT_VALUE_SET_CAPACITY = 2; + @VisibleForTesting + static final double VALUE_SET_LOAD_FACTOR = 1.0D; + + public static LinkedHashMultimap create() + { + return new LinkedHashMultimap(16, 2); + } + + + + + + + + + + + public static LinkedHashMultimap create(int expectedKeys, int expectedValuesPerKey) + { + return new LinkedHashMultimap(Maps.capacity(expectedKeys), Maps.capacity(expectedValuesPerKey)); + } + + + + + + + + + + + + + public static LinkedHashMultimap create(Multimap multimap) + { + LinkedHashMultimap result = create(multimap.keySet().size(), 2); + result.putAll(multimap); + return result; + } + + + + + + + + + private static void succeedsInValueSet(ValueSetLink pred, ValueSetLink succ) + { + pred.setSuccessorInValueSet(succ); + succ.setPredecessorInValueSet(pred); + } + + private static void succeedsInMultimap(ValueEntry pred, ValueEntry succ) + { + pred.setSuccessorInMultimap(succ); + succ.setPredecessorInMultimap(pred); + } + + private static void deleteFromValueSet(ValueSetLink entry) { + succeedsInValueSet(entry.getPredecessorInValueSet(), entry.getSuccessorInValueSet()); + } + + private static void deleteFromMultimap(ValueEntry entry) { + succeedsInMultimap(entry.getPredecessorInMultimap(), entry.getSuccessorInMultimap()); + } + + private static abstract interface ValueSetLink { + public abstract ValueSetLink getPredecessorInValueSet(); + + public abstract ValueSetLink getSuccessorInValueSet(); + + public abstract void setPredecessorInValueSet(ValueSetLink paramValueSetLink); + + public abstract void setSuccessorInValueSet(ValueSetLink paramValueSetLink); + } + + @VisibleForTesting + static final class ValueEntry extends ImmutableEntry implements LinkedHashMultimap.ValueSetLink { + final int smearedValueHash; + @Nullable + ValueEntry nextInValueBucket; + LinkedHashMultimap.ValueSetLink predecessorInValueSet; + LinkedHashMultimap.ValueSetLink successorInValueSet; + ValueEntry predecessorInMultimap; + ValueEntry successorInMultimap; + + ValueEntry(@Nullable K key, @Nullable V value, int smearedValueHash, @Nullable ValueEntry nextInValueBucket) { + super(value); + this.smearedValueHash = smearedValueHash; + this.nextInValueBucket = nextInValueBucket; + } + + boolean matchesValue(@Nullable Object v, int smearedVHash) { + return (smearedValueHash == smearedVHash) && (Objects.equal(getValue(), v)); + } + + public LinkedHashMultimap.ValueSetLink getPredecessorInValueSet() + { + return predecessorInValueSet; + } + + public LinkedHashMultimap.ValueSetLink getSuccessorInValueSet() + { + return successorInValueSet; + } + + public void setPredecessorInValueSet(LinkedHashMultimap.ValueSetLink entry) + { + predecessorInValueSet = entry; + } + + public void setSuccessorInValueSet(LinkedHashMultimap.ValueSetLink entry) + { + successorInValueSet = entry; + } + + public ValueEntry getPredecessorInMultimap() { + return predecessorInMultimap; + } + + public ValueEntry getSuccessorInMultimap() { + return successorInMultimap; + } + + public void setSuccessorInMultimap(ValueEntry multimapSuccessor) { + successorInMultimap = multimapSuccessor; + } + + public void setPredecessorInMultimap(ValueEntry multimapPredecessor) { + predecessorInMultimap = multimapPredecessor; + } + } + + + + + @VisibleForTesting + transient int valueSetCapacity = 2; + private transient ValueEntry multimapHeaderEntry; + + private LinkedHashMultimap(int keyCapacity, int valueSetCapacity) { + super(new LinkedHashMap(keyCapacity)); + CollectPreconditions.checkNonnegative(valueSetCapacity, "expectedValuesPerKey"); + + this.valueSetCapacity = valueSetCapacity; + multimapHeaderEntry = new ValueEntry(null, null, 0, null); + succeedsInMultimap(multimapHeaderEntry, multimapHeaderEntry); + } + + + + + + + + + + + Set createCollection() + { + return new LinkedHashSet(valueSetCapacity); + } + + + + + + + + + + + Collection createCollection(K key) + { + return new ValueSet(key, valueSetCapacity); + } + + + + + + + + + + public Set replaceValues(@Nullable K key, Iterable values) + { + return super.replaceValues(key, values); + } + + + + + + + @GwtIncompatible("java serialization not supported") + private static final long serialVersionUID = 1L; + + + + + public Set> entries() + { + return super.entries(); + } + + + + + + + + public Collection values() + { + return super.values(); + } + + + @VisibleForTesting + final class ValueSet + extends Sets.ImprovedAbstractSet + implements LinkedHashMultimap.ValueSetLink + { + private final K key; + @VisibleForTesting + LinkedHashMultimap.ValueEntry[] hashTable; + private int size = 0; + private int modCount = 0; + + private LinkedHashMultimap.ValueSetLink firstEntry; + + private LinkedHashMultimap.ValueSetLink lastEntry; + + ValueSet(int key) + { + this.key = key; + firstEntry = this; + lastEntry = this; + + int tableSize = Hashing.closedTableSize(expectedValues, 1.0D); + + + LinkedHashMultimap.ValueEntry[] hashTable = new LinkedHashMultimap.ValueEntry[tableSize]; + this.hashTable = hashTable; + } + + private int mask() { + return hashTable.length - 1; + } + + public LinkedHashMultimap.ValueSetLink getPredecessorInValueSet() + { + return lastEntry; + } + + public LinkedHashMultimap.ValueSetLink getSuccessorInValueSet() + { + return firstEntry; + } + + public void setPredecessorInValueSet(LinkedHashMultimap.ValueSetLink entry) + { + lastEntry = entry; + } + + public void setSuccessorInValueSet(LinkedHashMultimap.ValueSetLink entry) + { + firstEntry = entry; + } + + public Iterator iterator() + { + new Iterator() { + LinkedHashMultimap.ValueSetLink nextEntry = firstEntry; + LinkedHashMultimap.ValueEntry toRemove; + int expectedModCount = modCount; + + private void checkForComodification() { + if (modCount != expectedModCount) { + throw new ConcurrentModificationException(); + } + } + + public boolean hasNext() + { + checkForComodification(); + return nextEntry != LinkedHashMultimap.ValueSet.this; + } + + public V next() + { + if (!hasNext()) { + throw new NoSuchElementException(); + } + LinkedHashMultimap.ValueEntry entry = (LinkedHashMultimap.ValueEntry)nextEntry; + V result = entry.getValue(); + toRemove = entry; + nextEntry = entry.getSuccessorInValueSet(); + return result; + } + + public void remove() + { + checkForComodification(); + CollectPreconditions.checkRemove(toRemove != null); + remove(toRemove.getValue()); + expectedModCount = modCount; + toRemove = null; + } + }; + } + + public int size() + { + return size; + } + + public boolean contains(@Nullable Object o) + { + int smearedHash = Hashing.smearedHash(o); + for (LinkedHashMultimap.ValueEntry entry = hashTable[(smearedHash & mask())]; entry != null; + entry = nextInValueBucket) { + if (entry.matchesValue(o, smearedHash)) { + return true; + } + } + return false; + } + + public boolean add(@Nullable V value) + { + int smearedHash = Hashing.smearedHash(value); + int bucket = smearedHash & mask(); + LinkedHashMultimap.ValueEntry rowHead = hashTable[bucket]; + for (LinkedHashMultimap.ValueEntry entry = rowHead; entry != null; + entry = nextInValueBucket) { + if (entry.matchesValue(value, smearedHash)) { + return false; + } + } + + LinkedHashMultimap.ValueEntry newEntry = new LinkedHashMultimap.ValueEntry(key, value, smearedHash, rowHead); + LinkedHashMultimap.succeedsInValueSet(lastEntry, newEntry); + LinkedHashMultimap.succeedsInValueSet(newEntry, this); + LinkedHashMultimap.succeedsInMultimap(multimapHeaderEntry.getPredecessorInMultimap(), newEntry); + LinkedHashMultimap.succeedsInMultimap(newEntry, multimapHeaderEntry); + hashTable[bucket] = newEntry; + size += 1; + modCount += 1; + rehashIfNecessary(); + return true; + } + + private void rehashIfNecessary() { + if (Hashing.needsResizing(size, this.hashTable.length, 1.0D)) + { + LinkedHashMultimap.ValueEntry[] hashTable = new LinkedHashMultimap.ValueEntry[this.hashTable.length * 2]; + this.hashTable = hashTable; + int mask = hashTable.length - 1; + for (LinkedHashMultimap.ValueSetLink entry = firstEntry; + entry != this; entry = entry.getSuccessorInValueSet()) { + LinkedHashMultimap.ValueEntry valueEntry = (LinkedHashMultimap.ValueEntry)entry; + int bucket = smearedValueHash & mask; + nextInValueBucket = hashTable[bucket]; + hashTable[bucket] = valueEntry; + } + } + } + + public boolean remove(@Nullable Object o) + { + int smearedHash = Hashing.smearedHash(o); + int bucket = smearedHash & mask(); + LinkedHashMultimap.ValueEntry prev = null; + for (LinkedHashMultimap.ValueEntry entry = hashTable[bucket]; entry != null; + entry = nextInValueBucket) { + if (entry.matchesValue(o, smearedHash)) { + if (prev == null) + { + hashTable[bucket] = nextInValueBucket; + } else { + nextInValueBucket = nextInValueBucket; + } + LinkedHashMultimap.deleteFromValueSet(entry); + LinkedHashMultimap.deleteFromMultimap(entry); + size -= 1; + modCount += 1; + return true; + } + prev = entry; + } + + + + + + + + + + + + + + return false; + } + + public void clear() + { + Arrays.fill(hashTable, null); + size = 0; + for (LinkedHashMultimap.ValueSetLink entry = firstEntry; + entry != this; entry = entry.getSuccessorInValueSet()) { + LinkedHashMultimap.ValueEntry valueEntry = (LinkedHashMultimap.ValueEntry)entry; + LinkedHashMultimap.deleteFromMultimap(valueEntry); + } + LinkedHashMultimap.succeedsInValueSet(this, this); + modCount += 1; + } + } + + Iterator> entryIterator() + { + new Iterator() { + LinkedHashMultimap.ValueEntry nextEntry = multimapHeaderEntry.successorInMultimap; + LinkedHashMultimap.ValueEntry toRemove; + + public boolean hasNext() + { + return nextEntry != multimapHeaderEntry; + } + + public Map.Entry next() + { + if (!hasNext()) { + throw new NoSuchElementException(); + } + LinkedHashMultimap.ValueEntry result = nextEntry; + toRemove = result; + nextEntry = nextEntry.successorInMultimap; + return result; + } + + public void remove() + { + CollectPreconditions.checkRemove(toRemove != null); + remove(toRemove.getKey(), toRemove.getValue()); + toRemove = null; + } + }; + } + + Iterator valueIterator() + { + return Maps.valueIterator(entryIterator()); + } + + public void clear() + { + super.clear(); + succeedsInMultimap(multimapHeaderEntry, multimapHeaderEntry); + } + + + + @GwtIncompatible("java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) + throws IOException + { + stream.defaultWriteObject(); + stream.writeInt(valueSetCapacity); + stream.writeInt(keySet().size()); + for (K key : keySet()) { + stream.writeObject(key); + } + stream.writeInt(size()); + for (Map.Entry entry : entries()) { + stream.writeObject(entry.getKey()); + stream.writeObject(entry.getValue()); + } + } + + @GwtIncompatible("java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException + { + stream.defaultReadObject(); + multimapHeaderEntry = new ValueEntry(null, null, 0, null); + succeedsInMultimap(multimapHeaderEntry, multimapHeaderEntry); + valueSetCapacity = stream.readInt(); + int distinctKeys = stream.readInt(); + Map> map = new LinkedHashMap(Maps.capacity(distinctKeys)); + + for (int i = 0; i < distinctKeys; i++) + { + K key = stream.readObject(); + map.put(key, createCollection(key)); + } + int entries = stream.readInt(); + for (int i = 0; i < entries; i++) + { + K key = stream.readObject(); + + V value = stream.readObject(); + ((Collection)map.get(key)).add(value); + } + setMap(map); + } +} diff --git a/src/minecraft/com/google/common/collect/LinkedHashMultiset.java b/src/minecraft/com/google/common/collect/LinkedHashMultiset.java new file mode 100644 index 0000000..f35abe5 --- /dev/null +++ b/src/minecraft/com/google/common/collect/LinkedHashMultiset.java @@ -0,0 +1,110 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.LinkedHashMap; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +public final class LinkedHashMultiset + extends AbstractMapBasedMultiset +{ + @GwtIncompatible("not needed in emulated source") + private static final long serialVersionUID = 0L; + + public static LinkedHashMultiset create() + { + return new LinkedHashMultiset(); + } + + + + + + + + public static LinkedHashMultiset create(int distinctElements) + { + return new LinkedHashMultiset(distinctElements); + } + + + + + + + + + + public static LinkedHashMultiset create(Iterable elements) + { + LinkedHashMultiset multiset = create(Multisets.inferDistinctElements(elements)); + + Iterables.addAll(multiset, elements); + return multiset; + } + + private LinkedHashMultiset() { + super(new LinkedHashMap()); + } + + private LinkedHashMultiset(int distinctElements) + { + super(new LinkedHashMap(Maps.capacity(distinctElements))); + } + + + + @GwtIncompatible("java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) + throws IOException + { + stream.defaultWriteObject(); + Serialization.writeMultiset(this, stream); + } + + @GwtIncompatible("java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException + { + stream.defaultReadObject(); + int distinctElements = Serialization.readCount(stream); + setBackingMap(new LinkedHashMap(Maps.capacity(distinctElements))); + + Serialization.populateMultiset(this, stream, distinctElements); + } +} diff --git a/src/minecraft/com/google/common/collect/LinkedListMultimap.java b/src/minecraft/com/google/common/collect/LinkedListMultimap.java new file mode 100644 index 0000000..ec747fa --- /dev/null +++ b/src/minecraft/com/google/common/collect/LinkedListMultimap.java @@ -0,0 +1 @@ +null \ No newline at end of file diff --git a/src/minecraft/com/google/common/collect/ListMultimap.java b/src/minecraft/com/google/common/collect/ListMultimap.java new file mode 100644 index 0000000..fc8ea84 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ListMultimap.java @@ -0,0 +1,22 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract interface ListMultimap + extends Multimap +{ + public abstract List get(@Nullable K paramK); + + public abstract List removeAll(@Nullable Object paramObject); + + public abstract List replaceValues(K paramK, Iterable paramIterable); + + public abstract Map> asMap(); + + public abstract boolean equals(@Nullable Object paramObject); +} diff --git a/src/minecraft/com/google/common/collect/Lists.java b/src/minecraft/com/google/common/collect/Lists.java new file mode 100644 index 0000000..5866532 --- /dev/null +++ b/src/minecraft/com/google/common/collect/Lists.java @@ -0,0 +1,1044 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.math.IntMath; +import com.google.common.primitives.Ints; +import java.io.Serializable; +import java.math.RoundingMode; +import java.util.AbstractList; +import java.util.AbstractSequentialList; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.NoSuchElementException; +import java.util.RandomAccess; +import java.util.concurrent.CopyOnWriteArrayList; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public final class Lists +{ + private Lists() {} + + @GwtCompatible(serializable=true) + public static ArrayList newArrayList() + { + return new ArrayList(); + } + + + + + + + + + + + + @GwtCompatible(serializable=true) + public static ArrayList newArrayList(E... elements) + { + Preconditions.checkNotNull(elements); + + int capacity = computeArrayListCapacity(elements.length); + ArrayList list = new ArrayList(capacity); + Collections.addAll(list, elements); + return list; + } + + @VisibleForTesting + static int computeArrayListCapacity(int arraySize) { CollectPreconditions.checkNonnegative(arraySize, "arraySize"); + + + return Ints.saturatedCast(5L + arraySize + arraySize / 10); + } + + + + + + + + + + + @GwtCompatible(serializable=true) + public static ArrayList newArrayList(Iterable elements) + { + Preconditions.checkNotNull(elements); + + return (elements instanceof Collection) ? new ArrayList(Collections2.cast(elements)) : newArrayList(elements.iterator()); + } + + + + + + + + + + + + + @GwtCompatible(serializable=true) + public static ArrayList newArrayList(Iterator elements) + { + ArrayList list = newArrayList(); + Iterators.addAll(list, elements); + return list; + } + + + + + + + + + + + + + + + + + + + + + + @GwtCompatible(serializable=true) + public static ArrayList newArrayListWithCapacity(int initialArraySize) + { + CollectPreconditions.checkNonnegative(initialArraySize, "initialArraySize"); + return new ArrayList(initialArraySize); + } + + + + + + + + + + + + + + + + + @GwtCompatible(serializable=true) + public static ArrayList newArrayListWithExpectedSize(int estimatedSize) + { + return new ArrayList(computeArrayListCapacity(estimatedSize)); + } + + + + + + + + + + + @GwtCompatible(serializable=true) + public static LinkedList newLinkedList() + { + return new LinkedList(); + } + + + + + + + + @GwtCompatible(serializable=true) + public static LinkedList newLinkedList(Iterable elements) + { + LinkedList list = newLinkedList(); + Iterables.addAll(list, elements); + return list; + } + + + + + + + + + + @GwtIncompatible("CopyOnWriteArrayList") + public static CopyOnWriteArrayList newCopyOnWriteArrayList() + { + return new CopyOnWriteArrayList(); + } + + + + + + + + + + + @GwtIncompatible("CopyOnWriteArrayList") + public static CopyOnWriteArrayList newCopyOnWriteArrayList(Iterable elements) + { + Collection elementsCollection = (elements instanceof Collection) ? Collections2.cast(elements) : newArrayList(elements); + + + return new CopyOnWriteArrayList(elementsCollection); + } + + + + + + + + + + + + + + + + + public static List asList(@Nullable E first, E[] rest) + { + return new OnePlusArrayList(first, rest); + } + + private static class OnePlusArrayList extends AbstractList implements Serializable, RandomAccess + { + final E first; + final E[] rest; + private static final long serialVersionUID = 0L; + + OnePlusArrayList(@Nullable E first, E[] rest) { + this.first = first; + this.rest = ((Object[])Preconditions.checkNotNull(rest)); + } + + public int size() { return rest.length + 1; } + + public E get(int index) + { + Preconditions.checkElementIndex(index, size()); + return index == 0 ? first : rest[(index - 1)]; + } + } + + + + + + + + + + + + + + + + + + + + public static List asList(@Nullable E first, @Nullable E second, E[] rest) + { + return new TwoPlusArrayList(first, second, rest); + } + + private static class TwoPlusArrayList extends AbstractList implements Serializable, RandomAccess + { + final E first; + final E second; + final E[] rest; + private static final long serialVersionUID = 0L; + + TwoPlusArrayList(@Nullable E first, @Nullable E second, E[] rest) { + this.first = first; + this.second = second; + this.rest = ((Object[])Preconditions.checkNotNull(rest)); + } + + public int size() { return rest.length + 2; } + + public E get(int index) { + switch (index) { + case 0: + return first; + case 1: + return second; + } + + Preconditions.checkElementIndex(index, size()); + return rest[(index - 2)]; + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + static List> cartesianProduct(List> lists) + { + return CartesianList.create(lists); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + static List> cartesianProduct(List... lists) + { + return cartesianProduct(Arrays.asList(lists)); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static List transform(List fromList, Function function) + { + return (fromList instanceof RandomAccess) ? new TransformingRandomAccessList(fromList, function) : new TransformingSequentialList(fromList, function); + } + + + private static class TransformingSequentialList + extends AbstractSequentialList + implements Serializable + { + final List fromList; + + final Function function; + + private static final long serialVersionUID = 0L; + + + TransformingSequentialList(List fromList, Function function) + { + this.fromList = ((List)Preconditions.checkNotNull(fromList)); + this.function = ((Function)Preconditions.checkNotNull(function)); + } + + + + + public void clear() + { + fromList.clear(); + } + + public int size() { return fromList.size(); } + + public ListIterator listIterator(int index) { + new TransformedListIterator(fromList.listIterator(index)) + { + T transform(F from) { + return function.apply(from); + } + }; + } + } + + + + private static class TransformingRandomAccessList + extends AbstractList + implements RandomAccess, Serializable + { + final List fromList; + + + final Function function; + + + private static final long serialVersionUID = 0L; + + + TransformingRandomAccessList(List fromList, Function function) + { + this.fromList = ((List)Preconditions.checkNotNull(fromList)); + this.function = ((Function)Preconditions.checkNotNull(function)); + } + + public void clear() { fromList.clear(); } + + public T get(int index) { + return function.apply(fromList.get(index)); + } + + public Iterator iterator() { return listIterator(); } + + public ListIterator listIterator(int index) { + new TransformedListIterator(fromList.listIterator(index)) + { + T transform(F from) { + return function.apply(from); + } + }; + } + + public boolean isEmpty() { return fromList.isEmpty(); } + + public T remove(int index) { + return function.apply(fromList.remove(index)); + } + + public int size() { return fromList.size(); } + } + + + + + + + + + + + + + + + + + + + + + public static List> partition(List list, int size) + { + Preconditions.checkNotNull(list); + Preconditions.checkArgument(size > 0); + return (list instanceof RandomAccess) ? new RandomAccessPartition(list, size) : new Partition(list, size); + } + + private static class Partition extends AbstractList> + { + final List list; + final int size; + + Partition(List list, int size) + { + this.list = list; + this.size = size; + } + + public List get(int index) { + Preconditions.checkElementIndex(index, size()); + int start = index * size; + int end = Math.min(start + size, list.size()); + return list.subList(start, end); + } + + public int size() { + return IntMath.divide(list.size(), size, RoundingMode.CEILING); + } + + public boolean isEmpty() { + return list.isEmpty(); + } + } + + private static class RandomAccessPartition extends Lists.Partition implements RandomAccess + { + RandomAccessPartition(List list, int size) { + super(size); + } + } + + + + + + @Beta + public static ImmutableList charactersOf(String string) + { + return new StringAsImmutableList((String)Preconditions.checkNotNull(string)); + } + + private static final class StringAsImmutableList + extends ImmutableList + { + private final String string; + + StringAsImmutableList(String string) + { + this.string = string; + } + + public int indexOf(@Nullable Object object) { + return (object instanceof Character) ? string.indexOf(((Character)object).charValue()) : -1; + } + + public int lastIndexOf(@Nullable Object object) + { + return (object instanceof Character) ? string.lastIndexOf(((Character)object).charValue()) : -1; + } + + + public ImmutableList subList(int fromIndex, int toIndex) + { + Preconditions.checkPositionIndexes(fromIndex, toIndex, size()); + return Lists.charactersOf(string.substring(fromIndex, toIndex)); + } + + boolean isPartialView() { + return false; + } + + public Character get(int index) { + Preconditions.checkElementIndex(index, size()); + return Character.valueOf(string.charAt(index)); + } + + public int size() { + return string.length(); + } + } + + + + + + + + + + + @Beta + public static List charactersOf(CharSequence sequence) + { + return new CharSequenceAsList((CharSequence)Preconditions.checkNotNull(sequence)); + } + + private static final class CharSequenceAsList extends AbstractList + { + private final CharSequence sequence; + + CharSequenceAsList(CharSequence sequence) { + this.sequence = sequence; + } + + public Character get(int index) { + Preconditions.checkElementIndex(index, size()); + return Character.valueOf(sequence.charAt(index)); + } + + public int size() { + return sequence.length(); + } + } + + + + + + + + + + + + + public static List reverse(List list) + { + if ((list instanceof ImmutableList)) + return ((ImmutableList)list).reverse(); + if ((list instanceof ReverseList)) + return ((ReverseList)list).getForwardList(); + if ((list instanceof RandomAccess)) { + return new RandomAccessReverseList(list); + } + return new ReverseList(list); + } + + private static class ReverseList extends AbstractList + { + private final List forwardList; + + ReverseList(List forwardList) { + this.forwardList = ((List)Preconditions.checkNotNull(forwardList)); + } + + List getForwardList() { + return forwardList; + } + + private int reverseIndex(int index) { + int size = size(); + Preconditions.checkElementIndex(index, size); + return size - 1 - index; + } + + private int reversePosition(int index) { + int size = size(); + Preconditions.checkPositionIndex(index, size); + return size - index; + } + + public void add(int index, @Nullable T element) { + forwardList.add(reversePosition(index), element); + } + + public void clear() { + forwardList.clear(); + } + + public T remove(int index) { + return forwardList.remove(reverseIndex(index)); + } + + protected void removeRange(int fromIndex, int toIndex) { + subList(fromIndex, toIndex).clear(); + } + + public T set(int index, @Nullable T element) { + return forwardList.set(reverseIndex(index), element); + } + + public T get(int index) { + return forwardList.get(reverseIndex(index)); + } + + public int size() { + return forwardList.size(); + } + + public List subList(int fromIndex, int toIndex) { + Preconditions.checkPositionIndexes(fromIndex, toIndex, size()); + return Lists.reverse(forwardList.subList(reversePosition(toIndex), reversePosition(fromIndex))); + } + + public Iterator iterator() + { + return listIterator(); + } + + public ListIterator listIterator(int index) { + int start = reversePosition(index); + final ListIterator forwardIterator = forwardList.listIterator(start); + new ListIterator() + { + boolean canRemoveOrSet; + + public void add(T e) { + forwardIterator.add(e); + forwardIterator.previous(); + canRemoveOrSet = false; + } + + public boolean hasNext() { + return forwardIterator.hasPrevious(); + } + + public boolean hasPrevious() { + return forwardIterator.hasNext(); + } + + public T next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + canRemoveOrSet = true; + return forwardIterator.previous(); + } + + public int nextIndex() { + return Lists.ReverseList.this.reversePosition(forwardIterator.nextIndex()); + } + + public T previous() { + if (!hasPrevious()) { + throw new NoSuchElementException(); + } + canRemoveOrSet = true; + return forwardIterator.next(); + } + + public int previousIndex() { + return nextIndex() - 1; + } + + public void remove() { + CollectPreconditions.checkRemove(canRemoveOrSet); + forwardIterator.remove(); + canRemoveOrSet = false; + } + + public void set(T e) { + Preconditions.checkState(canRemoveOrSet); + forwardIterator.set(e); + } + }; + } + } + + private static class RandomAccessReverseList extends Lists.ReverseList implements RandomAccess + { + RandomAccessReverseList(List forwardList) { + super(); + } + } + + + + + static int hashCodeImpl(List list) + { + int hashCode = 1; + for (Object o : list) { + hashCode = 31 * hashCode + (o == null ? 0 : o.hashCode()); + + hashCode = hashCode ^ 0xFFFFFFFF ^ 0xFFFFFFFF; + } + + return hashCode; + } + + + + static boolean equalsImpl(List list, @Nullable Object object) + { + if (object == Preconditions.checkNotNull(list)) { + return true; + } + if (!(object instanceof List)) { + return false; + } + + List o = (List)object; + + return (list.size() == o.size()) && (Iterators.elementsEqual(list.iterator(), o.iterator())); + } + + + + + + static boolean addAllImpl(List list, int index, Iterable elements) + { + boolean changed = false; + ListIterator listIterator = list.listIterator(index); + for (E e : elements) { + listIterator.add(e); + changed = true; + } + return changed; + } + + + + static int indexOfImpl(List list, @Nullable Object element) + { + ListIterator listIterator = list.listIterator(); + while (listIterator.hasNext()) { + if (Objects.equal(element, listIterator.next())) { + return listIterator.previousIndex(); + } + } + return -1; + } + + + + static int lastIndexOfImpl(List list, @Nullable Object element) + { + ListIterator listIterator = list.listIterator(list.size()); + while (listIterator.hasPrevious()) { + if (Objects.equal(element, listIterator.previous())) { + return listIterator.nextIndex(); + } + } + return -1; + } + + + + static ListIterator listIteratorImpl(List list, int index) + { + return new AbstractListWrapper(list).listIterator(index); + } + + + static List subListImpl(List list, int fromIndex, int toIndex) + { + List wrapper; + + List wrapper; + if ((list instanceof RandomAccess)) { + wrapper = new RandomAccessListWrapper(list) { private static final long serialVersionUID = 0L; + + public ListIterator listIterator(int index) { return backingList.listIterator(index); + } + + }; + } + else { + wrapper = new AbstractListWrapper(list) { private static final long serialVersionUID = 0L; + + public ListIterator listIterator(int index) { return backingList.listIterator(index); } + }; + } + + + + return wrapper.subList(fromIndex, toIndex); + } + + private static class AbstractListWrapper extends AbstractList { + final List backingList; + + AbstractListWrapper(List backingList) { + this.backingList = ((List)Preconditions.checkNotNull(backingList)); + } + + public void add(int index, E element) { + backingList.add(index, element); + } + + public boolean addAll(int index, Collection c) { + return backingList.addAll(index, c); + } + + public E get(int index) { + return backingList.get(index); + } + + public E remove(int index) { + return backingList.remove(index); + } + + public E set(int index, E element) { + return backingList.set(index, element); + } + + public boolean contains(Object o) { + return backingList.contains(o); + } + + public int size() { + return backingList.size(); + } + } + + private static class RandomAccessListWrapper extends Lists.AbstractListWrapper implements RandomAccess + { + RandomAccessListWrapper(List backingList) { + super(); + } + } + + + + static List cast(Iterable iterable) + { + return (List)iterable; + } +} diff --git a/src/minecraft/com/google/common/collect/MapConstraint.java b/src/minecraft/com/google/common/collect/MapConstraint.java new file mode 100644 index 0000000..fc632d4 --- /dev/null +++ b/src/minecraft/com/google/common/collect/MapConstraint.java @@ -0,0 +1,14 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import javax.annotation.Nullable; + +@GwtCompatible +@Beta +public abstract interface MapConstraint +{ + public abstract void checkKeyValue(@Nullable K paramK, @Nullable V paramV); + + public abstract String toString(); +} diff --git a/src/minecraft/com/google/common/collect/MapConstraints.java b/src/minecraft/com/google/common/collect/MapConstraints.java new file mode 100644 index 0000000..ab94ccd --- /dev/null +++ b/src/minecraft/com/google/common/collect/MapConstraints.java @@ -0,0 +1,784 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.SortedSet; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +public final class MapConstraints +{ + private MapConstraints() {} + + public static MapConstraint notNull() + { + return NotNullMapConstraint.INSTANCE; + } + + private static enum NotNullMapConstraint implements MapConstraint + { + INSTANCE; + + private NotNullMapConstraint() {} + + public void checkKeyValue(Object key, Object value) { Preconditions.checkNotNull(key); + Preconditions.checkNotNull(value); + } + + public String toString() { + return "Not null"; + } + } + + + + + + + + + + + + + + public static Map constrainedMap(Map map, MapConstraint constraint) + { + return new ConstrainedMap(map, constraint); + } + + + + + + + + + + + + + + + + + + public static Multimap constrainedMultimap(Multimap multimap, MapConstraint constraint) + { + return new ConstrainedMultimap(multimap, constraint); + } + + + + + + + + + + + + + + + + + + + public static ListMultimap constrainedListMultimap(ListMultimap multimap, MapConstraint constraint) + { + return new ConstrainedListMultimap(multimap, constraint); + } + + + + + + + + + + + + + + + + + + public static SetMultimap constrainedSetMultimap(SetMultimap multimap, MapConstraint constraint) + { + return new ConstrainedSetMultimap(multimap, constraint); + } + + + + + + + + + + + + + + + + + + public static SortedSetMultimap constrainedSortedSetMultimap(SortedSetMultimap multimap, MapConstraint constraint) + { + return new ConstrainedSortedSetMultimap(multimap, constraint); + } + + + + + + + + + + + + private static Map.Entry constrainedEntry(Map.Entry entry, final MapConstraint constraint) + { + Preconditions.checkNotNull(entry); + Preconditions.checkNotNull(constraint); + new ForwardingMapEntry() + { + protected Map.Entry delegate() { return val$entry; } + + public V setValue(V value) { + constraint.checkKeyValue(getKey(), value); + return val$entry.setValue(value); + } + }; + } + + + + + + + + + + + + + private static Map.Entry> constrainedAsMapEntry(Map.Entry> entry, final MapConstraint constraint) + { + Preconditions.checkNotNull(entry); + Preconditions.checkNotNull(constraint); + new ForwardingMapEntry() { + protected Map.Entry> delegate() { + return val$entry; + } + + public Collection getValue() { Constraints.constrainedTypePreservingCollection((Collection)val$entry.getValue(), new Constraint() + { + public V checkElement(V value) + { + val$constraint.checkKeyValue(getKey(), value); + return value; + } + }); } + }; + } + + + + + + + + + + + + + + + + private static Set>> constrainedAsMapEntries(Set>> entries, MapConstraint constraint) + { + return new ConstrainedAsMapEntries(entries, constraint); + } + + + + + + + + + + + + + + + private static Collection> constrainedEntries(Collection> entries, MapConstraint constraint) + { + if ((entries instanceof Set)) { + return constrainedEntrySet((Set)entries, constraint); + } + return new ConstrainedEntries(entries, constraint); + } + + + + + + + + + + + + + + + + + private static Set> constrainedEntrySet(Set> entries, MapConstraint constraint) + { + return new ConstrainedEntrySet(entries, constraint); + } + + static class ConstrainedMap extends ForwardingMap + { + private final Map delegate; + final MapConstraint constraint; + private transient Set> entrySet; + + ConstrainedMap(Map delegate, MapConstraint constraint) + { + this.delegate = ((Map)Preconditions.checkNotNull(delegate)); + this.constraint = ((MapConstraint)Preconditions.checkNotNull(constraint)); + } + + protected Map delegate() { return delegate; } + + public Set> entrySet() { + Set> result = entrySet; + if (result == null) { + entrySet = (result = MapConstraints.constrainedEntrySet(delegate.entrySet(), constraint)); + } + + return result; + } + + public V put(K key, V value) { constraint.checkKeyValue(key, value); + return delegate.put(key, value); + } + + public void putAll(Map map) { delegate.putAll(MapConstraints.checkMap(map, constraint)); } + } + + + + + + + + + + + + + + public static BiMap constrainedBiMap(BiMap map, MapConstraint constraint) + { + return new ConstrainedBiMap(map, null, constraint); + } + + + + + + + + private static class ConstrainedBiMap + extends MapConstraints.ConstrainedMap + implements BiMap + { + volatile BiMap inverse; + + + + + + + ConstrainedBiMap(BiMap delegate, @Nullable BiMap inverse, MapConstraint constraint) + { + super(constraint); + this.inverse = inverse; + } + + protected BiMap delegate() { + return (BiMap)super.delegate(); + } + + public V forcePut(K key, V value) + { + constraint.checkKeyValue(key, value); + return delegate().forcePut(key, value); + } + + public BiMap inverse() + { + if (inverse == null) { + inverse = new ConstrainedBiMap(delegate().inverse(), this, new MapConstraints.InverseConstraint(constraint)); + } + + return inverse; + } + + public Set values() { + return delegate().values(); + } + } + + private static class InverseConstraint implements MapConstraint + { + final MapConstraint constraint; + + public InverseConstraint(MapConstraint constraint) { + this.constraint = ((MapConstraint)Preconditions.checkNotNull(constraint)); + } + + public void checkKeyValue(K key, V value) { + constraint.checkKeyValue(value, key); + } + } + + private static class ConstrainedMultimap + extends ForwardingMultimap implements Serializable + { + final MapConstraint constraint; + final Multimap delegate; + transient Collection> entries; + transient Map> asMap; + + public ConstrainedMultimap(Multimap delegate, MapConstraint constraint) + { + this.delegate = ((Multimap)Preconditions.checkNotNull(delegate)); + this.constraint = ((MapConstraint)Preconditions.checkNotNull(constraint)); + } + + protected Multimap delegate() { + return delegate; + } + + public Map> asMap() { + Map> result = asMap; + if (result == null) { + final Map> asMapDelegate = delegate.asMap(); + + asMap = (result = new ForwardingMap() { + Set>> entrySet; + Collection> values; + + protected Map> delegate() { + return asMapDelegate; + } + + public Set>> entrySet() { + Set>> result = entrySet; + if (result == null) { + entrySet = (result = MapConstraints.constrainedAsMapEntries(asMapDelegate.entrySet(), constraint)); + } + + return result; + } + + public Collection get(Object key) + { + try { + Collection collection = MapConstraints.ConstrainedMultimap.this.get(key); + return collection.isEmpty() ? null : collection; + } catch (ClassCastException e) {} + return null; + } + + public Collection> values() + { + Collection> result = values; + if (result == null) { + values = (result = new MapConstraints.ConstrainedAsMapValues(delegate().values(), entrySet())); + } + + return result; + } + + public boolean containsValue(Object o) { + return values().contains(o); + } + }); + } + return result; + } + + public Collection> entries() { + Collection> result = entries; + if (result == null) { + entries = (result = MapConstraints.constrainedEntries(delegate.entries(), constraint)); + } + return result; + } + + public Collection get(final K key) { + Constraints.constrainedTypePreservingCollection(delegate.get(key), new Constraint() + { + public V checkElement(V value) + { + constraint.checkKeyValue(key, value); + return value; + } + }); + } + + public boolean put(K key, V value) { + constraint.checkKeyValue(key, value); + return delegate.put(key, value); + } + + public boolean putAll(K key, Iterable values) { + return delegate.putAll(key, MapConstraints.checkValues(key, values, constraint)); + } + + public boolean putAll(Multimap multimap) + { + boolean changed = false; + for (Map.Entry entry : multimap.entries()) { + changed |= put(entry.getKey(), entry.getValue()); + } + return changed; + } + + public Collection replaceValues(K key, Iterable values) + { + return delegate.replaceValues(key, MapConstraints.checkValues(key, values, constraint)); + } + } + + + + private static class ConstrainedAsMapValues + extends ForwardingCollection> + { + final Collection> delegate; + + final Set>> entrySet; + + + ConstrainedAsMapValues(Collection> delegate, Set>> entrySet) + { + this.delegate = delegate; + this.entrySet = entrySet; + } + + protected Collection> delegate() { return delegate; } + + public Iterator> iterator() + { + final Iterator>> iterator = entrySet.iterator(); + new Iterator() + { + public boolean hasNext() { + return iterator.hasNext(); + } + + public Collection next() { + return (Collection)((Map.Entry)iterator.next()).getValue(); + } + + public void remove() { + iterator.remove(); + } + }; + } + + public Object[] toArray() { + return standardToArray(); + } + + public T[] toArray(T[] array) { return standardToArray(array); } + + public boolean contains(Object o) { + return standardContains(o); + } + + public boolean containsAll(Collection c) { return standardContainsAll(c); } + + public boolean remove(Object o) { + return standardRemove(o); + } + + public boolean removeAll(Collection c) { return standardRemoveAll(c); } + + public boolean retainAll(Collection c) { + return standardRetainAll(c); + } + } + + private static class ConstrainedEntries + extends ForwardingCollection> + { + final MapConstraint constraint; + final Collection> entries; + + ConstrainedEntries(Collection> entries, MapConstraint constraint) + { + this.entries = entries; + this.constraint = constraint; + } + + protected Collection> delegate() { return entries; } + + public Iterator> iterator() + { + final Iterator> iterator = entries.iterator(); + new ForwardingIterator() { + public Map.Entry next() { + return MapConstraints.constrainedEntry((Map.Entry)iterator.next(), constraint); + } + + protected Iterator> delegate() { return iterator; } + }; + } + + + + public Object[] toArray() + { + return standardToArray(); + } + + public T[] toArray(T[] array) { return standardToArray(array); } + + public boolean contains(Object o) { + return Maps.containsEntryImpl(delegate(), o); + } + + public boolean containsAll(Collection c) { return standardContainsAll(c); } + + public boolean remove(Object o) { + return Maps.removeEntryImpl(delegate(), o); + } + + public boolean removeAll(Collection c) { return standardRemoveAll(c); } + + public boolean retainAll(Collection c) { + return standardRetainAll(c); + } + } + + static class ConstrainedEntrySet + extends MapConstraints.ConstrainedEntries implements Set> + { + ConstrainedEntrySet(Set> entries, MapConstraint constraint) + { + super(constraint); + } + + + public boolean equals(@Nullable Object object) + { + return Sets.equalsImpl(this, object); + } + + public int hashCode() { + return Sets.hashCodeImpl(this); + } + } + + static class ConstrainedAsMapEntries + extends ForwardingSet>> + { + private final MapConstraint constraint; + private final Set>> entries; + + ConstrainedAsMapEntries(Set>> entries, MapConstraint constraint) + { + this.entries = entries; + this.constraint = constraint; + } + + protected Set>> delegate() { + return entries; + } + + public Iterator>> iterator() { + final Iterator>> iterator = entries.iterator(); + new ForwardingIterator() { + public Map.Entry> next() { + return MapConstraints.constrainedAsMapEntry((Map.Entry)iterator.next(), constraint); + } + + protected Iterator>> delegate() { return iterator; } + }; + } + + + + public Object[] toArray() + { + return standardToArray(); + } + + public T[] toArray(T[] array) { + return standardToArray(array); + } + + public boolean contains(Object o) { + return Maps.containsEntryImpl(delegate(), o); + } + + public boolean containsAll(Collection c) { + return standardContainsAll(c); + } + + public boolean equals(@Nullable Object object) { + return standardEquals(object); + } + + public int hashCode() { + return standardHashCode(); + } + + public boolean remove(Object o) { + return Maps.removeEntryImpl(delegate(), o); + } + + public boolean removeAll(Collection c) { + return standardRemoveAll(c); + } + + public boolean retainAll(Collection c) { + return standardRetainAll(c); + } + } + + private static class ConstrainedListMultimap extends MapConstraints.ConstrainedMultimap implements ListMultimap + { + ConstrainedListMultimap(ListMultimap delegate, MapConstraint constraint) + { + super(constraint); + } + + public List get(K key) { return (List)super.get(key); } + + public List removeAll(Object key) { + return (List)super.removeAll(key); + } + + public List replaceValues(K key, Iterable values) { + return (List)super.replaceValues(key, values); + } + } + + private static class ConstrainedSetMultimap extends MapConstraints.ConstrainedMultimap implements SetMultimap + { + ConstrainedSetMultimap(SetMultimap delegate, MapConstraint constraint) + { + super(constraint); + } + + public Set get(K key) { return (Set)super.get(key); } + + public Set> entries() { + return (Set)super.entries(); + } + + public Set removeAll(Object key) { return (Set)super.removeAll(key); } + + public Set replaceValues(K key, Iterable values) + { + return (Set)super.replaceValues(key, values); + } + } + + private static class ConstrainedSortedSetMultimap extends MapConstraints.ConstrainedSetMultimap implements SortedSetMultimap + { + ConstrainedSortedSetMultimap(SortedSetMultimap delegate, MapConstraint constraint) + { + super(constraint); + } + + public SortedSet get(K key) { return (SortedSet)super.get(key); } + + public SortedSet removeAll(Object key) { + return (SortedSet)super.removeAll(key); + } + + public SortedSet replaceValues(K key, Iterable values) { + return (SortedSet)super.replaceValues(key, values); + } + + public Comparator valueComparator() { + return ((SortedSetMultimap)delegate()).valueComparator(); + } + } + + + private static Collection checkValues(K key, Iterable values, MapConstraint constraint) + { + Collection copy = Lists.newArrayList(values); + for (V value : copy) { + constraint.checkKeyValue(key, value); + } + return copy; + } + + private static Map checkMap(Map map, MapConstraint constraint) + { + Map copy = new LinkedHashMap(map); + for (Map.Entry entry : copy.entrySet()) { + constraint.checkKeyValue(entry.getKey(), entry.getValue()); + } + return copy; + } +} diff --git a/src/minecraft/com/google/common/collect/MapDifference.java b/src/minecraft/com/google/common/collect/MapDifference.java new file mode 100644 index 0000000..680b1c3 --- /dev/null +++ b/src/minecraft/com/google/common/collect/MapDifference.java @@ -0,0 +1,34 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Map; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract interface MapDifference +{ + public abstract boolean areEqual(); + + public abstract Map entriesOnlyOnLeft(); + + public abstract Map entriesOnlyOnRight(); + + public abstract Map entriesInCommon(); + + public abstract Map> entriesDiffering(); + + public abstract boolean equals(@Nullable Object paramObject); + + public abstract int hashCode(); + + public static abstract interface ValueDifference + { + public abstract V leftValue(); + + public abstract V rightValue(); + + public abstract boolean equals(@Nullable Object paramObject); + + public abstract int hashCode(); + } +} diff --git a/src/minecraft/com/google/common/collect/MapMaker.java b/src/minecraft/com/google/common/collect/MapMaker.java new file mode 100644 index 0000000..154ec4e --- /dev/null +++ b/src/minecraft/com/google/common/collect/MapMaker.java @@ -0,0 +1,899 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Ascii; +import com.google.common.base.Equivalence; +import com.google.common.base.Function; +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; +import com.google.common.base.Preconditions; +import com.google.common.base.Throwables; +import com.google.common.base.Ticker; +import java.io.Serializable; +import java.util.AbstractMap; +import java.util.Collections; +import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public final class MapMaker + extends GenericMapMaker +{ + private static final int DEFAULT_INITIAL_CAPACITY = 16; + private static final int DEFAULT_CONCURRENCY_LEVEL = 4; + private static final int DEFAULT_EXPIRATION_NANOS = 0; + static final int UNSET_INT = -1; + boolean useCustomMap; + int initialCapacity = -1; + int concurrencyLevel = -1; + int maximumSize = -1; + + MapMakerInternalMap.Strength keyStrength; + + MapMakerInternalMap.Strength valueStrength; + long expireAfterWriteNanos = -1L; + long expireAfterAccessNanos = -1L; + + + + RemovalCause nullRemovalCause; + + + + Equivalence keyEquivalence; + + + + Ticker ticker; + + + + + public MapMaker() {} + + + + @GwtIncompatible("To be supported") + MapMaker keyEquivalence(Equivalence equivalence) + { + Preconditions.checkState(keyEquivalence == null, "key equivalence was already set to %s", new Object[] { keyEquivalence }); + keyEquivalence = ((Equivalence)Preconditions.checkNotNull(equivalence)); + useCustomMap = true; + return this; + } + + Equivalence getKeyEquivalence() { + return (Equivalence)Objects.firstNonNull(keyEquivalence, getKeyStrength().defaultEquivalence()); + } + + + + + + + + + + + + public MapMaker initialCapacity(int initialCapacity) + { + Preconditions.checkState(this.initialCapacity == -1, "initial capacity was already set to %s", new Object[] { Integer.valueOf(this.initialCapacity) }); + + Preconditions.checkArgument(initialCapacity >= 0); + this.initialCapacity = initialCapacity; + return this; + } + + int getInitialCapacity() { + return initialCapacity == -1 ? 16 : initialCapacity; + } + + + + + + + + + + + + + + + + + + + + + + + + + @Deprecated + MapMaker maximumSize(int size) + { + Preconditions.checkState(maximumSize == -1, "maximum size was already set to %s", new Object[] { Integer.valueOf(maximumSize) }); + + Preconditions.checkArgument(size >= 0, "maximum size must not be negative"); + maximumSize = size; + useCustomMap = true; + if (maximumSize == 0) + { + nullRemovalCause = RemovalCause.SIZE; + } + return this; + } + + + + + + + + + + + + + + + + + + + + + public MapMaker concurrencyLevel(int concurrencyLevel) + { + Preconditions.checkState(this.concurrencyLevel == -1, "concurrency level was already set to %s", new Object[] { Integer.valueOf(this.concurrencyLevel) }); + + Preconditions.checkArgument(concurrencyLevel > 0); + this.concurrencyLevel = concurrencyLevel; + return this; + } + + int getConcurrencyLevel() { + return concurrencyLevel == -1 ? 4 : concurrencyLevel; + } + + + + + + + + + + + + + @GwtIncompatible("java.lang.ref.WeakReference") + public MapMaker weakKeys() + { + return setKeyStrength(MapMakerInternalMap.Strength.WEAK); + } + + MapMaker setKeyStrength(MapMakerInternalMap.Strength strength) { + Preconditions.checkState(keyStrength == null, "Key strength was already set to %s", new Object[] { keyStrength }); + keyStrength = ((MapMakerInternalMap.Strength)Preconditions.checkNotNull(strength)); + Preconditions.checkArgument(keyStrength != MapMakerInternalMap.Strength.SOFT, "Soft keys are not supported"); + if (strength != MapMakerInternalMap.Strength.STRONG) + { + useCustomMap = true; + } + return this; + } + + MapMakerInternalMap.Strength getKeyStrength() { + return (MapMakerInternalMap.Strength)Objects.firstNonNull(keyStrength, MapMakerInternalMap.Strength.STRONG); + } + + + + + + + + + + + + + + + + + + + @GwtIncompatible("java.lang.ref.WeakReference") + public MapMaker weakValues() + { + return setValueStrength(MapMakerInternalMap.Strength.WEAK); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + @Deprecated + @GwtIncompatible("java.lang.ref.SoftReference") + public MapMaker softValues() + { + return setValueStrength(MapMakerInternalMap.Strength.SOFT); + } + + MapMaker setValueStrength(MapMakerInternalMap.Strength strength) { + Preconditions.checkState(valueStrength == null, "Value strength was already set to %s", new Object[] { valueStrength }); + valueStrength = ((MapMakerInternalMap.Strength)Preconditions.checkNotNull(strength)); + if (strength != MapMakerInternalMap.Strength.STRONG) + { + useCustomMap = true; + } + return this; + } + + MapMakerInternalMap.Strength getValueStrength() { + return (MapMakerInternalMap.Strength)Objects.firstNonNull(valueStrength, MapMakerInternalMap.Strength.STRONG); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + @Deprecated + MapMaker expireAfterWrite(long duration, TimeUnit unit) + { + checkExpiration(duration, unit); + expireAfterWriteNanos = unit.toNanos(duration); + if ((duration == 0L) && (nullRemovalCause == null)) + { + nullRemovalCause = RemovalCause.EXPIRED; + } + useCustomMap = true; + return this; + } + + private void checkExpiration(long duration, TimeUnit unit) { + Preconditions.checkState(expireAfterWriteNanos == -1L, "expireAfterWrite was already set to %s ns", new Object[] { Long.valueOf(expireAfterWriteNanos) }); + + Preconditions.checkState(expireAfterAccessNanos == -1L, "expireAfterAccess was already set to %s ns", new Object[] { Long.valueOf(expireAfterAccessNanos) }); + + Preconditions.checkArgument(duration >= 0L, "duration cannot be negative: %s %s", new Object[] { Long.valueOf(duration), unit }); + } + + long getExpireAfterWriteNanos() { + return expireAfterWriteNanos == -1L ? 0L : expireAfterWriteNanos; + } + + + + + + + + + + + + + + + + + + + + + + + + + + + @Deprecated + @GwtIncompatible("To be supported") + MapMaker expireAfterAccess(long duration, TimeUnit unit) + { + checkExpiration(duration, unit); + expireAfterAccessNanos = unit.toNanos(duration); + if ((duration == 0L) && (nullRemovalCause == null)) + { + nullRemovalCause = RemovalCause.EXPIRED; + } + useCustomMap = true; + return this; + } + + long getExpireAfterAccessNanos() { + return expireAfterAccessNanos == -1L ? 0L : expireAfterAccessNanos; + } + + Ticker getTicker() + { + return (Ticker)Objects.firstNonNull(ticker, Ticker.systemTicker()); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @Deprecated + @GwtIncompatible("To be supported") + GenericMapMaker removalListener(RemovalListener listener) + { + Preconditions.checkState(removalListener == null); + + + + GenericMapMaker me = this; + removalListener = ((RemovalListener)Preconditions.checkNotNull(listener)); + useCustomMap = true; + return me; + } + + + + + + + + + + + + + + public ConcurrentMap makeMap() + { + if (!useCustomMap) { + return new ConcurrentHashMap(getInitialCapacity(), 0.75F, getConcurrencyLevel()); + } + return (ConcurrentMap)(nullRemovalCause == null ? new MapMakerInternalMap(this) : new NullConcurrentMap(this)); + } + + + + + + + + @GwtIncompatible("MapMakerInternalMap") + MapMakerInternalMap makeCustomMap() + { + return new MapMakerInternalMap(this); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @Deprecated + ConcurrentMap makeComputingMap(Function computingFunction) + { + return (ConcurrentMap)(nullRemovalCause == null ? new ComputingMapAdapter(this, computingFunction) : new NullComputingConcurrentMap(this, computingFunction)); + } + + + + + + + + public String toString() + { + Objects.ToStringHelper s = Objects.toStringHelper(this); + if (initialCapacity != -1) { + s.add("initialCapacity", initialCapacity); + } + if (concurrencyLevel != -1) { + s.add("concurrencyLevel", concurrencyLevel); + } + if (maximumSize != -1) { + s.add("maximumSize", maximumSize); + } + if (expireAfterWriteNanos != -1L) { + s.add("expireAfterWrite", expireAfterWriteNanos + "ns"); + } + if (expireAfterAccessNanos != -1L) { + s.add("expireAfterAccess", expireAfterAccessNanos + "ns"); + } + if (keyStrength != null) { + s.add("keyStrength", Ascii.toLowerCase(keyStrength.toString())); + } + if (valueStrength != null) { + s.add("valueStrength", Ascii.toLowerCase(valueStrength.toString())); + } + if (keyEquivalence != null) { + s.addValue("keyEquivalence"); + } + if (removalListener != null) { + s.addValue("removalListener"); + } + return s.toString(); + } + + + + + + + + static abstract interface RemovalListener + { + public abstract void onRemoval(MapMaker.RemovalNotification paramRemovalNotification); + } + + + + + + + + static final class RemovalNotification + extends ImmutableEntry + { + private static final long serialVersionUID = 0L; + + + + + + private final MapMaker.RemovalCause cause; + + + + + + + RemovalNotification(@Nullable K key, @Nullable V value, MapMaker.RemovalCause cause) + { + super(value); + this.cause = cause; + } + + + + public MapMaker.RemovalCause getCause() + { + return cause; + } + + + + + public boolean wasEvicted() + { + return cause.wasEvicted(); + } + } + + + + + + + + static abstract enum RemovalCause + { + EXPLICIT, + + + + + + + + + + + + + REPLACED, + + + + + + + + + + + COLLECTED, + + + + + + + + + + + EXPIRED, + + + + + + + + + + + SIZE; + + + private RemovalCause() {} + + + abstract boolean wasEvicted(); + } + + + static class NullConcurrentMap + extends AbstractMap + implements ConcurrentMap, Serializable + { + private static final long serialVersionUID = 0L; + + private final MapMaker.RemovalListener removalListener; + + private final MapMaker.RemovalCause removalCause; + + + NullConcurrentMap(MapMaker mapMaker) + { + removalListener = mapMaker.getRemovalListener(); + removalCause = nullRemovalCause; + } + + + + public boolean containsKey(@Nullable Object key) + { + return false; + } + + public boolean containsValue(@Nullable Object value) + { + return false; + } + + public V get(@Nullable Object key) + { + return null; + } + + void notifyRemoval(K key, V value) { + MapMaker.RemovalNotification notification = new MapMaker.RemovalNotification(key, value, removalCause); + + removalListener.onRemoval(notification); + } + + public V put(K key, V value) + { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(value); + notifyRemoval(key, value); + return null; + } + + public V putIfAbsent(K key, V value) + { + return put(key, value); + } + + public V remove(@Nullable Object key) + { + return null; + } + + public boolean remove(@Nullable Object key, @Nullable Object value) + { + return false; + } + + public V replace(K key, V value) + { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(value); + return null; + } + + public boolean replace(K key, @Nullable V oldValue, V newValue) + { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(newValue); + return false; + } + + public Set> entrySet() + { + return Collections.emptySet(); + } + } + + static final class NullComputingConcurrentMap + extends MapMaker.NullConcurrentMap + { + private static final long serialVersionUID = 0L; + final Function computingFunction; + + NullComputingConcurrentMap(MapMaker mapMaker, Function computingFunction) + { + super(); + this.computingFunction = ((Function)Preconditions.checkNotNull(computingFunction)); + } + + + public V get(Object k) + { + K key = k; + V value = compute(key); + Preconditions.checkNotNull(value, "%s returned null for key %s.", new Object[] { computingFunction, key }); + notifyRemoval(key, value); + return value; + } + + private V compute(K key) { + Preconditions.checkNotNull(key); + try { + return computingFunction.apply(key); + } catch (ComputationException e) { + throw e; + } catch (Throwable t) { + throw new ComputationException(t); + } + } + } + + + + + static final class ComputingMapAdapter + extends ComputingConcurrentHashMap + implements Serializable + { + private static final long serialVersionUID = 0L; + + + + + ComputingMapAdapter(MapMaker mapMaker, Function computingFunction) + { + super(computingFunction); + } + + public V get(Object key) + { + V value; + try + { + value = getOrCompute(key); + } catch (ExecutionException e) { + Throwable cause = e.getCause(); + Throwables.propagateIfInstanceOf(cause, ComputationException.class); + throw new ComputationException(cause); + } + + if (value == null) { + throw new NullPointerException(computingFunction + " returned null for key " + key + "."); + } + return value; + } + } +} diff --git a/src/minecraft/com/google/common/collect/MapMakerInternalMap.java b/src/minecraft/com/google/common/collect/MapMakerInternalMap.java new file mode 100644 index 0000000..3ab0e1d --- /dev/null +++ b/src/minecraft/com/google/common/collect/MapMakerInternalMap.java @@ -0,0 +1,4018 @@ +package com.google.common.collect; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Equivalence; +import com.google.common.base.Preconditions; +import com.google.common.base.Ticker; +import com.google.common.primitives.Ints; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.SoftReference; +import java.lang.ref.WeakReference; +import java.util.AbstractCollection; +import java.util.AbstractMap; +import java.util.AbstractQueue; +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NoSuchElementException; +import java.util.Queue; +import java.util.Set; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReferenceArray; +import java.util.concurrent.locks.ReentrantLock; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; +import javax.annotation.concurrent.GuardedBy; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +class MapMakerInternalMap + extends AbstractMap + implements ConcurrentMap, Serializable +{ + static final int MAXIMUM_CAPACITY = 1073741824; + static final int MAX_SEGMENTS = 65536; + static final int CONTAINS_VALUE_RETRIES = 3; + static final int DRAIN_THRESHOLD = 63; + static final int DRAIN_MAX = 16; + static final long CLEANUP_EXECUTOR_DELAY_SECS = 60L; + private static final Logger logger = Logger.getLogger(MapMakerInternalMap.class.getName()); + + + + final transient int segmentMask; + + + + final transient int segmentShift; + + + + final transient Segment[] segments; + + + + final int concurrencyLevel; + + + + final Equivalence keyEquivalence; + + + + final Equivalence valueEquivalence; + + + + final Strength keyStrength; + + + + final Strength valueStrength; + + + + final int maximumSize; + + + + final long expireAfterAccessNanos; + + + final long expireAfterWriteNanos; + + + final Queue> removalNotificationQueue; + + + final MapMaker.RemovalListener removalListener; + + + final transient EntryFactory entryFactory; + + + final Ticker ticker; + + + + MapMakerInternalMap(MapMaker builder) + { + concurrencyLevel = Math.min(builder.getConcurrencyLevel(), 65536); + + keyStrength = builder.getKeyStrength(); + valueStrength = builder.getValueStrength(); + + keyEquivalence = builder.getKeyEquivalence(); + valueEquivalence = valueStrength.defaultEquivalence(); + + maximumSize = maximumSize; + expireAfterAccessNanos = builder.getExpireAfterAccessNanos(); + expireAfterWriteNanos = builder.getExpireAfterWriteNanos(); + + entryFactory = EntryFactory.getFactory(keyStrength, expires(), evictsBySize()); + ticker = builder.getTicker(); + + removalListener = builder.getRemovalListener(); + removalNotificationQueue = (removalListener == GenericMapMaker.NullListener.INSTANCE ? discardingQueue() : new ConcurrentLinkedQueue()); + + + + int initialCapacity = Math.min(builder.getInitialCapacity(), 1073741824); + if (evictsBySize()) { + initialCapacity = Math.min(initialCapacity, maximumSize); + } + + + + + int segmentShift = 0; + int segmentCount = 1; + + while ((segmentCount < concurrencyLevel) && ((!evictsBySize()) || (segmentCount * 2 <= maximumSize))) { + segmentShift++; + segmentCount <<= 1; + } + this.segmentShift = (32 - segmentShift); + segmentMask = (segmentCount - 1); + + segments = newSegmentArray(segmentCount); + + int segmentCapacity = initialCapacity / segmentCount; + if (segmentCapacity * segmentCount < initialCapacity) { + segmentCapacity++; + } + + int segmentSize = 1; + while (segmentSize < segmentCapacity) { + segmentSize <<= 1; + } + + if (evictsBySize()) + { + int maximumSegmentSize = maximumSize / segmentCount + 1; + int remainder = maximumSize % segmentCount; + for (int i = 0; i < segments.length; i++) { + if (i == remainder) { + maximumSegmentSize--; + } + segments[i] = createSegment(segmentSize, maximumSegmentSize); + } + } + else { + for (int i = 0; i < segments.length; i++) { + segments[i] = createSegment(segmentSize, -1); + } + } + } + + boolean evictsBySize() + { + return maximumSize != -1; + } + + boolean expires() { + return (expiresAfterWrite()) || (expiresAfterAccess()); + } + + boolean expiresAfterWrite() { + return expireAfterWriteNanos > 0L; + } + + boolean expiresAfterAccess() { + return expireAfterAccessNanos > 0L; + } + + boolean usesKeyReferences() { + return keyStrength != Strength.STRONG; + } + + boolean usesValueReferences() { + return valueStrength != Strength.STRONG; + } + + + + + + static abstract enum Strength + { + STRONG, + + + + + + + + + + + + + SOFT, + + + + + + + + + + + + + WEAK; + + + + + + + private Strength() {} + + + + + + + abstract MapMakerInternalMap.ValueReference referenceValue(MapMakerInternalMap.Segment paramSegment, MapMakerInternalMap.ReferenceEntry paramReferenceEntry, V paramV); + + + + + + + abstract Equivalence defaultEquivalence(); + } + + + + + + + static abstract enum EntryFactory + { + STRONG, + + + + + + + STRONG_EXPIRABLE, + + + + + + + + + + + + + + + STRONG_EVICTABLE, + + + + + + + + + + + + + + + STRONG_EXPIRABLE_EVICTABLE, + + + + + + + + + + + + + + + + + WEAK, + + + + + + + WEAK_EXPIRABLE, + + + + + + + + + + + + + + + WEAK_EVICTABLE, + + + + + + + + + + + + + + + WEAK_EXPIRABLE_EVICTABLE; + + + + + + + + + + static final int EXPIRABLE_MASK = 1; + + + + + + + + + static final int EVICTABLE_MASK = 2; + + + + + + + + static final EntryFactory[][] factories = { { STRONG, STRONG_EXPIRABLE, STRONG_EVICTABLE, STRONG_EXPIRABLE_EVICTABLE }, new EntryFactory[0], { WEAK, WEAK_EXPIRABLE, WEAK_EVICTABLE, WEAK_EXPIRABLE_EVICTABLE } }; + + + private EntryFactory() {} + + + static EntryFactory getFactory(MapMakerInternalMap.Strength keyStrength, boolean expireAfterWrite, boolean evictsBySize) + { + int flags = (expireAfterWrite ? 1 : 0) | (evictsBySize ? 2 : 0); + return factories[keyStrength.ordinal()][flags]; + } + + + + + + + + + + abstract MapMakerInternalMap.ReferenceEntry newEntry(MapMakerInternalMap.Segment paramSegment, K paramK, int paramInt, @Nullable MapMakerInternalMap.ReferenceEntry paramReferenceEntry); + + + + + + + + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry copyEntry(MapMakerInternalMap.Segment segment, MapMakerInternalMap.ReferenceEntry original, MapMakerInternalMap.ReferenceEntry newNext) + { + return newEntry(segment, original.getKey(), original.getHash(), newNext); + } + + + @GuardedBy("Segment.this") + void copyExpirableEntry(MapMakerInternalMap.ReferenceEntry original, MapMakerInternalMap.ReferenceEntry newEntry) + { + newEntry.setExpirationTime(original.getExpirationTime()); + + MapMakerInternalMap.connectExpirables(original.getPreviousExpirable(), newEntry); + MapMakerInternalMap.connectExpirables(newEntry, original.getNextExpirable()); + + MapMakerInternalMap.nullifyExpirable(original); + } + + + @GuardedBy("Segment.this") + void copyEvictableEntry(MapMakerInternalMap.ReferenceEntry original, MapMakerInternalMap.ReferenceEntry newEntry) + { + MapMakerInternalMap.connectEvictables(original.getPreviousEvictable(), newEntry); + MapMakerInternalMap.connectEvictables(newEntry, original.getNextEvictable()); + + MapMakerInternalMap.nullifyEvictable(original); + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + static final ValueReference UNSET = new ValueReference() + { + public Object get() { + return null; + } + + public MapMakerInternalMap.ReferenceEntry getEntry() + { + return null; + } + + + public MapMakerInternalMap.ValueReference copyFor(ReferenceQueue queue, @Nullable Object value, MapMakerInternalMap.ReferenceEntry entry) + { + return this; + } + + public boolean isComputingReference() + { + return false; + } + + public Object waitForValue() + { + return null; + } + + + + public void clear(MapMakerInternalMap.ValueReference newValue) {} + }; + + + + static ValueReference unset() + { + return UNSET; + } + + + + + static abstract interface ValueReference + { + public abstract V get(); + + + + + public abstract V waitForValue() + throws ExecutionException; + + + + + public abstract MapMakerInternalMap.ReferenceEntry getEntry(); + + + + + public abstract ValueReference copyFor(ReferenceQueue paramReferenceQueue, @Nullable V paramV, MapMakerInternalMap.ReferenceEntry paramReferenceEntry); + + + + + public abstract void clear(@Nullable ValueReference paramValueReference); + + + + + public abstract boolean isComputingReference(); + } + + + + + static abstract interface ReferenceEntry + { + public abstract MapMakerInternalMap.ValueReference getValueReference(); + + + + public abstract void setValueReference(MapMakerInternalMap.ValueReference paramValueReference); + + + + public abstract ReferenceEntry getNext(); + + + + public abstract int getHash(); + + + + public abstract K getKey(); + + + + public abstract long getExpirationTime(); + + + + public abstract void setExpirationTime(long paramLong); + + + + public abstract ReferenceEntry getNextExpirable(); + + + + public abstract void setNextExpirable(ReferenceEntry paramReferenceEntry); + + + + public abstract ReferenceEntry getPreviousExpirable(); + + + + public abstract void setPreviousExpirable(ReferenceEntry paramReferenceEntry); + + + + public abstract ReferenceEntry getNextEvictable(); + + + + public abstract void setNextEvictable(ReferenceEntry paramReferenceEntry); + + + + public abstract ReferenceEntry getPreviousEvictable(); + + + + public abstract void setPreviousEvictable(ReferenceEntry paramReferenceEntry); + } + + + + private static enum NullEntry + implements MapMakerInternalMap.ReferenceEntry + { + INSTANCE; + + private NullEntry() {} + + public MapMakerInternalMap.ValueReference getValueReference() { return null; } + + + public void setValueReference(MapMakerInternalMap.ValueReference valueReference) {} + + + public MapMakerInternalMap.ReferenceEntry getNext() + { + return null; + } + + public int getHash() + { + return 0; + } + + public Object getKey() + { + return null; + } + + public long getExpirationTime() + { + return 0L; + } + + + public void setExpirationTime(long time) {} + + public MapMakerInternalMap.ReferenceEntry getNextExpirable() + { + return this; + } + + + public void setNextExpirable(MapMakerInternalMap.ReferenceEntry next) {} + + public MapMakerInternalMap.ReferenceEntry getPreviousExpirable() + { + return this; + } + + + public void setPreviousExpirable(MapMakerInternalMap.ReferenceEntry previous) {} + + public MapMakerInternalMap.ReferenceEntry getNextEvictable() + { + return this; + } + + + public void setNextEvictable(MapMakerInternalMap.ReferenceEntry next) {} + + public MapMakerInternalMap.ReferenceEntry getPreviousEvictable() + { + return this; + } + + public void setPreviousEvictable(MapMakerInternalMap.ReferenceEntry previous) {} + } + + static abstract class AbstractReferenceEntry implements MapMakerInternalMap.ReferenceEntry { + AbstractReferenceEntry() {} + + public MapMakerInternalMap.ValueReference getValueReference() { + throw new UnsupportedOperationException(); + } + + public void setValueReference(MapMakerInternalMap.ValueReference valueReference) + { + throw new UnsupportedOperationException(); + } + + public MapMakerInternalMap.ReferenceEntry getNext() + { + throw new UnsupportedOperationException(); + } + + public int getHash() + { + throw new UnsupportedOperationException(); + } + + public K getKey() + { + throw new UnsupportedOperationException(); + } + + public long getExpirationTime() + { + throw new UnsupportedOperationException(); + } + + public void setExpirationTime(long time) + { + throw new UnsupportedOperationException(); + } + + public MapMakerInternalMap.ReferenceEntry getNextExpirable() + { + throw new UnsupportedOperationException(); + } + + public void setNextExpirable(MapMakerInternalMap.ReferenceEntry next) + { + throw new UnsupportedOperationException(); + } + + public MapMakerInternalMap.ReferenceEntry getPreviousExpirable() + { + throw new UnsupportedOperationException(); + } + + public void setPreviousExpirable(MapMakerInternalMap.ReferenceEntry previous) + { + throw new UnsupportedOperationException(); + } + + public MapMakerInternalMap.ReferenceEntry getNextEvictable() + { + throw new UnsupportedOperationException(); + } + + public void setNextEvictable(MapMakerInternalMap.ReferenceEntry next) + { + throw new UnsupportedOperationException(); + } + + public MapMakerInternalMap.ReferenceEntry getPreviousEvictable() + { + throw new UnsupportedOperationException(); + } + + public void setPreviousEvictable(MapMakerInternalMap.ReferenceEntry previous) + { + throw new UnsupportedOperationException(); + } + } + + static ReferenceEntry nullEntry() + { + return NullEntry.INSTANCE; + } + + static final Queue DISCARDING_QUEUE = new AbstractQueue() + { + public boolean offer(Object o) { + return true; + } + + public Object peek() + { + return null; + } + + public Object poll() + { + return null; + } + + public int size() + { + return 0; + } + + public Iterator iterator() + { + return Iterators.emptyIterator(); + } + }; + transient Set keySet; + transient Collection values; + transient Set> entrySet; + private static final long serialVersionUID = 5L; + + static Queue discardingQueue() { + return DISCARDING_QUEUE; + } + + + + static class StrongEntry + implements MapMakerInternalMap.ReferenceEntry + { + final K key; + + + final int hash; + + final MapMakerInternalMap.ReferenceEntry next; + + + StrongEntry(K key, int hash, @Nullable MapMakerInternalMap.ReferenceEntry next) + { + this.key = key; + this.hash = hash; + this.next = next; + } + + public K getKey() + { + return key; + } + + + + public long getExpirationTime() + { + throw new UnsupportedOperationException(); + } + + public void setExpirationTime(long time) + { + throw new UnsupportedOperationException(); + } + + public MapMakerInternalMap.ReferenceEntry getNextExpirable() + { + throw new UnsupportedOperationException(); + } + + public void setNextExpirable(MapMakerInternalMap.ReferenceEntry next) + { + throw new UnsupportedOperationException(); + } + + public MapMakerInternalMap.ReferenceEntry getPreviousExpirable() + { + throw new UnsupportedOperationException(); + } + + public void setPreviousExpirable(MapMakerInternalMap.ReferenceEntry previous) + { + throw new UnsupportedOperationException(); + } + + + + public MapMakerInternalMap.ReferenceEntry getNextEvictable() + { + throw new UnsupportedOperationException(); + } + + public void setNextEvictable(MapMakerInternalMap.ReferenceEntry next) + { + throw new UnsupportedOperationException(); + } + + public MapMakerInternalMap.ReferenceEntry getPreviousEvictable() + { + throw new UnsupportedOperationException(); + } + + public void setPreviousEvictable(MapMakerInternalMap.ReferenceEntry previous) + { + throw new UnsupportedOperationException(); + } + + + + + + volatile MapMakerInternalMap.ValueReference valueReference = MapMakerInternalMap.unset(); + + public MapMakerInternalMap.ValueReference getValueReference() + { + return valueReference; + } + + public void setValueReference(MapMakerInternalMap.ValueReference valueReference) + { + MapMakerInternalMap.ValueReference previous = this.valueReference; + this.valueReference = valueReference; + previous.clear(valueReference); + } + + public int getHash() + { + return hash; + } + + public MapMakerInternalMap.ReferenceEntry getNext() + { + return next; + } + } + + static final class StrongExpirableEntry extends MapMakerInternalMap.StrongEntry implements MapMakerInternalMap.ReferenceEntry + { + StrongExpirableEntry(K key, int hash, @Nullable MapMakerInternalMap.ReferenceEntry next) { + super(hash, next); + } + + + + volatile long time = Long.MAX_VALUE; + + public long getExpirationTime() + { + return time; + } + + + + public void setExpirationTime(long time) { this.time = time; } + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry nextExpirable = MapMakerInternalMap.nullEntry(); + + + public MapMakerInternalMap.ReferenceEntry getNextExpirable() + { + return nextExpirable; + } + + + + public void setNextExpirable(MapMakerInternalMap.ReferenceEntry next) { nextExpirable = next; } + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry previousExpirable = MapMakerInternalMap.nullEntry(); + + + public MapMakerInternalMap.ReferenceEntry getPreviousExpirable() + { + return previousExpirable; + } + + public void setPreviousExpirable(MapMakerInternalMap.ReferenceEntry previous) + { + previousExpirable = previous; + } + } + + static final class StrongEvictableEntry extends MapMakerInternalMap.StrongEntry implements MapMakerInternalMap.ReferenceEntry + { + StrongEvictableEntry(K key, int hash, @Nullable MapMakerInternalMap.ReferenceEntry next) { + super(hash, next); + } + + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry nextEvictable = MapMakerInternalMap.nullEntry(); + + + public MapMakerInternalMap.ReferenceEntry getNextEvictable() + { + return nextEvictable; + } + + + + public void setNextEvictable(MapMakerInternalMap.ReferenceEntry next) { nextEvictable = next; } + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry previousEvictable = MapMakerInternalMap.nullEntry(); + + + public MapMakerInternalMap.ReferenceEntry getPreviousEvictable() + { + return previousEvictable; + } + + public void setPreviousEvictable(MapMakerInternalMap.ReferenceEntry previous) + { + previousEvictable = previous; + } + } + + static final class StrongExpirableEvictableEntry extends MapMakerInternalMap.StrongEntry implements MapMakerInternalMap.ReferenceEntry + { + StrongExpirableEvictableEntry(K key, int hash, @Nullable MapMakerInternalMap.ReferenceEntry next) { + super(hash, next); + } + + + + volatile long time = Long.MAX_VALUE; + + public long getExpirationTime() + { + return time; + } + + + + public void setExpirationTime(long time) { this.time = time; } + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry nextExpirable = MapMakerInternalMap.nullEntry(); + + + public MapMakerInternalMap.ReferenceEntry getNextExpirable() + { + return nextExpirable; + } + + + + public void setNextExpirable(MapMakerInternalMap.ReferenceEntry next) { nextExpirable = next; } + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry previousExpirable = MapMakerInternalMap.nullEntry(); + + + public MapMakerInternalMap.ReferenceEntry getPreviousExpirable() + { + return previousExpirable; + } + + public void setPreviousExpirable(MapMakerInternalMap.ReferenceEntry previous) + { + previousExpirable = previous; + } + + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry nextEvictable = MapMakerInternalMap.nullEntry(); + + + public MapMakerInternalMap.ReferenceEntry getNextEvictable() + { + return nextEvictable; + } + + + + public void setNextEvictable(MapMakerInternalMap.ReferenceEntry next) { nextEvictable = next; } + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry previousEvictable = MapMakerInternalMap.nullEntry(); + + + public MapMakerInternalMap.ReferenceEntry getPreviousEvictable() + { + return previousEvictable; + } + + public void setPreviousEvictable(MapMakerInternalMap.ReferenceEntry previous) + { + previousEvictable = previous; + } + } + + static class SoftEntry extends SoftReference implements MapMakerInternalMap.ReferenceEntry { + final int hash; + final MapMakerInternalMap.ReferenceEntry next; + + SoftEntry(ReferenceQueue queue, K key, int hash, @Nullable MapMakerInternalMap.ReferenceEntry next) { + super(queue); + this.hash = hash; + this.next = next; + } + + public K getKey() + { + return get(); + } + + + public long getExpirationTime() + { + throw new UnsupportedOperationException(); + } + + public void setExpirationTime(long time) + { + throw new UnsupportedOperationException(); + } + + public MapMakerInternalMap.ReferenceEntry getNextExpirable() + { + throw new UnsupportedOperationException(); + } + + public void setNextExpirable(MapMakerInternalMap.ReferenceEntry next) + { + throw new UnsupportedOperationException(); + } + + public MapMakerInternalMap.ReferenceEntry getPreviousExpirable() + { + throw new UnsupportedOperationException(); + } + + public void setPreviousExpirable(MapMakerInternalMap.ReferenceEntry previous) + { + throw new UnsupportedOperationException(); + } + + + + public MapMakerInternalMap.ReferenceEntry getNextEvictable() + { + throw new UnsupportedOperationException(); + } + + public void setNextEvictable(MapMakerInternalMap.ReferenceEntry next) + { + throw new UnsupportedOperationException(); + } + + public MapMakerInternalMap.ReferenceEntry getPreviousEvictable() + { + throw new UnsupportedOperationException(); + } + + public void setPreviousEvictable(MapMakerInternalMap.ReferenceEntry previous) + { + throw new UnsupportedOperationException(); + } + + + + + + volatile MapMakerInternalMap.ValueReference valueReference = MapMakerInternalMap.unset(); + + public MapMakerInternalMap.ValueReference getValueReference() + { + return valueReference; + } + + public void setValueReference(MapMakerInternalMap.ValueReference valueReference) + { + MapMakerInternalMap.ValueReference previous = this.valueReference; + this.valueReference = valueReference; + previous.clear(valueReference); + } + + public int getHash() + { + return hash; + } + + public MapMakerInternalMap.ReferenceEntry getNext() + { + return next; + } + } + + static final class SoftExpirableEntry extends MapMakerInternalMap.SoftEntry implements MapMakerInternalMap.ReferenceEntry + { + SoftExpirableEntry(ReferenceQueue queue, K key, int hash, @Nullable MapMakerInternalMap.ReferenceEntry next) + { + super(key, hash, next); + } + + + + volatile long time = Long.MAX_VALUE; + + public long getExpirationTime() + { + return time; + } + + + + public void setExpirationTime(long time) { this.time = time; } + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry nextExpirable = MapMakerInternalMap.nullEntry(); + + + public MapMakerInternalMap.ReferenceEntry getNextExpirable() + { + return nextExpirable; + } + + + + public void setNextExpirable(MapMakerInternalMap.ReferenceEntry next) { nextExpirable = next; } + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry previousExpirable = MapMakerInternalMap.nullEntry(); + + + public MapMakerInternalMap.ReferenceEntry getPreviousExpirable() + { + return previousExpirable; + } + + public void setPreviousExpirable(MapMakerInternalMap.ReferenceEntry previous) + { + previousExpirable = previous; + } + } + + static final class SoftEvictableEntry extends MapMakerInternalMap.SoftEntry implements MapMakerInternalMap.ReferenceEntry + { + SoftEvictableEntry(ReferenceQueue queue, K key, int hash, @Nullable MapMakerInternalMap.ReferenceEntry next) + { + super(key, hash, next); + } + + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry nextEvictable = MapMakerInternalMap.nullEntry(); + + + public MapMakerInternalMap.ReferenceEntry getNextEvictable() + { + return nextEvictable; + } + + + + public void setNextEvictable(MapMakerInternalMap.ReferenceEntry next) { nextEvictable = next; } + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry previousEvictable = MapMakerInternalMap.nullEntry(); + + + public MapMakerInternalMap.ReferenceEntry getPreviousEvictable() + { + return previousEvictable; + } + + public void setPreviousEvictable(MapMakerInternalMap.ReferenceEntry previous) + { + previousEvictable = previous; + } + } + + static final class SoftExpirableEvictableEntry extends MapMakerInternalMap.SoftEntry implements MapMakerInternalMap.ReferenceEntry + { + SoftExpirableEvictableEntry(ReferenceQueue queue, K key, int hash, @Nullable MapMakerInternalMap.ReferenceEntry next) + { + super(key, hash, next); + } + + + + volatile long time = Long.MAX_VALUE; + + public long getExpirationTime() + { + return time; + } + + + + public void setExpirationTime(long time) { this.time = time; } + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry nextExpirable = MapMakerInternalMap.nullEntry(); + + + public MapMakerInternalMap.ReferenceEntry getNextExpirable() + { + return nextExpirable; + } + + + + public void setNextExpirable(MapMakerInternalMap.ReferenceEntry next) { nextExpirable = next; } + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry previousExpirable = MapMakerInternalMap.nullEntry(); + + + public MapMakerInternalMap.ReferenceEntry getPreviousExpirable() + { + return previousExpirable; + } + + public void setPreviousExpirable(MapMakerInternalMap.ReferenceEntry previous) + { + previousExpirable = previous; + } + + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry nextEvictable = MapMakerInternalMap.nullEntry(); + + + public MapMakerInternalMap.ReferenceEntry getNextEvictable() + { + return nextEvictable; + } + + + + public void setNextEvictable(MapMakerInternalMap.ReferenceEntry next) { nextEvictable = next; } + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry previousEvictable = MapMakerInternalMap.nullEntry(); + + + public MapMakerInternalMap.ReferenceEntry getPreviousEvictable() + { + return previousEvictable; + } + + public void setPreviousEvictable(MapMakerInternalMap.ReferenceEntry previous) + { + previousEvictable = previous; + } + } + + static class WeakEntry extends WeakReference implements MapMakerInternalMap.ReferenceEntry { + final int hash; + final MapMakerInternalMap.ReferenceEntry next; + + WeakEntry(ReferenceQueue queue, K key, int hash, @Nullable MapMakerInternalMap.ReferenceEntry next) { + super(queue); + this.hash = hash; + this.next = next; + } + + public K getKey() + { + return get(); + } + + + + public long getExpirationTime() + { + throw new UnsupportedOperationException(); + } + + public void setExpirationTime(long time) + { + throw new UnsupportedOperationException(); + } + + public MapMakerInternalMap.ReferenceEntry getNextExpirable() + { + throw new UnsupportedOperationException(); + } + + public void setNextExpirable(MapMakerInternalMap.ReferenceEntry next) + { + throw new UnsupportedOperationException(); + } + + public MapMakerInternalMap.ReferenceEntry getPreviousExpirable() + { + throw new UnsupportedOperationException(); + } + + public void setPreviousExpirable(MapMakerInternalMap.ReferenceEntry previous) + { + throw new UnsupportedOperationException(); + } + + + + public MapMakerInternalMap.ReferenceEntry getNextEvictable() + { + throw new UnsupportedOperationException(); + } + + public void setNextEvictable(MapMakerInternalMap.ReferenceEntry next) + { + throw new UnsupportedOperationException(); + } + + public MapMakerInternalMap.ReferenceEntry getPreviousEvictable() + { + throw new UnsupportedOperationException(); + } + + public void setPreviousEvictable(MapMakerInternalMap.ReferenceEntry previous) + { + throw new UnsupportedOperationException(); + } + + + + + + volatile MapMakerInternalMap.ValueReference valueReference = MapMakerInternalMap.unset(); + + public MapMakerInternalMap.ValueReference getValueReference() + { + return valueReference; + } + + public void setValueReference(MapMakerInternalMap.ValueReference valueReference) + { + MapMakerInternalMap.ValueReference previous = this.valueReference; + this.valueReference = valueReference; + previous.clear(valueReference); + } + + public int getHash() + { + return hash; + } + + public MapMakerInternalMap.ReferenceEntry getNext() + { + return next; + } + } + + static final class WeakExpirableEntry extends MapMakerInternalMap.WeakEntry implements MapMakerInternalMap.ReferenceEntry + { + WeakExpirableEntry(ReferenceQueue queue, K key, int hash, @Nullable MapMakerInternalMap.ReferenceEntry next) + { + super(key, hash, next); + } + + + + volatile long time = Long.MAX_VALUE; + + public long getExpirationTime() + { + return time; + } + + + + public void setExpirationTime(long time) { this.time = time; } + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry nextExpirable = MapMakerInternalMap.nullEntry(); + + + public MapMakerInternalMap.ReferenceEntry getNextExpirable() + { + return nextExpirable; + } + + + + public void setNextExpirable(MapMakerInternalMap.ReferenceEntry next) { nextExpirable = next; } + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry previousExpirable = MapMakerInternalMap.nullEntry(); + + + public MapMakerInternalMap.ReferenceEntry getPreviousExpirable() + { + return previousExpirable; + } + + public void setPreviousExpirable(MapMakerInternalMap.ReferenceEntry previous) + { + previousExpirable = previous; + } + } + + static final class WeakEvictableEntry extends MapMakerInternalMap.WeakEntry implements MapMakerInternalMap.ReferenceEntry + { + WeakEvictableEntry(ReferenceQueue queue, K key, int hash, @Nullable MapMakerInternalMap.ReferenceEntry next) + { + super(key, hash, next); + } + + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry nextEvictable = MapMakerInternalMap.nullEntry(); + + + public MapMakerInternalMap.ReferenceEntry getNextEvictable() + { + return nextEvictable; + } + + + + public void setNextEvictable(MapMakerInternalMap.ReferenceEntry next) { nextEvictable = next; } + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry previousEvictable = MapMakerInternalMap.nullEntry(); + + + public MapMakerInternalMap.ReferenceEntry getPreviousEvictable() + { + return previousEvictable; + } + + public void setPreviousEvictable(MapMakerInternalMap.ReferenceEntry previous) + { + previousEvictable = previous; + } + } + + static final class WeakExpirableEvictableEntry extends MapMakerInternalMap.WeakEntry implements MapMakerInternalMap.ReferenceEntry + { + WeakExpirableEvictableEntry(ReferenceQueue queue, K key, int hash, @Nullable MapMakerInternalMap.ReferenceEntry next) + { + super(key, hash, next); + } + + + + volatile long time = Long.MAX_VALUE; + + public long getExpirationTime() + { + return time; + } + + + + public void setExpirationTime(long time) { this.time = time; } + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry nextExpirable = MapMakerInternalMap.nullEntry(); + + + public MapMakerInternalMap.ReferenceEntry getNextExpirable() + { + return nextExpirable; + } + + + + public void setNextExpirable(MapMakerInternalMap.ReferenceEntry next) { nextExpirable = next; } + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry previousExpirable = MapMakerInternalMap.nullEntry(); + + + public MapMakerInternalMap.ReferenceEntry getPreviousExpirable() + { + return previousExpirable; + } + + public void setPreviousExpirable(MapMakerInternalMap.ReferenceEntry previous) + { + previousExpirable = previous; + } + + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry nextEvictable = MapMakerInternalMap.nullEntry(); + + + public MapMakerInternalMap.ReferenceEntry getNextEvictable() + { + return nextEvictable; + } + + + + public void setNextEvictable(MapMakerInternalMap.ReferenceEntry next) { nextEvictable = next; } + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry previousEvictable = MapMakerInternalMap.nullEntry(); + + + public MapMakerInternalMap.ReferenceEntry getPreviousEvictable() + { + return previousEvictable; + } + + public void setPreviousEvictable(MapMakerInternalMap.ReferenceEntry previous) + { + previousEvictable = previous; + } + } + + static final class WeakValueReference + extends WeakReference + implements MapMakerInternalMap.ValueReference + { + final MapMakerInternalMap.ReferenceEntry entry; + + WeakValueReference(ReferenceQueue queue, V referent, MapMakerInternalMap.ReferenceEntry entry) + { + super(queue); + this.entry = entry; + } + + public MapMakerInternalMap.ReferenceEntry getEntry() + { + return entry; + } + + public void clear(MapMakerInternalMap.ValueReference newValue) + { + clear(); + } + + + public MapMakerInternalMap.ValueReference copyFor(ReferenceQueue queue, V value, MapMakerInternalMap.ReferenceEntry entry) + { + return new WeakValueReference(queue, value, entry); + } + + public boolean isComputingReference() + { + return false; + } + + public V waitForValue() + { + return get(); + } + } + + static final class SoftValueReference + extends SoftReference + implements MapMakerInternalMap.ValueReference + { + final MapMakerInternalMap.ReferenceEntry entry; + + SoftValueReference(ReferenceQueue queue, V referent, MapMakerInternalMap.ReferenceEntry entry) + { + super(queue); + this.entry = entry; + } + + public MapMakerInternalMap.ReferenceEntry getEntry() + { + return entry; + } + + public void clear(MapMakerInternalMap.ValueReference newValue) + { + clear(); + } + + + public MapMakerInternalMap.ValueReference copyFor(ReferenceQueue queue, V value, MapMakerInternalMap.ReferenceEntry entry) + { + return new SoftValueReference(queue, value, entry); + } + + public boolean isComputingReference() + { + return false; + } + + public V waitForValue() + { + return get(); + } + } + + static final class StrongValueReference + implements MapMakerInternalMap.ValueReference + { + final V referent; + + StrongValueReference(V referent) + { + this.referent = referent; + } + + public V get() + { + return referent; + } + + public MapMakerInternalMap.ReferenceEntry getEntry() + { + return null; + } + + + public MapMakerInternalMap.ValueReference copyFor(ReferenceQueue queue, V value, MapMakerInternalMap.ReferenceEntry entry) + { + return this; + } + + public boolean isComputingReference() + { + return false; + } + + public V waitForValue() + { + return get(); + } + + + + + + + + public void clear(MapMakerInternalMap.ValueReference newValue) {} + } + + + + + + + static int rehash(int h) + { + h += (h << 15 ^ 0xCD7D); + h ^= h >>> 10; + h += (h << 3); + h ^= h >>> 6; + h += (h << 2) + (h << 14); + return h ^ h >>> 16; + } + + + + @GuardedBy("Segment.this") + @VisibleForTesting + ReferenceEntry newEntry(K key, int hash, @Nullable ReferenceEntry next) + { + return segmentFor(hash).newEntry(key, hash, next); + } + + + + @GuardedBy("Segment.this") + @VisibleForTesting + ReferenceEntry copyEntry(ReferenceEntry original, ReferenceEntry newNext) + { + int hash = original.getHash(); + return segmentFor(hash).copyEntry(original, newNext); + } + + + + @GuardedBy("Segment.this") + @VisibleForTesting + ValueReference newValueReference(ReferenceEntry entry, V value) + { + int hash = entry.getHash(); + return valueStrength.referenceValue(segmentFor(hash), entry, value); + } + + int hash(Object key) { + int h = keyEquivalence.hash(key); + return rehash(h); + } + + void reclaimValue(ValueReference valueReference) { + ReferenceEntry entry = valueReference.getEntry(); + int hash = entry.getHash(); + segmentFor(hash).reclaimValue(entry.getKey(), hash, valueReference); + } + + void reclaimKey(ReferenceEntry entry) { + int hash = entry.getHash(); + segmentFor(hash).reclaimKey(entry, hash); + } + + + + + @VisibleForTesting + boolean isLive(ReferenceEntry entry) + { + return segmentFor(entry.getHash()).getLiveValue(entry) != null; + } + + + + + + + + Segment segmentFor(int hash) + { + return segments[(hash >>> segmentShift & segmentMask)]; + } + + Segment createSegment(int initialCapacity, int maxSegmentSize) { + return new Segment(this, initialCapacity, maxSegmentSize); + } + + + + + + V getLiveValue(ReferenceEntry entry) + { + if (entry.getKey() == null) { + return null; + } + V value = entry.getValueReference().get(); + if (value == null) { + return null; + } + + if ((expires()) && (isExpired(entry))) { + return null; + } + return value; + } + + + + + + boolean isExpired(ReferenceEntry entry) + { + return isExpired(entry, ticker.read()); + } + + + + + boolean isExpired(ReferenceEntry entry, long now) + { + return now - entry.getExpirationTime() > 0L; + } + + @GuardedBy("Segment.this") + static void connectExpirables(ReferenceEntry previous, ReferenceEntry next) { + previous.setNextExpirable(next); + next.setPreviousExpirable(previous); + } + + @GuardedBy("Segment.this") + static void nullifyExpirable(ReferenceEntry nulled) { + ReferenceEntry nullEntry = nullEntry(); + nulled.setNextExpirable(nullEntry); + nulled.setPreviousExpirable(nullEntry); + } + + + + + void processPendingNotifications() + { + MapMaker.RemovalNotification notification; + + + + while ((notification = (MapMaker.RemovalNotification)removalNotificationQueue.poll()) != null) { + try { + removalListener.onRemoval(notification); + } catch (Exception e) { + logger.log(Level.WARNING, "Exception thrown by removal listener", e); + } + } + } + + @GuardedBy("Segment.this") + static void connectEvictables(ReferenceEntry previous, ReferenceEntry next) + { + previous.setNextEvictable(next); + next.setPreviousEvictable(previous); + } + + @GuardedBy("Segment.this") + static void nullifyEvictable(ReferenceEntry nulled) { + ReferenceEntry nullEntry = nullEntry(); + nulled.setNextEvictable(nullEntry); + nulled.setPreviousEvictable(nullEntry); + } + + final Segment[] newSegmentArray(int ssize) + { + return new Segment[ssize]; + } + + + + + + + + + + + static class Segment + extends ReentrantLock + { + final MapMakerInternalMap map; + + + + + + + + + + volatile int count; + + + + + + + + + + int modCount; + + + + + + + + + + int threshold; + + + + + + + + + + volatile AtomicReferenceArray> table; + + + + + + + + + final int maxSegmentSize; + + + + + + + + + final ReferenceQueue keyReferenceQueue; + + + + + + + + + final ReferenceQueue valueReferenceQueue; + + + + + + + + + final Queue> recencyQueue; + + + + + + + + + final AtomicInteger readCount = new AtomicInteger(); + + + + @GuardedBy("Segment.this") + final Queue> evictionQueue; + + + + @GuardedBy("Segment.this") + final Queue> expirationQueue; + + + + + Segment(MapMakerInternalMap map, int initialCapacity, int maxSegmentSize) + { + this.map = map; + this.maxSegmentSize = maxSegmentSize; + initTable(newEntryArray(initialCapacity)); + + keyReferenceQueue = (map.usesKeyReferences() ? new ReferenceQueue() : null); + + + valueReferenceQueue = (map.usesValueReferences() ? new ReferenceQueue() : null); + + + recencyQueue = ((map.evictsBySize()) || (map.expiresAfterAccess()) ? new ConcurrentLinkedQueue() : MapMakerInternalMap.discardingQueue()); + + + + evictionQueue = (map.evictsBySize() ? new MapMakerInternalMap.EvictionQueue() : MapMakerInternalMap.discardingQueue()); + + + + expirationQueue = (map.expires() ? new MapMakerInternalMap.ExpirationQueue() : MapMakerInternalMap.discardingQueue()); + } + + + AtomicReferenceArray> newEntryArray(int size) + { + return new AtomicReferenceArray(size); + } + + void initTable(AtomicReferenceArray> newTable) { + threshold = (newTable.length() * 3 / 4); + if (threshold == maxSegmentSize) + { + threshold += 1; + } + table = newTable; + } + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry newEntry(K key, int hash, @Nullable MapMakerInternalMap.ReferenceEntry next) { + return map.entryFactory.newEntry(this, key, hash, next); + } + + + + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry copyEntry(MapMakerInternalMap.ReferenceEntry original, MapMakerInternalMap.ReferenceEntry newNext) + { + if (original.getKey() == null) + { + return null; + } + + MapMakerInternalMap.ValueReference valueReference = original.getValueReference(); + V value = valueReference.get(); + if ((value == null) && (!valueReference.isComputingReference())) + { + return null; + } + + MapMakerInternalMap.ReferenceEntry newEntry = map.entryFactory.copyEntry(this, original, newNext); + newEntry.setValueReference(valueReference.copyFor(valueReferenceQueue, value, newEntry)); + return newEntry; + } + + + + @GuardedBy("Segment.this") + void setValue(MapMakerInternalMap.ReferenceEntry entry, V value) + { + MapMakerInternalMap.ValueReference valueReference = map.valueStrength.referenceValue(this, entry, value); + entry.setValueReference(valueReference); + recordWrite(entry); + } + + + + + + void tryDrainReferenceQueues() + { + if (tryLock()) { + try { + drainReferenceQueues(); + } finally { + unlock(); + } + } + } + + + + + @GuardedBy("Segment.this") + void drainReferenceQueues() + { + if (map.usesKeyReferences()) { + drainKeyReferenceQueue(); + } + if (map.usesValueReferences()) { + drainValueReferenceQueue(); + } + } + + @GuardedBy("Segment.this") + void drainKeyReferenceQueue() + { + int i = 0; + Reference ref; for (; (ref = keyReferenceQueue.poll()) != null; + + + + i == 16) + { + MapMakerInternalMap.ReferenceEntry entry = (MapMakerInternalMap.ReferenceEntry)ref; + map.reclaimKey(entry); + i++; + } + } + + + + @GuardedBy("Segment.this") + void drainValueReferenceQueue() + { + int i = 0; + Reference ref; for (; (ref = valueReferenceQueue.poll()) != null; + + + + i == 16) + { + MapMakerInternalMap.ValueReference valueReference = (MapMakerInternalMap.ValueReference)ref; + map.reclaimValue(valueReference); + i++; + } + } + + + + + + void clearReferenceQueues() + { + if (map.usesKeyReferences()) { + clearKeyReferenceQueue(); + } + if (map.usesValueReferences()) { + clearValueReferenceQueue(); + } + } + + void clearKeyReferenceQueue() { + while (keyReferenceQueue.poll() != null) {} + } + + void clearValueReferenceQueue() { + while (valueReferenceQueue.poll() != null) {} + } + + + + + + + + + + void recordRead(MapMakerInternalMap.ReferenceEntry entry) + { + if (map.expiresAfterAccess()) { + recordExpirationTime(entry, map.expireAfterAccessNanos); + } + recencyQueue.add(entry); + } + + + + + + + + @GuardedBy("Segment.this") + void recordLockedRead(MapMakerInternalMap.ReferenceEntry entry) + { + evictionQueue.add(entry); + if (map.expiresAfterAccess()) { + recordExpirationTime(entry, map.expireAfterAccessNanos); + expirationQueue.add(entry); + } + } + + + + + + @GuardedBy("Segment.this") + void recordWrite(MapMakerInternalMap.ReferenceEntry entry) + { + drainRecencyQueue(); + evictionQueue.add(entry); + if (map.expires()) + { + + long expiration = map.expiresAfterAccess() ? map.expireAfterAccessNanos : map.expireAfterWriteNanos; + + + recordExpirationTime(entry, expiration); + expirationQueue.add(entry); + } + } + + + + + @GuardedBy("Segment.this") + void drainRecencyQueue() + { + MapMakerInternalMap.ReferenceEntry e; + + + while ((e = (MapMakerInternalMap.ReferenceEntry)recencyQueue.poll()) != null) + { + + + + if (evictionQueue.contains(e)) { + evictionQueue.add(e); + } + if ((map.expiresAfterAccess()) && (expirationQueue.contains(e))) { + expirationQueue.add(e); + } + } + } + + + + void recordExpirationTime(MapMakerInternalMap.ReferenceEntry entry, long expirationNanos) + { + entry.setExpirationTime(map.ticker.read() + expirationNanos); + } + + + + void tryExpireEntries() + { + if (tryLock()) { + try { + expireEntries(); + } finally { + unlock(); + } + } + } + + @GuardedBy("Segment.this") + void expireEntries() + { + drainRecencyQueue(); + + if (expirationQueue.isEmpty()) + { + + return; + } + long now = map.ticker.read(); + MapMakerInternalMap.ReferenceEntry e; + while (((e = (MapMakerInternalMap.ReferenceEntry)expirationQueue.peek()) != null) && (map.isExpired(e, now))) { + if (!removeEntry(e, e.getHash(), MapMaker.RemovalCause.EXPIRED)) { + throw new AssertionError(); + } + } + } + + + void enqueueNotification(MapMakerInternalMap.ReferenceEntry entry, MapMaker.RemovalCause cause) + { + enqueueNotification(entry.getKey(), entry.getHash(), entry.getValueReference().get(), cause); + } + + void enqueueNotification(@Nullable K key, int hash, @Nullable V value, MapMaker.RemovalCause cause) { + if (map.removalNotificationQueue != MapMakerInternalMap.DISCARDING_QUEUE) { + MapMaker.RemovalNotification notification = new MapMaker.RemovalNotification(key, value, cause); + map.removalNotificationQueue.offer(notification); + } + } + + + + + + + @GuardedBy("Segment.this") + boolean evictEntries() + { + if ((map.evictsBySize()) && (count >= maxSegmentSize)) { + drainRecencyQueue(); + + MapMakerInternalMap.ReferenceEntry e = (MapMakerInternalMap.ReferenceEntry)evictionQueue.remove(); + if (!removeEntry(e, e.getHash(), MapMaker.RemovalCause.SIZE)) { + throw new AssertionError(); + } + return true; + } + return false; + } + + + + + MapMakerInternalMap.ReferenceEntry getFirst(int hash) + { + AtomicReferenceArray> table = this.table; + return (MapMakerInternalMap.ReferenceEntry)table.get(hash & table.length() - 1); + } + + + MapMakerInternalMap.ReferenceEntry getEntry(Object key, int hash) + { + if (count != 0) { + for (MapMakerInternalMap.ReferenceEntry e = getFirst(hash); e != null; e = e.getNext()) { + if (e.getHash() == hash) + { + + + K entryKey = e.getKey(); + if (entryKey == null) { + tryDrainReferenceQueues(); + + + } + else if (map.keyEquivalence.equivalent(key, entryKey)) { + return e; + } + } + } + } + return null; + } + + MapMakerInternalMap.ReferenceEntry getLiveEntry(Object key, int hash) { + MapMakerInternalMap.ReferenceEntry e = getEntry(key, hash); + if (e == null) + return null; + if ((map.expires()) && (map.isExpired(e))) { + tryExpireEntries(); + return null; + } + return e; + } + + V get(Object key, int hash) { + try { + MapMakerInternalMap.ReferenceEntry e = getLiveEntry(key, hash); + if (e == null) { + return null; + } + + Object value = e.getValueReference().get(); + if (value != null) { + recordRead(e); + } else { + tryDrainReferenceQueues(); + } + return value; + } finally { + postReadCleanup(); + } + } + + boolean containsKey(Object key, int hash) { + try { MapMakerInternalMap.ReferenceEntry e; + if (count != 0) { + e = getLiveEntry(key, hash); + boolean bool; if (e == null) { + return false; + } + return e.getValueReference().get() != null; + } + + return 0; + } finally { + postReadCleanup(); + } + } + + + @VisibleForTesting + boolean containsValue(Object value) + { + try + { + AtomicReferenceArray> table; + if (count != 0) { + table = this.table; + int length = table.length(); + for (int i = 0; i < length; i++) { + for (MapMakerInternalMap.ReferenceEntry e = (MapMakerInternalMap.ReferenceEntry)table.get(i); e != null; e = e.getNext()) { + V entryValue = getLiveValue(e); + if (entryValue != null) + { + + if (map.valueEquivalence.equivalent(value, entryValue)) { + return true; + } + } + } + } + } + return 0; + } finally { + postReadCleanup(); + } + } + + V put(K key, int hash, V value, boolean onlyIfAbsent) { + lock(); + try { + preWriteCleanup(); + + int newCount = count + 1; + if (newCount > threshold) { + expand(); + newCount = count + 1; + } + + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + MapMakerInternalMap.ReferenceEntry first = (MapMakerInternalMap.ReferenceEntry)table.get(index); + + K entryKey; + for (MapMakerInternalMap.ReferenceEntry e = first; e != null; e = e.getNext()) { + entryKey = e.getKey(); + if ((e.getHash() == hash) && (entryKey != null) && (map.keyEquivalence.equivalent(key, entryKey))) + { + + + MapMakerInternalMap.ValueReference valueReference = e.getValueReference(); + V entryValue = valueReference.get(); + V ?; + if (entryValue == null) { + modCount += 1; + setValue(e, value); + if (!valueReference.isComputingReference()) { + enqueueNotification(key, hash, entryValue, MapMaker.RemovalCause.COLLECTED); + newCount = count; + } else if (evictEntries()) { + newCount = count + 1; + } + count = newCount; + return null; } + if (onlyIfAbsent) + { + + + recordLockedRead(e); + return entryValue; + } + + modCount += 1; + enqueueNotification(key, hash, entryValue, MapMaker.RemovalCause.REPLACED); + setValue(e, value); + return entryValue; + } + } + + + + modCount += 1; + MapMakerInternalMap.ReferenceEntry newEntry = newEntry(key, hash, first); + setValue(newEntry, value); + table.set(index, newEntry); + if (evictEntries()) { + newCount = count + 1; + } + count = newCount; + return null; + } finally { + unlock(); + postWriteCleanup(); + } + } + + + + @GuardedBy("Segment.this") + void expand() + { + AtomicReferenceArray> oldTable = table; + int oldCapacity = oldTable.length(); + if (oldCapacity >= 1073741824) { + return; + } + + + + + + + + + + + + int newCount = count; + AtomicReferenceArray> newTable = newEntryArray(oldCapacity << 1); + threshold = (newTable.length() * 3 / 4); + int newMask = newTable.length() - 1; + for (int oldIndex = 0; oldIndex < oldCapacity; oldIndex++) + { + + MapMakerInternalMap.ReferenceEntry head = (MapMakerInternalMap.ReferenceEntry)oldTable.get(oldIndex); + + if (head != null) { + MapMakerInternalMap.ReferenceEntry next = head.getNext(); + int headIndex = head.getHash() & newMask; + + + if (next == null) { + newTable.set(headIndex, head); + + } + else + { + MapMakerInternalMap.ReferenceEntry tail = head; + int tailIndex = headIndex; + for (MapMakerInternalMap.ReferenceEntry e = next; e != null; e = e.getNext()) { + int newIndex = e.getHash() & newMask; + if (newIndex != tailIndex) + { + tailIndex = newIndex; + tail = e; + } + } + newTable.set(tailIndex, tail); + + + for (MapMakerInternalMap.ReferenceEntry e = head; e != tail; e = e.getNext()) { + int newIndex = e.getHash() & newMask; + MapMakerInternalMap.ReferenceEntry newNext = (MapMakerInternalMap.ReferenceEntry)newTable.get(newIndex); + MapMakerInternalMap.ReferenceEntry newFirst = copyEntry(e, newNext); + if (newFirst != null) { + newTable.set(newIndex, newFirst); + } else { + removeCollectedEntry(e); + newCount--; + } + } + } + } + } + table = newTable; + count = newCount; + } + + boolean replace(K key, int hash, V oldValue, V newValue) { + lock(); + try { + preWriteCleanup(); + + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + MapMakerInternalMap.ReferenceEntry first = (MapMakerInternalMap.ReferenceEntry)table.get(index); + + for (MapMakerInternalMap.ReferenceEntry e = first; e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if ((e.getHash() == hash) && (entryKey != null) && (map.keyEquivalence.equivalent(key, entryKey))) + { + + + MapMakerInternalMap.ValueReference valueReference = e.getValueReference(); + V entryValue = valueReference.get(); + int newCount; if (entryValue == null) { + if (isCollected(valueReference)) { + newCount = count - 1; + modCount += 1; + enqueueNotification(entryKey, hash, entryValue, MapMaker.RemovalCause.COLLECTED); + MapMakerInternalMap.ReferenceEntry newFirst = removeFromChain(first, e); + newCount = count - 1; + table.set(index, newFirst); + count = newCount; + } + return 0; + } + + if (map.valueEquivalence.equivalent(oldValue, entryValue)) { + modCount += 1; + enqueueNotification(key, hash, entryValue, MapMaker.RemovalCause.REPLACED); + setValue(e, newValue); + return 1; + } + + + recordLockedRead(e); + return 0; + } + } + + + return 0; + } finally { + unlock(); + postWriteCleanup(); + } + } + + V replace(K key, int hash, V newValue) { + lock(); + try { + preWriteCleanup(); + + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + MapMakerInternalMap.ReferenceEntry first = (MapMakerInternalMap.ReferenceEntry)table.get(index); + + for (MapMakerInternalMap.ReferenceEntry e = first; e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if ((e.getHash() == hash) && (entryKey != null) && (map.keyEquivalence.equivalent(key, entryKey))) + { + + + MapMakerInternalMap.ValueReference valueReference = e.getValueReference(); + V entryValue = valueReference.get(); + int newCount; if (entryValue == null) { + if (isCollected(valueReference)) { + newCount = count - 1; + modCount += 1; + enqueueNotification(entryKey, hash, entryValue, MapMaker.RemovalCause.COLLECTED); + MapMakerInternalMap.ReferenceEntry newFirst = removeFromChain(first, e); + newCount = count - 1; + table.set(index, newFirst); + count = newCount; + } + return null; + } + + modCount += 1; + enqueueNotification(key, hash, entryValue, MapMaker.RemovalCause.REPLACED); + setValue(e, newValue); + return entryValue; + } + } + + return null; + } finally { + unlock(); + postWriteCleanup(); + } + } + + V remove(Object key, int hash) { + lock(); + try { + preWriteCleanup(); + + int newCount = count - 1; + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + MapMakerInternalMap.ReferenceEntry first = (MapMakerInternalMap.ReferenceEntry)table.get(index); + + for (MapMakerInternalMap.ReferenceEntry e = first; e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if ((e.getHash() == hash) && (entryKey != null) && (map.keyEquivalence.equivalent(key, entryKey))) + { + MapMakerInternalMap.ValueReference valueReference = e.getValueReference(); + V entryValue = valueReference.get(); + + MapMaker.RemovalCause cause; + if (entryValue != null) { + cause = MapMaker.RemovalCause.EXPLICIT; } else { MapMaker.RemovalCause cause; + if (isCollected(valueReference)) { + cause = MapMaker.RemovalCause.COLLECTED; + } else + return null; + } + MapMaker.RemovalCause cause; + modCount += 1; + enqueueNotification(entryKey, hash, entryValue, cause); + Object newFirst = removeFromChain(first, e); + newCount = count - 1; + table.set(index, newFirst); + count = newCount; + return entryValue; + } + } + + return null; + } finally { + unlock(); + postWriteCleanup(); + } + } + + boolean remove(Object key, int hash, Object value) { + lock(); + try { + preWriteCleanup(); + + int newCount = count - 1; + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + MapMakerInternalMap.ReferenceEntry first = (MapMakerInternalMap.ReferenceEntry)table.get(index); + + for (MapMakerInternalMap.ReferenceEntry e = first; e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if ((e.getHash() == hash) && (entryKey != null) && (map.keyEquivalence.equivalent(key, entryKey))) + { + MapMakerInternalMap.ValueReference valueReference = e.getValueReference(); + V entryValue = valueReference.get(); + + MapMaker.RemovalCause cause; + if (map.valueEquivalence.equivalent(value, entryValue)) { + cause = MapMaker.RemovalCause.EXPLICIT; } else { MapMaker.RemovalCause cause; + if (isCollected(valueReference)) { + cause = MapMaker.RemovalCause.COLLECTED; + } else + return false; + } + MapMaker.RemovalCause cause; + modCount += 1; + enqueueNotification(entryKey, hash, entryValue, cause); + Object newFirst = removeFromChain(first, e); + newCount = count - 1; + table.set(index, newFirst); + count = newCount; + return cause == MapMaker.RemovalCause.EXPLICIT; + } + } + + return 0; + } finally { + unlock(); + postWriteCleanup(); + } + } + + void clear() { + if (count != 0) { + lock(); + try { + AtomicReferenceArray> table = this.table; + if (map.removalNotificationQueue != MapMakerInternalMap.DISCARDING_QUEUE) { + for (int i = 0; i < table.length(); i++) { + for (MapMakerInternalMap.ReferenceEntry e = (MapMakerInternalMap.ReferenceEntry)table.get(i); e != null; e = e.getNext()) + { + if (!e.getValueReference().isComputingReference()) { + enqueueNotification(e, MapMaker.RemovalCause.EXPLICIT); + } + } + } + } + for (int i = 0; i < table.length(); i++) { + table.set(i, null); + } + clearReferenceQueues(); + evictionQueue.clear(); + expirationQueue.clear(); + readCount.set(0); + + modCount += 1; + count = 0; + } finally { + unlock(); + postWriteCleanup(); + } + } + } + + + + + + + + + + + + + @GuardedBy("Segment.this") + MapMakerInternalMap.ReferenceEntry removeFromChain(MapMakerInternalMap.ReferenceEntry first, MapMakerInternalMap.ReferenceEntry entry) + { + evictionQueue.remove(entry); + expirationQueue.remove(entry); + + int newCount = count; + MapMakerInternalMap.ReferenceEntry newFirst = entry.getNext(); + for (MapMakerInternalMap.ReferenceEntry e = first; e != entry; e = e.getNext()) { + MapMakerInternalMap.ReferenceEntry next = copyEntry(e, newFirst); + if (next != null) { + newFirst = next; + } else { + removeCollectedEntry(e); + newCount--; + } + } + count = newCount; + return newFirst; + } + + void removeCollectedEntry(MapMakerInternalMap.ReferenceEntry entry) { + enqueueNotification(entry, MapMaker.RemovalCause.COLLECTED); + evictionQueue.remove(entry); + expirationQueue.remove(entry); + } + + + + boolean reclaimKey(MapMakerInternalMap.ReferenceEntry entry, int hash) + { + lock(); + try { + int newCount = count - 1; + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + MapMakerInternalMap.ReferenceEntry first = (MapMakerInternalMap.ReferenceEntry)table.get(index); + + for (MapMakerInternalMap.ReferenceEntry e = first; e != null; e = e.getNext()) { + if (e == entry) { + modCount += 1; + enqueueNotification(e.getKey(), hash, e.getValueReference().get(), MapMaker.RemovalCause.COLLECTED); + + MapMakerInternalMap.ReferenceEntry newFirst = removeFromChain(first, e); + newCount = count - 1; + table.set(index, newFirst); + count = newCount; + return true; + } + } + + return 0; + } finally { + unlock(); + postWriteCleanup(); + } + } + + + + boolean reclaimValue(K key, int hash, MapMakerInternalMap.ValueReference valueReference) + { + lock(); + try { + int newCount = count - 1; + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + MapMakerInternalMap.ReferenceEntry first = (MapMakerInternalMap.ReferenceEntry)table.get(index); + + for (MapMakerInternalMap.ReferenceEntry e = first; e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if ((e.getHash() == hash) && (entryKey != null) && (map.keyEquivalence.equivalent(key, entryKey))) + { + MapMakerInternalMap.ValueReference v = e.getValueReference(); + MapMakerInternalMap.ReferenceEntry newFirst; if (v == valueReference) { + modCount += 1; + enqueueNotification(key, hash, valueReference.get(), MapMaker.RemovalCause.COLLECTED); + newFirst = removeFromChain(first, e); + newCount = count - 1; + table.set(index, newFirst); + count = newCount; + return true; + } + return 0; + } + } + + return 0; + } finally { + unlock(); + if (!isHeldByCurrentThread()) { + postWriteCleanup(); + } + } + } + + + + boolean clearValue(K key, int hash, MapMakerInternalMap.ValueReference valueReference) + { + lock(); + try { + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + MapMakerInternalMap.ReferenceEntry first = (MapMakerInternalMap.ReferenceEntry)table.get(index); + + for (MapMakerInternalMap.ReferenceEntry e = first; e != null; e = e.getNext()) { + K entryKey = e.getKey(); + if ((e.getHash() == hash) && (entryKey != null) && (map.keyEquivalence.equivalent(key, entryKey))) + { + MapMakerInternalMap.ValueReference v = e.getValueReference(); + MapMakerInternalMap.ReferenceEntry newFirst; if (v == valueReference) { + newFirst = removeFromChain(first, e); + table.set(index, newFirst); + return true; + } + return 0; + } + } + + return 0; + } finally { + unlock(); + postWriteCleanup(); + } + } + + @GuardedBy("Segment.this") + boolean removeEntry(MapMakerInternalMap.ReferenceEntry entry, int hash, MapMaker.RemovalCause cause) { + int newCount = count - 1; + AtomicReferenceArray> table = this.table; + int index = hash & table.length() - 1; + MapMakerInternalMap.ReferenceEntry first = (MapMakerInternalMap.ReferenceEntry)table.get(index); + + for (MapMakerInternalMap.ReferenceEntry e = first; e != null; e = e.getNext()) { + if (e == entry) { + modCount += 1; + enqueueNotification(e.getKey(), hash, e.getValueReference().get(), cause); + MapMakerInternalMap.ReferenceEntry newFirst = removeFromChain(first, e); + newCount = count - 1; + table.set(index, newFirst); + count = newCount; + return true; + } + } + + return false; + } + + + + + boolean isCollected(MapMakerInternalMap.ValueReference valueReference) + { + if (valueReference.isComputingReference()) { + return false; + } + return valueReference.get() == null; + } + + + + + V getLiveValue(MapMakerInternalMap.ReferenceEntry entry) + { + if (entry.getKey() == null) { + tryDrainReferenceQueues(); + return null; + } + V value = entry.getValueReference().get(); + if (value == null) { + tryDrainReferenceQueues(); + return null; + } + + if ((map.expires()) && (map.isExpired(entry))) { + tryExpireEntries(); + return null; + } + return value; + } + + + + + + void postReadCleanup() + { + if ((readCount.incrementAndGet() & 0x3F) == 0) { + runCleanup(); + } + } + + + + + + + @GuardedBy("Segment.this") + void preWriteCleanup() + { + runLockedCleanup(); + } + + + + void postWriteCleanup() + { + runUnlockedCleanup(); + } + + void runCleanup() { + runLockedCleanup(); + runUnlockedCleanup(); + } + + void runLockedCleanup() { + if (tryLock()) { + try { + drainReferenceQueues(); + expireEntries(); + readCount.set(0); + } finally { + unlock(); + } + } + } + + void runUnlockedCleanup() + { + if (!isHeldByCurrentThread()) { + map.processPendingNotifications(); + } + } + } + + + + + + + + + + + + + + static final class EvictionQueue + extends AbstractQueue> + { + final MapMakerInternalMap.ReferenceEntry head = new MapMakerInternalMap.AbstractReferenceEntry() + { + MapMakerInternalMap.ReferenceEntry nextEvictable = this; + + public MapMakerInternalMap.ReferenceEntry getNextEvictable() + { + return nextEvictable; + } + + public void setNextEvictable(MapMakerInternalMap.ReferenceEntry next) + { + nextEvictable = next; + } + + MapMakerInternalMap.ReferenceEntry previousEvictable = this; + + public MapMakerInternalMap.ReferenceEntry getPreviousEvictable() + { + return previousEvictable; + } + + public void setPreviousEvictable(MapMakerInternalMap.ReferenceEntry previous) + { + previousEvictable = previous; + } + }; + + + EvictionQueue() {} + + public boolean offer(MapMakerInternalMap.ReferenceEntry entry) + { + MapMakerInternalMap.connectEvictables(entry.getPreviousEvictable(), entry.getNextEvictable()); + + + MapMakerInternalMap.connectEvictables(head.getPreviousEvictable(), entry); + MapMakerInternalMap.connectEvictables(entry, head); + + return true; + } + + public MapMakerInternalMap.ReferenceEntry peek() + { + MapMakerInternalMap.ReferenceEntry next = head.getNextEvictable(); + return next == head ? null : next; + } + + public MapMakerInternalMap.ReferenceEntry poll() + { + MapMakerInternalMap.ReferenceEntry next = head.getNextEvictable(); + if (next == head) { + return null; + } + + remove(next); + return next; + } + + + public boolean remove(Object o) + { + MapMakerInternalMap.ReferenceEntry e = (MapMakerInternalMap.ReferenceEntry)o; + MapMakerInternalMap.ReferenceEntry previous = e.getPreviousEvictable(); + MapMakerInternalMap.ReferenceEntry next = e.getNextEvictable(); + MapMakerInternalMap.connectEvictables(previous, next); + MapMakerInternalMap.nullifyEvictable(e); + + return next != MapMakerInternalMap.NullEntry.INSTANCE; + } + + + public boolean contains(Object o) + { + MapMakerInternalMap.ReferenceEntry e = (MapMakerInternalMap.ReferenceEntry)o; + return e.getNextEvictable() != MapMakerInternalMap.NullEntry.INSTANCE; + } + + public boolean isEmpty() + { + return head.getNextEvictable() == head; + } + + public int size() + { + int size = 0; + for (MapMakerInternalMap.ReferenceEntry e = head.getNextEvictable(); e != head; e = e.getNextEvictable()) { + size++; + } + return size; + } + + public void clear() + { + MapMakerInternalMap.ReferenceEntry e = head.getNextEvictable(); + while (e != head) { + MapMakerInternalMap.ReferenceEntry next = e.getNextEvictable(); + MapMakerInternalMap.nullifyEvictable(e); + e = next; + } + + head.setNextEvictable(head); + head.setPreviousEvictable(head); + } + + public Iterator> iterator() + { + new AbstractSequentialIterator(peek()) + { + protected MapMakerInternalMap.ReferenceEntry computeNext(MapMakerInternalMap.ReferenceEntry previous) { + MapMakerInternalMap.ReferenceEntry next = previous.getNextEvictable(); + return next == head ? null : next; + } + }; + } + } + + + + + + + + + + + static final class ExpirationQueue + extends AbstractQueue> + { + final MapMakerInternalMap.ReferenceEntry head = new MapMakerInternalMap.AbstractReferenceEntry() + { + public long getExpirationTime() + { + return Long.MAX_VALUE; + } + + + + + MapMakerInternalMap.ReferenceEntry nextExpirable = this; + + public void setExpirationTime(long time) {} + + public MapMakerInternalMap.ReferenceEntry getNextExpirable() { return nextExpirable; } + + + public void setNextExpirable(MapMakerInternalMap.ReferenceEntry next) + { + nextExpirable = next; + } + + MapMakerInternalMap.ReferenceEntry previousExpirable = this; + + public MapMakerInternalMap.ReferenceEntry getPreviousExpirable() + { + return previousExpirable; + } + + public void setPreviousExpirable(MapMakerInternalMap.ReferenceEntry previous) + { + previousExpirable = previous; + } + }; + + + ExpirationQueue() {} + + public boolean offer(MapMakerInternalMap.ReferenceEntry entry) + { + MapMakerInternalMap.connectExpirables(entry.getPreviousExpirable(), entry.getNextExpirable()); + + + MapMakerInternalMap.connectExpirables(head.getPreviousExpirable(), entry); + MapMakerInternalMap.connectExpirables(entry, head); + + return true; + } + + public MapMakerInternalMap.ReferenceEntry peek() + { + MapMakerInternalMap.ReferenceEntry next = head.getNextExpirable(); + return next == head ? null : next; + } + + public MapMakerInternalMap.ReferenceEntry poll() + { + MapMakerInternalMap.ReferenceEntry next = head.getNextExpirable(); + if (next == head) { + return null; + } + + remove(next); + return next; + } + + + public boolean remove(Object o) + { + MapMakerInternalMap.ReferenceEntry e = (MapMakerInternalMap.ReferenceEntry)o; + MapMakerInternalMap.ReferenceEntry previous = e.getPreviousExpirable(); + MapMakerInternalMap.ReferenceEntry next = e.getNextExpirable(); + MapMakerInternalMap.connectExpirables(previous, next); + MapMakerInternalMap.nullifyExpirable(e); + + return next != MapMakerInternalMap.NullEntry.INSTANCE; + } + + + public boolean contains(Object o) + { + MapMakerInternalMap.ReferenceEntry e = (MapMakerInternalMap.ReferenceEntry)o; + return e.getNextExpirable() != MapMakerInternalMap.NullEntry.INSTANCE; + } + + public boolean isEmpty() + { + return head.getNextExpirable() == head; + } + + public int size() + { + int size = 0; + for (MapMakerInternalMap.ReferenceEntry e = head.getNextExpirable(); e != head; e = e.getNextExpirable()) { + size++; + } + return size; + } + + public void clear() + { + MapMakerInternalMap.ReferenceEntry e = head.getNextExpirable(); + while (e != head) { + MapMakerInternalMap.ReferenceEntry next = e.getNextExpirable(); + MapMakerInternalMap.nullifyExpirable(e); + e = next; + } + + head.setNextExpirable(head); + head.setPreviousExpirable(head); + } + + public Iterator> iterator() + { + new AbstractSequentialIterator(peek()) + { + protected MapMakerInternalMap.ReferenceEntry computeNext(MapMakerInternalMap.ReferenceEntry previous) { + MapMakerInternalMap.ReferenceEntry next = previous.getNextExpirable(); + return next == head ? null : next; + } + }; + } + } + + static final class CleanupMapTask implements Runnable { + final WeakReference> mapReference; + + public CleanupMapTask(MapMakerInternalMap map) { + mapReference = new WeakReference(map); + } + + public void run() + { + MapMakerInternalMap map = (MapMakerInternalMap)mapReference.get(); + if (map == null) { + throw new CancellationException(); + } + + for (MapMakerInternalMap.Segment segment : segments) { + segment.runCleanup(); + } + } + } + + + + + + + + + + + public boolean isEmpty() + { + long sum = 0L; + Segment[] segments = this.segments; + for (int i = 0; i < segments.length; i++) { + if (count != 0) { + return false; + } + sum += modCount; + } + + if (sum != 0L) { + for (int i = 0; i < segments.length; i++) { + if (count != 0) { + return false; + } + sum -= modCount; + } + if (sum != 0L) { + return false; + } + } + return true; + } + + public int size() + { + Segment[] segments = this.segments; + long sum = 0L; + for (int i = 0; i < segments.length; i++) { + sum += count; + } + return Ints.saturatedCast(sum); + } + + public V get(@Nullable Object key) + { + if (key == null) { + return null; + } + int hash = hash(key); + return segmentFor(hash).get(key, hash); + } + + + + + ReferenceEntry getEntry(@Nullable Object key) + { + if (key == null) { + return null; + } + int hash = hash(key); + return segmentFor(hash).getEntry(key, hash); + } + + public boolean containsKey(@Nullable Object key) + { + if (key == null) { + return false; + } + int hash = hash(key); + return segmentFor(hash).containsKey(key, hash); + } + + public boolean containsValue(@Nullable Object value) + { + if (value == null) { + return false; + } + + + + + + + Segment[] segments = this.segments; + long last = -1L; + for (int i = 0; i < 3; i++) { + long sum = 0L; + for (Segment segment : segments) + { + + int c = count; + + AtomicReferenceArray> table = table; + for (int j = 0; j < table.length(); j++) { + for (ReferenceEntry e = (ReferenceEntry)table.get(j); e != null; e = e.getNext()) { + V v = segment.getLiveValue(e); + if ((v != null) && (valueEquivalence.equivalent(value, v))) { + return true; + } + } + } + sum += modCount; + } + if (sum == last) { + break; + } + last = sum; + } + return false; + } + + public V put(K key, V value) + { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(value); + int hash = hash(key); + return segmentFor(hash).put(key, hash, value, false); + } + + public V putIfAbsent(K key, V value) + { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(value); + int hash = hash(key); + return segmentFor(hash).put(key, hash, value, true); + } + + public void putAll(Map m) + { + for (Map.Entry e : m.entrySet()) { + put(e.getKey(), e.getValue()); + } + } + + public V remove(@Nullable Object key) + { + if (key == null) { + return null; + } + int hash = hash(key); + return segmentFor(hash).remove(key, hash); + } + + public boolean remove(@Nullable Object key, @Nullable Object value) + { + if ((key == null) || (value == null)) { + return false; + } + int hash = hash(key); + return segmentFor(hash).remove(key, hash, value); + } + + public boolean replace(K key, @Nullable V oldValue, V newValue) + { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(newValue); + if (oldValue == null) { + return false; + } + int hash = hash(key); + return segmentFor(hash).replace(key, hash, oldValue, newValue); + } + + public V replace(K key, V value) + { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(value); + int hash = hash(key); + return segmentFor(hash).replace(key, hash, value); + } + + public void clear() + { + for (Segment segment : segments) { + segment.clear(); + } + } + + + + public Set keySet() + { + Set ks = keySet; + return this.keySet = new KeySet(); + } + + + + public Collection values() + { + Collection vs = values; + return this.values = new Values(); + } + + + + public Set> entrySet() + { + Set> es = entrySet; + return this.entrySet = new EntrySet(); + } + + abstract class HashIterator + implements Iterator + { + int nextSegmentIndex; + int nextTableIndex; + MapMakerInternalMap.Segment currentSegment; + AtomicReferenceArray> currentTable; + MapMakerInternalMap.ReferenceEntry nextEntry; + MapMakerInternalMap.WriteThroughEntry nextExternal; + MapMakerInternalMap.WriteThroughEntry lastReturned; + + HashIterator() + { + nextSegmentIndex = (segments.length - 1); + nextTableIndex = -1; + advance(); + } + + public abstract E next(); + + final void advance() + { + nextExternal = null; + + if (nextInChain()) { + return; + } + + if (nextInTable()) { + return; + } + + while (nextSegmentIndex >= 0) { + currentSegment = segments[(nextSegmentIndex--)]; + if (currentSegment.count != 0) { + currentTable = currentSegment.table; + nextTableIndex = (currentTable.length() - 1); + if (nextInTable()) {} + } + } + } + + + + + + boolean nextInChain() + { + if (nextEntry != null) { + for (nextEntry = nextEntry.getNext(); nextEntry != null; nextEntry = nextEntry.getNext()) { + if (advanceTo(nextEntry)) { + return true; + } + } + } + return false; + } + + + + boolean nextInTable() + { + while (nextTableIndex >= 0) { + if (((this.nextEntry = (MapMakerInternalMap.ReferenceEntry)currentTable.get(nextTableIndex--)) != null) && ( + (advanceTo(nextEntry)) || (nextInChain()))) { + return true; + } + } + + return false; + } + + + + boolean advanceTo(MapMakerInternalMap.ReferenceEntry entry) + { + try + { + K key = entry.getKey(); + V value = getLiveValue(entry); + boolean bool; if (value != null) { + nextExternal = new MapMakerInternalMap.WriteThroughEntry(MapMakerInternalMap.this, key, value); + return true; + } + + return false; + } + finally { + currentSegment.postReadCleanup(); + } + } + + public boolean hasNext() + { + return nextExternal != null; + } + + MapMakerInternalMap.WriteThroughEntry nextEntry() { + if (nextExternal == null) { + throw new NoSuchElementException(); + } + lastReturned = nextExternal; + advance(); + return lastReturned; + } + + public void remove() + { + CollectPreconditions.checkRemove(lastReturned != null); + remove(lastReturned.getKey()); + lastReturned = null; + } + } + + final class KeyIterator extends MapMakerInternalMap.HashIterator { KeyIterator() { super(); } + + + + public K next() { return nextEntry().getKey(); } + } + + final class ValueIterator extends MapMakerInternalMap.HashIterator { + ValueIterator() { super(); } + + public V next() + { + return nextEntry().getValue(); + } + } + + + final class WriteThroughEntry + extends AbstractMapEntry + { + final K key; + V value; + + WriteThroughEntry(V key) + { + this.key = key; + this.value = value; + } + + public K getKey() + { + return key; + } + + public V getValue() + { + return value; + } + + + public boolean equals(@Nullable Object object) + { + if ((object instanceof Map.Entry)) { + Map.Entry that = (Map.Entry)object; + return (key.equals(that.getKey())) && (value.equals(that.getValue())); + } + return false; + } + + + public int hashCode() + { + return key.hashCode() ^ value.hashCode(); + } + + public V setValue(V newValue) + { + V oldValue = put(key, newValue); + value = newValue; + return oldValue; + } + } + + final class EntryIterator extends MapMakerInternalMap.HashIterator> { EntryIterator() { super(); } + + public Map.Entry next() + { + return nextEntry(); + } + } + + final class KeySet extends AbstractSet { + KeySet() {} + + public Iterator iterator() { + return new MapMakerInternalMap.KeyIterator(MapMakerInternalMap.this); + } + + public int size() + { + return MapMakerInternalMap.this.size(); + } + + public boolean isEmpty() + { + return MapMakerInternalMap.this.isEmpty(); + } + + public boolean contains(Object o) + { + return containsKey(o); + } + + public boolean remove(Object o) + { + return remove(o) != null; + } + + public void clear() + { + MapMakerInternalMap.this.clear(); + } + } + + final class Values extends AbstractCollection { + Values() {} + + public Iterator iterator() { + return new MapMakerInternalMap.ValueIterator(MapMakerInternalMap.this); + } + + public int size() + { + return MapMakerInternalMap.this.size(); + } + + public boolean isEmpty() + { + return MapMakerInternalMap.this.isEmpty(); + } + + public boolean contains(Object o) + { + return containsValue(o); + } + + public void clear() + { + MapMakerInternalMap.this.clear(); + } + } + + final class EntrySet extends AbstractSet> { + EntrySet() {} + + public Iterator> iterator() { + return new MapMakerInternalMap.EntryIterator(MapMakerInternalMap.this); + } + + public boolean contains(Object o) + { + if (!(o instanceof Map.Entry)) { + return false; + } + Map.Entry e = (Map.Entry)o; + Object key = e.getKey(); + if (key == null) { + return false; + } + V v = get(key); + + return (v != null) && (valueEquivalence.equivalent(e.getValue(), v)); + } + + public boolean remove(Object o) + { + if (!(o instanceof Map.Entry)) { + return false; + } + Map.Entry e = (Map.Entry)o; + Object key = e.getKey(); + return (key != null) && (remove(key, e.getValue())); + } + + public int size() + { + return MapMakerInternalMap.this.size(); + } + + public boolean isEmpty() + { + return MapMakerInternalMap.this.isEmpty(); + } + + public void clear() + { + MapMakerInternalMap.this.clear(); + } + } + + + + + Object writeReplace() + { + return new SerializationProxy(keyStrength, valueStrength, keyEquivalence, valueEquivalence, expireAfterWriteNanos, expireAfterAccessNanos, maximumSize, concurrencyLevel, removalListener, this); + } + + + static abstract class AbstractSerializationProxy + extends ForwardingConcurrentMap + implements Serializable + { + private static final long serialVersionUID = 3L; + + final MapMakerInternalMap.Strength keyStrength; + + final MapMakerInternalMap.Strength valueStrength; + + final Equivalence keyEquivalence; + + final Equivalence valueEquivalence; + + final long expireAfterWriteNanos; + + final long expireAfterAccessNanos; + + final int maximumSize; + + final int concurrencyLevel; + final MapMaker.RemovalListener removalListener; + transient ConcurrentMap delegate; + + AbstractSerializationProxy(MapMakerInternalMap.Strength keyStrength, MapMakerInternalMap.Strength valueStrength, Equivalence keyEquivalence, Equivalence valueEquivalence, long expireAfterWriteNanos, long expireAfterAccessNanos, int maximumSize, int concurrencyLevel, MapMaker.RemovalListener removalListener, ConcurrentMap delegate) + { + this.keyStrength = keyStrength; + this.valueStrength = valueStrength; + this.keyEquivalence = keyEquivalence; + this.valueEquivalence = valueEquivalence; + this.expireAfterWriteNanos = expireAfterWriteNanos; + this.expireAfterAccessNanos = expireAfterAccessNanos; + this.maximumSize = maximumSize; + this.concurrencyLevel = concurrencyLevel; + this.removalListener = removalListener; + this.delegate = delegate; + } + + protected ConcurrentMap delegate() + { + return delegate; + } + + void writeMapTo(ObjectOutputStream out) throws IOException { + out.writeInt(delegate.size()); + for (Map.Entry entry : delegate.entrySet()) { + out.writeObject(entry.getKey()); + out.writeObject(entry.getValue()); + } + out.writeObject(null); + } + + MapMaker readMapMaker(ObjectInputStream in) throws IOException + { + int size = in.readInt(); + MapMaker mapMaker = new MapMaker().initialCapacity(size).setKeyStrength(keyStrength).setValueStrength(valueStrength).keyEquivalence(keyEquivalence).concurrencyLevel(concurrencyLevel); + + + + + + mapMaker.removalListener(removalListener); + if (expireAfterWriteNanos > 0L) { + mapMaker.expireAfterWrite(expireAfterWriteNanos, TimeUnit.NANOSECONDS); + } + if (expireAfterAccessNanos > 0L) { + mapMaker.expireAfterAccess(expireAfterAccessNanos, TimeUnit.NANOSECONDS); + } + if (maximumSize != -1) { + mapMaker.maximumSize(maximumSize); + } + return mapMaker; + } + + void readEntries(ObjectInputStream in) throws IOException, ClassNotFoundException + { + for (;;) { + K key = in.readObject(); + if (key == null) { + break; + } + V value = in.readObject(); + delegate.put(key, value); + } + } + } + + + + + private static final class SerializationProxy + extends MapMakerInternalMap.AbstractSerializationProxy + { + private static final long serialVersionUID = 3L; + + + + SerializationProxy(MapMakerInternalMap.Strength keyStrength, MapMakerInternalMap.Strength valueStrength, Equivalence keyEquivalence, Equivalence valueEquivalence, long expireAfterWriteNanos, long expireAfterAccessNanos, int maximumSize, int concurrencyLevel, MapMaker.RemovalListener removalListener, ConcurrentMap delegate) + { + super(valueStrength, keyEquivalence, valueEquivalence, expireAfterWriteNanos, expireAfterAccessNanos, maximumSize, concurrencyLevel, removalListener, delegate); + } + + private void writeObject(ObjectOutputStream out) throws IOException + { + out.defaultWriteObject(); + writeMapTo(out); + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + MapMaker mapMaker = readMapMaker(in); + delegate = mapMaker.makeMap(); + readEntries(in); + } + + private Object readResolve() { + return delegate; + } + } +} diff --git a/src/minecraft/com/google/common/collect/Maps.java b/src/minecraft/com/google/common/collect/Maps.java new file mode 100644 index 0000000..c007be2 --- /dev/null +++ b/src/minecraft/com/google/common/collect/Maps.java @@ -0,0 +1,3979 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Converter; +import com.google.common.base.Equivalence; +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.base.Joiner.MapJoiner; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import java.io.Serializable; +import java.util.AbstractCollection; +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.EnumMap; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NavigableMap; +import java.util.NavigableSet; +import java.util.Properties; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.TreeMap; +import java.util.concurrent.ConcurrentMap; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public final class Maps +{ + private Maps() {} + + private static abstract enum EntryFunction + implements Function, Object> + { + KEY, + + + + + + + VALUE; + + + + private EntryFunction() {} + } + + + + static Function, K> keyFunction() + { + return EntryFunction.KEY; + } + + static Function, V> valueFunction() + { + return EntryFunction.VALUE; + } + + static Iterator keyIterator(Iterator> entryIterator) { + return Iterators.transform(entryIterator, keyFunction()); + } + + static Iterator valueIterator(Iterator> entryIterator) { + return Iterators.transform(entryIterator, valueFunction()); + } + + static UnmodifiableIterator valueIterator(UnmodifiableIterator> entryIterator) + { + new UnmodifiableIterator() + { + public boolean hasNext() { + return val$entryIterator.hasNext(); + } + + public V next() + { + return ((Map.Entry)val$entryIterator.next()).getValue(); + } + }; + } + + + + + + + + + + + + + @GwtCompatible(serializable=true) + @Beta + public static , V> ImmutableMap immutableEnumMap(Map map) + { + if ((map instanceof ImmutableEnumMap)) + { + ImmutableEnumMap result = (ImmutableEnumMap)map; + return result; } + if (map.isEmpty()) { + return ImmutableMap.of(); + } + for (Map.Entry entry : map.entrySet()) { + Preconditions.checkNotNull(entry.getKey()); + Preconditions.checkNotNull(entry.getValue()); + } + return ImmutableEnumMap.asImmutable(new EnumMap(map)); + } + + + + + + + + + + + + + public static HashMap newHashMap() + { + return new HashMap(); + } + + + + + + + + + + + + + + + public static HashMap newHashMapWithExpectedSize(int expectedSize) + { + return new HashMap(capacity(expectedSize)); + } + + + + + + static int capacity(int expectedSize) + { + if (expectedSize < 3) { + CollectPreconditions.checkNonnegative(expectedSize, "expectedSize"); + return expectedSize + 1; + } + if (expectedSize < 1073741824) { + return expectedSize + expectedSize / 3; + } + return Integer.MAX_VALUE; + } + + + + + + + + + + + + + + + + public static HashMap newHashMap(Map map) + { + return new HashMap(map); + } + + + + + + + + + + public static LinkedHashMap newLinkedHashMap() + { + return new LinkedHashMap(); + } + + + + + + + + + + + + + public static LinkedHashMap newLinkedHashMap(Map map) + { + return new LinkedHashMap(map); + } + + + + + + + + + + + + + + + + public static ConcurrentMap newConcurrentMap() + { + return new MapMaker().makeMap(); + } + + + + + + + + + + public static TreeMap newTreeMap() + { + return new TreeMap(); + } + + + + + + + + + + + + + public static TreeMap newTreeMap(SortedMap map) + { + return new TreeMap(map); + } + + + + + + + + + + + + + + + + + public static TreeMap newTreeMap(@Nullable Comparator comparator) + { + return new TreeMap(comparator); + } + + + + + + + public static , V> EnumMap newEnumMap(Class type) + { + return new EnumMap((Class)Preconditions.checkNotNull(type)); + } + + + + + + + + + + + public static , V> EnumMap newEnumMap(Map map) + { + return new EnumMap(map); + } + + + + + + public static IdentityHashMap newIdentityHashMap() + { + return new IdentityHashMap(); + } + + + + + + + + + + + + + + + + + + + public static MapDifference difference(Map left, Map right) + { + if ((left instanceof SortedMap)) { + SortedMap sortedLeft = (SortedMap)left; + SortedMapDifference result = difference(sortedLeft, right); + return result; + } + return difference(left, right, Equivalence.equals()); + } + + + + + + + + + + + + + + + + + + + + + + @Beta + public static MapDifference difference(Map left, Map right, Equivalence valueEquivalence) + { + Preconditions.checkNotNull(valueEquivalence); + + Map onlyOnLeft = newHashMap(); + Map onlyOnRight = new HashMap(right); + Map onBoth = newHashMap(); + Map> differences = newHashMap(); + doDifference(left, right, valueEquivalence, onlyOnLeft, onlyOnRight, onBoth, differences); + return new MapDifferenceImpl(onlyOnLeft, onlyOnRight, onBoth, differences); + } + + + + + private static void doDifference(Map left, Map right, Equivalence valueEquivalence, Map onlyOnLeft, Map onlyOnRight, Map onBoth, Map> differences) + { + for (Map.Entry entry : left.entrySet()) { + K leftKey = entry.getKey(); + V leftValue = entry.getValue(); + if (right.containsKey(leftKey)) { + V rightValue = onlyOnRight.remove(leftKey); + if (valueEquivalence.equivalent(leftValue, rightValue)) { + onBoth.put(leftKey, leftValue); + } else { + differences.put(leftKey, ValueDifferenceImpl.create(leftValue, rightValue)); + } + } + else { + onlyOnLeft.put(leftKey, leftValue); + } + } + } + + private static Map unmodifiableMap(Map map) { + if ((map instanceof SortedMap)) { + return Collections.unmodifiableSortedMap((SortedMap)map); + } + return Collections.unmodifiableMap(map); + } + + static class MapDifferenceImpl + implements MapDifference + { + final Map onlyOnLeft; + final Map onlyOnRight; + final Map onBoth; + final Map> differences; + + MapDifferenceImpl(Map onlyOnLeft, Map onlyOnRight, Map onBoth, Map> differences) + { + this.onlyOnLeft = Maps.unmodifiableMap(onlyOnLeft); + this.onlyOnRight = Maps.unmodifiableMap(onlyOnRight); + this.onBoth = Maps.unmodifiableMap(onBoth); + this.differences = Maps.unmodifiableMap(differences); + } + + public boolean areEqual() + { + return (onlyOnLeft.isEmpty()) && (onlyOnRight.isEmpty()) && (differences.isEmpty()); + } + + public Map entriesOnlyOnLeft() + { + return onlyOnLeft; + } + + public Map entriesOnlyOnRight() + { + return onlyOnRight; + } + + public Map entriesInCommon() + { + return onBoth; + } + + public Map> entriesDiffering() + { + return differences; + } + + public boolean equals(Object object) { + if (object == this) { + return true; + } + if ((object instanceof MapDifference)) { + MapDifference other = (MapDifference)object; + return (entriesOnlyOnLeft().equals(other.entriesOnlyOnLeft())) && (entriesOnlyOnRight().equals(other.entriesOnlyOnRight())) && (entriesInCommon().equals(other.entriesInCommon())) && (entriesDiffering().equals(other.entriesDiffering())); + } + + + + return false; + } + + public int hashCode() { + return Objects.hashCode(new Object[] { entriesOnlyOnLeft(), entriesOnlyOnRight(), entriesInCommon(), entriesDiffering() }); + } + + public String toString() + { + if (areEqual()) { + return "equal"; + } + + StringBuilder result = new StringBuilder("not equal"); + if (!onlyOnLeft.isEmpty()) { + result.append(": only on left=").append(onlyOnLeft); + } + if (!onlyOnRight.isEmpty()) { + result.append(": only on right=").append(onlyOnRight); + } + if (!differences.isEmpty()) { + result.append(": value differences=").append(differences); + } + return result.toString(); + } + } + + static class ValueDifferenceImpl implements MapDifference.ValueDifference + { + private final V left; + private final V right; + + static MapDifference.ValueDifference create(@Nullable V left, @Nullable V right) { + return new ValueDifferenceImpl(left, right); + } + + private ValueDifferenceImpl(@Nullable V left, @Nullable V right) { + this.left = left; + this.right = right; + } + + public V leftValue() + { + return left; + } + + public V rightValue() + { + return right; + } + + public boolean equals(@Nullable Object object) { + if ((object instanceof MapDifference.ValueDifference)) { + MapDifference.ValueDifference that = (MapDifference.ValueDifference)object; + + return (Objects.equal(left, that.leftValue())) && (Objects.equal(right, that.rightValue())); + } + + return false; + } + + public int hashCode() { + return Objects.hashCode(new Object[] { left, right }); + } + + public String toString() { + return "(" + left + ", " + right + ")"; + } + } + + + + + + + + + + + + + + + + + + + + + public static SortedMapDifference difference(SortedMap left, Map right) + { + Preconditions.checkNotNull(left); + Preconditions.checkNotNull(right); + Comparator comparator = orNaturalOrder(left.comparator()); + SortedMap onlyOnLeft = newTreeMap(comparator); + SortedMap onlyOnRight = newTreeMap(comparator); + onlyOnRight.putAll(right); + SortedMap onBoth = newTreeMap(comparator); + SortedMap> differences = newTreeMap(comparator); + + doDifference(left, right, Equivalence.equals(), onlyOnLeft, onlyOnRight, onBoth, differences); + return new SortedMapDifferenceImpl(onlyOnLeft, onlyOnRight, onBoth, differences); + } + + static class SortedMapDifferenceImpl + extends Maps.MapDifferenceImpl implements SortedMapDifference + { + SortedMapDifferenceImpl(SortedMap onlyOnLeft, SortedMap onlyOnRight, SortedMap onBoth, SortedMap> differences) + { + super(onlyOnRight, onBoth, differences); + } + + public SortedMap> entriesDiffering() { + return (SortedMap)super.entriesDiffering(); + } + + public SortedMap entriesInCommon() { + return (SortedMap)super.entriesInCommon(); + } + + public SortedMap entriesOnlyOnLeft() { + return (SortedMap)super.entriesOnlyOnLeft(); + } + + public SortedMap entriesOnlyOnRight() { + return (SortedMap)super.entriesOnlyOnRight(); + } + } + + + + + + + + static Comparator orNaturalOrder(@Nullable Comparator comparator) + { + if (comparator != null) { + return comparator; + } + return Ordering.natural(); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @Beta + public static Map asMap(Set set, Function function) + { + if ((set instanceof SortedSet)) { + return asMap((SortedSet)set, function); + } + return new AsMapView(set, function); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @Beta + public static SortedMap asMap(SortedSet set, Function function) + { + return Platform.mapsAsMapSortedSet(set, function); + } + + static SortedMap asMapSortedIgnoreNavigable(SortedSet set, Function function) + { + return new SortedAsMapView(set, function); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + @Beta + @GwtIncompatible("NavigableMap") + public static NavigableMap asMap(NavigableSet set, Function function) + { + return new NavigableAsMapView(set, function); + } + + private static class AsMapView extends Maps.ImprovedAbstractMap + { + private final Set set; + final Function function; + + Set backingSet() { + return set; + } + + AsMapView(Set set, Function function) { + this.set = ((Set)Preconditions.checkNotNull(set)); + this.function = ((Function)Preconditions.checkNotNull(function)); + } + + public Set createKeySet() + { + return Maps.removeOnlySet(backingSet()); + } + + Collection createValues() + { + return Collections2.transform(set, function); + } + + public int size() + { + return backingSet().size(); + } + + public boolean containsKey(@Nullable Object key) + { + return backingSet().contains(key); + } + + public V get(@Nullable Object key) + { + if (Collections2.safeContains(backingSet(), key)) + { + K k = key; + return function.apply(k); + } + return null; + } + + + public V remove(@Nullable Object key) + { + if (backingSet().remove(key)) + { + K k = key; + return function.apply(k); + } + return null; + } + + + public void clear() + { + backingSet().clear(); + } + + protected Set> createEntrySet() + { + new Maps.EntrySet() + { + Map map() { + return Maps.AsMapView.this; + } + + public Iterator> iterator() + { + return Maps.asMapEntryIterator(backingSet(), function); + } + }; + } + } + + static Iterator> asMapEntryIterator(Set set, final Function function) + { + new TransformedIterator(set.iterator()) + { + Map.Entry transform(K key) { + return Maps.immutableEntry(key, function.apply(key)); + } + }; + } + + private static class SortedAsMapView extends Maps.AsMapView implements SortedMap + { + SortedAsMapView(SortedSet set, Function function) + { + super(function); + } + + SortedSet backingSet() + { + return (SortedSet)super.backingSet(); + } + + public Comparator comparator() + { + return backingSet().comparator(); + } + + public Set keySet() + { + return Maps.removeOnlySortedSet(backingSet()); + } + + public SortedMap subMap(K fromKey, K toKey) + { + return Maps.asMap(backingSet().subSet(fromKey, toKey), function); + } + + public SortedMap headMap(K toKey) + { + return Maps.asMap(backingSet().headSet(toKey), function); + } + + public SortedMap tailMap(K fromKey) + { + return Maps.asMap(backingSet().tailSet(fromKey), function); + } + + public K firstKey() + { + return backingSet().first(); + } + + public K lastKey() + { + return backingSet().last(); + } + } + + + @GwtIncompatible("NavigableMap") + private static final class NavigableAsMapView + extends AbstractNavigableMap + { + private final NavigableSet set; + + private final Function function; + + + NavigableAsMapView(NavigableSet ks, Function vFunction) + { + set = ((NavigableSet)Preconditions.checkNotNull(ks)); + function = ((Function)Preconditions.checkNotNull(vFunction)); + } + + + public NavigableMap subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) + { + return Maps.asMap(set.subSet(fromKey, fromInclusive, toKey, toInclusive), function); + } + + public NavigableMap headMap(K toKey, boolean inclusive) + { + return Maps.asMap(set.headSet(toKey, inclusive), function); + } + + public NavigableMap tailMap(K fromKey, boolean inclusive) + { + return Maps.asMap(set.tailSet(fromKey, inclusive), function); + } + + public Comparator comparator() + { + return set.comparator(); + } + + @Nullable + public V get(@Nullable Object key) + { + if (Collections2.safeContains(set, key)) + { + K k = key; + return function.apply(k); + } + return null; + } + + + public void clear() + { + set.clear(); + } + + Iterator> entryIterator() + { + return Maps.asMapEntryIterator(set, function); + } + + Iterator> descendingEntryIterator() + { + return descendingMap().entrySet().iterator(); + } + + public NavigableSet navigableKeySet() + { + return Maps.removeOnlyNavigableSet(set); + } + + public int size() + { + return set.size(); + } + + public NavigableMap descendingMap() + { + return Maps.asMap(set.descendingSet(), function); + } + } + + private static Set removeOnlySet(Set set) { + new ForwardingSet() + { + protected Set delegate() { + return val$set; + } + + public boolean add(E element) + { + throw new UnsupportedOperationException(); + } + + public boolean addAll(Collection es) + { + throw new UnsupportedOperationException(); + } + }; + } + + private static SortedSet removeOnlySortedSet(SortedSet set) { + new ForwardingSortedSet() + { + protected SortedSet delegate() { + return val$set; + } + + public boolean add(E element) + { + throw new UnsupportedOperationException(); + } + + public boolean addAll(Collection es) + { + throw new UnsupportedOperationException(); + } + + public SortedSet headSet(E toElement) + { + return Maps.removeOnlySortedSet(super.headSet(toElement)); + } + + public SortedSet subSet(E fromElement, E toElement) + { + return Maps.removeOnlySortedSet(super.subSet(fromElement, toElement)); + } + + public SortedSet tailSet(E fromElement) + { + return Maps.removeOnlySortedSet(super.tailSet(fromElement)); + } + }; + } + + @GwtIncompatible("NavigableSet") + private static NavigableSet removeOnlyNavigableSet(NavigableSet set) { + new ForwardingNavigableSet() + { + protected NavigableSet delegate() { + return val$set; + } + + public boolean add(E element) + { + throw new UnsupportedOperationException(); + } + + public boolean addAll(Collection es) + { + throw new UnsupportedOperationException(); + } + + public SortedSet headSet(E toElement) + { + return Maps.removeOnlySortedSet(super.headSet(toElement)); + } + + public SortedSet subSet(E fromElement, E toElement) + { + return Maps.removeOnlySortedSet(super.subSet(fromElement, toElement)); + } + + + public SortedSet tailSet(E fromElement) + { + return Maps.removeOnlySortedSet(super.tailSet(fromElement)); + } + + public NavigableSet headSet(E toElement, boolean inclusive) + { + return Maps.removeOnlyNavigableSet(super.headSet(toElement, inclusive)); + } + + public NavigableSet tailSet(E fromElement, boolean inclusive) + { + return Maps.removeOnlyNavigableSet(super.tailSet(fromElement, inclusive)); + } + + + public NavigableSet subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) + { + return Maps.removeOnlyNavigableSet(super.subSet(fromElement, fromInclusive, toElement, toInclusive)); + } + + + public NavigableSet descendingSet() + { + return Maps.removeOnlyNavigableSet(super.descendingSet()); + } + }; + } + + + + + + + + + + + + + + + + @Beta + public static ImmutableMap toMap(Iterable keys, Function valueFunction) + { + return toMap(keys.iterator(), valueFunction); + } + + + + + + + + + + + + + @Beta + public static ImmutableMap toMap(Iterator keys, Function valueFunction) + { + Preconditions.checkNotNull(valueFunction); + + Map builder = newLinkedHashMap(); + while (keys.hasNext()) { + K key = keys.next(); + builder.put(key, valueFunction.apply(key)); + } + return ImmutableMap.copyOf(builder); + } + + + + + + + + + + + + + + + + public static ImmutableMap uniqueIndex(Iterable values, Function keyFunction) + { + return uniqueIndex(values.iterator(), keyFunction); + } + + + + + + + + + + + + + + + + + public static ImmutableMap uniqueIndex(Iterator values, Function keyFunction) + { + Preconditions.checkNotNull(keyFunction); + ImmutableMap.Builder builder = ImmutableMap.builder(); + while (values.hasNext()) { + V value = values.next(); + builder.put(keyFunction.apply(value), value); + } + return builder.build(); + } + + + + + + + + + + + + + + + @GwtIncompatible("java.util.Properties") + public static ImmutableMap fromProperties(Properties properties) + { + ImmutableMap.Builder builder = ImmutableMap.builder(); + + for (Enumeration e = properties.propertyNames(); e.hasMoreElements();) { + String key = (String)e.nextElement(); + builder.put(key, properties.getProperty(key)); + } + + return builder.build(); + } + + + + + + + + + + + @GwtCompatible(serializable=true) + public static Map.Entry immutableEntry(@Nullable K key, @Nullable V value) + { + return new ImmutableEntry(key, value); + } + + + + + + + + + + static Set> unmodifiableEntrySet(Set> entrySet) + { + return new UnmodifiableEntrySet(Collections.unmodifiableSet(entrySet)); + } + + + + + + + + + + + static Map.Entry unmodifiableEntry(Map.Entry entry) + { + Preconditions.checkNotNull(entry); + new AbstractMapEntry() { + public K getKey() { + return val$entry.getKey(); + } + + public V getValue() { + return val$entry.getValue(); + } + }; + } + + static class UnmodifiableEntries extends ForwardingCollection> + { + private final Collection> entries; + + UnmodifiableEntries(Collection> entries) + { + this.entries = entries; + } + + protected Collection> delegate() { + return entries; + } + + public Iterator> iterator() { + final Iterator> delegate = super.iterator(); + new UnmodifiableIterator() + { + public boolean hasNext() { + return delegate.hasNext(); + } + + public Map.Entry next() { + return Maps.unmodifiableEntry((Map.Entry)delegate.next()); + } + }; + } + + + public Object[] toArray() + { + return standardToArray(); + } + + public T[] toArray(T[] array) { + return standardToArray(array); + } + } + + static class UnmodifiableEntrySet extends Maps.UnmodifiableEntries implements Set> + { + UnmodifiableEntrySet(Set> entries) + { + super(); + } + + + public boolean equals(@Nullable Object object) + { + return Sets.equalsImpl(this, object); + } + + public int hashCode() { + return Sets.hashCodeImpl(this); + } + } + + + + + + + + + + + + @Beta + public static Converter asConverter(BiMap bimap) + { + return new BiMapConverter(bimap); + } + + private static final class BiMapConverter extends Converter implements Serializable { + private final BiMap bimap; + private static final long serialVersionUID = 0L; + + BiMapConverter(BiMap bimap) { this.bimap = ((BiMap)Preconditions.checkNotNull(bimap)); } + + + protected B doForward(A a) + { + return convert(bimap, a); + } + + protected A doBackward(B b) + { + return convert(bimap.inverse(), b); + } + + private static Y convert(BiMap bimap, X input) { + Y output = bimap.get(input); + Preconditions.checkArgument(output != null, "No non-null mapping present for input: %s", new Object[] { input }); + return output; + } + + public boolean equals(@Nullable Object object) + { + if ((object instanceof BiMapConverter)) { + BiMapConverter that = (BiMapConverter)object; + return bimap.equals(bimap); + } + return false; + } + + public int hashCode() + { + return bimap.hashCode(); + } + + + public String toString() + { + return "Maps.asConverter(" + bimap + ")"; + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static BiMap synchronizedBiMap(BiMap bimap) + { + return Synchronized.biMap(bimap, null); + } + + + + + + + + + + + + + + + public static BiMap unmodifiableBiMap(BiMap bimap) + { + return new UnmodifiableBiMap(bimap, null); + } + + private static class UnmodifiableBiMap extends ForwardingMap implements BiMap, Serializable + { + final Map unmodifiableMap; + final BiMap delegate; + BiMap inverse; + transient Set values; + private static final long serialVersionUID = 0L; + + UnmodifiableBiMap(BiMap delegate, @Nullable BiMap inverse) + { + unmodifiableMap = Collections.unmodifiableMap(delegate); + this.delegate = delegate; + this.inverse = inverse; + } + + protected Map delegate() { + return unmodifiableMap; + } + + public V forcePut(K key, V value) + { + throw new UnsupportedOperationException(); + } + + public BiMap inverse() + { + BiMap result = inverse; + return result == null ? (this.inverse = new UnmodifiableBiMap(delegate.inverse(), this)) : result; + } + + + public Set values() + { + Set result = values; + return result == null ? (this.values = Collections.unmodifiableSet(delegate.values())) : result; + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static Map transformValues(Map fromMap, Function function) + { + return transformEntries(fromMap, asEntryTransformer(function)); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static SortedMap transformValues(SortedMap fromMap, Function function) + { + return transformEntries(fromMap, asEntryTransformer(function)); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @GwtIncompatible("NavigableMap") + public static NavigableMap transformValues(NavigableMap fromMap, Function function) + { + return transformEntries(fromMap, asEntryTransformer(function)); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static Map transformEntries(Map fromMap, EntryTransformer transformer) + { + if ((fromMap instanceof SortedMap)) { + return transformEntries((SortedMap)fromMap, transformer); + } + return new TransformedEntriesMap(fromMap, transformer); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static SortedMap transformEntries(SortedMap fromMap, EntryTransformer transformer) + { + return Platform.mapsTransformEntriesSortedMap(fromMap, transformer); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @GwtIncompatible("NavigableMap") + public static NavigableMap transformEntries(NavigableMap fromMap, EntryTransformer transformer) + { + return new TransformedEntriesNavigableMap(fromMap, transformer); + } + + + static SortedMap transformEntriesIgnoreNavigable(SortedMap fromMap, EntryTransformer transformer) + { + return new TransformedEntriesSortedMap(fromMap, transformer); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + static EntryTransformer asEntryTransformer(Function function) + { + Preconditions.checkNotNull(function); + new EntryTransformer() + { + public V2 transformEntry(K key, V1 value) { + return val$function.apply(value); + } + }; + } + + static Function asValueToValueFunction(EntryTransformer transformer, final K key) + { + Preconditions.checkNotNull(transformer); + new Function() + { + public V2 apply(@Nullable V1 v1) { + return val$transformer.transformEntry(key, v1); + } + }; + } + + + + + static Function, V2> asEntryToValueFunction(EntryTransformer transformer) + { + Preconditions.checkNotNull(transformer); + new Function() + { + public V2 apply(Map.Entry entry) { + return val$transformer.transformEntry(entry.getKey(), entry.getValue()); + } + }; + } + + + + + static Map.Entry transformEntry(final EntryTransformer transformer, Map.Entry entry) + { + Preconditions.checkNotNull(transformer); + Preconditions.checkNotNull(entry); + new AbstractMapEntry() + { + public K getKey() { + return val$entry.getKey(); + } + + public V2 getValue() + { + return transformer.transformEntry(val$entry.getKey(), val$entry.getValue()); + } + }; + } + + + + + static Function, Map.Entry> asEntryToEntryFunction(EntryTransformer transformer) + { + Preconditions.checkNotNull(transformer); + new Function() + { + + public Map.Entry apply(Map.Entry entry) { return Maps.transformEntry(val$transformer, entry); } + }; + } + + public static abstract interface EntryTransformer { + public abstract V2 transformEntry(@Nullable K paramK, @Nullable V1 paramV1); + } + + static class TransformedEntriesMap extends Maps.ImprovedAbstractMap { + final Map fromMap; + final Maps.EntryTransformer transformer; + + TransformedEntriesMap(Map fromMap, Maps.EntryTransformer transformer) { + this.fromMap = ((Map)Preconditions.checkNotNull(fromMap)); + this.transformer = ((Maps.EntryTransformer)Preconditions.checkNotNull(transformer)); + } + + public int size() { + return fromMap.size(); + } + + public boolean containsKey(Object key) { + return fromMap.containsKey(key); + } + + + public V2 get(Object key) + { + V1 value = fromMap.get(key); + return (value != null) || (fromMap.containsKey(key)) ? transformer.transformEntry(key, value) : null; + } + + + + + public V2 remove(Object key) + { + return fromMap.containsKey(key) ? transformer.transformEntry(key, fromMap.remove(key)) : null; + } + + + public void clear() + { + fromMap.clear(); + } + + public Set keySet() { + return fromMap.keySet(); + } + + protected Set> createEntrySet() + { + new Maps.EntrySet() { + Map map() { + return Maps.TransformedEntriesMap.this; + } + + public Iterator> iterator() { + return Iterators.transform(fromMap.entrySet().iterator(), Maps.asEntryToEntryFunction(transformer)); + } + }; + } + } + + static class TransformedEntriesSortedMap + extends Maps.TransformedEntriesMap implements SortedMap + { + protected SortedMap fromMap() + { + return (SortedMap)fromMap; + } + + TransformedEntriesSortedMap(SortedMap fromMap, Maps.EntryTransformer transformer) + { + super(transformer); + } + + public Comparator comparator() { + return fromMap().comparator(); + } + + public K firstKey() { + return fromMap().firstKey(); + } + + public SortedMap headMap(K toKey) { + return Maps.transformEntries(fromMap().headMap(toKey), transformer); + } + + public K lastKey() { + return fromMap().lastKey(); + } + + public SortedMap subMap(K fromKey, K toKey) { + return Maps.transformEntries(fromMap().subMap(fromKey, toKey), transformer); + } + + public SortedMap tailMap(K fromKey) + { + return Maps.transformEntries(fromMap().tailMap(fromKey), transformer); + } + } + + @GwtIncompatible("NavigableMap") + private static class TransformedEntriesNavigableMap + extends Maps.TransformedEntriesSortedMap + implements NavigableMap + { + TransformedEntriesNavigableMap(NavigableMap fromMap, Maps.EntryTransformer transformer) + { + super(transformer); + } + + public Map.Entry ceilingEntry(K key) { + return transformEntry(fromMap().ceilingEntry(key)); + } + + public K ceilingKey(K key) { + return fromMap().ceilingKey(key); + } + + public NavigableSet descendingKeySet() { + return fromMap().descendingKeySet(); + } + + public NavigableMap descendingMap() { + return Maps.transformEntries(fromMap().descendingMap(), transformer); + } + + public Map.Entry firstEntry() { + return transformEntry(fromMap().firstEntry()); + } + + public Map.Entry floorEntry(K key) { return transformEntry(fromMap().floorEntry(key)); } + + public K floorKey(K key) + { + return fromMap().floorKey(key); + } + + public NavigableMap headMap(K toKey) { + return headMap(toKey, false); + } + + public NavigableMap headMap(K toKey, boolean inclusive) { + return Maps.transformEntries(fromMap().headMap(toKey, inclusive), transformer); + } + + public Map.Entry higherEntry(K key) + { + return transformEntry(fromMap().higherEntry(key)); + } + + public K higherKey(K key) { + return fromMap().higherKey(key); + } + + public Map.Entry lastEntry() { + return transformEntry(fromMap().lastEntry()); + } + + public Map.Entry lowerEntry(K key) { + return transformEntry(fromMap().lowerEntry(key)); + } + + public K lowerKey(K key) { + return fromMap().lowerKey(key); + } + + public NavigableSet navigableKeySet() { + return fromMap().navigableKeySet(); + } + + public Map.Entry pollFirstEntry() { + return transformEntry(fromMap().pollFirstEntry()); + } + + public Map.Entry pollLastEntry() { + return transformEntry(fromMap().pollLastEntry()); + } + + public NavigableMap subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) + { + return Maps.transformEntries(fromMap().subMap(fromKey, fromInclusive, toKey, toInclusive), transformer); + } + + + public NavigableMap subMap(K fromKey, K toKey) + { + return subMap(fromKey, true, toKey, false); + } + + public NavigableMap tailMap(K fromKey) { + return tailMap(fromKey, true); + } + + public NavigableMap tailMap(K fromKey, boolean inclusive) { + return Maps.transformEntries(fromMap().tailMap(fromKey, inclusive), transformer); + } + + @Nullable + private Map.Entry transformEntry(@Nullable Map.Entry entry) + { + return entry == null ? null : Maps.transformEntry(transformer, entry); + } + + protected NavigableMap fromMap() { + return (NavigableMap)super.fromMap(); + } + } + + static Predicate> keyPredicateOnEntries(Predicate keyPredicate) { + return Predicates.compose(keyPredicate, keyFunction()); + } + + static Predicate> valuePredicateOnEntries(Predicate valuePredicate) { + return Predicates.compose(valuePredicate, valueFunction()); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static Map filterKeys(Map unfiltered, Predicate keyPredicate) + { + if ((unfiltered instanceof SortedMap)) + return filterKeys((SortedMap)unfiltered, keyPredicate); + if ((unfiltered instanceof BiMap)) { + return filterKeys((BiMap)unfiltered, keyPredicate); + } + Preconditions.checkNotNull(keyPredicate); + Predicate> entryPredicate = keyPredicateOnEntries(keyPredicate); + return (unfiltered instanceof AbstractFilteredMap) ? filterFiltered((AbstractFilteredMap)unfiltered, entryPredicate) : new FilteredKeyMap((Map)Preconditions.checkNotNull(unfiltered), keyPredicate, entryPredicate); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static SortedMap filterKeys(SortedMap unfiltered, Predicate keyPredicate) + { + return filterEntries(unfiltered, keyPredicateOnEntries(keyPredicate)); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @GwtIncompatible("NavigableMap") + public static NavigableMap filterKeys(NavigableMap unfiltered, Predicate keyPredicate) + { + return filterEntries(unfiltered, keyPredicateOnEntries(keyPredicate)); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + public static BiMap filterKeys(BiMap unfiltered, Predicate keyPredicate) + { + Preconditions.checkNotNull(keyPredicate); + return filterEntries(unfiltered, keyPredicateOnEntries(keyPredicate)); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static Map filterValues(Map unfiltered, Predicate valuePredicate) + { + if ((unfiltered instanceof SortedMap)) + return filterValues((SortedMap)unfiltered, valuePredicate); + if ((unfiltered instanceof BiMap)) { + return filterValues((BiMap)unfiltered, valuePredicate); + } + return filterEntries(unfiltered, valuePredicateOnEntries(valuePredicate)); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static SortedMap filterValues(SortedMap unfiltered, Predicate valuePredicate) + { + return filterEntries(unfiltered, valuePredicateOnEntries(valuePredicate)); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @GwtIncompatible("NavigableMap") + public static NavigableMap filterValues(NavigableMap unfiltered, Predicate valuePredicate) + { + return filterEntries(unfiltered, valuePredicateOnEntries(valuePredicate)); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static BiMap filterValues(BiMap unfiltered, Predicate valuePredicate) + { + return filterEntries(unfiltered, valuePredicateOnEntries(valuePredicate)); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static Map filterEntries(Map unfiltered, Predicate> entryPredicate) + { + if ((unfiltered instanceof SortedMap)) + return filterEntries((SortedMap)unfiltered, entryPredicate); + if ((unfiltered instanceof BiMap)) { + return filterEntries((BiMap)unfiltered, entryPredicate); + } + Preconditions.checkNotNull(entryPredicate); + return (unfiltered instanceof AbstractFilteredMap) ? filterFiltered((AbstractFilteredMap)unfiltered, entryPredicate) : new FilteredEntryMap((Map)Preconditions.checkNotNull(unfiltered), entryPredicate); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static SortedMap filterEntries(SortedMap unfiltered, Predicate> entryPredicate) + { + return Platform.mapsFilterSortedMap(unfiltered, entryPredicate); + } + + + static SortedMap filterSortedIgnoreNavigable(SortedMap unfiltered, Predicate> entryPredicate) + { + Preconditions.checkNotNull(entryPredicate); + return (unfiltered instanceof FilteredEntrySortedMap) ? filterFiltered((FilteredEntrySortedMap)unfiltered, entryPredicate) : new FilteredEntrySortedMap((SortedMap)Preconditions.checkNotNull(unfiltered), entryPredicate); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @GwtIncompatible("NavigableMap") + public static NavigableMap filterEntries(NavigableMap unfiltered, Predicate> entryPredicate) + { + Preconditions.checkNotNull(entryPredicate); + return (unfiltered instanceof FilteredEntryNavigableMap) ? filterFiltered((FilteredEntryNavigableMap)unfiltered, entryPredicate) : new FilteredEntryNavigableMap((NavigableMap)Preconditions.checkNotNull(unfiltered), entryPredicate); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static BiMap filterEntries(BiMap unfiltered, Predicate> entryPredicate) + { + Preconditions.checkNotNull(unfiltered); + Preconditions.checkNotNull(entryPredicate); + return (unfiltered instanceof FilteredEntryBiMap) ? filterFiltered((FilteredEntryBiMap)unfiltered, entryPredicate) : new FilteredEntryBiMap(unfiltered, entryPredicate); + } + + + + + + + + private static Map filterFiltered(AbstractFilteredMap map, Predicate> entryPredicate) + { + return new FilteredEntryMap(unfiltered, Predicates.and(predicate, entryPredicate)); + } + + private static abstract class AbstractFilteredMap + extends Maps.ImprovedAbstractMap + { + final Map unfiltered; + final Predicate> predicate; + + AbstractFilteredMap(Map unfiltered, Predicate> predicate) + { + this.unfiltered = unfiltered; + this.predicate = predicate; + } + + + + boolean apply(@Nullable Object key, @Nullable V value) + { + K k = key; + return predicate.apply(Maps.immutableEntry(k, value)); + } + + public V put(K key, V value) { + Preconditions.checkArgument(apply(key, value)); + return unfiltered.put(key, value); + } + + public void putAll(Map map) { + for (Map.Entry entry : map.entrySet()) { + Preconditions.checkArgument(apply(entry.getKey(), entry.getValue())); + } + unfiltered.putAll(map); + } + + public boolean containsKey(Object key) { + return (unfiltered.containsKey(key)) && (apply(key, unfiltered.get(key))); + } + + public V get(Object key) { + V value = unfiltered.get(key); + return (value != null) && (apply(key, value)) ? value : null; + } + + public boolean isEmpty() { + return entrySet().isEmpty(); + } + + public V remove(Object key) { + return containsKey(key) ? unfiltered.remove(key) : null; + } + + Collection createValues() + { + return new Maps.FilteredMapValues(this, unfiltered, predicate); + } + } + + private static final class FilteredMapValues extends Maps.Values + { + Map unfiltered; + Predicate> predicate; + + FilteredMapValues(Map filteredMap, Map unfiltered, Predicate> predicate) { + super(); + this.unfiltered = unfiltered; + this.predicate = predicate; + } + + public boolean remove(Object o) { + return Iterables.removeFirstMatching(unfiltered.entrySet(), Predicates.and(predicate, Maps.valuePredicateOnEntries(Predicates.equalTo(o)))) != null; + } + + + private boolean removeIf(Predicate valuePredicate) + { + return Iterables.removeIf(unfiltered.entrySet(), Predicates.and(predicate, Maps.valuePredicateOnEntries(valuePredicate))); + } + + public boolean removeAll(Collection collection) + { + return removeIf(Predicates.in(collection)); + } + + public boolean retainAll(Collection collection) { + return removeIf(Predicates.not(Predicates.in(collection))); + } + + public Object[] toArray() + { + return Lists.newArrayList(iterator()).toArray(); + } + + public T[] toArray(T[] array) { + return Lists.newArrayList(iterator()).toArray(array); + } + } + + private static class FilteredKeyMap extends Maps.AbstractFilteredMap + { + Predicate keyPredicate; + + FilteredKeyMap(Map unfiltered, Predicate keyPredicate, Predicate> entryPredicate) { + super(entryPredicate); + this.keyPredicate = keyPredicate; + } + + protected Set> createEntrySet() + { + return Sets.filter(unfiltered.entrySet(), predicate); + } + + Set createKeySet() + { + return Sets.filter(unfiltered.keySet(), keyPredicate); + } + + + + + public boolean containsKey(Object key) + { + return (unfiltered.containsKey(key)) && (keyPredicate.apply(key)); + } + } + + + static class FilteredEntryMap + extends Maps.AbstractFilteredMap + { + final Set> filteredEntrySet; + + + FilteredEntryMap(Map unfiltered, Predicate> entryPredicate) + { + super(entryPredicate); + filteredEntrySet = Sets.filter(unfiltered.entrySet(), predicate); + } + + + + protected Set> createEntrySet() { return new EntrySet(null); } + + private class EntrySet extends ForwardingSet> { + private EntrySet() {} + + protected Set> delegate() { return filteredEntrySet; } + + public Iterator> iterator() + { + new TransformedIterator(filteredEntrySet.iterator()) + { + Map.Entry transform(final Map.Entry entry) { + new ForwardingMapEntry() + { + protected Map.Entry delegate() { + return entry; + } + + public V setValue(V newValue) + { + Preconditions.checkArgument(apply(getKey(), newValue)); + return super.setValue(newValue); + } + }; + } + }; + } + } + + Set createKeySet() + { + return new KeySet(); + } + + class KeySet extends Maps.KeySet { + KeySet() { + super(); + } + + public boolean remove(Object o) { + if (containsKey(o)) { + unfiltered.remove(o); + return true; + } + return false; + } + + private boolean removeIf(Predicate keyPredicate) { + return Iterables.removeIf(unfiltered.entrySet(), Predicates.and(predicate, Maps.keyPredicateOnEntries(keyPredicate))); + } + + + public boolean removeAll(Collection c) + { + return removeIf(Predicates.in(c)); + } + + public boolean retainAll(Collection c) + { + return removeIf(Predicates.not(Predicates.in(c))); + } + + public Object[] toArray() + { + return Lists.newArrayList(iterator()).toArray(); + } + + public T[] toArray(T[] array) { + return Lists.newArrayList(iterator()).toArray(array); + } + } + } + + + + + + + private static SortedMap filterFiltered(FilteredEntrySortedMap map, Predicate> entryPredicate) + { + Predicate> predicate = Predicates.and(map.predicate, entryPredicate); + + return new FilteredEntrySortedMap(map.sortedMap(), predicate); + } + + private static class FilteredEntrySortedMap + extends Maps.FilteredEntryMap implements SortedMap + { + FilteredEntrySortedMap(SortedMap unfiltered, Predicate> entryPredicate) + { + super(entryPredicate); + } + + SortedMap sortedMap() { + return (SortedMap)unfiltered; + } + + public SortedSet keySet() { + return (SortedSet)super.keySet(); + } + + + + SortedSet createKeySet() { return new SortedKeySet(); } + + class SortedKeySet extends Maps.FilteredEntryMap.KeySet implements SortedSet { + SortedKeySet() { super(); } + + public Comparator comparator() { + return sortedMap().comparator(); + } + + public SortedSet subSet(K fromElement, K toElement) + { + return (SortedSet)subMap(fromElement, toElement).keySet(); + } + + public SortedSet headSet(K toElement) + { + return (SortedSet)headMap(toElement).keySet(); + } + + public SortedSet tailSet(K fromElement) + { + return (SortedSet)tailMap(fromElement).keySet(); + } + + public K first() + { + return firstKey(); + } + + public K last() + { + return lastKey(); + } + } + + public Comparator comparator() { + return sortedMap().comparator(); + } + + public K firstKey() + { + return keySet().iterator().next(); + } + + public K lastKey() { + SortedMap headMap = sortedMap(); + for (;;) + { + K key = headMap.lastKey(); + if (apply(key, unfiltered.get(key))) { + return key; + } + headMap = sortedMap().headMap(key); + } + } + + public SortedMap headMap(K toKey) { + return new FilteredEntrySortedMap(sortedMap().headMap(toKey), predicate); + } + + public SortedMap subMap(K fromKey, K toKey) { + return new FilteredEntrySortedMap(sortedMap().subMap(fromKey, toKey), predicate); + } + + public SortedMap tailMap(K fromKey) + { + return new FilteredEntrySortedMap(sortedMap().tailMap(fromKey), predicate); + } + } + + + + + + + + @GwtIncompatible("NavigableMap") + private static NavigableMap filterFiltered(FilteredEntryNavigableMap map, Predicate> entryPredicate) + { + Predicate> predicate = Predicates.and(map.entryPredicate, entryPredicate); + + return new FilteredEntryNavigableMap(unfiltered, predicate); + } + + + @GwtIncompatible("NavigableMap") + private static class FilteredEntryNavigableMap + extends AbstractNavigableMap + { + private final NavigableMap unfiltered; + + private final Predicate> entryPredicate; + + private final Map filteredDelegate; + + + FilteredEntryNavigableMap(NavigableMap unfiltered, Predicate> entryPredicate) + { + this.unfiltered = ((NavigableMap)Preconditions.checkNotNull(unfiltered)); + this.entryPredicate = entryPredicate; + filteredDelegate = new Maps.FilteredEntryMap(unfiltered, entryPredicate); + } + + public Comparator comparator() + { + return unfiltered.comparator(); + } + + public NavigableSet navigableKeySet() + { + new Maps.NavigableKeySet(this) + { + public boolean removeAll(Collection c) { + return Iterators.removeIf(unfiltered.entrySet().iterator(), Predicates.and(entryPredicate, Maps.keyPredicateOnEntries(Predicates.in(c)))); + } + + + public boolean retainAll(Collection c) + { + return Iterators.removeIf(unfiltered.entrySet().iterator(), Predicates.and(entryPredicate, Maps.keyPredicateOnEntries(Predicates.not(Predicates.in(c))))); + } + }; + } + + + public Collection values() + { + return new Maps.FilteredMapValues(this, unfiltered, entryPredicate); + } + + Iterator> entryIterator() + { + return Iterators.filter(unfiltered.entrySet().iterator(), entryPredicate); + } + + Iterator> descendingEntryIterator() + { + return Iterators.filter(unfiltered.descendingMap().entrySet().iterator(), entryPredicate); + } + + public int size() + { + return filteredDelegate.size(); + } + + @Nullable + public V get(@Nullable Object key) + { + return filteredDelegate.get(key); + } + + public boolean containsKey(@Nullable Object key) + { + return filteredDelegate.containsKey(key); + } + + public V put(K key, V value) + { + return filteredDelegate.put(key, value); + } + + public V remove(@Nullable Object key) + { + return filteredDelegate.remove(key); + } + + public void putAll(Map m) + { + filteredDelegate.putAll(m); + } + + public void clear() + { + filteredDelegate.clear(); + } + + public Set> entrySet() + { + return filteredDelegate.entrySet(); + } + + public Map.Entry pollFirstEntry() + { + return (Map.Entry)Iterables.removeFirstMatching(unfiltered.entrySet(), entryPredicate); + } + + public Map.Entry pollLastEntry() + { + return (Map.Entry)Iterables.removeFirstMatching(unfiltered.descendingMap().entrySet(), entryPredicate); + } + + public NavigableMap descendingMap() + { + return Maps.filterEntries(unfiltered.descendingMap(), entryPredicate); + } + + + public NavigableMap subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) + { + return Maps.filterEntries(unfiltered.subMap(fromKey, fromInclusive, toKey, toInclusive), entryPredicate); + } + + + public NavigableMap headMap(K toKey, boolean inclusive) + { + return Maps.filterEntries(unfiltered.headMap(toKey, inclusive), entryPredicate); + } + + public NavigableMap tailMap(K fromKey, boolean inclusive) + { + return Maps.filterEntries(unfiltered.tailMap(fromKey, inclusive), entryPredicate); + } + } + + + + + + private static BiMap filterFiltered(FilteredEntryBiMap map, Predicate> entryPredicate) + { + Predicate> predicate = Predicates.and(map.predicate, entryPredicate); + return new FilteredEntryBiMap(map.unfiltered(), predicate); + } + + static final class FilteredEntryBiMap extends Maps.FilteredEntryMap implements BiMap + { + private final BiMap inverse; + + private static Predicate> inversePredicate(Predicate> forwardPredicate) + { + new Predicate() + { + public boolean apply(Map.Entry input) { + return val$forwardPredicate.apply(Maps.immutableEntry(input.getValue(), input.getKey())); + } + }; + } + + + FilteredEntryBiMap(BiMap delegate, Predicate> predicate) + { + super(predicate); + inverse = new FilteredEntryBiMap(delegate.inverse(), inversePredicate(predicate), this); + } + + + + private FilteredEntryBiMap(BiMap delegate, Predicate> predicate, BiMap inverse) + { + super(predicate); + this.inverse = inverse; + } + + BiMap unfiltered() { + return (BiMap)unfiltered; + } + + public V forcePut(@Nullable K key, @Nullable V value) + { + Preconditions.checkArgument(apply(key, value)); + return unfiltered().forcePut(key, value); + } + + public BiMap inverse() + { + return inverse; + } + + public Set values() + { + return inverse.keySet(); + } + } + + + + + + + + + + + + + @GwtIncompatible("NavigableMap") + public static NavigableMap unmodifiableNavigableMap(NavigableMap map) + { + Preconditions.checkNotNull(map); + if ((map instanceof UnmodifiableNavigableMap)) { + return map; + } + return new UnmodifiableNavigableMap(map); + } + + @Nullable + private static Map.Entry unmodifiableOrNull(@Nullable Map.Entry entry) { + return entry == null ? null : unmodifiableEntry(entry); + } + + @GwtIncompatible("NavigableMap") + static class UnmodifiableNavigableMap extends ForwardingSortedMap implements NavigableMap, Serializable { + private final NavigableMap delegate; + private transient UnmodifiableNavigableMap descendingMap; + + UnmodifiableNavigableMap(NavigableMap delegate) { + this.delegate = delegate; + } + + UnmodifiableNavigableMap(NavigableMap delegate, UnmodifiableNavigableMap descendingMap) + { + this.delegate = delegate; + this.descendingMap = descendingMap; + } + + protected SortedMap delegate() + { + return Collections.unmodifiableSortedMap(delegate); + } + + public Map.Entry lowerEntry(K key) + { + return Maps.unmodifiableOrNull(delegate.lowerEntry(key)); + } + + public K lowerKey(K key) + { + return delegate.lowerKey(key); + } + + public Map.Entry floorEntry(K key) + { + return Maps.unmodifiableOrNull(delegate.floorEntry(key)); + } + + public K floorKey(K key) + { + return delegate.floorKey(key); + } + + public Map.Entry ceilingEntry(K key) + { + return Maps.unmodifiableOrNull(delegate.ceilingEntry(key)); + } + + public K ceilingKey(K key) + { + return delegate.ceilingKey(key); + } + + public Map.Entry higherEntry(K key) + { + return Maps.unmodifiableOrNull(delegate.higherEntry(key)); + } + + public K higherKey(K key) + { + return delegate.higherKey(key); + } + + public Map.Entry firstEntry() + { + return Maps.unmodifiableOrNull(delegate.firstEntry()); + } + + public Map.Entry lastEntry() + { + return Maps.unmodifiableOrNull(delegate.lastEntry()); + } + + public final Map.Entry pollFirstEntry() + { + throw new UnsupportedOperationException(); + } + + public final Map.Entry pollLastEntry() + { + throw new UnsupportedOperationException(); + } + + + + public NavigableMap descendingMap() + { + UnmodifiableNavigableMap result = descendingMap; + return result == null ? (this.descendingMap = new UnmodifiableNavigableMap(delegate.descendingMap(), this)) : result; + } + + + + public Set keySet() + { + return navigableKeySet(); + } + + public NavigableSet navigableKeySet() + { + return Sets.unmodifiableNavigableSet(delegate.navigableKeySet()); + } + + public NavigableSet descendingKeySet() + { + return Sets.unmodifiableNavigableSet(delegate.descendingKeySet()); + } + + public SortedMap subMap(K fromKey, K toKey) + { + return subMap(fromKey, true, toKey, false); + } + + public SortedMap headMap(K toKey) + { + return headMap(toKey, false); + } + + public SortedMap tailMap(K fromKey) + { + return tailMap(fromKey, true); + } + + + + public NavigableMap subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) + { + return Maps.unmodifiableNavigableMap(delegate.subMap(fromKey, fromInclusive, toKey, toInclusive)); + } + + + + + + public NavigableMap headMap(K toKey, boolean inclusive) + { + return Maps.unmodifiableNavigableMap(delegate.headMap(toKey, inclusive)); + } + + public NavigableMap tailMap(K fromKey, boolean inclusive) + { + return Maps.unmodifiableNavigableMap(delegate.tailMap(fromKey, inclusive)); + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @GwtIncompatible("NavigableMap") + public static NavigableMap synchronizedNavigableMap(NavigableMap navigableMap) + { + return Synchronized.navigableMap(navigableMap); + } + + + @GwtCompatible + static abstract class ImprovedAbstractMap + extends AbstractMap + { + private transient Set> entrySet; + + private transient Set keySet; + + private transient Collection values; + + + ImprovedAbstractMap() {} + + + abstract Set> createEntrySet(); + + public Set> entrySet() + { + Set> result = entrySet; + return result == null ? (this.entrySet = createEntrySet()) : result; + } + + + public Set keySet() + { + Set result = keySet; + return result == null ? (this.keySet = createKeySet()) : result; + } + + Set createKeySet() { + return new Maps.KeySet(this); + } + + + public Collection values() + { + Collection result = values; + return result == null ? (this.values = createValues()) : result; + } + + Collection createValues() { + return new Maps.Values(this); + } + } + + + + + static V safeGet(Map map, @Nullable Object key) + { + Preconditions.checkNotNull(map); + try { + return map.get(key); + } catch (ClassCastException e) { + return null; + } catch (NullPointerException e) {} + return null; + } + + + + + + static boolean safeContainsKey(Map map, Object key) + { + Preconditions.checkNotNull(map); + try { + return map.containsKey(key); + } catch (ClassCastException e) { + return false; + } catch (NullPointerException e) {} + return false; + } + + + + + + static V safeRemove(Map map, Object key) + { + Preconditions.checkNotNull(map); + try { + return map.remove(key); + } catch (ClassCastException e) { + return null; + } catch (NullPointerException e) {} + return null; + } + + + + + static boolean containsKeyImpl(Map map, @Nullable Object key) + { + return Iterators.contains(keyIterator(map.entrySet().iterator()), key); + } + + + + static boolean containsValueImpl(Map map, @Nullable Object value) + { + return Iterators.contains(valueIterator(map.entrySet().iterator()), value); + } + + + + + + + + + + + + + + static boolean containsEntryImpl(Collection> c, Object o) + { + if (!(o instanceof Map.Entry)) { + return false; + } + return c.contains(unmodifiableEntry((Map.Entry)o)); + } + + + + + + + + + + + + + + static boolean removeEntryImpl(Collection> c, Object o) + { + if (!(o instanceof Map.Entry)) { + return false; + } + return c.remove(unmodifiableEntry((Map.Entry)o)); + } + + + + static boolean equalsImpl(Map map, Object object) + { + if (map == object) + return true; + if ((object instanceof Map)) { + Map o = (Map)object; + return map.entrySet().equals(o.entrySet()); + } + return false; + } + + static final Joiner.MapJoiner STANDARD_JOINER = Collections2.STANDARD_JOINER.withKeyValueSeparator("="); + + + + + static String toStringImpl(Map map) + { + StringBuilder sb = Collections2.newStringBuilderForCollection(map.size()).append('{'); + + STANDARD_JOINER.appendTo(sb, map); + return '}'; + } + + + + + static void putAllImpl(Map self, Map map) + { + for (Map.Entry entry : map.entrySet()) { + self.put(entry.getKey(), entry.getValue()); + } + } + + static class KeySet extends Sets.ImprovedAbstractSet { + final Map map; + + KeySet(Map map) { + this.map = ((Map)Preconditions.checkNotNull(map)); + } + + Map map() { + return map; + } + + public Iterator iterator() { + return Maps.keyIterator(map().entrySet().iterator()); + } + + public int size() { + return map().size(); + } + + public boolean isEmpty() { + return map().isEmpty(); + } + + public boolean contains(Object o) { + return map().containsKey(o); + } + + public boolean remove(Object o) { + if (contains(o)) { + map().remove(o); + return true; + } + return false; + } + + public void clear() { + map().clear(); + } + } + + @Nullable + static K keyOrNull(@Nullable Map.Entry entry) { + return entry == null ? null : entry.getKey(); + } + + @Nullable + static V valueOrNull(@Nullable Map.Entry entry) { + return entry == null ? null : entry.getValue(); + } + + static class SortedKeySet extends Maps.KeySet implements SortedSet { + SortedKeySet(SortedMap map) { + super(); + } + + SortedMap map() + { + return (SortedMap)super.map(); + } + + public Comparator comparator() + { + return map().comparator(); + } + + public SortedSet subSet(K fromElement, K toElement) + { + return new SortedKeySet(map().subMap(fromElement, toElement)); + } + + public SortedSet headSet(K toElement) + { + return new SortedKeySet(map().headMap(toElement)); + } + + public SortedSet tailSet(K fromElement) + { + return new SortedKeySet(map().tailMap(fromElement)); + } + + public K first() + { + return map().firstKey(); + } + + public K last() + { + return map().lastKey(); + } + } + + @GwtIncompatible("NavigableMap") + static class NavigableKeySet extends Maps.SortedKeySet implements NavigableSet { + NavigableKeySet(NavigableMap map) { + super(); + } + + NavigableMap map() + { + return (NavigableMap)map; + } + + public K lower(K e) + { + return map().lowerKey(e); + } + + public K floor(K e) + { + return map().floorKey(e); + } + + public K ceiling(K e) + { + return map().ceilingKey(e); + } + + public K higher(K e) + { + return map().higherKey(e); + } + + public K pollFirst() + { + return Maps.keyOrNull(map().pollFirstEntry()); + } + + public K pollLast() + { + return Maps.keyOrNull(map().pollLastEntry()); + } + + public NavigableSet descendingSet() + { + return map().descendingKeySet(); + } + + public Iterator descendingIterator() + { + return descendingSet().iterator(); + } + + + + + + public NavigableSet subSet(K fromElement, boolean fromInclusive, K toElement, boolean toInclusive) + { + return map().subMap(fromElement, fromInclusive, toElement, toInclusive).navigableKeySet(); + } + + public NavigableSet headSet(K toElement, boolean inclusive) + { + return map().headMap(toElement, inclusive).navigableKeySet(); + } + + public NavigableSet tailSet(K fromElement, boolean inclusive) + { + return map().tailMap(fromElement, inclusive).navigableKeySet(); + } + + public SortedSet subSet(K fromElement, K toElement) + { + return subSet(fromElement, true, toElement, false); + } + + public SortedSet headSet(K toElement) + { + return headSet(toElement, false); + } + + public SortedSet tailSet(K fromElement) + { + return tailSet(fromElement, true); + } + } + + static class Values extends AbstractCollection { + final Map map; + + Values(Map map) { + this.map = ((Map)Preconditions.checkNotNull(map)); + } + + final Map map() { + return map; + } + + public Iterator iterator() { + return Maps.valueIterator(map().entrySet().iterator()); + } + + public boolean remove(Object o) { + try { + return super.remove(o); + } catch (UnsupportedOperationException e) { + for (Map.Entry entry : map().entrySet()) + if (Objects.equal(o, entry.getValue())) { + map().remove(entry.getKey()); + return true; + } + } + return false; + } + + public boolean removeAll(Collection c) + { + try { + return super.removeAll((Collection)Preconditions.checkNotNull(c)); + } catch (UnsupportedOperationException e) { + Set toRemove = Sets.newHashSet(); + for (Map.Entry entry : map().entrySet()) { + if (c.contains(entry.getValue())) { + toRemove.add(entry.getKey()); + } + } + return map().keySet().removeAll(toRemove); + } + } + + public boolean retainAll(Collection c) { + try { + return super.retainAll((Collection)Preconditions.checkNotNull(c)); + } catch (UnsupportedOperationException e) { + Set toRetain = Sets.newHashSet(); + for (Map.Entry entry : map().entrySet()) { + if (c.contains(entry.getValue())) { + toRetain.add(entry.getKey()); + } + } + return map().keySet().retainAll(toRetain); + } + } + + public int size() { + return map().size(); + } + + public boolean isEmpty() { + return map().isEmpty(); + } + + public boolean contains(@Nullable Object o) { + return map().containsValue(o); + } + + public void clear() { + map().clear(); + } + } + + static abstract class EntrySet extends Sets.ImprovedAbstractSet> { + EntrySet() {} + + abstract Map map(); + + public int size() { return map().size(); } + + public void clear() + { + map().clear(); + } + + public boolean contains(Object o) { + if ((o instanceof Map.Entry)) { + Map.Entry entry = (Map.Entry)o; + Object key = entry.getKey(); + V value = Maps.safeGet(map(), key); + return (Objects.equal(value, entry.getValue())) && ((value != null) || (map().containsKey(key))); + } + + return false; + } + + public boolean isEmpty() { + return map().isEmpty(); + } + + public boolean remove(Object o) { + if (contains(o)) { + Map.Entry entry = (Map.Entry)o; + return map().keySet().remove(entry.getKey()); + } + return false; + } + + public boolean removeAll(Collection c) { + try { + return super.removeAll((Collection)Preconditions.checkNotNull(c)); + } + catch (UnsupportedOperationException e) {} + return Sets.removeAllImpl(this, c.iterator()); + } + + public boolean retainAll(Collection c) + { + try { + return super.retainAll((Collection)Preconditions.checkNotNull(c)); + } + catch (UnsupportedOperationException e) { + Set keys = Sets.newHashSetWithExpectedSize(c.size()); + for (Object o : c) { + if (contains(o)) { + Map.Entry entry = (Map.Entry)o; + keys.add(entry.getKey()); + } + } + return map().keySet().retainAll(keys); + } + } } + + @GwtIncompatible("NavigableMap") + static abstract class DescendingMap extends ForwardingMap implements NavigableMap { private transient Comparator comparator; + private transient Set> entrySet; + private transient NavigableSet navigableKeySet; + + DescendingMap() {} + + abstract NavigableMap forward(); + + protected final Map delegate() { return forward(); } + + + + + + public Comparator comparator() + { + Comparator result = comparator; + if (result == null) { + Comparator forwardCmp = forward().comparator(); + if (forwardCmp == null) { + forwardCmp = Ordering.natural(); + } + result = this.comparator = reverse(forwardCmp); + } + return result; + } + + private static Ordering reverse(Comparator forward) + { + return Ordering.from(forward).reverse(); + } + + public K firstKey() + { + return forward().lastKey(); + } + + public K lastKey() + { + return forward().firstKey(); + } + + public Map.Entry lowerEntry(K key) + { + return forward().higherEntry(key); + } + + public K lowerKey(K key) + { + return forward().higherKey(key); + } + + public Map.Entry floorEntry(K key) + { + return forward().ceilingEntry(key); + } + + public K floorKey(K key) + { + return forward().ceilingKey(key); + } + + public Map.Entry ceilingEntry(K key) + { + return forward().floorEntry(key); + } + + public K ceilingKey(K key) + { + return forward().floorKey(key); + } + + public Map.Entry higherEntry(K key) + { + return forward().lowerEntry(key); + } + + public K higherKey(K key) + { + return forward().lowerKey(key); + } + + public Map.Entry firstEntry() + { + return forward().lastEntry(); + } + + public Map.Entry lastEntry() + { + return forward().firstEntry(); + } + + public Map.Entry pollFirstEntry() + { + return forward().pollLastEntry(); + } + + public Map.Entry pollLastEntry() + { + return forward().pollFirstEntry(); + } + + public NavigableMap descendingMap() + { + return forward(); + } + + + + public Set> entrySet() + { + Set> result = entrySet; + return result == null ? (this.entrySet = createEntrySet()) : result; + } + + abstract Iterator> entryIterator(); + + Set> createEntrySet() { + new Maps.EntrySet() + { + Map map() { + return Maps.DescendingMap.this; + } + + public Iterator> iterator() + { + return entryIterator(); + } + }; + } + + public Set keySet() + { + return navigableKeySet(); + } + + + + public NavigableSet navigableKeySet() + { + NavigableSet result = navigableKeySet; + return result == null ? (this.navigableKeySet = new Maps.NavigableKeySet(this)) : result; + } + + public NavigableSet descendingKeySet() + { + return forward().navigableKeySet(); + } + + + + public NavigableMap subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) + { + return forward().subMap(toKey, toInclusive, fromKey, fromInclusive).descendingMap(); + } + + public NavigableMap headMap(K toKey, boolean inclusive) + { + return forward().tailMap(toKey, inclusive).descendingMap(); + } + + public NavigableMap tailMap(K fromKey, boolean inclusive) + { + return forward().headMap(fromKey, inclusive).descendingMap(); + } + + public SortedMap subMap(K fromKey, K toKey) + { + return subMap(fromKey, true, toKey, false); + } + + public SortedMap headMap(K toKey) + { + return headMap(toKey, false); + } + + public SortedMap tailMap(K fromKey) + { + return tailMap(fromKey, true); + } + + public Collection values() + { + return new Maps.Values(this); + } + + public String toString() + { + return standardToString(); + } + } +} diff --git a/src/minecraft/com/google/common/collect/MinMaxPriorityQueue.java b/src/minecraft/com/google/common/collect/MinMaxPriorityQueue.java new file mode 100644 index 0000000..2f06adc --- /dev/null +++ b/src/minecraft/com/google/common/collect/MinMaxPriorityQueue.java @@ -0,0 +1,939 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.math.IntMath; +import java.util.AbstractQueue; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.ConcurrentModificationException; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Queue; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class MinMaxPriorityQueue + extends AbstractQueue +{ + private final MinMaxPriorityQueue.Heap minHeap; + private final MinMaxPriorityQueue.Heap maxHeap; + @VisibleForTesting + final int maximumSize; + private Object[] queue; + private int size; + private int modCount; + private static final int EVEN_POWERS_OF_TWO = 1431655765; + private static final int ODD_POWERS_OF_TWO = -1431655766; + private static final int DEFAULT_CAPACITY = 11; + + public static > MinMaxPriorityQueue create() + { + return new Builder(Ordering.natural(), null).create(); + } + + + + + + public static > MinMaxPriorityQueue create(Iterable initialContents) + { + return new Builder(Ordering.natural(), null).create(initialContents); + } + + + + + + public static Builder orderedBy(Comparator comparator) + { + return new Builder(comparator, null); + } + + + + + + public static Builder expectedSize(int expectedSize) + { + return new Builder(Ordering.natural(), null).expectedSize(expectedSize); + } + + + + + + + + + public static Builder maximumSize(int maximumSize) + { + return new Builder(Ordering.natural(), null).maximumSize(maximumSize); + } + + + + + + + + @Beta + public static final class Builder + { + private static final int UNSET_EXPECTED_SIZE = -1; + + + + + + + private final Comparator comparator; + + + + + + + private int expectedSize = -1; + private int maximumSize = Integer.MAX_VALUE; + + private Builder(Comparator comparator) { + this.comparator = ((Comparator)Preconditions.checkNotNull(comparator)); + } + + + + + public Builder expectedSize(int expectedSize) + { + Preconditions.checkArgument(expectedSize >= 0); + this.expectedSize = expectedSize; + return this; + } + + + + + + + public Builder maximumSize(int maximumSize) + { + Preconditions.checkArgument(maximumSize > 0); + this.maximumSize = maximumSize; + return this; + } + + + + + public MinMaxPriorityQueue create() + { + return create(Collections.emptySet()); + } + + + + + + public MinMaxPriorityQueue create(Iterable initialContents) + { + MinMaxPriorityQueue queue = new MinMaxPriorityQueue(this, MinMaxPriorityQueue.initialQueueSize(expectedSize, maximumSize, initialContents), null); + + for (T element : initialContents) { + queue.offer(element); + } + return queue; + } + + private Ordering ordering() + { + return Ordering.from(comparator); + } + } + + + + + + + + private MinMaxPriorityQueue(Builder builder, int queueSize) + { + Ordering ordering = builder.ordering(); + minHeap = new Heap(ordering); + maxHeap = new Heap(ordering.reverse()); + minHeap.otherHeap = maxHeap; + maxHeap.otherHeap = minHeap; + + maximumSize = maximumSize; + + queue = new Object[queueSize]; + } + + public int size() { + return size; + } + + + + + + + + + public boolean add(E element) + { + offer(element); + return true; + } + + public boolean addAll(Collection newElements) { + boolean modified = false; + for (E element : newElements) { + offer(element); + modified = true; + } + return modified; + } + + + + + + + public boolean offer(E element) + { + Preconditions.checkNotNull(element); + modCount += 1; + int insertIndex = size++; + + growIfNeeded(); + + + + heapForIndex(insertIndex).bubbleUp(insertIndex, element); + return (size <= maximumSize) || (pollLast() != element); + } + + public E poll() { + return isEmpty() ? null : removeAndGet(0); + } + + E elementData(int index) + { + return queue[index]; + } + + public E peek() { + return isEmpty() ? null : elementData(0); + } + + + + private int getMaxElementIndex() + { + switch (size) { + case 1: + return 0; + case 2: + return 1; + } + + + return maxHeap.compareElements(1, 2) <= 0 ? 1 : 2; + } + + + + + + public E pollFirst() + { + return poll(); + } + + + + + + public E removeFirst() + { + return remove(); + } + + + + + public E peekFirst() + { + return peek(); + } + + + + + public E pollLast() + { + return isEmpty() ? null : removeAndGet(getMaxElementIndex()); + } + + + + + + public E removeLast() + { + if (isEmpty()) { + throw new NoSuchElementException(); + } + return removeAndGet(getMaxElementIndex()); + } + + + + + public E peekLast() + { + return isEmpty() ? null : elementData(getMaxElementIndex()); + } + + + + + + + + + + + + + + + @VisibleForTesting + MoveDesc removeAt(int index) + { + Preconditions.checkPositionIndex(index, size); + modCount += 1; + size -= 1; + if (size == index) { + queue[size] = null; + return null; + } + E actualLastElement = elementData(size); + int lastElementAt = heapForIndex(size).getCorrectLastElement(actualLastElement); + + E toTrickle = elementData(size); + queue[size] = null; + MoveDesc changes = fillHole(index, toTrickle); + if (lastElementAt < index) + { + if (changes == null) + { + return new MoveDesc(actualLastElement, toTrickle); + } + + + return new MoveDesc(actualLastElement, replaced); + } + + + return changes; + } + + private MoveDesc fillHole(int index, E toTrickle) { + MinMaxPriorityQueue.Heap heap = heapForIndex(index); + + + + + + + + int vacated = heap.fillHoleAt(index); + + int bubbledTo = heap.bubbleUpAlternatingLevels(vacated, toTrickle); + if (bubbledTo == vacated) + { + + + return heap.tryCrossOverAndBubbleUp(index, vacated, toTrickle); + } + return bubbledTo < index ? new MoveDesc(toTrickle, elementData(index)) : null; + } + + + static class MoveDesc + { + final E toTrickle; + + final E replaced; + + MoveDesc(E toTrickle, E replaced) + { + this.toTrickle = toTrickle; + this.replaced = replaced; + } + } + + + + private E removeAndGet(int index) + { + E value = elementData(index); + removeAt(index); + return value; + } + + private MinMaxPriorityQueue.Heap heapForIndex(int i) { + return isEvenLevel(i) ? minHeap : maxHeap; + } + + + @VisibleForTesting + static boolean isEvenLevel(int index) + { + int oneBased = index + 1; + Preconditions.checkState(oneBased > 0, "negative index"); + return (oneBased & 0x55555555) > (oneBased & 0xAAAAAAAA); + } + + + + + + @VisibleForTesting + boolean isIntact() + { + for (int i = 1; i < size; i++) { + if (!heapForIndex(i).verifyIndex(i)) { + return false; + } + } + return true; + } + + + + private class Heap + { + final Ordering ordering; + + MinMaxPriorityQueue.Heap otherHeap; + + + Heap() + { + this.ordering = ordering; + } + + int compareElements(int a, int b) { + return ordering.compare(elementData(a), elementData(b)); + } + + + + + + + MinMaxPriorityQueue.MoveDesc tryCrossOverAndBubbleUp(int removeIndex, int vacated, E toTrickle) + { + int crossOver = crossOver(vacated, toTrickle); + if (crossOver == vacated) { + return null; + } + + + E parent; + + E parent; + + if (crossOver < removeIndex) + { + + parent = elementData(removeIndex); + } else { + parent = elementData(getParentIndex(removeIndex)); + } + + if (otherHeap.bubbleUpAlternatingLevels(crossOver, toTrickle) < removeIndex) + { + return new MinMaxPriorityQueue.MoveDesc(toTrickle, parent); + } + return null; + } + + + + + void bubbleUp(int index, E x) + { + int crossOver = crossOverUp(index, x); + MinMaxPriorityQueue.Heap heap; + MinMaxPriorityQueue.Heap heap; + if (crossOver == index) { + heap = this; + } else { + index = crossOver; + heap = otherHeap; + } + heap.bubbleUpAlternatingLevels(index, x); + } + + + + + int bubbleUpAlternatingLevels(int index, E x) + { + while (index > 2) { + int grandParentIndex = getGrandparentIndex(index); + E e = elementData(grandParentIndex); + if (ordering.compare(e, x) <= 0) { + break; + } + queue[index] = e; + index = grandParentIndex; + } + queue[index] = x; + return index; + } + + + + + + int findMin(int index, int len) + { + if (index >= size) { + return -1; + } + Preconditions.checkState(index > 0); + int limit = Math.min(index, size - len) + len; + int minIndex = index; + for (int i = index + 1; i < limit; i++) { + if (compareElements(i, minIndex) < 0) { + minIndex = i; + } + } + return minIndex; + } + + + + int findMinChild(int index) + { + return findMin(getLeftChildIndex(index), 2); + } + + + + int findMinGrandChild(int index) + { + int leftChildIndex = getLeftChildIndex(index); + if (leftChildIndex < 0) { + return -1; + } + return findMin(getLeftChildIndex(leftChildIndex), 4); + } + + + + + + int crossOverUp(int index, E x) + { + if (index == 0) { + queue[0] = x; + return 0; + } + int parentIndex = getParentIndex(index); + E parentElement = elementData(parentIndex); + if (parentIndex != 0) + { + + + + int grandparentIndex = getParentIndex(parentIndex); + int uncleIndex = getRightChildIndex(grandparentIndex); + if ((uncleIndex != parentIndex) && (getLeftChildIndex(uncleIndex) >= size)) + { + E uncleElement = elementData(uncleIndex); + if (ordering.compare(uncleElement, parentElement) < 0) { + parentIndex = uncleIndex; + parentElement = uncleElement; + } + } + } + if (ordering.compare(parentElement, x) < 0) { + queue[index] = parentElement; + queue[parentIndex] = x; + return parentIndex; + } + queue[index] = x; + return index; + } + + + + + + + + + + int getCorrectLastElement(E actualLastElement) + { + int parentIndex = getParentIndex(size); + if (parentIndex != 0) { + int grandparentIndex = getParentIndex(parentIndex); + int uncleIndex = getRightChildIndex(grandparentIndex); + if ((uncleIndex != parentIndex) && (getLeftChildIndex(uncleIndex) >= size)) + { + E uncleElement = elementData(uncleIndex); + if (ordering.compare(uncleElement, actualLastElement) < 0) { + queue[uncleIndex] = actualLastElement; + queue[size] = uncleElement; + return uncleIndex; + } + } + } + return size; + } + + + + + + + int crossOver(int index, E x) + { + int minChildIndex = findMinChild(index); + + + if ((minChildIndex > 0) && (ordering.compare(elementData(minChildIndex), x) < 0)) + { + queue[index] = elementData(minChildIndex); + queue[minChildIndex] = x; + return minChildIndex; + } + return crossOverUp(index, x); + } + + + + + + int fillHoleAt(int index) + { + int minGrandchildIndex; + + + + while ((minGrandchildIndex = findMinGrandChild(index)) > 0) { + queue[index] = elementData(minGrandchildIndex); + index = minGrandchildIndex; + } + return index; + } + + private boolean verifyIndex(int i) { + if ((getLeftChildIndex(i) < size) && (compareElements(i, getLeftChildIndex(i)) > 0)) + { + return false; + } + if ((getRightChildIndex(i) < size) && (compareElements(i, getRightChildIndex(i)) > 0)) + { + return false; + } + if ((i > 0) && (compareElements(i, getParentIndex(i)) > 0)) { + return false; + } + if ((i > 2) && (compareElements(getGrandparentIndex(i), i) > 0)) { + return false; + } + return true; + } + + + private int getLeftChildIndex(int i) + { + return i * 2 + 1; + } + + private int getRightChildIndex(int i) { + return i * 2 + 2; + } + + private int getParentIndex(int i) { + return (i - 1) / 2; + } + + private int getGrandparentIndex(int i) { + return getParentIndex(getParentIndex(i)); + } + } + + + + + + private class QueueIterator + implements Iterator + { + private int cursor = -1; + private int expectedModCount = modCount; + private Queue forgetMeNot; + private List skipMe; + + private QueueIterator() {} + + public boolean hasNext() { + checkModCount(); + return (nextNotInSkipMe(cursor + 1) < size()) || ((forgetMeNot != null) && (!forgetMeNot.isEmpty())); + } + + public E next() + { + checkModCount(); + int tempCursor = nextNotInSkipMe(cursor + 1); + if (tempCursor < size()) { + cursor = tempCursor; + canRemove = true; + return elementData(cursor); } + if (forgetMeNot != null) { + cursor = size(); + lastFromForgetMeNot = forgetMeNot.poll(); + if (lastFromForgetMeNot != null) { + canRemove = true; + return lastFromForgetMeNot; + } + } + throw new NoSuchElementException("iterator moved past last element in queue."); + } + + public void remove() + { + CollectPreconditions.checkRemove(canRemove); + checkModCount(); + canRemove = false; + expectedModCount += 1; + if (cursor < size()) { + MinMaxPriorityQueue.MoveDesc moved = removeAt(cursor); + if (moved != null) { + if (forgetMeNot == null) { + forgetMeNot = new ArrayDeque(); + skipMe = new ArrayList(3); + } + forgetMeNot.add(toTrickle); + skipMe.add(replaced); + } + cursor -= 1; + } else { + Preconditions.checkState(removeExact(lastFromForgetMeNot)); + lastFromForgetMeNot = null; + } + } + + private boolean containsExact(Iterable elements, E target) + { + for (E element : elements) { + if (element == target) { + return true; + } + } + return false; + } + + boolean removeExact(Object target) + { + for (int i = 0; i < size; i++) { + if (queue[i] == target) { + removeAt(i); + return true; + } + } + return false; + } + + void checkModCount() { + if (modCount != expectedModCount) { + throw new ConcurrentModificationException(); + } + } + + + + + private int nextNotInSkipMe(int c) + { + if (skipMe != null) { + while ((c < size()) && (containsExact(skipMe, elementData(c)))) { + c++; + } + } + return c; + } + + + + + + + + private E lastFromForgetMeNot; + + + + + + + private boolean canRemove; + } + + + + + + + + public Iterator iterator() + { + return new QueueIterator(null); + } + + public void clear() { + for (int i = 0; i < size; i++) { + queue[i] = null; + } + size = 0; + } + + public Object[] toArray() { + Object[] copyTo = new Object[size]; + System.arraycopy(queue, 0, copyTo, 0, size); + return copyTo; + } + + + + + + public Comparator comparator() + { + return minHeap.ordering; + } + + @VisibleForTesting + int capacity() { return queue.length; } + + + + + + + @VisibleForTesting + static int initialQueueSize(int configuredExpectedSize, int maximumSize, Iterable initialContents) + { + int result = configuredExpectedSize == -1 ? 11 : configuredExpectedSize; + + + + + if ((initialContents instanceof Collection)) { + int initialSize = ((Collection)initialContents).size(); + result = Math.max(result, initialSize); + } + + + return capAtMaximumSize(result, maximumSize); + } + + private void growIfNeeded() { + if (size > queue.length) { + int newCapacity = calculateNewCapacity(); + Object[] newQueue = new Object[newCapacity]; + System.arraycopy(queue, 0, newQueue, 0, queue.length); + queue = newQueue; + } + } + + private int calculateNewCapacity() + { + int oldCapacity = queue.length; + int newCapacity = oldCapacity < 64 ? (oldCapacity + 1) * 2 : IntMath.checkedMultiply(oldCapacity / 2, 3); + + + return capAtMaximumSize(newCapacity, maximumSize); + } + + private static int capAtMaximumSize(int queueSize, int maximumSize) + { + return Math.min(queueSize - 1, maximumSize) + 1; + } +} diff --git a/src/minecraft/com/google/common/collect/Multimap.java b/src/minecraft/com/google/common/collect/Multimap.java new file mode 100644 index 0000000..08da75b --- /dev/null +++ b/src/minecraft/com/google/common/collect/Multimap.java @@ -0,0 +1,52 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Collection; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract interface Multimap +{ + public abstract int size(); + + public abstract boolean isEmpty(); + + public abstract boolean containsKey(@Nullable Object paramObject); + + public abstract boolean containsValue(@Nullable Object paramObject); + + public abstract boolean containsEntry(@Nullable Object paramObject1, @Nullable Object paramObject2); + + public abstract boolean put(@Nullable K paramK, @Nullable V paramV); + + public abstract boolean remove(@Nullable Object paramObject1, @Nullable Object paramObject2); + + public abstract boolean putAll(@Nullable K paramK, Iterable paramIterable); + + public abstract boolean putAll(Multimap paramMultimap); + + public abstract Collection replaceValues(@Nullable K paramK, Iterable paramIterable); + + public abstract Collection removeAll(@Nullable Object paramObject); + + public abstract void clear(); + + public abstract Collection get(@Nullable K paramK); + + public abstract Set keySet(); + + public abstract Multiset keys(); + + public abstract Collection values(); + + public abstract Collection> entries(); + + public abstract Map> asMap(); + + public abstract boolean equals(@Nullable Object paramObject); + + public abstract int hashCode(); +} diff --git a/src/minecraft/com/google/common/collect/MultimapBuilder.java b/src/minecraft/com/google/common/collect/MultimapBuilder.java new file mode 100644 index 0000000..5e8247f --- /dev/null +++ b/src/minecraft/com/google/common/collect/MultimapBuilder.java @@ -0,0 +1,485 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeMap; +import java.util.TreeSet; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +public abstract class MultimapBuilder +{ + private static final int DEFAULT_EXPECTED_KEYS = 8; + + private MultimapBuilder() {} + + public static MultimapBuilderWithKeys hashKeys() + { + return hashKeys(8); + } + + + + + + + public static MultimapBuilderWithKeys hashKeys(int expectedKeys) + { + CollectPreconditions.checkNonnegative(expectedKeys, "expectedKeys"); + new MultimapBuilderWithKeys() + { + Map> createMap() { + return new HashMap(val$expectedKeys); + } + }; + } + + + + + + + + + public static MultimapBuilderWithKeys linkedHashKeys() + { + return linkedHashKeys(8); + } + + + + + + + + + + public static MultimapBuilderWithKeys linkedHashKeys(int expectedKeys) + { + CollectPreconditions.checkNonnegative(expectedKeys, "expectedKeys"); + new MultimapBuilderWithKeys() + { + Map> createMap() { + return new LinkedHashMap(val$expectedKeys); + } + }; + } + + + + + + + + + + + + public static MultimapBuilderWithKeys treeKeys() + { + return treeKeys(Ordering.natural()); + } + + + + + + + + + + + + + + public static MultimapBuilderWithKeys treeKeys(Comparator comparator) + { + Preconditions.checkNotNull(comparator); + new MultimapBuilderWithKeys() + { + Map> createMap() { + return new TreeMap(val$comparator); + } + }; + } + + + + + public static > MultimapBuilderWithKeys enumKeys(Class keyClass) + { + Preconditions.checkNotNull(keyClass); + new MultimapBuilderWithKeys() + { + + + + Map> createMap() { + return new EnumMap(val$keyClass); } + }; + } + + public abstract Multimap build(); + + private static final class ArrayListSupplier implements Supplier>, Serializable { + private final int expectedValuesPerKey; + + ArrayListSupplier(int expectedValuesPerKey) { this.expectedValuesPerKey = CollectPreconditions.checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey"); } + + + public List get() + { + return new ArrayList(expectedValuesPerKey); + } + } + + private static enum LinkedListSupplier implements Supplier> { + INSTANCE; + + private LinkedListSupplier() {} + + public static Supplier> instance() { + Supplier> result = INSTANCE; + return result; + } + + public List get() + { + return new LinkedList(); + } + } + + private static final class HashSetSupplier implements Supplier>, Serializable { + private final int expectedValuesPerKey; + + HashSetSupplier(int expectedValuesPerKey) { + this.expectedValuesPerKey = CollectPreconditions.checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey"); + } + + public Set get() + { + return new HashSet(expectedValuesPerKey); + } + } + + private static final class LinkedHashSetSupplier implements Supplier>, Serializable { + private final int expectedValuesPerKey; + + LinkedHashSetSupplier(int expectedValuesPerKey) { + this.expectedValuesPerKey = CollectPreconditions.checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey"); + } + + public Set get() + { + return new LinkedHashSet(expectedValuesPerKey); + } + } + + private static final class TreeSetSupplier implements Supplier>, Serializable { + private final Comparator comparator; + + TreeSetSupplier(Comparator comparator) { + this.comparator = ((Comparator)Preconditions.checkNotNull(comparator)); + } + + public SortedSet get() + { + return new TreeSet(comparator); + } + } + + private static final class EnumSetSupplier> implements Supplier>, Serializable + { + private final Class clazz; + + EnumSetSupplier(Class clazz) { + this.clazz = ((Class)Preconditions.checkNotNull(clazz)); + } + + public Set get() + { + return EnumSet.noneOf(clazz); + } + } + + + + public static abstract class MultimapBuilderWithKeys + { + private static final int DEFAULT_EXPECTED_VALUES_PER_KEY = 2; + + + + MultimapBuilderWithKeys() {} + + + + abstract Map> createMap(); + + + + public MultimapBuilder.ListMultimapBuilder arrayListValues() + { + return arrayListValues(2); + } + + + + + + + public MultimapBuilder.ListMultimapBuilder arrayListValues(final int expectedValuesPerKey) + { + CollectPreconditions.checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey"); + new MultimapBuilder.ListMultimapBuilder() + { + public ListMultimap build() { + return Multimaps.newListMultimap(createMap(), new MultimapBuilder.ArrayListSupplier(expectedValuesPerKey)); + } + }; + } + + + + + + public MultimapBuilder.ListMultimapBuilder linkedListValues() + { + new MultimapBuilder.ListMultimapBuilder() + { + public ListMultimap build() { + return Multimaps.newListMultimap(createMap(), MultimapBuilder.LinkedListSupplier.instance()); + } + }; + } + + + + + + public MultimapBuilder.SetMultimapBuilder hashSetValues() + { + return hashSetValues(2); + } + + + + + + + public MultimapBuilder.SetMultimapBuilder hashSetValues(final int expectedValuesPerKey) + { + CollectPreconditions.checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey"); + new MultimapBuilder.SetMultimapBuilder() + { + public SetMultimap build() { + return Multimaps.newSetMultimap(createMap(), new MultimapBuilder.HashSetSupplier(expectedValuesPerKey)); + } + }; + } + + + + + + public MultimapBuilder.SetMultimapBuilder linkedHashSetValues() + { + return linkedHashSetValues(2); + } + + + + + + + public MultimapBuilder.SetMultimapBuilder linkedHashSetValues(final int expectedValuesPerKey) + { + CollectPreconditions.checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey"); + new MultimapBuilder.SetMultimapBuilder() + { + public SetMultimap build() { + return Multimaps.newSetMultimap(createMap(), new MultimapBuilder.LinkedHashSetSupplier(expectedValuesPerKey)); + } + }; + } + + + + + + + public MultimapBuilder.SortedSetMultimapBuilder treeSetValues() + { + return treeSetValues(Ordering.natural()); + } + + + + + + + public MultimapBuilder.SortedSetMultimapBuilder treeSetValues(final Comparator comparator) + { + Preconditions.checkNotNull(comparator, "comparator"); + new MultimapBuilder.SortedSetMultimapBuilder() + { + public SortedSetMultimap build() { + return Multimaps.newSortedSetMultimap(createMap(), new MultimapBuilder.TreeSetSupplier(comparator)); + } + }; + } + + + + + + + public > MultimapBuilder.SetMultimapBuilder enumSetValues(final Class valueClass) + { + Preconditions.checkNotNull(valueClass, "valueClass"); + new MultimapBuilder.SetMultimapBuilder() + { + + public SetMultimap build() + { + + Supplier> factory = new MultimapBuilder.EnumSetSupplier(valueClass); + return Multimaps.newSetMultimap(createMap(), factory); + } + }; + } + } + + + + + + + + + + + + + public Multimap build(Multimap multimap) + { + Multimap result = build(); + result.putAll(multimap); + return result; + } + + public static abstract class ListMultimapBuilder extends MultimapBuilder + { + ListMultimapBuilder() + { + super(); + } + + + public abstract ListMultimap build(); + + public ListMultimap build(Multimap multimap) + { + return (ListMultimap)super.build(multimap); + } + } + + public static abstract class SetMultimapBuilder extends MultimapBuilder + { + SetMultimapBuilder() + { + super(); + } + + + public abstract SetMultimap build(); + + public SetMultimap build(Multimap multimap) + { + return (SetMultimap)super.build(multimap); + } + } + + + public static abstract class SortedSetMultimapBuilder + extends MultimapBuilder.SetMultimapBuilder + { + SortedSetMultimapBuilder() {} + + + public abstract SortedSetMultimap build(); + + + public SortedSetMultimap build(Multimap multimap) + { + return (SortedSetMultimap)super.build(multimap); + } + } +} diff --git a/src/minecraft/com/google/common/collect/Multimaps.java b/src/minecraft/com/google/common/collect/Multimaps.java new file mode 100644 index 0000000..53f01c9 --- /dev/null +++ b/src/minecraft/com/google/common/collect/Multimaps.java @@ -0,0 +1,2057 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.base.Supplier; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.AbstractCollection; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.SortedSet; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public final class Multimaps +{ + private Multimaps() {} + + public static Multimap newMultimap(Map> map, Supplier> factory) { return new CustomMultimap(map, factory); } + + private static class CustomMultimap extends AbstractMapBasedMultimap { + transient Supplier> factory; + @GwtIncompatible("java serialization not supported") + private static final long serialVersionUID = 0L; + + CustomMultimap(Map> map, Supplier> factory) { + super(); + this.factory = ((Supplier)Preconditions.checkNotNull(factory)); + } + + protected Collection createCollection() { + return (Collection)factory.get(); + } + + + + @GwtIncompatible("java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) + throws IOException + { + stream.defaultWriteObject(); + stream.writeObject(factory); + stream.writeObject(backingMap()); + } + + @GwtIncompatible("java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException + { + stream.defaultReadObject(); + factory = ((Supplier)stream.readObject()); + Map> map = (Map)stream.readObject(); + setMap(map); + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static ListMultimap newListMultimap(Map> map, Supplier> factory) + { + return new CustomListMultimap(map, factory); + } + + private static class CustomListMultimap extends AbstractListMultimap { + transient Supplier> factory; + @GwtIncompatible("java serialization not supported") + private static final long serialVersionUID = 0L; + + CustomListMultimap(Map> map, Supplier> factory) { + super(); + this.factory = ((Supplier)Preconditions.checkNotNull(factory)); + } + + protected List createCollection() { + return (List)factory.get(); + } + + @GwtIncompatible("java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) throws IOException + { + stream.defaultWriteObject(); + stream.writeObject(factory); + stream.writeObject(backingMap()); + } + + @GwtIncompatible("java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException + { + stream.defaultReadObject(); + factory = ((Supplier)stream.readObject()); + Map> map = (Map)stream.readObject(); + setMap(map); + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static SetMultimap newSetMultimap(Map> map, Supplier> factory) + { + return new CustomSetMultimap(map, factory); + } + + private static class CustomSetMultimap extends AbstractSetMultimap { + transient Supplier> factory; + @GwtIncompatible("not needed in emulated source") + private static final long serialVersionUID = 0L; + + CustomSetMultimap(Map> map, Supplier> factory) { + super(); + this.factory = ((Supplier)Preconditions.checkNotNull(factory)); + } + + protected Set createCollection() { + return (Set)factory.get(); + } + + @GwtIncompatible("java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) throws IOException + { + stream.defaultWriteObject(); + stream.writeObject(factory); + stream.writeObject(backingMap()); + } + + @GwtIncompatible("java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException + { + stream.defaultReadObject(); + factory = ((Supplier)stream.readObject()); + Map> map = (Map)stream.readObject(); + setMap(map); + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static SortedSetMultimap newSortedSetMultimap(Map> map, Supplier> factory) + { + return new CustomSortedSetMultimap(map, factory); + } + + private static class CustomSortedSetMultimap extends AbstractSortedSetMultimap { + transient Supplier> factory; + transient Comparator valueComparator; + @GwtIncompatible("not needed in emulated source") + private static final long serialVersionUID = 0L; + + CustomSortedSetMultimap(Map> map, Supplier> factory) { + super(); + this.factory = ((Supplier)Preconditions.checkNotNull(factory)); + valueComparator = ((SortedSet)factory.get()).comparator(); + } + + protected SortedSet createCollection() { + return (SortedSet)factory.get(); + } + + public Comparator valueComparator() { + return valueComparator; + } + + @GwtIncompatible("java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) throws IOException + { + stream.defaultWriteObject(); + stream.writeObject(factory); + stream.writeObject(backingMap()); + } + + @GwtIncompatible("java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException + { + stream.defaultReadObject(); + factory = ((Supplier)stream.readObject()); + valueComparator = ((SortedSet)factory.get()).comparator(); + Map> map = (Map)stream.readObject(); + setMap(map); + } + } + + + + + + + + + + + + + + + + public static > M invertFrom(Multimap source, M dest) + { + Preconditions.checkNotNull(dest); + for (Map.Entry entry : source.entries()) { + dest.put(entry.getValue(), entry.getKey()); + } + return dest; + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static Multimap synchronizedMultimap(Multimap multimap) + { + return Synchronized.multimap(multimap, null); + } + + + + + + + + + + + + + + + + + + + public static Multimap unmodifiableMultimap(Multimap delegate) + { + if (((delegate instanceof UnmodifiableMultimap)) || ((delegate instanceof ImmutableMultimap))) + { + return delegate; + } + return new UnmodifiableMultimap(delegate); + } + + + + + + + @Deprecated + public static Multimap unmodifiableMultimap(ImmutableMultimap delegate) + { + return (Multimap)Preconditions.checkNotNull(delegate); + } + + private static class UnmodifiableMultimap extends ForwardingMultimap implements Serializable { + final Multimap delegate; + transient Collection> entries; + transient Multiset keys; + transient Set keySet; + transient Collection values; + transient Map> map; + private static final long serialVersionUID = 0L; + + UnmodifiableMultimap(Multimap delegate) { + this.delegate = ((Multimap)Preconditions.checkNotNull(delegate)); + } + + protected Multimap delegate() { + return delegate; + } + + public void clear() { + throw new UnsupportedOperationException(); + } + + public Map> asMap() { + Map> result = map; + if (result == null) { + result = this.map = Collections.unmodifiableMap(Maps.transformValues(delegate.asMap(), new Function() + { + public Collection apply(Collection collection) + { + return Multimaps.unmodifiableValueCollection(collection); + } + })); + } + return result; + } + + public Collection> entries() { + Collection> result = entries; + if (result == null) { + entries = (result = Multimaps.unmodifiableEntries(delegate.entries())); + } + return result; + } + + public Collection get(K key) { + return Multimaps.unmodifiableValueCollection(delegate.get(key)); + } + + public Multiset keys() { + Multiset result = keys; + if (result == null) { + keys = (result = Multisets.unmodifiableMultiset(delegate.keys())); + } + return result; + } + + public Set keySet() { + Set result = keySet; + if (result == null) { + keySet = (result = Collections.unmodifiableSet(delegate.keySet())); + } + return result; + } + + public boolean put(K key, V value) { + throw new UnsupportedOperationException(); + } + + public boolean putAll(K key, Iterable values) { + throw new UnsupportedOperationException(); + } + + public boolean putAll(Multimap multimap) + { + throw new UnsupportedOperationException(); + } + + public boolean remove(Object key, Object value) { + throw new UnsupportedOperationException(); + } + + public Collection removeAll(Object key) { + throw new UnsupportedOperationException(); + } + + public Collection replaceValues(K key, Iterable values) + { + throw new UnsupportedOperationException(); + } + + public Collection values() { + Collection result = values; + if (result == null) { + values = (result = Collections.unmodifiableCollection(delegate.values())); + } + return result; + } + } + + private static class UnmodifiableListMultimap extends Multimaps.UnmodifiableMultimap implements ListMultimap + { + private static final long serialVersionUID = 0L; + + UnmodifiableListMultimap(ListMultimap delegate) { + super(); + } + + public ListMultimap delegate() { return (ListMultimap)super.delegate(); } + + public List get(K key) { + return Collections.unmodifiableList(delegate().get(key)); + } + + public List removeAll(Object key) { throw new UnsupportedOperationException(); } + + public List replaceValues(K key, Iterable values) + { + throw new UnsupportedOperationException(); + } + } + + private static class UnmodifiableSetMultimap extends Multimaps.UnmodifiableMultimap implements SetMultimap { + private static final long serialVersionUID = 0L; + + UnmodifiableSetMultimap(SetMultimap delegate) { + super(); + } + + public SetMultimap delegate() { return (SetMultimap)super.delegate(); } + + + + + public Set get(K key) + { + return Collections.unmodifiableSet(delegate().get(key)); + } + + public Set> entries() { return Maps.unmodifiableEntrySet(delegate().entries()); } + + public Set removeAll(Object key) { + throw new UnsupportedOperationException(); + } + + public Set replaceValues(K key, Iterable values) { + throw new UnsupportedOperationException(); + } + } + + private static class UnmodifiableSortedSetMultimap extends Multimaps.UnmodifiableSetMultimap implements SortedSetMultimap { + private static final long serialVersionUID = 0L; + + UnmodifiableSortedSetMultimap(SortedSetMultimap delegate) { + super(); + } + + public SortedSetMultimap delegate() { return (SortedSetMultimap)super.delegate(); } + + public SortedSet get(K key) { + return Collections.unmodifiableSortedSet(delegate().get(key)); + } + + public SortedSet removeAll(Object key) { throw new UnsupportedOperationException(); } + + public SortedSet replaceValues(K key, Iterable values) + { + throw new UnsupportedOperationException(); + } + + public Comparator valueComparator() { + return delegate().valueComparator(); + } + } + + + + + + + + + + + + + + + public static SetMultimap synchronizedSetMultimap(SetMultimap multimap) + { + return Synchronized.setMultimap(multimap, null); + } + + + + + + + + + + + + + + + + + + + + public static SetMultimap unmodifiableSetMultimap(SetMultimap delegate) + { + if (((delegate instanceof UnmodifiableSetMultimap)) || ((delegate instanceof ImmutableSetMultimap))) + { + return delegate; + } + return new UnmodifiableSetMultimap(delegate); + } + + + + + + + @Deprecated + public static SetMultimap unmodifiableSetMultimap(ImmutableSetMultimap delegate) + { + return (SetMultimap)Preconditions.checkNotNull(delegate); + } + + + + + + + + + + + + + + public static SortedSetMultimap synchronizedSortedSetMultimap(SortedSetMultimap multimap) + { + return Synchronized.sortedSetMultimap(multimap, null); + } + + + + + + + + + + + + + + + + + + + + public static SortedSetMultimap unmodifiableSortedSetMultimap(SortedSetMultimap delegate) + { + if ((delegate instanceof UnmodifiableSortedSetMultimap)) { + return delegate; + } + return new UnmodifiableSortedSetMultimap(delegate); + } + + + + + + + + + + + public static ListMultimap synchronizedListMultimap(ListMultimap multimap) + { + return Synchronized.listMultimap(multimap, null); + } + + + + + + + + + + + + + + + + + + + + public static ListMultimap unmodifiableListMultimap(ListMultimap delegate) + { + if (((delegate instanceof UnmodifiableListMultimap)) || ((delegate instanceof ImmutableListMultimap))) + { + return delegate; + } + return new UnmodifiableListMultimap(delegate); + } + + + + + + + @Deprecated + public static ListMultimap unmodifiableListMultimap(ImmutableListMultimap delegate) + { + return (ListMultimap)Preconditions.checkNotNull(delegate); + } + + + + + + + + + + private static Collection unmodifiableValueCollection(Collection collection) + { + if ((collection instanceof SortedSet)) + return Collections.unmodifiableSortedSet((SortedSet)collection); + if ((collection instanceof Set)) + return Collections.unmodifiableSet((Set)collection); + if ((collection instanceof List)) { + return Collections.unmodifiableList((List)collection); + } + return Collections.unmodifiableCollection(collection); + } + + + + + + + + + + + private static Collection> unmodifiableEntries(Collection> entries) + { + if ((entries instanceof Set)) { + return Maps.unmodifiableEntrySet((Set)entries); + } + return new Maps.UnmodifiableEntries(Collections.unmodifiableCollection(entries)); + } + + + + + + + + + + @Beta + public static Map> asMap(ListMultimap multimap) + { + return multimap.asMap(); + } + + + + + + + + + @Beta + public static Map> asMap(SetMultimap multimap) + { + return multimap.asMap(); + } + + + + + + + + + + + @Beta + public static Map> asMap(SortedSetMultimap multimap) + { + return multimap.asMap(); + } + + + + + + + @Beta + public static Map> asMap(Multimap multimap) + { + return multimap.asMap(); + } + + + + + + + + + + + + + + + + + + public static SetMultimap forMap(Map map) + { + return new MapMultimap(map); + } + + private static class MapMultimap extends AbstractMultimap implements SetMultimap, Serializable + { + final Map map; + private static final long serialVersionUID = 7845222491160860175L; + + MapMultimap(Map map) { + this.map = ((Map)Preconditions.checkNotNull(map)); + } + + public int size() + { + return map.size(); + } + + public boolean containsKey(Object key) + { + return map.containsKey(key); + } + + public boolean containsValue(Object value) + { + return map.containsValue(value); + } + + public boolean containsEntry(Object key, Object value) + { + return map.entrySet().contains(Maps.immutableEntry(key, value)); + } + + public Set get(final K key) + { + new Sets.ImprovedAbstractSet() { + public Iterator iterator() { + new Iterator() + { + int i; + + public boolean hasNext() { + return (i == 0) && (map.containsKey(val$key)); + } + + public V next() + { + if (!hasNext()) { + throw new NoSuchElementException(); + } + i += 1; + return map.get(val$key); + } + + public void remove() + { + CollectPreconditions.checkRemove(i == 1); + i = -1; + map.remove(val$key); + } + }; + } + + public int size() { + return map.containsKey(key) ? 1 : 0; + } + }; + } + + public boolean put(K key, V value) + { + throw new UnsupportedOperationException(); + } + + public boolean putAll(K key, Iterable values) + { + throw new UnsupportedOperationException(); + } + + public boolean putAll(Multimap multimap) + { + throw new UnsupportedOperationException(); + } + + public Set replaceValues(K key, Iterable values) + { + throw new UnsupportedOperationException(); + } + + public boolean remove(Object key, Object value) + { + return map.entrySet().remove(Maps.immutableEntry(key, value)); + } + + public Set removeAll(Object key) + { + Set values = new HashSet(2); + if (!map.containsKey(key)) { + return values; + } + values.add(map.remove(key)); + return values; + } + + public void clear() + { + map.clear(); + } + + public Set keySet() + { + return map.keySet(); + } + + public Collection values() + { + return map.values(); + } + + public Set> entries() + { + return map.entrySet(); + } + + Iterator> entryIterator() + { + return map.entrySet().iterator(); + } + + Map> createAsMap() + { + return new Multimaps.AsMap(this); + } + + public int hashCode() { + return map.hashCode(); + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static Multimap transformValues(Multimap fromMultimap, Function function) + { + Preconditions.checkNotNull(function); + Maps.EntryTransformer transformer = Maps.asEntryTransformer(function); + return transformEntries(fromMultimap, transformer); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static Multimap transformEntries(Multimap fromMap, Maps.EntryTransformer transformer) + { + return new TransformedEntriesMultimap(fromMap, transformer); + } + + private static class TransformedEntriesMultimap extends AbstractMultimap + { + final Multimap fromMultimap; + final Maps.EntryTransformer transformer; + + TransformedEntriesMultimap(Multimap fromMultimap, Maps.EntryTransformer transformer) + { + this.fromMultimap = ((Multimap)Preconditions.checkNotNull(fromMultimap)); + this.transformer = ((Maps.EntryTransformer)Preconditions.checkNotNull(transformer)); + } + + Collection transform(K key, Collection values) { + Function function = Maps.asValueToValueFunction(transformer, key); + + if ((values instanceof List)) { + return Lists.transform((List)values, function); + } + return Collections2.transform(values, function); + } + + + Map> createAsMap() + { + Maps.transformEntries(fromMultimap.asMap(), new Maps.EntryTransformer() + { + public Collection transformEntry(K key, Collection value) + { + return transform(key, value); + } + }); + } + + public void clear() { + fromMultimap.clear(); + } + + public boolean containsKey(Object key) { + return fromMultimap.containsKey(key); + } + + Iterator> entryIterator() + { + return Iterators.transform(fromMultimap.entries().iterator(), Maps.asEntryToEntryFunction(transformer)); + } + + public Collection get(K key) + { + return transform(key, fromMultimap.get(key)); + } + + public boolean isEmpty() { + return fromMultimap.isEmpty(); + } + + public Set keySet() { + return fromMultimap.keySet(); + } + + public Multiset keys() { + return fromMultimap.keys(); + } + + public boolean put(K key, V2 value) { + throw new UnsupportedOperationException(); + } + + public boolean putAll(K key, Iterable values) { + throw new UnsupportedOperationException(); + } + + public boolean putAll(Multimap multimap) + { + throw new UnsupportedOperationException(); + } + + public boolean remove(Object key, Object value) + { + return get(key).remove(value); + } + + public Collection removeAll(Object key) + { + return transform(key, fromMultimap.removeAll(key)); + } + + public Collection replaceValues(K key, Iterable values) + { + throw new UnsupportedOperationException(); + } + + public int size() { + return fromMultimap.size(); + } + + Collection createValues() + { + return Collections2.transform(fromMultimap.entries(), Maps.asEntryToValueFunction(transformer)); + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static ListMultimap transformValues(ListMultimap fromMultimap, Function function) + { + Preconditions.checkNotNull(function); + Maps.EntryTransformer transformer = Maps.asEntryTransformer(function); + return transformEntries(fromMultimap, transformer); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static ListMultimap transformEntries(ListMultimap fromMap, Maps.EntryTransformer transformer) + { + return new TransformedEntriesListMultimap(fromMap, transformer); + } + + private static final class TransformedEntriesListMultimap + extends Multimaps.TransformedEntriesMultimap + implements ListMultimap + { + TransformedEntriesListMultimap(ListMultimap fromMultimap, Maps.EntryTransformer transformer) + { + super(transformer); + } + + List transform(K key, Collection values) { + return Lists.transform((List)values, Maps.asValueToValueFunction(transformer, key)); + } + + public List get(K key) { + return transform(key, fromMultimap.get(key)); + } + + public List removeAll(Object key) + { + return transform(key, fromMultimap.removeAll(key)); + } + + public List replaceValues(K key, Iterable values) + { + throw new UnsupportedOperationException(); + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static ImmutableListMultimap index(Iterable values, Function keyFunction) + { + return index(values.iterator(), keyFunction); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static ImmutableListMultimap index(Iterator values, Function keyFunction) + { + Preconditions.checkNotNull(keyFunction); + ImmutableListMultimap.Builder builder = ImmutableListMultimap.builder(); + + while (values.hasNext()) { + V value = values.next(); + Preconditions.checkNotNull(value, values); + builder.put(keyFunction.apply(value), value); + } + return builder.build(); + } + + static class Keys extends AbstractMultiset { + final Multimap multimap; + + Keys(Multimap multimap) { + this.multimap = multimap; + } + + Iterator> entryIterator() { + new TransformedIterator(multimap.asMap().entrySet().iterator()) + { + + Multiset.Entry transform(final Map.Entry> backingEntry) + { + new Multisets.AbstractEntry() + { + public K getElement() { + return backingEntry.getKey(); + } + + public int getCount() + { + return ((Collection)backingEntry.getValue()).size(); + } + }; + } + }; + } + + int distinctElements() { + return multimap.asMap().size(); + } + + + Set> createEntrySet() { return new KeysEntrySet(); } + + class KeysEntrySet extends Multisets.EntrySet { + KeysEntrySet() {} + + Multiset multiset() { return Multimaps.Keys.this; } + + public Iterator> iterator() + { + return entryIterator(); + } + + public int size() { + return distinctElements(); + } + + public boolean isEmpty() { + return multimap.isEmpty(); + } + + public boolean contains(@Nullable Object o) { + if ((o instanceof Multiset.Entry)) { + Multiset.Entry entry = (Multiset.Entry)o; + Collection collection = (Collection)multimap.asMap().get(entry.getElement()); + return (collection != null) && (collection.size() == entry.getCount()); + } + return false; + } + + public boolean remove(@Nullable Object o) { + if ((o instanceof Multiset.Entry)) { + Multiset.Entry entry = (Multiset.Entry)o; + Collection collection = (Collection)multimap.asMap().get(entry.getElement()); + if ((collection != null) && (collection.size() == entry.getCount())) { + collection.clear(); + return true; + } + } + return false; + } + } + + public boolean contains(@Nullable Object element) { + return multimap.containsKey(element); + } + + public Iterator iterator() { + return Maps.keyIterator(multimap.entries().iterator()); + } + + public int count(@Nullable Object element) { + Collection values = (Collection)Maps.safeGet(multimap.asMap(), element); + return values == null ? 0 : values.size(); + } + + public int remove(@Nullable Object element, int occurrences) { + CollectPreconditions.checkNonnegative(occurrences, "occurrences"); + if (occurrences == 0) { + return count(element); + } + + Collection values = (Collection)Maps.safeGet(multimap.asMap(), element); + + if (values == null) { + return 0; + } + + int oldCount = values.size(); + if (occurrences >= oldCount) { + values.clear(); + } else { + Iterator iterator = values.iterator(); + for (int i = 0; i < occurrences; i++) { + iterator.next(); + iterator.remove(); + } + } + return oldCount; + } + + public void clear() { + multimap.clear(); + } + + public Set elementSet() { + return multimap.keySet(); + } + } + + static abstract class Entries extends AbstractCollection> + { + Entries() {} + + abstract Multimap multimap(); + + public int size() + { + return multimap().size(); + } + + public boolean contains(@Nullable Object o) { + if ((o instanceof Map.Entry)) { + Map.Entry entry = (Map.Entry)o; + return multimap().containsEntry(entry.getKey(), entry.getValue()); + } + return false; + } + + public boolean remove(@Nullable Object o) { + if ((o instanceof Map.Entry)) { + Map.Entry entry = (Map.Entry)o; + return multimap().remove(entry.getKey(), entry.getValue()); + } + return false; + } + + public void clear() { + multimap().clear(); + } + } + + + static final class AsMap + extends Maps.ImprovedAbstractMap> + { + private final Multimap multimap; + + AsMap(Multimap multimap) + { + this.multimap = ((Multimap)Preconditions.checkNotNull(multimap)); + } + + public int size() { + return multimap.keySet().size(); + } + + protected Set>> createEntrySet() { + return new EntrySet(); + } + + + void removeValuesForKey(Object key) { multimap.keySet().remove(key); } + + class EntrySet extends Maps.EntrySet> { + EntrySet() {} + + Map> map() { return Multimaps.AsMap.this; } + + public Iterator>> iterator() + { + Maps.asMapEntryIterator(multimap.keySet(), new Function() + { + public Collection apply(K key) { + return multimap.get(key); + } + }); + } + + public boolean remove(Object o) { + if (!contains(o)) { + return false; + } + Map.Entry entry = (Map.Entry)o; + removeValuesForKey(entry.getKey()); + return true; + } + } + + public Collection get(Object key) + { + return containsKey(key) ? multimap.get(key) : null; + } + + public Collection remove(Object key) { + return containsKey(key) ? multimap.removeAll(key) : null; + } + + public Set keySet() { + return multimap.keySet(); + } + + public boolean isEmpty() { + return multimap.isEmpty(); + } + + public boolean containsKey(Object key) { + return multimap.containsKey(key); + } + + public void clear() { + multimap.clear(); + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static Multimap filterKeys(Multimap unfiltered, Predicate keyPredicate) + { + if ((unfiltered instanceof SetMultimap)) + return filterKeys((SetMultimap)unfiltered, keyPredicate); + if ((unfiltered instanceof ListMultimap)) + return filterKeys((ListMultimap)unfiltered, keyPredicate); + if ((unfiltered instanceof FilteredKeyMultimap)) { + FilteredKeyMultimap prev = (FilteredKeyMultimap)unfiltered; + return new FilteredKeyMultimap(unfiltered, Predicates.and(keyPredicate, keyPredicate)); + } + if ((unfiltered instanceof FilteredMultimap)) { + FilteredMultimap prev = (FilteredMultimap)unfiltered; + return filterFiltered(prev, Maps.keyPredicateOnEntries(keyPredicate)); + } + return new FilteredKeyMultimap(unfiltered, keyPredicate); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static SetMultimap filterKeys(SetMultimap unfiltered, Predicate keyPredicate) + { + if ((unfiltered instanceof FilteredKeySetMultimap)) { + FilteredKeySetMultimap prev = (FilteredKeySetMultimap)unfiltered; + return new FilteredKeySetMultimap(prev.unfiltered(), Predicates.and(keyPredicate, keyPredicate)); + } + if ((unfiltered instanceof FilteredSetMultimap)) { + FilteredSetMultimap prev = (FilteredSetMultimap)unfiltered; + return filterFiltered(prev, Maps.keyPredicateOnEntries(keyPredicate)); + } + return new FilteredKeySetMultimap(unfiltered, keyPredicate); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static ListMultimap filterKeys(ListMultimap unfiltered, Predicate keyPredicate) + { + if ((unfiltered instanceof FilteredKeyListMultimap)) { + FilteredKeyListMultimap prev = (FilteredKeyListMultimap)unfiltered; + return new FilteredKeyListMultimap(prev.unfiltered(), Predicates.and(keyPredicate, keyPredicate)); + } + + return new FilteredKeyListMultimap(unfiltered, keyPredicate); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static Multimap filterValues(Multimap unfiltered, Predicate valuePredicate) + { + return filterEntries(unfiltered, Maps.valuePredicateOnEntries(valuePredicate)); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static SetMultimap filterValues(SetMultimap unfiltered, Predicate valuePredicate) + { + return filterEntries(unfiltered, Maps.valuePredicateOnEntries(valuePredicate)); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static Multimap filterEntries(Multimap unfiltered, Predicate> entryPredicate) + { + Preconditions.checkNotNull(entryPredicate); + if ((unfiltered instanceof SetMultimap)) { + return filterEntries((SetMultimap)unfiltered, entryPredicate); + } + return (unfiltered instanceof FilteredMultimap) ? filterFiltered((FilteredMultimap)unfiltered, entryPredicate) : new FilteredEntryMultimap((Multimap)Preconditions.checkNotNull(unfiltered), entryPredicate); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static SetMultimap filterEntries(SetMultimap unfiltered, Predicate> entryPredicate) + { + Preconditions.checkNotNull(entryPredicate); + return (unfiltered instanceof FilteredSetMultimap) ? filterFiltered((FilteredSetMultimap)unfiltered, entryPredicate) : new FilteredEntrySetMultimap((SetMultimap)Preconditions.checkNotNull(unfiltered), entryPredicate); + } + + + + + + + + + + + private static Multimap filterFiltered(FilteredMultimap multimap, Predicate> entryPredicate) + { + Predicate> predicate = Predicates.and(multimap.entryPredicate(), entryPredicate); + + return new FilteredEntryMultimap(multimap.unfiltered(), predicate); + } + + + + + + + + + private static SetMultimap filterFiltered(FilteredSetMultimap multimap, Predicate> entryPredicate) + { + Predicate> predicate = Predicates.and(multimap.entryPredicate(), entryPredicate); + + return new FilteredEntrySetMultimap(multimap.unfiltered(), predicate); + } + + static boolean equalsImpl(Multimap multimap, @Nullable Object object) { + if (object == multimap) { + return true; + } + if ((object instanceof Multimap)) { + Multimap that = (Multimap)object; + return multimap.asMap().equals(that.asMap()); + } + return false; + } +} diff --git a/src/minecraft/com/google/common/collect/Multiset.java b/src/minecraft/com/google/common/collect/Multiset.java new file mode 100644 index 0000000..617dc83 --- /dev/null +++ b/src/minecraft/com/google/common/collect/Multiset.java @@ -0,0 +1,59 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract interface Multiset + extends Collection +{ + public abstract int count(@Nullable Object paramObject); + + public abstract int add(@Nullable E paramE, int paramInt); + + public abstract int remove(@Nullable Object paramObject, int paramInt); + + public abstract int setCount(E paramE, int paramInt); + + public abstract boolean setCount(E paramE, int paramInt1, int paramInt2); + + public abstract Set elementSet(); + + public abstract Set> entrySet(); + + public abstract boolean equals(@Nullable Object paramObject); + + public abstract int hashCode(); + + public abstract String toString(); + + public abstract Iterator iterator(); + + public abstract boolean contains(@Nullable Object paramObject); + + public abstract boolean containsAll(Collection paramCollection); + + public abstract boolean add(E paramE); + + public abstract boolean remove(@Nullable Object paramObject); + + public abstract boolean removeAll(Collection paramCollection); + + public abstract boolean retainAll(Collection paramCollection); + + public static abstract interface Entry + { + public abstract E getElement(); + + public abstract int getCount(); + + public abstract boolean equals(Object paramObject); + + public abstract int hashCode(); + + public abstract String toString(); + } +} diff --git a/src/minecraft/com/google/common/collect/Multisets.java b/src/minecraft/com/google/common/collect/Multisets.java new file mode 100644 index 0000000..58cb0dc --- /dev/null +++ b/src/minecraft/com/google/common/collect/Multisets.java @@ -0,0 +1,1082 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.primitives.Ints; +import java.io.Serializable; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public final class Multisets +{ + private Multisets() {} + + public static Multiset unmodifiableMultiset(Multiset multiset) + { + if (((multiset instanceof UnmodifiableMultiset)) || ((multiset instanceof ImmutableMultiset))) + { + + + Multiset result = multiset; + return result; + } + return new UnmodifiableMultiset((Multiset)Preconditions.checkNotNull(multiset)); + } + + + + + + + + + @Deprecated + public static Multiset unmodifiableMultiset(ImmutableMultiset multiset) { return (Multiset)Preconditions.checkNotNull(multiset); } + + static class UnmodifiableMultiset extends ForwardingMultiset implements Serializable { + final Multiset delegate; + transient Set elementSet; + transient Set> entrySet; + private static final long serialVersionUID = 0L; + + UnmodifiableMultiset(Multiset delegate) { this.delegate = delegate; } + + + + protected Multiset delegate() + { + return delegate; + } + + + Set createElementSet() + { + return Collections.unmodifiableSet(delegate.elementSet()); + } + + public Set elementSet() + { + Set es = elementSet; + return es == null ? (this.elementSet = createElementSet()) : es; + } + + + + public Set> entrySet() + { + Set> es = entrySet; + return es == null ? (this.entrySet = Collections.unmodifiableSet(delegate.entrySet())) : es; + } + + + + + + + public Iterator iterator() + { + return Iterators.unmodifiableIterator(delegate.iterator()); + } + + public boolean add(E element) { + throw new UnsupportedOperationException(); + } + + public int add(E element, int occurences) { + throw new UnsupportedOperationException(); + } + + public boolean addAll(Collection elementsToAdd) { + throw new UnsupportedOperationException(); + } + + public boolean remove(Object element) { + throw new UnsupportedOperationException(); + } + + public int remove(Object element, int occurrences) { + throw new UnsupportedOperationException(); + } + + public boolean removeAll(Collection elementsToRemove) { + throw new UnsupportedOperationException(); + } + + public boolean retainAll(Collection elementsToRetain) { + throw new UnsupportedOperationException(); + } + + public void clear() { + throw new UnsupportedOperationException(); + } + + public int setCount(E element, int count) { + throw new UnsupportedOperationException(); + } + + public boolean setCount(E element, int oldCount, int newCount) { + throw new UnsupportedOperationException(); + } + } + + + + + + + + + + + + + + + + + + + @Beta + public static SortedMultiset unmodifiableSortedMultiset(SortedMultiset sortedMultiset) + { + return new UnmodifiableSortedMultiset((SortedMultiset)Preconditions.checkNotNull(sortedMultiset)); + } + + + + + + + + + + + public static Multiset.Entry immutableEntry(@Nullable E e, int n) { return new ImmutableEntry(e, n); } + + static final class ImmutableEntry extends Multisets.AbstractEntry implements Serializable { + @Nullable + final E element; + final int count; + private static final long serialVersionUID = 0L; + + ImmutableEntry(@Nullable E element, int count) { + this.element = element; + this.count = count; + CollectPreconditions.checkNonnegative(count, "count"); + } + + @Nullable + public E getElement() { + return element; + } + + public int getCount() + { + return count; + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @Beta + public static Multiset filter(Multiset unfiltered, Predicate predicate) + { + if ((unfiltered instanceof FilteredMultiset)) + { + + FilteredMultiset filtered = (FilteredMultiset)unfiltered; + Predicate combinedPredicate = Predicates.and(predicate, predicate); + + return new FilteredMultiset(unfiltered, combinedPredicate); + } + return new FilteredMultiset(unfiltered, predicate); + } + + private static final class FilteredMultiset extends AbstractMultiset { + final Multiset unfiltered; + final Predicate predicate; + + FilteredMultiset(Multiset unfiltered, Predicate predicate) { + this.unfiltered = ((Multiset)Preconditions.checkNotNull(unfiltered)); + this.predicate = ((Predicate)Preconditions.checkNotNull(predicate)); + } + + public UnmodifiableIterator iterator() + { + return Iterators.filter(unfiltered.iterator(), predicate); + } + + Set createElementSet() + { + return Sets.filter(unfiltered.elementSet(), predicate); + } + + Set> createEntrySet() + { + Sets.filter(unfiltered.entrySet(), new Predicate() + { + public boolean apply(Multiset.Entry entry) { + return predicate.apply(entry.getElement()); + } + }); + } + + Iterator> entryIterator() + { + throw new AssertionError("should never be called"); + } + + int distinctElements() + { + return elementSet().size(); + } + + public int count(@Nullable Object element) + { + int count = unfiltered.count(element); + if (count > 0) + { + E e = element; + return predicate.apply(e) ? count : 0; + } + return 0; + } + + public int add(@Nullable E element, int occurrences) + { + Preconditions.checkArgument(predicate.apply(element), "Element %s does not match predicate %s", new Object[] { element, predicate }); + + return unfiltered.add(element, occurrences); + } + + public int remove(@Nullable Object element, int occurrences) + { + CollectPreconditions.checkNonnegative(occurrences, "occurrences"); + if (occurrences == 0) { + return count(element); + } + return contains(element) ? unfiltered.remove(element, occurrences) : 0; + } + + + public void clear() + { + elementSet().clear(); + } + } + + + + + + + static int inferDistinctElements(Iterable elements) + { + if ((elements instanceof Multiset)) { + return ((Multiset)elements).elementSet().size(); + } + return 11; + } + + + + + + + + + + + + + + + + + @Beta + public static Multiset union(Multiset multiset1, final Multiset multiset2) + { + Preconditions.checkNotNull(multiset1); + Preconditions.checkNotNull(multiset2); + + new AbstractMultiset() + { + public boolean contains(@Nullable Object element) { + return (val$multiset1.contains(element)) || (multiset2.contains(element)); + } + + public boolean isEmpty() + { + return (val$multiset1.isEmpty()) && (multiset2.isEmpty()); + } + + public int count(Object element) + { + return Math.max(val$multiset1.count(element), multiset2.count(element)); + } + + Set createElementSet() + { + return Sets.union(val$multiset1.elementSet(), multiset2.elementSet()); + } + + Iterator> entryIterator() + { + final Iterator> iterator1 = val$multiset1.entrySet().iterator(); + + final Iterator> iterator2 = multiset2.entrySet().iterator(); + + + new AbstractIterator() + { + protected Multiset.Entry computeNext() { + if (iterator1.hasNext()) { + Multiset.Entry entry1 = (Multiset.Entry)iterator1.next(); + E element = entry1.getElement(); + int count = Math.max(entry1.getCount(), val$multiset2.count(element)); + return Multisets.immutableEntry(element, count); + } + while (iterator2.hasNext()) { + Multiset.Entry entry2 = (Multiset.Entry)iterator2.next(); + E element = entry2.getElement(); + if (!val$multiset1.contains(element)) { + return Multisets.immutableEntry(element, entry2.getCount()); + } + } + return (Multiset.Entry)endOfData(); + } + }; + } + + int distinctElements() + { + return elementSet().size(); + } + }; + } + + + + + + + + + + + + + + + + public static Multiset intersection(Multiset multiset1, final Multiset multiset2) + { + Preconditions.checkNotNull(multiset1); + Preconditions.checkNotNull(multiset2); + + new AbstractMultiset() + { + public int count(Object element) { + int count1 = val$multiset1.count(element); + return count1 == 0 ? 0 : Math.min(count1, multiset2.count(element)); + } + + Set createElementSet() + { + return Sets.intersection(val$multiset1.elementSet(), multiset2.elementSet()); + } + + + Iterator> entryIterator() + { + final Iterator> iterator1 = val$multiset1.entrySet().iterator(); + + new AbstractIterator() + { + protected Multiset.Entry computeNext() { + while (iterator1.hasNext()) { + Multiset.Entry entry1 = (Multiset.Entry)iterator1.next(); + E element = entry1.getElement(); + int count = Math.min(entry1.getCount(), val$multiset2.count(element)); + if (count > 0) { + return Multisets.immutableEntry(element, count); + } + } + return (Multiset.Entry)endOfData(); + } + }; + } + + int distinctElements() + { + return elementSet().size(); + } + }; + } + + + + + + + + + + + + + + + + + @Beta + public static Multiset sum(Multiset multiset1, final Multiset multiset2) + { + Preconditions.checkNotNull(multiset1); + Preconditions.checkNotNull(multiset2); + + + new AbstractMultiset() + { + public boolean contains(@Nullable Object element) { + return (val$multiset1.contains(element)) || (multiset2.contains(element)); + } + + public boolean isEmpty() + { + return (val$multiset1.isEmpty()) && (multiset2.isEmpty()); + } + + public int size() + { + return val$multiset1.size() + multiset2.size(); + } + + public int count(Object element) + { + return val$multiset1.count(element) + multiset2.count(element); + } + + Set createElementSet() + { + return Sets.union(val$multiset1.elementSet(), multiset2.elementSet()); + } + + Iterator> entryIterator() + { + final Iterator> iterator1 = val$multiset1.entrySet().iterator(); + + final Iterator> iterator2 = multiset2.entrySet().iterator(); + + new AbstractIterator() + { + protected Multiset.Entry computeNext() { + if (iterator1.hasNext()) { + Multiset.Entry entry1 = (Multiset.Entry)iterator1.next(); + E element = entry1.getElement(); + int count = entry1.getCount() + val$multiset2.count(element); + return Multisets.immutableEntry(element, count); + } + while (iterator2.hasNext()) { + Multiset.Entry entry2 = (Multiset.Entry)iterator2.next(); + E element = entry2.getElement(); + if (!val$multiset1.contains(element)) { + return Multisets.immutableEntry(element, entry2.getCount()); + } + } + return (Multiset.Entry)endOfData(); + } + }; + } + + int distinctElements() + { + return elementSet().size(); + } + }; + } + + + + + + + + + + + + + + + + + @Beta + public static Multiset difference(Multiset multiset1, final Multiset multiset2) + { + Preconditions.checkNotNull(multiset1); + Preconditions.checkNotNull(multiset2); + + + new AbstractMultiset() + { + public int count(@Nullable Object element) { + int count1 = val$multiset1.count(element); + return count1 == 0 ? 0 : Math.max(0, count1 - multiset2.count(element)); + } + + + Iterator> entryIterator() + { + final Iterator> iterator1 = val$multiset1.entrySet().iterator(); + new AbstractIterator() + { + protected Multiset.Entry computeNext() { + while (iterator1.hasNext()) { + Multiset.Entry entry1 = (Multiset.Entry)iterator1.next(); + E element = entry1.getElement(); + int count = entry1.getCount() - val$multiset2.count(element); + if (count > 0) { + return Multisets.immutableEntry(element, count); + } + } + return (Multiset.Entry)endOfData(); + } + }; + } + + int distinctElements() + { + return Iterators.size(entryIterator()); + } + }; + } + + + + + + + + public static boolean containsOccurrences(Multiset superMultiset, Multiset subMultiset) + { + Preconditions.checkNotNull(superMultiset); + Preconditions.checkNotNull(subMultiset); + for (Multiset.Entry entry : subMultiset.entrySet()) { + int superCount = superMultiset.count(entry.getElement()); + if (superCount < entry.getCount()) { + return false; + } + } + return true; + } + + + + + + + + + + + + + + + + + + + + + public static boolean retainOccurrences(Multiset multisetToModify, Multiset multisetToRetain) + { + return retainOccurrencesImpl(multisetToModify, multisetToRetain); + } + + + + + private static boolean retainOccurrencesImpl(Multiset multisetToModify, Multiset occurrencesToRetain) + { + Preconditions.checkNotNull(multisetToModify); + Preconditions.checkNotNull(occurrencesToRetain); + + Iterator> entryIterator = multisetToModify.entrySet().iterator(); + boolean changed = false; + while (entryIterator.hasNext()) { + Multiset.Entry entry = (Multiset.Entry)entryIterator.next(); + int retainCount = occurrencesToRetain.count(entry.getElement()); + if (retainCount == 0) { + entryIterator.remove(); + changed = true; + } else if (retainCount < entry.getCount()) { + multisetToModify.setCount(entry.getElement(), retainCount); + changed = true; + } + } + return changed; + } + + + + + + + + + + + + + + + + + + + + + + + + + public static boolean removeOccurrences(Multiset multisetToModify, Multiset occurrencesToRemove) + { + return removeOccurrencesImpl(multisetToModify, occurrencesToRemove); + } + + + + + + private static boolean removeOccurrencesImpl(Multiset multisetToModify, Multiset occurrencesToRemove) + { + Preconditions.checkNotNull(multisetToModify); + Preconditions.checkNotNull(occurrencesToRemove); + + boolean changed = false; + Iterator> entryIterator = multisetToModify.entrySet().iterator(); + while (entryIterator.hasNext()) { + Multiset.Entry entry = (Multiset.Entry)entryIterator.next(); + int removeCount = occurrencesToRemove.count(entry.getElement()); + if (removeCount >= entry.getCount()) { + entryIterator.remove(); + changed = true; + } else if (removeCount > 0) { + multisetToModify.remove(entry.getElement(), removeCount); + changed = true; + } + } + return changed; + } + + + + static abstract class AbstractEntry + implements Multiset.Entry + { + AbstractEntry() {} + + + public boolean equals(@Nullable Object object) + { + if ((object instanceof Multiset.Entry)) { + Multiset.Entry that = (Multiset.Entry)object; + return (getCount() == that.getCount()) && (Objects.equal(getElement(), that.getElement())); + } + + return false; + } + + + + + public int hashCode() + { + E e = getElement(); + return (e == null ? 0 : e.hashCode()) ^ getCount(); + } + + + + + + + + public String toString() + { + String text = String.valueOf(getElement()); + int n = getCount(); + return text + " x " + n; + } + } + + + + static boolean equalsImpl(Multiset multiset, @Nullable Object object) + { + if (object == multiset) { + return true; + } + if ((object instanceof Multiset)) { + Multiset that = (Multiset)object; + + + + + + + if ((multiset.size() != that.size()) || (multiset.entrySet().size() != that.entrySet().size())) + { + return false; + } + for (Multiset.Entry entry : that.entrySet()) { + if (multiset.count(entry.getElement()) != entry.getCount()) { + return false; + } + } + return true; + } + return false; + } + + + + + static boolean addAllImpl(Multiset self, Collection elements) + { + if (elements.isEmpty()) { + return false; + } + if ((elements instanceof Multiset)) { + Multiset that = cast(elements); + for (Multiset.Entry entry : that.entrySet()) { + self.add(entry.getElement(), entry.getCount()); + } + } else { + Iterators.addAll(self, elements.iterator()); + } + return true; + } + + + + + static boolean removeAllImpl(Multiset self, Collection elementsToRemove) + { + Collection collection = (elementsToRemove instanceof Multiset) ? ((Multiset)elementsToRemove).elementSet() : elementsToRemove; + + + return self.elementSet().removeAll(collection); + } + + + + + static boolean retainAllImpl(Multiset self, Collection elementsToRetain) + { + Preconditions.checkNotNull(elementsToRetain); + Collection collection = (elementsToRetain instanceof Multiset) ? ((Multiset)elementsToRetain).elementSet() : elementsToRetain; + + + return self.elementSet().retainAll(collection); + } + + + + static int setCountImpl(Multiset self, E element, int count) + { + CollectPreconditions.checkNonnegative(count, "count"); + + int oldCount = self.count(element); + + int delta = count - oldCount; + if (delta > 0) { + self.add(element, delta); + } else if (delta < 0) { + self.remove(element, -delta); + } + + return oldCount; + } + + + + + static boolean setCountImpl(Multiset self, E element, int oldCount, int newCount) + { + CollectPreconditions.checkNonnegative(oldCount, "oldCount"); + CollectPreconditions.checkNonnegative(newCount, "newCount"); + + if (self.count(element) == oldCount) { + self.setCount(element, newCount); + return true; + } + return false; + } + + static abstract class ElementSet extends Sets.ImprovedAbstractSet { + ElementSet() {} + + abstract Multiset multiset(); + + public void clear() { multiset().clear(); } + + public boolean contains(Object o) + { + return multiset().contains(o); + } + + public boolean containsAll(Collection c) { + return multiset().containsAll(c); + } + + public boolean isEmpty() { + return multiset().isEmpty(); + } + + public Iterator iterator() { + new TransformedIterator(multiset().entrySet().iterator()) + { + E transform(Multiset.Entry entry) { + return entry.getElement(); + } + }; + } + + public boolean remove(Object o) + { + int count = multiset().count(o); + if (count > 0) { + multiset().remove(o, count); + return true; + } + return false; + } + + + public int size() { return multiset().entrySet().size(); } + } + + static abstract class EntrySet extends Sets.ImprovedAbstractSet> { + EntrySet() {} + + abstract Multiset multiset(); + + public boolean contains(@Nullable Object o) { if ((o instanceof Multiset.Entry)) + { + + + + Multiset.Entry entry = (Multiset.Entry)o; + if (entry.getCount() <= 0) { + return false; + } + int count = multiset().count(entry.getElement()); + return count == entry.getCount(); + } + + return false; + } + + + public boolean remove(Object object) + { + if ((object instanceof Multiset.Entry)) { + Multiset.Entry entry = (Multiset.Entry)object; + Object element = entry.getElement(); + int entryCount = entry.getCount(); + if (entryCount != 0) + { + + Multiset multiset = multiset(); + return multiset.setCount(element, entryCount, 0); + } + } + return false; + } + + public void clear() { + multiset().clear(); + } + } + + + + static Iterator iteratorImpl(Multiset multiset) + { + return new MultisetIteratorImpl(multiset, multiset.entrySet().iterator()); + } + + + static final class MultisetIteratorImpl + implements Iterator + { + private final Multiset multiset; + private final Iterator> entryIterator; + private Multiset.Entry currentEntry; + private int laterCount; + private int totalCount; + private boolean canRemove; + + MultisetIteratorImpl(Multiset multiset, Iterator> entryIterator) + { + this.multiset = multiset; + this.entryIterator = entryIterator; + } + + public boolean hasNext() + { + return (laterCount > 0) || (entryIterator.hasNext()); + } + + public E next() + { + if (!hasNext()) { + throw new NoSuchElementException(); + } + if (laterCount == 0) { + currentEntry = ((Multiset.Entry)entryIterator.next()); + totalCount = (this.laterCount = currentEntry.getCount()); + } + laterCount -= 1; + canRemove = true; + return currentEntry.getElement(); + } + + public void remove() + { + CollectPreconditions.checkRemove(canRemove); + if (totalCount == 1) { + entryIterator.remove(); + } else { + multiset.remove(currentEntry.getElement()); + } + totalCount -= 1; + canRemove = false; + } + } + + + + static int sizeImpl(Multiset multiset) + { + long size = 0L; + for (Multiset.Entry entry : multiset.entrySet()) { + size += entry.getCount(); + } + return Ints.saturatedCast(size); + } + + + + static Multiset cast(Iterable iterable) + { + return (Multiset)iterable; + } + + private static final Ordering> DECREASING_COUNT_ORDERING = new Ordering() + { + public int compare(Multiset.Entry entry1, Multiset.Entry entry2) { + return Ints.compare(entry2.getCount(), entry1.getCount()); + } + }; + + + + + + + @Beta + public static ImmutableMultiset copyHighestCountFirst(Multiset multiset) + { + List> sortedEntries = DECREASING_COUNT_ORDERING.immutableSortedCopy(multiset.entrySet()); + + return ImmutableMultiset.copyFromEntries(sortedEntries); + } +} diff --git a/src/minecraft/com/google/common/collect/MutableClassToInstanceMap.java b/src/minecraft/com/google/common/collect/MutableClassToInstanceMap.java new file mode 100644 index 0000000..fae75e1 --- /dev/null +++ b/src/minecraft/com/google/common/collect/MutableClassToInstanceMap.java @@ -0,0 +1,84 @@ +package com.google.common.collect; + +import com.google.common.primitives.Primitives; +import java.util.HashMap; +import java.util.Map; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public final class MutableClassToInstanceMap + extends MapConstraints.ConstrainedMap, B> + implements ClassToInstanceMap +{ + public static MutableClassToInstanceMap create() + { + return new MutableClassToInstanceMap(new HashMap()); + } + + + + + + + + public static MutableClassToInstanceMap create(Map, B> backingMap) + { + return new MutableClassToInstanceMap(backingMap); + } + + private MutableClassToInstanceMap(Map, B> delegate) { + super(delegate, VALUE_CAN_BE_CAST_TO_KEY); + } + + private static final MapConstraint, Object> VALUE_CAN_BE_CAST_TO_KEY = new MapConstraint() + { + public void checkKeyValue(Class key, Object value) + { + MutableClassToInstanceMap.cast(key, value); + } + }; + private static final long serialVersionUID = 0L; + + public T putInstance(Class type, T value) { + return cast(type, put(type, value)); + } + + public T getInstance(Class type) + { + return cast(type, get(type)); + } + + private static T cast(Class type, B value) { + return Primitives.wrap(type).cast(value); + } +} diff --git a/src/minecraft/com/google/common/collect/NaturalOrdering.java b/src/minecraft/com/google/common/collect/NaturalOrdering.java new file mode 100644 index 0000000..e8049f4 --- /dev/null +++ b/src/minecraft/com/google/common/collect/NaturalOrdering.java @@ -0,0 +1,52 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.io.Serializable; + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true) +final class NaturalOrdering + extends Ordering + implements Serializable +{ + static final NaturalOrdering INSTANCE = new NaturalOrdering(); + private static final long serialVersionUID = 0L; + + public int compare(Comparable left, Comparable right) { Preconditions.checkNotNull(left); + Preconditions.checkNotNull(right); + return left.compareTo(right); + } + + public Ordering reverse() { + return ReverseNaturalOrdering.INSTANCE; + } + + private Object readResolve() + { + return INSTANCE; + } + + public String toString() { + return "Ordering.natural()"; + } + + private NaturalOrdering() {} +} diff --git a/src/minecraft/com/google/common/collect/NullsFirstOrdering.java b/src/minecraft/com/google/common/collect/NullsFirstOrdering.java new file mode 100644 index 0000000..0cba4db --- /dev/null +++ b/src/minecraft/com/google/common/collect/NullsFirstOrdering.java @@ -0,0 +1,79 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.io.Serializable; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true) +final class NullsFirstOrdering + extends Ordering + implements Serializable +{ + final Ordering ordering; + private static final long serialVersionUID = 0L; + + NullsFirstOrdering(Ordering ordering) + { + this.ordering = ordering; + } + + public int compare(@Nullable T left, @Nullable T right) { + if (left == right) { + return 0; + } + if (left == null) { + return -1; + } + if (right == null) { + return 1; + } + return ordering.compare(left, right); + } + + public Ordering reverse() + { + return ordering.reverse().nullsLast(); + } + + public Ordering nullsFirst() + { + return this; + } + + public Ordering nullsLast() { + return ordering.nullsLast(); + } + + public boolean equals(@Nullable Object object) { + if (object == this) { + return true; + } + if ((object instanceof NullsFirstOrdering)) { + NullsFirstOrdering that = (NullsFirstOrdering)object; + return ordering.equals(ordering); + } + return false; + } + + public int hashCode() { + return ordering.hashCode() ^ 0x39153A74; + } + + public String toString() { + return ordering + ".nullsFirst()"; + } +} diff --git a/src/minecraft/com/google/common/collect/NullsLastOrdering.java b/src/minecraft/com/google/common/collect/NullsLastOrdering.java new file mode 100644 index 0000000..cec6e41 --- /dev/null +++ b/src/minecraft/com/google/common/collect/NullsLastOrdering.java @@ -0,0 +1,79 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.io.Serializable; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true) +final class NullsLastOrdering + extends Ordering + implements Serializable +{ + final Ordering ordering; + private static final long serialVersionUID = 0L; + + NullsLastOrdering(Ordering ordering) + { + this.ordering = ordering; + } + + public int compare(@Nullable T left, @Nullable T right) { + if (left == right) { + return 0; + } + if (left == null) { + return 1; + } + if (right == null) { + return -1; + } + return ordering.compare(left, right); + } + + public Ordering reverse() + { + return ordering.reverse().nullsFirst(); + } + + public Ordering nullsFirst() { + return ordering.nullsFirst(); + } + + public Ordering nullsLast() + { + return this; + } + + public boolean equals(@Nullable Object object) { + if (object == this) { + return true; + } + if ((object instanceof NullsLastOrdering)) { + NullsLastOrdering that = (NullsLastOrdering)object; + return ordering.equals(ordering); + } + return false; + } + + public int hashCode() { + return ordering.hashCode() ^ 0xC9177248; + } + + public String toString() { + return ordering + ".nullsLast()"; + } +} diff --git a/src/minecraft/com/google/common/collect/ObjectArrays.java b/src/minecraft/com/google/common/collect/ObjectArrays.java new file mode 100644 index 0000000..daa3213 --- /dev/null +++ b/src/minecraft/com/google/common/collect/ObjectArrays.java @@ -0,0 +1,244 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import java.lang.reflect.Array; +import java.util.Collection; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public final class ObjectArrays +{ + static final Object[] EMPTY_ARRAY = new Object[0]; + + + + + private ObjectArrays() {} + + + + + @GwtIncompatible("Array.newInstance(Class, int)") + public static T[] newArray(Class type, int length) + { + return (Object[])Array.newInstance(type, length); + } + + + + + + + + public static T[] newArray(T[] reference, int length) + { + return Platform.newArray(reference, length); + } + + + + + + + + @GwtIncompatible("Array.newInstance(Class, int)") + public static T[] concat(T[] first, T[] second, Class type) + { + T[] result = newArray(type, first.length + second.length); + System.arraycopy(first, 0, result, 0, first.length); + System.arraycopy(second, 0, result, first.length, second.length); + return result; + } + + + + + + + + + + public static T[] concat(@Nullable T element, T[] array) + { + T[] result = newArray(array, array.length + 1); + result[0] = element; + System.arraycopy(array, 0, result, 1, array.length); + return result; + } + + + + + + + + + + public static T[] concat(T[] array, @Nullable T element) + { + T[] result = arraysCopyOf(array, array.length + 1); + result[array.length] = element; + return result; + } + + static T[] arraysCopyOf(T[] original, int newLength) + { + T[] copy = newArray(original, newLength); + System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); + + return copy; + } + + + + + + + + + + + + + + + + + + + + + + + + + static T[] toArrayImpl(Collection c, T[] array) + { + int size = c.size(); + if (array.length < size) { + array = newArray(array, size); + } + fillArray(c, array); + if (array.length > size) { + array[size] = null; + } + return array; + } + + + + + + + + + + + + static T[] toArrayImpl(Object[] src, int offset, int len, T[] dst) + { + Preconditions.checkPositionIndexes(offset, offset + len, src.length); + if (dst.length < len) { + dst = newArray(dst, len); + } else if (dst.length > len) { + dst[len] = null; + } + System.arraycopy(src, offset, dst, 0, len); + return dst; + } + + + + + + + + + + + + + + + static Object[] toArrayImpl(Collection c) + { + return fillArray(c, new Object[c.size()]); + } + + + + + static Object[] copyAsObjectArray(Object[] elements, int offset, int length) + { + Preconditions.checkPositionIndexes(offset, offset + length, elements.length); + if (length == 0) { + return EMPTY_ARRAY; + } + Object[] result = new Object[length]; + System.arraycopy(elements, offset, result, 0, length); + return result; + } + + private static Object[] fillArray(Iterable elements, Object[] array) { + int i = 0; + for (Object element : elements) { + array[(i++)] = element; + } + return array; + } + + + + static void swap(Object[] array, int i, int j) + { + Object temp = array[i]; + array[i] = array[j]; + array[j] = temp; + } + + static Object[] checkElementsNotNull(Object... array) { + return checkElementsNotNull(array, array.length); + } + + static Object[] checkElementsNotNull(Object[] array, int length) { + for (int i = 0; i < length; i++) { + checkElementNotNull(array[i], i); + } + return array; + } + + + static Object checkElementNotNull(Object element, int index) + { + if (element == null) { + throw new NullPointerException("at index " + index); + } + return element; + } +} diff --git a/src/minecraft/com/google/common/collect/Ordering.java b/src/minecraft/com/google/common/collect/Ordering.java new file mode 100644 index 0000000..21278fe --- /dev/null +++ b/src/minecraft/com/google/common/collect/Ordering.java @@ -0,0 +1,927 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.atomic.AtomicInteger; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public abstract class Ordering + implements Comparator +{ + static final int LEFT_IS_GREATER = 1; + static final int RIGHT_IS_GREATER = -1; + + @GwtCompatible(serializable=true) + public static Ordering natural() + { + return NaturalOrdering.INSTANCE; + } + + + + + + + + + + + + + + @GwtCompatible(serializable=true) + public static Ordering from(Comparator comparator) + { + return (comparator instanceof Ordering) ? (Ordering)comparator : new ComparatorOrdering(comparator); + } + + + + + + + @Deprecated + @GwtCompatible(serializable=true) + public static Ordering from(Ordering ordering) + { + return (Ordering)Preconditions.checkNotNull(ordering); + } + + + + + + + + + + + + + + + + + + + + + + @GwtCompatible(serializable=true) + public static Ordering explicit(List valuesInOrder) + { + return new ExplicitOrdering(valuesInOrder); + } + + + + + + + + + + + + + + + + + + + + + + + + + @GwtCompatible(serializable=true) + public static Ordering explicit(T leastValue, T... remainingValuesInOrder) + { + return explicit(Lists.asList(leastValue, remainingValuesInOrder)); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + @GwtCompatible(serializable=true) + public static Ordering allEqual() + { + return AllEqualOrdering.INSTANCE; + } + + + + + + + + @GwtCompatible(serializable=true) + public static Ordering usingToString() + { + return UsingToStringOrdering.INSTANCE; + } + + + + + + + + + + + + + + + + + + + public static Ordering arbitrary() { return ArbitraryOrderingHolder.ARBITRARY_ORDERING; } + + protected Ordering() {} + private static class ArbitraryOrderingHolder { private ArbitraryOrderingHolder() {} + static final Ordering ARBITRARY_ORDERING = new Ordering.ArbitraryOrdering(); + + } + @VisibleForTesting + static class ArbitraryOrdering extends Ordering { private Map uids = Platform.tryWeakKeys(new MapMaker()).makeComputingMap(new Function() + { + + + final AtomicInteger counter = new AtomicInteger(0); + + public Integer apply(Object from) { + return Integer.valueOf(counter.getAndIncrement()); + } + }); + + + + + ArbitraryOrdering() {} + + + + + public int compare(Object left, Object right) + { + if (left == right) + return 0; + if (left == null) + return -1; + if (right == null) { + return 1; + } + int leftCode = identityHashCode(left); + int rightCode = identityHashCode(right); + if (leftCode != rightCode) { + return leftCode < rightCode ? -1 : 1; + } + + + int result = ((Integer)uids.get(left)).compareTo((Integer)uids.get(right)); + if (result == 0) { + throw new AssertionError(); + } + return result; + } + + public String toString() { + return "Ordering.arbitrary()"; + } + + + + + + + + + int identityHashCode(Object object) + { + return System.identityHashCode(object); + } + } + + + + + + + + + + + + + + + + + @GwtCompatible(serializable=true) + public Ordering reverse() + { + return new ReverseOrdering(this); + } + + + + + + + @GwtCompatible(serializable=true) + public Ordering nullsFirst() + { + return new NullsFirstOrdering(this); + } + + + + + + + @GwtCompatible(serializable=true) + public Ordering nullsLast() + { + return new NullsLastOrdering(this); + } + + + + + + + + + + @GwtCompatible(serializable=true) + public Ordering onResultOf(Function function) + { + return new ByFunctionOrdering(function, this); + } + + Ordering> onKeys() { + return onResultOf(Maps.keyFunction()); + } + + + + + + + + + + + + + @GwtCompatible(serializable=true) + public Ordering compound(Comparator secondaryComparator) + { + return new CompoundOrdering(this, (Comparator)Preconditions.checkNotNull(secondaryComparator)); + } + + + + + + + + + + + + + + + + + @GwtCompatible(serializable=true) + public static Ordering compound(Iterable> comparators) + { + return new CompoundOrdering(comparators); + } + + + + + + + + + + + + + + + + + + + + + + + + + @GwtCompatible(serializable=true) + public Ordering> lexicographical() + { + return new LexicographicalOrdering(this); + } + + + + + + + + + + public abstract int compare(@Nullable T paramT1, @Nullable T paramT2); + + + + + + + + + + public E min(Iterator iterator) + { + E minSoFar = iterator.next(); + + while (iterator.hasNext()) { + minSoFar = min(minSoFar, iterator.next()); + } + + return minSoFar; + } + + + + + + + + + + public E min(Iterable iterable) + { + return min(iterable.iterator()); + } + + + + + + + + + + + + + + public E min(@Nullable E a, @Nullable E b) + { + return compare(a, b) <= 0 ? a : b; + } + + + + + + + + + + + + + public E min(@Nullable E a, @Nullable E b, @Nullable E c, E... rest) + { + E minSoFar = min(min(a, b), c); + + for (E r : rest) { + minSoFar = min(minSoFar, r); + } + + return minSoFar; + } + + + + + + + + + + + + + + + public E max(Iterator iterator) + { + E maxSoFar = iterator.next(); + + while (iterator.hasNext()) { + maxSoFar = max(maxSoFar, iterator.next()); + } + + return maxSoFar; + } + + + + + + + + + + public E max(Iterable iterable) + { + return max(iterable.iterator()); + } + + + + + + + + + + + + + + public E max(@Nullable E a, @Nullable E b) + { + return compare(a, b) >= 0 ? a : b; + } + + + + + + + + + + + + + public E max(@Nullable E a, @Nullable E b, @Nullable E c, E... rest) + { + E maxSoFar = max(max(a, b), c); + + for (E r : rest) { + maxSoFar = max(maxSoFar, r); + } + + return maxSoFar; + } + + + + + + + + + + + + + + + public List leastOf(Iterable iterable, int k) + { + if ((iterable instanceof Collection)) { + Collection collection = (Collection)iterable; + if (collection.size() <= 2L * k) + { + + + + + E[] array = (Object[])collection.toArray(); + Arrays.sort(array, this); + if (array.length > k) { + array = ObjectArrays.arraysCopyOf(array, k); + } + return Collections.unmodifiableList(Arrays.asList(array)); + } + } + return leastOf(iterable.iterator(), k); + } + + + + + + + + + + + + + + + public List leastOf(Iterator elements, int k) + { + Preconditions.checkNotNull(elements); + CollectPreconditions.checkNonnegative(k, "k"); + + if ((k == 0) || (!elements.hasNext())) + return ImmutableList.of(); + if (k >= 1073741823) + { + ArrayList list = Lists.newArrayList(elements); + Collections.sort(list, this); + if (list.size() > k) { + list.subList(k, list.size()).clear(); + } + list.trimToSize(); + return Collections.unmodifiableList(list); + } + + + + + + + + + + + + + + + + int bufferCap = k * 2; + + E[] buffer = (Object[])new Object[bufferCap]; + E threshold = elements.next(); + buffer[0] = threshold; + int bufferSize = 1; + + + + while ((bufferSize < k) && (elements.hasNext())) { + E e = elements.next(); + buffer[(bufferSize++)] = e; + threshold = max(threshold, e); + } + + while (elements.hasNext()) { + E e = elements.next(); + if (compare(e, threshold) < 0) + { + + + buffer[(bufferSize++)] = e; + if (bufferSize == bufferCap) + { + + int left = 0; + int right = bufferCap - 1; + + int minThresholdPosition = 0; + + + + while (left < right) { + int pivotIndex = left + right + 1 >>> 1; + int pivotNewIndex = partition(buffer, left, right, pivotIndex); + if (pivotNewIndex > k) { + right = pivotNewIndex - 1; + } else { if (pivotNewIndex >= k) break; + left = Math.max(pivotNewIndex, left + 1); + minThresholdPosition = pivotNewIndex; + } + } + + + bufferSize = k; + + threshold = buffer[minThresholdPosition]; + for (int i = minThresholdPosition + 1; i < bufferSize; i++) { + threshold = max(threshold, buffer[i]); + } + } + } + } + Arrays.sort(buffer, 0, bufferSize, this); + + bufferSize = Math.min(bufferSize, k); + return Collections.unmodifiableList(Arrays.asList(ObjectArrays.arraysCopyOf(buffer, bufferSize))); + } + + + + private int partition(E[] values, int left, int right, int pivotIndex) + { + E pivotValue = values[pivotIndex]; + + values[pivotIndex] = values[right]; + values[right] = pivotValue; + + int storeIndex = left; + for (int i = left; i < right; i++) { + if (compare(values[i], pivotValue) < 0) { + ObjectArrays.swap(values, storeIndex, i); + storeIndex++; + } + } + ObjectArrays.swap(values, right, storeIndex); + return storeIndex; + } + + + + + + + + + + + + + + + + + public List greatestOf(Iterable iterable, int k) + { + return reverse().leastOf(iterable, k); + } + + + + + + + + + + + + + + + public List greatestOf(Iterator iterator, int k) + { + return reverse().leastOf(iterator, k); + } + + + + + + + + + + + + + + + + + + + + public List sortedCopy(Iterable elements) + { + E[] array = (Object[])Iterables.toArray(elements); + Arrays.sort(array, this); + return Lists.newArrayList(Arrays.asList(array)); + } + + + + + + + + + + + + + + + + + + + + + public ImmutableList immutableSortedCopy(Iterable elements) + { + E[] array = (Object[])Iterables.toArray(elements); + for (E e : array) { + Preconditions.checkNotNull(e); + } + Arrays.sort(array, this); + return ImmutableList.asImmutableList(array); + } + + + + + + + public boolean isOrdered(Iterable iterable) + { + Iterator it = iterable.iterator(); + if (it.hasNext()) { + T prev = it.next(); + while (it.hasNext()) { + T next = it.next(); + if (compare(prev, next) > 0) { + return false; + } + prev = next; + } + } + return true; + } + + + + + + + public boolean isStrictlyOrdered(Iterable iterable) + { + Iterator it = iterable.iterator(); + if (it.hasNext()) { + T prev = it.next(); + while (it.hasNext()) { + T next = it.next(); + if (compare(prev, next) >= 0) { + return false; + } + prev = next; + } + } + return true; + } + + + + + + + + + public int binarySearch(List sortedList, @Nullable T key) + { + return Collections.binarySearch(sortedList, key, this); + } + + + @VisibleForTesting + static class IncomparableValueException + extends ClassCastException + { + final Object value; + + private static final long serialVersionUID = 0L; + + + IncomparableValueException(Object value) + { + super(); + this.value = value; + } + } +} diff --git a/src/minecraft/com/google/common/collect/PeekingIterator.java b/src/minecraft/com/google/common/collect/PeekingIterator.java new file mode 100644 index 0000000..307ea04 --- /dev/null +++ b/src/minecraft/com/google/common/collect/PeekingIterator.java @@ -0,0 +1,15 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Iterator; + +@GwtCompatible +public abstract interface PeekingIterator + extends Iterator +{ + public abstract E peek(); + + public abstract E next(); + + public abstract void remove(); +} diff --git a/src/minecraft/com/google/common/collect/Platform.java b/src/minecraft/com/google/common/collect/Platform.java new file mode 100644 index 0000000..0a07fba --- /dev/null +++ b/src/minecraft/com/google/common/collect/Platform.java @@ -0,0 +1,99 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import java.lang.reflect.Array; +import java.util.Collections; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NavigableMap; +import java.util.NavigableSet; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +final class Platform +{ + static T[] newArray(T[] reference, int length) + { + Class type = reference.getClass().getComponentType(); + + + + + T[] result = (Object[])Array.newInstance(type, length); + return result; + } + + static Set newSetFromMap(Map map) { + return Collections.newSetFromMap(map); + } + + + + + + + static MapMaker tryWeakKeys(MapMaker mapMaker) + { + return mapMaker.weakKeys(); + } + + + static SortedMap mapsTransformEntriesSortedMap(SortedMap fromMap, Maps.EntryTransformer transformer) + { + return (fromMap instanceof NavigableMap) ? Maps.transformEntries((NavigableMap)fromMap, transformer) : Maps.transformEntriesIgnoreNavigable(fromMap, transformer); + } + + + + static SortedMap mapsAsMapSortedSet(SortedSet set, Function function) + { + return (set instanceof NavigableSet) ? Maps.asMap((NavigableSet)set, function) : Maps.asMapSortedIgnoreNavigable(set, function); + } + + + + static SortedSet setsFilterSortedSet(SortedSet set, Predicate predicate) + { + return (set instanceof NavigableSet) ? Sets.filter((NavigableSet)set, predicate) : Sets.filterSortedIgnoreNavigable(set, predicate); + } + + + + static SortedMap mapsFilterSortedMap(SortedMap map, Predicate> predicate) + { + return (map instanceof NavigableMap) ? Maps.filterEntries((NavigableMap)map, predicate) : Maps.filterSortedIgnoreNavigable(map, predicate); + } + + private Platform() {} +} diff --git a/src/minecraft/com/google/common/collect/Queues.java b/src/minecraft/com/google/common/collect/Queues.java new file mode 100644 index 0000000..2a12bd3 --- /dev/null +++ b/src/minecraft/com/google/common/collect/Queues.java @@ -0,0 +1,399 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import java.util.ArrayDeque; +import java.util.Collection; +import java.util.Deque; +import java.util.PriorityQueue; +import java.util.Queue; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.PriorityBlockingQueue; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.TimeUnit; + + + + + + + + + + + + + + + + + + + + + + + + + + + +public final class Queues +{ + private Queues() {} + + public static ArrayBlockingQueue newArrayBlockingQueue(int capacity) + { + return new ArrayBlockingQueue(capacity); + } + + + + + + + + public static ArrayDeque newArrayDeque() + { + return new ArrayDeque(); + } + + + + + + + public static ArrayDeque newArrayDeque(Iterable elements) + { + if ((elements instanceof Collection)) { + return new ArrayDeque(Collections2.cast(elements)); + } + ArrayDeque deque = new ArrayDeque(); + Iterables.addAll(deque, elements); + return deque; + } + + + + + + public static ConcurrentLinkedQueue newConcurrentLinkedQueue() + { + return new ConcurrentLinkedQueue(); + } + + + + + + public static ConcurrentLinkedQueue newConcurrentLinkedQueue(Iterable elements) + { + if ((elements instanceof Collection)) { + return new ConcurrentLinkedQueue(Collections2.cast(elements)); + } + ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue(); + Iterables.addAll(queue, elements); + return queue; + } + + + + + + + + public static LinkedBlockingDeque newLinkedBlockingDeque() + { + return new LinkedBlockingDeque(); + } + + + + + + + public static LinkedBlockingDeque newLinkedBlockingDeque(int capacity) + { + return new LinkedBlockingDeque(capacity); + } + + + + + + + + public static LinkedBlockingDeque newLinkedBlockingDeque(Iterable elements) + { + if ((elements instanceof Collection)) { + return new LinkedBlockingDeque(Collections2.cast(elements)); + } + LinkedBlockingDeque deque = new LinkedBlockingDeque(); + Iterables.addAll(deque, elements); + return deque; + } + + + + + + public static LinkedBlockingQueue newLinkedBlockingQueue() + { + return new LinkedBlockingQueue(); + } + + + + + + public static LinkedBlockingQueue newLinkedBlockingQueue(int capacity) + { + return new LinkedBlockingQueue(capacity); + } + + + + + + + + + public static LinkedBlockingQueue newLinkedBlockingQueue(Iterable elements) + { + if ((elements instanceof Collection)) { + return new LinkedBlockingQueue(Collections2.cast(elements)); + } + LinkedBlockingQueue queue = new LinkedBlockingQueue(); + Iterables.addAll(queue, elements); + return queue; + } + + + + + + + + + + + public static PriorityBlockingQueue newPriorityBlockingQueue() + { + return new PriorityBlockingQueue(); + } + + + + + + + + + + public static PriorityBlockingQueue newPriorityBlockingQueue(Iterable elements) + { + if ((elements instanceof Collection)) { + return new PriorityBlockingQueue(Collections2.cast(elements)); + } + PriorityBlockingQueue queue = new PriorityBlockingQueue(); + Iterables.addAll(queue, elements); + return queue; + } + + + + + + + + + public static PriorityQueue newPriorityQueue() + { + return new PriorityQueue(); + } + + + + + + + + + + public static PriorityQueue newPriorityQueue(Iterable elements) + { + if ((elements instanceof Collection)) { + return new PriorityQueue(Collections2.cast(elements)); + } + PriorityQueue queue = new PriorityQueue(); + Iterables.addAll(queue, elements); + return queue; + } + + + + + + public static SynchronousQueue newSynchronousQueue() + { + return new SynchronousQueue(); + } + + + + + + + + + + + + + + @Beta + public static int drain(BlockingQueue q, Collection buffer, int numElements, long timeout, TimeUnit unit) + throws InterruptedException + { + Preconditions.checkNotNull(buffer); + + + + + + long deadline = System.nanoTime() + unit.toNanos(timeout); + int added = 0; + while (added < numElements) + { + + added += q.drainTo(buffer, numElements - added); + if (added < numElements) { + E e = q.poll(deadline - System.nanoTime(), TimeUnit.NANOSECONDS); + if (e == null) { + break; + } + buffer.add(e); + added++; + } + } + return added; + } + + + + + + + + + + + + + + + @Beta + public static int drainUninterruptibly(BlockingQueue q, Collection buffer, int numElements, long timeout, TimeUnit unit) + { + Preconditions.checkNotNull(buffer); + long deadline = System.nanoTime() + unit.toNanos(timeout); + int added = 0; + boolean interrupted = false; + try { + while (added < numElements) + { + + added += q.drainTo(buffer, numElements - added); + if (added < numElements) { + E e; + for (;;) { + try { + e = q.poll(deadline - System.nanoTime(), TimeUnit.NANOSECONDS); + } + catch (InterruptedException ex) { + interrupted = true; + } + } + if (e == null) { + break; + } + buffer.add(e); + added++; + } + } + } finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + return added; + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + @Beta + public static Queue synchronizedQueue(Queue queue) + { + return Synchronized.queue(queue, null); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + @Beta + public static Deque synchronizedDeque(Deque deque) + { + return Synchronized.deque(deque, null); + } +} diff --git a/src/minecraft/com/google/common/collect/Range.java b/src/minecraft/com/google/common/collect/Range.java new file mode 100644 index 0000000..e7ed76a --- /dev/null +++ b/src/minecraft/com/google/common/collect/Range.java @@ -0,0 +1,685 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import java.io.Serializable; +import java.util.Comparator; +import java.util.Iterator; +import java.util.SortedSet; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public final class Range + implements Predicate, Serializable +{ + private static final Function LOWER_BOUND_FN = new Function() + { + public Cut apply(Range range) { + return lowerBound; + } + }; + + static > Function, Cut> lowerBoundFn() + { + return LOWER_BOUND_FN; + } + + private static final Function UPPER_BOUND_FN = new Function() + { + public Cut apply(Range range) { + return upperBound; + } + }; + + static > Function, Cut> upperBoundFn() + { + return UPPER_BOUND_FN; + } + + static final Ordering> RANGE_LEX_ORDERING = new Ordering() + { + public int compare(Range left, Range right) { + return ComparisonChain.start().compare(lowerBound, lowerBound).compare(upperBound, upperBound).result(); + } + }; + + + + + static > Range create(Cut lowerBound, Cut upperBound) + { + return new Range(lowerBound, upperBound); + } + + + + + + + + + public static > Range open(C lower, C upper) + { + return create(Cut.aboveValue(lower), Cut.belowValue(upper)); + } + + + + + + + + + public static > Range closed(C lower, C upper) + { + return create(Cut.belowValue(lower), Cut.aboveValue(upper)); + } + + + + + + + + + + public static > Range closedOpen(C lower, C upper) + { + return create(Cut.belowValue(lower), Cut.belowValue(upper)); + } + + + + + + + + + + public static > Range openClosed(C lower, C upper) + { + return create(Cut.aboveValue(lower), Cut.aboveValue(upper)); + } + + + + + + + + + + + public static > Range range(C lower, BoundType lowerType, C upper, BoundType upperType) + { + Preconditions.checkNotNull(lowerType); + Preconditions.checkNotNull(upperType); + + Cut lowerBound = lowerType == BoundType.OPEN ? Cut.aboveValue(lower) : Cut.belowValue(lower); + + + Cut upperBound = upperType == BoundType.OPEN ? Cut.belowValue(upper) : Cut.aboveValue(upper); + + + return create(lowerBound, upperBound); + } + + + + + + + public static > Range lessThan(C endpoint) + { + return create(Cut.belowAll(), Cut.belowValue(endpoint)); + } + + + + + + + public static > Range atMost(C endpoint) + { + return create(Cut.belowAll(), Cut.aboveValue(endpoint)); + } + + + + + + + + public static > Range upTo(C endpoint, BoundType boundType) + { + switch (4.$SwitchMap$com$google$common$collect$BoundType[boundType.ordinal()]) { + case 1: + return lessThan(endpoint); + case 2: + return atMost(endpoint); + } + throw new AssertionError(); + } + + + + + + + + public static > Range greaterThan(C endpoint) + { + return create(Cut.aboveValue(endpoint), Cut.aboveAll()); + } + + + + + + + public static > Range atLeast(C endpoint) + { + return create(Cut.belowValue(endpoint), Cut.aboveAll()); + } + + + + + + + + public static > Range downTo(C endpoint, BoundType boundType) + { + switch (4.$SwitchMap$com$google$common$collect$BoundType[boundType.ordinal()]) { + case 1: + return greaterThan(endpoint); + case 2: + return atLeast(endpoint); + } + throw new AssertionError(); + } + + + private static final Range ALL = new Range(Cut.belowAll(), Cut.aboveAll()); + + final Cut lowerBound; + + final Cut upperBound; + + private static final long serialVersionUID = 0L; + + public static > Range all() + { + return ALL; + } + + + + + + + + public static > Range singleton(C value) + { + return closed(value, value); + } + + + + + + + + + + + + + public static > Range encloseAll(Iterable values) + { + Preconditions.checkNotNull(values); + if ((values instanceof ContiguousSet)) { + return ((ContiguousSet)values).range(); + } + Iterator valueIterator = values.iterator(); + C min = (Comparable)Preconditions.checkNotNull(valueIterator.next()); + C max = min; + while (valueIterator.hasNext()) { + C value = (Comparable)Preconditions.checkNotNull(valueIterator.next()); + min = (Comparable)Ordering.natural().min(min, value); + max = (Comparable)Ordering.natural().max(max, value); + } + return closed(min, max); + } + + + + private Range(Cut lowerBound, Cut upperBound) + { + if ((lowerBound.compareTo(upperBound) > 0) || (lowerBound == Cut.aboveAll()) || (upperBound == Cut.belowAll())) + { + throw new IllegalArgumentException("Invalid range: " + toString(lowerBound, upperBound)); + } + this.lowerBound = ((Cut)Preconditions.checkNotNull(lowerBound)); + this.upperBound = ((Cut)Preconditions.checkNotNull(upperBound)); + } + + + + public boolean hasLowerBound() + { + return lowerBound != Cut.belowAll(); + } + + + + + + + public C lowerEndpoint() + { + return lowerBound.endpoint(); + } + + + + + + + + public BoundType lowerBoundType() + { + return lowerBound.typeAsLowerBound(); + } + + + + public boolean hasUpperBound() + { + return upperBound != Cut.aboveAll(); + } + + + + + + + public C upperEndpoint() + { + return upperBound.endpoint(); + } + + + + + + + + public BoundType upperBoundType() + { + return upperBound.typeAsUpperBound(); + } + + + + + + + + + + public boolean isEmpty() + { + return lowerBound.equals(upperBound); + } + + + + + + public boolean contains(C value) + { + Preconditions.checkNotNull(value); + + return (lowerBound.isLessThan(value)) && (!upperBound.isLessThan(value)); + } + + + + + + @Deprecated + public boolean apply(C input) + { + return contains(input); + } + + + + + public boolean containsAll(Iterable values) + { + if (Iterables.isEmpty(values)) { + return true; + } + + + if ((values instanceof SortedSet)) { + SortedSet set = cast(values); + Comparator comparator = set.comparator(); + if ((Ordering.natural().equals(comparator)) || (comparator == null)) { + return (contains((Comparable)set.first())) && (contains((Comparable)set.last())); + } + } + + for (C value : values) { + if (!contains(value)) { + return false; + } + } + return true; + } + + + + + + + + + + + + + + + + + + + + + + + + + public boolean encloses(Range other) + { + return (lowerBound.compareTo(lowerBound) <= 0) && (upperBound.compareTo(upperBound) >= 0); + } + + + + + + + + + + + + + + + + + + + + + + + + + + public boolean isConnected(Range other) + { + return (lowerBound.compareTo(upperBound) <= 0) && (lowerBound.compareTo(upperBound) <= 0); + } + + + + + + + + + + + + + + + + + + public Range intersection(Range connectedRange) + { + int lowerCmp = lowerBound.compareTo(lowerBound); + int upperCmp = upperBound.compareTo(upperBound); + if ((lowerCmp >= 0) && (upperCmp <= 0)) + return this; + if ((lowerCmp <= 0) && (upperCmp >= 0)) { + return connectedRange; + } + Cut newLower = lowerCmp >= 0 ? lowerBound : lowerBound; + Cut newUpper = upperCmp <= 0 ? upperBound : upperBound; + return create(newLower, newUpper); + } + + + + + + + + + + + + + public Range span(Range other) + { + int lowerCmp = lowerBound.compareTo(lowerBound); + int upperCmp = upperBound.compareTo(upperBound); + if ((lowerCmp <= 0) && (upperCmp >= 0)) + return this; + if ((lowerCmp >= 0) && (upperCmp <= 0)) { + return other; + } + Cut newLower = lowerCmp <= 0 ? lowerBound : lowerBound; + Cut newUpper = upperCmp >= 0 ? upperBound : upperBound; + return create(newLower, newUpper); + } + + + + + + + + + + + + + + + + + + + + + + + + + + public Range canonical(DiscreteDomain domain) + { + Preconditions.checkNotNull(domain); + Cut lower = lowerBound.canonical(domain); + Cut upper = upperBound.canonical(domain); + return (lower == lowerBound) && (upper == upperBound) ? this : create(lower, upper); + } + + + + + + + + public boolean equals(@Nullable Object object) + { + if ((object instanceof Range)) { + Range other = (Range)object; + return (lowerBound.equals(lowerBound)) && (upperBound.equals(upperBound)); + } + + return false; + } + + public int hashCode() + { + return lowerBound.hashCode() * 31 + upperBound.hashCode(); + } + + + + + public String toString() + { + return toString(lowerBound, upperBound); + } + + private static String toString(Cut lowerBound, Cut upperBound) { + StringBuilder sb = new StringBuilder(16); + lowerBound.describeAsLowerBound(sb); + sb.append('‥'); + upperBound.describeAsUpperBound(sb); + return sb.toString(); + } + + + + private static SortedSet cast(Iterable iterable) + { + return (SortedSet)iterable; + } + + Object readResolve() { + if (equals(ALL)) { + return all(); + } + return this; + } + + + static int compareOrThrow(Comparable left, Comparable right) + { + return left.compareTo(right); + } +} diff --git a/src/minecraft/com/google/common/collect/RangeMap.java b/src/minecraft/com/google/common/collect/RangeMap.java new file mode 100644 index 0000000..a8257f5 --- /dev/null +++ b/src/minecraft/com/google/common/collect/RangeMap.java @@ -0,0 +1,36 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import java.util.Map; +import java.util.Map.Entry; +import javax.annotation.Nullable; + +@Beta +public abstract interface RangeMap +{ + @Nullable + public abstract V get(K paramK); + + @Nullable + public abstract Map.Entry, V> getEntry(K paramK); + + public abstract Range span(); + + public abstract void put(Range paramRange, V paramV); + + public abstract void putAll(RangeMap paramRangeMap); + + public abstract void clear(); + + public abstract void remove(Range paramRange); + + public abstract Map, V> asMapOfRanges(); + + public abstract RangeMap subRangeMap(Range paramRange); + + public abstract boolean equals(@Nullable Object paramObject); + + public abstract int hashCode(); + + public abstract String toString(); +} diff --git a/src/minecraft/com/google/common/collect/RangeSet.java b/src/minecraft/com/google/common/collect/RangeSet.java new file mode 100644 index 0000000..47b459a --- /dev/null +++ b/src/minecraft/com/google/common/collect/RangeSet.java @@ -0,0 +1,43 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import java.util.Set; +import javax.annotation.Nullable; + +@Beta +public abstract interface RangeSet +{ + public abstract boolean contains(C paramC); + + public abstract Range rangeContaining(C paramC); + + public abstract boolean encloses(Range paramRange); + + public abstract boolean enclosesAll(RangeSet paramRangeSet); + + public abstract boolean isEmpty(); + + public abstract Range span(); + + public abstract Set> asRanges(); + + public abstract RangeSet complement(); + + public abstract RangeSet subRangeSet(Range paramRange); + + public abstract void add(Range paramRange); + + public abstract void remove(Range paramRange); + + public abstract void clear(); + + public abstract void addAll(RangeSet paramRangeSet); + + public abstract void removeAll(RangeSet paramRangeSet); + + public abstract boolean equals(@Nullable Object paramObject); + + public abstract int hashCode(); + + public abstract String toString(); +} diff --git a/src/minecraft/com/google/common/collect/RegularContiguousSet.java b/src/minecraft/com/google/common/collect/RegularContiguousSet.java new file mode 100644 index 0000000..319e32d --- /dev/null +++ b/src/minecraft/com/google/common/collect/RegularContiguousSet.java @@ -0,0 +1,197 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.Collection; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +final class RegularContiguousSet + extends ContiguousSet +{ + private final Range range; + private static final long serialVersionUID = 0L; + + RegularContiguousSet(Range range, DiscreteDomain domain) + { + super(domain); + this.range = range; + } + + private ContiguousSet intersectionInCurrentDomain(Range other) { + return range.isConnected(other) ? ContiguousSet.create(range.intersection(other), domain) : new EmptyContiguousSet(domain); + } + + + ContiguousSet headSetImpl(C toElement, boolean inclusive) + { + return intersectionInCurrentDomain(Range.upTo(toElement, BoundType.forBoolean(inclusive))); + } + + ContiguousSet subSetImpl(C fromElement, boolean fromInclusive, C toElement, boolean toInclusive) + { + if ((fromElement.compareTo(toElement) == 0) && (!fromInclusive) && (!toInclusive)) + { + return new EmptyContiguousSet(domain); + } + return intersectionInCurrentDomain(Range.range(fromElement, BoundType.forBoolean(fromInclusive), toElement, BoundType.forBoolean(toInclusive))); + } + + + ContiguousSet tailSetImpl(C fromElement, boolean inclusive) + { + return intersectionInCurrentDomain(Range.downTo(fromElement, BoundType.forBoolean(inclusive))); + } + + @GwtIncompatible("not used by GWT emulation") + int indexOf(Object target) { + return contains(target) ? (int)domain.distance(first(), (Comparable)target) : -1; + } + + public UnmodifiableIterator iterator() { + new AbstractSequentialIterator(first()) { + final C last = last(); + + protected C computeNext(C previous) + { + return RegularContiguousSet.equalsOrThrow(previous, last) ? null : domain.next(previous); + } + }; + } + + @GwtIncompatible("NavigableSet") + public UnmodifiableIterator descendingIterator() { + new AbstractSequentialIterator(last()) { + final C first = first(); + + protected C computeNext(C previous) + { + return RegularContiguousSet.equalsOrThrow(previous, first) ? null : domain.previous(previous); + } + }; + } + + private static boolean equalsOrThrow(Comparable left, @Nullable Comparable right) { + return (right != null) && (Range.compareOrThrow(left, right) == 0); + } + + boolean isPartialView() { + return false; + } + + public C first() { + return range.lowerBound.leastValueAbove(domain); + } + + public C last() { + return range.upperBound.greatestValueBelow(domain); + } + + public int size() { + long distance = domain.distance(first(), last()); + return distance >= 2147483647L ? Integer.MAX_VALUE : (int)distance + 1; + } + + public boolean contains(@Nullable Object object) { + if (object == null) { + return false; + } + try { + return range.contains((Comparable)object); + } catch (ClassCastException e) {} + return false; + } + + public boolean containsAll(Collection targets) + { + return Collections2.containsAllImpl(this, targets); + } + + public boolean isEmpty() { + return false; + } + + public ContiguousSet intersection(ContiguousSet other) { + Preconditions.checkNotNull(other); + Preconditions.checkArgument(domain.equals(domain)); + if (other.isEmpty()) { + return other; + } + C lowerEndpoint = (Comparable)Ordering.natural().max(first(), other.first()); + C upperEndpoint = (Comparable)Ordering.natural().min(last(), other.last()); + return lowerEndpoint.compareTo(upperEndpoint) < 0 ? ContiguousSet.create(Range.closed(lowerEndpoint, upperEndpoint), domain) : new EmptyContiguousSet(domain); + } + + + + public Range range() + { + return range(BoundType.CLOSED, BoundType.CLOSED); + } + + public Range range(BoundType lowerBoundType, BoundType upperBoundType) { + return Range.create(range.lowerBound.withLowerBoundType(lowerBoundType, domain), range.upperBound.withUpperBoundType(upperBoundType, domain)); + } + + public boolean equals(@Nullable Object object) + { + if (object == this) + return true; + if ((object instanceof RegularContiguousSet)) { + RegularContiguousSet that = (RegularContiguousSet)object; + if (domain.equals(domain)) { + return (first().equals(that.first())) && (last().equals(that.last())); + } + } + + return super.equals(object); + } + + public int hashCode() + { + return Sets.hashCodeImpl(this); + } + + @GwtIncompatible("serialization") + private static final class SerializedForm implements Serializable { + final Range range; + final DiscreteDomain domain; + + private SerializedForm(Range range, DiscreteDomain domain) { + this.range = range; + this.domain = domain; + } + + private Object readResolve() { + return new RegularContiguousSet(range, domain); + } + } + + @GwtIncompatible("serialization") + Object writeReplace() { + return new SerializedForm(range, domain, null); + } +} diff --git a/src/minecraft/com/google/common/collect/RegularImmutableAsList.java b/src/minecraft/com/google/common/collect/RegularImmutableAsList.java new file mode 100644 index 0000000..f154ba0 --- /dev/null +++ b/src/minecraft/com/google/common/collect/RegularImmutableAsList.java @@ -0,0 +1,68 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +class RegularImmutableAsList + extends ImmutableAsList +{ + private final ImmutableCollection delegate; + private final ImmutableList delegateList; + + RegularImmutableAsList(ImmutableCollection delegate, ImmutableList delegateList) + { + this.delegate = delegate; + this.delegateList = delegateList; + } + + RegularImmutableAsList(ImmutableCollection delegate, Object[] array) { + this(delegate, ImmutableList.asImmutableList(array)); + } + + ImmutableCollection delegateCollection() + { + return delegate; + } + + ImmutableList delegateList() { + return delegateList; + } + + + public UnmodifiableListIterator listIterator(int index) + { + return delegateList.listIterator(index); + } + + @GwtIncompatible("not present in emulated superclass") + int copyIntoArray(Object[] dst, int offset) + { + return delegateList.copyIntoArray(dst, offset); + } + + public E get(int index) + { + return delegateList.get(index); + } +} diff --git a/src/minecraft/com/google/common/collect/RegularImmutableBiMap.java b/src/minecraft/com/google/common/collect/RegularImmutableBiMap.java new file mode 100644 index 0000000..9dfc848 --- /dev/null +++ b/src/minecraft/com/google/common/collect/RegularImmutableBiMap.java @@ -0,0 +1,342 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.io.Serializable; +import java.util.Map.Entry; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +class RegularImmutableBiMap + extends ImmutableBiMap +{ + static final double MAX_LOAD_FACTOR = 1.2D; + private final transient ImmutableMapEntry[] keyTable; + private final transient ImmutableMapEntry[] valueTable; + private final transient ImmutableMapEntry[] entries; + private final transient int mask; + private final transient int hashCode; + private transient ImmutableBiMap inverse; + + RegularImmutableBiMap(ImmutableMapEntry.TerminalEntry... entriesToAdd) + { + this(entriesToAdd.length, entriesToAdd); + } + + + + + + + RegularImmutableBiMap(int n, ImmutableMapEntry.TerminalEntry[] entriesToAdd) + { + int tableSize = Hashing.closedTableSize(n, 1.2D); + mask = (tableSize - 1); + ImmutableMapEntry[] keyTable = createEntryArray(tableSize); + ImmutableMapEntry[] valueTable = createEntryArray(tableSize); + ImmutableMapEntry[] entries = createEntryArray(n); + int hashCode = 0; + + for (int i = 0; i < n; i++) + { + ImmutableMapEntry.TerminalEntry entry = entriesToAdd[i]; + K key = entry.getKey(); + V value = entry.getValue(); + + int keyHash = key.hashCode(); + int valueHash = value.hashCode(); + int keyBucket = Hashing.smear(keyHash) & mask; + int valueBucket = Hashing.smear(valueHash) & mask; + + ImmutableMapEntry nextInKeyBucket = keyTable[keyBucket]; + for (ImmutableMapEntry keyEntry = nextInKeyBucket; keyEntry != null; + keyEntry = keyEntry.getNextInKeyBucket()) { + checkNoConflict(!key.equals(keyEntry.getKey()), "key", entry, keyEntry); + } + ImmutableMapEntry nextInValueBucket = valueTable[valueBucket]; + for (ImmutableMapEntry valueEntry = nextInValueBucket; valueEntry != null; + valueEntry = valueEntry.getNextInValueBucket()) { + checkNoConflict(!value.equals(valueEntry.getValue()), "value", entry, valueEntry); + } + ImmutableMapEntry newEntry = (nextInKeyBucket == null) && (nextInValueBucket == null) ? entry : new NonTerminalBiMapEntry(entry, nextInKeyBucket, nextInValueBucket); + + + + keyTable[keyBucket] = newEntry; + valueTable[valueBucket] = newEntry; + entries[i] = newEntry; + hashCode += (keyHash ^ valueHash); + } + + this.keyTable = keyTable; + this.valueTable = valueTable; + this.entries = entries; + this.hashCode = hashCode; + } + + + + RegularImmutableBiMap(Map.Entry[] entriesToAdd) + { + int n = entriesToAdd.length; + int tableSize = Hashing.closedTableSize(n, 1.2D); + mask = (tableSize - 1); + ImmutableMapEntry[] keyTable = createEntryArray(tableSize); + ImmutableMapEntry[] valueTable = createEntryArray(tableSize); + ImmutableMapEntry[] entries = createEntryArray(n); + int hashCode = 0; + + for (int i = 0; i < n; i++) + { + Map.Entry entry = entriesToAdd[i]; + K key = entry.getKey(); + V value = entry.getValue(); + CollectPreconditions.checkEntryNotNull(key, value); + int keyHash = key.hashCode(); + int valueHash = value.hashCode(); + int keyBucket = Hashing.smear(keyHash) & mask; + int valueBucket = Hashing.smear(valueHash) & mask; + + ImmutableMapEntry nextInKeyBucket = keyTable[keyBucket]; + for (ImmutableMapEntry keyEntry = nextInKeyBucket; keyEntry != null; + keyEntry = keyEntry.getNextInKeyBucket()) { + checkNoConflict(!key.equals(keyEntry.getKey()), "key", entry, keyEntry); + } + ImmutableMapEntry nextInValueBucket = valueTable[valueBucket]; + for (ImmutableMapEntry valueEntry = nextInValueBucket; valueEntry != null; + valueEntry = valueEntry.getNextInValueBucket()) { + checkNoConflict(!value.equals(valueEntry.getValue()), "value", entry, valueEntry); + } + ImmutableMapEntry newEntry = (nextInKeyBucket == null) && (nextInValueBucket == null) ? new ImmutableMapEntry.TerminalEntry(key, value) : new NonTerminalBiMapEntry(key, value, nextInKeyBucket, nextInValueBucket); + + + + keyTable[keyBucket] = newEntry; + valueTable[valueBucket] = newEntry; + entries[i] = newEntry; + hashCode += (keyHash ^ valueHash); + } + + this.keyTable = keyTable; + this.valueTable = valueTable; + this.entries = entries; + this.hashCode = hashCode; + } + + private static final class NonTerminalBiMapEntry extends ImmutableMapEntry { + @Nullable + private final ImmutableMapEntry nextInKeyBucket; + @Nullable + private final ImmutableMapEntry nextInValueBucket; + + NonTerminalBiMapEntry(K key, V value, @Nullable ImmutableMapEntry nextInKeyBucket, @Nullable ImmutableMapEntry nextInValueBucket) { super(value); + this.nextInKeyBucket = nextInKeyBucket; + this.nextInValueBucket = nextInValueBucket; + } + + + NonTerminalBiMapEntry(ImmutableMapEntry contents, @Nullable ImmutableMapEntry nextInKeyBucket, @Nullable ImmutableMapEntry nextInValueBucket) + { + super(); + this.nextInKeyBucket = nextInKeyBucket; + this.nextInValueBucket = nextInValueBucket; + } + + @Nullable + ImmutableMapEntry getNextInKeyBucket() + { + return nextInKeyBucket; + } + + @Nullable + ImmutableMapEntry getNextInValueBucket() + { + return nextInValueBucket; + } + } + + private static ImmutableMapEntry[] createEntryArray(int length) + { + return new ImmutableMapEntry[length]; + } + + @Nullable + public V get(@Nullable Object key) + { + if (key == null) { + return null; + } + int bucket = Hashing.smear(key.hashCode()) & mask; + for (ImmutableMapEntry entry = keyTable[bucket]; entry != null; + entry = entry.getNextInKeyBucket()) { + if (key.equals(entry.getKey())) { + return entry.getValue(); + } + } + return null; + } + + ImmutableSet> createEntrySet() + { + new ImmutableMapEntrySet() + { + ImmutableMap map() { + return RegularImmutableBiMap.this; + } + + public UnmodifiableIterator> iterator() + { + return asList().iterator(); + } + + ImmutableList> createAsList() + { + return new RegularImmutableAsList(this, entries); + } + + boolean isHashCodeFast() + { + return true; + } + + public int hashCode() + { + return hashCode; + } + }; + } + + boolean isPartialView() + { + return false; + } + + public int size() + { + return entries.length; + } + + + + public ImmutableBiMap inverse() + { + ImmutableBiMap result = inverse; + return result == null ? (this.inverse = new Inverse(null)) : result; + } + + private final class Inverse extends ImmutableBiMap { + private Inverse() {} + + public int size() { + return inverse().size(); + } + + public ImmutableBiMap inverse() + { + return RegularImmutableBiMap.this; + } + + public K get(@Nullable Object value) + { + if (value == null) { + return null; + } + int bucket = Hashing.smear(value.hashCode()) & mask; + for (ImmutableMapEntry entry = valueTable[bucket]; entry != null; + entry = entry.getNextInValueBucket()) { + if (value.equals(entry.getValue())) { + return entry.getKey(); + } + } + return null; + } + + ImmutableSet> createEntrySet() + { + return new InverseEntrySet(); + } + + final class InverseEntrySet extends ImmutableMapEntrySet { + InverseEntrySet() {} + + ImmutableMap map() { return RegularImmutableBiMap.Inverse.this; } + + + boolean isHashCodeFast() + { + return true; + } + + public int hashCode() + { + return hashCode; + } + + public UnmodifiableIterator> iterator() + { + return asList().iterator(); + } + + ImmutableList> createAsList() + { + new ImmutableAsList() + { + public Map.Entry get(int index) { + Map.Entry entry = entries[index]; + return Maps.immutableEntry(entry.getValue(), entry.getKey()); + } + + ImmutableCollection> delegateCollection() + { + return RegularImmutableBiMap.Inverse.InverseEntrySet.this; + } + }; + } + } + + boolean isPartialView() + { + return false; + } + + Object writeReplace() + { + return new RegularImmutableBiMap.InverseSerializedForm(RegularImmutableBiMap.this); + } + } + + private static class InverseSerializedForm implements Serializable { + private final ImmutableBiMap forward; + private static final long serialVersionUID = 1L; + + InverseSerializedForm(ImmutableBiMap forward) { this.forward = forward; } + + Object readResolve() + { + return forward.inverse(); + } + } +} diff --git a/src/minecraft/com/google/common/collect/RegularImmutableList.java b/src/minecraft/com/google/common/collect/RegularImmutableList.java new file mode 100644 index 0000000..0265617 --- /dev/null +++ b/src/minecraft/com/google/common/collect/RegularImmutableList.java @@ -0,0 +1,108 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +class RegularImmutableList + extends ImmutableList +{ + private final transient int offset; + private final transient int size; + private final transient Object[] array; + + RegularImmutableList(Object[] array, int offset, int size) + { + this.offset = offset; + this.size = size; + this.array = array; + } + + RegularImmutableList(Object[] array) { + this(array, 0, array.length); + } + + public int size() + { + return size; + } + + boolean isPartialView() { + return size != array.length; + } + + int copyIntoArray(Object[] dst, int dstOff) + { + System.arraycopy(array, offset, dst, dstOff, size); + return dstOff + size; + } + + + + public E get(int index) + { + Preconditions.checkElementIndex(index, size); + return array[(index + offset)]; + } + + public int indexOf(@Nullable Object object) + { + if (object == null) { + return -1; + } + for (int i = 0; i < size; i++) { + if (array[(offset + i)].equals(object)) { + return i; + } + } + return -1; + } + + public int lastIndexOf(@Nullable Object object) + { + if (object == null) { + return -1; + } + for (int i = size - 1; i >= 0; i--) { + if (array[(offset + i)].equals(object)) { + return i; + } + } + return -1; + } + + ImmutableList subListUnchecked(int fromIndex, int toIndex) + { + return new RegularImmutableList(array, offset + fromIndex, toIndex - fromIndex); + } + + + + + + public UnmodifiableListIterator listIterator(int index) + { + return Iterators.forArray(array, offset, size, index); + } +} diff --git a/src/minecraft/com/google/common/collect/RegularImmutableMap.java b/src/minecraft/com/google/common/collect/RegularImmutableMap.java new file mode 100644 index 0000000..5937070 --- /dev/null +++ b/src/minecraft/com/google/common/collect/RegularImmutableMap.java @@ -0,0 +1,204 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Map.Entry; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +final class RegularImmutableMap + extends ImmutableMap +{ + private final transient ImmutableMapEntry[] entries; + private final transient ImmutableMapEntry[] table; + private final transient int mask; + private static final double MAX_LOAD_FACTOR = 1.2D; + private static final long serialVersionUID = 0L; + + RegularImmutableMap(ImmutableMapEntry.TerminalEntry... theEntries) + { + this(theEntries.length, theEntries); + } + + + + + + + RegularImmutableMap(int size, ImmutableMapEntry.TerminalEntry[] theEntries) + { + entries = createEntryArray(size); + int tableSize = Hashing.closedTableSize(size, 1.2D); + table = createEntryArray(tableSize); + mask = (tableSize - 1); + for (int entryIndex = 0; entryIndex < size; entryIndex++) + { + ImmutableMapEntry.TerminalEntry entry = theEntries[entryIndex]; + K key = entry.getKey(); + int tableIndex = Hashing.smear(key.hashCode()) & mask; + ImmutableMapEntry existing = table[tableIndex]; + + ImmutableMapEntry newEntry = existing == null ? entry : new NonTerminalMapEntry(entry, existing); + + + table[tableIndex] = newEntry; + entries[entryIndex] = newEntry; + checkNoConflictInBucket(key, newEntry, existing); + } + } + + + + RegularImmutableMap(Map.Entry[] theEntries) + { + int size = theEntries.length; + entries = createEntryArray(size); + int tableSize = Hashing.closedTableSize(size, 1.2D); + table = createEntryArray(tableSize); + mask = (tableSize - 1); + for (int entryIndex = 0; entryIndex < size; entryIndex++) + { + Map.Entry entry = theEntries[entryIndex]; + K key = entry.getKey(); + V value = entry.getValue(); + CollectPreconditions.checkEntryNotNull(key, value); + int tableIndex = Hashing.smear(key.hashCode()) & mask; + ImmutableMapEntry existing = table[tableIndex]; + + ImmutableMapEntry newEntry = existing == null ? new ImmutableMapEntry.TerminalEntry(key, value) : new NonTerminalMapEntry(key, value, existing); + + + table[tableIndex] = newEntry; + entries[entryIndex] = newEntry; + checkNoConflictInBucket(key, newEntry, existing); + } + } + + private void checkNoConflictInBucket(K key, ImmutableMapEntry entry, ImmutableMapEntry bucketHead) + { + for (; bucketHead != null; bucketHead = bucketHead.getNextInKeyBucket()) { + checkNoConflict(!key.equals(bucketHead.getKey()), "key", entry, bucketHead); + } + } + + private static final class NonTerminalMapEntry extends ImmutableMapEntry { + private final ImmutableMapEntry nextInKeyBucket; + + NonTerminalMapEntry(K key, V value, ImmutableMapEntry nextInKeyBucket) { + super(value); + this.nextInKeyBucket = nextInKeyBucket; + } + + NonTerminalMapEntry(ImmutableMapEntry contents, ImmutableMapEntry nextInKeyBucket) { + super(); + this.nextInKeyBucket = nextInKeyBucket; + } + + ImmutableMapEntry getNextInKeyBucket() + { + return nextInKeyBucket; + } + + @Nullable + ImmutableMapEntry getNextInValueBucket() + { + return null; + } + } + + + + + + + + + + + + + + + private ImmutableMapEntry[] createEntryArray(int size) + { + return new ImmutableMapEntry[size]; + } + + public V get(@Nullable Object key) { + if (key == null) { + return null; + } + int index = Hashing.smear(key.hashCode()) & mask; + for (ImmutableMapEntry entry = table[index]; + entry != null; + entry = entry.getNextInKeyBucket()) { + K candidateKey = entry.getKey(); + + + + + + + + if (key.equals(candidateKey)) { + return entry.getValue(); + } + } + return null; + } + + public int size() + { + return entries.length; + } + + boolean isPartialView() { + return false; + } + + ImmutableSet> createEntrySet() + { + return new EntrySet(null); + } + + private class EntrySet extends ImmutableMapEntrySet { + private EntrySet() {} + + ImmutableMap map() { return RegularImmutableMap.this; } + + + public UnmodifiableIterator> iterator() + { + return asList().iterator(); + } + + ImmutableList> createAsList() + { + return new RegularImmutableAsList(this, entries); + } + } +} diff --git a/src/minecraft/com/google/common/collect/RegularImmutableMultiset.java b/src/minecraft/com/google/common/collect/RegularImmutableMultiset.java new file mode 100644 index 0000000..664e430 --- /dev/null +++ b/src/minecraft/com/google/common/collect/RegularImmutableMultiset.java @@ -0,0 +1,79 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Map.Entry; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true) +class RegularImmutableMultiset + extends ImmutableMultiset +{ + private final transient ImmutableMap map; + private final transient int size; + + RegularImmutableMultiset(ImmutableMap map, int size) + { + this.map = map; + this.size = size; + } + + boolean isPartialView() + { + return map.isPartialView(); + } + + public int count(@Nullable Object element) + { + Integer value = (Integer)map.get(element); + return value == null ? 0 : value.intValue(); + } + + public int size() + { + return size; + } + + public boolean contains(@Nullable Object element) + { + return map.containsKey(element); + } + + public ImmutableSet elementSet() + { + return map.keySet(); + } + + Multiset.Entry getEntry(int index) + { + Map.Entry mapEntry = (Map.Entry)map.entrySet().asList().get(index); + return Multisets.immutableEntry(mapEntry.getKey(), ((Integer)mapEntry.getValue()).intValue()); + } + + public int hashCode() + { + return map.hashCode(); + } +} diff --git a/src/minecraft/com/google/common/collect/RegularImmutableSet.java b/src/minecraft/com/google/common/collect/RegularImmutableSet.java new file mode 100644 index 0000000..5dedf13 --- /dev/null +++ b/src/minecraft/com/google/common/collect/RegularImmutableSet.java @@ -0,0 +1,94 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.VisibleForTesting; + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +final class RegularImmutableSet + extends ImmutableSet +{ + private final Object[] elements; + @VisibleForTesting + final transient Object[] table; + private final transient int mask; + private final transient int hashCode; + + RegularImmutableSet(Object[] elements, int hashCode, Object[] table, int mask) + { + this.elements = elements; + this.table = table; + this.mask = mask; + this.hashCode = hashCode; + } + + public boolean contains(Object target) { + if (target == null) { + return false; + } + for (int i = Hashing.smear(target.hashCode());; i++) { + Object candidate = table[(i & mask)]; + if (candidate == null) { + return false; + } + if (candidate.equals(target)) { + return true; + } + } + } + + public int size() + { + return elements.length; + } + + + public UnmodifiableIterator iterator() + { + return Iterators.forArray(elements); + } + + int copyIntoArray(Object[] dst, int offset) + { + System.arraycopy(elements, 0, dst, offset, elements.length); + return offset + elements.length; + } + + ImmutableList createAsList() + { + return new RegularImmutableAsList(this, elements); + } + + boolean isPartialView() + { + return false; + } + + public int hashCode() { + return hashCode; + } + + boolean isHashCodeFast() { + return true; + } +} diff --git a/src/minecraft/com/google/common/collect/RegularImmutableSortedMap.java b/src/minecraft/com/google/common/collect/RegularImmutableSortedMap.java new file mode 100644 index 0000000..57dc6d7 --- /dev/null +++ b/src/minecraft/com/google/common/collect/RegularImmutableSortedMap.java @@ -0,0 +1,126 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.Map.Entry; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +final class RegularImmutableSortedMap + extends ImmutableSortedMap +{ + private final transient RegularImmutableSortedSet keySet; + private final transient ImmutableList valueList; + + RegularImmutableSortedMap(RegularImmutableSortedSet keySet, ImmutableList valueList) + { + this.keySet = keySet; + this.valueList = valueList; + } + + + + RegularImmutableSortedMap(RegularImmutableSortedSet keySet, ImmutableList valueList, ImmutableSortedMap descendingMap) + { + super(descendingMap); + this.keySet = keySet; + this.valueList = valueList; + } + + ImmutableSet> createEntrySet() + { + return new EntrySet(null); + } + + private class EntrySet extends ImmutableMapEntrySet { + private EntrySet() {} + + public UnmodifiableIterator> iterator() { return asList().iterator(); } + + + ImmutableList> createAsList() + { + new ImmutableAsList() + { + private final ImmutableList keyList = keySet().asList(); + + public Map.Entry get(int index) + { + return Maps.immutableEntry(keyList.get(index), valueList.get(index)); + } + + ImmutableCollection> delegateCollection() + { + return RegularImmutableSortedMap.EntrySet.this; + } + }; + } + + ImmutableMap map() + { + return RegularImmutableSortedMap.this; + } + } + + public ImmutableSortedSet keySet() + { + return keySet; + } + + public ImmutableCollection values() + { + return valueList; + } + + public V get(@Nullable Object key) + { + int index = keySet.indexOf(key); + return index == -1 ? null : valueList.get(index); + } + + private ImmutableSortedMap getSubMap(int fromIndex, int toIndex) { + if ((fromIndex == 0) && (toIndex == size())) + return this; + if (fromIndex == toIndex) { + return emptyMap(comparator()); + } + return from(keySet.getSubSet(fromIndex, toIndex), valueList.subList(fromIndex, toIndex)); + } + + + + + public ImmutableSortedMap headMap(K toKey, boolean inclusive) + { + return getSubMap(0, keySet.headIndex(Preconditions.checkNotNull(toKey), inclusive)); + } + + public ImmutableSortedMap tailMap(K fromKey, boolean inclusive) + { + return getSubMap(keySet.tailIndex(Preconditions.checkNotNull(fromKey), inclusive), size()); + } + + ImmutableSortedMap createDescendingMap() + { + return new RegularImmutableSortedMap((RegularImmutableSortedSet)keySet.descendingSet(), valueList.reverse(), this); + } +} diff --git a/src/minecraft/com/google/common/collect/RegularImmutableSortedMultiset.java b/src/minecraft/com/google/common/collect/RegularImmutableSortedMultiset.java new file mode 100644 index 0000000..0dcf505 --- /dev/null +++ b/src/minecraft/com/google/common/collect/RegularImmutableSortedMultiset.java @@ -0,0 +1,114 @@ +package com.google.common.collect; + +import com.google.common.base.Preconditions; +import com.google.common.primitives.Ints; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + +final class RegularImmutableSortedMultiset + extends ImmutableSortedMultiset +{ + private final transient RegularImmutableSortedSet elementSet; + private final transient int[] counts; + private final transient long[] cumulativeCounts; + private final transient int offset; + private final transient int length; + + RegularImmutableSortedMultiset(RegularImmutableSortedSet elementSet, int[] counts, long[] cumulativeCounts, int offset, int length) + { + this.elementSet = elementSet; + this.counts = counts; + this.cumulativeCounts = cumulativeCounts; + this.offset = offset; + this.length = length; + } + + Multiset.Entry getEntry(int index) + { + return Multisets.immutableEntry(elementSet.asList().get(index), counts[(offset + index)]); + } + + + + public Multiset.Entry firstEntry() + { + return getEntry(0); + } + + public Multiset.Entry lastEntry() + { + return getEntry(length - 1); + } + + public int count(@Nullable Object element) + { + int index = elementSet.indexOf(element); + return index == -1 ? 0 : counts[(index + offset)]; + } + + public int size() + { + long size = cumulativeCounts[(offset + length)] - cumulativeCounts[offset]; + return Ints.saturatedCast(size); + } + + public ImmutableSortedSet elementSet() + { + return elementSet; + } + + public ImmutableSortedMultiset headMultiset(E upperBound, BoundType boundType) + { + return getSubMultiset(0, elementSet.headIndex(upperBound, Preconditions.checkNotNull(boundType) == BoundType.CLOSED)); + } + + public ImmutableSortedMultiset tailMultiset(E lowerBound, BoundType boundType) + { + return getSubMultiset(elementSet.tailIndex(lowerBound, Preconditions.checkNotNull(boundType) == BoundType.CLOSED), length); + } + + ImmutableSortedMultiset getSubMultiset(int from, int to) + { + Preconditions.checkPositionIndexes(from, to, length); + if (from == to) + return emptyMultiset(comparator()); + if ((from == 0) && (to == length)) { + return this; + } + RegularImmutableSortedSet subElementSet = (RegularImmutableSortedSet)elementSet.getSubSet(from, to); + + return new RegularImmutableSortedMultiset(subElementSet, counts, cumulativeCounts, offset + from, to - from); + } + + + + boolean isPartialView() + { + return (offset > 0) || (length < counts.length); + } +} diff --git a/src/minecraft/com/google/common/collect/RegularImmutableSortedSet.java b/src/minecraft/com/google/common/collect/RegularImmutableSortedSet.java new file mode 100644 index 0000000..26169fd --- /dev/null +++ b/src/minecraft/com/google/common/collect/RegularImmutableSortedSet.java @@ -0,0 +1,290 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +final class RegularImmutableSortedSet + extends ImmutableSortedSet +{ + private final transient ImmutableList elements; + + RegularImmutableSortedSet(ImmutableList elements, Comparator comparator) + { + super(comparator); + this.elements = elements; + Preconditions.checkArgument(!elements.isEmpty()); + } + + public UnmodifiableIterator iterator() { + return elements.iterator(); + } + + @GwtIncompatible("NavigableSet") + public UnmodifiableIterator descendingIterator() { + return elements.reverse().iterator(); + } + + public boolean isEmpty() { + return false; + } + + public int size() + { + return elements.size(); + } + + public boolean contains(Object o) { + try { + return (o != null) && (unsafeBinarySearch(o) >= 0); + } catch (ClassCastException e) {} + return false; + } + + + + + + public boolean containsAll(Collection targets) + { + if ((targets instanceof Multiset)) { + targets = ((Multiset)targets).elementSet(); + } + if ((!SortedIterables.hasSameComparator(comparator(), targets)) || (targets.size() <= 1)) + { + return super.containsAll(targets); + } + + + + + + PeekingIterator thisIterator = Iterators.peekingIterator(iterator()); + Iterator thatIterator = targets.iterator(); + Object target = thatIterator.next(); + + try + { + while (thisIterator.hasNext()) + { + int cmp = unsafeCompare(thisIterator.peek(), target); + + if (cmp < 0) { + thisIterator.next(); + } else if (cmp == 0) + { + if (!thatIterator.hasNext()) + { + return true; + } + + target = thatIterator.next(); + } + else if (cmp > 0) { + return false; + } + } + } catch (NullPointerException e) { + return false; + } catch (ClassCastException e) { + return false; + } + + return false; + } + + private int unsafeBinarySearch(Object key) throws ClassCastException { + return Collections.binarySearch(elements, key, unsafeComparator()); + } + + boolean isPartialView() { + return elements.isPartialView(); + } + + int copyIntoArray(Object[] dst, int offset) + { + return elements.copyIntoArray(dst, offset); + } + + public boolean equals(@Nullable Object object) { + if (object == this) { + return true; + } + if (!(object instanceof Set)) { + return false; + } + + Set that = (Set)object; + if (size() != that.size()) { + return false; + } + + if (SortedIterables.hasSameComparator(comparator, that)) { + Iterator otherIterator = that.iterator(); + try { + Iterator iterator = iterator(); + while (iterator.hasNext()) { + Object element = iterator.next(); + Object otherElement = otherIterator.next(); + if ((otherElement == null) || (unsafeCompare(element, otherElement) != 0)) + { + return false; + } + } + return true; + } catch (ClassCastException e) { + return false; + } catch (NoSuchElementException e) { + return false; + } + } + return containsAll(that); + } + + public E first() + { + return elements.get(0); + } + + public E last() + { + return elements.get(size() - 1); + } + + public E lower(E element) + { + int index = headIndex(element, false) - 1; + return index == -1 ? null : elements.get(index); + } + + public E floor(E element) + { + int index = headIndex(element, true) - 1; + return index == -1 ? null : elements.get(index); + } + + public E ceiling(E element) + { + int index = tailIndex(element, true); + return index == size() ? null : elements.get(index); + } + + public E higher(E element) + { + int index = tailIndex(element, false); + return index == size() ? null : elements.get(index); + } + + ImmutableSortedSet headSetImpl(E toElement, boolean inclusive) + { + return getSubSet(0, headIndex(toElement, inclusive)); + } + + int headIndex(E toElement, boolean inclusive) { + return SortedLists.binarySearch(elements, Preconditions.checkNotNull(toElement), comparator(), inclusive ? SortedLists.KeyPresentBehavior.FIRST_AFTER : SortedLists.KeyPresentBehavior.FIRST_PRESENT, SortedLists.KeyAbsentBehavior.NEXT_HIGHER); + } + + + + + ImmutableSortedSet subSetImpl(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) + { + return tailSetImpl(fromElement, fromInclusive).headSetImpl(toElement, toInclusive); + } + + + ImmutableSortedSet tailSetImpl(E fromElement, boolean inclusive) + { + return getSubSet(tailIndex(fromElement, inclusive), size()); + } + + int tailIndex(E fromElement, boolean inclusive) { + return SortedLists.binarySearch(elements, Preconditions.checkNotNull(fromElement), comparator(), inclusive ? SortedLists.KeyPresentBehavior.FIRST_PRESENT : SortedLists.KeyPresentBehavior.FIRST_AFTER, SortedLists.KeyAbsentBehavior.NEXT_HIGHER); + } + + + + + + + + + Comparator unsafeComparator() + { + return comparator; + } + + ImmutableSortedSet getSubSet(int newFromIndex, int newToIndex) { + if ((newFromIndex == 0) && (newToIndex == size())) + return this; + if (newFromIndex < newToIndex) { + return new RegularImmutableSortedSet(elements.subList(newFromIndex, newToIndex), comparator); + } + + return emptySet(comparator); + } + + int indexOf(@Nullable Object target) + { + if (target == null) { + return -1; + } + int position; + try { + position = SortedLists.binarySearch(elements, target, unsafeComparator(), SortedLists.KeyPresentBehavior.ANY_PRESENT, SortedLists.KeyAbsentBehavior.INVERTED_INSERTION_INDEX); + } + catch (ClassCastException e) { + return -1; + } + return position >= 0 ? position : -1; + } + + ImmutableList createAsList() { + return new ImmutableSortedAsList(this, elements); + } + + ImmutableSortedSet createDescendingSet() + { + return new RegularImmutableSortedSet(elements.reverse(), Ordering.from(comparator).reverse()); + } +} diff --git a/src/minecraft/com/google/common/collect/RegularImmutableTable.java b/src/minecraft/com/google/common/collect/RegularImmutableTable.java new file mode 100644 index 0000000..821aad4 --- /dev/null +++ b/src/minecraft/com/google/common/collect/RegularImmutableTable.java @@ -0,0 +1,177 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +abstract class RegularImmutableTable + extends ImmutableTable +{ + RegularImmutableTable() {} + + abstract Table.Cell getCell(int paramInt); + + final ImmutableSet> createCellSet() { return isEmpty() ? ImmutableSet.of() : new CellSet(null); } + + abstract V getValue(int paramInt); + + private final class CellSet extends ImmutableSet> { private CellSet() {} + + public int size() { return RegularImmutableTable.this.size(); } + + + public UnmodifiableIterator> iterator() + { + return asList().iterator(); + } + + ImmutableList> createAsList() + { + new ImmutableAsList() + { + public Table.Cell get(int index) { + return getCell(index); + } + + ImmutableCollection> delegateCollection() + { + return RegularImmutableTable.CellSet.this; + } + }; + } + + public boolean contains(@Nullable Object object) + { + if ((object instanceof Table.Cell)) { + Table.Cell cell = (Table.Cell)object; + Object value = get(cell.getRowKey(), cell.getColumnKey()); + return (value != null) && (value.equals(cell.getValue())); + } + return false; + } + + boolean isPartialView() + { + return false; + } + } + + + + final ImmutableCollection createValues() + { + return isEmpty() ? ImmutableList.of() : new Values(null); + } + + private final class Values extends ImmutableList { + private Values() {} + + public int size() { return RegularImmutableTable.this.size(); } + + + public V get(int index) + { + return getValue(index); + } + + boolean isPartialView() + { + return true; + } + } + + + + static RegularImmutableTable forCells(List> cells, @Nullable Comparator rowComparator, @Nullable final Comparator columnComparator) + { + Preconditions.checkNotNull(cells); + if ((rowComparator != null) || (columnComparator != null)) + { + + + + + + + Comparator> comparator = new Comparator() { + public int compare(Table.Cell cell1, Table.Cell cell2) { + int rowCompare = val$rowComparator == null ? 0 : val$rowComparator.compare(cell1.getRowKey(), cell2.getRowKey()); + + if (rowCompare != 0) { + return rowCompare; + } + return columnComparator == null ? 0 : columnComparator.compare(cell1.getColumnKey(), cell2.getColumnKey()); + } + + }; + Collections.sort(cells, comparator); + } + return forCellsInternal(cells, rowComparator, columnComparator); + } + + static RegularImmutableTable forCells(Iterable> cells) + { + return forCellsInternal(cells, null, null); + } + + + + + + + + private static final RegularImmutableTable forCellsInternal(Iterable> cells, @Nullable Comparator rowComparator, @Nullable Comparator columnComparator) + { + ImmutableSet.Builder rowSpaceBuilder = ImmutableSet.builder(); + ImmutableSet.Builder columnSpaceBuilder = ImmutableSet.builder(); + ImmutableList> cellList = ImmutableList.copyOf(cells); + for (Table.Cell cell : cellList) { + rowSpaceBuilder.add(cell.getRowKey()); + columnSpaceBuilder.add(cell.getColumnKey()); + } + + ImmutableSet rowSpace = rowSpaceBuilder.build(); + if (rowComparator != null) { + List rowList = Lists.newArrayList(rowSpace); + Collections.sort(rowList, rowComparator); + rowSpace = ImmutableSet.copyOf(rowList); + } + ImmutableSet columnSpace = columnSpaceBuilder.build(); + if (columnComparator != null) { + List columnList = Lists.newArrayList(columnSpace); + Collections.sort(columnList, columnComparator); + columnSpace = ImmutableSet.copyOf(columnList); + } + + + + return cellList.size() > rowSpace.size() * columnSpace.size() / 2L ? new DenseImmutableTable(cellList, rowSpace, columnSpace) : new SparseImmutableTable(cellList, rowSpace, columnSpace); + } +} diff --git a/src/minecraft/com/google/common/collect/ReverseNaturalOrdering.java b/src/minecraft/com/google/common/collect/ReverseNaturalOrdering.java new file mode 100644 index 0000000..c30fa7c --- /dev/null +++ b/src/minecraft/com/google/common/collect/ReverseNaturalOrdering.java @@ -0,0 +1,90 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.Iterator; + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true) +final class ReverseNaturalOrdering + extends Ordering + implements Serializable +{ + static final ReverseNaturalOrdering INSTANCE = new ReverseNaturalOrdering(); + private static final long serialVersionUID = 0L; + + public int compare(Comparable left, Comparable right) { Preconditions.checkNotNull(left); + if (left == right) { + return 0; + } + + return right.compareTo(left); + } + + public Ordering reverse() { + return Ordering.natural(); + } + + + public E min(E a, E b) + { + return (Comparable)NaturalOrdering.INSTANCE.max(a, b); + } + + public E min(E a, E b, E c, E... rest) { + return (Comparable)NaturalOrdering.INSTANCE.max(a, b, c, rest); + } + + public E min(Iterator iterator) { + return (Comparable)NaturalOrdering.INSTANCE.max(iterator); + } + + public E min(Iterable iterable) { + return (Comparable)NaturalOrdering.INSTANCE.max(iterable); + } + + public E max(E a, E b) { + return (Comparable)NaturalOrdering.INSTANCE.min(a, b); + } + + public E max(E a, E b, E c, E... rest) { + return (Comparable)NaturalOrdering.INSTANCE.min(a, b, c, rest); + } + + public E max(Iterator iterator) { + return (Comparable)NaturalOrdering.INSTANCE.min(iterator); + } + + public E max(Iterable iterable) { + return (Comparable)NaturalOrdering.INSTANCE.min(iterable); + } + + private Object readResolve() + { + return INSTANCE; + } + + public String toString() { + return "Ordering.natural().reverse()"; + } + + private ReverseNaturalOrdering() {} +} diff --git a/src/minecraft/com/google/common/collect/ReverseOrdering.java b/src/minecraft/com/google/common/collect/ReverseOrdering.java new file mode 100644 index 0000000..0ff54fb --- /dev/null +++ b/src/minecraft/com/google/common/collect/ReverseOrdering.java @@ -0,0 +1,98 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.Iterator; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true) +final class ReverseOrdering + extends Ordering + implements Serializable +{ + final Ordering forwardOrder; + private static final long serialVersionUID = 0L; + + ReverseOrdering(Ordering forwardOrder) + { + this.forwardOrder = ((Ordering)Preconditions.checkNotNull(forwardOrder)); + } + + public int compare(T a, T b) { + return forwardOrder.compare(b, a); + } + + public Ordering reverse() + { + return forwardOrder; + } + + + public E min(E a, E b) + { + return forwardOrder.max(a, b); + } + + public E min(E a, E b, E c, E... rest) { + return forwardOrder.max(a, b, c, rest); + } + + public E min(Iterator iterator) { + return forwardOrder.max(iterator); + } + + public E min(Iterable iterable) { + return forwardOrder.max(iterable); + } + + public E max(E a, E b) { + return forwardOrder.min(a, b); + } + + public E max(E a, E b, E c, E... rest) { + return forwardOrder.min(a, b, c, rest); + } + + public E max(Iterator iterator) { + return forwardOrder.min(iterator); + } + + public E max(Iterable iterable) { + return forwardOrder.min(iterable); + } + + public int hashCode() { + return -forwardOrder.hashCode(); + } + + public boolean equals(@Nullable Object object) { + if (object == this) { + return true; + } + if ((object instanceof ReverseOrdering)) { + ReverseOrdering that = (ReverseOrdering)object; + return forwardOrder.equals(forwardOrder); + } + return false; + } + + public String toString() { + return forwardOrder + ".reverse()"; + } +} diff --git a/src/minecraft/com/google/common/collect/RowSortedTable.java b/src/minecraft/com/google/common/collect/RowSortedTable.java new file mode 100644 index 0000000..f3dd8f1 --- /dev/null +++ b/src/minecraft/com/google/common/collect/RowSortedTable.java @@ -0,0 +1,17 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import java.util.Map; +import java.util.SortedMap; +import java.util.SortedSet; + +@GwtCompatible +@Beta +public abstract interface RowSortedTable + extends Table +{ + public abstract SortedSet rowKeySet(); + + public abstract SortedMap> rowMap(); +} diff --git a/src/minecraft/com/google/common/collect/Serialization.java b/src/minecraft/com/google/common/collect/Serialization.java new file mode 100644 index 0000000..e1b5cb3 --- /dev/null +++ b/src/minecraft/com/google/common/collect/Serialization.java @@ -0,0 +1,231 @@ +package com.google.common.collect; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.lang.reflect.Field; +import java.util.Collection; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +final class Serialization +{ + private Serialization() {} + + static int readCount(ObjectInputStream stream) + throws IOException + { + return stream.readInt(); + } + + + + + + + + + static void writeMap(Map map, ObjectOutputStream stream) + throws IOException + { + stream.writeInt(map.size()); + for (Map.Entry entry : map.entrySet()) { + stream.writeObject(entry.getKey()); + stream.writeObject(entry.getValue()); + } + } + + + + + static void populateMap(Map map, ObjectInputStream stream) + throws IOException, ClassNotFoundException + { + int size = stream.readInt(); + populateMap(map, stream, size); + } + + + + + + static void populateMap(Map map, ObjectInputStream stream, int size) + throws IOException, ClassNotFoundException + { + for (int i = 0; i < size; i++) + { + K key = stream.readObject(); + + V value = stream.readObject(); + map.put(key, value); + } + } + + + + + + + + + static void writeMultiset(Multiset multiset, ObjectOutputStream stream) + throws IOException + { + int entryCount = multiset.entrySet().size(); + stream.writeInt(entryCount); + for (Multiset.Entry entry : multiset.entrySet()) { + stream.writeObject(entry.getElement()); + stream.writeInt(entry.getCount()); + } + } + + + + + + static void populateMultiset(Multiset multiset, ObjectInputStream stream) + throws IOException, ClassNotFoundException + { + int distinctElements = stream.readInt(); + populateMultiset(multiset, stream, distinctElements); + } + + + + + + + static void populateMultiset(Multiset multiset, ObjectInputStream stream, int distinctElements) + throws IOException, ClassNotFoundException + { + for (int i = 0; i < distinctElements; i++) + { + E element = stream.readObject(); + int count = stream.readInt(); + multiset.add(element, count); + } + } + + + + + + + + + + + static void writeMultimap(Multimap multimap, ObjectOutputStream stream) + throws IOException + { + stream.writeInt(multimap.asMap().size()); + for (Map.Entry> entry : multimap.asMap().entrySet()) { + stream.writeObject(entry.getKey()); + stream.writeInt(((Collection)entry.getValue()).size()); + for (V value : (Collection)entry.getValue()) { + stream.writeObject(value); + } + } + } + + + + + + static void populateMultimap(Multimap multimap, ObjectInputStream stream) + throws IOException, ClassNotFoundException + { + int distinctKeys = stream.readInt(); + populateMultimap(multimap, stream, distinctKeys); + } + + + + + + + static void populateMultimap(Multimap multimap, ObjectInputStream stream, int distinctKeys) + throws IOException, ClassNotFoundException + { + for (int i = 0; i < distinctKeys; i++) + { + K key = stream.readObject(); + Collection values = multimap.get(key); + int valueCount = stream.readInt(); + for (int j = 0; j < valueCount; j++) + { + V value = stream.readObject(); + values.add(value); + } + } + } + + static FieldSetter getFieldSetter(Class clazz, String fieldName) + { + try + { + Field field = clazz.getDeclaredField(fieldName); + return new FieldSetter(field, null); + } catch (NoSuchFieldException e) { + throw new AssertionError(e); + } + } + + static final class FieldSetter + { + private final Field field; + + private FieldSetter(Field field) { + this.field = field; + field.setAccessible(true); + } + + void set(T instance, Object value) { + try { + field.set(instance, value); + } catch (IllegalAccessException impossible) { + throw new AssertionError(impossible); + } + } + + void set(T instance, int value) { + try { + field.set(instance, Integer.valueOf(value)); + } catch (IllegalAccessException impossible) { + throw new AssertionError(impossible); + } + } + } +} diff --git a/src/minecraft/com/google/common/collect/SetMultimap.java b/src/minecraft/com/google/common/collect/SetMultimap.java new file mode 100644 index 0000000..e4514e7 --- /dev/null +++ b/src/minecraft/com/google/common/collect/SetMultimap.java @@ -0,0 +1,25 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Collection; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract interface SetMultimap + extends Multimap +{ + public abstract Set get(@Nullable K paramK); + + public abstract Set removeAll(@Nullable Object paramObject); + + public abstract Set replaceValues(K paramK, Iterable paramIterable); + + public abstract Set> entries(); + + public abstract Map> asMap(); + + public abstract boolean equals(@Nullable Object paramObject); +} diff --git a/src/minecraft/com/google/common/collect/Sets.java b/src/minecraft/com/google/common/collect/Sets.java new file mode 100644 index 0000000..3abc75c --- /dev/null +++ b/src/minecraft/com/google/common/collect/Sets.java @@ -0,0 +1,1698 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import java.io.Serializable; +import java.util.AbstractSet; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.NavigableSet; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArraySet; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public final class Sets +{ + private Sets() {} + + static abstract class ImprovedAbstractSet + extends AbstractSet + { + ImprovedAbstractSet() {} + + public boolean removeAll(Collection c) + { + return Sets.removeAllImpl(this, c); + } + + public boolean retainAll(Collection c) + { + return super.retainAll((Collection)Preconditions.checkNotNull(c)); + } + } + + + + + + + + + + + + + + @GwtCompatible(serializable=true) + public static > ImmutableSet immutableEnumSet(E anElement, E... otherElements) + { + return ImmutableEnumSet.asImmutable(EnumSet.of(anElement, otherElements)); + } + + + + + + + + + + + + + + @GwtCompatible(serializable=true) + public static > ImmutableSet immutableEnumSet(Iterable elements) + { + if ((elements instanceof ImmutableEnumSet)) + return (ImmutableEnumSet)elements; + if ((elements instanceof Collection)) { + Collection collection = (Collection)elements; + if (collection.isEmpty()) { + return ImmutableSet.of(); + } + return ImmutableEnumSet.asImmutable(EnumSet.copyOf(collection)); + } + + Iterator itr = elements.iterator(); + if (itr.hasNext()) { + EnumSet enumSet = EnumSet.of((Enum)itr.next()); + Iterators.addAll(enumSet, itr); + return ImmutableEnumSet.asImmutable(enumSet); + } + return ImmutableSet.of(); + } + + + + + + + + + + public static > EnumSet newEnumSet(Iterable iterable, Class elementType) + { + EnumSet set = EnumSet.noneOf(elementType); + Iterables.addAll(set, iterable); + return set; + } + + + + + + + + + + + + + + public static HashSet newHashSet() + { + return new HashSet(); + } + + + + + + + + + + + + + + + public static HashSet newHashSet(E... elements) + { + HashSet set = newHashSetWithExpectedSize(elements.length); + Collections.addAll(set, elements); + return set; + } + + + + + + + + + + + + + + public static HashSet newHashSetWithExpectedSize(int expectedSize) + { + return new HashSet(Maps.capacity(expectedSize)); + } + + + + + + + + + + + + + + public static HashSet newHashSet(Iterable elements) + { + return (elements instanceof Collection) ? new HashSet(Collections2.cast(elements)) : newHashSet(elements.iterator()); + } + + + + + + + + + + + + + + + + public static HashSet newHashSet(Iterator elements) + { + HashSet set = newHashSet(); + Iterators.addAll(set, elements); + return set; + } + + + + + + + + + + + + public static Set newConcurrentHashSet() + { + return newSetFromMap(new ConcurrentHashMap()); + } + + + + + + + + + + + + + + + + public static Set newConcurrentHashSet(Iterable elements) + { + Set set = newConcurrentHashSet(); + Iterables.addAll(set, elements); + return set; + } + + + + + + + + + + + public static LinkedHashSet newLinkedHashSet() + { + return new LinkedHashSet(); + } + + + + + + + + + + + + + + + + public static LinkedHashSet newLinkedHashSetWithExpectedSize(int expectedSize) + { + return new LinkedHashSet(Maps.capacity(expectedSize)); + } + + + + + + + + + + + + + public static LinkedHashSet newLinkedHashSet(Iterable elements) + { + if ((elements instanceof Collection)) { + return new LinkedHashSet(Collections2.cast(elements)); + } + LinkedHashSet set = newLinkedHashSet(); + Iterables.addAll(set, elements); + return set; + } + + + + + + + + + + + + public static TreeSet newTreeSet() + { + return new TreeSet(); + } + + + + + + + + + + + + + + + + + public static TreeSet newTreeSet(Iterable elements) + { + TreeSet set = newTreeSet(); + Iterables.addAll(set, elements); + return set; + } + + + + + + + + + + + + public static TreeSet newTreeSet(Comparator comparator) + { + return new TreeSet((Comparator)Preconditions.checkNotNull(comparator)); + } + + + + + + + + + + + public static Set newIdentityHashSet() + { + return newSetFromMap(Maps.newIdentityHashMap()); + } + + + + + + + + + + @GwtIncompatible("CopyOnWriteArraySet") + public static CopyOnWriteArraySet newCopyOnWriteArraySet() + { + return new CopyOnWriteArraySet(); + } + + + + + + + + + + + @GwtIncompatible("CopyOnWriteArraySet") + public static CopyOnWriteArraySet newCopyOnWriteArraySet(Iterable elements) + { + Collection elementsCollection = (elements instanceof Collection) ? Collections2.cast(elements) : Lists.newArrayList(elements); + + + return new CopyOnWriteArraySet(elementsCollection); + } + + + + + + + + + + + + + + + + + public static > EnumSet complementOf(Collection collection) + { + if ((collection instanceof EnumSet)) { + return EnumSet.complementOf((EnumSet)collection); + } + Preconditions.checkArgument(!collection.isEmpty(), "collection is empty; use the other version of this method"); + + Class type = ((Enum)collection.iterator().next()).getDeclaringClass(); + return makeComplementByHand(collection, type); + } + + + + + + + + + + + + + + public static > EnumSet complementOf(Collection collection, Class type) + { + Preconditions.checkNotNull(collection); + return (collection instanceof EnumSet) ? EnumSet.complementOf((EnumSet)collection) : makeComplementByHand(collection, type); + } + + + + private static > EnumSet makeComplementByHand(Collection collection, Class type) + { + EnumSet result = EnumSet.allOf(type); + result.removeAll(collection); + return result; + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static Set newSetFromMap(Map map) + { + return Platform.newSetFromMap(map); + } + + + + + + + + + + public static abstract class SetView + extends AbstractSet + { + private SetView() {} + + + + + + + + + + public ImmutableSet immutableCopy() + { + return ImmutableSet.copyOf(this); + } + + + + + + + + + + public > S copyInto(S set) + { + set.addAll(this); + return set; + } + } + + + + + + + + + + + + + + + + + + + + + + public static SetView union(Set set1, final Set set2) + { + Preconditions.checkNotNull(set1, "set1"); + Preconditions.checkNotNull(set2, "set2"); + + final Set set2minus1 = difference(set2, set1); + + new SetView(set1) { + public int size() { + return val$set1.size() + set2minus1.size(); + } + + public boolean isEmpty() { return (val$set1.isEmpty()) && (set2.isEmpty()); } + + public Iterator iterator() { + return Iterators.unmodifiableIterator(Iterators.concat(val$set1.iterator(), set2minus1.iterator())); + } + + + public boolean contains(Object object) { return (val$set1.contains(object)) || (set2.contains(object)); } + + public > S copyInto(S set) { + set.addAll(val$set1); + set.addAll(set2); + return set; + } + + public ImmutableSet immutableCopy() { return new ImmutableSet.Builder().addAll(val$set1).addAll(set2).build(); } + }; + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static SetView intersection(Set set1, final Set set2) + { + Preconditions.checkNotNull(set1, "set1"); + Preconditions.checkNotNull(set2, "set2"); + + final Predicate inSet2 = Predicates.in(set2); + new SetView(set1) { + public Iterator iterator() { + return Iterators.filter(val$set1.iterator(), inSet2); + } + + public int size() { return Iterators.size(iterator()); } + + public boolean isEmpty() { + return !iterator().hasNext(); + } + + public boolean contains(Object object) { return (val$set1.contains(object)) && (set2.contains(object)); } + + public boolean containsAll(Collection collection) { + return (val$set1.containsAll(collection)) && (set2.containsAll(collection)); + } + }; + } + + + + + + + + + + + + + + public static SetView difference(Set set1, final Set set2) + { + Preconditions.checkNotNull(set1, "set1"); + Preconditions.checkNotNull(set2, "set2"); + + final Predicate notInSet2 = Predicates.not(Predicates.in(set2)); + new SetView(set1) { + public Iterator iterator() { + return Iterators.filter(val$set1.iterator(), notInSet2); + } + + public int size() { return Iterators.size(iterator()); } + + public boolean isEmpty() { + return set2.containsAll(val$set1); + } + + public boolean contains(Object element) { return (val$set1.contains(element)) && (!set2.contains(element)); } + }; + } + + + + + + + + + + + + + + + public static SetView symmetricDifference(Set set1, Set set2) + { + Preconditions.checkNotNull(set1, "set1"); + Preconditions.checkNotNull(set2, "set2"); + + + return difference(union(set1, set2), intersection(set1, set2)); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static Set filter(Set unfiltered, Predicate predicate) + { + if ((unfiltered instanceof SortedSet)) { + return filter((SortedSet)unfiltered, predicate); + } + if ((unfiltered instanceof FilteredSet)) + { + + FilteredSet filtered = (FilteredSet)unfiltered; + Predicate combinedPredicate = Predicates.and(predicate, predicate); + + return new FilteredSet((Set)unfiltered, combinedPredicate); + } + + + return new FilteredSet((Set)Preconditions.checkNotNull(unfiltered), (Predicate)Preconditions.checkNotNull(predicate)); + } + + private static class FilteredSet extends Collections2.FilteredCollection implements Set + { + FilteredSet(Set unfiltered, Predicate predicate) + { + super(predicate); + } + + public boolean equals(@Nullable Object object) { + return Sets.equalsImpl(this, object); + } + + public int hashCode() { + return Sets.hashCodeImpl(this); + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static SortedSet filter(SortedSet unfiltered, Predicate predicate) + { + return Platform.setsFilterSortedSet(unfiltered, predicate); + } + + static SortedSet filterSortedIgnoreNavigable(SortedSet unfiltered, Predicate predicate) + { + if ((unfiltered instanceof FilteredSet)) + { + + FilteredSet filtered = (FilteredSet)unfiltered; + Predicate combinedPredicate = Predicates.and(predicate, predicate); + + return new FilteredSortedSet((SortedSet)unfiltered, combinedPredicate); + } + + + return new FilteredSortedSet((SortedSet)Preconditions.checkNotNull(unfiltered), (Predicate)Preconditions.checkNotNull(predicate)); + } + + private static class FilteredSortedSet + extends Sets.FilteredSet implements SortedSet + { + FilteredSortedSet(SortedSet unfiltered, Predicate predicate) + { + super(predicate); + } + + public Comparator comparator() + { + return ((SortedSet)unfiltered).comparator(); + } + + public SortedSet subSet(E fromElement, E toElement) + { + return new FilteredSortedSet(((SortedSet)unfiltered).subSet(fromElement, toElement), predicate); + } + + + public SortedSet headSet(E toElement) + { + return new FilteredSortedSet(((SortedSet)unfiltered).headSet(toElement), predicate); + } + + public SortedSet tailSet(E fromElement) + { + return new FilteredSortedSet(((SortedSet)unfiltered).tailSet(fromElement), predicate); + } + + public E first() + { + return iterator().next(); + } + + public E last() + { + SortedSet sortedUnfiltered = (SortedSet)unfiltered; + for (;;) { + E element = sortedUnfiltered.last(); + if (predicate.apply(element)) { + return element; + } + sortedUnfiltered = sortedUnfiltered.headSet(element); + } + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @GwtIncompatible("NavigableSet") + public static NavigableSet filter(NavigableSet unfiltered, Predicate predicate) + { + if ((unfiltered instanceof FilteredSet)) + { + + FilteredSet filtered = (FilteredSet)unfiltered; + Predicate combinedPredicate = Predicates.and(predicate, predicate); + + return new FilteredNavigableSet((NavigableSet)unfiltered, combinedPredicate); + } + + + return new FilteredNavigableSet((NavigableSet)Preconditions.checkNotNull(unfiltered), (Predicate)Preconditions.checkNotNull(predicate)); + } + + @GwtIncompatible("NavigableSet") + private static class FilteredNavigableSet extends Sets.FilteredSortedSet implements NavigableSet + { + FilteredNavigableSet(NavigableSet unfiltered, Predicate predicate) + { + super(predicate); + } + + NavigableSet unfiltered() { + return (NavigableSet)unfiltered; + } + + @Nullable + public E lower(E e) + { + return Iterators.getNext(headSet(e, false).descendingIterator(), null); + } + + @Nullable + public E floor(E e) + { + return Iterators.getNext(headSet(e, true).descendingIterator(), null); + } + + public E ceiling(E e) + { + return Iterables.getFirst(tailSet(e, true), null); + } + + public E higher(E e) + { + return Iterables.getFirst(tailSet(e, false), null); + } + + public E pollFirst() + { + return Iterables.removeFirstMatching(unfiltered(), predicate); + } + + public E pollLast() + { + return Iterables.removeFirstMatching(unfiltered().descendingSet(), predicate); + } + + public NavigableSet descendingSet() + { + return Sets.filter(unfiltered().descendingSet(), predicate); + } + + public Iterator descendingIterator() + { + return Iterators.filter(unfiltered().descendingIterator(), predicate); + } + + public E last() + { + return descendingIterator().next(); + } + + + public NavigableSet subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) + { + return Sets.filter(unfiltered().subSet(fromElement, fromInclusive, toElement, toInclusive), predicate); + } + + + public NavigableSet headSet(E toElement, boolean inclusive) + { + return Sets.filter(unfiltered().headSet(toElement, inclusive), predicate); + } + + public NavigableSet tailSet(E fromElement, boolean inclusive) + { + return Sets.filter(unfiltered().tailSet(fromElement, inclusive), predicate); + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static Set> cartesianProduct(List> sets) + { + return CartesianSet.create(sets); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static Set> cartesianProduct(Set... sets) + { + return cartesianProduct(Arrays.asList(sets)); + } + + private static final class CartesianSet extends ForwardingCollection> implements Set> + { + private final transient ImmutableList> axes; + private final transient CartesianList delegate; + + static Set> create(List> sets) { + ImmutableList.Builder> axesBuilder = new ImmutableList.Builder(sets.size()); + + for (Set set : sets) { + ImmutableSet copy = ImmutableSet.copyOf(set); + if (copy.isEmpty()) { + return ImmutableSet.of(); + } + axesBuilder.add(copy); + } + ImmutableList> axes = axesBuilder.build(); + ImmutableList> listAxes = new ImmutableList() + { + public int size() + { + return val$axes.size(); + } + + public List get(int index) + { + return ((ImmutableSet)val$axes.get(index)).asList(); + } + + boolean isPartialView() + { + return true; + } + }; + return new CartesianSet(axes, new CartesianList(listAxes)); + } + + private CartesianSet(ImmutableList> axes, CartesianList delegate) + { + this.axes = axes; + this.delegate = delegate; + } + + protected Collection> delegate() + { + return delegate; + } + + + public boolean equals(@Nullable Object object) + { + if ((object instanceof CartesianSet)) { + CartesianSet that = (CartesianSet)object; + return axes.equals(axes); + } + return super.equals(object); + } + + + + + + public int hashCode() + { + int adjust = size() - 1; + for (int i = 0; i < axes.size(); i++) { + adjust *= 31; + adjust = adjust ^ 0xFFFFFFFF ^ 0xFFFFFFFF; + } + + int hash = 1; + for (Set axis : axes) { + hash = 31 * hash + size() / axis.size() * axis.hashCode(); + + hash = hash ^ 0xFFFFFFFF ^ 0xFFFFFFFF; + } + hash += adjust; + return hash ^ 0xFFFFFFFF ^ 0xFFFFFFFF; + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @GwtCompatible(serializable=false) + public static Set> powerSet(Set set) + { + return new PowerSet(set); + } + + private static final class SubSet extends AbstractSet { + private final ImmutableMap inputSet; + private final int mask; + + SubSet(ImmutableMap inputSet, int mask) { + this.inputSet = inputSet; + this.mask = mask; + } + + public Iterator iterator() + { + new UnmodifiableIterator() { + final ImmutableList elements = inputSet.keySet().asList(); + int remainingSetBits = mask; + + public boolean hasNext() + { + return remainingSetBits != 0; + } + + public E next() + { + int index = Integer.numberOfTrailingZeros(remainingSetBits); + if (index == 32) { + throw new NoSuchElementException(); + } + remainingSetBits &= (1 << index ^ 0xFFFFFFFF); + return elements.get(index); + } + }; + } + + public int size() + { + return Integer.bitCount(mask); + } + + public boolean contains(@Nullable Object o) + { + Integer index = (Integer)inputSet.get(o); + return (index != null) && ((mask & 1 << index.intValue()) != 0); + } + } + + private static final class PowerSet extends AbstractSet> { + final ImmutableMap inputSet; + + PowerSet(Set input) { + ImmutableMap.Builder builder = ImmutableMap.builder(); + int i = 0; + for (E e : (Set)Preconditions.checkNotNull(input)) { + builder.put(e, Integer.valueOf(i++)); + } + inputSet = builder.build(); + Preconditions.checkArgument(inputSet.size() <= 30, "Too many elements to create power set: %s > 30", new Object[] { Integer.valueOf(inputSet.size()) }); + } + + public int size() + { + return 1 << inputSet.size(); + } + + public boolean isEmpty() { + return false; + } + + public Iterator> iterator() { + new AbstractIndexedListIterator(size()) { + protected Set get(int setBits) { + return new Sets.SubSet(inputSet, setBits); + } + }; + } + + public boolean contains(@Nullable Object obj) { + if ((obj instanceof Set)) { + Set set = (Set)obj; + return inputSet.keySet().containsAll(set); + } + return false; + } + + public boolean equals(@Nullable Object obj) { + if ((obj instanceof PowerSet)) { + PowerSet that = (PowerSet)obj; + return inputSet.equals(inputSet); + } + return super.equals(obj); + } + + + + + + public int hashCode() + { + return inputSet.keySet().hashCode() << inputSet.size() - 1; + } + + public String toString() { + return "powerSet(" + inputSet + ")"; + } + } + + + + static int hashCodeImpl(Set s) + { + int hashCode = 0; + for (Object o : s) { + hashCode += (o != null ? o.hashCode() : 0); + + hashCode = hashCode ^ 0xFFFFFFFF ^ 0xFFFFFFFF; + } + + return hashCode; + } + + + + static boolean equalsImpl(Set s, @Nullable Object object) + { + if (s == object) { + return true; + } + if ((object instanceof Set)) { + Set o = (Set)object; + try + { + return (s.size() == o.size()) && (s.containsAll(o)); + } catch (NullPointerException ignored) { + return false; + } catch (ClassCastException ignored) { + return false; + } + } + return false; + } + + + + + + + + + + + + + + + + + + @GwtIncompatible("NavigableSet") + public static NavigableSet unmodifiableNavigableSet(NavigableSet set) + { + if (((set instanceof ImmutableSortedSet)) || ((set instanceof UnmodifiableNavigableSet))) + { + return set; + } + return new UnmodifiableNavigableSet(set); + } + + @GwtIncompatible("NavigableSet") + static final class UnmodifiableNavigableSet extends ForwardingSortedSet implements NavigableSet, Serializable { + private final NavigableSet delegate; + private transient UnmodifiableNavigableSet descendingSet; + private static final long serialVersionUID = 0L; + + UnmodifiableNavigableSet(NavigableSet delegate) { this.delegate = ((NavigableSet)Preconditions.checkNotNull(delegate)); } + + + protected SortedSet delegate() + { + return Collections.unmodifiableSortedSet(delegate); + } + + public E lower(E e) + { + return delegate.lower(e); + } + + public E floor(E e) + { + return delegate.floor(e); + } + + public E ceiling(E e) + { + return delegate.ceiling(e); + } + + public E higher(E e) + { + return delegate.higher(e); + } + + public E pollFirst() + { + throw new UnsupportedOperationException(); + } + + public E pollLast() + { + throw new UnsupportedOperationException(); + } + + + + public NavigableSet descendingSet() + { + UnmodifiableNavigableSet result = descendingSet; + if (result == null) { + result = this.descendingSet = new UnmodifiableNavigableSet(delegate.descendingSet()); + + descendingSet = this; + } + return result; + } + + public Iterator descendingIterator() + { + return Iterators.unmodifiableIterator(delegate.descendingIterator()); + } + + + + + + public NavigableSet subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) + { + return Sets.unmodifiableNavigableSet(delegate.subSet(fromElement, fromInclusive, toElement, toInclusive)); + } + + + + + + public NavigableSet headSet(E toElement, boolean inclusive) + { + return Sets.unmodifiableNavigableSet(delegate.headSet(toElement, inclusive)); + } + + public NavigableSet tailSet(E fromElement, boolean inclusive) + { + return Sets.unmodifiableNavigableSet(delegate.tailSet(fromElement, inclusive)); + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @GwtIncompatible("NavigableSet") + public static NavigableSet synchronizedNavigableSet(NavigableSet navigableSet) + { + return Synchronized.navigableSet(navigableSet); + } + + + + static boolean removeAllImpl(Set set, Iterator iterator) + { + boolean changed = false; + while (iterator.hasNext()) { + changed |= set.remove(iterator.next()); + } + return changed; + } + + static boolean removeAllImpl(Set set, Collection collection) { + Preconditions.checkNotNull(collection); + if ((collection instanceof Multiset)) { + collection = ((Multiset)collection).elementSet(); + } + + + + + + + + if (((collection instanceof Set)) && (collection.size() > set.size())) { + return Iterators.removeAll(set.iterator(), collection); + } + return removeAllImpl(set, collection.iterator()); + } + + @GwtIncompatible("NavigableSet") + static class DescendingSet extends ForwardingNavigableSet + { + private final NavigableSet forward; + + DescendingSet(NavigableSet forward) { + this.forward = forward; + } + + protected NavigableSet delegate() + { + return forward; + } + + public E lower(E e) + { + return forward.higher(e); + } + + public E floor(E e) + { + return forward.ceiling(e); + } + + public E ceiling(E e) + { + return forward.floor(e); + } + + public E higher(E e) + { + return forward.lower(e); + } + + public E pollFirst() + { + return forward.pollLast(); + } + + public E pollLast() + { + return forward.pollFirst(); + } + + public NavigableSet descendingSet() + { + return forward; + } + + public Iterator descendingIterator() + { + return forward.iterator(); + } + + + + + + public NavigableSet subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) + { + return forward.subSet(toElement, toInclusive, fromElement, fromInclusive).descendingSet(); + } + + public NavigableSet headSet(E toElement, boolean inclusive) + { + return forward.tailSet(toElement, inclusive).descendingSet(); + } + + public NavigableSet tailSet(E fromElement, boolean inclusive) + { + return forward.headSet(fromElement, inclusive).descendingSet(); + } + + + public Comparator comparator() + { + Comparator forwardComparator = forward.comparator(); + if (forwardComparator == null) { + return Ordering.natural().reverse(); + } + return reverse(forwardComparator); + } + + + private static Ordering reverse(Comparator forward) + { + return Ordering.from(forward).reverse(); + } + + public E first() + { + return forward.last(); + } + + public SortedSet headSet(E toElement) + { + return standardHeadSet(toElement); + } + + public E last() + { + return forward.first(); + } + + public SortedSet subSet(E fromElement, E toElement) + { + return standardSubSet(fromElement, toElement); + } + + public SortedSet tailSet(E fromElement) + { + return standardTailSet(fromElement); + } + + public Iterator iterator() + { + return forward.descendingIterator(); + } + + public Object[] toArray() + { + return standardToArray(); + } + + public T[] toArray(T[] array) + { + return standardToArray(array); + } + + public String toString() + { + return standardToString(); + } + } +} diff --git a/src/minecraft/com/google/common/collect/SingletonImmutableBiMap.java b/src/minecraft/com/google/common/collect/SingletonImmutableBiMap.java new file mode 100644 index 0000000..b8096ab --- /dev/null +++ b/src/minecraft/com/google/common/collect/SingletonImmutableBiMap.java @@ -0,0 +1,98 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Map.Entry; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +final class SingletonImmutableBiMap + extends ImmutableBiMap +{ + final transient K singleKey; + final transient V singleValue; + transient ImmutableBiMap inverse; + + SingletonImmutableBiMap(K singleKey, V singleValue) + { + CollectPreconditions.checkEntryNotNull(singleKey, singleValue); + this.singleKey = singleKey; + this.singleValue = singleValue; + } + + private SingletonImmutableBiMap(K singleKey, V singleValue, ImmutableBiMap inverse) + { + this.singleKey = singleKey; + this.singleValue = singleValue; + this.inverse = inverse; + } + + SingletonImmutableBiMap(Map.Entry entry) { + this(entry.getKey(), entry.getValue()); + } + + public V get(@Nullable Object key) { + return singleKey.equals(key) ? singleValue : null; + } + + public int size() + { + return 1; + } + + public boolean containsKey(@Nullable Object key) { + return singleKey.equals(key); + } + + public boolean containsValue(@Nullable Object value) { + return singleValue.equals(value); + } + + boolean isPartialView() { + return false; + } + + ImmutableSet> createEntrySet() + { + return ImmutableSet.of(Maps.immutableEntry(singleKey, singleValue)); + } + + ImmutableSet createKeySet() + { + return ImmutableSet.of(singleKey); + } + + + + + public ImmutableBiMap inverse() + { + ImmutableBiMap result = inverse; + if (result == null) { + return this.inverse = new SingletonImmutableBiMap(singleValue, singleKey, this); + } + + return result; + } +} diff --git a/src/minecraft/com/google/common/collect/SingletonImmutableList.java b/src/minecraft/com/google/common/collect/SingletonImmutableList.java new file mode 100644 index 0000000..dceb6ec --- /dev/null +++ b/src/minecraft/com/google/common/collect/SingletonImmutableList.java @@ -0,0 +1,118 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.List; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +final class SingletonImmutableList + extends ImmutableList +{ + final transient E element; + + SingletonImmutableList(E element) + { + this.element = Preconditions.checkNotNull(element); + } + + public E get(int index) + { + Preconditions.checkElementIndex(index, 1); + return element; + } + + public int indexOf(@Nullable Object object) { + return element.equals(object) ? 0 : -1; + } + + public UnmodifiableIterator iterator() { + return Iterators.singletonIterator(element); + } + + public int lastIndexOf(@Nullable Object object) { + return indexOf(object); + } + + public int size() + { + return 1; + } + + public ImmutableList subList(int fromIndex, int toIndex) { + Preconditions.checkPositionIndexes(fromIndex, toIndex, 1); + return fromIndex == toIndex ? ImmutableList.of() : this; + } + + public ImmutableList reverse() { + return this; + } + + public boolean contains(@Nullable Object object) { + return element.equals(object); + } + + public boolean equals(@Nullable Object object) { + if (object == this) { + return true; + } + if ((object instanceof List)) { + List that = (List)object; + return (that.size() == 1) && (element.equals(that.get(0))); + } + return false; + } + + + public int hashCode() + { + return 31 + element.hashCode(); + } + + public String toString() { + String elementToString = element.toString(); + return elementToString.length() + 2 + '[' + elementToString + ']'; + } + + + + + public boolean isEmpty() + { + return false; + } + + boolean isPartialView() { + return false; + } + + int copyIntoArray(Object[] dst, int offset) + { + dst[offset] = element; + return offset + 1; + } +} diff --git a/src/minecraft/com/google/common/collect/SingletonImmutableSet.java b/src/minecraft/com/google/common/collect/SingletonImmutableSet.java new file mode 100644 index 0000000..17cb190 --- /dev/null +++ b/src/minecraft/com/google/common/collect/SingletonImmutableSet.java @@ -0,0 +1,111 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.Iterator; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +final class SingletonImmutableSet + extends ImmutableSet +{ + final transient E element; + private transient int cachedHashCode; + + SingletonImmutableSet(E element) + { + this.element = Preconditions.checkNotNull(element); + } + + SingletonImmutableSet(E element, int hashCode) + { + this.element = element; + cachedHashCode = hashCode; + } + + public int size() + { + return 1; + } + + public boolean isEmpty() { + return false; + } + + public boolean contains(Object target) { + return element.equals(target); + } + + public UnmodifiableIterator iterator() { + return Iterators.singletonIterator(element); + } + + boolean isPartialView() { + return false; + } + + int copyIntoArray(Object[] dst, int offset) + { + dst[offset] = element; + return offset + 1; + } + + public boolean equals(@Nullable Object object) { + if (object == this) { + return true; + } + if ((object instanceof Set)) { + Set that = (Set)object; + return (that.size() == 1) && (element.equals(that.iterator().next())); + } + return false; + } + + public final int hashCode() + { + int code = cachedHashCode; + if (code == 0) { + cachedHashCode = (code = element.hashCode()); + } + return code; + } + + boolean isHashCodeFast() { + return cachedHashCode != 0; + } + + public String toString() { + String elementToString = element.toString(); + return elementToString.length() + 2 + '[' + elementToString + ']'; + } +} diff --git a/src/minecraft/com/google/common/collect/SingletonImmutableTable.java b/src/minecraft/com/google/common/collect/SingletonImmutableTable.java new file mode 100644 index 0000000..123b5f8 --- /dev/null +++ b/src/minecraft/com/google/common/collect/SingletonImmutableTable.java @@ -0,0 +1,76 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.Map; + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +class SingletonImmutableTable + extends ImmutableTable +{ + final R singleRowKey; + final C singleColumnKey; + final V singleValue; + + SingletonImmutableTable(R rowKey, C columnKey, V value) + { + singleRowKey = Preconditions.checkNotNull(rowKey); + singleColumnKey = Preconditions.checkNotNull(columnKey); + singleValue = Preconditions.checkNotNull(value); + } + + SingletonImmutableTable(Table.Cell cell) { + this(cell.getRowKey(), cell.getColumnKey(), cell.getValue()); + } + + public ImmutableMap column(C columnKey) { + Preconditions.checkNotNull(columnKey); + return containsColumn(columnKey) ? ImmutableMap.of(singleRowKey, singleValue) : ImmutableMap.of(); + } + + + public ImmutableMap> columnMap() + { + return ImmutableMap.of(singleColumnKey, ImmutableMap.of(singleRowKey, singleValue)); + } + + public ImmutableMap> rowMap() + { + return ImmutableMap.of(singleRowKey, ImmutableMap.of(singleColumnKey, singleValue)); + } + + public int size() + { + return 1; + } + + ImmutableSet> createCellSet() + { + return ImmutableSet.of(cellOf(singleRowKey, singleColumnKey, singleValue)); + } + + ImmutableCollection createValues() + { + return ImmutableSet.of(singleValue); + } +} diff --git a/src/minecraft/com/google/common/collect/SortedIterable.java b/src/minecraft/com/google/common/collect/SortedIterable.java new file mode 100644 index 0000000..fb440b4 --- /dev/null +++ b/src/minecraft/com/google/common/collect/SortedIterable.java @@ -0,0 +1,14 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Comparator; +import java.util.Iterator; + +@GwtCompatible +abstract interface SortedIterable + extends Iterable +{ + public abstract Comparator comparator(); + + public abstract Iterator iterator(); +} diff --git a/src/minecraft/com/google/common/collect/SortedIterables.java b/src/minecraft/com/google/common/collect/SortedIterables.java new file mode 100644 index 0000000..1ef12e1 --- /dev/null +++ b/src/minecraft/com/google/common/collect/SortedIterables.java @@ -0,0 +1,60 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.Comparator; +import java.util.SortedSet; + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +final class SortedIterables +{ + private SortedIterables() {} + + public static boolean hasSameComparator(Comparator comparator, Iterable elements) + { + Preconditions.checkNotNull(comparator); + Preconditions.checkNotNull(elements); + Comparator comparator2; + if ((elements instanceof SortedSet)) { + comparator2 = comparator((SortedSet)elements); } else { Comparator comparator2; + if ((elements instanceof SortedIterable)) { + comparator2 = ((SortedIterable)elements).comparator(); + } else + return false; } + Comparator comparator2; + return comparator.equals(comparator2); + } + + + public static Comparator comparator(SortedSet sortedSet) + { + Comparator result = sortedSet.comparator(); + if (result == null) { + result = Ordering.natural(); + } + return result; + } +} diff --git a/src/minecraft/com/google/common/collect/SortedLists.java b/src/minecraft/com/google/common/collect/SortedLists.java new file mode 100644 index 0000000..0230fc5 --- /dev/null +++ b/src/minecraft/com/google/common/collect/SortedLists.java @@ -0,0 +1,284 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import java.util.Comparator; +import java.util.List; +import java.util.RandomAccess; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +@Beta +final class SortedLists +{ + private SortedLists() {} + + public static abstract enum KeyPresentBehavior + { + ANY_PRESENT, + + + + + + + + + + LAST_PRESENT, + + + + + + + + + + + + + + + + + + + + + + + + FIRST_PRESENT, + + + + + + + + + + + + + + + + + + + + + + + + + + FIRST_AFTER, + + + + + + + + + + + LAST_BEFORE; + + + + + + private KeyPresentBehavior() {} + + + + + + abstract int resultIndex(Comparator paramComparator, E paramE, List paramList, int paramInt); + } + + + + + public static abstract enum KeyAbsentBehavior + { + NEXT_LOWER, + + + + + + + + + + NEXT_HIGHER, + + + + + + + + + + + + + + + + + + INVERTED_INSERTION_INDEX; + + + + + + private KeyAbsentBehavior() {} + + + + + abstract int resultIndex(int paramInt); + } + + + + + public static int binarySearch(List list, E e, KeyPresentBehavior presentBehavior, KeyAbsentBehavior absentBehavior) + { + Preconditions.checkNotNull(e); + return binarySearch(list, Preconditions.checkNotNull(e), Ordering.natural(), presentBehavior, absentBehavior); + } + + + + + + + + + + public static int binarySearch(List list, Function keyFunction, @Nullable K key, KeyPresentBehavior presentBehavior, KeyAbsentBehavior absentBehavior) + { + return binarySearch(list, keyFunction, key, Ordering.natural(), presentBehavior, absentBehavior); + } + + + + + + + + + + + + + + + + + + + + public static int binarySearch(List list, Function keyFunction, @Nullable K key, Comparator keyComparator, KeyPresentBehavior presentBehavior, KeyAbsentBehavior absentBehavior) + { + return binarySearch(Lists.transform(list, keyFunction), key, keyComparator, presentBehavior, absentBehavior); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + public static int binarySearch(List list, @Nullable E key, Comparator comparator, KeyPresentBehavior presentBehavior, KeyAbsentBehavior absentBehavior) + { + Preconditions.checkNotNull(comparator); + Preconditions.checkNotNull(list); + Preconditions.checkNotNull(presentBehavior); + Preconditions.checkNotNull(absentBehavior); + if (!(list instanceof RandomAccess)) { + list = Lists.newArrayList(list); + } + + + int lower = 0; + int upper = list.size() - 1; + + while (lower <= upper) { + int middle = lower + upper >>> 1; + int c = comparator.compare(key, list.get(middle)); + if (c < 0) { + upper = middle - 1; + } else if (c > 0) { + lower = middle + 1; + } else { + return lower + presentBehavior.resultIndex(comparator, key, list.subList(lower, upper + 1), middle - lower); + } + } + + return absentBehavior.resultIndex(lower); + } +} diff --git a/src/minecraft/com/google/common/collect/SortedMapDifference.java b/src/minecraft/com/google/common/collect/SortedMapDifference.java new file mode 100644 index 0000000..6a78e78 --- /dev/null +++ b/src/minecraft/com/google/common/collect/SortedMapDifference.java @@ -0,0 +1,17 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.SortedMap; + +@GwtCompatible +public abstract interface SortedMapDifference + extends MapDifference +{ + public abstract SortedMap entriesOnlyOnLeft(); + + public abstract SortedMap entriesOnlyOnRight(); + + public abstract SortedMap entriesInCommon(); + + public abstract SortedMap> entriesDiffering(); +} diff --git a/src/minecraft/com/google/common/collect/SortedMultiset.java b/src/minecraft/com/google/common/collect/SortedMultiset.java new file mode 100644 index 0000000..cf29662 --- /dev/null +++ b/src/minecraft/com/google/common/collect/SortedMultiset.java @@ -0,0 +1,38 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NavigableSet; +import java.util.Set; + +@Beta +@GwtCompatible(emulated=true) +public abstract interface SortedMultiset + extends SortedMultisetBridge, SortedIterable +{ + public abstract Comparator comparator(); + + public abstract Multiset.Entry firstEntry(); + + public abstract Multiset.Entry lastEntry(); + + public abstract Multiset.Entry pollFirstEntry(); + + public abstract Multiset.Entry pollLastEntry(); + + public abstract NavigableSet elementSet(); + + public abstract Set> entrySet(); + + public abstract Iterator iterator(); + + public abstract SortedMultiset descendingMultiset(); + + public abstract SortedMultiset headMultiset(E paramE, BoundType paramBoundType); + + public abstract SortedMultiset subMultiset(E paramE1, BoundType paramBoundType1, E paramE2, BoundType paramBoundType2); + + public abstract SortedMultiset tailMultiset(E paramE, BoundType paramBoundType); +} diff --git a/src/minecraft/com/google/common/collect/SortedMultisetBridge.java b/src/minecraft/com/google/common/collect/SortedMultisetBridge.java new file mode 100644 index 0000000..0471eba --- /dev/null +++ b/src/minecraft/com/google/common/collect/SortedMultisetBridge.java @@ -0,0 +1,9 @@ +package com.google.common.collect; + +import java.util.SortedSet; + +abstract interface SortedMultisetBridge + extends Multiset +{ + public abstract SortedSet elementSet(); +} diff --git a/src/minecraft/com/google/common/collect/SortedMultisets.java b/src/minecraft/com/google/common/collect/SortedMultisets.java new file mode 100644 index 0000000..19f35a3 --- /dev/null +++ b/src/minecraft/com/google/common/collect/SortedMultisets.java @@ -0,0 +1,165 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NavigableSet; +import java.util.NoSuchElementException; +import java.util.SortedSet; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +final class SortedMultisets +{ + private SortedMultisets() {} + + static class ElementSet + extends Multisets.ElementSet + implements SortedSet + { + private final SortedMultiset multiset; + + ElementSet(SortedMultiset multiset) + { + this.multiset = multiset; + } + + final SortedMultiset multiset() { + return multiset; + } + + public Comparator comparator() { + return multiset().comparator(); + } + + public SortedSet subSet(E fromElement, E toElement) { + return multiset().subMultiset(fromElement, BoundType.CLOSED, toElement, BoundType.OPEN).elementSet(); + } + + public SortedSet headSet(E toElement) { + return multiset().headMultiset(toElement, BoundType.OPEN).elementSet(); + } + + public SortedSet tailSet(E fromElement) { + return multiset().tailMultiset(fromElement, BoundType.CLOSED).elementSet(); + } + + public E first() { + return SortedMultisets.getElementOrThrow(multiset().firstEntry()); + } + + public E last() { + return SortedMultisets.getElementOrThrow(multiset().lastEntry()); + } + } + + @GwtIncompatible("Navigable") + static class NavigableElementSet + extends SortedMultisets.ElementSet implements NavigableSet + { + NavigableElementSet(SortedMultiset multiset) + { + super(); + } + + public E lower(E e) + { + return SortedMultisets.getElementOrNull(multiset().headMultiset(e, BoundType.OPEN).lastEntry()); + } + + public E floor(E e) + { + return SortedMultisets.getElementOrNull(multiset().headMultiset(e, BoundType.CLOSED).lastEntry()); + } + + public E ceiling(E e) + { + return SortedMultisets.getElementOrNull(multiset().tailMultiset(e, BoundType.CLOSED).firstEntry()); + } + + public E higher(E e) + { + return SortedMultisets.getElementOrNull(multiset().tailMultiset(e, BoundType.OPEN).firstEntry()); + } + + public NavigableSet descendingSet() + { + return new NavigableElementSet(multiset().descendingMultiset()); + } + + public Iterator descendingIterator() + { + return descendingSet().iterator(); + } + + public E pollFirst() + { + return SortedMultisets.getElementOrNull(multiset().pollFirstEntry()); + } + + public E pollLast() + { + return SortedMultisets.getElementOrNull(multiset().pollLastEntry()); + } + + + public NavigableSet subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) + { + return new NavigableElementSet(multiset().subMultiset(fromElement, BoundType.forBoolean(fromInclusive), toElement, BoundType.forBoolean(toInclusive))); + } + + + + public NavigableSet headSet(E toElement, boolean inclusive) + { + return new NavigableElementSet(multiset().headMultiset(toElement, BoundType.forBoolean(inclusive))); + } + + + public NavigableSet tailSet(E fromElement, boolean inclusive) + { + return new NavigableElementSet(multiset().tailMultiset(fromElement, BoundType.forBoolean(inclusive))); + } + } + + private static E getElementOrThrow(Multiset.Entry entry) + { + if (entry == null) { + throw new NoSuchElementException(); + } + return entry.getElement(); + } + + private static E getElementOrNull(@Nullable Multiset.Entry entry) { + return entry == null ? null : entry.getElement(); + } +} diff --git a/src/minecraft/com/google/common/collect/SortedSetMultimap.java b/src/minecraft/com/google/common/collect/SortedSetMultimap.java new file mode 100644 index 0000000..7d78d4c --- /dev/null +++ b/src/minecraft/com/google/common/collect/SortedSetMultimap.java @@ -0,0 +1,23 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Collection; +import java.util.Comparator; +import java.util.Map; +import java.util.SortedSet; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract interface SortedSetMultimap + extends SetMultimap +{ + public abstract SortedSet get(@Nullable K paramK); + + public abstract SortedSet removeAll(@Nullable Object paramObject); + + public abstract SortedSet replaceValues(K paramK, Iterable paramIterable); + + public abstract Map> asMap(); + + public abstract Comparator valueComparator(); +} diff --git a/src/minecraft/com/google/common/collect/SparseImmutableTable.java b/src/minecraft/com/google/common/collect/SparseImmutableTable.java new file mode 100644 index 0000000..73d31d9 --- /dev/null +++ b/src/minecraft/com/google/common/collect/SparseImmutableTable.java @@ -0,0 +1,112 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; +import javax.annotation.concurrent.Immutable; + + + + + + + + + + + + + + + + + + + +@GwtCompatible +@Immutable +final class SparseImmutableTable + extends RegularImmutableTable +{ + private final ImmutableMap> rowMap; + private final ImmutableMap> columnMap; + private final int[] iterationOrderRow; + private final int[] iterationOrderColumn; + + SparseImmutableTable(ImmutableList> cellList, ImmutableSet rowSpace, ImmutableSet columnSpace) + { + Map rowIndex = Maps.newHashMap(); + Map> rows = Maps.newLinkedHashMap(); + for (R row : rowSpace) { + rowIndex.put(row, Integer.valueOf(rows.size())); + rows.put(row, new LinkedHashMap()); + } + Map> columns = Maps.newLinkedHashMap(); + for (C col : columnSpace) { + columns.put(col, new LinkedHashMap()); + } + int[] iterationOrderRow = new int[cellList.size()]; + int[] iterationOrderColumn = new int[cellList.size()]; + for (int i = 0; i < cellList.size(); i++) { + Table.Cell cell = (Table.Cell)cellList.get(i); + R rowKey = cell.getRowKey(); + C columnKey = cell.getColumnKey(); + V value = cell.getValue(); + + iterationOrderRow[i] = ((Integer)rowIndex.get(rowKey)).intValue(); + Map thisRow = (Map)rows.get(rowKey); + iterationOrderColumn[i] = thisRow.size(); + V oldValue = thisRow.put(columnKey, value); + if (oldValue != null) { + throw new IllegalArgumentException("Duplicate value for row=" + rowKey + ", column=" + columnKey + ": " + value + ", " + oldValue); + } + + ((Map)columns.get(columnKey)).put(rowKey, value); + } + this.iterationOrderRow = iterationOrderRow; + this.iterationOrderColumn = iterationOrderColumn; + ImmutableMap.Builder> rowBuilder = ImmutableMap.builder(); + for (Map.Entry> row : rows.entrySet()) { + rowBuilder.put(row.getKey(), ImmutableMap.copyOf((Map)row.getValue())); + } + rowMap = rowBuilder.build(); + + ImmutableMap.Builder> columnBuilder = ImmutableMap.builder(); + for (Map.Entry> col : columns.entrySet()) { + columnBuilder.put(col.getKey(), ImmutableMap.copyOf((Map)col.getValue())); + } + columnMap = columnBuilder.build(); + } + + public ImmutableMap> columnMap() { + return columnMap; + } + + public ImmutableMap> rowMap() { + return rowMap; + } + + public int size() + { + return iterationOrderRow.length; + } + + Table.Cell getCell(int index) + { + int rowIndex = iterationOrderRow[index]; + Map.Entry> rowEntry = (Map.Entry)rowMap.entrySet().asList().get(rowIndex); + ImmutableMap row = (ImmutableMap)rowEntry.getValue(); + int columnIndex = iterationOrderColumn[index]; + Map.Entry colEntry = (Map.Entry)row.entrySet().asList().get(columnIndex); + return cellOf(rowEntry.getKey(), colEntry.getKey(), colEntry.getValue()); + } + + V getValue(int index) + { + int rowIndex = iterationOrderRow[index]; + ImmutableMap row = (ImmutableMap)rowMap.values().asList().get(rowIndex); + int columnIndex = iterationOrderColumn[index]; + return row.values().asList().get(columnIndex); + } +} diff --git a/src/minecraft/com/google/common/collect/StandardRowSortedTable.java b/src/minecraft/com/google/common/collect/StandardRowSortedTable.java new file mode 100644 index 0000000..19d4018 --- /dev/null +++ b/src/minecraft/com/google/common/collect/StandardRowSortedTable.java @@ -0,0 +1,138 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import java.util.Comparator; +import java.util.Map; +import java.util.SortedMap; +import java.util.SortedSet; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +class StandardRowSortedTable + extends StandardTable + implements RowSortedTable +{ + private static final long serialVersionUID = 0L; + + StandardRowSortedTable(SortedMap> backingMap, Supplier> factory) + { + super(backingMap, factory); + } + + private SortedMap> sortedBackingMap() { + return (SortedMap)backingMap; + } + + + + + + + public SortedSet rowKeySet() + { + return (SortedSet)rowMap().keySet(); + } + + + + + + + public SortedMap> rowMap() + { + return (SortedMap)super.rowMap(); + } + + + + SortedMap> createRowMap() { return new RowSortedMap(null); } + + private class RowSortedMap extends StandardTable.RowMap implements SortedMap> { + private RowSortedMap() { super(); } + + public SortedSet keySet() { + return (SortedSet)super.keySet(); + } + + SortedSet createKeySet() + { + return new Maps.SortedKeySet(this); + } + + public Comparator comparator() + { + return StandardRowSortedTable.this.sortedBackingMap().comparator(); + } + + public R firstKey() + { + return StandardRowSortedTable.this.sortedBackingMap().firstKey(); + } + + public R lastKey() + { + return StandardRowSortedTable.this.sortedBackingMap().lastKey(); + } + + public SortedMap> headMap(R toKey) + { + Preconditions.checkNotNull(toKey); + return new StandardRowSortedTable(StandardRowSortedTable.this.sortedBackingMap().headMap(toKey), factory).rowMap(); + } + + + public SortedMap> subMap(R fromKey, R toKey) + { + Preconditions.checkNotNull(fromKey); + Preconditions.checkNotNull(toKey); + return new StandardRowSortedTable(StandardRowSortedTable.this.sortedBackingMap().subMap(fromKey, toKey), factory).rowMap(); + } + + + public SortedMap> tailMap(R fromKey) + { + Preconditions.checkNotNull(fromKey); + return new StandardRowSortedTable(StandardRowSortedTable.this.sortedBackingMap().tailMap(fromKey), factory).rowMap(); + } + } +} diff --git a/src/minecraft/com/google/common/collect/StandardTable.java b/src/minecraft/com/google/common/collect/StandardTable.java new file mode 100644 index 0000000..cd3ec57 --- /dev/null +++ b/src/minecraft/com/google/common/collect/StandardTable.java @@ -0,0 +1,892 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.base.Supplier; +import java.io.Serializable; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +class StandardTable + extends AbstractTable + implements Serializable +{ + @GwtTransient + final Map> backingMap; + @GwtTransient + final Supplier> factory; + private transient Set columnKeySet; + private transient Map> rowMap; + private transient StandardTable.ColumnMap columnMap; + private static final long serialVersionUID = 0L; + + StandardTable(Map> backingMap, Supplier> factory) + { + this.backingMap = backingMap; + this.factory = factory; + } + + + + public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) + { + return (rowKey != null) && (columnKey != null) && (super.contains(rowKey, columnKey)); + } + + public boolean containsColumn(@Nullable Object columnKey) { + if (columnKey == null) { + return false; + } + for (Map map : backingMap.values()) { + if (Maps.safeContainsKey(map, columnKey)) { + return true; + } + } + return false; + } + + public boolean containsRow(@Nullable Object rowKey) { + return (rowKey != null) && (Maps.safeContainsKey(backingMap, rowKey)); + } + + public boolean containsValue(@Nullable Object value) { + return (value != null) && (super.containsValue(value)); + } + + public V get(@Nullable Object rowKey, @Nullable Object columnKey) { + return (rowKey == null) || (columnKey == null) ? null : super.get(rowKey, columnKey); + } + + + public boolean isEmpty() + { + return backingMap.isEmpty(); + } + + public int size() { + int size = 0; + for (Map map : backingMap.values()) { + size += map.size(); + } + return size; + } + + + public void clear() + { + backingMap.clear(); + } + + private Map getOrCreate(R rowKey) { + Map map = (Map)backingMap.get(rowKey); + if (map == null) { + map = (Map)factory.get(); + backingMap.put(rowKey, map); + } + return map; + } + + public V put(R rowKey, C columnKey, V value) { + Preconditions.checkNotNull(rowKey); + Preconditions.checkNotNull(columnKey); + Preconditions.checkNotNull(value); + return getOrCreate(rowKey).put(columnKey, value); + } + + public V remove(@Nullable Object rowKey, @Nullable Object columnKey) + { + if ((rowKey == null) || (columnKey == null)) { + return null; + } + Map map = (Map)Maps.safeGet(backingMap, rowKey); + if (map == null) { + return null; + } + V value = map.remove(columnKey); + if (map.isEmpty()) { + backingMap.remove(rowKey); + } + return value; + } + + private Map removeColumn(Object column) { + Map output = new LinkedHashMap(); + Iterator>> iterator = backingMap.entrySet().iterator(); + + while (iterator.hasNext()) { + Map.Entry> entry = (Map.Entry)iterator.next(); + V value = ((Map)entry.getValue()).remove(column); + if (value != null) { + output.put(entry.getKey(), value); + if (((Map)entry.getValue()).isEmpty()) { + iterator.remove(); + } + } + } + return output; + } + + private boolean containsMapping(Object rowKey, Object columnKey, Object value) + { + return (value != null) && (value.equals(get(rowKey, columnKey))); + } + + private boolean removeMapping(Object rowKey, Object columnKey, Object value) + { + if (containsMapping(rowKey, columnKey, value)) { + remove(rowKey, columnKey); + return true; + } + return false; + } + + + private abstract class TableSet + extends Sets.ImprovedAbstractSet + { + private TableSet() {} + + public boolean isEmpty() + { + return backingMap.isEmpty(); + } + + public void clear() { + backingMap.clear(); + } + } + + + + + + + + + + + public Set> cellSet() + { + return super.cellSet(); + } + + Iterator> cellIterator() { + return new CellIterator(null); + } + + private class CellIterator implements Iterator> { + final Iterator>> rowIterator = backingMap.entrySet().iterator(); + + Map.Entry> rowEntry; + Iterator> columnIterator = Iterators.emptyModifiableIterator(); + + private CellIterator() {} + + public boolean hasNext() { return (rowIterator.hasNext()) || (columnIterator.hasNext()); } + + public Table.Cell next() + { + if (!columnIterator.hasNext()) { + rowEntry = ((Map.Entry)rowIterator.next()); + columnIterator = ((Map)rowEntry.getValue()).entrySet().iterator(); + } + Map.Entry columnEntry = (Map.Entry)columnIterator.next(); + return Tables.immutableCell(rowEntry.getKey(), columnEntry.getKey(), columnEntry.getValue()); + } + + public void remove() + { + columnIterator.remove(); + if (((Map)rowEntry.getValue()).isEmpty()) { + rowIterator.remove(); + } + } + } + + public Map row(R rowKey) { + return new Row(rowKey); + } + + class Row extends Maps.ImprovedAbstractMap { + final R rowKey; + Map backingRowMap; + + Row() { this.rowKey = Preconditions.checkNotNull(rowKey); } + + + + Map backingRowMap() + { + return (backingRowMap == null) || ((backingRowMap.isEmpty()) && (backingMap.containsKey(rowKey))) ? (this.backingRowMap = computeBackingRowMap()) : backingRowMap; + } + + + + Map computeBackingRowMap() + { + return (Map)backingMap.get(rowKey); + } + + void maintainEmptyInvariant() + { + if ((backingRowMap() != null) && (backingRowMap.isEmpty())) { + backingMap.remove(rowKey); + backingRowMap = null; + } + } + + public boolean containsKey(Object key) + { + Map backingRowMap = backingRowMap(); + return (key != null) && (backingRowMap != null) && (Maps.safeContainsKey(backingRowMap, key)); + } + + + public V get(Object key) + { + Map backingRowMap = backingRowMap(); + return (key != null) && (backingRowMap != null) ? Maps.safeGet(backingRowMap, key) : null; + } + + + + public V put(C key, V value) + { + Preconditions.checkNotNull(key); + Preconditions.checkNotNull(value); + if ((backingRowMap != null) && (!backingRowMap.isEmpty())) { + return backingRowMap.put(key, value); + } + return put(rowKey, key, value); + } + + public V remove(Object key) + { + Map backingRowMap = backingRowMap(); + if (backingRowMap == null) { + return null; + } + V result = Maps.safeRemove(backingRowMap, key); + maintainEmptyInvariant(); + return result; + } + + public void clear() + { + Map backingRowMap = backingRowMap(); + if (backingRowMap != null) { + backingRowMap.clear(); + } + maintainEmptyInvariant(); + } + + protected Set> createEntrySet() + { + return new RowEntrySet(null); + } + + private final class RowEntrySet extends Maps.EntrySet { + private RowEntrySet() {} + + Map map() { return StandardTable.Row.this; } + + + public int size() + { + Map map = backingRowMap(); + return map == null ? 0 : map.size(); + } + + public Iterator> iterator() + { + Map map = backingRowMap(); + if (map == null) { + return Iterators.emptyModifiableIterator(); + } + final Iterator> iterator = map.entrySet().iterator(); + new Iterator() + { + public boolean hasNext() { return iterator.hasNext(); } + + public Map.Entry next() { + final Map.Entry entry = (Map.Entry)iterator.next(); + new ForwardingMapEntry() { + protected Map.Entry delegate() { + return entry; + } + + public V setValue(V value) { return super.setValue(Preconditions.checkNotNull(value)); } + + + public boolean equals(Object object) + { + return standardEquals(object); + } + }; + } + + public void remove() + { + iterator.remove(); + maintainEmptyInvariant(); + } + }; + } + } + } + + + + + + + public Map column(C columnKey) + { + return new Column(columnKey); + } + + private class Column extends Maps.ImprovedAbstractMap { + final C columnKey; + + Column() { + this.columnKey = Preconditions.checkNotNull(columnKey); + } + + public V put(R key, V value) { + return put(key, columnKey, value); + } + + public V get(Object key) { + return get(key, columnKey); + } + + public boolean containsKey(Object key) { + return contains(key, columnKey); + } + + public V remove(Object key) { + return remove(key, columnKey); + } + + + + + boolean removeFromColumnIf(Predicate> predicate) + { + boolean changed = false; + Iterator>> iterator = backingMap.entrySet().iterator(); + + while (iterator.hasNext()) { + Map.Entry> entry = (Map.Entry)iterator.next(); + Map map = (Map)entry.getValue(); + V value = map.get(columnKey); + if ((value != null) && (predicate.apply(Maps.immutableEntry(entry.getKey(), value)))) + { + map.remove(columnKey); + changed = true; + if (map.isEmpty()) { + iterator.remove(); + } + } + } + return changed; + } + + + Set> createEntrySet() { return new EntrySet(null); } + + private class EntrySet extends Sets.ImprovedAbstractSet> { + private EntrySet() {} + + public Iterator> iterator() { return new StandardTable.Column.EntrySetIterator(StandardTable.Column.this, null); } + + public int size() + { + int size = 0; + for (Map map : backingMap.values()) { + if (map.containsKey(columnKey)) { + size++; + } + } + return size; + } + + public boolean isEmpty() { + return !containsColumn(columnKey); + } + + public void clear() { + removeFromColumnIf(Predicates.alwaysTrue()); + } + + public boolean contains(Object o) { + if ((o instanceof Map.Entry)) { + Map.Entry entry = (Map.Entry)o; + return StandardTable.this.containsMapping(entry.getKey(), columnKey, entry.getValue()); + } + return false; + } + + public boolean remove(Object obj) { + if ((obj instanceof Map.Entry)) { + Map.Entry entry = (Map.Entry)obj; + return StandardTable.this.removeMapping(entry.getKey(), columnKey, entry.getValue()); + } + return false; + } + + + public boolean retainAll(Collection c) { return removeFromColumnIf(Predicates.not(Predicates.in(c))); } + } + + private class EntrySetIterator extends AbstractIterator> { private EntrySetIterator() {} + + final Iterator>> iterator = backingMap.entrySet().iterator(); + + protected Map.Entry computeNext() { + while (iterator.hasNext()) { + final Map.Entry> entry = (Map.Entry)iterator.next(); + if (((Map)entry.getValue()).containsKey(columnKey)) { + new AbstractMapEntry() { + public R getKey() { + return entry.getKey(); + } + + public V getValue() { return ((Map)entry.getValue()).get(columnKey); } + + public V setValue(V value) { + return ((Map)entry.getValue()).put(columnKey, Preconditions.checkNotNull(value)); + } + }; + } + } + return (Map.Entry)endOfData(); + } + } + + Set createKeySet() { + return new KeySet(); + } + + private class KeySet extends Maps.KeySet { + KeySet() { + super(); + } + + public boolean contains(Object obj) { + return contains(obj, columnKey); + } + + public boolean remove(Object obj) { + return remove(obj, columnKey) != null; + } + + public boolean retainAll(Collection c) { + return removeFromColumnIf(Maps.keyPredicateOnEntries(Predicates.not(Predicates.in(c)))); + } + } + + Collection createValues() + { + return new Values(); + } + + private class Values extends Maps.Values { + Values() { + super(); + } + + public boolean remove(Object obj) { + return (obj != null) && (removeFromColumnIf(Maps.valuePredicateOnEntries(Predicates.equalTo(obj)))); + } + + public boolean removeAll(Collection c) { + return removeFromColumnIf(Maps.valuePredicateOnEntries(Predicates.in(c))); + } + + public boolean retainAll(Collection c) { + return removeFromColumnIf(Maps.valuePredicateOnEntries(Predicates.not(Predicates.in(c)))); + } + } + } + + public Set rowKeySet() { + return rowMap().keySet(); + } + + + + + + + + + + + + + public Set columnKeySet() + { + Set result = columnKeySet; + return result == null ? (this.columnKeySet = new ColumnKeySet(null)) : result; + } + + private class ColumnKeySet extends StandardTable.TableSet { private ColumnKeySet() { super(null); } + + public Iterator iterator() { return createColumnKeyIterator(); } + + public int size() + { + return Iterators.size(iterator()); + } + + public boolean remove(Object obj) { + if (obj == null) { + return false; + } + boolean changed = false; + Iterator> iterator = backingMap.values().iterator(); + while (iterator.hasNext()) { + Map map = (Map)iterator.next(); + if (map.keySet().remove(obj)) { + changed = true; + if (map.isEmpty()) { + iterator.remove(); + } + } + } + return changed; + } + + public boolean removeAll(Collection c) { + Preconditions.checkNotNull(c); + boolean changed = false; + Iterator> iterator = backingMap.values().iterator(); + while (iterator.hasNext()) { + Map map = (Map)iterator.next(); + + + if (Iterators.removeAll(map.keySet().iterator(), c)) { + changed = true; + if (map.isEmpty()) { + iterator.remove(); + } + } + } + return changed; + } + + public boolean retainAll(Collection c) { + Preconditions.checkNotNull(c); + boolean changed = false; + Iterator> iterator = backingMap.values().iterator(); + while (iterator.hasNext()) { + Map map = (Map)iterator.next(); + if (map.keySet().retainAll(c)) { + changed = true; + if (map.isEmpty()) { + iterator.remove(); + } + } + } + return changed; + } + + public boolean contains(Object obj) { + return containsColumn(obj); + } + } + + + + + Iterator createColumnKeyIterator() + { + return new ColumnKeyIterator(null); + } + + private class ColumnKeyIterator + extends AbstractIterator + { + final Map seen = (Map)factory.get(); + final Iterator> mapIterator = backingMap.values().iterator(); + Iterator> entryIterator = Iterators.emptyIterator(); + + private ColumnKeyIterator() {} + + protected C computeNext() { for (;;) { if (entryIterator.hasNext()) { + Map.Entry entry = (Map.Entry)entryIterator.next(); + if (!seen.containsKey(entry.getKey())) { + seen.put(entry.getKey(), entry.getValue()); + return entry.getKey(); + } + } else { if (!mapIterator.hasNext()) break; + entryIterator = ((Map)mapIterator.next()).entrySet().iterator(); + } } + return endOfData(); + } + } + + + + + + + + + public Collection values() + { + return super.values(); + } + + + public Map> rowMap() + { + Map> result = rowMap; + return result == null ? (this.rowMap = createRowMap()) : result; + } + + + Map> createRowMap() { return new RowMap(); } + + class RowMap extends Maps.ImprovedAbstractMap> { + RowMap() {} + + public boolean containsKey(Object key) { return containsRow(key); } + + + + public Map get(Object key) + { + return containsRow(key) ? row(key) : null; + } + + public Map remove(Object key) { + return key == null ? null : (Map)backingMap.remove(key); + } + + + protected Set>> createEntrySet() { return new EntrySet(); } + + class EntrySet extends StandardTable.TableSet>> { + EntrySet() { super(null); } + + public Iterator>> iterator() { Maps.asMapEntryIterator(backingMap.keySet(), new Function() + { + public Map apply(R rowKey) { + return row(rowKey); + } + }); } + + public int size() + { + return backingMap.size(); + } + + public boolean contains(Object obj) { + if ((obj instanceof Map.Entry)) { + Map.Entry entry = (Map.Entry)obj; + return (entry.getKey() != null) && ((entry.getValue() instanceof Map)) && (Collections2.safeContains(backingMap.entrySet(), entry)); + } + + + return false; + } + + public boolean remove(Object obj) { + if ((obj instanceof Map.Entry)) { + Map.Entry entry = (Map.Entry)obj; + return (entry.getKey() != null) && ((entry.getValue() instanceof Map)) && (backingMap.entrySet().remove(entry)); + } + + + return false; + } + } + } + + + public Map> columnMap() + { + StandardTable.ColumnMap result = columnMap; + return result == null ? (this.columnMap = new ColumnMap(null)) : result; + } + + private class ColumnMap extends Maps.ImprovedAbstractMap> + { + private ColumnMap() {} + + public Map get(Object key) { + return containsColumn(key) ? column(key) : null; + } + + public boolean containsKey(Object key) { + return containsColumn(key); + } + + public Map remove(Object key) { + return containsColumn(key) ? StandardTable.this.removeColumn(key) : null; + } + + public Set>> createEntrySet() { + return new ColumnMapEntrySet(); + } + + public Set keySet() { + return columnKeySet(); + } + + + Collection> createValues() { return new ColumnMapValues(); } + + class ColumnMapEntrySet extends StandardTable.TableSet>> { + ColumnMapEntrySet() { super(null); } + + public Iterator>> iterator() { Maps.asMapEntryIterator(columnKeySet(), new Function() + { + public Map apply(C columnKey) { + return column(columnKey); + } + }); } + + public int size() + { + return columnKeySet().size(); + } + + public boolean contains(Object obj) { + if ((obj instanceof Map.Entry)) { + Map.Entry entry = (Map.Entry)obj; + if (containsColumn(entry.getKey())) + { + + + C columnKey = entry.getKey(); + return get(columnKey).equals(entry.getValue()); + } + } + return false; + } + + public boolean remove(Object obj) { + if (contains(obj)) { + Map.Entry entry = (Map.Entry)obj; + StandardTable.this.removeColumn(entry.getKey()); + return true; + } + return false; + } + + + + + + + public boolean removeAll(Collection c) + { + Preconditions.checkNotNull(c); + return Sets.removeAllImpl(this, c.iterator()); + } + + public boolean retainAll(Collection c) { + Preconditions.checkNotNull(c); + boolean changed = false; + for (C columnKey : Lists.newArrayList(columnKeySet().iterator())) { + if (!c.contains(Maps.immutableEntry(columnKey, column(columnKey)))) { + StandardTable.this.removeColumn(columnKey); + changed = true; + } + } + return changed; + } + } + + private class ColumnMapValues extends Maps.Values> { + ColumnMapValues() { + super(); + } + + public boolean remove(Object obj) { + for (Map.Entry> entry : entrySet()) { + if (((Map)entry.getValue()).equals(obj)) { + StandardTable.this.removeColumn(entry.getKey()); + return true; + } + } + return false; + } + + public boolean removeAll(Collection c) { + Preconditions.checkNotNull(c); + boolean changed = false; + for (C columnKey : Lists.newArrayList(columnKeySet().iterator())) { + if (c.contains(column(columnKey))) { + StandardTable.this.removeColumn(columnKey); + changed = true; + } + } + return changed; + } + + public boolean retainAll(Collection c) { + Preconditions.checkNotNull(c); + boolean changed = false; + for (C columnKey : Lists.newArrayList(columnKeySet().iterator())) { + if (!c.contains(column(columnKey))) { + StandardTable.this.removeColumn(columnKey); + changed = true; + } + } + return changed; + } + } + } +} diff --git a/src/minecraft/com/google/common/collect/Synchronized.java b/src/minecraft/com/google/common/collect/Synchronized.java new file mode 100644 index 0000000..6c9133d --- /dev/null +++ b/src/minecraft/com/google/common/collect/Synchronized.java @@ -0,0 +1,1759 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Collection; +import java.util.Comparator; +import java.util.Deque; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NavigableMap; +import java.util.NavigableSet; +import java.util.Queue; +import java.util.RandomAccess; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +final class Synchronized +{ + private Synchronized() {} + + static class SynchronizedObject + implements Serializable + { + final Object delegate; + final Object mutex; + @GwtIncompatible("not needed in emulated source") + private static final long serialVersionUID = 0L; + + SynchronizedObject(Object delegate, @Nullable Object mutex) + { + this.delegate = Preconditions.checkNotNull(delegate); + this.mutex = (mutex == null ? this : mutex); + } + + Object delegate() { + return delegate; + } + + + public String toString() + { + synchronized (mutex) { + return delegate.toString(); + } + } + + + + + @GwtIncompatible("java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) + throws IOException + { + synchronized (mutex) { + stream.defaultWriteObject(); + } + } + } + + + + + private static Collection collection(Collection collection, @Nullable Object mutex) + { + return new SynchronizedCollection(collection, mutex, null); + } + + @VisibleForTesting + static class SynchronizedCollection extends Synchronized.SynchronizedObject implements Collection { + private static final long serialVersionUID = 0L; + + private SynchronizedCollection(Collection delegate, @Nullable Object mutex) { super(mutex); } + + + Collection delegate() + { + return (Collection)super.delegate(); + } + + public boolean add(E e) + { + synchronized (mutex) { + return delegate().add(e); + } + } + + public boolean addAll(Collection c) + { + synchronized (mutex) { + return delegate().addAll(c); + } + } + + public void clear() + { + synchronized (mutex) { + delegate().clear(); + } + } + + public boolean contains(Object o) + { + synchronized (mutex) { + return delegate().contains(o); + } + } + + public boolean containsAll(Collection c) + { + synchronized (mutex) { + return delegate().containsAll(c); + } + } + + public boolean isEmpty() + { + synchronized (mutex) { + return delegate().isEmpty(); + } + } + + public Iterator iterator() + { + return delegate().iterator(); + } + + public boolean remove(Object o) + { + synchronized (mutex) { + return delegate().remove(o); + } + } + + public boolean removeAll(Collection c) + { + synchronized (mutex) { + return delegate().removeAll(c); + } + } + + public boolean retainAll(Collection c) + { + synchronized (mutex) { + return delegate().retainAll(c); + } + } + + public int size() + { + synchronized (mutex) { + return delegate().size(); + } + } + + public Object[] toArray() + { + synchronized (mutex) { + return delegate().toArray(); + } + } + + public T[] toArray(T[] a) + { + synchronized (mutex) { + return delegate().toArray(a); + } + } + } + + @VisibleForTesting + static Set set(Set set, @Nullable Object mutex) + { + return new SynchronizedSet(set, mutex); + } + + static class SynchronizedSet extends Synchronized.SynchronizedCollection implements Set { + private static final long serialVersionUID = 0L; + + SynchronizedSet(Set delegate, @Nullable Object mutex) { + super(mutex, null); + } + + Set delegate() { + return (Set)super.delegate(); + } + + public boolean equals(Object o) { + if (o == this) { + return true; + } + synchronized (mutex) { + return delegate().equals(o); + } + } + + public int hashCode() { + synchronized (mutex) { + return delegate().hashCode(); + } + } + } + + + + private static SortedSet sortedSet(SortedSet set, @Nullable Object mutex) + { + return new SynchronizedSortedSet(set, mutex); + } + + static class SynchronizedSortedSet extends Synchronized.SynchronizedSet implements SortedSet { + private static final long serialVersionUID = 0L; + + SynchronizedSortedSet(SortedSet delegate, @Nullable Object mutex) { super(mutex); } + + SortedSet delegate() + { + return (SortedSet)super.delegate(); + } + + public Comparator comparator() + { + synchronized (mutex) { + return delegate().comparator(); + } + } + + public SortedSet subSet(E fromElement, E toElement) + { + synchronized (mutex) { + return Synchronized.sortedSet(delegate().subSet(fromElement, toElement), mutex); + } + } + + public SortedSet headSet(E toElement) + { + synchronized (mutex) { + return Synchronized.sortedSet(delegate().headSet(toElement), mutex); + } + } + + public SortedSet tailSet(E fromElement) + { + synchronized (mutex) { + return Synchronized.sortedSet(delegate().tailSet(fromElement), mutex); + } + } + + public E first() + { + synchronized (mutex) { + return delegate().first(); + } + } + + public E last() + { + synchronized (mutex) { + return delegate().last(); + } + } + } + + + private static List list(List list, @Nullable Object mutex) + { + return (list instanceof RandomAccess) ? new SynchronizedRandomAccessList(list, mutex) : new SynchronizedList(list, mutex); + } + + private static class SynchronizedList extends Synchronized.SynchronizedCollection implements List + { + private static final long serialVersionUID = 0L; + + SynchronizedList(List delegate, @Nullable Object mutex) { + super(mutex, null); + } + + List delegate() { + return (List)super.delegate(); + } + + public void add(int index, E element) + { + synchronized (mutex) { + delegate().add(index, element); + } + } + + public boolean addAll(int index, Collection c) + { + synchronized (mutex) { + return delegate().addAll(index, c); + } + } + + public E get(int index) + { + synchronized (mutex) { + return delegate().get(index); + } + } + + public int indexOf(Object o) + { + synchronized (mutex) { + return delegate().indexOf(o); + } + } + + public int lastIndexOf(Object o) + { + synchronized (mutex) { + return delegate().lastIndexOf(o); + } + } + + public ListIterator listIterator() + { + return delegate().listIterator(); + } + + public ListIterator listIterator(int index) + { + return delegate().listIterator(index); + } + + public E remove(int index) + { + synchronized (mutex) { + return delegate().remove(index); + } + } + + public E set(int index, E element) + { + synchronized (mutex) { + return delegate().set(index, element); + } + } + + public List subList(int fromIndex, int toIndex) + { + synchronized (mutex) { + return Synchronized.list(delegate().subList(fromIndex, toIndex), mutex); + } + } + + public boolean equals(Object o) { + if (o == this) { + return true; + } + synchronized (mutex) { + return delegate().equals(o); + } + } + + public int hashCode() { + synchronized (mutex) { + return delegate().hashCode(); + } + } + } + + private static class SynchronizedRandomAccessList extends Synchronized.SynchronizedList implements RandomAccess + { + private static final long serialVersionUID = 0L; + + SynchronizedRandomAccessList(List list, @Nullable Object mutex) { + super(mutex); + } + } + + + static Multiset multiset(Multiset multiset, @Nullable Object mutex) + { + if (((multiset instanceof SynchronizedMultiset)) || ((multiset instanceof ImmutableMultiset))) + { + return multiset; + } + return new SynchronizedMultiset(multiset, mutex); + } + + private static class SynchronizedMultiset extends Synchronized.SynchronizedCollection implements Multiset { + transient Set elementSet; + transient Set> entrySet; + private static final long serialVersionUID = 0L; + + SynchronizedMultiset(Multiset delegate, @Nullable Object mutex) { + super(mutex, null); + } + + Multiset delegate() { + return (Multiset)super.delegate(); + } + + public int count(Object o) + { + synchronized (mutex) { + return delegate().count(o); + } + } + + public int add(E e, int n) + { + synchronized (mutex) { + return delegate().add(e, n); + } + } + + public int remove(Object o, int n) + { + synchronized (mutex) { + return delegate().remove(o, n); + } + } + + public int setCount(E element, int count) + { + synchronized (mutex) { + return delegate().setCount(element, count); + } + } + + public boolean setCount(E element, int oldCount, int newCount) + { + synchronized (mutex) { + return delegate().setCount(element, oldCount, newCount); + } + } + + public Set elementSet() + { + synchronized (mutex) { + if (elementSet == null) { + elementSet = Synchronized.typePreservingSet(delegate().elementSet(), mutex); + } + return elementSet; + } + } + + public Set> entrySet() + { + synchronized (mutex) { + if (entrySet == null) { + entrySet = Synchronized.typePreservingSet(delegate().entrySet(), mutex); + } + return entrySet; + } + } + + public boolean equals(Object o) { + if (o == this) { + return true; + } + synchronized (mutex) { + return delegate().equals(o); + } + } + + public int hashCode() { + synchronized (mutex) { + return delegate().hashCode(); + } + } + } + + + + static Multimap multimap(Multimap multimap, @Nullable Object mutex) + { + if (((multimap instanceof SynchronizedMultimap)) || ((multimap instanceof ImmutableMultimap))) + { + return multimap; + } + return new SynchronizedMultimap(multimap, mutex); + } + + private static class SynchronizedMultimap extends Synchronized.SynchronizedObject implements Multimap + { + transient Set keySet; + transient Collection valuesCollection; + transient Collection> entries; + transient Map> asMap; + transient Multiset keys; + private static final long serialVersionUID = 0L; + + Multimap delegate() { + return (Multimap)super.delegate(); + } + + SynchronizedMultimap(Multimap delegate, @Nullable Object mutex) { + super(mutex); + } + + public int size() + { + synchronized (mutex) { + return delegate().size(); + } + } + + public boolean isEmpty() + { + synchronized (mutex) { + return delegate().isEmpty(); + } + } + + public boolean containsKey(Object key) + { + synchronized (mutex) { + return delegate().containsKey(key); + } + } + + public boolean containsValue(Object value) + { + synchronized (mutex) { + return delegate().containsValue(value); + } + } + + public boolean containsEntry(Object key, Object value) + { + synchronized (mutex) { + return delegate().containsEntry(key, value); + } + } + + public Collection get(K key) + { + synchronized (mutex) { + return Synchronized.typePreservingCollection(delegate().get(key), mutex); + } + } + + public boolean put(K key, V value) + { + synchronized (mutex) { + return delegate().put(key, value); + } + } + + public boolean putAll(K key, Iterable values) + { + synchronized (mutex) { + return delegate().putAll(key, values); + } + } + + public boolean putAll(Multimap multimap) + { + synchronized (mutex) { + return delegate().putAll(multimap); + } + } + + public Collection replaceValues(K key, Iterable values) + { + synchronized (mutex) { + return delegate().replaceValues(key, values); + } + } + + public boolean remove(Object key, Object value) + { + synchronized (mutex) { + return delegate().remove(key, value); + } + } + + public Collection removeAll(Object key) + { + synchronized (mutex) { + return delegate().removeAll(key); + } + } + + public void clear() + { + synchronized (mutex) { + delegate().clear(); + } + } + + public Set keySet() + { + synchronized (mutex) { + if (keySet == null) { + keySet = Synchronized.typePreservingSet(delegate().keySet(), mutex); + } + return keySet; + } + } + + public Collection values() + { + synchronized (mutex) { + if (valuesCollection == null) { + valuesCollection = Synchronized.collection(delegate().values(), mutex); + } + return valuesCollection; + } + } + + public Collection> entries() + { + synchronized (mutex) { + if (entries == null) { + entries = Synchronized.typePreservingCollection(delegate().entries(), mutex); + } + return entries; + } + } + + public Map> asMap() + { + synchronized (mutex) { + if (asMap == null) { + asMap = new Synchronized.SynchronizedAsMap(delegate().asMap(), mutex); + } + return asMap; + } + } + + public Multiset keys() + { + synchronized (mutex) { + if (keys == null) { + keys = Synchronized.multiset(delegate().keys(), mutex); + } + return keys; + } + } + + public boolean equals(Object o) { + if (o == this) { + return true; + } + synchronized (mutex) { + return delegate().equals(o); + } + } + + public int hashCode() { + synchronized (mutex) { + return delegate().hashCode(); + } + } + } + + + + static ListMultimap listMultimap(ListMultimap multimap, @Nullable Object mutex) + { + if (((multimap instanceof SynchronizedListMultimap)) || ((multimap instanceof ImmutableListMultimap))) + { + return multimap; + } + return new SynchronizedListMultimap(multimap, mutex); + } + + private static class SynchronizedListMultimap extends Synchronized.SynchronizedMultimap implements ListMultimap { + private static final long serialVersionUID = 0L; + + SynchronizedListMultimap(ListMultimap delegate, @Nullable Object mutex) { + super(mutex); + } + + ListMultimap delegate() { return (ListMultimap)super.delegate(); } + + public List get(K key) { + synchronized (mutex) { + return Synchronized.list(delegate().get(key), mutex); + } + } + + public List removeAll(Object key) { synchronized (mutex) { + return delegate().removeAll(key); + } + } + + public List replaceValues(K key, Iterable values) { + synchronized (mutex) { + return delegate().replaceValues(key, values); + } + } + } + + + static SetMultimap setMultimap(SetMultimap multimap, @Nullable Object mutex) + { + if (((multimap instanceof SynchronizedSetMultimap)) || ((multimap instanceof ImmutableSetMultimap))) + { + return multimap; + } + return new SynchronizedSetMultimap(multimap, mutex); + } + + private static class SynchronizedSetMultimap extends Synchronized.SynchronizedMultimap implements SetMultimap + { + transient Set> entrySet; + private static final long serialVersionUID = 0L; + + SynchronizedSetMultimap(SetMultimap delegate, @Nullable Object mutex) { + super(mutex); + } + + SetMultimap delegate() { return (SetMultimap)super.delegate(); } + + public Set get(K key) { + synchronized (mutex) { + return Synchronized.set(delegate().get(key), mutex); + } + } + + public Set removeAll(Object key) { synchronized (mutex) { + return delegate().removeAll(key); + } + } + + public Set replaceValues(K key, Iterable values) { + synchronized (mutex) { + return delegate().replaceValues(key, values); + } + } + + public Set> entries() { synchronized (mutex) { + if (entrySet == null) { + entrySet = Synchronized.set(delegate().entries(), mutex); + } + return entrySet; + } + } + } + + + static SortedSetMultimap sortedSetMultimap(SortedSetMultimap multimap, @Nullable Object mutex) + { + if ((multimap instanceof SynchronizedSortedSetMultimap)) { + return multimap; + } + return new SynchronizedSortedSetMultimap(multimap, mutex); + } + + private static class SynchronizedSortedSetMultimap extends Synchronized.SynchronizedSetMultimap implements SortedSetMultimap { + private static final long serialVersionUID = 0L; + + SynchronizedSortedSetMultimap(SortedSetMultimap delegate, @Nullable Object mutex) { + super(mutex); + } + + SortedSetMultimap delegate() { return (SortedSetMultimap)super.delegate(); } + + public SortedSet get(K key) { + synchronized (mutex) { + return Synchronized.sortedSet(delegate().get(key), mutex); + } + } + + public SortedSet removeAll(Object key) { synchronized (mutex) { + return delegate().removeAll(key); + } + } + + public SortedSet replaceValues(K key, Iterable values) { + synchronized (mutex) { + return delegate().replaceValues(key, values); + } + } + + public Comparator valueComparator() { + synchronized (mutex) { + return delegate().valueComparator(); + } + } + } + + + private static Collection typePreservingCollection(Collection collection, @Nullable Object mutex) + { + if ((collection instanceof SortedSet)) { + return sortedSet((SortedSet)collection, mutex); + } + if ((collection instanceof Set)) { + return set((Set)collection, mutex); + } + if ((collection instanceof List)) { + return list((List)collection, mutex); + } + return collection(collection, mutex); + } + + private static Set typePreservingSet(Set set, @Nullable Object mutex) + { + if ((set instanceof SortedSet)) { + return sortedSet((SortedSet)set, mutex); + } + return set(set, mutex); + } + + private static class SynchronizedAsMapEntries extends Synchronized.SynchronizedSet>> + { + private static final long serialVersionUID = 0L; + + SynchronizedAsMapEntries(Set>> delegate, @Nullable Object mutex) { + super(mutex); + } + + public Iterator>> iterator() + { + final Iterator>> iterator = super.iterator(); + new ForwardingIterator() { + protected Iterator>> delegate() { + return iterator; + } + + public Map.Entry> next() { + final Map.Entry> entry = (Map.Entry)super.next(); + new ForwardingMapEntry() { + protected Map.Entry> delegate() { + return entry; + } + + public Collection getValue() { return Synchronized.typePreservingCollection((Collection)entry.getValue(), mutex); } + }; + } + }; + } + + + + public Object[] toArray() + { + synchronized (mutex) { + return ObjectArrays.toArrayImpl(delegate()); + } + } + + public T[] toArray(T[] array) { synchronized (mutex) { + return ObjectArrays.toArrayImpl(delegate(), array); + } + } + + public boolean contains(Object o) { synchronized (mutex) { + return Maps.containsEntryImpl(delegate(), o); + } + } + + public boolean containsAll(Collection c) { synchronized (mutex) { + return Collections2.containsAllImpl(delegate(), c); + } + } + + public boolean equals(Object o) { if (o == this) { + return true; + } + synchronized (mutex) { + return Sets.equalsImpl(delegate(), o); + } + } + + public boolean remove(Object o) { synchronized (mutex) { + return Maps.removeEntryImpl(delegate(), o); + } + } + + public boolean removeAll(Collection c) { synchronized (mutex) { + return Iterators.removeAll(delegate().iterator(), c); + } + } + + public boolean retainAll(Collection c) { synchronized (mutex) { + return Iterators.retainAll(delegate().iterator(), c); + } + } + } + + + @VisibleForTesting + static Map map(Map map, @Nullable Object mutex) + { + return new SynchronizedMap(map, mutex); + } + + private static class SynchronizedMap extends Synchronized.SynchronizedObject implements Map { + transient Set keySet; + transient Collection values; + transient Set> entrySet; + private static final long serialVersionUID = 0L; + + SynchronizedMap(Map delegate, @Nullable Object mutex) { + super(mutex); + } + + Map delegate() + { + return (Map)super.delegate(); + } + + public void clear() + { + synchronized (mutex) { + delegate().clear(); + } + } + + public boolean containsKey(Object key) + { + synchronized (mutex) { + return delegate().containsKey(key); + } + } + + public boolean containsValue(Object value) + { + synchronized (mutex) { + return delegate().containsValue(value); + } + } + + public Set> entrySet() + { + synchronized (mutex) { + if (entrySet == null) { + entrySet = Synchronized.set(delegate().entrySet(), mutex); + } + return entrySet; + } + } + + public V get(Object key) + { + synchronized (mutex) { + return delegate().get(key); + } + } + + public boolean isEmpty() + { + synchronized (mutex) { + return delegate().isEmpty(); + } + } + + public Set keySet() + { + synchronized (mutex) { + if (keySet == null) { + keySet = Synchronized.set(delegate().keySet(), mutex); + } + return keySet; + } + } + + public V put(K key, V value) + { + synchronized (mutex) { + return delegate().put(key, value); + } + } + + public void putAll(Map map) + { + synchronized (mutex) { + delegate().putAll(map); + } + } + + public V remove(Object key) + { + synchronized (mutex) { + return delegate().remove(key); + } + } + + public int size() + { + synchronized (mutex) { + return delegate().size(); + } + } + + public Collection values() + { + synchronized (mutex) { + if (values == null) { + values = Synchronized.collection(delegate().values(), mutex); + } + return values; + } + } + + public boolean equals(Object o) { + if (o == this) { + return true; + } + synchronized (mutex) { + return delegate().equals(o); + } + } + + public int hashCode() { + synchronized (mutex) { + return delegate().hashCode(); + } + } + } + + + + static SortedMap sortedMap(SortedMap sortedMap, @Nullable Object mutex) + { + return new SynchronizedSortedMap(sortedMap, mutex); + } + + static class SynchronizedSortedMap extends Synchronized.SynchronizedMap implements SortedMap { + private static final long serialVersionUID = 0L; + + SynchronizedSortedMap(SortedMap delegate, @Nullable Object mutex) { + super(mutex); + } + + SortedMap delegate() { + return (SortedMap)super.delegate(); + } + + public Comparator comparator() { + synchronized (mutex) { + return delegate().comparator(); + } + } + + public K firstKey() { + synchronized (mutex) { + return delegate().firstKey(); + } + } + + public SortedMap headMap(K toKey) { + synchronized (mutex) { + return Synchronized.sortedMap(delegate().headMap(toKey), mutex); + } + } + + public K lastKey() { + synchronized (mutex) { + return delegate().lastKey(); + } + } + + public SortedMap subMap(K fromKey, K toKey) { + synchronized (mutex) { + return Synchronized.sortedMap(delegate().subMap(fromKey, toKey), mutex); + } + } + + public SortedMap tailMap(K fromKey) { + synchronized (mutex) { + return Synchronized.sortedMap(delegate().tailMap(fromKey), mutex); + } + } + } + + + static BiMap biMap(BiMap bimap, @Nullable Object mutex) + { + if (((bimap instanceof SynchronizedBiMap)) || ((bimap instanceof ImmutableBiMap))) + { + return bimap; + } + return new SynchronizedBiMap(bimap, mutex, null, null); + } + + @VisibleForTesting + static class SynchronizedBiMap extends Synchronized.SynchronizedMap implements BiMap, Serializable { + private transient Set valueSet; + private transient BiMap inverse; + private static final long serialVersionUID = 0L; + + private SynchronizedBiMap(BiMap delegate, @Nullable Object mutex, @Nullable BiMap inverse) { + super(mutex); + this.inverse = inverse; + } + + BiMap delegate() { + return (BiMap)super.delegate(); + } + + public Set values() { + synchronized (mutex) { + if (valueSet == null) { + valueSet = Synchronized.set(delegate().values(), mutex); + } + return valueSet; + } + } + + public V forcePut(K key, V value) + { + synchronized (mutex) { + return delegate().forcePut(key, value); + } + } + + public BiMap inverse() + { + synchronized (mutex) { + if (inverse == null) { + inverse = new SynchronizedBiMap(delegate().inverse(), mutex, this); + } + + return inverse; + } + } + } + + private static class SynchronizedAsMap extends Synchronized.SynchronizedMap> + { + transient Set>> asMapEntrySet; + transient Collection> asMapValues; + private static final long serialVersionUID = 0L; + + SynchronizedAsMap(Map> delegate, @Nullable Object mutex) + { + super(mutex); + } + + public Collection get(Object key) { + synchronized (mutex) { + Collection collection = (Collection)super.get(key); + return collection == null ? null : Synchronized.typePreservingCollection(collection, mutex); + } + } + + public Set>> entrySet() + { + synchronized (mutex) { + if (asMapEntrySet == null) { + asMapEntrySet = new Synchronized.SynchronizedAsMapEntries(delegate().entrySet(), mutex); + } + + return asMapEntrySet; + } + } + + public Collection> values() { + synchronized (mutex) { + if (asMapValues == null) { + asMapValues = new Synchronized.SynchronizedAsMapValues(delegate().values(), mutex); + } + + return asMapValues; + } + } + + public boolean containsValue(Object o) + { + return values().contains(o); + } + } + + private static class SynchronizedAsMapValues extends Synchronized.SynchronizedCollection> + { + private static final long serialVersionUID = 0L; + + SynchronizedAsMapValues(Collection> delegate, @Nullable Object mutex) + { + super(mutex, null); + } + + public Iterator> iterator() + { + final Iterator> iterator = super.iterator(); + new ForwardingIterator() { + protected Iterator> delegate() { + return iterator; + } + + public Collection next() { return Synchronized.typePreservingCollection((Collection)super.next(), mutex); } + }; + } + } + + @GwtIncompatible("NavigableSet") + @VisibleForTesting + static class SynchronizedNavigableSet extends Synchronized.SynchronizedSortedSet implements NavigableSet + { + transient NavigableSet descendingSet; + private static final long serialVersionUID = 0L; + + SynchronizedNavigableSet(NavigableSet delegate, @Nullable Object mutex) { + super(mutex); + } + + NavigableSet delegate() { + return (NavigableSet)super.delegate(); + } + + public E ceiling(E e) { + synchronized (mutex) { + return delegate().ceiling(e); + } + } + + public Iterator descendingIterator() { + return delegate().descendingIterator(); + } + + + public NavigableSet descendingSet() + { + synchronized (mutex) { + if (descendingSet == null) { + NavigableSet dS = Synchronized.navigableSet(delegate().descendingSet(), mutex); + + descendingSet = dS; + return dS; + } + return descendingSet; + } + } + + public E floor(E e) { + synchronized (mutex) { + return delegate().floor(e); + } + } + + public NavigableSet headSet(E toElement, boolean inclusive) { + synchronized (mutex) { + return Synchronized.navigableSet(delegate().headSet(toElement, inclusive), mutex); + } + } + + public E higher(E e) + { + synchronized (mutex) { + return delegate().higher(e); + } + } + + public E lower(E e) { + synchronized (mutex) { + return delegate().lower(e); + } + } + + public E pollFirst() { + synchronized (mutex) { + return delegate().pollFirst(); + } + } + + public E pollLast() { + synchronized (mutex) { + return delegate().pollLast(); + } + } + + public NavigableSet subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) + { + synchronized (mutex) { + return Synchronized.navigableSet(delegate().subSet(fromElement, fromInclusive, toElement, toInclusive), mutex); + } + } + + public NavigableSet tailSet(E fromElement, boolean inclusive) + { + synchronized (mutex) { + return Synchronized.navigableSet(delegate().tailSet(fromElement, inclusive), mutex); + } + } + + public SortedSet headSet(E toElement) + { + return headSet(toElement, false); + } + + public SortedSet subSet(E fromElement, E toElement) { + return subSet(fromElement, true, toElement, false); + } + + public SortedSet tailSet(E fromElement) { + return tailSet(fromElement, true); + } + } + + + + @GwtIncompatible("NavigableSet") + static NavigableSet navigableSet(NavigableSet navigableSet, @Nullable Object mutex) + { + return new SynchronizedNavigableSet(navigableSet, mutex); + } + + @GwtIncompatible("NavigableSet") + static NavigableSet navigableSet(NavigableSet navigableSet) { + return navigableSet(navigableSet, null); + } + + @GwtIncompatible("NavigableMap") + static NavigableMap navigableMap(NavigableMap navigableMap) + { + return navigableMap(navigableMap, null); + } + + + + @GwtIncompatible("NavigableMap") + static NavigableMap navigableMap(NavigableMap navigableMap, @Nullable Object mutex) { return new SynchronizedNavigableMap(navigableMap, mutex); } + + @GwtIncompatible("NavigableMap") + @VisibleForTesting + static class SynchronizedNavigableMap extends Synchronized.SynchronizedSortedMap implements NavigableMap { transient NavigableSet descendingKeySet; + transient NavigableMap descendingMap; + transient NavigableSet navigableKeySet; + private static final long serialVersionUID = 0L; + + SynchronizedNavigableMap(NavigableMap delegate, @Nullable Object mutex) { super(mutex); } + + NavigableMap delegate() + { + return (NavigableMap)super.delegate(); + } + + public Map.Entry ceilingEntry(K key) { + synchronized (mutex) { + return Synchronized.nullableSynchronizedEntry(delegate().ceilingEntry(key), mutex); + } + } + + public K ceilingKey(K key) { + synchronized (mutex) { + return delegate().ceilingKey(key); + } + } + + + public NavigableSet descendingKeySet() + { + synchronized (mutex) { + if (descendingKeySet == null) { + return this.descendingKeySet = Synchronized.navigableSet(delegate().descendingKeySet(), mutex); + } + + return descendingKeySet; + } + } + + + public NavigableMap descendingMap() + { + synchronized (mutex) { + if (descendingMap == null) { + return this.descendingMap = Synchronized.navigableMap(delegate().descendingMap(), mutex); + } + + return descendingMap; + } + } + + public Map.Entry firstEntry() { + synchronized (mutex) { + return Synchronized.nullableSynchronizedEntry(delegate().firstEntry(), mutex); + } + } + + public Map.Entry floorEntry(K key) { + synchronized (mutex) { + return Synchronized.nullableSynchronizedEntry(delegate().floorEntry(key), mutex); + } + } + + public K floorKey(K key) { + synchronized (mutex) { + return delegate().floorKey(key); + } + } + + public NavigableMap headMap(K toKey, boolean inclusive) { + synchronized (mutex) { + return Synchronized.navigableMap(delegate().headMap(toKey, inclusive), mutex); + } + } + + public Map.Entry higherEntry(K key) + { + synchronized (mutex) { + return Synchronized.nullableSynchronizedEntry(delegate().higherEntry(key), mutex); + } + } + + public K higherKey(K key) { + synchronized (mutex) { + return delegate().higherKey(key); + } + } + + public Map.Entry lastEntry() { + synchronized (mutex) { + return Synchronized.nullableSynchronizedEntry(delegate().lastEntry(), mutex); + } + } + + public Map.Entry lowerEntry(K key) { + synchronized (mutex) { + return Synchronized.nullableSynchronizedEntry(delegate().lowerEntry(key), mutex); + } + } + + public K lowerKey(K key) { + synchronized (mutex) { + return delegate().lowerKey(key); + } + } + + public Set keySet() { + return navigableKeySet(); + } + + + public NavigableSet navigableKeySet() + { + synchronized (mutex) { + if (navigableKeySet == null) { + return this.navigableKeySet = Synchronized.navigableSet(delegate().navigableKeySet(), mutex); + } + + return navigableKeySet; + } + } + + public Map.Entry pollFirstEntry() { + synchronized (mutex) { + return Synchronized.nullableSynchronizedEntry(delegate().pollFirstEntry(), mutex); + } + } + + public Map.Entry pollLastEntry() { + synchronized (mutex) { + return Synchronized.nullableSynchronizedEntry(delegate().pollLastEntry(), mutex); + } + } + + public NavigableMap subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) + { + synchronized (mutex) { + return Synchronized.navigableMap(delegate().subMap(fromKey, fromInclusive, toKey, toInclusive), mutex); + } + } + + + public NavigableMap tailMap(K fromKey, boolean inclusive) + { + synchronized (mutex) { + return Synchronized.navigableMap(delegate().tailMap(fromKey, inclusive), mutex); + } + } + + public SortedMap headMap(K toKey) + { + return headMap(toKey, false); + } + + public SortedMap subMap(K fromKey, K toKey) { + return subMap(fromKey, true, toKey, false); + } + + public SortedMap tailMap(K fromKey) { + return tailMap(fromKey, true); + } + } + + + + @GwtIncompatible("works but is needed only for NavigableMap") + private static Map.Entry nullableSynchronizedEntry(@Nullable Map.Entry entry, @Nullable Object mutex) + { + if (entry == null) { + return null; + } + return new SynchronizedEntry(entry, mutex); + } + + @GwtIncompatible("works but is needed only for NavigableMap") + private static class SynchronizedEntry extends Synchronized.SynchronizedObject implements Map.Entry { + private static final long serialVersionUID = 0L; + + SynchronizedEntry(Map.Entry delegate, @Nullable Object mutex) { + super(mutex); + } + + Map.Entry delegate() + { + return (Map.Entry)super.delegate(); + } + + public boolean equals(Object obj) { + synchronized (mutex) { + return delegate().equals(obj); + } + } + + public int hashCode() { + synchronized (mutex) { + return delegate().hashCode(); + } + } + + public K getKey() { + synchronized (mutex) { + return delegate().getKey(); + } + } + + public V getValue() { + synchronized (mutex) { + return delegate().getValue(); + } + } + + public V setValue(V value) { + synchronized (mutex) { + return delegate().setValue(value); + } + } + } + + + static Queue queue(Queue queue, @Nullable Object mutex) + { + return (queue instanceof SynchronizedQueue) ? queue : new SynchronizedQueue(queue, mutex); + } + + private static class SynchronizedQueue extends Synchronized.SynchronizedCollection implements Queue + { + private static final long serialVersionUID = 0L; + + SynchronizedQueue(Queue delegate, @Nullable Object mutex) + { + super(mutex, null); + } + + Queue delegate() { + return (Queue)super.delegate(); + } + + public E element() + { + synchronized (mutex) { + return delegate().element(); + } + } + + public boolean offer(E e) + { + synchronized (mutex) { + return delegate().offer(e); + } + } + + public E peek() + { + synchronized (mutex) { + return delegate().peek(); + } + } + + public E poll() + { + synchronized (mutex) { + return delegate().poll(); + } + } + + public E remove() + { + synchronized (mutex) { + return delegate().remove(); + } + } + } + + + @GwtIncompatible("Deque") + static Deque deque(Deque deque, @Nullable Object mutex) + { + return new SynchronizedDeque(deque, mutex); + } + + @GwtIncompatible("Deque") + private static final class SynchronizedDeque extends Synchronized.SynchronizedQueue implements Deque { + private static final long serialVersionUID = 0L; + + SynchronizedDeque(Deque delegate, @Nullable Object mutex) { + super(mutex); + } + + Deque delegate() { + return (Deque)super.delegate(); + } + + public void addFirst(E e) + { + synchronized (mutex) { + delegate().addFirst(e); + } + } + + public void addLast(E e) + { + synchronized (mutex) { + delegate().addLast(e); + } + } + + public boolean offerFirst(E e) + { + synchronized (mutex) { + return delegate().offerFirst(e); + } + } + + public boolean offerLast(E e) + { + synchronized (mutex) { + return delegate().offerLast(e); + } + } + + public E removeFirst() + { + synchronized (mutex) { + return delegate().removeFirst(); + } + } + + public E removeLast() + { + synchronized (mutex) { + return delegate().removeLast(); + } + } + + public E pollFirst() + { + synchronized (mutex) { + return delegate().pollFirst(); + } + } + + public E pollLast() + { + synchronized (mutex) { + return delegate().pollLast(); + } + } + + public E getFirst() + { + synchronized (mutex) { + return delegate().getFirst(); + } + } + + public E getLast() + { + synchronized (mutex) { + return delegate().getLast(); + } + } + + public E peekFirst() + { + synchronized (mutex) { + return delegate().peekFirst(); + } + } + + public E peekLast() + { + synchronized (mutex) { + return delegate().peekLast(); + } + } + + public boolean removeFirstOccurrence(Object o) + { + synchronized (mutex) { + return delegate().removeFirstOccurrence(o); + } + } + + public boolean removeLastOccurrence(Object o) + { + synchronized (mutex) { + return delegate().removeLastOccurrence(o); + } + } + + public void push(E e) + { + synchronized (mutex) { + delegate().push(e); + } + } + + public E pop() + { + synchronized (mutex) { + return delegate().pop(); + } + } + + public Iterator descendingIterator() + { + synchronized (mutex) { + return delegate().descendingIterator(); + } + } + } +} diff --git a/src/minecraft/com/google/common/collect/Table.java b/src/minecraft/com/google/common/collect/Table.java new file mode 100644 index 0000000..5dfac89 --- /dev/null +++ b/src/minecraft/com/google/common/collect/Table.java @@ -0,0 +1,66 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Collection; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + +@GwtCompatible +public abstract interface Table +{ + public abstract boolean contains(@Nullable Object paramObject1, @Nullable Object paramObject2); + + public abstract boolean containsRow(@Nullable Object paramObject); + + public abstract boolean containsColumn(@Nullable Object paramObject); + + public abstract boolean containsValue(@Nullable Object paramObject); + + public abstract V get(@Nullable Object paramObject1, @Nullable Object paramObject2); + + public abstract boolean isEmpty(); + + public abstract int size(); + + public abstract boolean equals(@Nullable Object paramObject); + + public abstract int hashCode(); + + public abstract void clear(); + + public abstract V put(R paramR, C paramC, V paramV); + + public abstract void putAll(Table paramTable); + + public abstract V remove(@Nullable Object paramObject1, @Nullable Object paramObject2); + + public abstract Map row(R paramR); + + public abstract Map column(C paramC); + + public abstract Set> cellSet(); + + public abstract Set rowKeySet(); + + public abstract Set columnKeySet(); + + public abstract Collection values(); + + public abstract Map> rowMap(); + + public abstract Map> columnMap(); + + public static abstract interface Cell + { + public abstract R getRowKey(); + + public abstract C getColumnKey(); + + public abstract V getValue(); + + public abstract boolean equals(@Nullable Object paramObject); + + public abstract int hashCode(); + } +} diff --git a/src/minecraft/com/google/common/collect/Tables.java b/src/minecraft/com/google/common/collect/Tables.java new file mode 100644 index 0000000..cfef350 --- /dev/null +++ b/src/minecraft/com/google/common/collect/Tables.java @@ -0,0 +1,608 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import java.io.Serializable; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public final class Tables +{ + private Tables() {} + + public static Table.Cell immutableCell(@Nullable R rowKey, @Nullable C columnKey, @Nullable V value) + { + return new ImmutableCell(rowKey, columnKey, value); + } + + static final class ImmutableCell extends Tables.AbstractCell implements Serializable + { + private final R rowKey; + private final C columnKey; + private final V value; + private static final long serialVersionUID = 0L; + + ImmutableCell(@Nullable R rowKey, @Nullable C columnKey, @Nullable V value) { + this.rowKey = rowKey; + this.columnKey = columnKey; + this.value = value; + } + + public R getRowKey() + { + return rowKey; + } + + public C getColumnKey() { + return columnKey; + } + + public V getValue() { + return value; + } + } + + static abstract class AbstractCell + implements Table.Cell + { + AbstractCell() {} + + public boolean equals(Object obj) + { + if (obj == this) { + return true; + } + if ((obj instanceof Table.Cell)) { + Table.Cell other = (Table.Cell)obj; + return (Objects.equal(getRowKey(), other.getRowKey())) && (Objects.equal(getColumnKey(), other.getColumnKey())) && (Objects.equal(getValue(), other.getValue())); + } + + + return false; + } + + public int hashCode() { + return Objects.hashCode(new Object[] { getRowKey(), getColumnKey(), getValue() }); + } + + public String toString() { + return "(" + getRowKey() + "," + getColumnKey() + ")=" + getValue(); + } + } + + + + + + + + + + + + + + + public static Table transpose(Table table) + { + return (table instanceof TransposeTable) ? original : new TransposeTable(table); + } + + private static class TransposeTable extends AbstractTable + { + final Table original; + + TransposeTable(Table original) + { + this.original = ((Table)Preconditions.checkNotNull(original)); + } + + public void clear() + { + original.clear(); + } + + public Map column(R columnKey) + { + return original.row(columnKey); + } + + public Set columnKeySet() + { + return original.rowKeySet(); + } + + public Map> columnMap() + { + return original.rowMap(); + } + + + public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) + { + return original.contains(columnKey, rowKey); + } + + public boolean containsColumn(@Nullable Object columnKey) + { + return original.containsRow(columnKey); + } + + public boolean containsRow(@Nullable Object rowKey) + { + return original.containsColumn(rowKey); + } + + public boolean containsValue(@Nullable Object value) + { + return original.containsValue(value); + } + + public V get(@Nullable Object rowKey, @Nullable Object columnKey) + { + return original.get(columnKey, rowKey); + } + + public V put(C rowKey, R columnKey, V value) + { + return original.put(columnKey, rowKey, value); + } + + public void putAll(Table table) + { + original.putAll(Tables.transpose(table)); + } + + public V remove(@Nullable Object rowKey, @Nullable Object columnKey) + { + return original.remove(columnKey, rowKey); + } + + public Map row(C rowKey) + { + return original.column(rowKey); + } + + public Set rowKeySet() + { + return original.columnKeySet(); + } + + public Map> rowMap() + { + return original.columnMap(); + } + + public int size() + { + return original.size(); + } + + public Collection values() + { + return original.values(); + } + + + private static final Function, Table.Cell> TRANSPOSE_CELL = new Function() + { + public Table.Cell apply(Table.Cell cell) + { + return Tables.immutableCell(cell.getColumnKey(), cell.getRowKey(), cell.getValue()); + } + }; + + + + Iterator> cellIterator() + { + return Iterators.transform(original.cellSet().iterator(), TRANSPOSE_CELL); + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @Beta + public static Table newCustomTable(Map> backingMap, Supplier> factory) + { + Preconditions.checkArgument(backingMap.isEmpty()); + Preconditions.checkNotNull(factory); + + return new StandardTable(backingMap, factory); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + @Beta + public static Table transformValues(Table fromTable, Function function) + { + return new TransformedTable(fromTable, function); + } + + private static class TransformedTable extends AbstractTable + { + final Table fromTable; + final Function function; + + TransformedTable(Table fromTable, Function function) + { + this.fromTable = ((Table)Preconditions.checkNotNull(fromTable)); + this.function = ((Function)Preconditions.checkNotNull(function)); + } + + public boolean contains(Object rowKey, Object columnKey) { + return fromTable.contains(rowKey, columnKey); + } + + + public V2 get(Object rowKey, Object columnKey) + { + return contains(rowKey, columnKey) ? function.apply(fromTable.get(rowKey, columnKey)) : null; + } + + public int size() + { + return fromTable.size(); + } + + public void clear() { + fromTable.clear(); + } + + public V2 put(R rowKey, C columnKey, V2 value) { + throw new UnsupportedOperationException(); + } + + public void putAll(Table table) + { + throw new UnsupportedOperationException(); + } + + public V2 remove(Object rowKey, Object columnKey) { + return contains(rowKey, columnKey) ? function.apply(fromTable.remove(rowKey, columnKey)) : null; + } + + public Map row(R rowKey) + { + return Maps.transformValues(fromTable.row(rowKey), function); + } + + public Map column(C columnKey) { + return Maps.transformValues(fromTable.column(columnKey), function); + } + + Function, Table.Cell> cellFunction() { + new Function() { + public Table.Cell apply(Table.Cell cell) { + return Tables.immutableCell(cell.getRowKey(), cell.getColumnKey(), function.apply(cell.getValue())); + } + }; + } + + + + Iterator> cellIterator() + { + return Iterators.transform(fromTable.cellSet().iterator(), cellFunction()); + } + + public Set rowKeySet() { + return fromTable.rowKeySet(); + } + + public Set columnKeySet() { + return fromTable.columnKeySet(); + } + + Collection createValues() + { + return Collections2.transform(fromTable.values(), function); + } + + public Map> rowMap() { + Function, Map> rowFunction = new Function() + { + public Map apply(Map row) { + return Maps.transformValues(row, function); + } + }; + return Maps.transformValues(fromTable.rowMap(), rowFunction); + } + + public Map> columnMap() { + Function, Map> columnFunction = new Function() + { + public Map apply(Map column) { + return Maps.transformValues(column, function); + } + }; + return Maps.transformValues(fromTable.columnMap(), columnFunction); + } + } + + + + + + + + + + + + + + + + + public static Table unmodifiableTable(Table table) + { + return new UnmodifiableTable(table); + } + + private static class UnmodifiableTable extends ForwardingTable implements Serializable { + final Table delegate; + private static final long serialVersionUID = 0L; + + UnmodifiableTable(Table delegate) { + this.delegate = ((Table)Preconditions.checkNotNull(delegate)); + } + + + protected Table delegate() + { + return delegate; + } + + public Set> cellSet() + { + return Collections.unmodifiableSet(super.cellSet()); + } + + public void clear() + { + throw new UnsupportedOperationException(); + } + + public Map column(@Nullable C columnKey) + { + return Collections.unmodifiableMap(super.column(columnKey)); + } + + public Set columnKeySet() + { + return Collections.unmodifiableSet(super.columnKeySet()); + } + + public Map> columnMap() + { + Function, Map> wrapper = Tables.access$000(); + return Collections.unmodifiableMap(Maps.transformValues(super.columnMap(), wrapper)); + } + + public V put(@Nullable R rowKey, @Nullable C columnKey, @Nullable V value) + { + throw new UnsupportedOperationException(); + } + + public void putAll(Table table) + { + throw new UnsupportedOperationException(); + } + + public V remove(@Nullable Object rowKey, @Nullable Object columnKey) + { + throw new UnsupportedOperationException(); + } + + public Map row(@Nullable R rowKey) + { + return Collections.unmodifiableMap(super.row(rowKey)); + } + + public Set rowKeySet() + { + return Collections.unmodifiableSet(super.rowKeySet()); + } + + public Map> rowMap() + { + Function, Map> wrapper = Tables.access$000(); + return Collections.unmodifiableMap(Maps.transformValues(super.rowMap(), wrapper)); + } + + public Collection values() + { + return Collections.unmodifiableCollection(super.values()); + } + } + + + + + + + + + + + + + + + + + + + + + @Beta + public static RowSortedTable unmodifiableRowSortedTable(RowSortedTable table) + { + return new UnmodifiableRowSortedMap(table); + } + + static final class UnmodifiableRowSortedMap extends Tables.UnmodifiableTable implements RowSortedTable { + private static final long serialVersionUID = 0L; + + public UnmodifiableRowSortedMap(RowSortedTable delegate) { + super(); + } + + protected RowSortedTable delegate() + { + return (RowSortedTable)super.delegate(); + } + + public SortedMap> rowMap() + { + Function, Map> wrapper = Tables.access$000(); + return Collections.unmodifiableSortedMap(Maps.transformValues(delegate().rowMap(), wrapper)); + } + + public SortedSet rowKeySet() + { + return Collections.unmodifiableSortedSet(delegate().rowKeySet()); + } + } + + + + private static Function, Map> unmodifiableWrapper() + { + return UNMODIFIABLE_WRAPPER; + } + + private static final Function, ? extends Map> UNMODIFIABLE_WRAPPER = new Function() + { + public Map apply(Map input) + { + return Collections.unmodifiableMap(input); + } + }; + + static boolean equalsImpl(Table table, @Nullable Object obj) { + if (obj == table) + return true; + if ((obj instanceof Table)) { + Table that = (Table)obj; + return table.cellSet().equals(that.cellSet()); + } + return false; + } +} diff --git a/src/minecraft/com/google/common/collect/TransformedIterator.java b/src/minecraft/com/google/common/collect/TransformedIterator.java new file mode 100644 index 0000000..fecb334 --- /dev/null +++ b/src/minecraft/com/google/common/collect/TransformedIterator.java @@ -0,0 +1,55 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.Iterator; + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +abstract class TransformedIterator + implements Iterator +{ + final Iterator backingIterator; + + TransformedIterator(Iterator backingIterator) + { + this.backingIterator = ((Iterator)Preconditions.checkNotNull(backingIterator)); + } + + abstract T transform(F paramF); + + public final boolean hasNext() + { + return backingIterator.hasNext(); + } + + public final T next() + { + return transform(backingIterator.next()); + } + + public final void remove() + { + backingIterator.remove(); + } +} diff --git a/src/minecraft/com/google/common/collect/TransformedListIterator.java b/src/minecraft/com/google/common/collect/TransformedListIterator.java new file mode 100644 index 0000000..1c6d428 --- /dev/null +++ b/src/minecraft/com/google/common/collect/TransformedListIterator.java @@ -0,0 +1,71 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.ListIterator; + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +abstract class TransformedListIterator + extends TransformedIterator + implements ListIterator +{ + TransformedListIterator(ListIterator backingIterator) + { + super(backingIterator); + } + + private ListIterator backingIterator() { + return Iterators.cast(backingIterator); + } + + public final boolean hasPrevious() + { + return backingIterator().hasPrevious(); + } + + public final T previous() + { + return transform(backingIterator().previous()); + } + + public final int nextIndex() + { + return backingIterator().nextIndex(); + } + + public final int previousIndex() + { + return backingIterator().previousIndex(); + } + + public void set(T element) + { + throw new UnsupportedOperationException(); + } + + public void add(T element) + { + throw new UnsupportedOperationException(); + } +} diff --git a/src/minecraft/com/google/common/collect/TreeBasedTable.java b/src/minecraft/com/google/common/collect/TreeBasedTable.java new file mode 100644 index 0000000..5d0850c --- /dev/null +++ b/src/minecraft/com/google/common/collect/TreeBasedTable.java @@ -0,0 +1,350 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import java.io.Serializable; +import java.util.Comparator; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.TreeMap; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true) +@Beta +public class TreeBasedTable + extends StandardRowSortedTable +{ + private final Comparator columnComparator; + private static final long serialVersionUID = 0L; + + private static class Factory + implements Supplier>, Serializable + { + final Comparator comparator; + private static final long serialVersionUID = 0L; + + Factory(Comparator comparator) + { + this.comparator = comparator; + } + + public TreeMap get() { + return new TreeMap(comparator); + } + } + + + + + + + + + + + + public static TreeBasedTable create() + { + return new TreeBasedTable(Ordering.natural(), Ordering.natural()); + } + + + + + + + + + + + public static TreeBasedTable create(Comparator rowComparator, Comparator columnComparator) + { + Preconditions.checkNotNull(rowComparator); + Preconditions.checkNotNull(columnComparator); + return new TreeBasedTable(rowComparator, columnComparator); + } + + + + + + public static TreeBasedTable create(TreeBasedTable table) + { + TreeBasedTable result = new TreeBasedTable(table.rowComparator(), table.columnComparator()); + + + result.putAll(table); + return result; + } + + TreeBasedTable(Comparator rowComparator, Comparator columnComparator) + { + super(new TreeMap(rowComparator), new Factory(columnComparator)); + + this.columnComparator = columnComparator; + } + + + + + + + public Comparator rowComparator() + { + return rowKeySet().comparator(); + } + + + + + public Comparator columnComparator() + { + return columnComparator; + } + + + + + + + + + + + + + + + + public SortedMap row(R rowKey) { return new TreeRow(rowKey); } + + private class TreeRow extends StandardTable.Row implements SortedMap { @Nullable + final C lowerBound; + @Nullable + final C upperBound; + transient SortedMap wholeRow; + + TreeRow() { this(rowKey, null, null); } + + TreeRow(@Nullable C rowKey, @Nullable C lowerBound) + { + super(rowKey); + this.lowerBound = lowerBound; + this.upperBound = upperBound; + Preconditions.checkArgument((lowerBound == null) || (upperBound == null) || (compare(lowerBound, upperBound) <= 0)); + } + + public SortedSet keySet() + { + return new Maps.SortedKeySet(this); + } + + public Comparator comparator() { + return columnComparator(); + } + + + int compare(Object a, Object b) + { + Comparator cmp = comparator(); + return cmp.compare(a, b); + } + + boolean rangeContains(@Nullable Object o) { + return (o != null) && ((lowerBound == null) || (compare(lowerBound, o) <= 0)) && ((upperBound == null) || (compare(upperBound, o) > 0)); + } + + public SortedMap subMap(C fromKey, C toKey) + { + Preconditions.checkArgument((rangeContains(Preconditions.checkNotNull(fromKey))) && (rangeContains(Preconditions.checkNotNull(toKey)))); + + return new TreeRow(TreeBasedTable.this, rowKey, fromKey, toKey); + } + + public SortedMap headMap(C toKey) { + Preconditions.checkArgument(rangeContains(Preconditions.checkNotNull(toKey))); + return new TreeRow(TreeBasedTable.this, rowKey, lowerBound, toKey); + } + + public SortedMap tailMap(C fromKey) { + Preconditions.checkArgument(rangeContains(Preconditions.checkNotNull(fromKey))); + return new TreeRow(TreeBasedTable.this, rowKey, fromKey, upperBound); + } + + public C firstKey() { + SortedMap backing = backingRowMap(); + if (backing == null) { + throw new NoSuchElementException(); + } + return backingRowMap().firstKey(); + } + + public C lastKey() { + SortedMap backing = backingRowMap(); + if (backing == null) { + throw new NoSuchElementException(); + } + return backingRowMap().lastKey(); + } + + + + + + + SortedMap wholeRow() + { + if ((wholeRow == null) || ((wholeRow.isEmpty()) && (backingMap.containsKey(rowKey)))) + { + wholeRow = ((SortedMap)backingMap.get(rowKey)); + } + return wholeRow; + } + + SortedMap backingRowMap() + { + return (SortedMap)super.backingRowMap(); + } + + SortedMap computeBackingRowMap() + { + SortedMap map = wholeRow(); + if (map != null) { + if (lowerBound != null) { + map = map.tailMap(lowerBound); + } + if (upperBound != null) { + map = map.headMap(upperBound); + } + return map; + } + return null; + } + + void maintainEmptyInvariant() + { + if ((wholeRow() != null) && (wholeRow.isEmpty())) { + backingMap.remove(rowKey); + wholeRow = null; + backingRowMap = null; + } + } + + public boolean containsKey(Object key) { + return (rangeContains(key)) && (super.containsKey(key)); + } + + public V put(C key, V value) { + Preconditions.checkArgument(rangeContains(Preconditions.checkNotNull(key))); + return super.put(key, value); + } + } + + + public SortedSet rowKeySet() + { + return super.rowKeySet(); + } + + public SortedMap> rowMap() { + return super.rowMap(); + } + + + + + + Iterator createColumnKeyIterator() + { + final Comparator comparator = columnComparator(); + + final Iterator merged = Iterators.mergeSorted(Iterables.transform(backingMap.values(), new Function() + { + + + public Iterator apply(Map input) { + return input.keySet().iterator(); } }), comparator); + + + + new AbstractIterator() + { + C lastValue; + + protected C computeNext() { + while (merged.hasNext()) { + C next = merged.next(); + boolean duplicate = (lastValue != null) && (comparator.compare(next, lastValue) == 0); + + + + if (!duplicate) { + lastValue = next; + return lastValue; + } + } + + lastValue = null; + return endOfData(); + } + }; + } +} diff --git a/src/minecraft/com/google/common/collect/TreeMultimap.java b/src/minecraft/com/google/common/collect/TreeMultimap.java new file mode 100644 index 0000000..76ff8a8 --- /dev/null +++ b/src/minecraft/com/google/common/collect/TreeMultimap.java @@ -0,0 +1,263 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Collection; +import java.util.Comparator; +import java.util.NavigableMap; +import java.util.NavigableSet; +import java.util.SortedSet; +import java.util.TreeMap; +import java.util.TreeSet; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true, emulated=true) +public class TreeMultimap + extends AbstractSortedKeySortedSetMultimap +{ + private transient Comparator keyComparator; + private transient Comparator valueComparator; + @GwtIncompatible("not needed in emulated source") + private static final long serialVersionUID = 0L; + + public static TreeMultimap create() + { + return new TreeMultimap(Ordering.natural(), Ordering.natural()); + } + + + + + + + + + + + public static TreeMultimap create(Comparator keyComparator, Comparator valueComparator) + { + return new TreeMultimap((Comparator)Preconditions.checkNotNull(keyComparator), (Comparator)Preconditions.checkNotNull(valueComparator)); + } + + + + + + + + + public static TreeMultimap create(Multimap multimap) + { + return new TreeMultimap(Ordering.natural(), Ordering.natural(), multimap); + } + + + TreeMultimap(Comparator keyComparator, Comparator valueComparator) + { + super(new TreeMap(keyComparator)); + this.keyComparator = keyComparator; + this.valueComparator = valueComparator; + } + + + private TreeMultimap(Comparator keyComparator, Comparator valueComparator, Multimap multimap) + { + this(keyComparator, valueComparator); + putAll(multimap); + } + + + + + + + + + SortedSet createCollection() + { + return new TreeSet(valueComparator); + } + + Collection createCollection(@Nullable K key) + { + if (key == null) { + keyComparator().compare(key, key); + } + return super.createCollection(key); + } + + + + public Comparator keyComparator() + { + return keyComparator; + } + + public Comparator valueComparator() + { + return valueComparator; + } + + + + + + + + @GwtIncompatible("NavigableMap") + NavigableMap> backingMap() + { + return (NavigableMap)super.backingMap(); + } + + + + + @GwtIncompatible("NavigableSet") + public NavigableSet get(@Nullable K key) + { + return (NavigableSet)super.get(key); + } + + @GwtIncompatible("NavigableSet") + Collection unmodifiableCollectionSubclass(Collection collection) + { + return Sets.unmodifiableNavigableSet((NavigableSet)collection); + } + + @GwtIncompatible("NavigableSet") + Collection wrapCollection(K key, Collection collection) + { + return new AbstractMapBasedMultimap.WrappedNavigableSet(this, key, (NavigableSet)collection, null); + } + + + + + + + + + + + @GwtIncompatible("NavigableSet") + public NavigableSet keySet() + { + return (NavigableSet)super.keySet(); + } + + @GwtIncompatible("NavigableSet") + NavigableSet createKeySet() + { + return new AbstractMapBasedMultimap.NavigableKeySet(this, backingMap()); + } + + + + + + + + + + + @GwtIncompatible("NavigableMap") + public NavigableMap> asMap() + { + return (NavigableMap)super.asMap(); + } + + @GwtIncompatible("NavigableMap") + NavigableMap> createAsMap() + { + return new AbstractMapBasedMultimap.NavigableAsMap(this, backingMap()); + } + + + + + @GwtIncompatible("java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) + throws IOException + { + stream.defaultWriteObject(); + stream.writeObject(keyComparator()); + stream.writeObject(valueComparator()); + Serialization.writeMultimap(this, stream); + } + + @GwtIncompatible("java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException + { + stream.defaultReadObject(); + keyComparator = ((Comparator)Preconditions.checkNotNull((Comparator)stream.readObject())); + valueComparator = ((Comparator)Preconditions.checkNotNull((Comparator)stream.readObject())); + setMap(new TreeMap(keyComparator)); + Serialization.populateMultimap(this, stream); + } +} diff --git a/src/minecraft/com/google/common/collect/TreeMultiset.java b/src/minecraft/com/google/common/collect/TreeMultiset.java new file mode 100644 index 0000000..1a9c09e --- /dev/null +++ b/src/minecraft/com/google/common/collect/TreeMultiset.java @@ -0,0 +1,982 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.primitives.Ints; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Comparator; +import java.util.ConcurrentModificationException; +import java.util.Iterator; +import java.util.NavigableSet; +import java.util.NoSuchElementException; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public final class TreeMultiset + extends AbstractSortedMultiset + implements Serializable +{ + private final transient Reference> rootReference; + private final transient GeneralRange range; + private final transient AvlNode header; + @GwtIncompatible("not needed in emulated source") + private static final long serialVersionUID = 1L; + + public static TreeMultiset create() + { + return new TreeMultiset(Ordering.natural()); + } + + + + + + + + + + + + + + public static TreeMultiset create(@Nullable Comparator comparator) + { + return comparator == null ? new TreeMultiset(Ordering.natural()) : new TreeMultiset(comparator); + } + + + + + + + + + + + + public static TreeMultiset create(Iterable elements) + { + TreeMultiset multiset = create(); + Iterables.addAll(multiset, elements); + return multiset; + } + + + + + TreeMultiset(Reference> rootReference, GeneralRange range, AvlNode endLink) + { + super(range.comparator()); + this.rootReference = rootReference; + this.range = range; + header = endLink; + } + + TreeMultiset(Comparator comparator) { + super(comparator); + range = GeneralRange.all(comparator); + header = new AvlNode(null, 1); + successor(header, header); + rootReference = new Reference(null); + } + + + + private static abstract enum Aggregate + { + SIZE, + + + + + + + + + + + DISTINCT; + + + + private Aggregate() {} + + + + abstract int nodeAggregate(TreeMultiset.AvlNode paramAvlNode); + + + abstract long treeAggregate(@Nullable TreeMultiset.AvlNode paramAvlNode); + } + + + private long aggregateForEntries(Aggregate aggr) + { + AvlNode root = (AvlNode)rootReference.get(); + long total = aggr.treeAggregate(root); + if (range.hasLowerBound()) { + total -= aggregateBelowRange(aggr, root); + } + if (range.hasUpperBound()) { + total -= aggregateAboveRange(aggr, root); + } + return total; + } + + private long aggregateBelowRange(Aggregate aggr, @Nullable AvlNode node) { + if (node == null) { + return 0L; + } + int cmp = comparator().compare(range.getLowerEndpoint(), elem); + if (cmp < 0) + return aggregateBelowRange(aggr, left); + if (cmp == 0) { + switch (4.$SwitchMap$com$google$common$collect$BoundType[range.getLowerBoundType().ordinal()]) { + case 1: + return aggr.nodeAggregate(node) + aggr.treeAggregate(left); + case 2: + return aggr.treeAggregate(left); + } + throw new AssertionError(); + } + + return aggr.treeAggregate(left) + aggr.nodeAggregate(node) + aggregateBelowRange(aggr, right); + } + + + private long aggregateAboveRange(Aggregate aggr, @Nullable AvlNode node) + { + if (node == null) { + return 0L; + } + int cmp = comparator().compare(range.getUpperEndpoint(), elem); + if (cmp > 0) + return aggregateAboveRange(aggr, right); + if (cmp == 0) { + switch (4.$SwitchMap$com$google$common$collect$BoundType[range.getUpperBoundType().ordinal()]) { + case 1: + return aggr.nodeAggregate(node) + aggr.treeAggregate(right); + case 2: + return aggr.treeAggregate(right); + } + throw new AssertionError(); + } + + return aggr.treeAggregate(right) + aggr.nodeAggregate(node) + aggregateAboveRange(aggr, left); + } + + + + public int size() + { + return Ints.saturatedCast(aggregateForEntries(Aggregate.SIZE)); + } + + int distinctElements() + { + return Ints.saturatedCast(aggregateForEntries(Aggregate.DISTINCT)); + } + + public int count(@Nullable Object element) + { + try + { + E e = element; + AvlNode root = (AvlNode)rootReference.get(); + if ((!range.contains(e)) || (root == null)) { + return 0; + } + return root.count(comparator(), e); + } catch (ClassCastException e) { + return 0; + } catch (NullPointerException e) {} + return 0; + } + + + public int add(@Nullable E element, int occurrences) + { + CollectPreconditions.checkNonnegative(occurrences, "occurrences"); + if (occurrences == 0) { + return count(element); + } + Preconditions.checkArgument(range.contains(element)); + AvlNode root = (AvlNode)rootReference.get(); + if (root == null) { + comparator().compare(element, element); + AvlNode newRoot = new AvlNode(element, occurrences); + successor(header, newRoot, header); + rootReference.checkAndSet(root, newRoot); + return 0; + } + int[] result = new int[1]; + AvlNode newRoot = root.add(comparator(), element, occurrences, result); + rootReference.checkAndSet(root, newRoot); + return result[0]; + } + + public int remove(@Nullable Object element, int occurrences) + { + CollectPreconditions.checkNonnegative(occurrences, "occurrences"); + if (occurrences == 0) { + return count(element); + } + AvlNode root = (AvlNode)rootReference.get(); + int[] result = new int[1]; + AvlNode newRoot; + try + { + E e = element; + if ((!range.contains(e)) || (root == null)) { + return 0; + } + newRoot = root.remove(comparator(), e, occurrences, result); + } catch (ClassCastException e) { + return 0; + } catch (NullPointerException e) { + return 0; + } + rootReference.checkAndSet(root, newRoot); + return result[0]; + } + + public int setCount(@Nullable E element, int count) + { + CollectPreconditions.checkNonnegative(count, "count"); + if (!range.contains(element)) { + Preconditions.checkArgument(count == 0); + return 0; + } + + AvlNode root = (AvlNode)rootReference.get(); + if (root == null) { + if (count > 0) { + add(element, count); + } + return 0; + } + int[] result = new int[1]; + AvlNode newRoot = root.setCount(comparator(), element, count, result); + rootReference.checkAndSet(root, newRoot); + return result[0]; + } + + public boolean setCount(@Nullable E element, int oldCount, int newCount) + { + CollectPreconditions.checkNonnegative(newCount, "newCount"); + CollectPreconditions.checkNonnegative(oldCount, "oldCount"); + Preconditions.checkArgument(range.contains(element)); + + AvlNode root = (AvlNode)rootReference.get(); + if (root == null) { + if (oldCount == 0) { + if (newCount > 0) { + add(element, newCount); + } + return true; + } + return false; + } + + int[] result = new int[1]; + AvlNode newRoot = root.setCount(comparator(), element, oldCount, newCount, result); + rootReference.checkAndSet(root, newRoot); + return result[0] == oldCount; + } + + private Multiset.Entry wrapEntry(final AvlNode baseEntry) { + new Multisets.AbstractEntry() + { + public E getElement() { + return baseEntry.getElement(); + } + + public int getCount() + { + int result = baseEntry.getCount(); + if (result == 0) { + return count(getElement()); + } + return result; + } + }; + } + + + + @Nullable + private AvlNode firstNode() + { + AvlNode root = (AvlNode)rootReference.get(); + if (root == null) { + return null; + } + AvlNode node; + if (range.hasLowerBound()) { + E endpoint = range.getLowerEndpoint(); + AvlNode node = ((AvlNode)rootReference.get()).ceiling(comparator(), endpoint); + if (node == null) { + return null; + } + if ((range.getLowerBoundType() == BoundType.OPEN) && (comparator().compare(endpoint, node.getElement()) == 0)) + { + node = succ; + } + } else { + node = header.succ; + } + return (node == header) || (!range.contains(node.getElement())) ? null : node; + } + + @Nullable + private AvlNode lastNode() { AvlNode root = (AvlNode)rootReference.get(); + if (root == null) { + return null; + } + AvlNode node; + if (range.hasUpperBound()) { + E endpoint = range.getUpperEndpoint(); + AvlNode node = ((AvlNode)rootReference.get()).floor(comparator(), endpoint); + if (node == null) { + return null; + } + if ((range.getUpperBoundType() == BoundType.OPEN) && (comparator().compare(endpoint, node.getElement()) == 0)) + { + node = pred; + } + } else { + node = header.pred; + } + return (node == header) || (!range.contains(node.getElement())) ? null : node; + } + + Iterator> entryIterator() + { + new Iterator() { + TreeMultiset.AvlNode current = TreeMultiset.this.firstNode(); + Multiset.Entry prevEntry; + + public boolean hasNext() + { + if (current == null) + return false; + if (range.tooHigh(current.getElement())) { + current = null; + return false; + } + return true; + } + + + public Multiset.Entry next() + { + if (!hasNext()) { + throw new NoSuchElementException(); + } + Multiset.Entry result = TreeMultiset.this.wrapEntry(current); + prevEntry = result; + if (current.succ == header) { + current = null; + } else { + current = current.succ; + } + return result; + } + + public void remove() + { + CollectPreconditions.checkRemove(prevEntry != null); + setCount(prevEntry.getElement(), 0); + prevEntry = null; + } + }; + } + + Iterator> descendingEntryIterator() + { + new Iterator() { + TreeMultiset.AvlNode current = TreeMultiset.this.lastNode(); + Multiset.Entry prevEntry = null; + + public boolean hasNext() + { + if (current == null) + return false; + if (range.tooLow(current.getElement())) { + current = null; + return false; + } + return true; + } + + + public Multiset.Entry next() + { + if (!hasNext()) { + throw new NoSuchElementException(); + } + Multiset.Entry result = TreeMultiset.this.wrapEntry(current); + prevEntry = result; + if (current.pred == header) { + current = null; + } else { + current = current.pred; + } + return result; + } + + public void remove() + { + CollectPreconditions.checkRemove(prevEntry != null); + setCount(prevEntry.getElement(), 0); + prevEntry = null; + } + }; + } + + public SortedMultiset headMultiset(@Nullable E upperBound, BoundType boundType) + { + return new TreeMultiset(rootReference, range.intersect(GeneralRange.upTo(comparator(), upperBound, boundType)), header); + } + + + + + public SortedMultiset tailMultiset(@Nullable E lowerBound, BoundType boundType) + { + return new TreeMultiset(rootReference, range.intersect(GeneralRange.downTo(comparator(), lowerBound, boundType)), header); + } + + + + static int distinctElements(@Nullable AvlNode node) + { + return node == null ? 0 : distinctElements; + } + + private static final class Reference { + private Reference() {} + + @Nullable + public T get() { return value; } + + @Nullable + private T value; + public void checkAndSet(@Nullable T expected, T newValue) { if (value != expected) { + throw new ConcurrentModificationException(); + } + value = newValue; + } + } + + private static final class AvlNode extends Multisets.AbstractEntry + { + @Nullable + private final E elem; + private int elemCount; + private int distinctElements; + private long totalCount; + private int height; + private AvlNode left; + private AvlNode right; + private AvlNode pred; + private AvlNode succ; + + AvlNode(@Nullable E elem, int elemCount) + { + Preconditions.checkArgument(elemCount > 0); + this.elem = elem; + this.elemCount = elemCount; + totalCount = elemCount; + distinctElements = 1; + height = 1; + left = null; + right = null; + } + + public int count(Comparator comparator, E e) { + int cmp = comparator.compare(e, elem); + if (cmp < 0) + return left == null ? 0 : left.count(comparator, e); + if (cmp > 0) { + return right == null ? 0 : right.count(comparator, e); + } + return elemCount; + } + + private AvlNode addRightChild(E e, int count) + { + right = new AvlNode(e, count); + TreeMultiset.successor(this, right, succ); + height = Math.max(2, height); + distinctElements += 1; + totalCount += count; + return this; + } + + private AvlNode addLeftChild(E e, int count) { + left = new AvlNode(e, count); + TreeMultiset.successor(pred, left, this); + height = Math.max(2, height); + distinctElements += 1; + totalCount += count; + return this; + } + + + + + AvlNode add(Comparator comparator, @Nullable E e, int count, int[] result) + { + int cmp = comparator.compare(e, elem); + if (cmp < 0) { + AvlNode initLeft = left; + if (initLeft == null) { + result[0] = 0; + return addLeftChild(e, count); + } + int initHeight = height; + + left = initLeft.add(comparator, e, count, result); + if (result[0] == 0) { + distinctElements += 1; + } + totalCount += count; + return left.height == initHeight ? this : rebalance(); } + if (cmp > 0) { + AvlNode initRight = right; + if (initRight == null) { + result[0] = 0; + return addRightChild(e, count); + } + int initHeight = height; + + right = initRight.add(comparator, e, count, result); + if (result[0] == 0) { + distinctElements += 1; + } + totalCount += count; + return right.height == initHeight ? this : rebalance(); + } + + + result[0] = elemCount; + long resultCount = elemCount + count; + Preconditions.checkArgument(resultCount <= 2147483647L); + elemCount += count; + totalCount += count; + return this; + } + + AvlNode remove(Comparator comparator, @Nullable E e, int count, int[] result) { + int cmp = comparator.compare(e, elem); + if (cmp < 0) { + AvlNode initLeft = left; + if (initLeft == null) { + result[0] = 0; + return this; + } + + left = initLeft.remove(comparator, e, count, result); + + if (result[0] > 0) { + if (count >= result[0]) { + distinctElements -= 1; + totalCount -= result[0]; + } else { + totalCount -= count; + } + } + return result[0] == 0 ? this : rebalance(); } + if (cmp > 0) { + AvlNode initRight = right; + if (initRight == null) { + result[0] = 0; + return this; + } + + right = initRight.remove(comparator, e, count, result); + + if (result[0] > 0) { + if (count >= result[0]) { + distinctElements -= 1; + totalCount -= result[0]; + } else { + totalCount -= count; + } + } + return rebalance(); + } + + + result[0] = elemCount; + if (count >= elemCount) { + return deleteMe(); + } + elemCount -= count; + totalCount -= count; + return this; + } + + AvlNode setCount(Comparator comparator, @Nullable E e, int count, int[] result) + { + int cmp = comparator.compare(e, elem); + if (cmp < 0) { + AvlNode initLeft = left; + if (initLeft == null) { + result[0] = 0; + return count > 0 ? addLeftChild(e, count) : this; + } + + left = initLeft.setCount(comparator, e, count, result); + + if ((count == 0) && (result[0] != 0)) { + distinctElements -= 1; + } else if ((count > 0) && (result[0] == 0)) { + distinctElements += 1; + } + + totalCount += count - result[0]; + return rebalance(); } + if (cmp > 0) { + AvlNode initRight = right; + if (initRight == null) { + result[0] = 0; + return count > 0 ? addRightChild(e, count) : this; + } + + right = initRight.setCount(comparator, e, count, result); + + if ((count == 0) && (result[0] != 0)) { + distinctElements -= 1; + } else if ((count > 0) && (result[0] == 0)) { + distinctElements += 1; + } + + totalCount += count - result[0]; + return rebalance(); + } + + + result[0] = elemCount; + if (count == 0) { + return deleteMe(); + } + totalCount += count - elemCount; + elemCount = count; + return this; + } + + + + + + AvlNode setCount(Comparator comparator, @Nullable E e, int expectedCount, int newCount, int[] result) + { + int cmp = comparator.compare(e, elem); + if (cmp < 0) { + AvlNode initLeft = left; + if (initLeft == null) { + result[0] = 0; + if ((expectedCount == 0) && (newCount > 0)) { + return addLeftChild(e, newCount); + } + return this; + } + + left = initLeft.setCount(comparator, e, expectedCount, newCount, result); + + if (result[0] == expectedCount) { + if ((newCount == 0) && (result[0] != 0)) { + distinctElements -= 1; + } else if ((newCount > 0) && (result[0] == 0)) { + distinctElements += 1; + } + totalCount += newCount - result[0]; + } + return rebalance(); } + if (cmp > 0) { + AvlNode initRight = right; + if (initRight == null) { + result[0] = 0; + if ((expectedCount == 0) && (newCount > 0)) { + return addRightChild(e, newCount); + } + return this; + } + + right = initRight.setCount(comparator, e, expectedCount, newCount, result); + + if (result[0] == expectedCount) { + if ((newCount == 0) && (result[0] != 0)) { + distinctElements -= 1; + } else if ((newCount > 0) && (result[0] == 0)) { + distinctElements += 1; + } + totalCount += newCount - result[0]; + } + return rebalance(); + } + + + result[0] = elemCount; + if (expectedCount == elemCount) { + if (newCount == 0) { + return deleteMe(); + } + totalCount += newCount - elemCount; + elemCount = newCount; + } + return this; + } + + private AvlNode deleteMe() { + int oldElemCount = elemCount; + elemCount = 0; + TreeMultiset.successor(pred, succ); + if (left == null) + return right; + if (right == null) + return left; + if (left.height >= right.height) { + AvlNode newTop = pred; + + left = left.removeMax(newTop); + right = right; + distinctElements -= 1; + totalCount -= oldElemCount; + return newTop.rebalance(); + } + AvlNode newTop = succ; + right = right.removeMin(newTop); + left = left; + distinctElements -= 1; + totalCount -= oldElemCount; + return newTop.rebalance(); + } + + + private AvlNode removeMin(AvlNode node) + { + if (left == null) { + return right; + } + left = left.removeMin(node); + distinctElements -= 1; + totalCount -= elemCount; + return rebalance(); + } + + + private AvlNode removeMax(AvlNode node) + { + if (right == null) { + return left; + } + right = right.removeMax(node); + distinctElements -= 1; + totalCount -= elemCount; + return rebalance(); + } + + private void recomputeMultiset() + { + distinctElements = (1 + TreeMultiset.distinctElements(left) + TreeMultiset.distinctElements(right)); + + totalCount = (elemCount + totalCount(left) + totalCount(right)); + } + + private void recomputeHeight() { + height = (1 + Math.max(height(left), height(right))); + } + + private void recompute() { + recomputeMultiset(); + recomputeHeight(); + } + + private AvlNode rebalance() { + switch (balanceFactor()) { + case -2: + if (right.balanceFactor() > 0) { + right = right.rotateRight(); + } + return rotateLeft(); + case 2: + if (left.balanceFactor() < 0) { + left = left.rotateLeft(); + } + return rotateRight(); + } + recomputeHeight(); + return this; + } + + private int balanceFactor() + { + return height(left) - height(right); + } + + private AvlNode rotateLeft() { + Preconditions.checkState(right != null); + AvlNode newTop = right; + right = left; + left = this; + totalCount = totalCount; + distinctElements = distinctElements; + recompute(); + newTop.recomputeHeight(); + return newTop; + } + + private AvlNode rotateRight() { + Preconditions.checkState(left != null); + AvlNode newTop = left; + left = right; + right = this; + totalCount = totalCount; + distinctElements = distinctElements; + recompute(); + newTop.recomputeHeight(); + return newTop; + } + + private static long totalCount(@Nullable AvlNode node) { + return node == null ? 0L : totalCount; + } + + + private static int height(@Nullable AvlNode node) { return node == null ? 0 : height; } + + @Nullable + private AvlNode ceiling(Comparator comparator, E e) { + int cmp = comparator.compare(e, elem); + if (cmp < 0) + return left == null ? this : (AvlNode)Objects.firstNonNull(left.ceiling(comparator, e), this); + if (cmp == 0) { + return this; + } + return right == null ? null : right.ceiling(comparator, e); + } + + @Nullable + private AvlNode floor(Comparator comparator, E e) { + int cmp = comparator.compare(e, elem); + if (cmp > 0) + return right == null ? this : (AvlNode)Objects.firstNonNull(right.floor(comparator, e), this); + if (cmp == 0) { + return this; + } + return left == null ? null : left.floor(comparator, e); + } + + + public E getElement() + { + return elem; + } + + public int getCount() + { + return elemCount; + } + + public String toString() + { + return Multisets.immutableEntry(getElement(), getCount()).toString(); + } + } + + private static void successor(AvlNode a, AvlNode b) { + succ = b; + pred = a; + } + + private static void successor(AvlNode a, AvlNode b, AvlNode c) { + successor(a, b); + successor(b, c); + } + + + + + + + + + + @GwtIncompatible("java.io.ObjectOutputStream") + private void writeObject(ObjectOutputStream stream) + throws IOException + { + stream.defaultWriteObject(); + stream.writeObject(elementSet().comparator()); + Serialization.writeMultiset(this, stream); + } + + @GwtIncompatible("java.io.ObjectInputStream") + private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + + + Comparator comparator = (Comparator)stream.readObject(); + Serialization.getFieldSetter(AbstractSortedMultiset.class, "comparator").set(this, comparator); + Serialization.getFieldSetter(TreeMultiset.class, "range").set(this, GeneralRange.all(comparator)); + + + Serialization.getFieldSetter(TreeMultiset.class, "rootReference").set(this, new Reference(null)); + + + AvlNode header = new AvlNode(null, 1); + Serialization.getFieldSetter(TreeMultiset.class, "header").set(this, header); + successor(header, header); + Serialization.populateMultiset(this, stream); + } +} diff --git a/src/minecraft/com/google/common/collect/TreeRangeMap.java b/src/minecraft/com/google/common/collect/TreeRangeMap.java new file mode 100644 index 0000000..9dd4858 --- /dev/null +++ b/src/minecraft/com/google/common/collect/TreeRangeMap.java @@ -0,0 +1,608 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import java.util.AbstractMap; +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NavigableMap; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.SortedMap; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtIncompatible("NavigableMap") +public final class TreeRangeMap + implements RangeMap +{ + private final NavigableMap, RangeMapEntry> entriesByLowerBound; + + public static TreeRangeMap create() + { + return new TreeRangeMap(); + } + + private TreeRangeMap() { + entriesByLowerBound = Maps.newTreeMap(); + } + + private static final class RangeMapEntry extends AbstractMapEntry, V> + { + private final Range range; + private final V value; + + RangeMapEntry(Cut lowerBound, Cut upperBound, V value) { + this(Range.create(lowerBound, upperBound), value); + } + + RangeMapEntry(Range range, V value) { + this.range = range; + this.value = value; + } + + public Range getKey() + { + return range; + } + + public V getValue() + { + return value; + } + + public boolean contains(K value) { + return range.contains(value); + } + + Cut getLowerBound() { + return range.lowerBound; + } + + Cut getUpperBound() { + return range.upperBound; + } + } + + @Nullable + public V get(K key) + { + Map.Entry, V> entry = getEntry(key); + return entry == null ? null : entry.getValue(); + } + + @Nullable + public Map.Entry, V> getEntry(K key) + { + Map.Entry, RangeMapEntry> mapEntry = entriesByLowerBound.floorEntry(Cut.belowValue(key)); + + if ((mapEntry != null) && (((RangeMapEntry)mapEntry.getValue()).contains(key))) { + return (Map.Entry)mapEntry.getValue(); + } + return null; + } + + + public void put(Range range, V value) + { + if (!range.isEmpty()) { + Preconditions.checkNotNull(value); + remove(range); + entriesByLowerBound.put(lowerBound, new RangeMapEntry(range, value)); + } + } + + public void putAll(RangeMap rangeMap) + { + for (Map.Entry, V> entry : rangeMap.asMapOfRanges().entrySet()) { + put((Range)entry.getKey(), entry.getValue()); + } + } + + public void clear() + { + entriesByLowerBound.clear(); + } + + public Range span() + { + Map.Entry, RangeMapEntry> firstEntry = entriesByLowerBound.firstEntry(); + Map.Entry, RangeMapEntry> lastEntry = entriesByLowerBound.lastEntry(); + if (firstEntry == null) { + throw new NoSuchElementException(); + } + return Range.create(getValuegetKeylowerBound, getValuegetKeyupperBound); + } + + + private void putRangeMapEntry(Cut lowerBound, Cut upperBound, V value) + { + entriesByLowerBound.put(lowerBound, new RangeMapEntry(lowerBound, upperBound, value)); + } + + public void remove(Range rangeToRemove) + { + if (rangeToRemove.isEmpty()) { + return; + } + + + + + + Map.Entry, RangeMapEntry> mapEntryBelowToTruncate = entriesByLowerBound.lowerEntry(lowerBound); + + if (mapEntryBelowToTruncate != null) + { + RangeMapEntry rangeMapEntry = (RangeMapEntry)mapEntryBelowToTruncate.getValue(); + if (rangeMapEntry.getUpperBound().compareTo(lowerBound) > 0) + { + if (rangeMapEntry.getUpperBound().compareTo(upperBound) > 0) + { + + putRangeMapEntry(upperBound, rangeMapEntry.getUpperBound(), ((RangeMapEntry)mapEntryBelowToTruncate.getValue()).getValue()); + } + + + putRangeMapEntry(rangeMapEntry.getLowerBound(), lowerBound, ((RangeMapEntry)mapEntryBelowToTruncate.getValue()).getValue()); + } + } + + + Map.Entry, RangeMapEntry> mapEntryAboveToTruncate = entriesByLowerBound.lowerEntry(upperBound); + + if (mapEntryAboveToTruncate != null) + { + RangeMapEntry rangeMapEntry = (RangeMapEntry)mapEntryAboveToTruncate.getValue(); + if (rangeMapEntry.getUpperBound().compareTo(upperBound) > 0) + { + + putRangeMapEntry(upperBound, rangeMapEntry.getUpperBound(), ((RangeMapEntry)mapEntryAboveToTruncate.getValue()).getValue()); + + entriesByLowerBound.remove(lowerBound); + } + } + entriesByLowerBound.subMap(lowerBound, upperBound).clear(); + } + + public Map, V> asMapOfRanges() + { + return new AsMapOfRanges(null); + } + + private final class AsMapOfRanges extends AbstractMap, V> { + private AsMapOfRanges() {} + + public boolean containsKey(@Nullable Object key) { + return get(key) != null; + } + + public V get(@Nullable Object key) + { + if ((key instanceof Range)) { + Range range = (Range)key; + TreeRangeMap.RangeMapEntry rangeMapEntry = (TreeRangeMap.RangeMapEntry)entriesByLowerBound.get(lowerBound); + if ((rangeMapEntry != null) && (rangeMapEntry.getKey().equals(range))) { + return rangeMapEntry.getValue(); + } + } + return null; + } + + public Set, V>> entrySet() + { + new AbstractSet() + { + + public Iterator, V>> iterator() + { + return entriesByLowerBound.values().iterator(); + } + + public int size() + { + return entriesByLowerBound.size(); + } + }; + } + } + + public RangeMap subRangeMap(Range subRange) + { + if (subRange.equals(Range.all())) { + return this; + } + return new SubRangeMap(subRange); + } + + + private RangeMap emptySubRangeMap() + { + return EMPTY_SUB_RANGE_MAP; + } + + private static final RangeMap EMPTY_SUB_RANGE_MAP = new RangeMap() + { + @Nullable + public Object get(Comparable key) + { + return null; + } + + @Nullable + public Map.Entry getEntry(Comparable key) + { + return null; + } + + public Range span() + { + throw new NoSuchElementException(); + } + + public void put(Range range, Object value) + { + Preconditions.checkNotNull(range); + throw new IllegalArgumentException("Cannot insert range " + range + " into an empty subRangeMap"); + } + + + public void putAll(RangeMap rangeMap) + { + if (!rangeMap.asMapOfRanges().isEmpty()) { + throw new IllegalArgumentException("Cannot putAll(nonEmptyRangeMap) into an empty subRangeMap"); + } + } + + + public void clear() {} + + + public void remove(Range range) + { + Preconditions.checkNotNull(range); + } + + public Map asMapOfRanges() + { + return Collections.emptyMap(); + } + + public RangeMap subRangeMap(Range range) + { + Preconditions.checkNotNull(range); + return this; + } + }; + + private class SubRangeMap implements RangeMap + { + private final Range subRange; + + SubRangeMap() { + this.subRange = subRange; + } + + @Nullable + public V get(K key) + { + return subRange.contains(key) ? TreeRangeMap.this.get(key) : null; + } + + + + @Nullable + public Map.Entry, V> getEntry(K key) + { + if (subRange.contains(key)) { + Map.Entry, V> entry = TreeRangeMap.this.getEntry(key); + if (entry != null) { + return Maps.immutableEntry(((Range)entry.getKey()).intersection(subRange), entry.getValue()); + } + } + return null; + } + + + public Range span() + { + Map.Entry, TreeRangeMap.RangeMapEntry> lowerEntry = entriesByLowerBound.floorEntry(subRange.lowerBound); + Cut lowerBound; + Cut lowerBound; if ((lowerEntry != null) && (((TreeRangeMap.RangeMapEntry)lowerEntry.getValue()).getUpperBound().compareTo(subRange.lowerBound) > 0)) + { + lowerBound = subRange.lowerBound; + } else { + lowerBound = (Cut)entriesByLowerBound.ceilingKey(subRange.lowerBound); + if ((lowerBound == null) || (lowerBound.compareTo(subRange.upperBound) >= 0)) { + throw new NoSuchElementException(); + } + } + + + Map.Entry, TreeRangeMap.RangeMapEntry> upperEntry = entriesByLowerBound.lowerEntry(subRange.upperBound); + + if (upperEntry == null) + throw new NoSuchElementException(); + Cut upperBound; Cut upperBound; if (((TreeRangeMap.RangeMapEntry)upperEntry.getValue()).getUpperBound().compareTo(subRange.upperBound) >= 0) { + upperBound = subRange.upperBound; + } else { + upperBound = ((TreeRangeMap.RangeMapEntry)upperEntry.getValue()).getUpperBound(); + } + return Range.create(lowerBound, upperBound); + } + + public void put(Range range, V value) + { + Preconditions.checkArgument(subRange.encloses(range), "Cannot put range %s into a subRangeMap(%s)", new Object[] { range, subRange }); + + TreeRangeMap.this.put(range, value); + } + + public void putAll(RangeMap rangeMap) + { + if (rangeMap.asMapOfRanges().isEmpty()) { + return; + } + Range span = rangeMap.span(); + Preconditions.checkArgument(subRange.encloses(span), "Cannot putAll rangeMap with span %s into a subRangeMap(%s)", new Object[] { span, subRange }); + + TreeRangeMap.this.putAll(rangeMap); + } + + public void clear() + { + TreeRangeMap.this.remove(subRange); + } + + public void remove(Range range) + { + if (range.isConnected(subRange)) { + TreeRangeMap.this.remove(range.intersection(subRange)); + } + } + + public RangeMap subRangeMap(Range range) + { + if (!range.isConnected(subRange)) { + return TreeRangeMap.this.emptySubRangeMap(); + } + return TreeRangeMap.this.subRangeMap(range.intersection(subRange)); + } + + + public Map, V> asMapOfRanges() + { + return new SubRangeMapAsMap(); + } + + public boolean equals(@Nullable Object o) + { + if ((o instanceof RangeMap)) { + RangeMap rangeMap = (RangeMap)o; + return asMapOfRanges().equals(rangeMap.asMapOfRanges()); + } + return false; + } + + public int hashCode() + { + return asMapOfRanges().hashCode(); + } + + public String toString() + { + return asMapOfRanges().toString(); + } + + class SubRangeMapAsMap extends AbstractMap, V> { + SubRangeMapAsMap() {} + + public boolean containsKey(Object key) { + return get(key) != null; + } + + public V get(Object key) + { + try { + if ((key instanceof Range)) + { + Range r = (Range)key; + if ((!subRange.encloses(r)) || (r.isEmpty())) { + return null; + } + TreeRangeMap.RangeMapEntry candidate = null; + if (lowerBound.compareTo(subRange.lowerBound) == 0) + { + Map.Entry, TreeRangeMap.RangeMapEntry> entry = entriesByLowerBound.floorEntry(lowerBound); + + if (entry != null) { + candidate = (TreeRangeMap.RangeMapEntry)entry.getValue(); + } + } else { + candidate = (TreeRangeMap.RangeMapEntry)entriesByLowerBound.get(lowerBound); + } + + if ((candidate != null) && (candidate.getKey().isConnected(subRange)) && (candidate.getKey().intersection(subRange).equals(r))) + { + return candidate.getValue(); + } + } + } catch (ClassCastException e) { + return null; + } + return null; + } + + public V remove(Object key) + { + V value = get(key); + if (value != null) + { + Range range = (Range)key; + TreeRangeMap.this.remove(range); + return value; + } + return null; + } + + public void clear() + { + TreeRangeMap.SubRangeMap.this.clear(); + } + + private boolean removeEntryIf(Predicate, V>> predicate) { + List> toRemove = Lists.newArrayList(); + for (Map.Entry, V> entry : entrySet()) { + if (predicate.apply(entry)) { + toRemove.add(entry.getKey()); + } + } + for (Range range : toRemove) { + TreeRangeMap.this.remove(range); + } + return !toRemove.isEmpty(); + } + + public Set> keySet() + { + new Maps.KeySet(this) + { + public boolean remove(@Nullable Object o) { + return remove(o) != null; + } + + public boolean retainAll(Collection c) + { + return TreeRangeMap.SubRangeMap.SubRangeMapAsMap.this.removeEntryIf(Predicates.compose(Predicates.not(Predicates.in(c)), Maps.keyFunction())); + } + }; + } + + public Set, V>> entrySet() + { + new Maps.EntrySet() + { + Map, V> map() { + return TreeRangeMap.SubRangeMap.SubRangeMapAsMap.this; + } + + public Iterator, V>> iterator() + { + if (subRange.isEmpty()) { + return Iterators.emptyIterator(); + } + Cut cutToStart = (Cut)Objects.firstNonNull(entriesByLowerBound.floorKey(subRange.lowerBound), subRange.lowerBound); + + + final Iterator> backingItr = entriesByLowerBound.tailMap(cutToStart, true).values().iterator(); + + new AbstractIterator() + { + protected Map.Entry, V> computeNext() + { + while (backingItr.hasNext()) { + TreeRangeMap.RangeMapEntry entry = (TreeRangeMap.RangeMapEntry)backingItr.next(); + if (entry.getLowerBound().compareTo(subRange.upperBound) >= 0) + break; + if (entry.getUpperBound().compareTo(subRange.lowerBound) > 0) + { + return Maps.immutableEntry(entry.getKey().intersection(subRange), entry.getValue()); + } + } + + return (Map.Entry)endOfData(); + } + }; + } + + public boolean retainAll(Collection c) + { + return TreeRangeMap.SubRangeMap.SubRangeMapAsMap.this.removeEntryIf(Predicates.not(Predicates.in(c))); + } + + public int size() + { + return Iterators.size(iterator()); + } + + public boolean isEmpty() + { + return !iterator().hasNext(); + } + }; + } + + public Collection values() + { + new Maps.Values(this) + { + public boolean removeAll(Collection c) { + return TreeRangeMap.SubRangeMap.SubRangeMapAsMap.this.removeEntryIf(Predicates.compose(Predicates.in(c), Maps.valueFunction())); + } + + public boolean retainAll(Collection c) + { + return TreeRangeMap.SubRangeMap.SubRangeMapAsMap.this.removeEntryIf(Predicates.compose(Predicates.not(Predicates.in(c)), Maps.valueFunction())); + } + }; + } + } + } + + public boolean equals(@Nullable Object o) + { + if ((o instanceof RangeMap)) { + RangeMap rangeMap = (RangeMap)o; + return asMapOfRanges().equals(rangeMap.asMapOfRanges()); + } + return false; + } + + public int hashCode() + { + return asMapOfRanges().hashCode(); + } + + public String toString() + { + return entriesByLowerBound.values().toString(); + } +} diff --git a/src/minecraft/com/google/common/collect/TreeRangeSet.java b/src/minecraft/com/google/common/collect/TreeRangeSet.java new file mode 100644 index 0000000..cb5eff8 --- /dev/null +++ b/src/minecraft/com/google/common/collect/TreeRangeSet.java @@ -0,0 +1,850 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.NavigableMap; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtIncompatible("uses NavigableMap") +public class TreeRangeSet> + extends AbstractRangeSet +{ + @VisibleForTesting + final NavigableMap, Range> rangesByLowerBound; + private transient Set> asRanges; + private transient RangeSet complement; + + public static > TreeRangeSet create() + { + return new TreeRangeSet(new TreeMap()); + } + + + + public static > TreeRangeSet create(RangeSet rangeSet) + { + TreeRangeSet result = create(); + result.addAll(rangeSet); + return result; + } + + private TreeRangeSet(NavigableMap, Range> rangesByLowerCut) { + rangesByLowerBound = rangesByLowerCut; + } + + + + public Set> asRanges() + { + Set> result = asRanges; + return result == null ? (this.asRanges = new AsRanges()) : result; + } + + final class AsRanges extends ForwardingCollection> implements Set> { + AsRanges() {} + + protected Collection> delegate() { return rangesByLowerBound.values(); } + + + public int hashCode() + { + return Sets.hashCodeImpl(this); + } + + public boolean equals(@Nullable Object o) + { + return Sets.equalsImpl(this, o); + } + } + + @Nullable + public Range rangeContaining(C value) + { + Preconditions.checkNotNull(value); + Map.Entry, Range> floorEntry = rangesByLowerBound.floorEntry(Cut.belowValue(value)); + if ((floorEntry != null) && (((Range)floorEntry.getValue()).contains(value))) { + return (Range)floorEntry.getValue(); + } + + return null; + } + + + public boolean encloses(Range range) + { + Preconditions.checkNotNull(range); + Map.Entry, Range> floorEntry = rangesByLowerBound.floorEntry(lowerBound); + return (floorEntry != null) && (((Range)floorEntry.getValue()).encloses(range)); + } + + @Nullable + private Range rangeEnclosing(Range range) { + Preconditions.checkNotNull(range); + Map.Entry, Range> floorEntry = rangesByLowerBound.floorEntry(lowerBound); + return (floorEntry != null) && (((Range)floorEntry.getValue()).encloses(range)) ? (Range)floorEntry.getValue() : null; + } + + + + public Range span() + { + Map.Entry, Range> firstEntry = rangesByLowerBound.firstEntry(); + Map.Entry, Range> lastEntry = rangesByLowerBound.lastEntry(); + if (firstEntry == null) { + throw new NoSuchElementException(); + } + return Range.create(getValuelowerBound, getValueupperBound); + } + + public void add(Range rangeToAdd) + { + Preconditions.checkNotNull(rangeToAdd); + + if (rangeToAdd.isEmpty()) { + return; + } + + + + Cut lbToAdd = lowerBound; + Cut ubToAdd = upperBound; + + Map.Entry, Range> entryBelowLB = rangesByLowerBound.lowerEntry(lbToAdd); + if (entryBelowLB != null) + { + Range rangeBelowLB = (Range)entryBelowLB.getValue(); + if (upperBound.compareTo(lbToAdd) >= 0) + { + if (upperBound.compareTo(ubToAdd) >= 0) + { + ubToAdd = upperBound; + } + + + + + lbToAdd = lowerBound; + } + } + + Map.Entry, Range> entryBelowUB = rangesByLowerBound.floorEntry(ubToAdd); + if (entryBelowUB != null) + { + Range rangeBelowUB = (Range)entryBelowUB.getValue(); + if (upperBound.compareTo(ubToAdd) >= 0) + { + ubToAdd = upperBound; + } + } + + + rangesByLowerBound.subMap(lbToAdd, ubToAdd).clear(); + + replaceRangeWithSameLowerBound(Range.create(lbToAdd, ubToAdd)); + } + + public void remove(Range rangeToRemove) + { + Preconditions.checkNotNull(rangeToRemove); + + if (rangeToRemove.isEmpty()) { + return; + } + + + + + Map.Entry, Range> entryBelowLB = rangesByLowerBound.lowerEntry(lowerBound); + if (entryBelowLB != null) + { + Range rangeBelowLB = (Range)entryBelowLB.getValue(); + if (upperBound.compareTo(lowerBound) >= 0) + { + if ((rangeToRemove.hasUpperBound()) && (upperBound.compareTo(upperBound) >= 0)) + { + + replaceRangeWithSameLowerBound(Range.create(upperBound, upperBound)); + } + + replaceRangeWithSameLowerBound(Range.create(lowerBound, lowerBound)); + } + } + + + Map.Entry, Range> entryBelowUB = rangesByLowerBound.floorEntry(upperBound); + if (entryBelowUB != null) + { + Range rangeBelowUB = (Range)entryBelowUB.getValue(); + if ((rangeToRemove.hasUpperBound()) && (upperBound.compareTo(upperBound) >= 0)) + { + + replaceRangeWithSameLowerBound(Range.create(upperBound, upperBound)); + } + } + + + rangesByLowerBound.subMap(lowerBound, upperBound).clear(); + } + + private void replaceRangeWithSameLowerBound(Range range) { + if (range.isEmpty()) { + rangesByLowerBound.remove(lowerBound); + } else { + rangesByLowerBound.put(lowerBound, range); + } + } + + + + public RangeSet complement() + { + RangeSet result = complement; + return result == null ? (this.complement = new Complement()) : result; + } + + + @VisibleForTesting + static final class RangesByUpperBound> + extends AbstractNavigableMap, Range> + { + private final NavigableMap, Range> rangesByLowerBound; + + private final Range> upperBoundWindow; + + + RangesByUpperBound(NavigableMap, Range> rangesByLowerBound) + { + this.rangesByLowerBound = rangesByLowerBound; + upperBoundWindow = Range.all(); + } + + private RangesByUpperBound(NavigableMap, Range> rangesByLowerBound, Range> upperBoundWindow) + { + this.rangesByLowerBound = rangesByLowerBound; + this.upperBoundWindow = upperBoundWindow; + } + + private NavigableMap, Range> subMap(Range> window) { + if (window.isConnected(upperBoundWindow)) { + return new RangesByUpperBound(rangesByLowerBound, window.intersection(upperBoundWindow)); + } + return ImmutableSortedMap.of(); + } + + + + public NavigableMap, Range> subMap(Cut fromKey, boolean fromInclusive, Cut toKey, boolean toInclusive) + { + return subMap(Range.range(fromKey, BoundType.forBoolean(fromInclusive), toKey, BoundType.forBoolean(toInclusive))); + } + + + + public NavigableMap, Range> headMap(Cut toKey, boolean inclusive) + { + return subMap(Range.upTo(toKey, BoundType.forBoolean(inclusive))); + } + + public NavigableMap, Range> tailMap(Cut fromKey, boolean inclusive) + { + return subMap(Range.downTo(fromKey, BoundType.forBoolean(inclusive))); + } + + public Comparator> comparator() + { + return Ordering.natural(); + } + + public boolean containsKey(@Nullable Object key) + { + return get(key) != null; + } + + public Range get(@Nullable Object key) + { + if ((key instanceof Cut)) { + try + { + Cut cut = (Cut)key; + if (!upperBoundWindow.contains(cut)) { + return null; + } + Map.Entry, Range> candidate = rangesByLowerBound.lowerEntry(cut); + if ((candidate != null) && (getValueupperBound.equals(cut))) { + return (Range)candidate.getValue(); + } + } catch (ClassCastException e) { + return null; + } + } + return null; + } + + + Iterator, Range>> entryIterator() + { + Iterator> backingItr; + + final Iterator> backingItr; + + if (!upperBoundWindow.hasLowerBound()) { + backingItr = rangesByLowerBound.values().iterator(); + } else { + Map.Entry, Range> lowerEntry = rangesByLowerBound.lowerEntry(upperBoundWindow.lowerEndpoint()); + Iterator> backingItr; + if (lowerEntry == null) { + backingItr = rangesByLowerBound.values().iterator(); } else { Iterator> backingItr; + if (upperBoundWindow.lowerBound.isLessThan(getValueupperBound)) { + backingItr = rangesByLowerBound.tailMap(lowerEntry.getKey(), true).values().iterator(); + } else { + backingItr = rangesByLowerBound.tailMap(upperBoundWindow.lowerEndpoint(), true).values().iterator(); + } + } + } + new AbstractIterator() + { + protected Map.Entry, Range> computeNext() { + if (!backingItr.hasNext()) { + return (Map.Entry)endOfData(); + } + Range range = (Range)backingItr.next(); + if (upperBoundWindow.upperBound.isLessThan(upperBound)) { + return (Map.Entry)endOfData(); + } + return Maps.immutableEntry(upperBound, range); + } + }; + } + + Iterator, Range>> descendingEntryIterator() + { + Collection> candidates; + Collection> candidates; + if (upperBoundWindow.hasUpperBound()) { + candidates = rangesByLowerBound.headMap(upperBoundWindow.upperEndpoint(), false).descendingMap().values(); + } + else { + candidates = rangesByLowerBound.descendingMap().values(); + } + final PeekingIterator> backingItr = Iterators.peekingIterator(candidates.iterator()); + if ((backingItr.hasNext()) && (upperBoundWindow.upperBound.isLessThan(peekupperBound))) + { + backingItr.next(); + } + new AbstractIterator() + { + protected Map.Entry, Range> computeNext() { + if (!backingItr.hasNext()) { + return (Map.Entry)endOfData(); + } + Range range = (Range)backingItr.next(); + return upperBoundWindow.lowerBound.isLessThan(upperBound) ? Maps.immutableEntry(upperBound, range) : (Map.Entry)endOfData(); + } + }; + } + + + + public int size() + { + if (upperBoundWindow.equals(Range.all())) { + return rangesByLowerBound.size(); + } + return Iterators.size(entryIterator()); + } + + public boolean isEmpty() + { + return !entryIterator().hasNext() ? true : upperBoundWindow.equals(Range.all()) ? rangesByLowerBound.isEmpty() : false; + } + } + + + + private static final class ComplementRangesByLowerBound> + extends AbstractNavigableMap, Range> + { + private final NavigableMap, Range> positiveRangesByLowerBound; + + + private final NavigableMap, Range> positiveRangesByUpperBound; + + private final Range> complementLowerBoundWindow; + + + ComplementRangesByLowerBound(NavigableMap, Range> positiveRangesByLowerBound) + { + this(positiveRangesByLowerBound, Range.all()); + } + + private ComplementRangesByLowerBound(NavigableMap, Range> positiveRangesByLowerBound, Range> window) + { + this.positiveRangesByLowerBound = positiveRangesByLowerBound; + positiveRangesByUpperBound = new TreeRangeSet.RangesByUpperBound(positiveRangesByLowerBound); + complementLowerBoundWindow = window; + } + + private NavigableMap, Range> subMap(Range> subWindow) { + if (!complementLowerBoundWindow.isConnected(subWindow)) { + return ImmutableSortedMap.of(); + } + subWindow = subWindow.intersection(complementLowerBoundWindow); + return new ComplementRangesByLowerBound(positiveRangesByLowerBound, subWindow); + } + + + + public NavigableMap, Range> subMap(Cut fromKey, boolean fromInclusive, Cut toKey, boolean toInclusive) + { + return subMap(Range.range(fromKey, BoundType.forBoolean(fromInclusive), toKey, BoundType.forBoolean(toInclusive))); + } + + + + public NavigableMap, Range> headMap(Cut toKey, boolean inclusive) + { + return subMap(Range.upTo(toKey, BoundType.forBoolean(inclusive))); + } + + public NavigableMap, Range> tailMap(Cut fromKey, boolean inclusive) + { + return subMap(Range.downTo(fromKey, BoundType.forBoolean(inclusive))); + } + + public Comparator> comparator() + { + return Ordering.natural(); + } + + + + + Iterator, Range>> entryIterator() + { + Collection> positiveRanges; + + + + Collection> positiveRanges; + + + if (complementLowerBoundWindow.hasLowerBound()) { + positiveRanges = positiveRangesByUpperBound.tailMap(complementLowerBoundWindow.lowerEndpoint(), complementLowerBoundWindow.lowerBoundType() == BoundType.CLOSED).values(); + } + else + { + positiveRanges = positiveRangesByUpperBound.values(); + } + final PeekingIterator> positiveItr = Iterators.peekingIterator(positiveRanges.iterator()); + + Cut firstComplementRangeLowerBound; + if ((complementLowerBoundWindow.contains(Cut.belowAll())) && ((!positiveItr.hasNext()) || (peeklowerBound != Cut.belowAll()))) + { + firstComplementRangeLowerBound = Cut.belowAll(); } else { Cut firstComplementRangeLowerBound; + if (positiveItr.hasNext()) { + firstComplementRangeLowerBound = nextupperBound; + } else + return Iterators.emptyIterator(); } + final Cut firstComplementRangeLowerBound; + new AbstractIterator() { + Cut nextComplementRangeLowerBound = firstComplementRangeLowerBound; + + protected Map.Entry, Range> computeNext() + { + if ((complementLowerBoundWindow.upperBound.isLessThan(nextComplementRangeLowerBound)) || (nextComplementRangeLowerBound == Cut.aboveAll())) + { + return (Map.Entry)endOfData(); + } + Range negativeRange; + if (positiveItr.hasNext()) { + Range positiveRange = (Range)positiveItr.next(); + Range negativeRange = Range.create(nextComplementRangeLowerBound, lowerBound); + nextComplementRangeLowerBound = upperBound; + } else { + negativeRange = Range.create(nextComplementRangeLowerBound, Cut.aboveAll()); + nextComplementRangeLowerBound = Cut.aboveAll(); + } + return Maps.immutableEntry(lowerBound, negativeRange); + } + }; + } + + + + + + + + + + + Iterator, Range>> descendingEntryIterator() + { + Cut startingPoint = complementLowerBoundWindow.hasUpperBound() ? (Cut)complementLowerBoundWindow.upperEndpoint() : Cut.aboveAll(); + + + boolean inclusive = (complementLowerBoundWindow.hasUpperBound()) && (complementLowerBoundWindow.upperBoundType() == BoundType.CLOSED); + + final PeekingIterator> positiveItr = Iterators.peekingIterator(positiveRangesByUpperBound.headMap(startingPoint, inclusive).descendingMap().values().iterator()); + + Cut cut; + Cut cut; + if (positiveItr.hasNext()) { + cut = peekupperBound == Cut.aboveAll() ? nextlowerBound : (Cut)positiveRangesByLowerBound.higherKey(peekupperBound); + } + else { + if ((!complementLowerBoundWindow.contains(Cut.belowAll())) || (positiveRangesByLowerBound.containsKey(Cut.belowAll()))) + { + return Iterators.emptyIterator(); + } + cut = (Cut)positiveRangesByLowerBound.higherKey(Cut.belowAll()); + } + final Cut firstComplementRangeUpperBound = (Cut)Objects.firstNonNull(cut, Cut.aboveAll()); + new AbstractIterator() { + Cut nextComplementRangeUpperBound = firstComplementRangeUpperBound; + + protected Map.Entry, Range> computeNext() + { + if (nextComplementRangeUpperBound == Cut.belowAll()) + return (Map.Entry)endOfData(); + if (positiveItr.hasNext()) { + Range positiveRange = (Range)positiveItr.next(); + Range negativeRange = Range.create(upperBound, nextComplementRangeUpperBound); + + nextComplementRangeUpperBound = lowerBound; + if (complementLowerBoundWindow.lowerBound.isLessThan(lowerBound)) { + return Maps.immutableEntry(lowerBound, negativeRange); + } + } else if (complementLowerBoundWindow.lowerBound.isLessThan(Cut.belowAll())) { + Range negativeRange = Range.create(Cut.belowAll(), nextComplementRangeUpperBound); + + nextComplementRangeUpperBound = Cut.belowAll(); + return Maps.immutableEntry(Cut.belowAll(), negativeRange); + } + return (Map.Entry)endOfData(); + } + }; + } + + public int size() + { + return Iterators.size(entryIterator()); + } + + @Nullable + public Range get(Object key) + { + if ((key instanceof Cut)) { + try + { + Cut cut = (Cut)key; + + Map.Entry, Range> firstEntry = tailMap(cut, true).firstEntry(); + if ((firstEntry != null) && (((Cut)firstEntry.getKey()).equals(cut))) { + return (Range)firstEntry.getValue(); + } + } catch (ClassCastException e) { + return null; + } + } + return null; + } + + public boolean containsKey(Object key) + { + return get(key) != null; + } + } + + private final class Complement extends TreeRangeSet { + Complement() { + super(null); + } + + public void add(Range rangeToAdd) + { + TreeRangeSet.this.remove(rangeToAdd); + } + + public void remove(Range rangeToRemove) + { + TreeRangeSet.this.add(rangeToRemove); + } + + public boolean contains(C value) + { + return !TreeRangeSet.this.contains(value); + } + + public RangeSet complement() + { + return TreeRangeSet.this; + } + } + + + + private static final class SubRangeSetRangesByLowerBound> + extends AbstractNavigableMap, Range> + { + private final Range> lowerBoundWindow; + + + private final Range restriction; + + + private final NavigableMap, Range> rangesByLowerBound; + + + private final NavigableMap, Range> rangesByUpperBound; + + + private SubRangeSetRangesByLowerBound(Range> lowerBoundWindow, Range restriction, NavigableMap, Range> rangesByLowerBound) + { + this.lowerBoundWindow = ((Range)Preconditions.checkNotNull(lowerBoundWindow)); + this.restriction = ((Range)Preconditions.checkNotNull(restriction)); + this.rangesByLowerBound = ((NavigableMap)Preconditions.checkNotNull(rangesByLowerBound)); + rangesByUpperBound = new TreeRangeSet.RangesByUpperBound(rangesByLowerBound); + } + + private NavigableMap, Range> subMap(Range> window) { + if (!window.isConnected(lowerBoundWindow)) { + return ImmutableSortedMap.of(); + } + return new SubRangeSetRangesByLowerBound(lowerBoundWindow.intersection(window), restriction, rangesByLowerBound); + } + + + + + public NavigableMap, Range> subMap(Cut fromKey, boolean fromInclusive, Cut toKey, boolean toInclusive) + { + return subMap(Range.range(fromKey, BoundType.forBoolean(fromInclusive), toKey, BoundType.forBoolean(toInclusive))); + } + + + public NavigableMap, Range> headMap(Cut toKey, boolean inclusive) + { + return subMap(Range.upTo(toKey, BoundType.forBoolean(inclusive))); + } + + public NavigableMap, Range> tailMap(Cut fromKey, boolean inclusive) + { + return subMap(Range.downTo(fromKey, BoundType.forBoolean(inclusive))); + } + + public Comparator> comparator() + { + return Ordering.natural(); + } + + public boolean containsKey(@Nullable Object key) + { + return get(key) != null; + } + + @Nullable + public Range get(@Nullable Object key) + { + if ((key instanceof Cut)) { + try + { + Cut cut = (Cut)key; + if ((!lowerBoundWindow.contains(cut)) || (cut.compareTo(restriction.lowerBound) < 0) || (cut.compareTo(restriction.upperBound) >= 0)) + { + return null; } + if (cut.equals(restriction.lowerBound)) + { + Range candidate = (Range)Maps.valueOrNull(rangesByLowerBound.floorEntry(cut)); + if ((candidate != null) && (upperBound.compareTo(restriction.lowerBound) > 0)) { + return candidate.intersection(restriction); + } + } else { + Range result = (Range)rangesByLowerBound.get(cut); + if (result != null) { + return result.intersection(restriction); + } + } + } catch (ClassCastException e) { + return null; + } + } + return null; + } + + Iterator, Range>> entryIterator() + { + if (restriction.isEmpty()) { + return Iterators.emptyIterator(); + } + + if (lowerBoundWindow.upperBound.isLessThan(restriction.lowerBound)) + return Iterators.emptyIterator(); + Iterator> completeRangeItr; final Iterator> completeRangeItr; if (lowerBoundWindow.lowerBound.isLessThan(restriction.lowerBound)) + { + completeRangeItr = rangesByUpperBound.tailMap(restriction.lowerBound, false).values().iterator(); + } + else + { + completeRangeItr = rangesByLowerBound.tailMap(lowerBoundWindow.lowerBound.endpoint(), lowerBoundWindow.lowerBoundType() == BoundType.CLOSED).values().iterator(); + } + + final Cut> upperBoundOnLowerBounds = (Cut)Ordering.natural().min(lowerBoundWindow.upperBound, Cut.belowValue(restriction.upperBound)); + + new AbstractIterator() + { + protected Map.Entry, Range> computeNext() { + if (!completeRangeItr.hasNext()) { + return (Map.Entry)endOfData(); + } + Range nextRange = (Range)completeRangeItr.next(); + if (upperBoundOnLowerBounds.isLessThan(lowerBound)) { + return (Map.Entry)endOfData(); + } + nextRange = nextRange.intersection(restriction); + return Maps.immutableEntry(lowerBound, nextRange); + } + }; + } + + + Iterator, Range>> descendingEntryIterator() + { + if (restriction.isEmpty()) { + return Iterators.emptyIterator(); + } + Cut> upperBoundOnLowerBounds = (Cut)Ordering.natural().min(lowerBoundWindow.upperBound, Cut.belowValue(restriction.upperBound)); + + final Iterator> completeRangeItr = rangesByLowerBound.headMap(upperBoundOnLowerBounds.endpoint(), upperBoundOnLowerBounds.typeAsUpperBound() == BoundType.CLOSED).descendingMap().values().iterator(); + + + + new AbstractIterator() + { + protected Map.Entry, Range> computeNext() { + if (!completeRangeItr.hasNext()) { + return (Map.Entry)endOfData(); + } + Range nextRange = (Range)completeRangeItr.next(); + if (restriction.lowerBound.compareTo(upperBound) >= 0) { + return (Map.Entry)endOfData(); + } + nextRange = nextRange.intersection(restriction); + if (lowerBoundWindow.contains(lowerBound)) { + return Maps.immutableEntry(lowerBound, nextRange); + } + return (Map.Entry)endOfData(); + } + }; + } + + + public int size() + { + return Iterators.size(entryIterator()); + } + } + + public RangeSet subRangeSet(Range view) + { + return view.equals(Range.all()) ? this : new SubRangeSet(view); + } + + private final class SubRangeSet extends TreeRangeSet { + private final Range restriction; + + SubRangeSet() { + super(null); + + this.restriction = restriction; + } + + public boolean encloses(Range range) + { + if ((!restriction.isEmpty()) && (restriction.encloses(range))) { + Range enclosing = TreeRangeSet.this.rangeEnclosing(range); + return (enclosing != null) && (!enclosing.intersection(restriction).isEmpty()); + } + return false; + } + + @Nullable + public Range rangeContaining(C value) + { + if (!restriction.contains(value)) { + return null; + } + Range result = TreeRangeSet.this.rangeContaining(value); + return result == null ? null : result.intersection(restriction); + } + + public void add(Range rangeToAdd) + { + Preconditions.checkArgument(restriction.encloses(rangeToAdd), "Cannot add range %s to subRangeSet(%s)", new Object[] { rangeToAdd, restriction }); + + super.add(rangeToAdd); + } + + public void remove(Range rangeToRemove) + { + if (rangeToRemove.isConnected(restriction)) { + TreeRangeSet.this.remove(rangeToRemove.intersection(restriction)); + } + } + + public boolean contains(C value) + { + return (restriction.contains(value)) && (TreeRangeSet.this.contains(value)); + } + + public void clear() + { + TreeRangeSet.this.remove(restriction); + } + + public RangeSet subRangeSet(Range view) + { + if (view.encloses(restriction)) + return this; + if (view.isConnected(restriction)) { + return new SubRangeSet(this, restriction.intersection(view)); + } + return ImmutableRangeSet.of(); + } + } +} diff --git a/src/minecraft/com/google/common/collect/TreeTraverser.java b/src/minecraft/com/google/common/collect/TreeTraverser.java new file mode 100644 index 0000000..42fc146 --- /dev/null +++ b/src/minecraft/com/google/common/collect/TreeTraverser.java @@ -0,0 +1,215 @@ +package com.google.common.collect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.Iterator; +import java.util.Queue; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible(emulated=true) +public abstract class TreeTraverser +{ + public TreeTraverser() {} + + public abstract Iterable children(T paramT); + + public final FluentIterable preOrderTraversal(final T root) + { + Preconditions.checkNotNull(root); + new FluentIterable() + { + public UnmodifiableIterator iterator() { + return preOrderIterator(root); + } + }; + } + + UnmodifiableIterator preOrderIterator(T root) + { + return new PreOrderIterator(root); + } + + private final class PreOrderIterator extends UnmodifiableIterator { + private final Deque> stack; + + PreOrderIterator() { + stack = new ArrayDeque(); + stack.addLast(Iterators.singletonIterator(Preconditions.checkNotNull(root))); + } + + public boolean hasNext() + { + return !stack.isEmpty(); + } + + public T next() + { + Iterator itr = (Iterator)stack.getLast(); + T result = Preconditions.checkNotNull(itr.next()); + if (!itr.hasNext()) { + stack.removeLast(); + } + Iterator childItr = children(result).iterator(); + if (childItr.hasNext()) { + stack.addLast(childItr); + } + return result; + } + } + + + + + + + + public final FluentIterable postOrderTraversal(final T root) + { + Preconditions.checkNotNull(root); + new FluentIterable() + { + public UnmodifiableIterator iterator() { + return postOrderIterator(root); + } + }; + } + + UnmodifiableIterator postOrderIterator(T root) + { + return new PostOrderIterator(root); + } + + private static final class PostOrderNode { + final T root; + final Iterator childIterator; + + PostOrderNode(T root, Iterator childIterator) { + this.root = Preconditions.checkNotNull(root); + this.childIterator = ((Iterator)Preconditions.checkNotNull(childIterator)); + } + } + + private final class PostOrderIterator extends AbstractIterator { + private final ArrayDeque> stack; + + PostOrderIterator() { + stack = new ArrayDeque(); + stack.addLast(expand(root)); + } + + protected T computeNext() + { + while (!stack.isEmpty()) { + TreeTraverser.PostOrderNode top = (TreeTraverser.PostOrderNode)stack.getLast(); + if (childIterator.hasNext()) { + T child = childIterator.next(); + stack.addLast(expand(child)); + } else { + stack.removeLast(); + return root; + } + } + return endOfData(); + } + + private TreeTraverser.PostOrderNode expand(T t) { + return new TreeTraverser.PostOrderNode(t, children(t).iterator()); + } + } + + + + + + + + public final FluentIterable breadthFirstTraversal(final T root) + { + Preconditions.checkNotNull(root); + new FluentIterable() + { + public UnmodifiableIterator iterator() { + return new TreeTraverser.BreadthFirstIterator(TreeTraverser.this, root); + } + }; + } + + private final class BreadthFirstIterator extends UnmodifiableIterator implements PeekingIterator + { + private final Queue queue; + + BreadthFirstIterator() { + queue = new ArrayDeque(); + queue.add(root); + } + + public boolean hasNext() + { + return !queue.isEmpty(); + } + + public T peek() + { + return queue.element(); + } + + public T next() + { + T result = queue.remove(); + Iterables.addAll(queue, children(result)); + return result; + } + } +} diff --git a/src/minecraft/com/google/common/collect/UnmodifiableIterator.java b/src/minecraft/com/google/common/collect/UnmodifiableIterator.java new file mode 100644 index 0000000..4557195 --- /dev/null +++ b/src/minecraft/com/google/common/collect/UnmodifiableIterator.java @@ -0,0 +1,45 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Iterator; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public abstract class UnmodifiableIterator + implements Iterator +{ + protected UnmodifiableIterator() {} + + @Deprecated + public final void remove() + { + throw new UnsupportedOperationException(); + } +} diff --git a/src/minecraft/com/google/common/collect/UnmodifiableListIterator.java b/src/minecraft/com/google/common/collect/UnmodifiableListIterator.java new file mode 100644 index 0000000..7edbd35 --- /dev/null +++ b/src/minecraft/com/google/common/collect/UnmodifiableListIterator.java @@ -0,0 +1,55 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.ListIterator; + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public abstract class UnmodifiableListIterator + extends UnmodifiableIterator + implements ListIterator +{ + protected UnmodifiableListIterator() {} + + @Deprecated + public final void add(E e) + { + throw new UnsupportedOperationException(); + } + + + + + + @Deprecated + public final void set(E e) + { + throw new UnsupportedOperationException(); + } +} diff --git a/src/minecraft/com/google/common/collect/UnmodifiableSortedMultiset.java b/src/minecraft/com/google/common/collect/UnmodifiableSortedMultiset.java new file mode 100644 index 0000000..c063844 --- /dev/null +++ b/src/minecraft/com/google/common/collect/UnmodifiableSortedMultiset.java @@ -0,0 +1,111 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Comparator; +import java.util.NavigableSet; + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +final class UnmodifiableSortedMultiset + extends Multisets.UnmodifiableMultiset + implements SortedMultiset +{ + private transient UnmodifiableSortedMultiset descendingMultiset; + private static final long serialVersionUID = 0L; + + UnmodifiableSortedMultiset(SortedMultiset delegate) + { + super(delegate); + } + + protected SortedMultiset delegate() + { + return (SortedMultiset)super.delegate(); + } + + public Comparator comparator() + { + return delegate().comparator(); + } + + NavigableSet createElementSet() + { + return Sets.unmodifiableNavigableSet(delegate().elementSet()); + } + + public NavigableSet elementSet() + { + return (NavigableSet)super.elementSet(); + } + + + + public SortedMultiset descendingMultiset() + { + UnmodifiableSortedMultiset result = descendingMultiset; + if (result == null) { + result = new UnmodifiableSortedMultiset(delegate().descendingMultiset()); + + descendingMultiset = this; + return this.descendingMultiset = result; + } + return result; + } + + public Multiset.Entry firstEntry() + { + return delegate().firstEntry(); + } + + public Multiset.Entry lastEntry() + { + return delegate().lastEntry(); + } + + public Multiset.Entry pollFirstEntry() + { + throw new UnsupportedOperationException(); + } + + public Multiset.Entry pollLastEntry() + { + throw new UnsupportedOperationException(); + } + + public SortedMultiset headMultiset(E upperBound, BoundType boundType) + { + return Multisets.unmodifiableSortedMultiset(delegate().headMultiset(upperBound, boundType)); + } + + + + + public SortedMultiset subMultiset(E lowerBound, BoundType lowerBoundType, E upperBound, BoundType upperBoundType) + { + return Multisets.unmodifiableSortedMultiset(delegate().subMultiset(lowerBound, lowerBoundType, upperBound, upperBoundType)); + } + + + public SortedMultiset tailMultiset(E lowerBound, BoundType boundType) + { + return Multisets.unmodifiableSortedMultiset(delegate().tailMultiset(lowerBound, boundType)); + } +} diff --git a/src/minecraft/com/google/common/collect/UsingToStringOrdering.java b/src/minecraft/com/google/common/collect/UsingToStringOrdering.java new file mode 100644 index 0000000..c26dcf3 --- /dev/null +++ b/src/minecraft/com/google/common/collect/UsingToStringOrdering.java @@ -0,0 +1,46 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.io.Serializable; + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true) +final class UsingToStringOrdering + extends Ordering + implements Serializable +{ + static final UsingToStringOrdering INSTANCE = new UsingToStringOrdering(); + private static final long serialVersionUID = 0L; + + public int compare(Object left, Object right) { return left.toString().compareTo(right.toString()); } + + + private Object readResolve() + { + return INSTANCE; + } + + public String toString() { + return "Ordering.usingToString()"; + } + + private UsingToStringOrdering() {} +} diff --git a/src/minecraft/com/google/common/collect/WellBehavedMap.java b/src/minecraft/com/google/common/collect/WellBehavedMap.java new file mode 100644 index 0000000..f614cb5 --- /dev/null +++ b/src/minecraft/com/google/common/collect/WellBehavedMap.java @@ -0,0 +1,98 @@ +package com.google.common.collect; + +import com.google.common.annotations.GwtCompatible; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +final class WellBehavedMap + extends ForwardingMap +{ + private final Map delegate; + private Set> entrySet; + + private WellBehavedMap(Map delegate) + { + this.delegate = delegate; + } + + + + + + + static WellBehavedMap wrap(Map delegate) + { + return new WellBehavedMap(delegate); + } + + protected Map delegate() { + return delegate; + } + + public Set> entrySet() { + Set> es = entrySet; + if (es != null) { + return es; + } + return this.entrySet = new EntrySet(null); + } + + private final class EntrySet extends Maps.EntrySet { + private EntrySet() {} + + Map map() { return WellBehavedMap.this; } + + + public Iterator> iterator() + { + new TransformedIterator(keySet().iterator()) + { + Map.Entry transform(final K key) { + new AbstractMapEntry() + { + public K getKey() { + return key; + } + + public V getValue() + { + return get(key); + } + + public V setValue(V value) + { + return put(key, value); + } + }; + } + }; + } + } +} diff --git a/src/minecraft/com/google/common/collect/package-info.java b/src/minecraft/com/google/common/collect/package-info.java new file mode 100644 index 0000000..8960712 --- /dev/null +++ b/src/minecraft/com/google/common/collect/package-info.java @@ -0,0 +1,6 @@ +package com.google.common.collect; + +import javax.annotation.ParametersAreNonnullByDefault; + +@ParametersAreNonnullByDefault +abstract interface package-info {} diff --git a/src/minecraft/com/google/common/escape/ArrayBasedCharEscaper.java b/src/minecraft/com/google/common/escape/ArrayBasedCharEscaper.java new file mode 100644 index 0000000..87fd8dc --- /dev/null +++ b/src/minecraft/com/google/common/escape/ArrayBasedCharEscaper.java @@ -0,0 +1,148 @@ +package com.google.common.escape; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.Map; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +public abstract class ArrayBasedCharEscaper + extends CharEscaper +{ + private final char[][] replacements; + private final int replacementsLength; + private final char safeMin; + private final char safeMax; + + protected ArrayBasedCharEscaper(Map replacementMap, char safeMin, char safeMax) + { + this(ArrayBasedEscaperMap.create(replacementMap), safeMin, safeMax); + } + + + + + + + + + + + + + + + + + + protected ArrayBasedCharEscaper(ArrayBasedEscaperMap escaperMap, char safeMin, char safeMax) + { + Preconditions.checkNotNull(escaperMap); + replacements = escaperMap.getReplacementArray(); + replacementsLength = replacements.length; + if (safeMax < safeMin) + { + + safeMax = '\000'; + safeMin = 65535; + } + this.safeMin = safeMin; + this.safeMax = safeMax; + } + + + + + + + public final String escape(String s) + { + Preconditions.checkNotNull(s); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (((c < replacementsLength) && (replacements[c] != null)) || (c > safeMax) || (c < safeMin)) + { + return escapeSlow(s, i); + } + } + return s; + } + + + + + + protected final char[] escape(char c) + { + if (c < replacementsLength) { + char[] chars = replacements[c]; + if (chars != null) { + return chars; + } + } + if ((c >= safeMin) && (c <= safeMax)) { + return null; + } + return escapeUnsafe(c); + } + + protected abstract char[] escapeUnsafe(char paramChar); +} diff --git a/src/minecraft/com/google/common/escape/ArrayBasedEscaperMap.java b/src/minecraft/com/google/common/escape/ArrayBasedEscaperMap.java new file mode 100644 index 0000000..94f40ee --- /dev/null +++ b/src/minecraft/com/google/common/escape/ArrayBasedEscaperMap.java @@ -0,0 +1,91 @@ +package com.google.common.escape; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import java.util.Collections; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +public final class ArrayBasedEscaperMap +{ + private final char[][] replacementArray; + + public static ArrayBasedEscaperMap create(Map replacements) + { + return new ArrayBasedEscaperMap(createReplacementArray(replacements)); + } + + + + + private ArrayBasedEscaperMap(char[][] replacementArray) + { + this.replacementArray = replacementArray; + } + + char[][] getReplacementArray() + { + return replacementArray; + } + + + + @VisibleForTesting + static char[][] createReplacementArray(Map map) + { + Preconditions.checkNotNull(map); + if (map.isEmpty()) { + return EMPTY_REPLACEMENT_ARRAY; + } + char max = ((Character)Collections.max(map.keySet())).charValue(); + char[][] replacements = new char[max + '\001'][]; + for (Iterator i$ = map.keySet().iterator(); i$.hasNext();) { char c = ((Character)i$.next()).charValue(); + replacements[c] = ((String)map.get(Character.valueOf(c))).toCharArray(); + } + return replacements; + } + + + private static final char[][] EMPTY_REPLACEMENT_ARRAY = new char[0][0]; +} diff --git a/src/minecraft/com/google/common/escape/ArrayBasedUnicodeEscaper.java b/src/minecraft/com/google/common/escape/ArrayBasedUnicodeEscaper.java new file mode 100644 index 0000000..9fe8dc9 --- /dev/null +++ b/src/minecraft/com/google/common/escape/ArrayBasedUnicodeEscaper.java @@ -0,0 +1,198 @@ +package com.google.common.escape; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.Map; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +public abstract class ArrayBasedUnicodeEscaper + extends UnicodeEscaper +{ + private final char[][] replacements; + private final int replacementsLength; + private final int safeMin; + private final int safeMax; + private final char safeMinChar; + private final char safeMaxChar; + + protected ArrayBasedUnicodeEscaper(Map replacementMap, int safeMin, int safeMax, @Nullable String unsafeReplacement) + { + this(ArrayBasedEscaperMap.create(replacementMap), safeMin, safeMax, unsafeReplacement); + } + + + + + + + + + + + + + + + + + + + + + protected ArrayBasedUnicodeEscaper(ArrayBasedEscaperMap escaperMap, int safeMin, int safeMax, @Nullable String unsafeReplacement) + { + Preconditions.checkNotNull(escaperMap); + replacements = escaperMap.getReplacementArray(); + replacementsLength = replacements.length; + if (safeMax < safeMin) + { + + safeMax = -1; + safeMin = Integer.MAX_VALUE; + } + this.safeMin = safeMin; + this.safeMax = safeMax; + + + + + + + + + + + + + + + if (safeMin >= 55296) + { + + safeMinChar = 65535; + safeMaxChar = '\000'; + } + else + { + safeMinChar = ((char)safeMin); + safeMaxChar = ((char)Math.min(safeMax, 55295)); + } + } + + + + + + + + public final String escape(String s) + { + Preconditions.checkNotNull(s); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (((c < replacementsLength) && (replacements[c] != null)) || (c > safeMaxChar) || (c < safeMinChar)) + { + return escapeSlow(s, i); + } + } + return s; + } + + + protected final int nextEscapeIndex(CharSequence csq, int index, int end) + { + while (index < end) { + char c = csq.charAt(index); + if (((c < replacementsLength) && (replacements[c] != null)) || (c > safeMaxChar) || (c < safeMinChar)) { + break; + } + + index++; + } + return index; + } + + + + + + + protected final char[] escape(int cp) + { + if (cp < replacementsLength) { + char[] chars = replacements[cp]; + if (chars != null) { + return chars; + } + } + if ((cp >= safeMin) && (cp <= safeMax)) { + return null; + } + return escapeUnsafe(cp); + } + + protected abstract char[] escapeUnsafe(int paramInt); +} diff --git a/src/minecraft/com/google/common/escape/CharEscaper.java b/src/minecraft/com/google/common/escape/CharEscaper.java new file mode 100644 index 0000000..241222c --- /dev/null +++ b/src/minecraft/com/google/common/escape/CharEscaper.java @@ -0,0 +1,169 @@ +package com.google.common.escape; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +public abstract class CharEscaper + extends Escaper +{ + private static final int DEST_PAD_MULTIPLIER = 2; + + protected CharEscaper() {} + + public String escape(String string) + { + Preconditions.checkNotNull(string); + + int length = string.length(); + for (int index = 0; index < length; index++) { + if (escape(string.charAt(index)) != null) { + return escapeSlow(string, index); + } + } + return string; + } + + + + + + + + + + + + protected final String escapeSlow(String s, int index) + { + int slen = s.length(); + + + char[] dest = Platform.charBufferFromThreadLocal(); + int destSize = dest.length; + int destIndex = 0; + int lastEscape = 0; + for (; + + + index < slen; index++) + { + + char[] r = escape(s.charAt(index)); + + + if (r != null) + { + int rlen = r.length; + int charsSkipped = index - lastEscape; + + + + + int sizeNeeded = destIndex + charsSkipped + rlen; + if (destSize < sizeNeeded) { + destSize = sizeNeeded + 2 * (slen - index); + dest = growBuffer(dest, destIndex, destSize); + } + + + if (charsSkipped > 0) { + s.getChars(lastEscape, index, dest, destIndex); + destIndex += charsSkipped; + } + + + if (rlen > 0) { + System.arraycopy(r, 0, dest, destIndex, rlen); + destIndex += rlen; + } + lastEscape = index + 1; + } + } + + int charsLeft = slen - lastEscape; + if (charsLeft > 0) { + int sizeNeeded = destIndex + charsLeft; + if (destSize < sizeNeeded) + { + + dest = growBuffer(dest, destIndex, sizeNeeded); + } + s.getChars(lastEscape, slen, dest, destIndex); + destIndex = sizeNeeded; + } + return new String(dest, 0, destIndex); + } + + + + + + + + + + + protected abstract char[] escape(char paramChar); + + + + + + + + + + + private static char[] growBuffer(char[] dest, int index, int size) + { + char[] copy = new char[size]; + if (index > 0) { + System.arraycopy(dest, 0, copy, 0, index); + } + return copy; + } +} diff --git a/src/minecraft/com/google/common/escape/CharEscaperBuilder.java b/src/minecraft/com/google/common/escape/CharEscaperBuilder.java new file mode 100644 index 0000000..318b4c7 --- /dev/null +++ b/src/minecraft/com/google/common/escape/CharEscaperBuilder.java @@ -0,0 +1,131 @@ +package com.google.common.escape; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +public final class CharEscaperBuilder +{ + private final Map map; + + private static class CharArrayDecorator + extends CharEscaper + { + private final char[][] replacements; + private final int replaceLength; + + CharArrayDecorator(char[][] replacements) + { + this.replacements = replacements; + replaceLength = replacements.length; + } + + + + + public String escape(String s) + { + int slen = s.length(); + for (int index = 0; index < slen; index++) { + char c = s.charAt(index); + if ((c < replacements.length) && (replacements[c] != null)) { + return escapeSlow(s, index); + } + } + return s; + } + + protected char[] escape(char c) { + return c < replaceLength ? replacements[c] : null; + } + } + + + + + + private int max = -1; + + + + public CharEscaperBuilder() + { + map = new HashMap(); + } + + + + public CharEscaperBuilder addEscape(char c, String r) + { + map.put(Character.valueOf(c), Preconditions.checkNotNull(r)); + if (c > max) { + max = c; + } + return this; + } + + + + public CharEscaperBuilder addEscapes(char[] cs, String r) + { + Preconditions.checkNotNull(r); + for (char c : cs) { + addEscape(c, r); + } + return this; + } + + + + + + + + public char[][] toArray() + { + char[][] result = new char[max + 1][]; + for (Map.Entry entry : map.entrySet()) { + result[((Character)entry.getKey()).charValue()] = ((String)entry.getValue()).toCharArray(); + } + return result; + } + + + + + + + public Escaper toEscaper() + { + return new CharArrayDecorator(toArray()); + } +} diff --git a/src/minecraft/com/google/common/escape/Escaper.java b/src/minecraft/com/google/common/escape/Escaper.java new file mode 100644 index 0000000..8d8616b --- /dev/null +++ b/src/minecraft/com/google/common/escape/Escaper.java @@ -0,0 +1,102 @@ +package com.google.common.escape; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +public abstract class Escaper +{ + private final Function asFunction = new Function() + { + public String apply(String from) + { + return escape(from); + } + }; + + protected Escaper() {} + + public abstract String escape(String paramString); + + public final Function asFunction() { return asFunction; } +} diff --git a/src/minecraft/com/google/common/escape/Escapers.java b/src/minecraft/com/google/common/escape/Escapers.java new file mode 100644 index 0000000..4bde55a --- /dev/null +++ b/src/minecraft/com/google/common/escape/Escapers.java @@ -0,0 +1,275 @@ +package com.google.common.escape; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +public final class Escapers +{ + private Escapers() {} + + public static Escaper nullEscaper() + { + return NULL_ESCAPER; + } + + + + private static final Escaper NULL_ESCAPER = new CharEscaper() { + public String escape(String string) { + return (String)Preconditions.checkNotNull(string); + } + + protected char[] escape(char c) + { + return null; + } + }; + + + + + + + + + + + + + + + + public static Builder builder() + { + return new Builder(null); + } + + + + + + + + + + + + + @Beta + public static final class Builder + { + private final Map replacementMap = new HashMap(); + + private char safeMin = '\000'; + private char safeMax = 65535; + private String unsafeReplacement = null; + + + + + + + private Builder() {} + + + + + + + public Builder setSafeRange(char safeMin, char safeMax) + { + this.safeMin = safeMin; + this.safeMax = safeMax; + return this; + } + + + + + + + + + + public Builder setUnsafeReplacement(@Nullable String unsafeReplacement) + { + this.unsafeReplacement = unsafeReplacement; + return this; + } + + + + + + + + + + + + public Builder addEscape(char c, String replacement) + { + Preconditions.checkNotNull(replacement); + + replacementMap.put(Character.valueOf(c), replacement); + return this; + } + + + + public Escaper build() + { + new ArrayBasedCharEscaper(replacementMap, safeMin, safeMax) { + private final char[] replacementChars = unsafeReplacement != null ? unsafeReplacement.toCharArray() : null; + + protected char[] escapeUnsafe(char c) { + return replacementChars; + } + }; + } + } + + + + + + + + + + + + + + + + + static UnicodeEscaper asUnicodeEscaper(Escaper escaper) + { + Preconditions.checkNotNull(escaper); + if ((escaper instanceof UnicodeEscaper)) + return (UnicodeEscaper)escaper; + if ((escaper instanceof CharEscaper)) { + return wrap((CharEscaper)escaper); + } + + + throw new IllegalArgumentException("Cannot create a UnicodeEscaper from: " + escaper.getClass().getName()); + } + + + + + + + + + + + + public static String computeReplacement(CharEscaper escaper, char c) + { + return stringOrNull(escaper.escape(c)); + } + + + + + + + + + + + public static String computeReplacement(UnicodeEscaper escaper, int cp) + { + return stringOrNull(escaper.escape(cp)); + } + + private static String stringOrNull(char[] in) { + return in == null ? null : new String(in); + } + + private static UnicodeEscaper wrap(CharEscaper escaper) + { + new UnicodeEscaper() + { + protected char[] escape(int cp) { + if (cp < 65536) { + return val$escaper.escape((char)cp); + } + + + + + char[] surrogateChars = new char[2]; + Character.toChars(cp, surrogateChars, 0); + char[] hiChars = val$escaper.escape(surrogateChars[0]); + char[] loChars = val$escaper.escape(surrogateChars[1]); + + + + + + if ((hiChars == null) && (loChars == null)) + { + return null; + } + + int hiCount = hiChars != null ? hiChars.length : 1; + int loCount = loChars != null ? loChars.length : 1; + char[] output = new char[hiCount + loCount]; + if (hiChars != null) + { + for (int n = 0; n < hiChars.length; n++) { + output[n] = hiChars[n]; + } + } else { + output[0] = surrogateChars[0]; + } + if (loChars != null) { + for (int n = 0; n < loChars.length; n++) { + output[(hiCount + n)] = loChars[n]; + } + } else { + output[hiCount] = surrogateChars[1]; + } + return output; + } + }; + } +} diff --git a/src/minecraft/com/google/common/escape/Platform.java b/src/minecraft/com/google/common/escape/Platform.java new file mode 100644 index 0000000..ff718a3 --- /dev/null +++ b/src/minecraft/com/google/common/escape/Platform.java @@ -0,0 +1,46 @@ +package com.google.common.escape; + +import com.google.common.annotations.GwtCompatible; + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +final class Platform +{ + private Platform() {} + + static char[] charBufferFromThreadLocal() + { + return (char[])DEST_TL.get(); + } + + + + + + + private static final ThreadLocal DEST_TL = new ThreadLocal() + { + protected char[] initialValue() { + return new char['Ѐ']; + } + }; +} diff --git a/src/minecraft/com/google/common/escape/UnicodeEscaper.java b/src/minecraft/com/google/common/escape/UnicodeEscaper.java new file mode 100644 index 0000000..c1d2266 --- /dev/null +++ b/src/minecraft/com/google/common/escape/UnicodeEscaper.java @@ -0,0 +1,310 @@ +package com.google.common.escape; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +public abstract class UnicodeEscaper + extends Escaper +{ + private static final int DEST_PAD = 32; + + protected UnicodeEscaper() {} + + protected abstract char[] escape(int paramInt); + + protected int nextEscapeIndex(CharSequence csq, int start, int end) + { + int index = start; + while (index < end) { + int cp = codePointAt(csq, index, end); + if ((cp < 0) || (escape(cp) != null)) { + break; + } + index += (Character.isSupplementaryCodePoint(cp) ? 2 : 1); + } + return index; + } + + + + + + + + + + + + + + + + + + + + + + + + + public String escape(String string) + { + Preconditions.checkNotNull(string); + int end = string.length(); + int index = nextEscapeIndex(string, 0, end); + return index == end ? string : escapeSlow(string, index); + } + + + + + + + + + + + + + + + + + + protected final String escapeSlow(String s, int index) + { + int end = s.length(); + + + char[] dest = Platform.charBufferFromThreadLocal(); + int destIndex = 0; + int unescapedChunkStart = 0; + + while (index < end) { + int cp = codePointAt(s, index, end); + if (cp < 0) { + throw new IllegalArgumentException("Trailing high surrogate at end of input"); + } + + + + + char[] escaped = escape(cp); + int nextIndex = index + (Character.isSupplementaryCodePoint(cp) ? 2 : 1); + if (escaped != null) { + int charsSkipped = index - unescapedChunkStart; + + + + int sizeNeeded = destIndex + charsSkipped + escaped.length; + if (dest.length < sizeNeeded) { + int destLength = sizeNeeded + (end - index) + 32; + dest = growBuffer(dest, destIndex, destLength); + } + + if (charsSkipped > 0) { + s.getChars(unescapedChunkStart, index, dest, destIndex); + destIndex += charsSkipped; + } + if (escaped.length > 0) { + System.arraycopy(escaped, 0, dest, destIndex, escaped.length); + destIndex += escaped.length; + } + + unescapedChunkStart = nextIndex; + } + index = nextEscapeIndex(s, nextIndex, end); + } + + + + int charsSkipped = end - unescapedChunkStart; + if (charsSkipped > 0) { + int endIndex = destIndex + charsSkipped; + if (dest.length < endIndex) { + dest = growBuffer(dest, destIndex, endIndex); + } + s.getChars(unescapedChunkStart, end, dest, destIndex); + destIndex = endIndex; + } + return new String(dest, 0, destIndex); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + protected static int codePointAt(CharSequence seq, int index, int end) + { + Preconditions.checkNotNull(seq); + if (index < end) { + char c1 = seq.charAt(index++); + if ((c1 < 55296) || (c1 > 57343)) + { + + return c1; } + if (c1 <= 56319) + { + if (index == end) { + return -c1; + } + + char c2 = seq.charAt(index); + if (Character.isLowSurrogate(c2)) { + return Character.toCodePoint(c1, c2); + } + throw new IllegalArgumentException("Expected low surrogate but got char '" + c2 + "' with value " + c2 + " at index " + index + " in '" + seq + "'"); + } + + + + throw new IllegalArgumentException("Unexpected low surrogate character '" + c1 + "' with value " + c1 + " at index " + (index - 1) + " in '" + seq + "'"); + } + + + + + throw new IndexOutOfBoundsException("Index exceeds specified range"); + } + + + + + + private static char[] growBuffer(char[] dest, int index, int size) + { + char[] copy = new char[size]; + if (index > 0) { + System.arraycopy(dest, 0, copy, 0, index); + } + return copy; + } +} diff --git a/src/minecraft/com/google/common/escape/package-info.java b/src/minecraft/com/google/common/escape/package-info.java new file mode 100644 index 0000000..89a3277 --- /dev/null +++ b/src/minecraft/com/google/common/escape/package-info.java @@ -0,0 +1,6 @@ +package com.google.common.escape; + +import javax.annotation.ParametersAreNonnullByDefault; + +@ParametersAreNonnullByDefault +abstract interface package-info {} diff --git a/src/minecraft/com/google/common/eventbus/AllowConcurrentEvents.java b/src/minecraft/com/google/common/eventbus/AllowConcurrentEvents.java new file mode 100644 index 0000000..8dfe9c3 --- /dev/null +++ b/src/minecraft/com/google/common/eventbus/AllowConcurrentEvents.java @@ -0,0 +1,12 @@ +package com.google.common.eventbus; + +import com.google.common.annotations.Beta; +import java.lang.annotation.Annotation; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({java.lang.annotation.ElementType.METHOD}) +@Beta +public @interface AllowConcurrentEvents {} diff --git a/src/minecraft/com/google/common/eventbus/AnnotatedSubscriberFinder.java b/src/minecraft/com/google/common/eventbus/AnnotatedSubscriberFinder.java new file mode 100644 index 0000000..388092e --- /dev/null +++ b/src/minecraft/com/google/common/eventbus/AnnotatedSubscriberFinder.java @@ -0,0 +1,176 @@ +package com.google.common.eventbus; + +import com.google.common.base.Objects; +import com.google.common.base.Throwables; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.common.reflect.TypeToken; +import com.google.common.reflect.TypeToken.TypeSet; +import com.google.common.util.concurrent.UncheckedExecutionException; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +class AnnotatedSubscriberFinder + implements SubscriberFindingStrategy +{ + private static final LoadingCache, ImmutableList> subscriberMethodsCache = CacheBuilder.newBuilder().weakKeys().build(new CacheLoader() + { + + public ImmutableList load(Class concreteClass) + throws Exception + { + return AnnotatedSubscriberFinder.getAnnotatedMethodsInternal(concreteClass); + } + }); + + + + + + + + AnnotatedSubscriberFinder() {} + + + + + + + public Multimap, EventSubscriber> findAllSubscribers(Object listener) + { + Multimap, EventSubscriber> methodsInListener = HashMultimap.create(); + Class clazz = listener.getClass(); + for (Method method : getAnnotatedMethods(clazz)) { + Class[] parameterTypes = method.getParameterTypes(); + Class eventType = parameterTypes[0]; + EventSubscriber subscriber = makeSubscriber(listener, method); + methodsInListener.put(eventType, subscriber); + } + return methodsInListener; + } + + private static ImmutableList getAnnotatedMethods(Class clazz) { + try { + return (ImmutableList)subscriberMethodsCache.getUnchecked(clazz); + } catch (UncheckedExecutionException e) { + throw Throwables.propagate(e.getCause()); + } + } + + private static final class MethodIdentifier { + private final String name; + private final List> parameterTypes; + + MethodIdentifier(Method method) { + name = method.getName(); + parameterTypes = Arrays.asList(method.getParameterTypes()); + } + + public int hashCode() + { + return Objects.hashCode(new Object[] { name, parameterTypes }); + } + + public boolean equals(@Nullable Object o) + { + if ((o instanceof MethodIdentifier)) { + MethodIdentifier ident = (MethodIdentifier)o; + return (name.equals(name)) && (parameterTypes.equals(parameterTypes)); + } + return false; + } + } + + private static ImmutableList getAnnotatedMethodsInternal(Class clazz) { + Set> supers = TypeToken.of(clazz).getTypes().rawTypes(); + Map identifiers = Maps.newHashMap(); + for (Class superClazz : supers) { + for (Method superClazzMethod : superClazz.getMethods()) { + if (superClazzMethod.isAnnotationPresent(Subscribe.class)) { + Class[] parameterTypes = superClazzMethod.getParameterTypes(); + if (parameterTypes.length != 1) { + throw new IllegalArgumentException("Method " + superClazzMethod + " has @Subscribe annotation, but requires " + parameterTypes.length + " arguments. Event subscriber methods must require a single argument."); + } + + + + MethodIdentifier ident = new MethodIdentifier(superClazzMethod); + if (!identifiers.containsKey(ident)) { + identifiers.put(ident, superClazzMethod); + } + } + } + } + return ImmutableList.copyOf(identifiers.values()); + } + + + + + private static EventSubscriber makeSubscriber(Object listener, Method method) + { + EventSubscriber wrapper; + + + + EventSubscriber wrapper; + + + + if (methodIsDeclaredThreadSafe(method)) { + wrapper = new EventSubscriber(listener, method); + } else { + wrapper = new SynchronizedEventSubscriber(listener, method); + } + return wrapper; + } + + + + + + + + + private static boolean methodIsDeclaredThreadSafe(Method method) + { + return method.getAnnotation(AllowConcurrentEvents.class) != null; + } +} diff --git a/src/minecraft/com/google/common/eventbus/AsyncEventBus.java b/src/minecraft/com/google/common/eventbus/AsyncEventBus.java new file mode 100644 index 0000000..f53d88e --- /dev/null +++ b/src/minecraft/com/google/common/eventbus/AsyncEventBus.java @@ -0,0 +1,121 @@ +package com.google.common.eventbus; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.Executor; + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public class AsyncEventBus + extends EventBus +{ + private final Executor executor; + private final ConcurrentLinkedQueue eventsToDispatch = new ConcurrentLinkedQueue(); + + + + + + + + + + + public AsyncEventBus(String identifier, Executor executor) + { + super(identifier); + this.executor = ((Executor)Preconditions.checkNotNull(executor)); + } + + + + + + + + + + + + public AsyncEventBus(Executor executor, SubscriberExceptionHandler subscriberExceptionHandler) + { + super(subscriberExceptionHandler); + this.executor = ((Executor)Preconditions.checkNotNull(executor)); + } + + + + + + + + + public AsyncEventBus(Executor executor) + { + super("default"); + this.executor = ((Executor)Preconditions.checkNotNull(executor)); + } + + void enqueueEvent(Object event, EventSubscriber subscriber) + { + eventsToDispatch.offer(new EventBus.EventWithSubscriber(event, subscriber)); + } + + + + + + protected void dispatchQueuedEvents() + { + for (;;) + { + EventBus.EventWithSubscriber eventWithSubscriber = (EventBus.EventWithSubscriber)eventsToDispatch.poll(); + if (eventWithSubscriber == null) { + break; + } + + dispatch(event, subscriber); + } + } + + + + + void dispatch(final Object event, final EventSubscriber subscriber) + { + Preconditions.checkNotNull(event); + Preconditions.checkNotNull(subscriber); + executor.execute(new Runnable() + { + public void run() + { + AsyncEventBus.this.dispatch(event, subscriber); + } + }); + } +} diff --git a/src/minecraft/com/google/common/eventbus/DeadEvent.java b/src/minecraft/com/google/common/eventbus/DeadEvent.java new file mode 100644 index 0000000..ecb42d9 --- /dev/null +++ b/src/minecraft/com/google/common/eventbus/DeadEvent.java @@ -0,0 +1,70 @@ +package com.google.common.eventbus; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public class DeadEvent +{ + private final Object source; + private final Object event; + + public DeadEvent(Object source, Object event) + { + this.source = Preconditions.checkNotNull(source); + this.event = Preconditions.checkNotNull(event); + } + + + + + + + public Object getSource() + { + return source; + } + + + + + + + public Object getEvent() + { + return event; + } +} diff --git a/src/minecraft/com/google/common/eventbus/EventBus.java b/src/minecraft/com/google/common/eventbus/EventBus.java new file mode 100644 index 0000000..11ff7b6 --- /dev/null +++ b/src/minecraft/com/google/common/eventbus/EventBus.java @@ -0,0 +1,408 @@ +package com.google.common.eventbus; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.base.Throwables; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import com.google.common.collect.SetMultimap; +import com.google.common.reflect.TypeToken; +import com.google.common.reflect.TypeToken.TypeSet; +import com.google.common.util.concurrent.UncheckedExecutionException; +import java.lang.reflect.InvocationTargetException; +import java.util.Collection; +import java.util.LinkedList; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Queue; +import java.util.Set; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.logging.Level; +import java.util.logging.Logger; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public class EventBus +{ + private static final LoadingCache, Set>> flattenHierarchyCache = CacheBuilder.newBuilder().weakKeys().build(new CacheLoader() + { + + + public Set> load(Class concreteClass) + { + + return TypeToken.of(concreteClass).getTypes().rawTypes(); + } + }); + + + + + + + + + + + + + + + + + private final SetMultimap, EventSubscriber> subscribersByType = HashMultimap.create(); + + private final ReadWriteLock subscribersByTypeLock = new ReentrantReadWriteLock(); + + + + + + + private final SubscriberFindingStrategy finder = new AnnotatedSubscriberFinder(); + + + private final ThreadLocal> eventsToDispatch = new ThreadLocal() + { + protected Queue initialValue() { + return new LinkedList(); + } + }; + + + private final ThreadLocal isDispatching = new ThreadLocal() + { + protected Boolean initialValue() { + return Boolean.valueOf(false); + } + }; + + + private SubscriberExceptionHandler subscriberExceptionHandler; + + + public EventBus() + { + this("default"); + } + + + + + + + public EventBus(String identifier) + { + this(new LoggingSubscriberExceptionHandler(identifier)); + } + + + + + + + public EventBus(SubscriberExceptionHandler subscriberExceptionHandler) + { + this.subscriberExceptionHandler = ((SubscriberExceptionHandler)Preconditions.checkNotNull(subscriberExceptionHandler)); + } + + + + + + + + + public void register(Object object) + { + Multimap, EventSubscriber> methodsInListener = finder.findAllSubscribers(object); + + subscribersByTypeLock.writeLock().lock(); + try { + subscribersByType.putAll(methodsInListener); + } finally { + subscribersByTypeLock.writeLock().unlock(); + } + } + + + + + + + public void unregister(Object object) + { + Multimap, EventSubscriber> methodsInListener = finder.findAllSubscribers(object); + + for (Map.Entry, Collection> entry : methodsInListener.asMap().entrySet()) { + Class eventType = (Class)entry.getKey(); + Collection eventMethodsInListener = (Collection)entry.getValue(); + + subscribersByTypeLock.writeLock().lock(); + try { + Set currentSubscribers = subscribersByType.get(eventType); + if (!currentSubscribers.containsAll(eventMethodsInListener)) { + throw new IllegalArgumentException("missing event subscriber for an annotated method. Is " + object + " registered?"); + } + + currentSubscribers.removeAll(eventMethodsInListener); + } finally { + subscribersByTypeLock.writeLock().unlock(); + } + } + } + + + + + + + + + + + + public void post(Object event) + { + Set> dispatchTypes = flattenHierarchy(event.getClass()); + + boolean dispatched = false; + for (Class eventType : dispatchTypes) { + subscribersByTypeLock.readLock().lock(); + try { + Set wrappers = subscribersByType.get(eventType); + + if (!wrappers.isEmpty()) { + dispatched = true; + for (EventSubscriber wrapper : wrappers) { + enqueueEvent(event, wrapper); + } + } + } finally { + subscribersByTypeLock.readLock().unlock(); + } + } + + if ((!dispatched) && (!(event instanceof DeadEvent))) { + post(new DeadEvent(this, event)); + } + + dispatchQueuedEvents(); + } + + + + + + void enqueueEvent(Object event, EventSubscriber subscriber) + { + ((Queue)eventsToDispatch.get()).offer(new EventWithSubscriber(event, subscriber)); + } + + + + + + + + void dispatchQueuedEvents() + { + if (((Boolean)isDispatching.get()).booleanValue()) { + return; + } + + isDispatching.set(Boolean.valueOf(true)); + try { + Queue events = (Queue)eventsToDispatch.get(); + EventWithSubscriber eventWithSubscriber; + while ((eventWithSubscriber = (EventWithSubscriber)events.poll()) != null) { + dispatch(event, subscriber); + } + } finally { + isDispatching.remove(); + eventsToDispatch.remove(); + } + } + + + + + + + + void dispatch(Object event, EventSubscriber wrapper) + { + try + { + wrapper.handleEvent(event); + } catch (InvocationTargetException e) { + try { + subscriberExceptionHandler.handleException(e.getCause(), new SubscriberExceptionContext(this, event, wrapper.getSubscriber(), wrapper.getMethod())); + + + + } + catch (Throwable t) + { + + + Logger.getLogger(EventBus.class.getName()).log(Level.SEVERE, String.format("Exception %s thrown while handling exception: %s", new Object[] { t, e.getCause() }), t); + } + } + } + + + + + + + + + + + + @VisibleForTesting + Set> flattenHierarchy(Class concreteClass) + { + try + { + return (Set)flattenHierarchyCache.getUnchecked(concreteClass); + } catch (UncheckedExecutionException e) { + throw Throwables.propagate(e.getCause()); + } + } + + + + + + + private static final class LoggingSubscriberExceptionHandler + implements SubscriberExceptionHandler + { + private final Logger logger; + + + + + + + public LoggingSubscriberExceptionHandler(String identifier) + { + logger = Logger.getLogger(EventBus.class.getName() + "." + (String)Preconditions.checkNotNull(identifier)); + } + + + + public void handleException(Throwable exception, SubscriberExceptionContext context) + { + logger.log(Level.SEVERE, "Could not dispatch event: " + context.getSubscriber() + " to " + context.getSubscriberMethod(), exception.getCause()); + } + } + + static class EventWithSubscriber + { + final Object event; + final EventSubscriber subscriber; + + public EventWithSubscriber(Object event, EventSubscriber subscriber) + { + this.event = Preconditions.checkNotNull(event); + this.subscriber = ((EventSubscriber)Preconditions.checkNotNull(subscriber)); + } + } +} diff --git a/src/minecraft/com/google/common/eventbus/EventSubscriber.java b/src/minecraft/com/google/common/eventbus/EventSubscriber.java new file mode 100644 index 0000000..e88a2d4 --- /dev/null +++ b/src/minecraft/com/google/common/eventbus/EventSubscriber.java @@ -0,0 +1,115 @@ +package com.google.common.eventbus; + +import com.google.common.base.Preconditions; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +class EventSubscriber +{ + private final Object target; + private final Method method; + + EventSubscriber(Object target, Method method) + { + Preconditions.checkNotNull(target, "EventSubscriber target cannot be null."); + + Preconditions.checkNotNull(method, "EventSubscriber method cannot be null."); + + this.target = target; + this.method = method; + method.setAccessible(true); + } + + + + + + + + public void handleEvent(Object event) + throws InvocationTargetException + { + Preconditions.checkNotNull(event); + try { + method.invoke(target, new Object[] { event }); + } catch (IllegalArgumentException e) { + throw new Error("Method rejected target/argument: " + event, e); + } catch (IllegalAccessException e) { + throw new Error("Method became inaccessible: " + event, e); + } catch (InvocationTargetException e) { + if ((e.getCause() instanceof Error)) { + throw ((Error)e.getCause()); + } + throw e; + } + } + + public String toString() { + return "[wrapper " + method + "]"; + } + + public int hashCode() { + int PRIME = 31; + return (31 + method.hashCode()) * 31 + System.identityHashCode(target); + } + + public boolean equals(@Nullable Object obj) + { + if ((obj instanceof EventSubscriber)) { + EventSubscriber that = (EventSubscriber)obj; + + + + return (target == target) && (method.equals(method)); + } + return false; + } + + public Object getSubscriber() { + return target; + } + + public Method getMethod() { + return method; + } +} diff --git a/src/minecraft/com/google/common/eventbus/Subscribe.java b/src/minecraft/com/google/common/eventbus/Subscribe.java new file mode 100644 index 0000000..2927e79 --- /dev/null +++ b/src/minecraft/com/google/common/eventbus/Subscribe.java @@ -0,0 +1,12 @@ +package com.google.common.eventbus; + +import com.google.common.annotations.Beta; +import java.lang.annotation.Annotation; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({java.lang.annotation.ElementType.METHOD}) +@Beta +public @interface Subscribe {} diff --git a/src/minecraft/com/google/common/eventbus/SubscriberExceptionContext.java b/src/minecraft/com/google/common/eventbus/SubscriberExceptionContext.java new file mode 100644 index 0000000..91a52af --- /dev/null +++ b/src/minecraft/com/google/common/eventbus/SubscriberExceptionContext.java @@ -0,0 +1,76 @@ +package com.google.common.eventbus; + +import com.google.common.base.Preconditions; +import java.lang.reflect.Method; + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class SubscriberExceptionContext +{ + private final EventBus eventBus; + private final Object event; + private final Object subscriber; + private final Method subscriberMethod; + + SubscriberExceptionContext(EventBus eventBus, Object event, Object subscriber, Method subscriberMethod) + { + this.eventBus = ((EventBus)Preconditions.checkNotNull(eventBus)); + this.event = Preconditions.checkNotNull(event); + this.subscriber = Preconditions.checkNotNull(subscriber); + this.subscriberMethod = ((Method)Preconditions.checkNotNull(subscriberMethod)); + } + + + + + public EventBus getEventBus() + { + return eventBus; + } + + + + public Object getEvent() + { + return event; + } + + + + public Object getSubscriber() + { + return subscriber; + } + + + + public Method getSubscriberMethod() + { + return subscriberMethod; + } +} diff --git a/src/minecraft/com/google/common/eventbus/SubscriberExceptionHandler.java b/src/minecraft/com/google/common/eventbus/SubscriberExceptionHandler.java new file mode 100644 index 0000000..4769447 --- /dev/null +++ b/src/minecraft/com/google/common/eventbus/SubscriberExceptionHandler.java @@ -0,0 +1,6 @@ +package com.google.common.eventbus; + +public abstract interface SubscriberExceptionHandler +{ + public abstract void handleException(Throwable paramThrowable, SubscriberExceptionContext paramSubscriberExceptionContext); +} diff --git a/src/minecraft/com/google/common/eventbus/SubscriberFindingStrategy.java b/src/minecraft/com/google/common/eventbus/SubscriberFindingStrategy.java new file mode 100644 index 0000000..bf38670 --- /dev/null +++ b/src/minecraft/com/google/common/eventbus/SubscriberFindingStrategy.java @@ -0,0 +1,8 @@ +package com.google.common.eventbus; + +import com.google.common.collect.Multimap; + +abstract interface SubscriberFindingStrategy +{ + public abstract Multimap, EventSubscriber> findAllSubscribers(Object paramObject); +} diff --git a/src/minecraft/com/google/common/eventbus/SynchronizedEventSubscriber.java b/src/minecraft/com/google/common/eventbus/SynchronizedEventSubscriber.java new file mode 100644 index 0000000..4a6268a --- /dev/null +++ b/src/minecraft/com/google/common/eventbus/SynchronizedEventSubscriber.java @@ -0,0 +1,50 @@ +package com.google.common.eventbus; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +final class SynchronizedEventSubscriber + extends EventSubscriber +{ + public SynchronizedEventSubscriber(Object target, Method method) + { + super(target, method); + } + + public void handleEvent(Object event) + throws InvocationTargetException + { + synchronized (this) { + super.handleEvent(event); + } + } +} diff --git a/src/minecraft/com/google/common/hash/AbstractByteHasher.java b/src/minecraft/com/google/common/hash/AbstractByteHasher.java new file mode 100644 index 0000000..77eb006 --- /dev/null +++ b/src/minecraft/com/google/common/hash/AbstractByteHasher.java @@ -0,0 +1,122 @@ +package com.google.common.hash; + +import com.google.common.base.Preconditions; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +abstract class AbstractByteHasher + extends AbstractHasher +{ + private final ByteBuffer scratch = ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN); + + + AbstractByteHasher() {} + + + protected abstract void update(byte paramByte); + + + protected void update(byte[] b) + { + update(b, 0, b.length); + } + + + + protected void update(byte[] b, int off, int len) + { + for (int i = off; i < off + len; i++) { + update(b[i]); + } + } + + public Hasher putByte(byte b) + { + update(b); + return this; + } + + public Hasher putBytes(byte[] bytes) + { + Preconditions.checkNotNull(bytes); + update(bytes); + return this; + } + + public Hasher putBytes(byte[] bytes, int off, int len) + { + Preconditions.checkPositionIndexes(off, off + len, bytes.length); + update(bytes, off, len); + return this; + } + + + private Hasher update(int bytes) + { + try + { + update(scratch.array(), 0, bytes); + } finally { + scratch.clear(); + } + return this; + } + + public Hasher putShort(short s) + { + scratch.putShort(s); + return update(2); + } + + public Hasher putInt(int i) + { + scratch.putInt(i); + return update(4); + } + + public Hasher putLong(long l) + { + scratch.putLong(l); + return update(8); + } + + public Hasher putChar(char c) + { + scratch.putChar(c); + return update(2); + } + + public Hasher putObject(T instance, Funnel funnel) + { + funnel.funnel(instance, this); + return this; + } +} diff --git a/src/minecraft/com/google/common/hash/AbstractCompositeHashFunction.java b/src/minecraft/com/google/common/hash/AbstractCompositeHashFunction.java new file mode 100644 index 0000000..888f50f --- /dev/null +++ b/src/minecraft/com/google/common/hash/AbstractCompositeHashFunction.java @@ -0,0 +1,151 @@ +package com.google.common.hash; + +import com.google.common.base.Preconditions; +import java.nio.charset.Charset; + + + + + + + + + + + + + + + + + + + + + +abstract class AbstractCompositeHashFunction + extends AbstractStreamingHashFunction +{ + final HashFunction[] functions; + private static final long serialVersionUID = 0L; + + AbstractCompositeHashFunction(HashFunction... functions) + { + for (HashFunction function : functions) { + Preconditions.checkNotNull(function); + } + this.functions = functions; + } + + + + + abstract HashCode makeHash(Hasher[] paramArrayOfHasher); + + + + + public Hasher newHasher() + { + final Hasher[] hashers = new Hasher[functions.length]; + for (int i = 0; i < hashers.length; i++) { + hashers[i] = functions[i].newHasher(); + } + new Hasher() { + public Hasher putByte(byte b) { + for (Hasher hasher : hashers) { + hasher.putByte(b); + } + return this; + } + + public Hasher putBytes(byte[] bytes) { + for (Hasher hasher : hashers) { + hasher.putBytes(bytes); + } + return this; + } + + public Hasher putBytes(byte[] bytes, int off, int len) { + for (Hasher hasher : hashers) { + hasher.putBytes(bytes, off, len); + } + return this; + } + + public Hasher putShort(short s) { + for (Hasher hasher : hashers) { + hasher.putShort(s); + } + return this; + } + + public Hasher putInt(int i) { + for (Hasher hasher : hashers) { + hasher.putInt(i); + } + return this; + } + + public Hasher putLong(long l) { + for (Hasher hasher : hashers) { + hasher.putLong(l); + } + return this; + } + + public Hasher putFloat(float f) { + for (Hasher hasher : hashers) { + hasher.putFloat(f); + } + return this; + } + + public Hasher putDouble(double d) { + for (Hasher hasher : hashers) { + hasher.putDouble(d); + } + return this; + } + + public Hasher putBoolean(boolean b) { + for (Hasher hasher : hashers) { + hasher.putBoolean(b); + } + return this; + } + + public Hasher putChar(char c) { + for (Hasher hasher : hashers) { + hasher.putChar(c); + } + return this; + } + + public Hasher putUnencodedChars(CharSequence chars) { + for (Hasher hasher : hashers) { + hasher.putUnencodedChars(chars); + } + return this; + } + + public Hasher putString(CharSequence chars, Charset charset) { + for (Hasher hasher : hashers) { + hasher.putString(chars, charset); + } + return this; + } + + public Hasher putObject(T instance, Funnel funnel) { + for (Hasher hasher : hashers) { + hasher.putObject(instance, funnel); + } + return this; + } + + public HashCode hash() { + return makeHash(hashers); + } + }; + } +} diff --git a/src/minecraft/com/google/common/hash/AbstractHasher.java b/src/minecraft/com/google/common/hash/AbstractHasher.java new file mode 100644 index 0000000..afb1c03 --- /dev/null +++ b/src/minecraft/com/google/common/hash/AbstractHasher.java @@ -0,0 +1,49 @@ +package com.google.common.hash; + +import java.nio.charset.Charset; + + + + + + + + + + + + + + + + + +abstract class AbstractHasher + implements Hasher +{ + AbstractHasher() {} + + public final Hasher putBoolean(boolean b) + { + return putByte((byte)(b ? 1 : 0)); + } + + public final Hasher putDouble(double d) { + return putLong(Double.doubleToRawLongBits(d)); + } + + public final Hasher putFloat(float f) { + return putInt(Float.floatToRawIntBits(f)); + } + + public Hasher putUnencodedChars(CharSequence charSequence) { + int i = 0; for (int len = charSequence.length(); i < len; i++) { + putChar(charSequence.charAt(i)); + } + return this; + } + + public Hasher putString(CharSequence charSequence, Charset charset) { + return putBytes(charSequence.toString().getBytes(charset)); + } +} diff --git a/src/minecraft/com/google/common/hash/AbstractNonStreamingHashFunction.java b/src/minecraft/com/google/common/hash/AbstractNonStreamingHashFunction.java new file mode 100644 index 0000000..64adaee --- /dev/null +++ b/src/minecraft/com/google/common/hash/AbstractNonStreamingHashFunction.java @@ -0,0 +1,161 @@ +package com.google.common.hash; + +import com.google.common.base.Preconditions; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.charset.Charset; + + + + + + + + + + + + + + + + + + + + + +abstract class AbstractNonStreamingHashFunction + implements HashFunction +{ + AbstractNonStreamingHashFunction() {} + + public Hasher newHasher() + { + return new BufferingHasher(32); + } + + public Hasher newHasher(int expectedInputSize) + { + Preconditions.checkArgument(expectedInputSize >= 0); + return new BufferingHasher(expectedInputSize); + } + + public HashCode hashObject(T instance, Funnel funnel) { + return newHasher().putObject(instance, funnel).hash(); + } + + public HashCode hashUnencodedChars(CharSequence input) { + int len = input.length(); + Hasher hasher = newHasher(len * 2); + for (int i = 0; i < len; i++) { + hasher.putChar(input.charAt(i)); + } + return hasher.hash(); + } + + public HashCode hashString(CharSequence input, Charset charset) { + return hashBytes(input.toString().getBytes(charset)); + } + + public HashCode hashInt(int input) { + return newHasher(4).putInt(input).hash(); + } + + public HashCode hashLong(long input) { + return newHasher(8).putLong(input).hash(); + } + + public HashCode hashBytes(byte[] input) { + return hashBytes(input, 0, input.length); + } + + private final class BufferingHasher + extends AbstractHasher + { + final AbstractNonStreamingHashFunction.ExposedByteArrayOutputStream stream; + static final int BOTTOM_BYTE = 255; + + BufferingHasher(int expectedInputSize) + { + stream = new AbstractNonStreamingHashFunction.ExposedByteArrayOutputStream(expectedInputSize); + } + + public Hasher putByte(byte b) + { + stream.write(b); + return this; + } + + public Hasher putBytes(byte[] bytes) + { + try { + stream.write(bytes); + } catch (IOException e) { + throw new RuntimeException(e); + } + return this; + } + + public Hasher putBytes(byte[] bytes, int off, int len) + { + stream.write(bytes, off, len); + return this; + } + + public Hasher putShort(short s) + { + stream.write(s & 0xFF); + stream.write(s >>> 8 & 0xFF); + return this; + } + + public Hasher putInt(int i) + { + stream.write(i & 0xFF); + stream.write(i >>> 8 & 0xFF); + stream.write(i >>> 16 & 0xFF); + stream.write(i >>> 24 & 0xFF); + return this; + } + + public Hasher putLong(long l) + { + for (int i = 0; i < 64; i += 8) { + stream.write((byte)(int)(l >>> i & 0xFF)); + } + return this; + } + + public Hasher putChar(char c) + { + stream.write(c & 0xFF); + stream.write(c >>> '\b' & 0xFF); + return this; + } + + public Hasher putObject(T instance, Funnel funnel) + { + funnel.funnel(instance, this); + return this; + } + + public HashCode hash() + { + return hashBytes(stream.byteArray(), 0, stream.length()); + } + } + + private static final class ExposedByteArrayOutputStream extends ByteArrayOutputStream + { + ExposedByteArrayOutputStream(int expectedInputSize) { + super(); + } + + byte[] byteArray() { return buf; } + + int length() { + return count; + } + } +} diff --git a/src/minecraft/com/google/common/hash/AbstractStreamingHashFunction.java b/src/minecraft/com/google/common/hash/AbstractStreamingHashFunction.java new file mode 100644 index 0000000..6d1bd39 --- /dev/null +++ b/src/minecraft/com/google/common/hash/AbstractStreamingHashFunction.java @@ -0,0 +1,257 @@ +package com.google.common.hash; + +import com.google.common.base.Preconditions; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.charset.Charset; + + + + + + + + + + + + + + + + + + + + + + + +abstract class AbstractStreamingHashFunction + implements HashFunction +{ + AbstractStreamingHashFunction() {} + + public HashCode hashObject(T instance, Funnel funnel) + { + return newHasher().putObject(instance, funnel).hash(); + } + + public HashCode hashUnencodedChars(CharSequence input) { + return newHasher().putUnencodedChars(input).hash(); + } + + public HashCode hashString(CharSequence input, Charset charset) { + return newHasher().putString(input, charset).hash(); + } + + public HashCode hashInt(int input) { + return newHasher().putInt(input).hash(); + } + + public HashCode hashLong(long input) { + return newHasher().putLong(input).hash(); + } + + public HashCode hashBytes(byte[] input) { + return newHasher().putBytes(input).hash(); + } + + public HashCode hashBytes(byte[] input, int off, int len) { + return newHasher().putBytes(input, off, len).hash(); + } + + public Hasher newHasher(int expectedInputSize) { + Preconditions.checkArgument(expectedInputSize >= 0); + return newHasher(); + } + + + + + + + protected static abstract class AbstractStreamingHasher + extends AbstractHasher + { + private final ByteBuffer buffer; + + + + + private final int bufferSize; + + + + + private final int chunkSize; + + + + + + protected AbstractStreamingHasher(int chunkSize) + { + this(chunkSize, chunkSize); + } + + + + + + + + + + + protected AbstractStreamingHasher(int chunkSize, int bufferSize) + { + Preconditions.checkArgument(bufferSize % chunkSize == 0); + + + buffer = ByteBuffer.allocate(bufferSize + 7).order(ByteOrder.LITTLE_ENDIAN); + + + this.bufferSize = bufferSize; + this.chunkSize = chunkSize; + } + + + + + + + protected abstract void process(ByteBuffer paramByteBuffer); + + + + + + + protected void processRemaining(ByteBuffer bb) + { + bb.position(bb.limit()); + bb.limit(chunkSize + 7); + while (bb.position() < chunkSize) { + bb.putLong(0L); + } + bb.limit(chunkSize); + bb.flip(); + process(bb); + } + + public final Hasher putBytes(byte[] bytes) + { + return putBytes(bytes, 0, bytes.length); + } + + public final Hasher putBytes(byte[] bytes, int off, int len) + { + return putBytes(ByteBuffer.wrap(bytes, off, len).order(ByteOrder.LITTLE_ENDIAN)); + } + + private Hasher putBytes(ByteBuffer readBuffer) + { + if (readBuffer.remaining() <= buffer.remaining()) { + buffer.put(readBuffer); + munchIfFull(); + return this; + } + + + int bytesToCopy = bufferSize - buffer.position(); + for (int i = 0; i < bytesToCopy; i++) { + buffer.put(readBuffer.get()); + } + munch(); + + + while (readBuffer.remaining() >= chunkSize) { + process(readBuffer); + } + + + buffer.put(readBuffer); + return this; + } + + public final Hasher putUnencodedChars(CharSequence charSequence) + { + for (int i = 0; i < charSequence.length(); i++) { + putChar(charSequence.charAt(i)); + } + return this; + } + + public final Hasher putByte(byte b) + { + buffer.put(b); + munchIfFull(); + return this; + } + + public final Hasher putShort(short s) + { + buffer.putShort(s); + munchIfFull(); + return this; + } + + public final Hasher putChar(char c) + { + buffer.putChar(c); + munchIfFull(); + return this; + } + + public final Hasher putInt(int i) + { + buffer.putInt(i); + munchIfFull(); + return this; + } + + public final Hasher putLong(long l) + { + buffer.putLong(l); + munchIfFull(); + return this; + } + + public final Hasher putObject(T instance, Funnel funnel) + { + funnel.funnel(instance, this); + return this; + } + + public final HashCode hash() + { + munch(); + buffer.flip(); + if (buffer.remaining() > 0) { + processRemaining(buffer); + } + return makeHash(); + } + + abstract HashCode makeHash(); + + private void munchIfFull() + { + if (buffer.remaining() < 8) + { + munch(); + } + } + + private void munch() { + buffer.flip(); + while (buffer.remaining() >= chunkSize) + { + + process(buffer); + } + buffer.compact(); + } + } +} diff --git a/src/minecraft/com/google/common/hash/BloomFilter.java b/src/minecraft/com/google/common/hash/BloomFilter.java new file mode 100644 index 0000000..3e09748 --- /dev/null +++ b/src/minecraft/com/google/common/hash/BloomFilter.java @@ -0,0 +1,415 @@ +package com.google.common.hash; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import java.io.Serializable; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class BloomFilter + implements Predicate, Serializable +{ + private final BloomFilterStrategies.BitArray bits; + private final int numHashFunctions; + private final Funnel funnel; + private final Strategy strategy; + + private BloomFilter(BloomFilterStrategies.BitArray bits, int numHashFunctions, Funnel funnel, Strategy strategy) + { + Preconditions.checkArgument(numHashFunctions > 0, "numHashFunctions (%s) must be > 0", new Object[] { Integer.valueOf(numHashFunctions) }); + + Preconditions.checkArgument(numHashFunctions <= 255, "numHashFunctions (%s) must be <= 255", new Object[] { Integer.valueOf(numHashFunctions) }); + + this.bits = ((BloomFilterStrategies.BitArray)Preconditions.checkNotNull(bits)); + this.numHashFunctions = numHashFunctions; + this.funnel = ((Funnel)Preconditions.checkNotNull(funnel)); + this.strategy = ((Strategy)Preconditions.checkNotNull(strategy)); + } + + + + + + + public BloomFilter copy() + { + return new BloomFilter(bits.copy(), numHashFunctions, funnel, strategy); + } + + + + + public boolean mightContain(T object) + { + return strategy.mightContain(object, funnel, numHashFunctions, bits); + } + + + + + + @Deprecated + public boolean apply(T input) + { + return mightContain(input); + } + + + + + + + + + + + + + public boolean put(T object) + { + return strategy.put(object, funnel, numHashFunctions, bits); + } + + + + + + + + + + + + + public double expectedFpp() + { + return Math.pow(bits.bitCount() / bitSize(), numHashFunctions); + } + + + @VisibleForTesting + long bitSize() + { + return bits.bitSize(); + } + + + + + + + + + + + + + + + + public boolean isCompatible(BloomFilter that) + { + Preconditions.checkNotNull(that); + return (this != that) && (numHashFunctions == numHashFunctions) && (bitSize() == that.bitSize()) && (strategy.equals(strategy)) && (funnel.equals(funnel)); + } + + + + + + + + + + + + + + + public void putAll(BloomFilter that) + { + Preconditions.checkNotNull(that); + Preconditions.checkArgument(this != that, "Cannot combine a BloomFilter with itself."); + Preconditions.checkArgument(numHashFunctions == numHashFunctions, "BloomFilters must have the same number of hash functions (%s != %s)", new Object[] { Integer.valueOf(numHashFunctions), Integer.valueOf(numHashFunctions) }); + + + Preconditions.checkArgument(bitSize() == that.bitSize(), "BloomFilters must have the same size underlying bit arrays (%s != %s)", new Object[] { Long.valueOf(bitSize()), Long.valueOf(that.bitSize()) }); + + + Preconditions.checkArgument(strategy.equals(strategy), "BloomFilters must have equal strategies (%s != %s)", new Object[] { strategy, strategy }); + + + Preconditions.checkArgument(funnel.equals(funnel), "BloomFilters must have equal funnels (%s != %s)", new Object[] { funnel, funnel }); + + + bits.putAll(bits); + } + + public boolean equals(@Nullable Object object) + { + if (object == this) { + return true; + } + if ((object instanceof BloomFilter)) { + BloomFilter that = (BloomFilter)object; + return (numHashFunctions == numHashFunctions) && (funnel.equals(funnel)) && (bits.equals(bits)) && (strategy.equals(strategy)); + } + + + + return false; + } + + public int hashCode() + { + return Objects.hashCode(new Object[] { Integer.valueOf(numHashFunctions), funnel, strategy, bits }); + } + + private static final Strategy DEFAULT_STRATEGY = ; + + @VisibleForTesting + static final String USE_MITZ32_PROPERTY = "com.google.common.hash.BloomFilter.useMitz32"; + + @VisibleForTesting + static Strategy getDefaultStrategyFromSystemProperty() + { + return Boolean.parseBoolean(System.getProperty("com.google.common.hash.BloomFilter.useMitz32")) ? BloomFilterStrategies.MURMUR128_MITZ_32 : BloomFilterStrategies.MURMUR128_MITZ_64; + } + + + + + + + + + + + + + + + + + + + + + + + + + public static BloomFilter create(Funnel funnel, int expectedInsertions, double fpp) + { + return create(funnel, expectedInsertions, fpp, DEFAULT_STRATEGY); + } + + @VisibleForTesting + static BloomFilter create(Funnel funnel, int expectedInsertions, double fpp, Strategy strategy) + { + Preconditions.checkNotNull(funnel); + Preconditions.checkArgument(expectedInsertions >= 0, "Expected insertions (%s) must be >= 0", new Object[] { Integer.valueOf(expectedInsertions) }); + + Preconditions.checkArgument(fpp > 0.0D, "False positive probability (%s) must be > 0.0", new Object[] { Double.valueOf(fpp) }); + Preconditions.checkArgument(fpp < 1.0D, "False positive probability (%s) must be < 1.0", new Object[] { Double.valueOf(fpp) }); + Preconditions.checkNotNull(strategy); + + if (expectedInsertions == 0) { + expectedInsertions = 1; + } + + + + + + + long numBits = optimalNumOfBits(expectedInsertions, fpp); + int numHashFunctions = optimalNumOfHashFunctions(expectedInsertions, numBits); + try { + return new BloomFilter(new BloomFilterStrategies.BitArray(numBits), numHashFunctions, funnel, strategy); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("Could not create BloomFilter of " + numBits + " bits", e); + } + } + + + + + + + + + + + + + + + + + public static BloomFilter create(Funnel funnel, int expectedInsertions) + { + return create(funnel, expectedInsertions, 0.03D); + } + + + + + + + + + + + + + + + + + + + + + + + + @VisibleForTesting + static int optimalNumOfHashFunctions(long n, long m) + { + return Math.max(1, (int)Math.round(m / n * Math.log(2.0D))); + } + + + + + + + + + + @VisibleForTesting + static long optimalNumOfBits(long n, double p) + { + if (p == 0.0D) { + p = Double.MIN_VALUE; + } + return (-n * Math.log(p) / (Math.log(2.0D) * Math.log(2.0D))); + } + + + private Object writeReplace() { return new SerialForm(this); } + + private static class SerialForm implements Serializable { + final long[] data; + final int numHashFunctions; + final Funnel funnel; + final BloomFilter.Strategy strategy; + private static final long serialVersionUID = 1L; + + SerialForm(BloomFilter bf) { + data = bits.data; + numHashFunctions = numHashFunctions; + funnel = funnel; + strategy = strategy; + } + + Object readResolve() { return new BloomFilter(new BloomFilterStrategies.BitArray(data), numHashFunctions, funnel, strategy, null); } + } + + static abstract interface Strategy + extends Serializable + { + public abstract boolean put(T paramT, Funnel paramFunnel, int paramInt, BloomFilterStrategies.BitArray paramBitArray); + + public abstract boolean mightContain(T paramT, Funnel paramFunnel, int paramInt, BloomFilterStrategies.BitArray paramBitArray); + + public abstract int ordinal(); + } +} diff --git a/src/minecraft/com/google/common/hash/BloomFilterStrategies.java b/src/minecraft/com/google/common/hash/BloomFilterStrategies.java new file mode 100644 index 0000000..b981b19 --- /dev/null +++ b/src/minecraft/com/google/common/hash/BloomFilterStrategies.java @@ -0,0 +1,210 @@ +package com.google.common.hash; + +import com.google.common.base.Preconditions; +import com.google.common.math.LongMath; +import com.google.common.primitives.Ints; +import com.google.common.primitives.Longs; +import java.math.RoundingMode; +import java.util.Arrays; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + enum BloomFilterStrategies + implements BloomFilter.Strategy +{ + MURMUR128_MITZ_32, + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MURMUR128_MITZ_64; + + + + + + + + + + + + + private BloomFilterStrategies() {} + + + + + + + + + + + + + static final class BitArray + { + final long[] data; + + + + + + + + + + + + long bitCount; + + + + + + + + + + + + + BitArray(long bits) + { + this(new long[Ints.checkedCast(LongMath.divide(bits, 64L, RoundingMode.CEILING))]); + } + + BitArray(long[] data) + { + Preconditions.checkArgument(data.length > 0, "data length is zero!"); + this.data = data; + long bitCount = 0L; + for (long value : data) { + bitCount += Long.bitCount(value); + } + this.bitCount = bitCount; + } + + boolean set(long index) + { + if (!get(index)) { + data[((int)(index >>> 6))] |= 1L << (int)index; + bitCount += 1L; + return true; + } + return false; + } + + boolean get(long index) { + return (data[((int)(index >>> 6))] & 1L << (int)index) != 0L; + } + + long bitSize() + { + return data.length * 64L; + } + + long bitCount() + { + return bitCount; + } + + BitArray copy() { + return new BitArray((long[])data.clone()); + } + + void putAll(BitArray array) + { + Preconditions.checkArgument(data.length == data.length, "BitArrays must be of equal length (%s != %s)", new Object[] { Integer.valueOf(data.length), Integer.valueOf(data.length) }); + + bitCount = 0L; + for (int i = 0; i < data.length; i++) { + data[i] |= data[i]; + bitCount += Long.bitCount(data[i]); + } + } + + public boolean equals(Object o) { + if ((o instanceof BitArray)) { + BitArray bitArray = (BitArray)o; + return Arrays.equals(data, data); + } + return false; + } + + public int hashCode() { + return Arrays.hashCode(data); + } + } +} diff --git a/src/minecraft/com/google/common/hash/ChecksumHashFunction.java b/src/minecraft/com/google/common/hash/ChecksumHashFunction.java new file mode 100644 index 0000000..021bf1a --- /dev/null +++ b/src/minecraft/com/google/common/hash/ChecksumHashFunction.java @@ -0,0 +1,93 @@ +package com.google.common.hash; + +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import java.io.Serializable; +import java.util.zip.Checksum; + + + + + + + + + + + + + + + + + + + +final class ChecksumHashFunction + extends AbstractStreamingHashFunction + implements Serializable +{ + private final Supplier checksumSupplier; + private final int bits; + private final String toString; + private static final long serialVersionUID = 0L; + + ChecksumHashFunction(Supplier checksumSupplier, int bits, String toString) + { + this.checksumSupplier = ((Supplier)Preconditions.checkNotNull(checksumSupplier)); + Preconditions.checkArgument((bits == 32) || (bits == 64), "bits (%s) must be either 32 or 64", new Object[] { Integer.valueOf(bits) }); + this.bits = bits; + this.toString = ((String)Preconditions.checkNotNull(toString)); + } + + public int bits() + { + return bits; + } + + public Hasher newHasher() + { + return new ChecksumHasher((Checksum)checksumSupplier.get(), null); + } + + public String toString() + { + return toString; + } + + + private final class ChecksumHasher + extends AbstractByteHasher + { + private final Checksum checksum; + + private ChecksumHasher(Checksum checksum) + { + this.checksum = ((Checksum)Preconditions.checkNotNull(checksum)); + } + + protected void update(byte b) + { + checksum.update(b); + } + + protected void update(byte[] bytes, int off, int len) + { + checksum.update(bytes, off, len); + } + + public HashCode hash() + { + long value = checksum.getValue(); + if (bits == 32) + { + + + + + return HashCode.fromInt((int)value); + } + return HashCode.fromLong(value); + } + } +} diff --git a/src/minecraft/com/google/common/hash/Funnel.java b/src/minecraft/com/google/common/hash/Funnel.java new file mode 100644 index 0000000..6f6b49e --- /dev/null +++ b/src/minecraft/com/google/common/hash/Funnel.java @@ -0,0 +1,11 @@ +package com.google.common.hash; + +import com.google.common.annotations.Beta; +import java.io.Serializable; + +@Beta +public abstract interface Funnel + extends Serializable +{ + public abstract void funnel(T paramT, PrimitiveSink paramPrimitiveSink); +} diff --git a/src/minecraft/com/google/common/hash/Funnels.java b/src/minecraft/com/google/common/hash/Funnels.java new file mode 100644 index 0000000..3993808 --- /dev/null +++ b/src/minecraft/com/google/common/hash/Funnels.java @@ -0,0 +1,252 @@ +package com.google.common.hash; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import java.io.OutputStream; +import java.io.Serializable; +import java.nio.charset.Charset; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class Funnels +{ + private Funnels() {} + + public static Funnel byteArrayFunnel() + { + return ByteArrayFunnel.INSTANCE; + } + + private static enum ByteArrayFunnel implements Funnel { + INSTANCE; + + private ByteArrayFunnel() {} + public void funnel(byte[] from, PrimitiveSink into) { into.putBytes(from); } + + public String toString() + { + return "Funnels.byteArrayFunnel()"; + } + } + + + + + + + + public static Funnel unencodedCharsFunnel() + { + return UnencodedCharsFunnel.INSTANCE; + } + + private static enum UnencodedCharsFunnel implements Funnel { + INSTANCE; + + private UnencodedCharsFunnel() {} + public void funnel(CharSequence from, PrimitiveSink into) { into.putUnencodedChars(from); } + + public String toString() + { + return "Funnels.unencodedCharsFunnel()"; + } + } + + + + + + + public static Funnel stringFunnel(Charset charset) + { + return new StringCharsetFunnel(charset); + } + + private static class StringCharsetFunnel implements Funnel, Serializable { + private final Charset charset; + + StringCharsetFunnel(Charset charset) { + this.charset = ((Charset)Preconditions.checkNotNull(charset)); + } + + public void funnel(CharSequence from, PrimitiveSink into) { + into.putString(from, charset); + } + + public String toString() { + return "Funnels.stringFunnel(" + charset.name() + ")"; + } + + public boolean equals(@Nullable Object o) { + if ((o instanceof StringCharsetFunnel)) { + StringCharsetFunnel funnel = (StringCharsetFunnel)o; + return charset.equals(charset); + } + return false; + } + + public int hashCode() { + return StringCharsetFunnel.class.hashCode() ^ charset.hashCode(); + } + + Object writeReplace() { + return new SerializedForm(charset); + } + + private static class SerializedForm implements Serializable { + private final String charsetCanonicalName; + private static final long serialVersionUID = 0L; + + SerializedForm(Charset charset) { charsetCanonicalName = charset.name(); } + + private Object readResolve() + { + return Funnels.stringFunnel(Charset.forName(charsetCanonicalName)); + } + } + } + + + + + + + + public static Funnel integerFunnel() + { + return IntegerFunnel.INSTANCE; + } + + private static enum IntegerFunnel implements Funnel { + INSTANCE; + + private IntegerFunnel() {} + public void funnel(Integer from, PrimitiveSink into) { into.putInt(from.intValue()); } + + public String toString() + { + return "Funnels.integerFunnel()"; + } + } + + + + + + + public static Funnel> sequentialFunnel(Funnel elementFunnel) + { + return new SequentialFunnel(elementFunnel); + } + + private static class SequentialFunnel implements Funnel>, Serializable { + private final Funnel elementFunnel; + + SequentialFunnel(Funnel elementFunnel) { + this.elementFunnel = ((Funnel)Preconditions.checkNotNull(elementFunnel)); + } + + public void funnel(Iterable from, PrimitiveSink into) { + for (E e : from) { + elementFunnel.funnel(e, into); + } + } + + public String toString() { + return "Funnels.sequentialFunnel(" + elementFunnel + ")"; + } + + public boolean equals(@Nullable Object o) { + if ((o instanceof SequentialFunnel)) { + SequentialFunnel funnel = (SequentialFunnel)o; + return elementFunnel.equals(elementFunnel); + } + return false; + } + + public int hashCode() { + return SequentialFunnel.class.hashCode() ^ elementFunnel.hashCode(); + } + } + + + + + + public static Funnel longFunnel() + { + return LongFunnel.INSTANCE; + } + + private static enum LongFunnel implements Funnel { + INSTANCE; + + private LongFunnel() {} + public void funnel(Long from, PrimitiveSink into) { into.putLong(from.longValue()); } + + public String toString() + { + return "Funnels.longFunnel()"; + } + } + + + + + + + + + + + public static OutputStream asOutputStream(PrimitiveSink sink) + { + return new SinkAsStream(sink); + } + + private static class SinkAsStream extends OutputStream { + final PrimitiveSink sink; + + SinkAsStream(PrimitiveSink sink) { this.sink = ((PrimitiveSink)Preconditions.checkNotNull(sink)); } + + public void write(int b) + { + sink.putByte((byte)b); + } + + public void write(byte[] bytes) { + sink.putBytes(bytes); + } + + public void write(byte[] bytes, int off, int len) { + sink.putBytes(bytes, off, len); + } + + public String toString() { + return "Funnels.asOutputStream(" + sink + ")"; + } + } +} diff --git a/src/minecraft/com/google/common/hash/HashCode.java b/src/minecraft/com/google/common/hash/HashCode.java new file mode 100644 index 0000000..2eaa1ad --- /dev/null +++ b/src/minecraft/com/google/common/hash/HashCode.java @@ -0,0 +1,387 @@ +package com.google.common.hash; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.primitives.Ints; +import com.google.common.primitives.UnsignedInts; +import java.io.Serializable; +import java.security.MessageDigest; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public abstract class HashCode +{ + HashCode() {} + + public abstract int bits(); + + public abstract int asInt(); + + public abstract long asLong(); + + public abstract long padToLong(); + + public abstract byte[] asBytes(); + + public int writeBytesTo(byte[] dest, int offset, int maxLength) + { + maxLength = Ints.min(new int[] { maxLength, bits() / 8 }); + Preconditions.checkPositionIndexes(offset, offset + maxLength, dest.length); + writeBytesToImpl(dest, offset, maxLength); + return maxLength; + } + + + + abstract void writeBytesToImpl(byte[] paramArrayOfByte, int paramInt1, int paramInt2); + + + + byte[] getBytesInternal() + { + return asBytes(); + } + + + + + + + public static HashCode fromInt(int hash) + { + return new IntHashCode(hash); + } + + private static final class IntHashCode extends HashCode implements Serializable { + final int hash; + private static final long serialVersionUID = 0L; + + IntHashCode(int hash) { this.hash = hash; } + + + public int bits() + { + return 32; + } + + public byte[] asBytes() + { + return new byte[] { (byte)hash, (byte)(hash >> 8), (byte)(hash >> 16), (byte)(hash >> 24) }; + } + + + + + + public int asInt() + { + return hash; + } + + public long asLong() + { + throw new IllegalStateException("this HashCode only has 32 bits; cannot create a long"); + } + + public long padToLong() + { + return UnsignedInts.toLong(hash); + } + + void writeBytesToImpl(byte[] dest, int offset, int maxLength) + { + for (int i = 0; i < maxLength; i++) { + dest[(offset + i)] = ((byte)(hash >> i * 8)); + } + } + } + + + + + + + + + public static HashCode fromLong(long hash) + { + return new LongHashCode(hash); + } + + private static final class LongHashCode extends HashCode implements Serializable { + final long hash; + private static final long serialVersionUID = 0L; + + LongHashCode(long hash) { this.hash = hash; } + + + public int bits() + { + return 64; + } + + public byte[] asBytes() + { + return new byte[] { (byte)(int)hash, (byte)(int)(hash >> 8), (byte)(int)(hash >> 16), (byte)(int)(hash >> 24), (byte)(int)(hash >> 32), (byte)(int)(hash >> 40), (byte)(int)(hash >> 48), (byte)(int)(hash >> 56) }; + } + + + + + + + + + + public int asInt() + { + return (int)hash; + } + + public long asLong() + { + return hash; + } + + public long padToLong() + { + return hash; + } + + void writeBytesToImpl(byte[] dest, int offset, int maxLength) + { + for (int i = 0; i < maxLength; i++) { + dest[(offset + i)] = ((byte)(int)(hash >> i * 8)); + } + } + } + + + + + + + + + public static HashCode fromBytes(byte[] bytes) + { + Preconditions.checkArgument(bytes.length >= 1, "A HashCode must contain at least 1 byte."); + return fromBytesNoCopy((byte[])bytes.clone()); + } + + + + + static HashCode fromBytesNoCopy(byte[] bytes) + { + return new BytesHashCode(bytes); + } + + private static final class BytesHashCode extends HashCode implements Serializable { + final byte[] bytes; + private static final long serialVersionUID = 0L; + + BytesHashCode(byte[] bytes) { this.bytes = ((byte[])Preconditions.checkNotNull(bytes)); } + + + public int bits() + { + return bytes.length * 8; + } + + public byte[] asBytes() + { + return (byte[])bytes.clone(); + } + + public int asInt() + { + Preconditions.checkState(bytes.length >= 4, "HashCode#asInt() requires >= 4 bytes (it only has %s bytes).", new Object[] { Integer.valueOf(bytes.length) }); + + return bytes[0] & 0xFF | (bytes[1] & 0xFF) << 8 | (bytes[2] & 0xFF) << 16 | (bytes[3] & 0xFF) << 24; + } + + + + + public long asLong() + { + Preconditions.checkState(bytes.length >= 8, "HashCode#asLong() requires >= 8 bytes (it only has %s bytes).", new Object[] { Integer.valueOf(bytes.length) }); + + return padToLong(); + } + + public long padToLong() + { + long retVal = bytes[0] & 0xFF; + for (int i = 1; i < Math.min(bytes.length, 8); i++) { + retVal |= (bytes[i] & 0xFF) << i * 8; + } + return retVal; + } + + void writeBytesToImpl(byte[] dest, int offset, int maxLength) + { + System.arraycopy(bytes, 0, dest, offset, maxLength); + } + + byte[] getBytesInternal() + { + return bytes; + } + } + + + + + + + + + + + + + public static HashCode fromString(String string) + { + Preconditions.checkArgument(string.length() >= 2, "input string (%s) must have at least 2 characters", new Object[] { string }); + + Preconditions.checkArgument(string.length() % 2 == 0, "input string (%s) must have an even number of characters", new Object[] { string }); + + + byte[] bytes = new byte[string.length() / 2]; + for (int i = 0; i < string.length(); i += 2) { + int ch1 = decode(string.charAt(i)) << 4; + int ch2 = decode(string.charAt(i + 1)); + bytes[(i / 2)] = ((byte)(ch1 + ch2)); + } + return fromBytesNoCopy(bytes); + } + + private static int decode(char ch) { + if ((ch >= '0') && (ch <= '9')) { + return ch - '0'; + } + if ((ch >= 'a') && (ch <= 'f')) { + return ch - 'a' + 10; + } + throw new IllegalArgumentException("Illegal hexadecimal character: " + ch); + } + + public final boolean equals(@Nullable Object object) + { + if ((object instanceof HashCode)) { + HashCode that = (HashCode)object; + + + return MessageDigest.isEqual(asBytes(), that.asBytes()); + } + return false; + } + + + + + + + + + public final int hashCode() + { + if (bits() >= 32) { + return asInt(); + } + + byte[] bytes = asBytes(); + int val = bytes[0] & 0xFF; + for (int i = 1; i < bytes.length; i++) { + val |= (bytes[i] & 0xFF) << i * 8; + } + return val; + } + + + + + + + + + + + + + public final String toString() + { + byte[] bytes = asBytes(); + StringBuilder sb = new StringBuilder(2 * bytes.length); + for (byte b : bytes) { + sb.append(hexDigits[(b >> 4 & 0xF)]).append(hexDigits[(b & 0xF)]); + } + return sb.toString(); + } + + private static final char[] hexDigits = "0123456789abcdef".toCharArray(); +} diff --git a/src/minecraft/com/google/common/hash/HashFunction.java b/src/minecraft/com/google/common/hash/HashFunction.java new file mode 100644 index 0000000..ddbcd39 --- /dev/null +++ b/src/minecraft/com/google/common/hash/HashFunction.java @@ -0,0 +1,28 @@ +package com.google.common.hash; + +import com.google.common.annotations.Beta; +import java.nio.charset.Charset; + +@Beta +public abstract interface HashFunction +{ + public abstract Hasher newHasher(); + + public abstract Hasher newHasher(int paramInt); + + public abstract HashCode hashInt(int paramInt); + + public abstract HashCode hashLong(long paramLong); + + public abstract HashCode hashBytes(byte[] paramArrayOfByte); + + public abstract HashCode hashBytes(byte[] paramArrayOfByte, int paramInt1, int paramInt2); + + public abstract HashCode hashUnencodedChars(CharSequence paramCharSequence); + + public abstract HashCode hashString(CharSequence paramCharSequence, Charset paramCharset); + + public abstract HashCode hashObject(T paramT, Funnel paramFunnel); + + public abstract int bits(); +} diff --git a/src/minecraft/com/google/common/hash/Hasher.java b/src/minecraft/com/google/common/hash/Hasher.java new file mode 100644 index 0000000..23d791f --- /dev/null +++ b/src/minecraft/com/google/common/hash/Hasher.java @@ -0,0 +1,37 @@ +package com.google.common.hash; + +import com.google.common.annotations.Beta; +import java.nio.charset.Charset; + +@Beta +public abstract interface Hasher + extends PrimitiveSink +{ + public abstract Hasher putByte(byte paramByte); + + public abstract Hasher putBytes(byte[] paramArrayOfByte); + + public abstract Hasher putBytes(byte[] paramArrayOfByte, int paramInt1, int paramInt2); + + public abstract Hasher putShort(short paramShort); + + public abstract Hasher putInt(int paramInt); + + public abstract Hasher putLong(long paramLong); + + public abstract Hasher putFloat(float paramFloat); + + public abstract Hasher putDouble(double paramDouble); + + public abstract Hasher putBoolean(boolean paramBoolean); + + public abstract Hasher putChar(char paramChar); + + public abstract Hasher putUnencodedChars(CharSequence paramCharSequence); + + public abstract Hasher putString(CharSequence paramCharSequence, Charset paramCharset); + + public abstract Hasher putObject(T paramT, Funnel paramFunnel); + + public abstract HashCode hash(); +} diff --git a/src/minecraft/com/google/common/hash/Hashing.java b/src/minecraft/com/google/common/hash/Hashing.java new file mode 100644 index 0000000..dc4d3ac --- /dev/null +++ b/src/minecraft/com/google/common/hash/Hashing.java @@ -0,0 +1,471 @@ +package com.google.common.hash; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import java.util.Iterator; +import java.util.zip.Adler32; +import java.util.zip.CRC32; +import java.util.zip.Checksum; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class Hashing +{ + public static HashFunction goodFastHash(int minimumBits) + { + int bits = checkPositiveAndMakeMultipleOf32(minimumBits); + + if (bits == 32) { + return Murmur3_32Holder.GOOD_FAST_HASH_FUNCTION_32; + } + if (bits <= 128) { + return Murmur3_128Holder.GOOD_FAST_HASH_FUNCTION_128; + } + + + int hashFunctionsNeeded = (bits + 127) / 128; + HashFunction[] hashFunctions = new HashFunction[hashFunctionsNeeded]; + hashFunctions[0] = Murmur3_128Holder.GOOD_FAST_HASH_FUNCTION_128; + int seed = GOOD_FAST_HASH_SEED; + for (int i = 1; i < hashFunctionsNeeded; i++) { + seed += 1500450271; + hashFunctions[i] = murmur3_128(seed); + } + return new ConcatenatedHashFunction(hashFunctions); + } + + + + + + private static final int GOOD_FAST_HASH_SEED = (int)System.currentTimeMillis(); + + + + + + + + + public static HashFunction murmur3_32(int seed) + { + return new Murmur3_32HashFunction(seed); + } + + + + + + + + + public static HashFunction murmur3_32() + { + return Murmur3_32Holder.MURMUR3_32; + } + + private static class Murmur3_32Holder { + static final HashFunction MURMUR3_32 = new Murmur3_32HashFunction(0); + + + static final HashFunction GOOD_FAST_HASH_FUNCTION_32 = Hashing.murmur3_32(Hashing.GOOD_FAST_HASH_SEED); + + + + + private Murmur3_32Holder() {} + } + + + + public static HashFunction murmur3_128(int seed) + { + return new Murmur3_128HashFunction(seed); + } + + + + + + + + + public static HashFunction murmur3_128() + { + return Murmur3_128Holder.MURMUR3_128; + } + + private static class Murmur3_128Holder { + static final HashFunction MURMUR3_128 = new Murmur3_128HashFunction(0); + + + static final HashFunction GOOD_FAST_HASH_FUNCTION_128 = Hashing.murmur3_128(Hashing.GOOD_FAST_HASH_SEED); + + + + private Murmur3_128Holder() {} + } + + + + public static HashFunction sipHash24() + { + return SipHash24Holder.SIP_HASH_24; + } + + private static class SipHash24Holder { + static final HashFunction SIP_HASH_24 = new SipHashFunction(2, 4, 506097522914230528L, 1084818905618843912L); + + + + + private SipHash24Holder() {} + } + + + + public static HashFunction sipHash24(long k0, long k1) + { + return new SipHashFunction(2, 4, k0, k1); + } + + + + + public static HashFunction md5() + { + return Md5Holder.MD5; + } + + private static class Md5Holder { + static final HashFunction MD5 = new MessageDigestHashFunction("MD5", "Hashing.md5()"); + + + private Md5Holder() {} + } + + public static HashFunction sha1() + { + return Sha1Holder.SHA_1; + } + + private static class Sha1Holder { + static final HashFunction SHA_1 = new MessageDigestHashFunction("SHA-1", "Hashing.sha1()"); + + + private Sha1Holder() {} + } + + + public static HashFunction sha256() + { + return Sha256Holder.SHA_256; + } + + private static class Sha256Holder { + static final HashFunction SHA_256 = new MessageDigestHashFunction("SHA-256", "Hashing.sha256()"); + + + private Sha256Holder() {} + } + + + public static HashFunction sha512() + { + return Sha512Holder.SHA_512; + } + + private static class Sha512Holder { + static final HashFunction SHA_512 = new MessageDigestHashFunction("SHA-512", "Hashing.sha512()"); + + + + + + private Sha512Holder() {} + } + + + + + public static HashFunction crc32() + { + return Crc32Holder.CRC_32; + } + + private static class Crc32Holder { + static final HashFunction CRC_32 = Hashing.checksumHashFunction(Hashing.ChecksumType.CRC_32, "Hashing.crc32()"); + + + + + + private Crc32Holder() {} + } + + + + + public static HashFunction adler32() + { + return Adler32Holder.ADLER_32; + } + + private static class Adler32Holder { + static final HashFunction ADLER_32 = Hashing.checksumHashFunction(Hashing.ChecksumType.ADLER_32, "Hashing.adler32()"); + + private Adler32Holder() {} + } + + private static HashFunction checksumHashFunction(ChecksumType type, String toString) { return new ChecksumHashFunction(type, bits, toString); } + + static abstract enum ChecksumType implements Supplier + { + CRC_32(32), + + + + + + ADLER_32(32); + + + + private final int bits; + + + + private ChecksumType(int bits) + { + this.bits = bits; + } + + + + + + + + + public abstract Checksum get(); + } + + + + + + + + public static int consistentHash(HashCode hashCode, int buckets) + { + return consistentHash(hashCode.padToLong(), buckets); + } + + + + + + + + + + + + + + public static int consistentHash(long input, int buckets) + { + Preconditions.checkArgument(buckets > 0, "buckets must be positive: %s", new Object[] { Integer.valueOf(buckets) }); + LinearCongruentialGenerator generator = new LinearCongruentialGenerator(input); + int candidate = 0; + + + for (;;) + { + int next = (int)((candidate + 1) / generator.nextDouble()); + if ((next < 0) || (next >= buckets)) break; + candidate = next; + } + return candidate; + } + + + + + + + + + + + + + public static HashCode combineOrdered(Iterable hashCodes) + { + Iterator iterator = hashCodes.iterator(); + Preconditions.checkArgument(iterator.hasNext(), "Must be at least 1 hash code to combine."); + int bits = ((HashCode)iterator.next()).bits(); + byte[] resultBytes = new byte[bits / 8]; + for (HashCode hashCode : hashCodes) { + byte[] nextBytes = hashCode.asBytes(); + Preconditions.checkArgument(nextBytes.length == resultBytes.length, "All hashcodes must have the same bit length."); + + for (int i = 0; i < nextBytes.length; i++) { + resultBytes[i] = ((byte)(resultBytes[i] * 37 ^ nextBytes[i])); + } + } + return HashCode.fromBytesNoCopy(resultBytes); + } + + + + + + + + + + + public static HashCode combineUnordered(Iterable hashCodes) + { + Iterator iterator = hashCodes.iterator(); + Preconditions.checkArgument(iterator.hasNext(), "Must be at least 1 hash code to combine."); + byte[] resultBytes = new byte[((HashCode)iterator.next()).bits() / 8]; + for (HashCode hashCode : hashCodes) { + byte[] nextBytes = hashCode.asBytes(); + Preconditions.checkArgument(nextBytes.length == resultBytes.length, "All hashcodes must have the same bit length."); + + for (int i = 0; i < nextBytes.length; tmp102_100++) { + int tmp102_100 = i; byte[] tmp102_99 = resultBytes;tmp102_99[tmp102_100] = ((byte)(tmp102_99[tmp102_100] + nextBytes[tmp102_100])); + } + } + return HashCode.fromBytesNoCopy(resultBytes); + } + + + + static int checkPositiveAndMakeMultipleOf32(int bits) + { + Preconditions.checkArgument(bits > 0, "Number of bits must be positive"); + return bits + 31 & 0xFFFFFFE0; + } + + private Hashing() {} + + @VisibleForTesting + static final class ConcatenatedHashFunction extends AbstractCompositeHashFunction { + private final int bits; + + ConcatenatedHashFunction(HashFunction... functions) { super(); + int bitSum = 0; + for (HashFunction function : functions) { + bitSum += function.bits(); + } + bits = bitSum; + } + + HashCode makeHash(Hasher[] hashers) + { + byte[] bytes = new byte[bits / 8]; + int i = 0; + for (Hasher hasher : hashers) { + HashCode newHash = hasher.hash(); + i += newHash.writeBytesTo(bytes, i, newHash.bits() / 8); + } + return HashCode.fromBytesNoCopy(bytes); + } + + public int bits() + { + return bits; + } + + public boolean equals(@Nullable Object object) + { + if ((object instanceof ConcatenatedHashFunction)) { + ConcatenatedHashFunction other = (ConcatenatedHashFunction)object; + if ((bits != bits) || (functions.length != functions.length)) { + return false; + } + for (int i = 0; i < functions.length; i++) { + if (!functions[i].equals(functions[i])) { + return false; + } + } + return true; + } + return false; + } + + public int hashCode() + { + int hash = bits; + for (HashFunction function : functions) { + hash ^= function.hashCode(); + } + return hash; + } + } + + + private static final class LinearCongruentialGenerator + { + private long state; + + + public LinearCongruentialGenerator(long seed) + { + state = seed; + } + + public double nextDouble() { + state = (2862933555777941757L * state + 1L); + return ((int)(state >>> 33) + 1) / 2.147483648E9D; + } + } +} diff --git a/src/minecraft/com/google/common/hash/HashingInputStream.java b/src/minecraft/com/google/common/hash/HashingInputStream.java new file mode 100644 index 0000000..30a3f53 --- /dev/null +++ b/src/minecraft/com/google/common/hash/HashingInputStream.java @@ -0,0 +1,103 @@ +package com.google.common.hash; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class HashingInputStream + extends FilterInputStream +{ + private final Hasher hasher; + + public HashingInputStream(HashFunction hashFunction, InputStream in) + { + super((InputStream)Preconditions.checkNotNull(in)); + hasher = ((Hasher)Preconditions.checkNotNull(hashFunction.newHasher())); + } + + + + + public int read() + throws IOException + { + int b = in.read(); + if (b != -1) { + hasher.putByte((byte)b); + } + return b; + } + + + + + public int read(byte[] bytes, int off, int len) + throws IOException + { + int numOfBytesRead = in.read(bytes, off, len); + if (numOfBytesRead != -1) { + hasher.putBytes(bytes, off, numOfBytesRead); + } + return numOfBytesRead; + } + + + + + + public boolean markSupported() + { + return false; + } + + + + + + public void mark(int readlimit) {} + + + + + public void reset() + throws IOException + { + throw new IOException("reset not supported"); + } + + + + + public HashCode hash() + { + return hasher.hash(); + } +} diff --git a/src/minecraft/com/google/common/hash/HashingOutputStream.java b/src/minecraft/com/google/common/hash/HashingOutputStream.java new file mode 100644 index 0000000..f6abcc1 --- /dev/null +++ b/src/minecraft/com/google/common/hash/HashingOutputStream.java @@ -0,0 +1,74 @@ +package com.google.common.hash; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class HashingOutputStream + extends FilterOutputStream +{ + private final Hasher hasher; + + public HashingOutputStream(HashFunction hashFunction, OutputStream out) + { + super((OutputStream)Preconditions.checkNotNull(out)); + hasher = ((Hasher)Preconditions.checkNotNull(hashFunction.newHasher())); + } + + public void write(int b) throws IOException { + hasher.putByte((byte)b); + out.write(b); + } + + public void write(byte[] bytes, int off, int len) throws IOException { + hasher.putBytes(bytes, off, len); + out.write(bytes, off, len); + } + + + + + public HashCode hash() + { + return hasher.hash(); + } + + + public void close() + throws IOException + { + out.close(); + } +} diff --git a/src/minecraft/com/google/common/hash/MessageDigestHashFunction.java b/src/minecraft/com/google/common/hash/MessageDigestHashFunction.java new file mode 100644 index 0000000..20f822b --- /dev/null +++ b/src/minecraft/com/google/common/hash/MessageDigestHashFunction.java @@ -0,0 +1,157 @@ +package com.google.common.hash; + +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; + + + + + + + + + + + + + + + + + + + + + +final class MessageDigestHashFunction + extends AbstractStreamingHashFunction + implements Serializable +{ + private final MessageDigest prototype; + private final int bytes; + private final boolean supportsClone; + private final String toString; + + MessageDigestHashFunction(String algorithmName, String toString) + { + prototype = getMessageDigest(algorithmName); + bytes = prototype.getDigestLength(); + this.toString = ((String)Preconditions.checkNotNull(toString)); + supportsClone = supportsClone(); + } + + MessageDigestHashFunction(String algorithmName, int bytes, String toString) { + this.toString = ((String)Preconditions.checkNotNull(toString)); + prototype = getMessageDigest(algorithmName); + int maxLength = prototype.getDigestLength(); + Preconditions.checkArgument((bytes >= 4) && (bytes <= maxLength), "bytes (%s) must be >= 4 and < %s", new Object[] { Integer.valueOf(bytes), Integer.valueOf(maxLength) }); + + this.bytes = bytes; + supportsClone = supportsClone(); + } + + private boolean supportsClone() { + try { + prototype.clone(); + return true; + } catch (CloneNotSupportedException e) {} + return false; + } + + public int bits() + { + return bytes * 8; + } + + public String toString() { + return toString; + } + + private static MessageDigest getMessageDigest(String algorithmName) { + try { + return MessageDigest.getInstance(algorithmName); + } catch (NoSuchAlgorithmException e) { + throw new AssertionError(e); + } + } + + public Hasher newHasher() { + if (supportsClone) { + try { + return new MessageDigestHasher((MessageDigest)prototype.clone(), bytes, null); + } + catch (CloneNotSupportedException e) {} + } + + return new MessageDigestHasher(getMessageDigest(prototype.getAlgorithm()), bytes, null); + } + + private static final class SerializedForm implements Serializable { + private final String algorithmName; + private final int bytes; + private final String toString; + private static final long serialVersionUID = 0L; + + private SerializedForm(String algorithmName, int bytes, String toString) { this.algorithmName = algorithmName; + this.bytes = bytes; + this.toString = toString; + } + + private Object readResolve() { + return new MessageDigestHashFunction(algorithmName, bytes, toString); + } + } + + + Object writeReplace() + { + return new SerializedForm(prototype.getAlgorithm(), bytes, toString, null); + } + + + private static final class MessageDigestHasher + extends AbstractByteHasher + { + private final MessageDigest digest; + private final int bytes; + private boolean done; + + private MessageDigestHasher(MessageDigest digest, int bytes) + { + this.digest = digest; + this.bytes = bytes; + } + + protected void update(byte b) + { + checkNotDone(); + digest.update(b); + } + + protected void update(byte[] b) + { + checkNotDone(); + digest.update(b); + } + + protected void update(byte[] b, int off, int len) + { + checkNotDone(); + digest.update(b, off, len); + } + + private void checkNotDone() { + Preconditions.checkState(!done, "Cannot re-use a Hasher after calling hash() on it"); + } + + public HashCode hash() + { + checkNotDone(); + done = true; + return bytes == digest.getDigestLength() ? HashCode.fromBytesNoCopy(digest.digest()) : HashCode.fromBytesNoCopy(Arrays.copyOf(digest.digest(), bytes)); + } + } +} diff --git a/src/minecraft/com/google/common/hash/Murmur3_128HashFunction.java b/src/minecraft/com/google/common/hash/Murmur3_128HashFunction.java new file mode 100644 index 0000000..1d2013c --- /dev/null +++ b/src/minecraft/com/google/common/hash/Murmur3_128HashFunction.java @@ -0,0 +1,202 @@ +package com.google.common.hash; + +import com.google.common.primitives.UnsignedBytes; +import java.io.Serializable; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +final class Murmur3_128HashFunction + extends AbstractStreamingHashFunction + implements Serializable +{ + private final int seed; + private static final long serialVersionUID = 0L; + + Murmur3_128HashFunction(int seed) + { + this.seed = seed; + } + + public int bits() { + return 128; + } + + public Hasher newHasher() { + return new Murmur3_128Hasher(seed); + } + + public String toString() + { + return "Hashing.murmur3_128(" + seed + ")"; + } + + public boolean equals(@Nullable Object object) + { + if ((object instanceof Murmur3_128HashFunction)) { + Murmur3_128HashFunction other = (Murmur3_128HashFunction)object; + return seed == seed; + } + return false; + } + + public int hashCode() + { + return getClass().hashCode() ^ seed; + } + + private static final class Murmur3_128Hasher extends AbstractStreamingHashFunction.AbstractStreamingHasher { + private static final int CHUNK_SIZE = 16; + private static final long C1 = -8663945395140668459L; + private static final long C2 = 5545529020109919103L; + private long h1; + private long h2; + private int length; + + Murmur3_128Hasher(int seed) { + super(); + h1 = seed; + h2 = seed; + length = 0; + } + + protected void process(ByteBuffer bb) { + long k1 = bb.getLong(); + long k2 = bb.getLong(); + bmix64(k1, k2); + length += 16; + } + + private void bmix64(long k1, long k2) { + h1 ^= mixK1(k1); + + h1 = Long.rotateLeft(h1, 27); + h1 += h2; + h1 = (h1 * 5L + 1390208809L); + + h2 ^= mixK2(k2); + + h2 = Long.rotateLeft(h2, 31); + h2 += h1; + h2 = (h2 * 5L + 944331445L); + } + + protected void processRemaining(ByteBuffer bb) { + long k1 = 0L; + long k2 = 0L; + length += bb.remaining(); + switch (bb.remaining()) { + case 15: + k2 ^= UnsignedBytes.toInt(bb.get(14)) << 48; + case 14: + k2 ^= UnsignedBytes.toInt(bb.get(13)) << 40; + case 13: + k2 ^= UnsignedBytes.toInt(bb.get(12)) << 32; + case 12: + k2 ^= UnsignedBytes.toInt(bb.get(11)) << 24; + case 11: + k2 ^= UnsignedBytes.toInt(bb.get(10)) << 16; + case 10: + k2 ^= UnsignedBytes.toInt(bb.get(9)) << 8; + case 9: + k2 ^= UnsignedBytes.toInt(bb.get(8)); + case 8: + k1 ^= bb.getLong(); + break; + case 7: + k1 ^= UnsignedBytes.toInt(bb.get(6)) << 48; + case 6: + k1 ^= UnsignedBytes.toInt(bb.get(5)) << 40; + case 5: + k1 ^= UnsignedBytes.toInt(bb.get(4)) << 32; + case 4: + k1 ^= UnsignedBytes.toInt(bb.get(3)) << 24; + case 3: + k1 ^= UnsignedBytes.toInt(bb.get(2)) << 16; + case 2: + k1 ^= UnsignedBytes.toInt(bb.get(1)) << 8; + case 1: + k1 ^= UnsignedBytes.toInt(bb.get(0)); + break; + default: + throw new AssertionError("Should never get here."); + } + h1 ^= mixK1(k1); + h2 ^= mixK2(k2); + } + + public HashCode makeHash() { + h1 ^= length; + h2 ^= length; + + h1 += h2; + h2 += h1; + + h1 = fmix64(h1); + h2 = fmix64(h2); + + h1 += h2; + h2 += h1; + + return HashCode.fromBytesNoCopy(ByteBuffer.wrap(new byte[16]).order(ByteOrder.LITTLE_ENDIAN).putLong(h1).putLong(h2).array()); + } + + + + + + private static long fmix64(long k) + { + k ^= k >>> 33; + k *= -49064778989728563L; + k ^= k >>> 33; + k *= -4265267296055464877L; + k ^= k >>> 33; + return k; + } + + private static long mixK1(long k1) { + k1 *= -8663945395140668459L; + k1 = Long.rotateLeft(k1, 31); + k1 *= 5545529020109919103L; + return k1; + } + + private static long mixK2(long k2) { + k2 *= 5545529020109919103L; + k2 = Long.rotateLeft(k2, 33); + k2 *= -8663945395140668459L; + return k2; + } + } +} diff --git a/src/minecraft/com/google/common/hash/Murmur3_32HashFunction.java b/src/minecraft/com/google/common/hash/Murmur3_32HashFunction.java new file mode 100644 index 0000000..5bbfc8f --- /dev/null +++ b/src/minecraft/com/google/common/hash/Murmur3_32HashFunction.java @@ -0,0 +1,180 @@ +package com.google.common.hash; + +import com.google.common.primitives.UnsignedBytes; +import java.io.Serializable; +import java.nio.ByteBuffer; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +final class Murmur3_32HashFunction + extends AbstractStreamingHashFunction + implements Serializable +{ + private static final int C1 = -862048943; + private static final int C2 = 461845907; + private final int seed; + private static final long serialVersionUID = 0L; + + Murmur3_32HashFunction(int seed) + { + this.seed = seed; + } + + public int bits() { + return 32; + } + + public Hasher newHasher() { + return new Murmur3_32Hasher(seed); + } + + public String toString() + { + return "Hashing.murmur3_32(" + seed + ")"; + } + + public boolean equals(@Nullable Object object) + { + if ((object instanceof Murmur3_32HashFunction)) { + Murmur3_32HashFunction other = (Murmur3_32HashFunction)object; + return seed == seed; + } + return false; + } + + public int hashCode() + { + return getClass().hashCode() ^ seed; + } + + public HashCode hashInt(int input) { + int k1 = mixK1(input); + int h1 = mixH1(seed, k1); + + return fmix(h1, 4); + } + + public HashCode hashLong(long input) { + int low = (int)input; + int high = (int)(input >>> 32); + + int k1 = mixK1(low); + int h1 = mixH1(seed, k1); + + k1 = mixK1(high); + h1 = mixH1(h1, k1); + + return fmix(h1, 8); + } + + public HashCode hashUnencodedChars(CharSequence input) + { + int h1 = seed; + + + for (int i = 1; i < input.length(); i += 2) { + int k1 = input.charAt(i - 1) | input.charAt(i) << '\020'; + k1 = mixK1(k1); + h1 = mixH1(h1, k1); + } + + + if ((input.length() & 0x1) == 1) { + int k1 = input.charAt(input.length() - 1); + k1 = mixK1(k1); + h1 ^= k1; + } + + return fmix(h1, 2 * input.length()); + } + + private static int mixK1(int k1) { + k1 *= -862048943; + k1 = Integer.rotateLeft(k1, 15); + k1 *= 461845907; + return k1; + } + + private static int mixH1(int h1, int k1) { + h1 ^= k1; + h1 = Integer.rotateLeft(h1, 13); + h1 = h1 * 5 + -430675100; + return h1; + } + + private static HashCode fmix(int h1, int length) + { + h1 ^= length; + h1 ^= h1 >>> 16; + h1 *= -2048144789; + h1 ^= h1 >>> 13; + h1 *= -1028477387; + h1 ^= h1 >>> 16; + return HashCode.fromInt(h1); + } + + private static final class Murmur3_32Hasher extends AbstractStreamingHashFunction.AbstractStreamingHasher { + private static final int CHUNK_SIZE = 4; + private int h1; + private int length; + + Murmur3_32Hasher(int seed) { + super(); + h1 = seed; + length = 0; + } + + protected void process(ByteBuffer bb) { + int k1 = Murmur3_32HashFunction.mixK1(bb.getInt()); + h1 = Murmur3_32HashFunction.mixH1(h1, k1); + length += 4; + } + + protected void processRemaining(ByteBuffer bb) { + length += bb.remaining(); + int k1 = 0; + for (int i = 0; bb.hasRemaining(); i += 8) { + k1 ^= UnsignedBytes.toInt(bb.get()) << i; + } + h1 ^= Murmur3_32HashFunction.mixK1(k1); + } + + public HashCode makeHash() { + return Murmur3_32HashFunction.fmix(h1, length); + } + } +} diff --git a/src/minecraft/com/google/common/hash/PrimitiveSink.java b/src/minecraft/com/google/common/hash/PrimitiveSink.java new file mode 100644 index 0000000..87e500e --- /dev/null +++ b/src/minecraft/com/google/common/hash/PrimitiveSink.java @@ -0,0 +1,32 @@ +package com.google.common.hash; + +import com.google.common.annotations.Beta; +import java.nio.charset.Charset; + +@Beta +public abstract interface PrimitiveSink +{ + public abstract PrimitiveSink putByte(byte paramByte); + + public abstract PrimitiveSink putBytes(byte[] paramArrayOfByte); + + public abstract PrimitiveSink putBytes(byte[] paramArrayOfByte, int paramInt1, int paramInt2); + + public abstract PrimitiveSink putShort(short paramShort); + + public abstract PrimitiveSink putInt(int paramInt); + + public abstract PrimitiveSink putLong(long paramLong); + + public abstract PrimitiveSink putFloat(float paramFloat); + + public abstract PrimitiveSink putDouble(double paramDouble); + + public abstract PrimitiveSink putBoolean(boolean paramBoolean); + + public abstract PrimitiveSink putChar(char paramChar); + + public abstract PrimitiveSink putUnencodedChars(CharSequence paramCharSequence); + + public abstract PrimitiveSink putString(CharSequence paramCharSequence, Charset paramCharset); +} diff --git a/src/minecraft/com/google/common/hash/SipHashFunction.java b/src/minecraft/com/google/common/hash/SipHashFunction.java new file mode 100644 index 0000000..9c59dac --- /dev/null +++ b/src/minecraft/com/google/common/hash/SipHashFunction.java @@ -0,0 +1,176 @@ +package com.google.common.hash; + +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.nio.ByteBuffer; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +final class SipHashFunction + extends AbstractStreamingHashFunction + implements Serializable +{ + private final int c; + private final int d; + private final long k0; + private final long k1; + private static final long serialVersionUID = 0L; + + SipHashFunction(int c, int d, long k0, long k1) + { + Preconditions.checkArgument(c > 0, "The number of SipRound iterations (c=%s) during Compression must be positive.", new Object[] { Integer.valueOf(c) }); + + Preconditions.checkArgument(d > 0, "The number of SipRound iterations (d=%s) during Finalization must be positive.", new Object[] { Integer.valueOf(d) }); + + this.c = c; + this.d = d; + this.k0 = k0; + this.k1 = k1; + } + + public int bits() { + return 64; + } + + public Hasher newHasher() { + return new SipHasher(c, d, k0, k1); + } + + + public String toString() + { + return "Hashing.sipHash" + c + "" + d + "(" + k0 + ", " + k1 + ")"; + } + + public boolean equals(@Nullable Object object) + { + if ((object instanceof SipHashFunction)) { + SipHashFunction other = (SipHashFunction)object; + return (c == c) && (d == d) && (k0 == k0) && (k1 == k1); + } + + + + return false; + } + + public int hashCode() + { + return (int)(getClass().hashCode() ^ c ^ d ^ k0 ^ k1); + } + + + + private static final class SipHasher + extends AbstractStreamingHashFunction.AbstractStreamingHasher + { + private static final int CHUNK_SIZE = 8; + + + private final int c; + + private final int d; + + private long v0 = 8317987319222330741L; + private long v1 = 7237128888997146477L; + private long v2 = 7816392313619706465L; + private long v3 = 8387220255154660723L; + + + private long b = 0L; + + + + private long finalM = 0L; + + SipHasher(int c, int d, long k0, long k1) { + super(); + this.c = c; + this.d = d; + v0 ^= k0; + v1 ^= k1; + v2 ^= k0; + v3 ^= k1; + } + + protected void process(ByteBuffer buffer) { + b += 8L; + processM(buffer.getLong()); + } + + protected void processRemaining(ByteBuffer buffer) { + b += buffer.remaining(); + for (int i = 0; buffer.hasRemaining(); i += 8) { + finalM ^= (buffer.get() & 0xFF) << i; + } + } + + public HashCode makeHash() + { + finalM ^= b << 56; + processM(finalM); + + + v2 ^= 0xFF; + sipRound(d); + return HashCode.fromLong(v0 ^ v1 ^ v2 ^ v3); + } + + private void processM(long m) { + v3 ^= m; + sipRound(c); + v0 ^= m; + } + + private void sipRound(int iterations) { + for (int i = 0; i < iterations; i++) { + v0 += v1; + v2 += v3; + v1 = Long.rotateLeft(v1, 13); + v3 = Long.rotateLeft(v3, 16); + v1 ^= v0; + v3 ^= v2; + v0 = Long.rotateLeft(v0, 32); + v2 += v1; + v0 += v3; + v1 = Long.rotateLeft(v1, 17); + v3 = Long.rotateLeft(v3, 21); + v1 ^= v2; + v3 ^= v0; + v2 = Long.rotateLeft(v2, 32); + } + } + } +} diff --git a/src/minecraft/com/google/common/hash/package-info.java b/src/minecraft/com/google/common/hash/package-info.java new file mode 100644 index 0000000..8073fad --- /dev/null +++ b/src/minecraft/com/google/common/hash/package-info.java @@ -0,0 +1,6 @@ +package com.google.common.hash; + +import javax.annotation.ParametersAreNonnullByDefault; + +@ParametersAreNonnullByDefault +abstract interface package-info {} diff --git a/src/minecraft/com/google/common/html/HtmlEscapers.java b/src/minecraft/com/google/common/html/HtmlEscapers.java new file mode 100644 index 0000000..1c44cc8 --- /dev/null +++ b/src/minecraft/com/google/common/html/HtmlEscapers.java @@ -0,0 +1,68 @@ +package com.google.common.html; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.escape.Escaper; +import com.google.common.escape.Escapers; +import com.google.common.escape.Escapers.Builder; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +public final class HtmlEscapers +{ + public static Escaper htmlEscaper() + { + return HTML_ESCAPER; + } + + + + + private static final Escaper HTML_ESCAPER = Escapers.builder().addEscape('"', """).addEscape('\'', "'").addEscape('&', "&").addEscape('<', "<").addEscape('>', ">").build(); + + private HtmlEscapers() {} +} diff --git a/src/minecraft/com/google/common/html/package-info.java b/src/minecraft/com/google/common/html/package-info.java new file mode 100644 index 0000000..47a47eb --- /dev/null +++ b/src/minecraft/com/google/common/html/package-info.java @@ -0,0 +1,6 @@ +package com.google.common.html; + +import javax.annotation.ParametersAreNonnullByDefault; + +@ParametersAreNonnullByDefault +abstract interface package-info {} diff --git a/src/minecraft/com/google/common/io/AppendableWriter.java b/src/minecraft/com/google/common/io/AppendableWriter.java new file mode 100644 index 0000000..102d3da --- /dev/null +++ b/src/minecraft/com/google/common/io/AppendableWriter.java @@ -0,0 +1,121 @@ +package com.google.common.io; + +import com.google.common.base.Preconditions; +import java.io.Closeable; +import java.io.Flushable; +import java.io.IOException; +import java.io.Writer; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +class AppendableWriter + extends Writer +{ + private final Appendable target; + private boolean closed; + + AppendableWriter(Appendable target) + { + this.target = ((Appendable)Preconditions.checkNotNull(target)); + } + + + + + public void write(char[] cbuf, int off, int len) + throws IOException + { + checkNotClosed(); + + + target.append(new String(cbuf, off, len)); + } + + public void flush() throws IOException { + checkNotClosed(); + if ((target instanceof Flushable)) { + ((Flushable)target).flush(); + } + } + + public void close() throws IOException { + closed = true; + if ((target instanceof Closeable)) { + ((Closeable)target).close(); + } + } + + + + + public void write(int c) + throws IOException + { + checkNotClosed(); + target.append((char)c); + } + + public void write(@Nullable String str) throws IOException { + checkNotClosed(); + target.append(str); + } + + public void write(@Nullable String str, int off, int len) throws IOException { + checkNotClosed(); + + target.append(str, off, off + len); + } + + public Writer append(char c) throws IOException { + checkNotClosed(); + target.append(c); + return this; + } + + public Writer append(@Nullable CharSequence charSeq) throws IOException { + checkNotClosed(); + target.append(charSeq); + return this; + } + + public Writer append(@Nullable CharSequence charSeq, int start, int end) throws IOException + { + checkNotClosed(); + target.append(charSeq, start, end); + return this; + } + + private void checkNotClosed() throws IOException { + if (closed) { + throw new IOException("Cannot write to a closed writer."); + } + } +} diff --git a/src/minecraft/com/google/common/io/BaseEncoding.java b/src/minecraft/com/google/common/io/BaseEncoding.java new file mode 100644 index 0000000..3759772 --- /dev/null +++ b/src/minecraft/com/google/common/io/BaseEncoding.java @@ -0,0 +1,880 @@ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Ascii; +import com.google.common.base.CharMatcher; +import com.google.common.base.Preconditions; +import com.google.common.math.IntMath; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.math.RoundingMode; +import java.util.Arrays; +import javax.annotation.CheckReturnValue; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible(emulated=true) +public abstract class BaseEncoding +{ + BaseEncoding() {} + + public static final class DecodingException + extends IOException + { + DecodingException(String message) + { + super(); + } + + DecodingException(Throwable cause) { + super(); + } + } + + + + public String encode(byte[] bytes) + { + return encode((byte[])Preconditions.checkNotNull(bytes), 0, bytes.length); + } + + + + + public final String encode(byte[] bytes, int off, int len) + { + Preconditions.checkNotNull(bytes); + Preconditions.checkPositionIndexes(off, off + len, bytes.length); + GwtWorkarounds.CharOutput result = GwtWorkarounds.stringBuilderOutput(maxEncodedSize(len)); + GwtWorkarounds.ByteOutput byteOutput = encodingStream(result); + try { + for (int i = 0; i < len; i++) { + byteOutput.write(bytes[(off + i)]); + } + byteOutput.close(); + } catch (IOException impossible) { + throw new AssertionError("impossible"); + } + return result.toString(); + } + + + + + + @GwtIncompatible("Writer,OutputStream") + public final OutputStream encodingStream(Writer writer) + { + return GwtWorkarounds.asOutputStream(encodingStream(GwtWorkarounds.asCharOutput(writer))); + } + + + + @GwtIncompatible("ByteSink,CharSink") + public final ByteSink encodingSink(final CharSink encodedSink) + { + Preconditions.checkNotNull(encodedSink); + new ByteSink() + { + public OutputStream openStream() throws IOException { + return encodingStream(encodedSink.openStream()); + } + }; + } + + + private static byte[] extract(byte[] result, int length) + { + if (length == result.length) { + return result; + } + byte[] trunc = new byte[length]; + System.arraycopy(result, 0, trunc, 0, length); + return trunc; + } + + + + + + + + public final byte[] decode(CharSequence chars) + { + try + { + return decodeChecked(chars); + } catch (DecodingException badInput) { + throw new IllegalArgumentException(badInput); + } + } + + + + + + + final byte[] decodeChecked(CharSequence chars) + throws BaseEncoding.DecodingException + { + chars = padding().trimTrailingFrom(chars); + GwtWorkarounds.ByteInput decodedInput = decodingStream(GwtWorkarounds.asCharInput(chars)); + byte[] tmp = new byte[maxDecodedSize(chars.length())]; + int index = 0; + try { + for (int i = decodedInput.read(); i != -1; i = decodedInput.read()) { + tmp[(index++)] = ((byte)i); + } + } catch (DecodingException badInput) { + throw badInput; + } catch (IOException impossible) { + throw new AssertionError(impossible); + } + return extract(tmp, index); + } + + + + + + @GwtIncompatible("Reader,InputStream") + public final InputStream decodingStream(Reader reader) + { + return GwtWorkarounds.asInputStream(decodingStream(GwtWorkarounds.asCharInput(reader))); + } + + + + + @GwtIncompatible("ByteSource,CharSource") + public final ByteSource decodingSource(final CharSource encodedSource) + { + Preconditions.checkNotNull(encodedSource); + new ByteSource() + { + public InputStream openStream() throws IOException { + return decodingStream(encodedSource.openStream()); + } + }; + } + + + + + + + + + + + abstract int maxEncodedSize(int paramInt); + + + + + + + + + + + abstract GwtWorkarounds.ByteOutput encodingStream(GwtWorkarounds.CharOutput paramCharOutput); + + + + + + + + + + + abstract int maxDecodedSize(int paramInt); + + + + + + + + + + + abstract GwtWorkarounds.ByteInput decodingStream(GwtWorkarounds.CharInput paramCharInput); + + + + + + + + + + + abstract CharMatcher padding(); + + + + + + + + + + + private static final BaseEncoding BASE64 = new StandardBaseEncoding("base64()", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", Character.valueOf('=')); + + @CheckReturnValue + public abstract BaseEncoding omitPadding(); + + @CheckReturnValue + public abstract BaseEncoding withPadChar(char paramChar); + + @CheckReturnValue + public abstract BaseEncoding withSeparator(String paramString, int paramInt); + + @CheckReturnValue + public abstract BaseEncoding upperCase(); + + @CheckReturnValue + public abstract BaseEncoding lowerCase(); + + public static BaseEncoding base64() { return BASE64; } + + + private static final BaseEncoding BASE64_URL = new StandardBaseEncoding("base64Url()", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", Character.valueOf('=')); + + + + + + + + + + + + + + + + public static BaseEncoding base64Url() + { + return BASE64_URL; + } + + private static final BaseEncoding BASE32 = new StandardBaseEncoding("base32()", "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", Character.valueOf('=')); + + + + + + + + + + + + + + + public static BaseEncoding base32() + { + return BASE32; + } + + private static final BaseEncoding BASE32_HEX = new StandardBaseEncoding("base32Hex()", "0123456789ABCDEFGHIJKLMNOPQRSTUV", Character.valueOf('=')); + + + + + + + + + + + + + + public static BaseEncoding base32Hex() + { + return BASE32_HEX; + } + + private static final BaseEncoding BASE16 = new StandardBaseEncoding("base16()", "0123456789ABCDEF", null); + + + + + + + + + + + + + + + + public static BaseEncoding base16() + { + return BASE16; + } + + private static final class Alphabet extends CharMatcher + { + private final String name; + private final char[] chars; + final int mask; + final int bitsPerChar; + final int charsPerChunk; + final int bytesPerChunk; + private final byte[] decodabet; + private final boolean[] validPadding; + + Alphabet(String name, char[] chars) { + this.name = ((String)Preconditions.checkNotNull(name)); + this.chars = ((char[])Preconditions.checkNotNull(chars)); + try { + bitsPerChar = IntMath.log2(chars.length, RoundingMode.UNNECESSARY); + } catch (ArithmeticException e) { + throw new IllegalArgumentException("Illegal alphabet length " + chars.length, e); + } + + + + + + int gcd = Math.min(8, Integer.lowestOneBit(bitsPerChar)); + charsPerChunk = (8 / gcd); + bytesPerChunk = (bitsPerChar / gcd); + + mask = (chars.length - 1); + + byte[] decodabet = new byte['€']; + Arrays.fill(decodabet, (byte)-1); + for (int i = 0; i < chars.length; i++) { + char c = chars[i]; + Preconditions.checkArgument(CharMatcher.ASCII.matches(c), "Non-ASCII character: %s", new Object[] { Character.valueOf(c) }); + Preconditions.checkArgument(decodabet[c] == -1, "Duplicate character: %s", new Object[] { Character.valueOf(c) }); + decodabet[c] = ((byte)i); + } + this.decodabet = decodabet; + + boolean[] validPadding = new boolean[charsPerChunk]; + for (int i = 0; i < bytesPerChunk; i++) { + validPadding[IntMath.divide(i * 8, bitsPerChar, RoundingMode.CEILING)] = true; + } + this.validPadding = validPadding; + } + + char encode(int bits) { + return chars[bits]; + } + + boolean isValidPaddingStartPosition(int index) { + return validPadding[(index % charsPerChunk)]; + } + + int decode(char ch) throws IOException { + if ((ch > '') || (decodabet[ch] == -1)) { + throw new BaseEncoding.DecodingException("Unrecognized character: " + ch); + } + return decodabet[ch]; + } + + private boolean hasLowerCase() { + for (char c : chars) { + if (Ascii.isLowerCase(c)) { + return true; + } + } + return false; + } + + private boolean hasUpperCase() { + for (char c : chars) { + if (Ascii.isUpperCase(c)) { + return true; + } + } + return false; + } + + Alphabet upperCase() { + if (!hasLowerCase()) { + return this; + } + Preconditions.checkState(!hasUpperCase(), "Cannot call upperCase() on a mixed-case alphabet"); + char[] upperCased = new char[chars.length]; + for (int i = 0; i < chars.length; i++) { + upperCased[i] = Ascii.toUpperCase(chars[i]); + } + return new Alphabet(name + ".upperCase()", upperCased); + } + + Alphabet lowerCase() + { + if (!hasUpperCase()) { + return this; + } + Preconditions.checkState(!hasLowerCase(), "Cannot call lowerCase() on a mixed-case alphabet"); + char[] lowerCased = new char[chars.length]; + for (int i = 0; i < chars.length; i++) { + lowerCased[i] = Ascii.toLowerCase(chars[i]); + } + return new Alphabet(name + ".lowerCase()", lowerCased); + } + + + public boolean matches(char c) + { + return (CharMatcher.ASCII.matches(c)) && (decodabet[c] != -1); + } + + public String toString() + { + return name; + } + } + + static final class StandardBaseEncoding extends BaseEncoding { + private final BaseEncoding.Alphabet alphabet; + @Nullable + private final Character paddingChar; + private transient BaseEncoding upperCase; + private transient BaseEncoding lowerCase; + + StandardBaseEncoding(String name, String alphabetChars, @Nullable Character paddingChar) { + this(new BaseEncoding.Alphabet(name, alphabetChars.toCharArray()), paddingChar); + } + + StandardBaseEncoding(BaseEncoding.Alphabet alphabet, @Nullable Character paddingChar) { + this.alphabet = ((BaseEncoding.Alphabet)Preconditions.checkNotNull(alphabet)); + Preconditions.checkArgument((paddingChar == null) || (!alphabet.matches(paddingChar.charValue())), "Padding character %s was already in alphabet", new Object[] { paddingChar }); + + this.paddingChar = paddingChar; + } + + CharMatcher padding() + { + return paddingChar == null ? CharMatcher.NONE : CharMatcher.is(paddingChar.charValue()); + } + + int maxEncodedSize(int bytes) + { + return alphabet.charsPerChunk * IntMath.divide(bytes, alphabet.bytesPerChunk, RoundingMode.CEILING); + } + + GwtWorkarounds.ByteOutput encodingStream(final GwtWorkarounds.CharOutput out) + { + Preconditions.checkNotNull(out); + new GwtWorkarounds.ByteOutput() { + int bitBuffer = 0; + int bitBufferLength = 0; + int writtenChars = 0; + + public void write(byte b) throws IOException + { + bitBuffer <<= 8; + bitBuffer |= b & 0xFF; + bitBufferLength += 8; + while (bitBufferLength >= alphabet.bitsPerChar) { + int charIndex = bitBuffer >> bitBufferLength - alphabet.bitsPerChar & alphabet.mask; + + out.write(alphabet.encode(charIndex)); + writtenChars += 1; + bitBufferLength -= alphabet.bitsPerChar; + } + } + + public void flush() throws IOException + { + out.flush(); + } + + public void close() throws IOException + { + if (bitBufferLength > 0) { + int charIndex = bitBuffer << alphabet.bitsPerChar - bitBufferLength & alphabet.mask; + + out.write(alphabet.encode(charIndex)); + writtenChars += 1; + if (paddingChar != null) { + while (writtenChars % alphabet.charsPerChunk != 0) { + out.write(paddingChar.charValue()); + writtenChars += 1; + } + } + } + out.close(); + } + }; + } + + int maxDecodedSize(int chars) + { + return (int)((alphabet.bitsPerChar * chars + 7L) / 8L); + } + + GwtWorkarounds.ByteInput decodingStream(final GwtWorkarounds.CharInput reader) + { + Preconditions.checkNotNull(reader); + new GwtWorkarounds.ByteInput() { + int bitBuffer = 0; + int bitBufferLength = 0; + int readChars = 0; + boolean hitPadding = false; + final CharMatcher paddingMatcher = padding(); + + public int read() throws IOException + { + for (;;) { + int readChar = reader.read(); + if (readChar == -1) { + if ((!hitPadding) && (!alphabet.isValidPaddingStartPosition(readChars))) { + throw new BaseEncoding.DecodingException("Invalid input length " + readChars); + } + return -1; + } + readChars += 1; + char ch = (char)readChar; + if (paddingMatcher.matches(ch)) { + if ((!hitPadding) && ((readChars == 1) || (!alphabet.isValidPaddingStartPosition(readChars - 1)))) + { + throw new BaseEncoding.DecodingException("Padding cannot start at index " + readChars); + } + hitPadding = true; + } else { if (hitPadding) { + throw new BaseEncoding.DecodingException("Expected padding character but found '" + ch + "' at index " + readChars); + } + + bitBuffer <<= alphabet.bitsPerChar; + bitBuffer |= alphabet.decode(ch); + bitBufferLength += alphabet.bitsPerChar; + + if (bitBufferLength >= 8) { + bitBufferLength -= 8; + return bitBuffer >> bitBufferLength & 0xFF; + } + } + } + } + + public void close() throws IOException + { + reader.close(); + } + }; + } + + public BaseEncoding omitPadding() + { + return paddingChar == null ? this : new StandardBaseEncoding(alphabet, null); + } + + public BaseEncoding withPadChar(char padChar) + { + if ((8 % alphabet.bitsPerChar == 0) || ((paddingChar != null) && (paddingChar.charValue() == padChar))) + { + return this; + } + return new StandardBaseEncoding(alphabet, Character.valueOf(padChar)); + } + + + public BaseEncoding withSeparator(String separator, int afterEveryChars) + { + Preconditions.checkNotNull(separator); + Preconditions.checkArgument(padding().or(alphabet).matchesNoneOf(separator), "Separator cannot contain alphabet or padding characters"); + + return new BaseEncoding.SeparatedBaseEncoding(this, separator, afterEveryChars); + } + + + + + public BaseEncoding upperCase() + { + BaseEncoding result = upperCase; + if (result == null) { + BaseEncoding.Alphabet upper = alphabet.upperCase(); + result = this.upperCase = upper == alphabet ? this : new StandardBaseEncoding(upper, paddingChar); + } + + return result; + } + + public BaseEncoding lowerCase() + { + BaseEncoding result = lowerCase; + if (result == null) { + BaseEncoding.Alphabet lower = alphabet.lowerCase(); + result = this.lowerCase = lower == alphabet ? this : new StandardBaseEncoding(lower, paddingChar); + } + + return result; + } + + public String toString() + { + StringBuilder builder = new StringBuilder("BaseEncoding."); + builder.append(alphabet.toString()); + if (8 % alphabet.bitsPerChar != 0) { + if (paddingChar == null) { + builder.append(".omitPadding()"); + } else { + builder.append(".withPadChar(").append(paddingChar).append(')'); + } + } + return builder.toString(); + } + } + + static GwtWorkarounds.CharInput ignoringInput(GwtWorkarounds.CharInput delegate, final CharMatcher toIgnore) { + Preconditions.checkNotNull(delegate); + Preconditions.checkNotNull(toIgnore); + new GwtWorkarounds.CharInput() + { + public int read() throws IOException { + int readChar; + do { + readChar = val$delegate.read(); + } while ((readChar != -1) && (toIgnore.matches((char)readChar))); + return readChar; + } + + public void close() throws IOException + { + val$delegate.close(); + } + }; + } + + static GwtWorkarounds.CharOutput separatingOutput(final GwtWorkarounds.CharOutput delegate, final String separator, int afterEveryChars) + { + Preconditions.checkNotNull(delegate); + Preconditions.checkNotNull(separator); + Preconditions.checkArgument(afterEveryChars > 0); + new GwtWorkarounds.CharOutput() { + int charsUntilSeparator = val$afterEveryChars; + + public void write(char c) throws IOException + { + if (charsUntilSeparator == 0) { + for (int i = 0; i < separator.length(); i++) { + delegate.write(separator.charAt(i)); + } + charsUntilSeparator = val$afterEveryChars; + } + delegate.write(c); + charsUntilSeparator -= 1; + } + + public void flush() throws IOException + { + delegate.flush(); + } + + public void close() throws IOException + { + delegate.close(); + } + }; + } + + static final class SeparatedBaseEncoding extends BaseEncoding { + private final BaseEncoding delegate; + private final String separator; + private final int afterEveryChars; + private final CharMatcher separatorChars; + + SeparatedBaseEncoding(BaseEncoding delegate, String separator, int afterEveryChars) { + this.delegate = ((BaseEncoding)Preconditions.checkNotNull(delegate)); + this.separator = ((String)Preconditions.checkNotNull(separator)); + this.afterEveryChars = afterEveryChars; + Preconditions.checkArgument(afterEveryChars > 0, "Cannot add a separator after every %s chars", new Object[] { Integer.valueOf(afterEveryChars) }); + + separatorChars = CharMatcher.anyOf(separator).precomputed(); + } + + CharMatcher padding() + { + return delegate.padding(); + } + + int maxEncodedSize(int bytes) + { + int unseparatedSize = delegate.maxEncodedSize(bytes); + return unseparatedSize + separator.length() * IntMath.divide(Math.max(0, unseparatedSize - 1), afterEveryChars, RoundingMode.FLOOR); + } + + + GwtWorkarounds.ByteOutput encodingStream(GwtWorkarounds.CharOutput output) + { + return delegate.encodingStream(separatingOutput(output, separator, afterEveryChars)); + } + + int maxDecodedSize(int chars) + { + return delegate.maxDecodedSize(chars); + } + + GwtWorkarounds.ByteInput decodingStream(GwtWorkarounds.CharInput input) + { + return delegate.decodingStream(ignoringInput(input, separatorChars)); + } + + public BaseEncoding omitPadding() + { + return delegate.omitPadding().withSeparator(separator, afterEveryChars); + } + + public BaseEncoding withPadChar(char padChar) + { + return delegate.withPadChar(padChar).withSeparator(separator, afterEveryChars); + } + + public BaseEncoding withSeparator(String separator, int afterEveryChars) + { + throw new UnsupportedOperationException("Already have a separator"); + } + + public BaseEncoding upperCase() + { + return delegate.upperCase().withSeparator(separator, afterEveryChars); + } + + public BaseEncoding lowerCase() + { + return delegate.lowerCase().withSeparator(separator, afterEveryChars); + } + + public String toString() + { + return delegate.toString() + ".withSeparator(\"" + separator + "\", " + afterEveryChars + ")"; + } + } +} diff --git a/src/minecraft/com/google/common/io/ByteArrayDataInput.java b/src/minecraft/com/google/common/io/ByteArrayDataInput.java new file mode 100644 index 0000000..0a39655 --- /dev/null +++ b/src/minecraft/com/google/common/io/ByteArrayDataInput.java @@ -0,0 +1,37 @@ +package com.google.common.io; + +import java.io.DataInput; + +public abstract interface ByteArrayDataInput + extends DataInput +{ + public abstract void readFully(byte[] paramArrayOfByte); + + public abstract void readFully(byte[] paramArrayOfByte, int paramInt1, int paramInt2); + + public abstract int skipBytes(int paramInt); + + public abstract boolean readBoolean(); + + public abstract byte readByte(); + + public abstract int readUnsignedByte(); + + public abstract short readShort(); + + public abstract int readUnsignedShort(); + + public abstract char readChar(); + + public abstract int readInt(); + + public abstract long readLong(); + + public abstract float readFloat(); + + public abstract double readDouble(); + + public abstract String readLine(); + + public abstract String readUTF(); +} diff --git a/src/minecraft/com/google/common/io/ByteArrayDataOutput.java b/src/minecraft/com/google/common/io/ByteArrayDataOutput.java new file mode 100644 index 0000000..ca55076 --- /dev/null +++ b/src/minecraft/com/google/common/io/ByteArrayDataOutput.java @@ -0,0 +1,38 @@ +package com.google.common.io; + +import java.io.DataOutput; + +public abstract interface ByteArrayDataOutput + extends DataOutput +{ + public abstract void write(int paramInt); + + public abstract void write(byte[] paramArrayOfByte); + + public abstract void write(byte[] paramArrayOfByte, int paramInt1, int paramInt2); + + public abstract void writeBoolean(boolean paramBoolean); + + public abstract void writeByte(int paramInt); + + public abstract void writeShort(int paramInt); + + public abstract void writeChar(int paramInt); + + public abstract void writeInt(int paramInt); + + public abstract void writeLong(long paramLong); + + public abstract void writeFloat(float paramFloat); + + public abstract void writeDouble(double paramDouble); + + public abstract void writeChars(String paramString); + + public abstract void writeUTF(String paramString); + + @Deprecated + public abstract void writeBytes(String paramString); + + public abstract byte[] toByteArray(); +} diff --git a/src/minecraft/com/google/common/io/ByteProcessor.java b/src/minecraft/com/google/common/io/ByteProcessor.java new file mode 100644 index 0000000..d9a4356 --- /dev/null +++ b/src/minecraft/com/google/common/io/ByteProcessor.java @@ -0,0 +1,13 @@ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import java.io.IOException; + +@Beta +public abstract interface ByteProcessor +{ + public abstract boolean processBytes(byte[] paramArrayOfByte, int paramInt1, int paramInt2) + throws IOException; + + public abstract T getResult(); +} diff --git a/src/minecraft/com/google/common/io/ByteSink.java b/src/minecraft/com/google/common/io/ByteSink.java new file mode 100644 index 0000000..654f31f --- /dev/null +++ b/src/minecraft/com/google/common/io/ByteSink.java @@ -0,0 +1,171 @@ +package com.google.common.io; + +import com.google.common.base.Preconditions; +import java.io.BufferedOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.nio.charset.Charset; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class ByteSink + implements OutputSupplier +{ + protected ByteSink() {} + + public CharSink asCharSink(Charset charset) + { + return new AsCharSink(charset, null); + } + + + + + + + + + + public abstract OutputStream openStream() + throws IOException; + + + + + + + + + @Deprecated + public final OutputStream getOutput() + throws IOException + { + return openStream(); + } + + + + + + + + + + + + public OutputStream openBufferedStream() + throws IOException + { + OutputStream out = openStream(); + return (out instanceof BufferedOutputStream) ? (BufferedOutputStream)out : new BufferedOutputStream(out); + } + + + + + + + public void write(byte[] bytes) + throws IOException + { + Preconditions.checkNotNull(bytes); + + Closer closer = Closer.create(); + try { + OutputStream out = (OutputStream)closer.register(openStream()); + out.write(bytes); + out.flush(); + } catch (Throwable e) { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } + + + + + + + public long writeFrom(InputStream input) + throws IOException + { + Preconditions.checkNotNull(input); + + Closer closer = Closer.create(); + try { + OutputStream out = (OutputStream)closer.register(openStream()); + long written = ByteStreams.copy(input, out); + out.flush(); + return written; + } catch (Throwable e) { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } + + + private final class AsCharSink + extends CharSink + { + private final Charset charset; + + + private AsCharSink(Charset charset) + { + this.charset = ((Charset)Preconditions.checkNotNull(charset)); + } + + public Writer openStream() throws IOException + { + return new OutputStreamWriter(openStream(), charset); + } + + public String toString() + { + return ByteSink.this.toString() + ".asCharSink(" + charset + ")"; + } + } +} diff --git a/src/minecraft/com/google/common/io/ByteSource.java b/src/minecraft/com/google/common/io/ByteSource.java new file mode 100644 index 0000000..09383ff --- /dev/null +++ b/src/minecraft/com/google/common/io/ByteSource.java @@ -0,0 +1,699 @@ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.base.Ascii; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.hash.Funnels; +import com.google.common.hash.HashCode; +import com.google.common.hash.HashFunction; +import com.google.common.hash.Hasher; +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.Reader; +import java.nio.charset.Charset; +import java.util.Iterator; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class ByteSource + implements InputSupplier +{ + private static final int BUF_SIZE = 4096; + + protected ByteSource() {} + + public CharSource asCharSource(Charset charset) + { + return new AsCharSource(charset, null); + } + + + + + + + + + + public abstract InputStream openStream() + throws IOException; + + + + + + + + + @Deprecated + public final InputStream getInput() + throws IOException + { + return openStream(); + } + + + + + + + + + + + + public InputStream openBufferedStream() + throws IOException + { + InputStream in = openStream(); + return (in instanceof BufferedInputStream) ? (BufferedInputStream)in : new BufferedInputStream(in); + } + + + + + + + + + public ByteSource slice(long offset, long length) + { + return new SlicedByteSource(offset, length, null); + } + + + + + + + public boolean isEmpty() + throws IOException + { + Closer closer = Closer.create(); + try { + InputStream in = (InputStream)closer.register(openStream()); + return in.read() == -1; + } catch (Throwable e) { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } + + + + + + + + + + + + + + + public long size() + throws IOException + { + Closer closer = Closer.create(); + long l; + try { InputStream in = (InputStream)closer.register(openStream()); + return countBySkipping(in); + } + catch (IOException e) {}finally + { + closer.close(); + } + + closer = Closer.create(); + try { + InputStream in = (InputStream)closer.register(openStream()); + return countByReading(in); + } catch (Throwable e) { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } + + + + private long countBySkipping(InputStream in) + throws IOException + { + long count = 0L; + + for (;;) + { + long skipped = in.skip(Math.min(in.available(), Integer.MAX_VALUE)); + if (skipped <= 0L) { + if (in.read() == -1) + return count; + if ((count == 0L) && (in.available() == 0)) + { + + throw new IOException(); + } + count += 1L; + } else { + count += skipped; + } + } + } + + private static final byte[] countBuffer = new byte['က']; + + private long countByReading(InputStream in) throws IOException { + long count = 0L; + long read; + while ((read = in.read(countBuffer)) != -1L) { + count += read; + } + return count; + } + + + + + + + public long copyTo(OutputStream output) + throws IOException + { + Preconditions.checkNotNull(output); + + Closer closer = Closer.create(); + try { + InputStream in = (InputStream)closer.register(openStream()); + return ByteStreams.copy(in, output); + } catch (Throwable e) { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } + + + + + + public long copyTo(ByteSink sink) + throws IOException + { + Preconditions.checkNotNull(sink); + + Closer closer = Closer.create(); + try { + InputStream in = (InputStream)closer.register(openStream()); + OutputStream out = (OutputStream)closer.register(sink.openStream()); + return ByteStreams.copy(in, out); + } catch (Throwable e) { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } + + + + + public byte[] read() + throws IOException + { + Closer closer = Closer.create(); + try { + InputStream in = (InputStream)closer.register(openStream()); + return ByteStreams.toByteArray(in); + } catch (Throwable e) { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } + + + + + + + + + @Beta + public T read(ByteProcessor processor) + throws IOException + { + Preconditions.checkNotNull(processor); + + Closer closer = Closer.create(); + try { + InputStream in = (InputStream)closer.register(openStream()); + return ByteStreams.readBytes(in, processor); + } catch (Throwable e) { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } + + + + + public HashCode hash(HashFunction hashFunction) + throws IOException + { + Hasher hasher = hashFunction.newHasher(); + copyTo(Funnels.asOutputStream(hasher)); + return hasher.hash(); + } + + /* Error */ + public boolean contentEquals(ByteSource other) + throws IOException + { + // Byte code: + // 0: aload_1 + // 1: invokestatic 29 com/google/common/base/Preconditions:checkNotNull (Ljava/lang/Object;)Ljava/lang/Object; + // 4: pop + // 5: sipush 4096 + // 8: newarray byte + // 10: astore_2 + // 11: sipush 4096 + // 14: newarray byte + // 16: astore_3 + // 17: invokestatic 10 com/google/common/io/Closer:create ()Lcom/google/common/io/Closer; + // 20: astore 4 + // 22: aload 4 + // 24: aload_0 + // 25: invokevirtual 5 com/google/common/io/ByteSource:openStream ()Ljava/io/InputStream; + // 28: invokevirtual 11 com/google/common/io/Closer:register (Ljava/io/Closeable;)Ljava/io/Closeable; + // 31: checkcast 12 java/io/InputStream + // 34: astore 5 + // 36: aload 4 + // 38: aload_1 + // 39: invokevirtual 5 com/google/common/io/ByteSource:openStream ()Ljava/io/InputStream; + // 42: invokevirtual 11 com/google/common/io/Closer:register (Ljava/io/Closeable;)Ljava/io/Closeable; + // 45: checkcast 12 java/io/InputStream + // 48: astore 6 + // 50: aload 5 + // 52: aload_2 + // 53: iconst_0 + // 54: sipush 4096 + // 57: invokestatic 39 com/google/common/io/ByteStreams:read (Ljava/io/InputStream;[BII)I + // 60: istore 7 + // 62: aload 6 + // 64: aload_3 + // 65: iconst_0 + // 66: sipush 4096 + // 69: invokestatic 39 com/google/common/io/ByteStreams:read (Ljava/io/InputStream;[BII)I + // 72: istore 8 + // 74: iload 7 + // 76: iload 8 + // 78: if_icmpne +11 -> 89 + // 81: aload_2 + // 82: aload_3 + // 83: invokestatic 40 java/util/Arrays:equals ([B[B)Z + // 86: ifne +14 -> 100 + // 89: iconst_0 + // 90: istore 9 + // 92: aload 4 + // 94: invokevirtual 14 com/google/common/io/Closer:close ()V + // 97: iload 9 + // 99: ireturn + // 100: iload 7 + // 102: sipush 4096 + // 105: if_icmpeq +14 -> 119 + // 108: iconst_1 + // 109: istore 9 + // 111: aload 4 + // 113: invokevirtual 14 com/google/common/io/Closer:close ()V + // 116: iload 9 + // 118: ireturn + // 119: goto -69 -> 50 + // 122: astore 5 + // 124: aload 4 + // 126: aload 5 + // 128: invokevirtual 16 com/google/common/io/Closer:rethrow (Ljava/lang/Throwable;)Ljava/lang/RuntimeException; + // 131: athrow + // 132: astore 10 + // 134: aload 4 + // 136: invokevirtual 14 com/google/common/io/Closer:close ()V + // 139: aload 10 + // 141: athrow + // Line number table: + // Java source line #324 -> byte code offset #0 + // Java source line #326 -> byte code offset #5 + // Java source line #327 -> byte code offset #11 + // Java source line #329 -> byte code offset #17 + // Java source line #331 -> byte code offset #22 + // Java source line #332 -> byte code offset #36 + // Java source line #334 -> byte code offset #50 + // Java source line #335 -> byte code offset #62 + // Java source line #336 -> byte code offset #74 + // Java source line #337 -> byte code offset #89 + // Java source line #345 -> byte code offset #92 + // Java source line #338 -> byte code offset #100 + // Java source line #339 -> byte code offset #108 + // Java source line #345 -> byte code offset #111 + // Java source line #341 -> byte code offset #119 + // Java source line #342 -> byte code offset #122 + // Java source line #343 -> byte code offset #124 + // Java source line #345 -> byte code offset #132 + // Local variable table: + // start length slot name signature + // 0 142 0 this ByteSource + // 0 142 1 other ByteSource + // 10 72 2 buf1 byte[] + // 16 67 3 buf2 byte[] + // 20 115 4 closer Closer + // 34 17 5 in1 InputStream + // 122 5 5 e Throwable + // 48 15 6 in2 InputStream + // 60 41 7 read1 int + // 72 5 8 read2 int + // 90 27 9 bool boolean + // 132 8 10 localObject Object + // Exception table: + // from to target type + // 22 92 122 java/lang/Throwable + // 100 111 122 java/lang/Throwable + // 119 122 122 java/lang/Throwable + // 22 92 132 finally + // 100 111 132 finally + // 119 134 132 finally + } + + public static ByteSource concat(Iterable sources) + { + return new ConcatenatedByteSource(sources); + } + + + + + + + + + + + + + + + + + + + public static ByteSource concat(Iterator sources) + { + return concat(ImmutableList.copyOf(sources)); + } + + + + + + + + + + + + + public static ByteSource concat(ByteSource... sources) + { + return concat(ImmutableList.copyOf(sources)); + } + + + + + + + public static ByteSource wrap(byte[] b) + { + return new ByteArrayByteSource(b); + } + + + + + + public static ByteSource empty() + { + return EmptyByteSource.INSTANCE; + } + + + private final class AsCharSource + extends CharSource + { + private final Charset charset; + + + private AsCharSource(Charset charset) + { + this.charset = ((Charset)Preconditions.checkNotNull(charset)); + } + + public Reader openStream() throws IOException + { + return new InputStreamReader(openStream(), charset); + } + + public String toString() + { + return ByteSource.this.toString() + ".asCharSource(" + charset + ")"; + } + } + + + private final class SlicedByteSource + extends ByteSource + { + private final long offset; + private final long length; + + private SlicedByteSource(long offset, long length) + { + Preconditions.checkArgument(offset >= 0L, "offset (%s) may not be negative", new Object[] { Long.valueOf(offset) }); + Preconditions.checkArgument(length >= 0L, "length (%s) may not be negative", new Object[] { Long.valueOf(length) }); + this.offset = offset; + this.length = length; + } + + public InputStream openStream() throws IOException + { + return sliceStream(ByteSource.this.openStream()); + } + + public InputStream openBufferedStream() throws IOException + { + return sliceStream(ByteSource.this.openBufferedStream()); + } + + private InputStream sliceStream(InputStream in) throws IOException { + if (offset > 0L) { + try { + ByteStreams.skipFully(in, offset); + } catch (Throwable e) { + Closer closer = Closer.create(); + closer.register(in); + try { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } + } + return ByteStreams.limit(in, length); + } + + public ByteSource slice(long offset, long length) + { + Preconditions.checkArgument(offset >= 0L, "offset (%s) may not be negative", new Object[] { Long.valueOf(offset) }); + Preconditions.checkArgument(length >= 0L, "length (%s) may not be negative", new Object[] { Long.valueOf(length) }); + long maxLength = this.length - offset; + return ByteSource.this.slice(this.offset + offset, Math.min(length, maxLength)); + } + + public boolean isEmpty() throws IOException + { + return (length == 0L) || (super.isEmpty()); + } + + public String toString() + { + return ByteSource.this.toString() + ".slice(" + offset + ", " + length + ")"; + } + } + + private static class ByteArrayByteSource extends ByteSource + { + protected final byte[] bytes; + + protected ByteArrayByteSource(byte[] bytes) { + this.bytes = ((byte[])Preconditions.checkNotNull(bytes)); + } + + public InputStream openStream() + { + return new ByteArrayInputStream(bytes); + } + + public InputStream openBufferedStream() throws IOException + { + return openStream(); + } + + public boolean isEmpty() + { + return bytes.length == 0; + } + + public long size() + { + return bytes.length; + } + + public byte[] read() + { + return (byte[])bytes.clone(); + } + + public long copyTo(OutputStream output) throws IOException + { + output.write(bytes); + return bytes.length; + } + + public T read(ByteProcessor processor) throws IOException + { + processor.processBytes(bytes, 0, bytes.length); + return processor.getResult(); + } + + public HashCode hash(HashFunction hashFunction) throws IOException + { + return hashFunction.hashBytes(bytes); + } + + + + public String toString() + { + return "ByteSource.wrap(" + Ascii.truncate(BaseEncoding.base16().encode(bytes), 30, "...") + ")"; + } + } + + private static final class EmptyByteSource + extends ByteSource.ByteArrayByteSource + { + private static final EmptyByteSource INSTANCE = new EmptyByteSource(); + + private EmptyByteSource() { + super(); + } + + public CharSource asCharSource(Charset charset) + { + Preconditions.checkNotNull(charset); + return CharSource.empty(); + } + + public byte[] read() + { + return bytes; + } + + public String toString() + { + return "ByteSource.empty()"; + } + } + + private static final class ConcatenatedByteSource extends ByteSource + { + private final Iterable sources; + + ConcatenatedByteSource(Iterable sources) { + this.sources = ((Iterable)Preconditions.checkNotNull(sources)); + } + + public InputStream openStream() throws IOException + { + return new MultiInputStream(sources.iterator()); + } + + public boolean isEmpty() throws IOException + { + for (ByteSource source : sources) { + if (!source.isEmpty()) { + return false; + } + } + return true; + } + + public long size() throws IOException + { + long result = 0L; + for (ByteSource source : sources) { + result += source.size(); + } + return result; + } + + public String toString() + { + return "ByteSource.concat(" + sources + ")"; + } + } +} diff --git a/src/minecraft/com/google/common/io/ByteStreams.java b/src/minecraft/com/google/common/io/ByteStreams.java new file mode 100644 index 0000000..403c6b9 --- /dev/null +++ b/src/minecraft/com/google/common/io/ByteStreams.java @@ -0,0 +1,1071 @@ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.Iterables; +import com.google.common.hash.HashCode; +import com.google.common.hash.HashFunction; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.Closeable; +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.DataOutput; +import java.io.DataOutputStream; +import java.io.EOFException; +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; +import java.util.Arrays; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class ByteStreams +{ + private static final int BUF_SIZE = 4096; + + private ByteStreams() {} + + @Deprecated + public static InputSupplier newInputStreamSupplier(byte[] b) + { + return asInputSupplier(ByteSource.wrap(b)); + } + + + + + + + + + + + + + @Deprecated + public static InputSupplier newInputStreamSupplier(byte[] b, int off, int len) + { + return asInputSupplier(ByteSource.wrap(b).slice(off, len)); + } + + + + + + + + + + @Deprecated + public static void write(byte[] from, OutputSupplier to) + throws IOException + { + asByteSink(to).write(from); + } + + + + + + + + + + + + @Deprecated + public static long copy(InputSupplier from, OutputSupplier to) + throws IOException + { + return asByteSource(from).copyTo(asByteSink(to)); + } + + + + + + + + + + + + + @Deprecated + public static long copy(InputSupplier from, OutputStream to) + throws IOException + { + return asByteSource(from).copyTo(to); + } + + + + + + + + + + + + + + @Deprecated + public static long copy(InputStream from, OutputSupplier to) + throws IOException + { + return asByteSink(to).writeFrom(from); + } + + + + + + + + + + public static long copy(InputStream from, OutputStream to) + throws IOException + { + Preconditions.checkNotNull(from); + Preconditions.checkNotNull(to); + byte[] buf = new byte['က']; + long total = 0L; + for (;;) { + int r = from.read(buf); + if (r == -1) { + break; + } + to.write(buf, 0, r); + total += r; + } + return total; + } + + + + + + + + + + public static long copy(ReadableByteChannel from, WritableByteChannel to) + throws IOException + { + Preconditions.checkNotNull(from); + Preconditions.checkNotNull(to); + ByteBuffer buf = ByteBuffer.allocate(4096); + long total = 0L; + while (from.read(buf) != -1) { + buf.flip(); + while (buf.hasRemaining()) { + total += to.write(buf); + } + buf.clear(); + } + return total; + } + + + + + + + + public static byte[] toByteArray(InputStream in) + throws IOException + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + copy(in, out); + return out.toByteArray(); + } + + + + + + + static byte[] toByteArray(InputStream in, int expectedSize) + throws IOException + { + byte[] bytes = new byte[expectedSize]; + int remaining = expectedSize; + + while (remaining > 0) { + int off = expectedSize - remaining; + int read = in.read(bytes, off, remaining); + if (read == -1) + { + + return Arrays.copyOf(bytes, off); + } + remaining -= read; + } + + + int b = in.read(); + if (b == -1) { + return bytes; + } + + + FastByteArrayOutputStream out = new FastByteArrayOutputStream(null); + out.write(b); + copy(in, out); + + byte[] result = new byte[bytes.length + out.size()]; + System.arraycopy(bytes, 0, result, 0, bytes.length); + out.writeTo(result, bytes.length); + return result; + } + + + + private static final class FastByteArrayOutputStream + extends ByteArrayOutputStream + { + private FastByteArrayOutputStream() {} + + + void writeTo(byte[] b, int off) + { + System.arraycopy(buf, 0, b, off, count); + } + } + + + + + + + + + @Deprecated + public static byte[] toByteArray(InputSupplier supplier) + throws IOException + { + return asByteSource(supplier).read(); + } + + + + + public static ByteArrayDataInput newDataInput(byte[] bytes) + { + return newDataInput(new ByteArrayInputStream(bytes)); + } + + + + + + + + public static ByteArrayDataInput newDataInput(byte[] bytes, int start) + { + Preconditions.checkPositionIndex(start, bytes.length); + return newDataInput(new ByteArrayInputStream(bytes, start, bytes.length - start)); + } + + + + + + + + + + public static ByteArrayDataInput newDataInput(ByteArrayInputStream byteArrayInputStream) + { + return new ByteArrayDataInputStream((ByteArrayInputStream)Preconditions.checkNotNull(byteArrayInputStream)); + } + + private static class ByteArrayDataInputStream implements ByteArrayDataInput { + final DataInput input; + + ByteArrayDataInputStream(ByteArrayInputStream byteArrayInputStream) { + input = new DataInputStream(byteArrayInputStream); + } + + public void readFully(byte[] b) { + try { + input.readFully(b); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + public void readFully(byte[] b, int off, int len) { + try { + input.readFully(b, off, len); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + public int skipBytes(int n) { + try { + return input.skipBytes(n); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + public boolean readBoolean() { + try { + return input.readBoolean(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + public byte readByte() { + try { + return input.readByte(); + } catch (EOFException e) { + throw new IllegalStateException(e); + } catch (IOException impossible) { + throw new AssertionError(impossible); + } + } + + public int readUnsignedByte() { + try { + return input.readUnsignedByte(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + public short readShort() { + try { + return input.readShort(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + public int readUnsignedShort() { + try { + return input.readUnsignedShort(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + public char readChar() { + try { + return input.readChar(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + public int readInt() { + try { + return input.readInt(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + public long readLong() { + try { + return input.readLong(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + public float readFloat() { + try { + return input.readFloat(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + public double readDouble() { + try { + return input.readDouble(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + public String readLine() { + try { + return input.readLine(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + public String readUTF() { + try { + return input.readUTF(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + } + + + + public static ByteArrayDataOutput newDataOutput() + { + return newDataOutput(new ByteArrayOutputStream()); + } + + + + + + + public static ByteArrayDataOutput newDataOutput(int size) + { + Preconditions.checkArgument(size >= 0, "Invalid size: %s", new Object[] { Integer.valueOf(size) }); + return newDataOutput(new ByteArrayOutputStream(size)); + } + + + + + + + + + + + + + + + + public static ByteArrayDataOutput newDataOutput(ByteArrayOutputStream byteArrayOutputSteam) + { + return new ByteArrayDataOutputStream((ByteArrayOutputStream)Preconditions.checkNotNull(byteArrayOutputSteam)); + } + + private static class ByteArrayDataOutputStream + implements ByteArrayDataOutput + { + final DataOutput output; + final ByteArrayOutputStream byteArrayOutputSteam; + + ByteArrayDataOutputStream(ByteArrayOutputStream byteArrayOutputSteam) + { + this.byteArrayOutputSteam = byteArrayOutputSteam; + output = new DataOutputStream(byteArrayOutputSteam); + } + + public void write(int b) { + try { + output.write(b); + } catch (IOException impossible) { + throw new AssertionError(impossible); + } + } + + public void write(byte[] b) { + try { + output.write(b); + } catch (IOException impossible) { + throw new AssertionError(impossible); + } + } + + public void write(byte[] b, int off, int len) { + try { + output.write(b, off, len); + } catch (IOException impossible) { + throw new AssertionError(impossible); + } + } + + public void writeBoolean(boolean v) { + try { + output.writeBoolean(v); + } catch (IOException impossible) { + throw new AssertionError(impossible); + } + } + + public void writeByte(int v) { + try { + output.writeByte(v); + } catch (IOException impossible) { + throw new AssertionError(impossible); + } + } + + public void writeBytes(String s) { + try { + output.writeBytes(s); + } catch (IOException impossible) { + throw new AssertionError(impossible); + } + } + + public void writeChar(int v) { + try { + output.writeChar(v); + } catch (IOException impossible) { + throw new AssertionError(impossible); + } + } + + public void writeChars(String s) { + try { + output.writeChars(s); + } catch (IOException impossible) { + throw new AssertionError(impossible); + } + } + + public void writeDouble(double v) { + try { + output.writeDouble(v); + } catch (IOException impossible) { + throw new AssertionError(impossible); + } + } + + public void writeFloat(float v) { + try { + output.writeFloat(v); + } catch (IOException impossible) { + throw new AssertionError(impossible); + } + } + + public void writeInt(int v) { + try { + output.writeInt(v); + } catch (IOException impossible) { + throw new AssertionError(impossible); + } + } + + public void writeLong(long v) { + try { + output.writeLong(v); + } catch (IOException impossible) { + throw new AssertionError(impossible); + } + } + + public void writeShort(int v) { + try { + output.writeShort(v); + } catch (IOException impossible) { + throw new AssertionError(impossible); + } + } + + public void writeUTF(String s) { + try { + output.writeUTF(s); + } catch (IOException impossible) { + throw new AssertionError(impossible); + } + } + + public byte[] toByteArray() { + return byteArrayOutputSteam.toByteArray(); + } + } + + private static final OutputStream NULL_OUTPUT_STREAM = new OutputStream() + { + public void write(int b) {} + + + public void write(byte[] b) + { + Preconditions.checkNotNull(b); + } + + public void write(byte[] b, int off, int len) { + Preconditions.checkNotNull(b); + } + + public String toString() + { + return "ByteStreams.nullOutputStream()"; + } + }; + + + + + + public static OutputStream nullOutputStream() + { + return NULL_OUTPUT_STREAM; + } + + + + + + + + + + public static InputStream limit(InputStream in, long limit) + { + return new LimitedInputStream(in, limit); + } + + private static final class LimitedInputStream extends FilterInputStream + { + private long left; + private long mark = -1L; + + LimitedInputStream(InputStream in, long limit) { + super(); + Preconditions.checkNotNull(in); + Preconditions.checkArgument(limit >= 0L, "limit must be non-negative"); + left = limit; + } + + public int available() throws IOException { + return (int)Math.min(in.available(), left); + } + + public synchronized void mark(int readLimit) + { + in.mark(readLimit); + mark = left; + } + + public int read() throws IOException { + if (left == 0L) { + return -1; + } + + int result = in.read(); + if (result != -1) { + left -= 1L; + } + return result; + } + + public int read(byte[] b, int off, int len) throws IOException { + if (left == 0L) { + return -1; + } + + len = (int)Math.min(len, left); + int result = in.read(b, off, len); + if (result != -1) { + left -= result; + } + return result; + } + + public synchronized void reset() throws IOException { + if (!in.markSupported()) { + throw new IOException("Mark not supported"); + } + if (mark == -1L) { + throw new IOException("Mark not set"); + } + + in.reset(); + left = mark; + } + + public long skip(long n) throws IOException { + n = Math.min(n, left); + long skipped = in.skip(n); + left -= skipped; + return skipped; + } + } + + + + + + + @Deprecated + public static long length(InputSupplier supplier) + throws IOException + { + return asByteSource(supplier).size(); + } + + + + + + + + @Deprecated + public static boolean equal(InputSupplier supplier1, InputSupplier supplier2) + throws IOException + { + return asByteSource(supplier1).contentEquals(asByteSource(supplier2)); + } + + + + + + + + + + + public static void readFully(InputStream in, byte[] b) + throws IOException + { + readFully(in, b, 0, b.length); + } + + + + + + + + + + + + + + + public static void readFully(InputStream in, byte[] b, int off, int len) + throws IOException + { + int read = read(in, b, off, len); + if (read != len) { + throw new EOFException("reached end of stream after reading " + read + " bytes; " + len + " bytes expected"); + } + } + + + + + + + + + + + + + public static void skipFully(InputStream in, long n) + throws IOException + { + long toSkip = n; + while (n > 0L) { + long amt = in.skip(n); + if (amt == 0L) + { + if (in.read() == -1) { + long skipped = toSkip - n; + throw new EOFException("reached end of stream after skipping " + skipped + " bytes; " + toSkip + " bytes expected"); + } + + n -= 1L; + } else { + n -= amt; + } + } + } + + + + + + + + + + + + @Deprecated + public static T readBytes(InputSupplier supplier, ByteProcessor processor) + throws IOException + { + Preconditions.checkNotNull(supplier); + Preconditions.checkNotNull(processor); + + Closer closer = Closer.create(); + try { + InputStream in = (InputStream)closer.register((Closeable)supplier.getInput()); + return readBytes(in, processor); + } catch (Throwable e) { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } + + + + + + + + + + public static T readBytes(InputStream input, ByteProcessor processor) + throws IOException + { + Preconditions.checkNotNull(input); + Preconditions.checkNotNull(processor); + + byte[] buf = new byte['က']; + int read; + do { + read = input.read(buf); + } while ((read != -1) && (processor.processBytes(buf, 0, read))); + return processor.getResult(); + } + + + + + + + + + + + + + + @Deprecated + public static HashCode hash(InputSupplier supplier, HashFunction hashFunction) + throws IOException + { + return asByteSource(supplier).hash(hashFunction); + } + + + + + + + + + + + + + + + + + + + + + + + + + public static int read(InputStream in, byte[] b, int off, int len) + throws IOException + { + Preconditions.checkNotNull(in); + Preconditions.checkNotNull(b); + if (len < 0) { + throw new IndexOutOfBoundsException("len is negative"); + } + int total = 0; + while (total < len) { + int result = in.read(b, off + total, len - total); + if (result == -1) { + break; + } + total += result; + } + return total; + } + + + + + + + + + + + + + + + + + @Deprecated + public static InputSupplier slice(InputSupplier supplier, long offset, long length) + { + return asInputSupplier(asByteSource(supplier).slice(offset, length)); + } + + + + + + + + + + + + + + + + + + + @Deprecated + public static InputSupplier join(Iterable> suppliers) + { + Preconditions.checkNotNull(suppliers); + Iterable sources = Iterables.transform(suppliers, new Function() + { + public ByteSource apply(InputSupplier input) + { + return ByteStreams.asByteSource(input); + } + }); + return asInputSupplier(ByteSource.concat(sources)); + } + + + + + + + + + @Deprecated + public static InputSupplier join(InputSupplier... suppliers) + { + return join(Arrays.asList(suppliers)); + } + + + + + + + + + + + + + + + + + @Deprecated + public static ByteSource asByteSource(InputSupplier supplier) + { + Preconditions.checkNotNull(supplier); + new ByteSource() + { + public InputStream openStream() throws IOException { + return (InputStream)val$supplier.getInput(); + } + + public String toString() + { + return "ByteStreams.asByteSource(" + val$supplier + ")"; + } + }; + } + + + + + + + + + + + + + + + @Deprecated + public static ByteSink asByteSink(OutputSupplier supplier) + { + Preconditions.checkNotNull(supplier); + new ByteSink() + { + public OutputStream openStream() throws IOException { + return (OutputStream)val$supplier.getOutput(); + } + + public String toString() + { + return "ByteStreams.asByteSink(" + val$supplier + ")"; + } + }; + } + + + static InputSupplier asInputSupplier(ByteSource source) + { + return (InputSupplier)Preconditions.checkNotNull(source); + } + + + static OutputSupplier asOutputSupplier(ByteSink sink) + { + return (OutputSupplier)Preconditions.checkNotNull(sink); + } +} diff --git a/src/minecraft/com/google/common/io/CharSequenceReader.java b/src/minecraft/com/google/common/io/CharSequenceReader.java new file mode 100644 index 0000000..6df337e --- /dev/null +++ b/src/minecraft/com/google/common/io/CharSequenceReader.java @@ -0,0 +1,132 @@ +package com.google.common.io; + +import com.google.common.base.Preconditions; +import java.io.IOException; +import java.io.Reader; +import java.nio.CharBuffer; + + + + + + + + + + + + + + + + + + + + + + + + + + + + +final class CharSequenceReader + extends Reader +{ + private CharSequence seq; + private int pos; + private int mark; + + public CharSequenceReader(CharSequence seq) + { + this.seq = ((CharSequence)Preconditions.checkNotNull(seq)); + } + + private void checkOpen() throws IOException { + if (seq == null) { + throw new IOException("reader closed"); + } + } + + private boolean hasRemaining() { + return remaining() > 0; + } + + private int remaining() { + return seq.length() - pos; + } + + public synchronized int read(CharBuffer target) throws IOException + { + Preconditions.checkNotNull(target); + checkOpen(); + if (!hasRemaining()) { + return -1; + } + int charsToRead = Math.min(target.remaining(), remaining()); + for (int i = 0; i < charsToRead; i++) { + target.put(seq.charAt(pos++)); + } + return charsToRead; + } + + public synchronized int read() throws IOException + { + checkOpen(); + return hasRemaining() ? seq.charAt(pos++) : -1; + } + + public synchronized int read(char[] cbuf, int off, int len) throws IOException + { + Preconditions.checkPositionIndexes(off, off + len, cbuf.length); + checkOpen(); + if (!hasRemaining()) { + return -1; + } + int charsToRead = Math.min(len, remaining()); + for (int i = 0; i < charsToRead; i++) { + cbuf[(off + i)] = seq.charAt(pos++); + } + return charsToRead; + } + + public synchronized long skip(long n) throws IOException + { + Preconditions.checkArgument(n >= 0L, "n (%s) may not be negative", new Object[] { Long.valueOf(n) }); + checkOpen(); + int charsToSkip = (int)Math.min(remaining(), n); + pos += charsToSkip; + return charsToSkip; + } + + public synchronized boolean ready() throws IOException + { + checkOpen(); + return true; + } + + public boolean markSupported() + { + return true; + } + + public synchronized void mark(int readAheadLimit) throws IOException + { + Preconditions.checkArgument(readAheadLimit >= 0, "readAheadLimit (%s) may not be negative", new Object[] { Integer.valueOf(readAheadLimit) }); + checkOpen(); + mark = pos; + } + + public synchronized void reset() throws IOException + { + checkOpen(); + pos = mark; + } + + public synchronized void close() throws IOException + { + seq = null; + } +} diff --git a/src/minecraft/com/google/common/io/CharSink.java b/src/minecraft/com/google/common/io/CharSink.java new file mode 100644 index 0000000..c192407 --- /dev/null +++ b/src/minecraft/com/google/common/io/CharSink.java @@ -0,0 +1,178 @@ +package com.google.common.io; + +import com.google.common.base.Preconditions; +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.Writer; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class CharSink + implements OutputSupplier +{ + protected CharSink() {} + + public abstract Writer openStream() + throws IOException; + + @Deprecated + public final Writer getOutput() + throws IOException + { + return openStream(); + } + + + + + + + + + + + + public Writer openBufferedStream() + throws IOException + { + Writer writer = openStream(); + return (writer instanceof BufferedWriter) ? (BufferedWriter)writer : new BufferedWriter(writer); + } + + + + + + + public void write(CharSequence charSequence) + throws IOException + { + Preconditions.checkNotNull(charSequence); + + Closer closer = Closer.create(); + try { + Writer out = (Writer)closer.register(openStream()); + out.append(charSequence); + out.flush(); + } catch (Throwable e) { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } + + + + + + + public void writeLines(Iterable lines) + throws IOException + { + writeLines(lines, System.getProperty("line.separator")); + } + + + + + + + public void writeLines(Iterable lines, String lineSeparator) + throws IOException + { + Preconditions.checkNotNull(lines); + Preconditions.checkNotNull(lineSeparator); + + Closer closer = Closer.create(); + try { + Writer out = (Writer)closer.register(openBufferedStream()); + for (CharSequence line : lines) { + out.append(line).append(lineSeparator); + } + out.flush(); + } catch (Throwable e) { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } + + + + + + + public long writeFrom(Readable readable) + throws IOException + { + Preconditions.checkNotNull(readable); + + Closer closer = Closer.create(); + try { + Writer out = (Writer)closer.register(openStream()); + long written = CharStreams.copy(readable, out); + out.flush(); + return written; + } catch (Throwable e) { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } +} diff --git a/src/minecraft/com/google/common/io/CharSource.java b/src/minecraft/com/google/common/io/CharSource.java new file mode 100644 index 0000000..45cf5ab --- /dev/null +++ b/src/minecraft/com/google/common/io/CharSource.java @@ -0,0 +1,463 @@ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.base.Ascii; +import com.google.common.base.Preconditions; +import com.google.common.base.Splitter; +import com.google.common.collect.AbstractIterator; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; +import java.util.Iterator; +import java.util.List; +import java.util.regex.Pattern; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class CharSource + implements InputSupplier +{ + protected CharSource() {} + + public abstract Reader openStream() + throws IOException; + + @Deprecated + public final Reader getInput() + throws IOException + { + return openStream(); + } + + + + + + + + public BufferedReader openBufferedStream() + throws IOException + { + Reader reader = openStream(); + return (reader instanceof BufferedReader) ? (BufferedReader)reader : new BufferedReader(reader); + } + + + + + + + + + public long copyTo(Appendable appendable) + throws IOException + { + Preconditions.checkNotNull(appendable); + + Closer closer = Closer.create(); + try { + Reader reader = (Reader)closer.register(openStream()); + return CharStreams.copy(reader, appendable); + } catch (Throwable e) { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } + + + + + + public long copyTo(CharSink sink) + throws IOException + { + Preconditions.checkNotNull(sink); + + Closer closer = Closer.create(); + try { + Reader reader = (Reader)closer.register(openStream()); + Writer writer = (Writer)closer.register(sink.openStream()); + return CharStreams.copy(reader, writer); + } catch (Throwable e) { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } + + + + + public String read() + throws IOException + { + Closer closer = Closer.create(); + try { + Reader reader = (Reader)closer.register(openStream()); + return CharStreams.toString(reader); + } catch (Throwable e) { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } + + + + + + + + @Nullable + public String readFirstLine() + throws IOException + { + Closer closer = Closer.create(); + try { + BufferedReader reader = (BufferedReader)closer.register(openBufferedStream()); + return reader.readLine(); + } catch (Throwable e) { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } + + + + + + + + + + public ImmutableList readLines() + throws IOException + { + Closer closer = Closer.create(); + try { + BufferedReader reader = (BufferedReader)closer.register(openBufferedStream()); + List result = Lists.newArrayList(); + String line; + while ((line = reader.readLine()) != null) { + result.add(line); + } + return ImmutableList.copyOf(result); + } catch (Throwable e) { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } + + + + + + + + + + + + + + @Beta + public T readLines(LineProcessor processor) + throws IOException + { + Preconditions.checkNotNull(processor); + + Closer closer = Closer.create(); + try { + Reader reader = (Reader)closer.register(openStream()); + return CharStreams.readLines(reader, processor); + } catch (Throwable e) { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } + + + + + + + public boolean isEmpty() + throws IOException + { + Closer closer = Closer.create(); + try { + Reader reader = (Reader)closer.register(openStream()); + return reader.read() == -1; + } catch (Throwable e) { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } + + + + + + + + + + + + public static CharSource concat(Iterable sources) + { + return new ConcatenatedCharSource(sources); + } + + + + + + + + + + + + + + + + + + + public static CharSource concat(Iterator sources) + { + return concat(ImmutableList.copyOf(sources)); + } + + + + + + + + + + + + + public static CharSource concat(CharSource... sources) + { + return concat(ImmutableList.copyOf(sources)); + } + + + + + + + + public static CharSource wrap(CharSequence charSequence) + { + return new CharSequenceCharSource(charSequence); + } + + + + + + public static CharSource empty() + { + return EmptyCharSource.INSTANCE; + } + + private static class CharSequenceCharSource extends CharSource + { + private static final Splitter LINE_SPLITTER = Splitter.on(Pattern.compile("\r\n|\n|\r")); + + private final CharSequence seq; + + protected CharSequenceCharSource(CharSequence seq) + { + this.seq = ((CharSequence)Preconditions.checkNotNull(seq)); + } + + public Reader openStream() + { + return new CharSequenceReader(seq); + } + + public String read() + { + return seq.toString(); + } + + public boolean isEmpty() + { + return seq.length() == 0; + } + + + + + + private Iterable lines() + { + new Iterable() + { + public Iterator iterator() { + new AbstractIterator() { + Iterator lines = CharSource.CharSequenceCharSource.LINE_SPLITTER.split(seq).iterator(); + + protected String computeNext() + { + if (lines.hasNext()) { + String next = (String)lines.next(); + + if ((lines.hasNext()) || (!next.isEmpty())) { + return next; + } + } + return (String)endOfData(); + } + }; + } + }; + } + + public String readFirstLine() + { + Iterator lines = lines().iterator(); + return lines.hasNext() ? (String)lines.next() : null; + } + + public ImmutableList readLines() + { + return ImmutableList.copyOf(lines()); + } + + public T readLines(LineProcessor processor) throws IOException + { + for (String line : lines()) { + if (!processor.processLine(line)) { + break; + } + } + return processor.getResult(); + } + + public String toString() + { + return "CharSource.wrap(" + Ascii.truncate(seq, 30, "...") + ")"; + } + } + + private static final class EmptyCharSource extends CharSource.CharSequenceCharSource + { + private static final EmptyCharSource INSTANCE = new EmptyCharSource(); + + private EmptyCharSource() { + super(); + } + + public String toString() + { + return "CharSource.empty()"; + } + } + + private static final class ConcatenatedCharSource extends CharSource + { + private final Iterable sources; + + ConcatenatedCharSource(Iterable sources) { + this.sources = ((Iterable)Preconditions.checkNotNull(sources)); + } + + public Reader openStream() throws IOException + { + return new MultiReader(sources.iterator()); + } + + public boolean isEmpty() throws IOException + { + for (CharSource source : sources) { + if (!source.isEmpty()) { + return false; + } + } + return true; + } + + public String toString() + { + return "CharSource.concat(" + sources + ")"; + } + } +} diff --git a/src/minecraft/com/google/common/io/CharStreams.java b/src/minecraft/com/google/common/io/CharStreams.java new file mode 100644 index 0000000..e475571 --- /dev/null +++ b/src/minecraft/com/google/common/io/CharStreams.java @@ -0,0 +1,607 @@ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.Iterables; +import java.io.Closeable; +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.StringReader; +import java.io.Writer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class CharStreams +{ + private static final int BUF_SIZE = 2048; + + private CharStreams() {} + + @Deprecated + public static InputSupplier newReaderSupplier(String value) + { + return asInputSupplier(CharSource.wrap(value)); + } + + + + + + + + + + + + + @Deprecated + public static InputSupplier newReaderSupplier(InputSupplier in, Charset charset) + { + return asInputSupplier(ByteStreams.asByteSource(in).asCharSource(charset)); + } + + + + + + + + + + + + + + @Deprecated + public static OutputSupplier newWriterSupplier(OutputSupplier out, Charset charset) + { + return asOutputSupplier(ByteStreams.asByteSink(out).asCharSink(charset)); + } + + + + + + + + + + + + @Deprecated + public static void write(CharSequence from, OutputSupplier to) + throws IOException + { + asCharSink(to).write(from); + } + + + + + + + + + + + + + + @Deprecated + public static long copy(InputSupplier from, OutputSupplier to) + throws IOException + { + return asCharSource(from).copyTo(asCharSink(to)); + } + + + + + + + + + + + + + @Deprecated + public static long copy(InputSupplier from, Appendable to) + throws IOException + { + return asCharSource(from).copyTo(to); + } + + + + + + + + + public static long copy(Readable from, Appendable to) + throws IOException + { + Preconditions.checkNotNull(from); + Preconditions.checkNotNull(to); + CharBuffer buf = CharBuffer.allocate(2048); + long total = 0L; + while (from.read(buf) != -1) { + buf.flip(); + to.append(buf); + total += buf.remaining(); + buf.clear(); + } + return total; + } + + + + + + + + public static String toString(Readable r) + throws IOException + { + return toStringBuilder(r).toString(); + } + + + + + + + + + + + @Deprecated + public static String toString(InputSupplier supplier) + throws IOException + { + return asCharSource(supplier).read(); + } + + + + + + + + private static StringBuilder toStringBuilder(Readable r) + throws IOException + { + StringBuilder sb = new StringBuilder(); + copy(r, sb); + return sb; + } + + + + + + + + + + + + @Deprecated + public static String readFirstLine(InputSupplier supplier) + throws IOException + { + return asCharSource(supplier).readFirstLine(); + } + + + + + + + + + + + + + @Deprecated + public static List readLines(InputSupplier supplier) + throws IOException + { + Closer closer = Closer.create(); + try { + R r = (Readable)closer.register((Closeable)supplier.getInput()); + return readLines(r); + } catch (Throwable e) { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } + + + + + + + + + + + + + public static List readLines(Readable r) + throws IOException + { + List result = new ArrayList(); + LineReader lineReader = new LineReader(r); + String line; + while ((line = lineReader.readLine()) != null) { + result.add(line); + } + return result; + } + + + + + + + + + + + public static T readLines(Readable readable, LineProcessor processor) + throws IOException + { + Preconditions.checkNotNull(readable); + Preconditions.checkNotNull(processor); + + LineReader lineReader = new LineReader(readable); + String line; + while ((line = lineReader.readLine()) != null) { + if (!processor.processLine(line)) { + break; + } + } + return processor.getResult(); + } + + + + + + + + + + + + + @Deprecated + public static T readLines(InputSupplier supplier, LineProcessor callback) + throws IOException + { + Preconditions.checkNotNull(supplier); + Preconditions.checkNotNull(callback); + + Closer closer = Closer.create(); + try { + R r = (Readable)closer.register((Closeable)supplier.getInput()); + return readLines(r, callback); + } catch (Throwable e) { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } + + + + + + + + + + + + + + + + + + + @Deprecated + public static InputSupplier join(Iterable> suppliers) + { + Preconditions.checkNotNull(suppliers); + Iterable sources = Iterables.transform(suppliers, new Function() + { + public CharSource apply(InputSupplier input) + { + return CharStreams.asCharSource(input); + } + }); + return asInputSupplier(CharSource.concat(sources)); + } + + + + + + + + + @Deprecated + public static InputSupplier join(InputSupplier... suppliers) + { + return join(Arrays.asList(suppliers)); + } + + + + + + + + + + + public static void skipFully(Reader reader, long n) + throws IOException + { + Preconditions.checkNotNull(reader); + while (n > 0L) { + long amt = reader.skip(n); + if (amt == 0L) + { + if (reader.read() == -1) { + throw new EOFException(); + } + n -= 1L; + } else { + n -= amt; + } + } + } + + + + + + public static Writer nullWriter() + { + return NullWriter.INSTANCE; + } + + private static final class NullWriter extends Writer + { + private static final NullWriter INSTANCE = new NullWriter(); + + private NullWriter() {} + + public void write(int c) {} + + public void write(char[] cbuf) + { + Preconditions.checkNotNull(cbuf); + } + + public void write(char[] cbuf, int off, int len) + { + Preconditions.checkPositionIndexes(off, off + len, cbuf.length); + } + + public void write(String str) + { + Preconditions.checkNotNull(str); + } + + public void write(String str, int off, int len) + { + Preconditions.checkPositionIndexes(off, off + len, str.length()); + } + + public Writer append(CharSequence csq) + { + Preconditions.checkNotNull(csq); + return this; + } + + public Writer append(CharSequence csq, int start, int end) + { + Preconditions.checkPositionIndexes(start, end, csq.length()); + return this; + } + + public Writer append(char c) + { + return this; + } + + + + public void flush() {} + + + public void close() {} + + + public String toString() + { + return "CharStreams.nullWriter()"; + } + } + + + + + + + + + + + public static Writer asWriter(Appendable target) + { + if ((target instanceof Writer)) { + return (Writer)target; + } + return new AppendableWriter(target); + } + + + static Reader asReader(Readable readable) + { + Preconditions.checkNotNull(readable); + if ((readable instanceof Reader)) { + return (Reader)readable; + } + new Reader() + { + public int read(char[] cbuf, int off, int len) throws IOException { + return read(CharBuffer.wrap(cbuf, off, len)); + } + + public int read(CharBuffer target) throws IOException + { + return val$readable.read(target); + } + + public void close() throws IOException + { + if ((val$readable instanceof Closeable)) { + ((Closeable)val$readable).close(); + } + } + }; + } + + + + + + + + + + + + + + + @Deprecated + public static CharSource asCharSource(InputSupplier supplier) + { + Preconditions.checkNotNull(supplier); + new CharSource() + { + public Reader openStream() throws IOException { + return CharStreams.asReader((Readable)val$supplier.getInput()); + } + + public String toString() + { + return "CharStreams.asCharSource(" + val$supplier + ")"; + } + }; + } + + + + + + + + + + + + + + + @Deprecated + public static CharSink asCharSink(OutputSupplier supplier) + { + Preconditions.checkNotNull(supplier); + new CharSink() + { + public Writer openStream() throws IOException { + return CharStreams.asWriter((Appendable)val$supplier.getOutput()); + } + + public String toString() + { + return "CharStreams.asCharSink(" + val$supplier + ")"; + } + }; + } + + + static InputSupplier asInputSupplier(CharSource source) + { + return (InputSupplier)Preconditions.checkNotNull(source); + } + + + static OutputSupplier asOutputSupplier(CharSink sink) + { + return (OutputSupplier)Preconditions.checkNotNull(sink); + } +} diff --git a/src/minecraft/com/google/common/io/Closeables.java b/src/minecraft/com/google/common/io/Closeables.java new file mode 100644 index 0000000..6a6f78c --- /dev/null +++ b/src/minecraft/com/google/common/io/Closeables.java @@ -0,0 +1,132 @@ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class Closeables +{ + @VisibleForTesting + static final Logger logger = Logger.getLogger(Closeables.class.getName()); + + + + + + + + + + + + + + + + + private Closeables() {} + + + + + + + + + + + + + + + + public static void close(@Nullable Closeable closeable, boolean swallowIOException) + throws IOException + { + if (closeable == null) { + return; + } + try { + closeable.close(); + } catch (IOException e) { + if (swallowIOException) { + logger.log(Level.WARNING, "IOException thrown while closing Closeable.", e); + } + else { + throw e; + } + } + } + + + + + + + + + + + + + + public static void closeQuietly(@Nullable InputStream inputStream) + { + try + { + close(inputStream, true); + } catch (IOException impossible) { + throw new AssertionError(impossible); + } + } + + + + + + + + + + + + + public static void closeQuietly(@Nullable Reader reader) + { + try + { + close(reader, true); + } catch (IOException impossible) { + throw new AssertionError(impossible); + } + } +} diff --git a/src/minecraft/com/google/common/io/Closer.java b/src/minecraft/com/google/common/io/Closer.java new file mode 100644 index 0000000..f9a5153 --- /dev/null +++ b/src/minecraft/com/google/common/io/Closer.java @@ -0,0 +1,293 @@ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.base.Throwables; +import java.io.Closeable; +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class Closer + implements Closeable +{ + private static final Suppressor SUPPRESSOR = SuppressingSuppressor.isAvailable() ? SuppressingSuppressor.INSTANCE : LoggingSuppressor.INSTANCE; + + @VisibleForTesting + final Suppressor suppressor; + + + public static Closer create() + { + return new Closer(SUPPRESSOR); + } + + + + + private final Deque stack = new ArrayDeque(4); + private Throwable thrown; + + @VisibleForTesting + Closer(Suppressor suppressor) { this.suppressor = ((Suppressor)Preconditions.checkNotNull(suppressor)); } + + + + + + + + + public C register(@Nullable C closeable) + { + if (closeable != null) { + stack.addFirst(closeable); + } + + return closeable; + } + + + + + + + + + + + + + public RuntimeException rethrow(Throwable e) + throws IOException + { + Preconditions.checkNotNull(e); + thrown = e; + Throwables.propagateIfPossible(e, IOException.class); + throw new RuntimeException(e); + } + + + + + + + + + + + + + + + public RuntimeException rethrow(Throwable e, Class declaredType) + throws IOException, Exception + { + Preconditions.checkNotNull(e); + thrown = e; + Throwables.propagateIfPossible(e, IOException.class); + Throwables.propagateIfPossible(e, declaredType); + throw new RuntimeException(e); + } + + + + + + + + + + + + + + + + public RuntimeException rethrow(Throwable e, Class declaredType1, Class declaredType2) + throws IOException, Exception, Exception + { + Preconditions.checkNotNull(e); + thrown = e; + Throwables.propagateIfPossible(e, IOException.class); + Throwables.propagateIfPossible(e, declaredType1, declaredType2); + throw new RuntimeException(e); + } + + + + + + + + public void close() + throws IOException + { + Throwable throwable = thrown; + + + while (!stack.isEmpty()) { + Closeable closeable = (Closeable)stack.removeFirst(); + try { + closeable.close(); + } catch (Throwable e) { + if (throwable == null) { + throwable = e; + } else { + suppressor.suppress(closeable, throwable, e); + } + } + } + + if ((thrown == null) && (throwable != null)) { + Throwables.propagateIfPossible(throwable, IOException.class); + throw new AssertionError(throwable); + } + } + + + + + + @VisibleForTesting + static abstract interface Suppressor + { + public abstract void suppress(Closeable paramCloseable, Throwable paramThrowable1, Throwable paramThrowable2); + } + + + + + @VisibleForTesting + static final class LoggingSuppressor + implements Closer.Suppressor + { + static final LoggingSuppressor INSTANCE = new LoggingSuppressor(); + + LoggingSuppressor() {} + + public void suppress(Closeable closeable, Throwable thrown, Throwable suppressed) { + Closeables.logger.log(Level.WARNING, "Suppressing exception thrown when closing " + closeable, suppressed); + } + } + + + @VisibleForTesting + static final class SuppressingSuppressor + implements Closer.Suppressor + { + SuppressingSuppressor() {} + + static final SuppressingSuppressor INSTANCE = new SuppressingSuppressor(); + + static boolean isAvailable() { + return addSuppressed != null; } + + + static final Method addSuppressed = getAddSuppressed(); + + private static Method getAddSuppressed() { + try { + return Throwable.class.getMethod("addSuppressed", new Class[] { Throwable.class }); + } catch (Throwable e) {} + return null; + } + + + + public void suppress(Closeable closeable, Throwable thrown, Throwable suppressed) + { + if (thrown == suppressed) { + return; + } + try { + addSuppressed.invoke(thrown, new Object[] { suppressed }); + } + catch (Throwable e) { + Closer.LoggingSuppressor.INSTANCE.suppress(closeable, thrown, suppressed); + } + } + } +} diff --git a/src/minecraft/com/google/common/io/CountingInputStream.java b/src/minecraft/com/google/common/io/CountingInputStream.java new file mode 100644 index 0000000..df960e3 --- /dev/null +++ b/src/minecraft/com/google/common/io/CountingInputStream.java @@ -0,0 +1,92 @@ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class CountingInputStream + extends FilterInputStream +{ + private long count; + private long mark = -1L; + + + + + + public CountingInputStream(@Nullable InputStream in) + { + super(in); + } + + public long getCount() + { + return count; + } + + public int read() throws IOException { + int result = in.read(); + if (result != -1) { + count += 1L; + } + return result; + } + + public int read(byte[] b, int off, int len) throws IOException { + int result = in.read(b, off, len); + if (result != -1) { + count += result; + } + return result; + } + + public long skip(long n) throws IOException { + long result = in.skip(n); + count += result; + return result; + } + + public synchronized void mark(int readlimit) { + in.mark(readlimit); + mark = count; + } + + public synchronized void reset() throws IOException + { + if (!in.markSupported()) { + throw new IOException("Mark not supported"); + } + if (mark == -1L) { + throw new IOException("Mark not set"); + } + + in.reset(); + count = mark; + } +} diff --git a/src/minecraft/com/google/common/io/CountingOutputStream.java b/src/minecraft/com/google/common/io/CountingOutputStream.java new file mode 100644 index 0000000..37a09fc --- /dev/null +++ b/src/minecraft/com/google/common/io/CountingOutputStream.java @@ -0,0 +1,68 @@ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class CountingOutputStream + extends FilterOutputStream +{ + private long count; + + public CountingOutputStream(@Nullable OutputStream out) + { + super(out); + } + + public long getCount() + { + return count; + } + + public void write(byte[] b, int off, int len) throws IOException { + out.write(b, off, len); + count += len; + } + + public void write(int b) throws IOException { + out.write(b); + count += 1L; + } + + + public void close() + throws IOException + { + out.close(); + } +} diff --git a/src/minecraft/com/google/common/io/FileBackedOutputStream.java b/src/minecraft/com/google/common/io/FileBackedOutputStream.java new file mode 100644 index 0000000..a9f4736 --- /dev/null +++ b/src/minecraft/com/google/common/io/FileBackedOutputStream.java @@ -0,0 +1,212 @@ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class FileBackedOutputStream + extends OutputStream +{ + private final int fileThreshold; + private final boolean resetOnFinalize; + private final ByteSource source; + private OutputStream out; + private MemoryOutput memory; + private File file; + + private static class MemoryOutput + extends ByteArrayOutputStream + { + private MemoryOutput() {} + + byte[] getBuffer() + { + return buf; + } + + int getCount() { + return count; + } + } + + @VisibleForTesting + synchronized File getFile() { + return file; + } + + + + + + + + + public FileBackedOutputStream(int fileThreshold) + { + this(fileThreshold, false); + } + + + + + + + + + + + + public FileBackedOutputStream(int fileThreshold, boolean resetOnFinalize) + { + this.fileThreshold = fileThreshold; + this.resetOnFinalize = resetOnFinalize; + memory = new MemoryOutput(null); + out = memory; + + if (resetOnFinalize) { + source = new ByteSource() + { + public InputStream openStream() throws IOException { + return FileBackedOutputStream.this.openInputStream(); + } + + protected void finalize() { + try { + reset(); + } catch (Throwable t) { + t.printStackTrace(System.err); + } + } + }; + } else { + source = new ByteSource() + { + public InputStream openStream() throws IOException { + return FileBackedOutputStream.this.openInputStream(); + } + }; + } + } + + + + + + + public ByteSource asByteSource() + { + return source; + } + + private synchronized InputStream openInputStream() throws IOException { + if (file != null) { + return new FileInputStream(file); + } + return new ByteArrayInputStream(memory.getBuffer(), 0, memory.getCount()); + } + + + + + + + + public synchronized void reset() + throws IOException + { + try + { + close(); + } finally { File deleteMe; + if (memory == null) { + memory = new MemoryOutput(null); + } else { + memory.reset(); + } + out = memory; + if (file != null) { + File deleteMe = file; + file = null; + if (!deleteMe.delete()) { + throw new IOException("Could not delete: " + deleteMe); + } + } + } + } + + public synchronized void write(int b) throws IOException { + update(1); + out.write(b); + } + + public synchronized void write(byte[] b) throws IOException { + write(b, 0, b.length); + } + + public synchronized void write(byte[] b, int off, int len) throws IOException + { + update(len); + out.write(b, off, len); + } + + public synchronized void close() throws IOException { + out.close(); + } + + public synchronized void flush() throws IOException { + out.flush(); + } + + + + private void update(int len) + throws IOException + { + if ((file == null) && (memory.getCount() + len > fileThreshold)) { + File temp = File.createTempFile("FileBackedOutputStream", null); + if (resetOnFinalize) + { + + temp.deleteOnExit(); + } + FileOutputStream transfer = new FileOutputStream(temp); + transfer.write(memory.getBuffer(), 0, memory.getCount()); + transfer.flush(); + + + out = transfer; + file = temp; + memory = null; + } + } +} diff --git a/src/minecraft/com/google/common/io/FileWriteMode.java b/src/minecraft/com/google/common/io/FileWriteMode.java new file mode 100644 index 0000000..69e556a --- /dev/null +++ b/src/minecraft/com/google/common/io/FileWriteMode.java @@ -0,0 +1,8 @@ +package com.google.common.io; + +public enum FileWriteMode +{ + APPEND; + + private FileWriteMode() {} +} diff --git a/src/minecraft/com/google/common/io/Files.java b/src/minecraft/com/google/common/io/Files.java new file mode 100644 index 0000000..30d32ae --- /dev/null +++ b/src/minecraft/com/google/common/io/Files.java @@ -0,0 +1,1039 @@ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.base.Joiner; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import com.google.common.collect.TreeTraverser; +import com.google.common.hash.HashCode; +import com.google.common.hash.HashFunction; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.Closeable; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.RandomAccessFile; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.channels.FileChannel.MapMode; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class Files +{ + private static final int TEMP_DIR_ATTEMPTS = 10000; + + private Files() {} + + public static BufferedReader newReader(File file, Charset charset) + throws FileNotFoundException + { + Preconditions.checkNotNull(file); + Preconditions.checkNotNull(charset); + return new BufferedReader(new InputStreamReader(new FileInputStream(file), charset)); + } + + + + + + + + + + + public static BufferedWriter newWriter(File file, Charset charset) + throws FileNotFoundException + { + Preconditions.checkNotNull(file); + Preconditions.checkNotNull(charset); + return new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), charset)); + } + + + + + + + public static ByteSource asByteSource(File file) + { + return new FileByteSource(file, null); + } + + private static final class FileByteSource extends ByteSource + { + private final File file; + + private FileByteSource(File file) { + this.file = ((File)Preconditions.checkNotNull(file)); + } + + public FileInputStream openStream() throws IOException + { + return new FileInputStream(file); + } + + public long size() throws IOException + { + if (!file.isFile()) { + throw new FileNotFoundException(file.toString()); + } + return file.length(); + } + + public byte[] read() throws IOException + { + Closer closer = Closer.create(); + try { + FileInputStream in = (FileInputStream)closer.register(openStream()); + return Files.readFile(in, in.getChannel().size()); + } catch (Throwable e) { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } + + public String toString() + { + return "Files.asByteSource(" + file + ")"; + } + } + + + + + + + static byte[] readFile(InputStream in, long expectedSize) + throws IOException + { + if (expectedSize > 2147483647L) { + throw new OutOfMemoryError("file is too large to fit in a byte array: " + expectedSize + " bytes"); + } + + + + + return expectedSize == 0L ? ByteStreams.toByteArray(in) : ByteStreams.toByteArray(in, (int)expectedSize); + } + + + + + + + + + + + + public static ByteSink asByteSink(File file, FileWriteMode... modes) + { + return new FileByteSink(file, modes, null); + } + + private static final class FileByteSink extends ByteSink + { + private final File file; + private final ImmutableSet modes; + + private FileByteSink(File file, FileWriteMode... modes) { + this.file = ((File)Preconditions.checkNotNull(file)); + this.modes = ImmutableSet.copyOf(modes); + } + + public FileOutputStream openStream() throws IOException + { + return new FileOutputStream(file, modes.contains(FileWriteMode.APPEND)); + } + + public String toString() + { + return "Files.asByteSink(" + file + ", " + modes + ")"; + } + } + + + + + + + public static CharSource asCharSource(File file, Charset charset) + { + return asByteSource(file).asCharSource(charset); + } + + + + + + + + + + + + public static CharSink asCharSink(File file, Charset charset, FileWriteMode... modes) + { + return asByteSink(file, modes).asCharSink(charset); + } + + + + + + + + + + + @Deprecated + public static InputSupplier newInputStreamSupplier(File file) + { + return ByteStreams.asInputSupplier(asByteSource(file)); + } + + + + + + + + + + + @Deprecated + public static OutputSupplier newOutputStreamSupplier(File file) + { + return newOutputStreamSupplier(file, false); + } + + + + + + + + + + + + + + @Deprecated + public static OutputSupplier newOutputStreamSupplier(File file, boolean append) + { + return ByteStreams.asOutputSupplier(asByteSink(file, modes(append))); + } + + private static FileWriteMode[] modes(boolean append) { + return append ? new FileWriteMode[] { FileWriteMode.APPEND } : new FileWriteMode[0]; + } + + + + + + + + + + + + + + + @Deprecated + public static InputSupplier newReaderSupplier(File file, Charset charset) + { + return CharStreams.asInputSupplier(asCharSource(file, charset)); + } + + + + + + + + + + + + + @Deprecated + public static OutputSupplier newWriterSupplier(File file, Charset charset) + { + return newWriterSupplier(file, charset, false); + } + + + + + + + + + + + + + + + + @Deprecated + public static OutputSupplier newWriterSupplier(File file, Charset charset, boolean append) + { + return CharStreams.asOutputSupplier(asCharSink(file, charset, modes(append))); + } + + + + + + + + + public static byte[] toByteArray(File file) + throws IOException + { + return asByteSource(file).read(); + } + + + + + + + + + + public static String toString(File file, Charset charset) + throws IOException + { + return asCharSource(file, charset).read(); + } + + + + + + + + + + + + @Deprecated + public static void copy(InputSupplier from, File to) + throws IOException + { + ByteStreams.asByteSource(from).copyTo(asByteSink(to, new FileWriteMode[0])); + } + + + + + + + public static void write(byte[] from, File to) + throws IOException + { + asByteSink(to, new FileWriteMode[0]).write(from); + } + + + + + + + + + + + + @Deprecated + public static void copy(File from, OutputSupplier to) + throws IOException + { + asByteSource(from).copyTo(ByteStreams.asByteSink(to)); + } + + + + + + + public static void copy(File from, OutputStream to) + throws IOException + { + asByteSource(from).copyTo(to); + } + + + + + + + + + + + + + public static void copy(File from, File to) + throws IOException + { + Preconditions.checkArgument(!from.equals(to), "Source %s and destination %s must be different", new Object[] { from, to }); + + asByteSource(from).copyTo(asByteSink(to, new FileWriteMode[0])); + } + + + + + + + + + + + + + + + @Deprecated + public static void copy(InputSupplier from, File to, Charset charset) + throws IOException + { + CharStreams.asCharSource(from).copyTo(asCharSink(to, charset, new FileWriteMode[0])); + } + + + + + + + + + + + public static void write(CharSequence from, File to, Charset charset) + throws IOException + { + asCharSink(to, charset, new FileWriteMode[0]).write(from); + } + + + + + + + + + + + public static void append(CharSequence from, File to, Charset charset) + throws IOException + { + write(from, to, charset, true); + } + + + + + + + + + + + + private static void write(CharSequence from, File to, Charset charset, boolean append) + throws IOException + { + asCharSink(to, charset, modes(append)).write(from); + } + + + + + + + + + + + + + + + @Deprecated + public static void copy(File from, Charset charset, OutputSupplier to) + throws IOException + { + asCharSource(from, charset).copyTo(CharStreams.asCharSink(to)); + } + + + + + + + + + + + public static void copy(File from, Charset charset, Appendable to) + throws IOException + { + asCharSource(from, charset).copyTo(to); + } + + + + + public static boolean equal(File file1, File file2) + throws IOException + { + Preconditions.checkNotNull(file1); + Preconditions.checkNotNull(file2); + if ((file1 == file2) || (file1.equals(file2))) { + return true; + } + + + + + + + long len1 = file1.length(); + long len2 = file2.length(); + if ((len1 != 0L) && (len2 != 0L) && (len1 != len2)) { + return false; + } + return asByteSource(file1).contentEquals(asByteSource(file2)); + } + + + + + + + + + + + + + + + + + + + + public static File createTempDir() + { + File baseDir = new File(System.getProperty("java.io.tmpdir")); + String baseName = System.currentTimeMillis() + "-"; + + for (int counter = 0; counter < 10000; counter++) { + File tempDir = new File(baseDir, baseName + counter); + if (tempDir.mkdir()) { + return tempDir; + } + } + throw new IllegalStateException("Failed to create directory within 10000 attempts (tried " + baseName + "0 to " + baseName + 9999 + ')'); + } + + + + + + + + + public static void touch(File file) + throws IOException + { + Preconditions.checkNotNull(file); + if ((!file.createNewFile()) && (!file.setLastModified(System.currentTimeMillis()))) + { + throw new IOException("Unable to update modification time of " + file); + } + } + + + + + + + + + + public static void createParentDirs(File file) + throws IOException + { + Preconditions.checkNotNull(file); + File parent = file.getCanonicalFile().getParentFile(); + if (parent == null) + { + + + + + + + return; + } + parent.mkdirs(); + if (!parent.isDirectory()) { + throw new IOException("Unable to create parent directories of " + file); + } + } + + + + + + + + + + + public static void move(File from, File to) + throws IOException + { + Preconditions.checkNotNull(from); + Preconditions.checkNotNull(to); + Preconditions.checkArgument(!from.equals(to), "Source %s and destination %s must be different", new Object[] { from, to }); + + + if (!from.renameTo(to)) { + copy(from, to); + if (!from.delete()) { + if (!to.delete()) { + throw new IOException("Unable to delete " + to); + } + throw new IOException("Unable to delete " + from); + } + } + } + + + + + + + + + + + + public static String readFirstLine(File file, Charset charset) + throws IOException + { + return asCharSource(file, charset).readFirstLine(); + } + + + + + + + + + + + + + + + + + + public static List readLines(File file, Charset charset) + throws IOException + { + (List)readLines(file, charset, new LineProcessor() { + final List result = Lists.newArrayList(); + + public boolean processLine(String line) + { + result.add(line); + return true; + } + + public List getResult() + { + return result; + } + }); + } + + + + + + + + + + + + public static T readLines(File file, Charset charset, LineProcessor callback) + throws IOException + { + return CharStreams.readLines(newReaderSupplier(file, charset), callback); + } + + + + + + + + + + + + public static T readBytes(File file, ByteProcessor processor) + throws IOException + { + return ByteStreams.readBytes(newInputStreamSupplier(file), processor); + } + + + + + + + + + + public static HashCode hash(File file, HashFunction hashFunction) + throws IOException + { + return asByteSource(file).hash(hashFunction); + } + + + + + + + + + + + + + + + + public static MappedByteBuffer map(File file) + throws IOException + { + Preconditions.checkNotNull(file); + return map(file, FileChannel.MapMode.READ_ONLY); + } + + + + + + + + + + + + + + + + + + + public static MappedByteBuffer map(File file, FileChannel.MapMode mode) + throws IOException + { + Preconditions.checkNotNull(file); + Preconditions.checkNotNull(mode); + if (!file.exists()) { + throw new FileNotFoundException(file.toString()); + } + return map(file, mode, file.length()); + } + + + + + + + + + + + + + + + + + + + + + + public static MappedByteBuffer map(File file, FileChannel.MapMode mode, long size) + throws FileNotFoundException, IOException + { + Preconditions.checkNotNull(file); + Preconditions.checkNotNull(mode); + + Closer closer = Closer.create(); + try { + RandomAccessFile raf = (RandomAccessFile)closer.register(new RandomAccessFile(file, mode == FileChannel.MapMode.READ_ONLY ? "r" : "rw")); + + return map(raf, mode, size); + } catch (Throwable e) { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } + + private static MappedByteBuffer map(RandomAccessFile raf, FileChannel.MapMode mode, long size) throws IOException + { + Closer closer = Closer.create(); + try { + FileChannel channel = (FileChannel)closer.register(raf.getChannel()); + return channel.map(mode, 0L, size); + } catch (Throwable e) { + throw closer.rethrow(e); + } finally { + closer.close(); + } + } + + + + + + + + + + + + + + + + + + + + + + public static String simplifyPath(String pathname) + { + Preconditions.checkNotNull(pathname); + if (pathname.length() == 0) { + return "."; + } + + + Iterable components = Splitter.on('/').omitEmptyStrings().split(pathname); + + List path = new ArrayList(); + + + for (String component : components) { + if (!component.equals(".")) + { + if (component.equals("..")) { + if ((path.size() > 0) && (!((String)path.get(path.size() - 1)).equals(".."))) { + path.remove(path.size() - 1); + } else { + path.add(".."); + } + } else { + path.add(component); + } + } + } + + String result = Joiner.on('/').join(path); + if (pathname.charAt(0) == '/') { + result = "/" + result; + } + + while (result.startsWith("/../")) { + result = result.substring(3); + } + if (result.equals("/..")) { + result = "/"; + } else if ("".equals(result)) { + result = "."; + } + + return result; + } + + + + + + + + public static String getFileExtension(String fullName) + { + Preconditions.checkNotNull(fullName); + String fileName = new File(fullName).getName(); + int dotIndex = fileName.lastIndexOf('.'); + return dotIndex == -1 ? "" : fileName.substring(dotIndex + 1); + } + + + + + + + + + + + public static String getNameWithoutExtension(String file) + { + Preconditions.checkNotNull(file); + String fileName = new File(file).getName(); + int dotIndex = fileName.lastIndexOf('.'); + return dotIndex == -1 ? fileName : fileName.substring(0, dotIndex); + } + + + + + + + + + + + public static TreeTraverser fileTreeTraverser() + { + return FILE_TREE_TRAVERSER; + } + + private static final TreeTraverser FILE_TREE_TRAVERSER = new TreeTraverser() + { + public Iterable children(File file) + { + if (file.isDirectory()) { + File[] files = file.listFiles(); + if (files != null) { + return Collections.unmodifiableList(Arrays.asList(files)); + } + } + + return Collections.emptyList(); + } + + public String toString() + { + return "Files.fileTreeTraverser()"; + } + }; + + + + + + public static Predicate isDirectory() + { + return FilePredicate.IS_DIRECTORY; + } + + + + + + public static Predicate isFile() + { + return FilePredicate.IS_FILE; + } + + private static abstract enum FilePredicate implements Predicate { + IS_DIRECTORY, + + + + + + + + + + + + IS_FILE; + + private FilePredicate() {} + } +} diff --git a/src/minecraft/com/google/common/io/Flushables.java b/src/minecraft/com/google/common/io/Flushables.java new file mode 100644 index 0000000..1c55dfd --- /dev/null +++ b/src/minecraft/com/google/common/io/Flushables.java @@ -0,0 +1,80 @@ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import java.io.Flushable; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class Flushables +{ + private static final Logger logger = Logger.getLogger(Flushables.class.getName()); + + + + + + + + + private Flushables() {} + + + + + + + + public static void flush(Flushable flushable, boolean swallowIOException) + throws IOException + { + try + { + flushable.flush(); + } catch (IOException e) { + if (swallowIOException) { + logger.log(Level.WARNING, "IOException thrown while flushing Flushable.", e); + } + else { + throw e; + } + } + } + + + + + + public static void flushQuietly(Flushable flushable) + { + try + { + flush(flushable, true); + } catch (IOException e) { + logger.log(Level.SEVERE, "IOException should not have been thrown.", e); + } + } +} diff --git a/src/minecraft/com/google/common/io/GwtWorkarounds.java b/src/minecraft/com/google/common/io/GwtWorkarounds.java new file mode 100644 index 0000000..921d248 --- /dev/null +++ b/src/minecraft/com/google/common/io/GwtWorkarounds.java @@ -0,0 +1,273 @@ +package com.google.common.io; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +final class GwtWorkarounds +{ + private GwtWorkarounds() {} + + @GwtIncompatible("Reader") + static CharInput asCharInput(Reader reader) + { + Preconditions.checkNotNull(reader); + new CharInput() + { + public int read() throws IOException { + return val$reader.read(); + } + + public void close() throws IOException + { + val$reader.close(); + } + }; + } + + + + static CharInput asCharInput(CharSequence chars) + { + Preconditions.checkNotNull(chars); + new CharInput() { + int index = 0; + + public int read() + { + if (index < val$chars.length()) { + return val$chars.charAt(index++); + } + return -1; + } + + + public void close() + { + index = val$chars.length(); + } + }; + } + + + + + + + + + + + + @GwtIncompatible("InputStream") + static InputStream asInputStream(ByteInput input) + { + Preconditions.checkNotNull(input); + new InputStream() + { + public int read() throws IOException { + return val$input.read(); + } + + public int read(byte[] b, int off, int len) throws IOException + { + Preconditions.checkNotNull(b); + Preconditions.checkPositionIndexes(off, off + len, b.length); + if (len == 0) { + return 0; + } + int firstByte = read(); + if (firstByte == -1) { + return -1; + } + b[off] = ((byte)firstByte); + for (int dst = 1; dst < len; dst++) { + int readByte = read(); + if (readByte == -1) { + return dst; + } + b[(off + dst)] = ((byte)readByte); + } + return len; + } + + public void close() throws IOException + { + val$input.close(); + } + }; + } + + + + + + + + + + + + + @GwtIncompatible("OutputStream") + static OutputStream asOutputStream(ByteOutput output) + { + Preconditions.checkNotNull(output); + new OutputStream() + { + public void write(int b) throws IOException { + val$output.write((byte)b); + } + + public void flush() throws IOException + { + val$output.flush(); + } + + public void close() throws IOException + { + val$output.close(); + } + }; + } + + + + + + + + + + + + + @GwtIncompatible("Writer") + static CharOutput asCharOutput(Writer writer) + { + Preconditions.checkNotNull(writer); + new CharOutput() + { + public void write(char c) throws IOException { + val$writer.append(c); + } + + public void flush() throws IOException + { + val$writer.flush(); + } + + public void close() throws IOException + { + val$writer.close(); + } + }; + } + + + + + static CharOutput stringBuilderOutput(int initialSize) + { + StringBuilder builder = new StringBuilder(initialSize); + new CharOutput() + { + public void write(char c) + { + val$builder.append(c); + } + + + public void flush() {} + + + public void close() {} + + public String toString() + { + return val$builder.toString(); + } + }; + } + + static abstract interface CharOutput + { + public abstract void write(char paramChar) + throws IOException; + + public abstract void flush() + throws IOException; + + public abstract void close() + throws IOException; + } + + static abstract interface ByteOutput + { + public abstract void write(byte paramByte) + throws IOException; + + public abstract void flush() + throws IOException; + + public abstract void close() + throws IOException; + } + + static abstract interface ByteInput + { + public abstract int read() + throws IOException; + + public abstract void close() + throws IOException; + } + + static abstract interface CharInput + { + public abstract int read() + throws IOException; + + public abstract void close() + throws IOException; + } +} diff --git a/src/minecraft/com/google/common/io/InputSupplier.java b/src/minecraft/com/google/common/io/InputSupplier.java new file mode 100644 index 0000000..909a584 --- /dev/null +++ b/src/minecraft/com/google/common/io/InputSupplier.java @@ -0,0 +1,10 @@ +package com.google.common.io; + +import java.io.IOException; + +@Deprecated +public abstract interface InputSupplier +{ + public abstract T getInput() + throws IOException; +} diff --git a/src/minecraft/com/google/common/io/LineBuffer.java b/src/minecraft/com/google/common/io/LineBuffer.java new file mode 100644 index 0000000..72a020e --- /dev/null +++ b/src/minecraft/com/google/common/io/LineBuffer.java @@ -0,0 +1,111 @@ +package com.google.common.io; + +import java.io.IOException; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +abstract class LineBuffer +{ + private StringBuilder line = new StringBuilder(); + + + + private boolean sawReturn; + + + + + LineBuffer() {} + + + + protected void add(char[] cbuf, int off, int len) + throws IOException + { + int pos = off; + if ((sawReturn) && (len > 0)) + { + if (finishLine(cbuf[pos] == '\n')) { + pos++; + } + } + + int start = pos; + for (int end = off + len; pos < end; pos++) { + switch (cbuf[pos]) { + case '\r': + line.append(cbuf, start, pos - start); + sawReturn = true; + if (pos + 1 < end) { + if (finishLine(cbuf[(pos + 1)] == '\n')) { + pos++; + } + } + start = pos + 1; + break; + + case '\n': + line.append(cbuf, start, pos - start); + finishLine(true); + start = pos + 1; + } + + } + + + + line.append(cbuf, start, off + len - start); + } + + private boolean finishLine(boolean sawNewline) throws IOException + { + handleLine(line.toString(), sawNewline ? "\n" : sawReturn ? "\r" : sawNewline ? "\r\n" : ""); + + + line = new StringBuilder(); + sawReturn = false; + return sawNewline; + } + + + + + + + protected void finish() + throws IOException + { + if ((sawReturn) || (line.length() > 0)) { + finishLine(false); + } + } + + protected abstract void handleLine(String paramString1, String paramString2) + throws IOException; +} diff --git a/src/minecraft/com/google/common/io/LineProcessor.java b/src/minecraft/com/google/common/io/LineProcessor.java new file mode 100644 index 0000000..7e82d25 --- /dev/null +++ b/src/minecraft/com/google/common/io/LineProcessor.java @@ -0,0 +1,13 @@ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import java.io.IOException; + +@Beta +public abstract interface LineProcessor +{ + public abstract boolean processLine(String paramString) + throws IOException; + + public abstract T getResult(); +} diff --git a/src/minecraft/com/google/common/io/LineReader.java b/src/minecraft/com/google/common/io/LineReader.java new file mode 100644 index 0000000..183056f --- /dev/null +++ b/src/minecraft/com/google/common/io/LineReader.java @@ -0,0 +1,87 @@ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import java.io.IOException; +import java.io.Reader; +import java.nio.CharBuffer; +import java.util.LinkedList; +import java.util.Queue; + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class LineReader +{ + private final Readable readable; + private final Reader reader; + private final char[] buf = new char['က']; + private final CharBuffer cbuf = CharBuffer.wrap(buf); + + private final Queue lines = new LinkedList(); + private final LineBuffer lineBuf = new LineBuffer() { + protected void handleLine(String line, String end) { + lines.add(line); + } + }; + + + + + public LineReader(Readable readable) + { + this.readable = ((Readable)Preconditions.checkNotNull(readable)); + reader = ((readable instanceof Reader) ? (Reader)readable : null); + } + + + + + + + + + + + public String readLine() + throws IOException + { + while (lines.peek() == null) { + cbuf.clear(); + + + int read = reader != null ? reader.read(buf, 0, buf.length) : readable.read(cbuf); + + + if (read == -1) { + lineBuf.finish(); + break; + } + lineBuf.add(buf, 0, read); + } + return (String)lines.poll(); + } +} diff --git a/src/minecraft/com/google/common/io/LittleEndianDataInputStream.java b/src/minecraft/com/google/common/io/LittleEndianDataInputStream.java new file mode 100644 index 0000000..d8eb234 --- /dev/null +++ b/src/minecraft/com/google/common/io/LittleEndianDataInputStream.java @@ -0,0 +1,231 @@ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.primitives.Ints; +import com.google.common.primitives.Longs; +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.EOFException; +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class LittleEndianDataInputStream + extends FilterInputStream + implements DataInput +{ + public LittleEndianDataInputStream(InputStream in) + { + super((InputStream)Preconditions.checkNotNull(in)); + } + + + + + public String readLine() + { + throw new UnsupportedOperationException("readLine is not supported"); + } + + public void readFully(byte[] b) throws IOException + { + ByteStreams.readFully(this, b); + } + + public void readFully(byte[] b, int off, int len) throws IOException + { + ByteStreams.readFully(this, b, off, len); + } + + public int skipBytes(int n) throws IOException + { + return (int)in.skip(n); + } + + public int readUnsignedByte() throws IOException + { + int b1 = in.read(); + if (0 > b1) { + throw new EOFException(); + } + + return b1; + } + + + + + + + + + + public int readUnsignedShort() + throws IOException + { + byte b1 = readAndCheckByte(); + byte b2 = readAndCheckByte(); + + return Ints.fromBytes((byte)0, (byte)0, b2, b1); + } + + + + + + + + + public int readInt() + throws IOException + { + byte b1 = readAndCheckByte(); + byte b2 = readAndCheckByte(); + byte b3 = readAndCheckByte(); + byte b4 = readAndCheckByte(); + + return Ints.fromBytes(b4, b3, b2, b1); + } + + + + + + + + + public long readLong() + throws IOException + { + byte b1 = readAndCheckByte(); + byte b2 = readAndCheckByte(); + byte b3 = readAndCheckByte(); + byte b4 = readAndCheckByte(); + byte b5 = readAndCheckByte(); + byte b6 = readAndCheckByte(); + byte b7 = readAndCheckByte(); + byte b8 = readAndCheckByte(); + + return Longs.fromBytes(b8, b7, b6, b5, b4, b3, b2, b1); + } + + + + + + + + + public float readFloat() + throws IOException + { + return Float.intBitsToFloat(readInt()); + } + + + + + + + + + + public double readDouble() + throws IOException + { + return Double.longBitsToDouble(readLong()); + } + + public String readUTF() throws IOException + { + return new DataInputStream(in).readUTF(); + } + + + + + + + + + public short readShort() + throws IOException + { + return (short)readUnsignedShort(); + } + + + + + + + + + public char readChar() + throws IOException + { + return (char)readUnsignedShort(); + } + + public byte readByte() throws IOException + { + return (byte)readUnsignedByte(); + } + + public boolean readBoolean() throws IOException + { + return readUnsignedByte() != 0; + } + + + + + + + + private byte readAndCheckByte() + throws IOException, EOFException + { + int b1 = in.read(); + + if (-1 == b1) { + throw new EOFException(); + } + + return (byte)b1; + } +} diff --git a/src/minecraft/com/google/common/io/LittleEndianDataOutputStream.java b/src/minecraft/com/google/common/io/LittleEndianDataOutputStream.java new file mode 100644 index 0000000..bba77aa --- /dev/null +++ b/src/minecraft/com/google/common/io/LittleEndianDataOutputStream.java @@ -0,0 +1,171 @@ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.primitives.Longs; +import java.io.DataOutput; +import java.io.DataOutputStream; +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public class LittleEndianDataOutputStream + extends FilterOutputStream + implements DataOutput +{ + public LittleEndianDataOutputStream(OutputStream out) + { + super(new DataOutputStream((OutputStream)Preconditions.checkNotNull(out))); + } + + public void write(byte[] b, int off, int len) throws IOException + { + out.write(b, off, len); + } + + public void writeBoolean(boolean v) throws IOException { + ((DataOutputStream)out).writeBoolean(v); + } + + public void writeByte(int v) throws IOException { + ((DataOutputStream)out).writeByte(v); + } + + + + + @Deprecated + public void writeBytes(String s) + throws IOException + { + ((DataOutputStream)out).writeBytes(s); + } + + + + + + public void writeChar(int v) + throws IOException + { + writeShort(v); + } + + + + + + + public void writeChars(String s) + throws IOException + { + for (int i = 0; i < s.length(); i++) { + writeChar(s.charAt(i)); + } + } + + + + + + + public void writeDouble(double v) + throws IOException + { + writeLong(Double.doubleToLongBits(v)); + } + + + + + + + public void writeFloat(float v) + throws IOException + { + writeInt(Float.floatToIntBits(v)); + } + + + + + + + public void writeInt(int v) + throws IOException + { + out.write(0xFF & v); + out.write(0xFF & v >> 8); + out.write(0xFF & v >> 16); + out.write(0xFF & v >> 24); + } + + + + + + + public void writeLong(long v) + throws IOException + { + byte[] bytes = Longs.toByteArray(Long.reverseBytes(v)); + write(bytes, 0, bytes.length); + } + + + + + + + public void writeShort(int v) + throws IOException + { + out.write(0xFF & v); + out.write(0xFF & v >> 8); + } + + public void writeUTF(String str) throws IOException { + ((DataOutputStream)out).writeUTF(str); + } + + + public void close() + throws IOException + { + out.close(); + } +} diff --git a/src/minecraft/com/google/common/io/MultiInputStream.java b/src/minecraft/com/google/common/io/MultiInputStream.java new file mode 100644 index 0000000..bb39c5a --- /dev/null +++ b/src/minecraft/com/google/common/io/MultiInputStream.java @@ -0,0 +1,118 @@ +package com.google.common.io; + +import com.google.common.base.Preconditions; +import java.io.IOException; +import java.io.InputStream; +import java.util.Iterator; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +final class MultiInputStream + extends InputStream +{ + private Iterator it; + private InputStream in; + + public MultiInputStream(Iterator it) + throws IOException + { + this.it = ((Iterator)Preconditions.checkNotNull(it)); + advance(); + } + + public void close() throws IOException { + if (in != null) { + try { + in.close(); + } finally { + in = null; + } + } + } + + + private void advance() + throws IOException + { + close(); + if (it.hasNext()) { + in = ((ByteSource)it.next()).openStream(); + } + } + + public int available() throws IOException { + if (in == null) { + return 0; + } + return in.available(); + } + + public boolean markSupported() { + return false; + } + + public int read() throws IOException { + if (in == null) { + return -1; + } + int result = in.read(); + if (result == -1) { + advance(); + return read(); + } + return result; + } + + public int read(@Nullable byte[] b, int off, int len) throws IOException { + if (in == null) { + return -1; + } + int result = in.read(b, off, len); + if (result == -1) { + advance(); + return read(b, off, len); + } + return result; + } + + public long skip(long n) throws IOException { + if ((in == null) || (n <= 0L)) { + return 0L; + } + long result = in.skip(n); + if (result != 0L) { + return result; + } + if (read() == -1) { + return 0L; + } + return 1L + in.skip(n - 1L); + } +} diff --git a/src/minecraft/com/google/common/io/MultiReader.java b/src/minecraft/com/google/common/io/MultiReader.java new file mode 100644 index 0000000..bea247b --- /dev/null +++ b/src/minecraft/com/google/common/io/MultiReader.java @@ -0,0 +1,91 @@ +package com.google.common.io; + +import com.google.common.base.Preconditions; +import java.io.IOException; +import java.io.Reader; +import java.util.Iterator; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + +class MultiReader + extends Reader +{ + private final Iterator it; + private Reader current; + + MultiReader(Iterator readers) + throws IOException + { + it = readers; + advance(); + } + + + private void advance() + throws IOException + { + close(); + if (it.hasNext()) { + current = ((CharSource)it.next()).openStream(); + } + } + + public int read(@Nullable char[] cbuf, int off, int len) throws IOException { + if (current == null) { + return -1; + } + int result = current.read(cbuf, off, len); + if (result == -1) { + advance(); + return read(cbuf, off, len); + } + return result; + } + + public long skip(long n) throws IOException { + Preconditions.checkArgument(n >= 0L, "n is negative"); + if (n > 0L) { + while (current != null) { + long result = current.skip(n); + if (result > 0L) { + return result; + } + advance(); + } + } + return 0L; + } + + public boolean ready() throws IOException { + return (current != null) && (current.ready()); + } + + public void close() throws IOException { + if (current != null) { + try { + current.close(); + } finally { + current = null; + } + } + } +} diff --git a/src/minecraft/com/google/common/io/OutputSupplier.java b/src/minecraft/com/google/common/io/OutputSupplier.java new file mode 100644 index 0000000..3faa491 --- /dev/null +++ b/src/minecraft/com/google/common/io/OutputSupplier.java @@ -0,0 +1,10 @@ +package com.google.common.io; + +import java.io.IOException; + +@Deprecated +public abstract interface OutputSupplier +{ + public abstract T getOutput() + throws IOException; +} diff --git a/src/minecraft/com/google/common/io/PatternFilenameFilter.java b/src/minecraft/com/google/common/io/PatternFilenameFilter.java new file mode 100644 index 0000000..1439e8e --- /dev/null +++ b/src/minecraft/com/google/common/io/PatternFilenameFilter.java @@ -0,0 +1,62 @@ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import java.io.File; +import java.io.FilenameFilter; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class PatternFilenameFilter + implements FilenameFilter +{ + private final Pattern pattern; + + public PatternFilenameFilter(String patternStr) + { + this(Pattern.compile(patternStr)); + } + + + + + public PatternFilenameFilter(Pattern pattern) + { + this.pattern = ((Pattern)Preconditions.checkNotNull(pattern)); + } + + public boolean accept(@Nullable File dir, String fileName) { + return pattern.matcher(fileName).matches(); + } +} diff --git a/src/minecraft/com/google/common/io/Resources.java b/src/minecraft/com/google/common/io/Resources.java new file mode 100644 index 0000000..794359e --- /dev/null +++ b/src/minecraft/com/google/common/io/Resources.java @@ -0,0 +1,245 @@ +package com.google.common.io; + +import com.google.common.annotations.Beta; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.URL; +import java.nio.charset.Charset; +import java.util.List; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class Resources +{ + private Resources() {} + + @Deprecated + public static InputSupplier newInputStreamSupplier(URL url) + { + return ByteStreams.asInputSupplier(asByteSource(url)); + } + + + + + + public static ByteSource asByteSource(URL url) + { + return new UrlByteSource(url, null); + } + + + private static final class UrlByteSource + extends ByteSource + { + private final URL url; + + private UrlByteSource(URL url) + { + this.url = ((URL)Preconditions.checkNotNull(url)); + } + + public InputStream openStream() throws IOException + { + return url.openStream(); + } + + public String toString() + { + return "Resources.asByteSource(" + url + ")"; + } + } + + + + + + + + + + + + + @Deprecated + public static InputSupplier newReaderSupplier(URL url, Charset charset) + { + return CharStreams.asInputSupplier(asCharSource(url, charset)); + } + + + + + + + public static CharSource asCharSource(URL url, Charset charset) + { + return asByteSource(url).asCharSource(charset); + } + + + + + + + public static byte[] toByteArray(URL url) + throws IOException + { + return asByteSource(url).read(); + } + + + + + + + + + + public static String toString(URL url, Charset charset) + throws IOException + { + return asCharSource(url, charset).read(); + } + + + + + + + + + + + + public static T readLines(URL url, Charset charset, LineProcessor callback) + throws IOException + { + return CharStreams.readLines(newReaderSupplier(url, charset), callback); + } + + + + + + + + + + + + + + + + + + public static List readLines(URL url, Charset charset) + throws IOException + { + (List)readLines(url, charset, new LineProcessor() { + final List result = Lists.newArrayList(); + + public boolean processLine(String line) + { + result.add(line); + return true; + } + + public List getResult() + { + return result; + } + }); + } + + + + + + + public static void copy(URL from, OutputStream to) + throws IOException + { + asByteSource(from).copyTo(to); + } + + + + + + + + + + + + + + + public static URL getResource(String resourceName) + { + ClassLoader loader = (ClassLoader)Objects.firstNonNull(Thread.currentThread().getContextClassLoader(), Resources.class.getClassLoader()); + + + URL url = loader.getResource(resourceName); + Preconditions.checkArgument(url != null, "resource %s not found.", new Object[] { resourceName }); + return url; + } + + + + + + + public static URL getResource(Class contextClass, String resourceName) + { + URL url = contextClass.getResource(resourceName); + Preconditions.checkArgument(url != null, "resource %s relative to %s not found.", new Object[] { resourceName, contextClass.getName() }); + + return url; + } +} diff --git a/src/minecraft/com/google/common/io/package-info.java b/src/minecraft/com/google/common/io/package-info.java new file mode 100644 index 0000000..fd4f056 --- /dev/null +++ b/src/minecraft/com/google/common/io/package-info.java @@ -0,0 +1,6 @@ +package com.google.common.io; + +import javax.annotation.ParametersAreNonnullByDefault; + +@ParametersAreNonnullByDefault +abstract interface package-info {} diff --git a/src/minecraft/com/google/common/math/BigIntegerMath.java b/src/minecraft/com/google/common/math/BigIntegerMath.java new file mode 100644 index 0000000..052cb04 --- /dev/null +++ b/src/minecraft/com/google/common/math/BigIntegerMath.java @@ -0,0 +1,454 @@ +package com.google.common.math; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.RoundingMode; +import java.util.ArrayList; +import java.util.List; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public final class BigIntegerMath +{ + @VisibleForTesting + static final int SQRT2_PRECOMPUTE_THRESHOLD = 256; + + public static boolean isPowerOfTwo(BigInteger x) + { + Preconditions.checkNotNull(x); + return (x.signum() > 0) && (x.getLowestSetBit() == x.bitLength() - 1); + } + + + + + + + + + + public static int log2(BigInteger x, RoundingMode mode) + { + MathPreconditions.checkPositive("x", (BigInteger)Preconditions.checkNotNull(x)); + int logFloor = x.bitLength() - 1; + switch (1.$SwitchMap$java$math$RoundingMode[mode.ordinal()]) { + case 1: + MathPreconditions.checkRoundingUnnecessary(isPowerOfTwo(x)); + case 2: + case 3: + return logFloor; + + case 4: + case 5: + return isPowerOfTwo(x) ? logFloor : logFloor + 1; + + case 6: + case 7: + case 8: + if (logFloor < 256) { + BigInteger halfPower = SQRT2_PRECOMPUTED_BITS.shiftRight(256 - logFloor); + + if (x.compareTo(halfPower) <= 0) { + return logFloor; + } + return logFloor + 1; + } + + + + + + + + BigInteger x2 = x.pow(2); + int logX2Floor = x2.bitLength() - 1; + return logX2Floor < 2 * logFloor + 1 ? logFloor : logFloor + 1; + } + + throw new AssertionError(); + } + + + + + + + + + @VisibleForTesting + static final BigInteger SQRT2_PRECOMPUTED_BITS = new BigInteger("16a09e667f3bcc908b2fb1366ea957d3e3adec17512775099da2f590b0667322a", 16); + + + + + + + + + + @GwtIncompatible("TODO") + public static int log10(BigInteger x, RoundingMode mode) + { + MathPreconditions.checkPositive("x", x); + if (fitsInLong(x)) { + return LongMath.log10(x.longValue(), mode); + } + + int approxLog10 = (int)(log2(x, RoundingMode.FLOOR) * LN_2 / LN_10); + BigInteger approxPow = BigInteger.TEN.pow(approxLog10); + int approxCmp = approxPow.compareTo(x); + + + + + + + if (approxCmp > 0) + { + + + do + { + + approxLog10--; + approxPow = approxPow.divide(BigInteger.TEN); + approxCmp = approxPow.compareTo(x); + } while (approxCmp > 0); + } else { + BigInteger nextPow = BigInteger.TEN.multiply(approxPow); + int nextCmp = nextPow.compareTo(x); + while (nextCmp <= 0) { + approxLog10++; + approxPow = nextPow; + approxCmp = nextCmp; + nextPow = BigInteger.TEN.multiply(approxPow); + nextCmp = nextPow.compareTo(x); + } + } + + int floorLog = approxLog10; + BigInteger floorPow = approxPow; + int floorCmp = approxCmp; + + switch (1.$SwitchMap$java$math$RoundingMode[mode.ordinal()]) { + case 1: + MathPreconditions.checkRoundingUnnecessary(floorCmp == 0); + + case 2: + case 3: + return floorLog; + + case 4: + case 5: + return floorPow.equals(x) ? floorLog : floorLog + 1; + + + case 6: + case 7: + case 8: + BigInteger x2 = x.pow(2); + BigInteger halfPowerSquared = floorPow.pow(2).multiply(BigInteger.TEN); + return x2.compareTo(halfPowerSquared) <= 0 ? floorLog : floorLog + 1; + } + throw new AssertionError(); + } + + + private static final double LN_10 = Math.log(10.0D); + private static final double LN_2 = Math.log(2.0D); + + + + + + + + + @GwtIncompatible("TODO") + public static BigInteger sqrt(BigInteger x, RoundingMode mode) + { + MathPreconditions.checkNonNegative("x", x); + if (fitsInLong(x)) { + return BigInteger.valueOf(LongMath.sqrt(x.longValue(), mode)); + } + BigInteger sqrtFloor = sqrtFloor(x); + switch (1.$SwitchMap$java$math$RoundingMode[mode.ordinal()]) { + case 1: + MathPreconditions.checkRoundingUnnecessary(sqrtFloor.pow(2).equals(x)); + case 2: + case 3: + return sqrtFloor; + case 4: + case 5: + int sqrtFloorInt = sqrtFloor.intValue(); + boolean sqrtFloorIsExact = (sqrtFloorInt * sqrtFloorInt == x.intValue()) && (sqrtFloor.pow(2).equals(x)); + + + return sqrtFloorIsExact ? sqrtFloor : sqrtFloor.add(BigInteger.ONE); + case 6: + case 7: + case 8: + BigInteger halfSquare = sqrtFloor.pow(2).add(sqrtFloor); + + + + + + return halfSquare.compareTo(x) >= 0 ? sqrtFloor : sqrtFloor.add(BigInteger.ONE); + } + throw new AssertionError(); + } + + + + + + + + + + + + + + + + + + + + + + @GwtIncompatible("TODO") + private static BigInteger sqrtFloor(BigInteger x) + { + int log2 = log2(x, RoundingMode.FLOOR); + BigInteger sqrt0; BigInteger sqrt0; if (log2 < 1023) { + sqrt0 = sqrtApproxWithDoubles(x); + } else { + int shift = log2 - 52 & 0xFFFFFFFE; + + + + + sqrt0 = sqrtApproxWithDoubles(x.shiftRight(shift)).shiftLeft(shift >> 1); + } + BigInteger sqrt1 = sqrt0.add(x.divide(sqrt0)).shiftRight(1); + if (sqrt0.equals(sqrt1)) { + return sqrt0; + } + do { + sqrt0 = sqrt1; + sqrt1 = sqrt0.add(x.divide(sqrt0)).shiftRight(1); + } while (sqrt1.compareTo(sqrt0) < 0); + return sqrt0; + } + + @GwtIncompatible("TODO") + private static BigInteger sqrtApproxWithDoubles(BigInteger x) { + return DoubleMath.roundToBigInteger(Math.sqrt(DoubleUtils.bigToDouble(x)), RoundingMode.HALF_EVEN); + } + + + + + + + + @GwtIncompatible("TODO") + public static BigInteger divide(BigInteger p, BigInteger q, RoundingMode mode) + { + BigDecimal pDec = new BigDecimal(p); + BigDecimal qDec = new BigDecimal(q); + return pDec.divide(qDec, 0, mode).toBigIntegerExact(); + } + + + + + + + + + + + + + public static BigInteger factorial(int n) + { + MathPreconditions.checkNonNegative("n", n); + + + if (n < LongMath.factorials.length) { + return BigInteger.valueOf(LongMath.factorials[n]); + } + + + int approxSize = IntMath.divide(n * IntMath.log2(n, RoundingMode.CEILING), 64, RoundingMode.CEILING); + ArrayList bignums = new ArrayList(approxSize); + + + int startingNumber = LongMath.factorials.length; + long product = LongMath.factorials[(startingNumber - 1)]; + + int shift = Long.numberOfTrailingZeros(product); + product >>= shift; + + + int productBits = LongMath.log2(product, RoundingMode.FLOOR) + 1; + int bits = LongMath.log2(startingNumber, RoundingMode.FLOOR) + 1; + + int nextPowerOfTwo = 1 << bits - 1; + + + for (long num = startingNumber; num <= n; num += 1L) + { + if ((num & nextPowerOfTwo) != 0L) { + nextPowerOfTwo <<= 1; + bits++; + } + + int tz = Long.numberOfTrailingZeros(num); + long normalizedNum = num >> tz; + shift += tz; + + int normalizedBits = bits - tz; + + if (normalizedBits + productBits >= 64) { + bignums.add(BigInteger.valueOf(product)); + product = 1L; + productBits = 0; + } + product *= normalizedNum; + productBits = LongMath.log2(product, RoundingMode.FLOOR) + 1; + } + + if (product > 1L) { + bignums.add(BigInteger.valueOf(product)); + } + + return listProduct(bignums).shiftLeft(shift); + } + + static BigInteger listProduct(List nums) { + return listProduct(nums, 0, nums.size()); + } + + static BigInteger listProduct(List nums, int start, int end) { + switch (end - start) { + case 0: + return BigInteger.ONE; + case 1: + return (BigInteger)nums.get(start); + case 2: + return ((BigInteger)nums.get(start)).multiply((BigInteger)nums.get(start + 1)); + case 3: + return ((BigInteger)nums.get(start)).multiply((BigInteger)nums.get(start + 1)).multiply((BigInteger)nums.get(start + 2)); + } + + int m = end + start >>> 1; + return listProduct(nums, start, m).multiply(listProduct(nums, m, end)); + } + + + + + + + + + + public static BigInteger binomial(int n, int k) + { + MathPreconditions.checkNonNegative("n", n); + MathPreconditions.checkNonNegative("k", k); + Preconditions.checkArgument(k <= n, "k (%s) > n (%s)", new Object[] { Integer.valueOf(k), Integer.valueOf(n) }); + if (k > n >> 1) { + k = n - k; + } + if ((k < LongMath.biggestBinomials.length) && (n <= LongMath.biggestBinomials[k])) { + return BigInteger.valueOf(LongMath.binomial(n, k)); + } + + BigInteger accum = BigInteger.ONE; + + long numeratorAccum = n; + long denominatorAccum = 1L; + + int bits = LongMath.log2(n, RoundingMode.CEILING); + + int numeratorBits = bits; + + for (int i = 1; i < k; i++) { + int p = n - i; + int q = i + 1; + + + + if (numeratorBits + bits >= 63) + { + + accum = accum.multiply(BigInteger.valueOf(numeratorAccum)).divide(BigInteger.valueOf(denominatorAccum)); + + + numeratorAccum = p; + denominatorAccum = q; + numeratorBits = bits; + } + else { + numeratorAccum *= p; + denominatorAccum *= q; + numeratorBits += bits; + } + } + return accum.multiply(BigInteger.valueOf(numeratorAccum)).divide(BigInteger.valueOf(denominatorAccum)); + } + + + + @GwtIncompatible("TODO") + static boolean fitsInLong(BigInteger x) + { + return x.bitLength() <= 63; + } + + private BigIntegerMath() {} +} diff --git a/src/minecraft/com/google/common/math/DoubleMath.java b/src/minecraft/com/google/common/math/DoubleMath.java new file mode 100644 index 0000000..5d7346a --- /dev/null +++ b/src/minecraft/com/google/common/math/DoubleMath.java @@ -0,0 +1,474 @@ +package com.google.common.math; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.primitives.Booleans; +import java.math.BigInteger; +import java.math.RoundingMode; +import java.util.Iterator; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public final class DoubleMath +{ + private static final double MIN_INT_AS_DOUBLE = -2.147483648E9D; + private static final double MAX_INT_AS_DOUBLE = 2.147483647E9D; + private static final double MIN_LONG_AS_DOUBLE = -9.223372036854776E18D; + private static final double MAX_LONG_AS_DOUBLE_PLUS_ONE = 9.223372036854776E18D; + + @GwtIncompatible("#isMathematicalInteger, com.google.common.math.DoubleUtils") + static double roundIntermediate(double x, RoundingMode mode) + { + if (!DoubleUtils.isFinite(x)) { + throw new ArithmeticException("input is infinite or NaN"); + } + switch (1.$SwitchMap$java$math$RoundingMode[mode.ordinal()]) { + case 1: + MathPreconditions.checkRoundingUnnecessary(isMathematicalInteger(x)); + return x; + + case 2: + if ((x >= 0.0D) || (isMathematicalInteger(x))) { + return x; + } + return x - 1.0D; + + + case 3: + if ((x <= 0.0D) || (isMathematicalInteger(x))) { + return x; + } + return x + 1.0D; + + + case 4: + return x; + + case 5: + if (isMathematicalInteger(x)) { + return x; + } + return x + Math.copySign(1.0D, x); + + + case 6: + return Math.rint(x); + + case 7: + double z = Math.rint(x); + if (Math.abs(x - z) == 0.5D) { + return x + Math.copySign(0.5D, x); + } + return z; + + + + case 8: + double z = Math.rint(x); + if (Math.abs(x - z) == 0.5D) { + return x; + } + return z; + } + + + + throw new AssertionError(); + } + + + + + + + + + + + + + + + + @GwtIncompatible("#roundIntermediate") + public static int roundToInt(double x, RoundingMode mode) + { + double z = roundIntermediate(x, mode); + MathPreconditions.checkInRange((z > -2.147483649E9D ? 1 : 0) & (z < 2.147483648E9D ? 1 : 0)); + return (int)z; + } + + + + + + + + + + + + + + + + + + @GwtIncompatible("#roundIntermediate") + public static long roundToLong(double x, RoundingMode mode) + { + double z = roundIntermediate(x, mode); + MathPreconditions.checkInRange((-9.223372036854776E18D - z < 1.0D ? 1 : 0) & (z < 9.223372036854776E18D ? 1 : 0)); + return z; + } + + + + + + + + + + + + + + + + + + + + @GwtIncompatible("#roundIntermediate, java.lang.Math.getExponent, com.google.common.math.DoubleUtils") + public static BigInteger roundToBigInteger(double x, RoundingMode mode) + { + x = roundIntermediate(x, mode); + if (((-9.223372036854776E18D - x < 1.0D ? 1 : 0) & (x < 9.223372036854776E18D ? 1 : 0)) != 0) { + return BigInteger.valueOf(x); + } + int exponent = Math.getExponent(x); + long significand = DoubleUtils.getSignificand(x); + BigInteger result = BigInteger.valueOf(significand).shiftLeft(exponent - 52); + return x < 0.0D ? result.negate() : result; + } + + + + + @GwtIncompatible("com.google.common.math.DoubleUtils") + public static boolean isPowerOfTwo(double x) + { + return (x > 0.0D) && (DoubleUtils.isFinite(x)) && (LongMath.isPowerOfTwo(DoubleUtils.getSignificand(x))); + } + + + + + + + + + + + + + + + + public static double log2(double x) + { + return Math.log(x) / LN_2; + } + + private static final double LN_2 = Math.log(2.0D); + + + + + @VisibleForTesting + static final int MAX_FACTORIAL = 170; + + + + + @GwtIncompatible("java.lang.Math.getExponent, com.google.common.math.DoubleUtils") + public static int log2(double x, RoundingMode mode) + { + Preconditions.checkArgument((x > 0.0D) && (DoubleUtils.isFinite(x)), "x must be positive and finite"); + int exponent = Math.getExponent(x); + if (!DoubleUtils.isNormal(x)) { + return log2(x * 4.503599627370496E15D, mode) - 52; + } + + boolean increment; + + switch (1.$SwitchMap$java$math$RoundingMode[mode.ordinal()]) { + case 1: + MathPreconditions.checkRoundingUnnecessary(isPowerOfTwo(x)); + + case 2: + increment = false; + break; + case 3: + increment = !isPowerOfTwo(x); + break; + case 4: + increment = (exponent < 0 ? 1 : 0) & (!isPowerOfTwo(x) ? 1 : 0); + break; + case 5: + increment = (exponent >= 0 ? 1 : 0) & (!isPowerOfTwo(x) ? 1 : 0); + break; + case 6: + case 7: + case 8: + double xScaled = DoubleUtils.scaleNormalize(x); + + + increment = xScaled * xScaled > 2.0D; + break; + default: + throw new AssertionError(); + } + return increment ? exponent + 1 : exponent; + } + + + + + + + @GwtIncompatible("java.lang.Math.getExponent, com.google.common.math.DoubleUtils") + public static boolean isMathematicalInteger(double x) + { + return (DoubleUtils.isFinite(x)) && ((x == 0.0D) || (52 - Long.numberOfTrailingZeros(DoubleUtils.getSignificand(x)) <= Math.getExponent(x))); + } + + + + + + + + + + + + public static double factorial(int n) + { + MathPreconditions.checkNonNegative("n", n); + if (n > 170) { + return Double.POSITIVE_INFINITY; + } + + + double accum = 1.0D; + for (int i = 1 + (n & 0xFFFFFFF0); i <= n; i++) { + accum *= i; + } + return accum * everySixteenthFactorial[(n >> 4)]; + } + + + + + + @VisibleForTesting + static final double[] everySixteenthFactorial = { 1.0D, 2.0922789888E13D, 2.631308369336935E35D, 1.2413915592536073E61D, 1.2688693218588417E89D, 7.156945704626381E118D, 9.916779348709496E149D, 1.974506857221074E182D, 3.856204823625804E215D, 5.5502938327393044E249D, 4.7147236359920616E284D }; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static boolean fuzzyEquals(double a, double b, double tolerance) + { + MathPreconditions.checkNonNegative("tolerance", tolerance); + return (Math.copySign(a - b, 1.0D) <= tolerance) || (a == b) || ((Double.isNaN(a)) && (Double.isNaN(b))); + } + + + + + + + + + + + + + + + + + + + public static int fuzzyCompare(double a, double b, double tolerance) + { + if (fuzzyEquals(a, b, tolerance)) + return 0; + if (a < b) + return -1; + if (a > b) { + return 1; + } + return Booleans.compare(Double.isNaN(a), Double.isNaN(b)); + } + + @GwtIncompatible("com.google.common.math.DoubleUtils") + private static final class MeanAccumulator { + private MeanAccumulator() {} + + private long count = 0L; + private double mean = 0.0D; + + void add(double value) { + Preconditions.checkArgument(DoubleUtils.isFinite(value)); + count += 1L; + + mean += (value - mean) / count; + } + + double mean() { + Preconditions.checkArgument(count > 0L, "Cannot take mean of 0 values"); + return mean; + } + } + + + + + @GwtIncompatible("MeanAccumulator") + public static double mean(double... values) + { + MeanAccumulator accumulator = new MeanAccumulator(null); + for (double value : values) { + accumulator.add(value); + } + return accumulator.mean(); + } + + + + + @GwtIncompatible("MeanAccumulator") + public static double mean(int... values) + { + MeanAccumulator accumulator = new MeanAccumulator(null); + for (int value : values) { + accumulator.add(value); + } + return accumulator.mean(); + } + + + + + + @GwtIncompatible("MeanAccumulator") + public static double mean(long... values) + { + MeanAccumulator accumulator = new MeanAccumulator(null); + for (long value : values) { + accumulator.add(value); + } + return accumulator.mean(); + } + + + + + + @GwtIncompatible("MeanAccumulator") + public static double mean(Iterable values) + { + MeanAccumulator accumulator = new MeanAccumulator(null); + for (Number value : values) { + accumulator.add(value.doubleValue()); + } + return accumulator.mean(); + } + + + + + + @GwtIncompatible("MeanAccumulator") + public static double mean(Iterator values) + { + MeanAccumulator accumulator = new MeanAccumulator(null); + while (values.hasNext()) { + accumulator.add(((Number)values.next()).doubleValue()); + } + return accumulator.mean(); + } + + private DoubleMath() {} +} diff --git a/src/minecraft/com/google/common/math/DoubleUtils.java b/src/minecraft/com/google/common/math/DoubleUtils.java new file mode 100644 index 0000000..0e16ce4 --- /dev/null +++ b/src/minecraft/com/google/common/math/DoubleUtils.java @@ -0,0 +1,148 @@ +package com.google.common.math; + +import com.google.common.base.Preconditions; +import java.math.BigInteger; + + + + + + + + + + + + + + + + + + + + + + +final class DoubleUtils +{ + static final long SIGNIFICAND_MASK = 4503599627370495L; + static final long EXPONENT_MASK = 9218868437227405312L; + static final long SIGN_MASK = Long.MIN_VALUE; + static final int SIGNIFICAND_BITS = 52; + static final int EXPONENT_BIAS = 1023; + static final long IMPLICIT_BIT = 4503599627370496L; + + private DoubleUtils() {} + + static double nextDown(double d) + { + return -Math.nextUp(-d); + } + + + + + + + + + + + + + + + + + + + + + + static long getSignificand(double d) + { + Preconditions.checkArgument(isFinite(d), "not a normal value"); + int exponent = Math.getExponent(d); + long bits = Double.doubleToRawLongBits(d); + bits &= 0xFFFFFFFFFFFFF; + return exponent == 64513 ? bits << 1 : bits | 0x10000000000000; + } + + + static boolean isFinite(double d) + { + return Math.getExponent(d) <= 1023; + } + + static boolean isNormal(double d) { + return Math.getExponent(d) >= 64514; + } + + + + + static double scaleNormalize(double x) + { + long significand = Double.doubleToRawLongBits(x) & 0xFFFFFFFFFFFFF; + return Double.longBitsToDouble(significand | ONE_BITS); + } + + static double bigToDouble(BigInteger x) + { + BigInteger absX = x.abs(); + int exponent = absX.bitLength() - 1; + + if (exponent < 63) + return x.longValue(); + if (exponent > 1023) { + return x.signum() * Double.POSITIVE_INFINITY; + } + + + + + + + + + + int shift = exponent - 52 - 1; + long twiceSignifFloor = absX.shiftRight(shift).longValue(); + long signifFloor = twiceSignifFloor >> 1; + signifFloor &= 0xFFFFFFFFFFFFF; + + + + + + + boolean increment = ((twiceSignifFloor & 1L) != 0L) && (((signifFloor & 1L) != 0L) || (absX.getLowestSetBit() < shift)); + + long signifRounded = increment ? signifFloor + 1L : signifFloor; + long bits = exponent + 1023 << 52; + bits += signifRounded; + + + + + + + bits |= x.signum() & 0x8000000000000000; + return Double.longBitsToDouble(bits); + } + + + + static double ensureNonNegative(double value) + { + Preconditions.checkArgument(!Double.isNaN(value)); + if (value > 0.0D) { + return value; + } + return 0.0D; + } + + + private static final long ONE_BITS = Double.doubleToRawLongBits(1.0D); +} diff --git a/src/minecraft/com/google/common/math/IntMath.java b/src/minecraft/com/google/common/math/IntMath.java new file mode 100644 index 0000000..30507af --- /dev/null +++ b/src/minecraft/com/google/common/math/IntMath.java @@ -0,0 +1,584 @@ +package com.google.common.math; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import java.math.RoundingMode; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public final class IntMath +{ + @VisibleForTesting + static final int MAX_POWER_OF_SQRT2_UNSIGNED = -1257966797; + + public static boolean isPowerOfTwo(int x) + { + return (x > 0 ? 1 : 0) & ((x & x - 1) == 0 ? 1 : 0); + } + + + + + + + + @VisibleForTesting + static int lessThanBranchFree(int x, int y) + { + return (x - y ^ 0xFFFFFFFF ^ 0xFFFFFFFF) >>> 31; + } + + + + + + + + + + public static int log2(int x, RoundingMode mode) + { + MathPreconditions.checkPositive("x", x); + switch (1.$SwitchMap$java$math$RoundingMode[mode.ordinal()]) { + case 1: + MathPreconditions.checkRoundingUnnecessary(isPowerOfTwo(x)); + + case 2: + case 3: + return 31 - Integer.numberOfLeadingZeros(x); + + case 4: + case 5: + return 32 - Integer.numberOfLeadingZeros(x - 1); + + + case 6: + case 7: + case 8: + int leadingZeros = Integer.numberOfLeadingZeros(x); + int cmp = -1257966797 >>> leadingZeros; + + int logFloor = 31 - leadingZeros; + return logFloor + lessThanBranchFree(cmp, x); + } + + throw new AssertionError(); + } + + + + + + + + + + + + + @GwtIncompatible("need BigIntegerMath to adequately test") + public static int log10(int x, RoundingMode mode) + { + MathPreconditions.checkPositive("x", x); + int logFloor = log10Floor(x); + int floorPow = powersOf10[logFloor]; + switch (1.$SwitchMap$java$math$RoundingMode[mode.ordinal()]) { + case 1: + MathPreconditions.checkRoundingUnnecessary(x == floorPow); + + case 2: + case 3: + return logFloor; + case 4: + case 5: + return logFloor + lessThanBranchFree(floorPow, x); + + case 6: + case 7: + case 8: + return logFloor + lessThanBranchFree(halfPowersOf10[logFloor], x); + } + throw new AssertionError(); + } + + + + + + + + + private static int log10Floor(int x) + { + int y = maxLog10ForLeadingZeros[Integer.numberOfLeadingZeros(x)]; + + + + + return y - lessThanBranchFree(x, powersOf10[y]); + } + + @VisibleForTesting + static final byte[] maxLog10ForLeadingZeros = { 9, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0 }; + + @VisibleForTesting + static final int[] powersOf10 = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; + + + @VisibleForTesting + static final int[] halfPowersOf10 = { 3, 31, 316, 3162, 31622, 316227, 3162277, 31622776, 316227766, Integer.MAX_VALUE }; + + + + + @VisibleForTesting + static final int FLOOR_SQRT_MAX_INT = 46340; + + + + + @GwtIncompatible("failing tests") + public static int pow(int b, int k) + { + MathPreconditions.checkNonNegative("exponent", k); + switch (b) { + case 0: + return k == 0 ? 1 : 0; + case 1: + return 1; + case -1: + return (k & 0x1) == 0 ? 1 : -1; + case 2: + return k < 32 ? 1 << k : 0; + case -2: + if (k < 32) { + return (k & 0x1) == 0 ? 1 << k : -(1 << k); + } + return 0; + } + + + + for (int accum = 1;; k >>= 1) { + switch (k) { + case 0: + return accum; + case 1: + return b * accum; + } + accum *= ((k & 0x1) == 0 ? 1 : b); + b *= b; + } + } + + + + + + + + + + @GwtIncompatible("need BigIntegerMath to adequately test") + public static int sqrt(int x, RoundingMode mode) + { + MathPreconditions.checkNonNegative("x", x); + int sqrtFloor = sqrtFloor(x); + switch (1.$SwitchMap$java$math$RoundingMode[mode.ordinal()]) { + case 1: + MathPreconditions.checkRoundingUnnecessary(sqrtFloor * sqrtFloor == x); + case 2: + case 3: + return sqrtFloor; + case 4: + case 5: + return sqrtFloor + lessThanBranchFree(sqrtFloor * sqrtFloor, x); + case 6: + case 7: + case 8: + int halfSquare = sqrtFloor * sqrtFloor + sqrtFloor; + + + + + + + + + + + + return sqrtFloor + lessThanBranchFree(halfSquare, x); + } + throw new AssertionError(); + } + + + + private static int sqrtFloor(int x) + { + return (int)Math.sqrt(x); + } + + + + + + + + + public static int divide(int p, int q, RoundingMode mode) + { + Preconditions.checkNotNull(mode); + if (q == 0) { + throw new ArithmeticException("/ by zero"); + } + int div = p / q; + int rem = p - q * div; + + if (rem == 0) { + return div; + } + + + + + + + + + int signum = 0x1 | (p ^ q) >> 31; + boolean increment; + boolean increment; switch (1.$SwitchMap$java$math$RoundingMode[mode.ordinal()]) { + case 1: + MathPreconditions.checkRoundingUnnecessary(rem == 0); + + case 2: + increment = false; + break; + case 4: + increment = true; + break; + case 5: + increment = signum > 0; + break; + case 3: + increment = signum < 0; + break; + case 6: + case 7: + case 8: + int absRem = Math.abs(rem); + int cmpRemToHalfDivisor = absRem - (Math.abs(q) - absRem); + + + if (cmpRemToHalfDivisor == 0) { + if (mode != RoundingMode.HALF_UP) {} increment = ((mode == RoundingMode.HALF_EVEN ? 1 : 0) & ((div & 0x1) != 0 ? 1 : 0)) != 0; + } else { + increment = cmpRemToHalfDivisor > 0; + } + break; + default: + throw new AssertionError(); + } + return increment ? div + signum : div; + } + + + + + + + + + + + + + + + + + public static int mod(int x, int m) + { + if (m <= 0) { + throw new ArithmeticException("Modulus " + m + " must be > 0"); + } + int result = x % m; + return result >= 0 ? result : result + m; + } + + + + + + + + + + + + public static int gcd(int a, int b) + { + MathPreconditions.checkNonNegative("a", a); + MathPreconditions.checkNonNegative("b", b); + if (a == 0) + { + + return b; } + if (b == 0) { + return a; + } + + + + + int aTwos = Integer.numberOfTrailingZeros(a); + a >>= aTwos; + int bTwos = Integer.numberOfTrailingZeros(b); + b >>= bTwos; + while (a != b) + { + + + + + + + int delta = a - b; + + int minDeltaOrZero = delta & delta >> 31; + + + a = delta - minDeltaOrZero - minDeltaOrZero; + + + b += minDeltaOrZero; + a >>= Integer.numberOfTrailingZeros(a); + } + return a << Math.min(aTwos, bTwos); + } + + + + + + public static int checkedAdd(int a, int b) + { + long result = a + b; + MathPreconditions.checkNoOverflow(result == (int)result); + return (int)result; + } + + + + + + public static int checkedSubtract(int a, int b) + { + long result = a - b; + MathPreconditions.checkNoOverflow(result == (int)result); + return (int)result; + } + + + + + + public static int checkedMultiply(int a, int b) + { + long result = a * b; + MathPreconditions.checkNoOverflow(result == (int)result); + return (int)result; + } + + + + + + + + + public static int checkedPow(int b, int k) + { + MathPreconditions.checkNonNegative("exponent", k); + switch (b) { + case 0: + return k == 0 ? 1 : 0; + case 1: + return 1; + case -1: + return (k & 0x1) == 0 ? 1 : -1; + case 2: + MathPreconditions.checkNoOverflow(k < 31); + return 1 << k; + case -2: + MathPreconditions.checkNoOverflow(k < 32); + return (k & 0x1) == 0 ? 1 << k : -1 << k; + } + + + int accum = 1; + for (;;) { + switch (k) { + case 0: + return accum; + case 1: + return checkedMultiply(accum, b); + } + if ((k & 0x1) != 0) { + accum = checkedMultiply(accum, b); + } + k >>= 1; + if (k > 0) { + MathPreconditions.checkNoOverflow((-46340 <= b ? 1 : 0) & (b <= 46340 ? 1 : 0)); + b *= b; + } + } + } + + + + + + + + + + + public static int factorial(int n) + { + MathPreconditions.checkNonNegative("n", n); + return n < factorials.length ? factorials[n] : Integer.MAX_VALUE; + } + + private static final int[] factorials = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600 }; + + + + + + + + + + + + + + + + + + + + @GwtIncompatible("need BigIntegerMath to adequately test") + public static int binomial(int n, int k) + { + MathPreconditions.checkNonNegative("n", n); + MathPreconditions.checkNonNegative("k", k); + Preconditions.checkArgument(k <= n, "k (%s) > n (%s)", new Object[] { Integer.valueOf(k), Integer.valueOf(n) }); + if (k > n >> 1) { + k = n - k; + } + if ((k >= biggestBinomials.length) || (n > biggestBinomials[k])) { + return Integer.MAX_VALUE; + } + switch (k) { + case 0: + return 1; + case 1: + return n; + } + long result = 1L; + for (int i = 0; i < k; i++) { + result *= (n - i); + result /= (i + 1); + } + return (int)result; + } + + + @VisibleForTesting + static int[] biggestBinomials = { Integer.MAX_VALUE, Integer.MAX_VALUE, 65536, 2345, 477, 193, 110, 75, 58, 49, 43, 39, 37, 35, 34, 34, 33 }; + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static int mean(int x, int y) + { + return (x & y) + ((x ^ y) >> 1); + } + + private IntMath() {} +} diff --git a/src/minecraft/com/google/common/math/LongMath.java b/src/minecraft/com/google/common/math/LongMath.java new file mode 100644 index 0000000..d8e0d0a --- /dev/null +++ b/src/minecraft/com/google/common/math/LongMath.java @@ -0,0 +1,776 @@ +package com.google.common.math; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import java.math.RoundingMode; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public final class LongMath +{ + @VisibleForTesting + static final long MAX_POWER_OF_SQRT2_UNSIGNED = -5402926248376769404L; + + public static boolean isPowerOfTwo(long x) + { + return (x > 0L ? 1 : 0) & ((x & x - 1L) == 0L ? 1 : 0); + } + + + + + + + @VisibleForTesting + static int lessThanBranchFree(long x, long y) + { + return (int)((x - y ^ 0xFFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFF) >>> 63); + } + + + + + + + + + + public static int log2(long x, RoundingMode mode) + { + MathPreconditions.checkPositive("x", x); + switch (1.$SwitchMap$java$math$RoundingMode[mode.ordinal()]) { + case 1: + MathPreconditions.checkRoundingUnnecessary(isPowerOfTwo(x)); + + case 2: + case 3: + return 63 - Long.numberOfLeadingZeros(x); + + case 4: + case 5: + return 64 - Long.numberOfLeadingZeros(x - 1L); + + + case 6: + case 7: + case 8: + int leadingZeros = Long.numberOfLeadingZeros(x); + long cmp = -5402926248376769404L >>> leadingZeros; + + int logFloor = 63 - leadingZeros; + return logFloor + lessThanBranchFree(cmp, x); + } + + throw new AssertionError("impossible"); + } + + + + + + + + + + + + + + @GwtIncompatible("TODO") + public static int log10(long x, RoundingMode mode) + { + MathPreconditions.checkPositive("x", x); + int logFloor = log10Floor(x); + long floorPow = powersOf10[logFloor]; + switch (1.$SwitchMap$java$math$RoundingMode[mode.ordinal()]) { + case 1: + MathPreconditions.checkRoundingUnnecessary(x == floorPow); + + case 2: + case 3: + return logFloor; + case 4: + case 5: + return logFloor + lessThanBranchFree(floorPow, x); + + case 6: + case 7: + case 8: + return logFloor + lessThanBranchFree(halfPowersOf10[logFloor], x); + } + throw new AssertionError(); + } + + + + + + + + + @GwtIncompatible("TODO") + static int log10Floor(long x) + { + int y = maxLog10ForLeadingZeros[Long.numberOfLeadingZeros(x)]; + + + + + return y - lessThanBranchFree(x, powersOf10[y]); + } + + @VisibleForTesting + static final byte[] maxLog10ForLeadingZeros = { 19, 18, 18, 18, 18, 17, 17, 17, 16, 16, 16, 15, 15, 15, 15, 14, 14, 14, 13, 13, 13, 12, 12, 12, 12, 11, 11, 11, 10, 10, 10, 9, 9, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1, 0, 0, 0 }; + + + + + @GwtIncompatible("TODO") + @VisibleForTesting + static final long[] powersOf10 = { 1L, 10L, 100L, 1000L, 10000L, 100000L, 1000000L, 10000000L, 100000000L, 1000000000L, 10000000000L, 100000000000L, 1000000000000L, 10000000000000L, 100000000000000L, 1000000000000000L, 10000000000000000L, 100000000000000000L, 1000000000000000000L }; + + + + + + + + + + + + + + + + + + + + + + + @GwtIncompatible("TODO") + @VisibleForTesting + static final long[] halfPowersOf10 = { 3L, 31L, 316L, 3162L, 31622L, 316227L, 3162277L, 31622776L, 316227766L, 3162277660L, 31622776601L, 316227766016L, 3162277660168L, 31622776601683L, 316227766016837L, 3162277660168379L, 31622776601683793L, 316227766016837933L, 3162277660168379331L }; + + + + + + + + + + + + + @VisibleForTesting + static final long FLOOR_SQRT_MAX_LONG = 3037000499L; + + + + + + + + + + + + + + @GwtIncompatible("TODO") + public static long pow(long b, int k) + { + MathPreconditions.checkNonNegative("exponent", k); + if ((-2L <= b) && (b <= 2L)) { + switch ((int)b) { + case 0: + return k == 0 ? 1L : 0L; + case 1: + return 1L; + case -1: + return (k & 0x1) == 0 ? 1L : -1L; + case 2: + return k < 64 ? 1L << k : 0L; + case -2: + if (k < 64) { + return (k & 0x1) == 0 ? 1L << k : -(1L << k); + } + return 0L; + } + + throw new AssertionError(); + } + + for (long accum = 1L;; k >>= 1) { + switch (k) { + case 0: + return accum; + case 1: + return accum * b; + } + accum *= ((k & 0x1) == 0 ? 1L : b); + b *= b; + } + } + + + + + + + + + + @GwtIncompatible("TODO") + public static long sqrt(long x, RoundingMode mode) + { + MathPreconditions.checkNonNegative("x", x); + if (fitsInInt(x)) { + return IntMath.sqrt((int)x, mode); + } + + + + + + + + + + + + + + + + long guess = Math.sqrt(x); + + long guessSquared = guess * guess; + + + switch (1.$SwitchMap$java$math$RoundingMode[mode.ordinal()]) { + case 1: + MathPreconditions.checkRoundingUnnecessary(guessSquared == x); + return guess; + case 2: + case 3: + if (x < guessSquared) { + return guess - 1L; + } + return guess; + case 4: + case 5: + if (x > guessSquared) { + return guess + 1L; + } + return guess; + case 6: + case 7: + case 8: + long sqrtFloor = guess - (x < guessSquared ? 1 : 0); + long halfSquare = sqrtFloor * sqrtFloor + sqrtFloor; + + + + + + + + + + + + return sqrtFloor + lessThanBranchFree(halfSquare, x); + } + throw new AssertionError(); + } + + + + + + + + + + @GwtIncompatible("TODO") + public static long divide(long p, long q, RoundingMode mode) + { + Preconditions.checkNotNull(mode); + long div = p / q; + long rem = p - q * div; + + if (rem == 0L) { + return div; + } + + + + + + + + + int signum = 0x1 | (int)((p ^ q) >> 63); + boolean increment; + boolean increment; switch (1.$SwitchMap$java$math$RoundingMode[mode.ordinal()]) { + case 1: + MathPreconditions.checkRoundingUnnecessary(rem == 0L); + + case 2: + increment = false; + break; + case 4: + increment = true; + break; + case 5: + increment = signum > 0; + break; + case 3: + increment = signum < 0; + break; + case 6: + case 7: + case 8: + long absRem = Math.abs(rem); + long cmpRemToHalfDivisor = absRem - (Math.abs(q) - absRem); + + + if (cmpRemToHalfDivisor == 0L) { + increment = (mode == RoundingMode.HALF_UP ? 1 : 0) | (mode == RoundingMode.HALF_EVEN ? 1 : 0) & ((div & 1L) != 0L ? 1 : 0); + } else { + increment = cmpRemToHalfDivisor > 0L; + } + break; + default: + throw new AssertionError(); + } + return increment ? div + signum : div; + } + + + + + + + + + + + + + + + + + + + + @GwtIncompatible("TODO") + public static int mod(long x, int m) + { + return (int)mod(x, m); + } + + + + + + + + + + + + + + + + + + + @GwtIncompatible("TODO") + public static long mod(long x, long m) + { + if (m <= 0L) { + throw new ArithmeticException("Modulus must be positive"); + } + long result = x % m; + return result >= 0L ? result : result + m; + } + + + + + + + + + + + + public static long gcd(long a, long b) + { + MathPreconditions.checkNonNegative("a", a); + MathPreconditions.checkNonNegative("b", b); + if (a == 0L) + { + + return b; } + if (b == 0L) { + return a; + } + + + + + int aTwos = Long.numberOfTrailingZeros(a); + a >>= aTwos; + int bTwos = Long.numberOfTrailingZeros(b); + b >>= bTwos; + while (a != b) + { + + + + + + + long delta = a - b; + + long minDeltaOrZero = delta & delta >> 63; + + + a = delta - minDeltaOrZero - minDeltaOrZero; + + + b += minDeltaOrZero; + a >>= Long.numberOfTrailingZeros(a); + } + return a << Math.min(aTwos, bTwos); + } + + + + + + @GwtIncompatible("TODO") + public static long checkedAdd(long a, long b) + { + long result = a + b; + MathPreconditions.checkNoOverflow(((a ^ b) < 0L ? 1 : 0) | ((a ^ result) >= 0L ? 1 : 0)); + return result; + } + + + + + + @GwtIncompatible("TODO") + public static long checkedSubtract(long a, long b) + { + long result = a - b; + MathPreconditions.checkNoOverflow(((a ^ b) >= 0L ? 1 : 0) | ((a ^ result) >= 0L ? 1 : 0)); + return result; + } + + + + + + + @GwtIncompatible("TODO") + public static long checkedMultiply(long a, long b) + { + int leadingZeros = Long.numberOfLeadingZeros(a) + Long.numberOfLeadingZeros(a ^ 0xFFFFFFFFFFFFFFFF) + Long.numberOfLeadingZeros(b) + Long.numberOfLeadingZeros(b ^ 0xFFFFFFFFFFFFFFFF); + + + + + + + + + + + + if (leadingZeros > 65) { + return a * b; + } + MathPreconditions.checkNoOverflow(leadingZeros >= 64); + MathPreconditions.checkNoOverflow((a >= 0L ? 1 : 0) | (b != Long.MIN_VALUE ? 1 : 0)); + long result = a * b; + MathPreconditions.checkNoOverflow((a == 0L) || (result / a == b)); + return result; + } + + + + + + + @GwtIncompatible("TODO") + public static long checkedPow(long b, int k) + { + MathPreconditions.checkNonNegative("exponent", k); + if (((b >= -2L ? 1 : 0) & (b <= 2L ? 1 : 0)) != 0) { + switch ((int)b) { + case 0: + return k == 0 ? 1L : 0L; + case 1: + return 1L; + case -1: + return (k & 0x1) == 0 ? 1L : -1L; + case 2: + MathPreconditions.checkNoOverflow(k < 63); + return 1L << k; + case -2: + MathPreconditions.checkNoOverflow(k < 64); + return (k & 0x1) == 0 ? 1L << k : -1L << k; + } + throw new AssertionError(); + } + + long accum = 1L; + for (;;) { + switch (k) { + case 0: + return accum; + case 1: + return checkedMultiply(accum, b); + } + if ((k & 0x1) != 0) { + accum = checkedMultiply(accum, b); + } + k >>= 1; + if (k > 0) { + MathPreconditions.checkNoOverflow(b <= 3037000499L); + b *= b; + } + } + } + + + + + + + + + + + @GwtIncompatible("TODO") + public static long factorial(int n) + { + MathPreconditions.checkNonNegative("n", n); + return n < factorials.length ? factorials[n] : Long.MAX_VALUE; + } + + static final long[] factorials = { 1L, 1L, 2L, 6L, 24L, 120L, 720L, 5040L, 40320L, 362880L, 3628800L, 39916800L, 479001600L, 6227020800L, 87178291200L, 1307674368000L, 20922789888000L, 355687428096000L, 6402373705728000L, 121645100408832000L, 2432902008176640000L }; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static long binomial(int n, int k) + { + MathPreconditions.checkNonNegative("n", n); + MathPreconditions.checkNonNegative("k", k); + Preconditions.checkArgument(k <= n, "k (%s) > n (%s)", new Object[] { Integer.valueOf(k), Integer.valueOf(n) }); + if (k > n >> 1) { + k = n - k; + } + switch (k) { + case 0: + return 1L; + case 1: + return n; + } + if (n < factorials.length) + return factorials[n] / (factorials[k] * factorials[(n - k)]); + if ((k >= biggestBinomials.length) || (n > biggestBinomials[k])) + return Long.MAX_VALUE; + if ((k < biggestSimpleBinomials.length) && (n <= biggestSimpleBinomials[k])) + { + long result = n--; + for (int i = 2; i <= k; i++) { + result *= n; + result /= i;n--; + } + + return result; + } + int nBits = log2(n, RoundingMode.CEILING); + + long result = 1L; + long numerator = n--; + long denominator = 1L; + + int numeratorBits = nBits; + + + + + + + + for (int i = 2; i <= k; n--) { + if (numeratorBits + nBits < 63) + { + numerator *= n; + denominator *= i; + numeratorBits += nBits; + } + else + { + result = multiplyFraction(result, numerator, denominator); + numerator = n; + denominator = i; + numeratorBits = nBits; + } + i++; + } + + + + + + + + + + + + + + return multiplyFraction(result, numerator, denominator); + } + + + + + + static long multiplyFraction(long x, long numerator, long denominator) + { + if (x == 1L) { + return numerator / denominator; + } + long commonDivisor = gcd(x, denominator); + x /= commonDivisor; + denominator /= commonDivisor; + + + return x * (numerator / denominator); + } + + + + + + static final int[] biggestBinomials = { Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 3810779, 121977, 16175, 4337, 1733, 887, 534, 361, 265, 206, 169, 143, 125, 111, 101, 94, 88, 83, 79, 76, 74, 72, 70, 69, 68, 67, 67, 66, 66, 66, 66 }; + + + + + + + + @VisibleForTesting + static final int[] biggestSimpleBinomials = { Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 2642246, 86251, 11724, 3218, 1313, 684, 419, 287, 214, 169, 139, 119, 105, 95, 87, 81, 76, 73, 70, 68, 66, 64, 63, 62, 62, 61, 61, 61 }; + + + + + + static boolean fitsInInt(long x) + { + return (int)x == x; + } + + + + + + + + + + public static long mean(long x, long y) + { + return (x & y) + ((x ^ y) >> 1); + } + + private LongMath() {} +} diff --git a/src/minecraft/com/google/common/math/MathPreconditions.java b/src/minecraft/com/google/common/math/MathPreconditions.java new file mode 100644 index 0000000..050ad32 --- /dev/null +++ b/src/minecraft/com/google/common/math/MathPreconditions.java @@ -0,0 +1,98 @@ +package com.google.common.math; + +import com.google.common.annotations.GwtCompatible; +import java.math.BigInteger; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +final class MathPreconditions +{ + static int checkPositive(@Nullable String role, int x) + { + if (x <= 0) { + throw new IllegalArgumentException(role + " (" + x + ") must be > 0"); + } + return x; + } + + static long checkPositive(@Nullable String role, long x) { + if (x <= 0L) { + throw new IllegalArgumentException(role + " (" + x + ") must be > 0"); + } + return x; + } + + static BigInteger checkPositive(@Nullable String role, BigInteger x) { + if (x.signum() <= 0) { + throw new IllegalArgumentException(role + " (" + x + ") must be > 0"); + } + return x; + } + + static int checkNonNegative(@Nullable String role, int x) { + if (x < 0) { + throw new IllegalArgumentException(role + " (" + x + ") must be >= 0"); + } + return x; + } + + static long checkNonNegative(@Nullable String role, long x) { + if (x < 0L) { + throw new IllegalArgumentException(role + " (" + x + ") must be >= 0"); + } + return x; + } + + static BigInteger checkNonNegative(@Nullable String role, BigInteger x) { + if (x.signum() < 0) { + throw new IllegalArgumentException(role + " (" + x + ") must be >= 0"); + } + return x; + } + + static double checkNonNegative(@Nullable String role, double x) { + if (x < 0.0D) { + throw new IllegalArgumentException(role + " (" + x + ") must be >= 0"); + } + return x; + } + + static void checkRoundingUnnecessary(boolean condition) { + if (!condition) { + throw new ArithmeticException("mode was UNNECESSARY, but rounding was necessary"); + } + } + + static void checkInRange(boolean condition) { + if (!condition) { + throw new ArithmeticException("not in range"); + } + } + + static void checkNoOverflow(boolean condition) { + if (!condition) { + throw new ArithmeticException("overflow"); + } + } + + private MathPreconditions() {} +} diff --git a/src/minecraft/com/google/common/math/package-info.java b/src/minecraft/com/google/common/math/package-info.java new file mode 100644 index 0000000..d4f4173 --- /dev/null +++ b/src/minecraft/com/google/common/math/package-info.java @@ -0,0 +1,6 @@ +package com.google.common.math; + +import javax.annotation.ParametersAreNonnullByDefault; + +@ParametersAreNonnullByDefault +abstract interface package-info {} diff --git a/src/minecraft/com/google/common/net/HostAndPort.java b/src/minecraft/com/google/common/net/HostAndPort.java new file mode 100644 index 0000000..692a4f1 --- /dev/null +++ b/src/minecraft/com/google/common/net/HostAndPort.java @@ -0,0 +1,315 @@ +package com.google.common.net; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; +import java.io.Serializable; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@Immutable +@GwtCompatible +public final class HostAndPort + implements Serializable +{ + private static final int NO_PORT = -1; + private final String host; + private final int port; + private final boolean hasBracketlessColons; + private static final long serialVersionUID = 0L; + + private HostAndPort(String host, int port, boolean hasBracketlessColons) + { + this.host = host; + this.port = port; + this.hasBracketlessColons = hasBracketlessColons; + } + + + + + + + + public String getHostText() + { + return host; + } + + public boolean hasPort() + { + return port >= 0; + } + + + + + + + + public int getPort() + { + Preconditions.checkState(hasPort()); + return port; + } + + + + public int getPortOrDefault(int defaultPort) + { + return hasPort() ? port : defaultPort; + } + + + + + + + + + + + + + public static HostAndPort fromParts(String host, int port) + { + Preconditions.checkArgument(isValidPort(port), "Port out of range: %s", new Object[] { Integer.valueOf(port) }); + HostAndPort parsedHost = fromString(host); + Preconditions.checkArgument(!parsedHost.hasPort(), "Host has a port: %s", new Object[] { host }); + return new HostAndPort(host, port, hasBracketlessColons); + } + + + + + + + + + + + + public static HostAndPort fromHost(String host) + { + HostAndPort parsedHost = fromString(host); + Preconditions.checkArgument(!parsedHost.hasPort(), "Host has a port: %s", new Object[] { host }); + return parsedHost; + } + + + + + + + + + + + public static HostAndPort fromString(String hostPortString) + { + Preconditions.checkNotNull(hostPortString); + + String portString = null; + boolean hasBracketlessColons = false; + String host; + if (hostPortString.startsWith("[")) { + String[] hostAndPort = getHostAndPortFromBracketedHost(hostPortString); + String host = hostAndPort[0]; + portString = hostAndPort[1]; + } else { + int colonPos = hostPortString.indexOf(':'); + if ((colonPos >= 0) && (hostPortString.indexOf(':', colonPos + 1) == -1)) + { + String host = hostPortString.substring(0, colonPos); + portString = hostPortString.substring(colonPos + 1); + } + else { + host = hostPortString; + hasBracketlessColons = colonPos >= 0; + } + } + + int port = -1; + if (!Strings.isNullOrEmpty(portString)) + { + + Preconditions.checkArgument(!portString.startsWith("+"), "Unparseable port number: %s", new Object[] { hostPortString }); + try { + port = Integer.parseInt(portString); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Unparseable port number: " + hostPortString); + } + Preconditions.checkArgument(isValidPort(port), "Port number out of range: %s", new Object[] { hostPortString }); + } + + return new HostAndPort(host, port, hasBracketlessColons); + } + + + + + + + + private static String[] getHostAndPortFromBracketedHost(String hostPortString) + { + int colonIndex = 0; + int closeBracketIndex = 0; + boolean hasPort = false; + Preconditions.checkArgument(hostPortString.charAt(0) == '[', "Bracketed host-port string must start with a bracket: %s", new Object[] { hostPortString }); + + colonIndex = hostPortString.indexOf(':'); + closeBracketIndex = hostPortString.lastIndexOf(']'); + Preconditions.checkArgument((colonIndex > -1) && (closeBracketIndex > colonIndex), "Invalid bracketed host/port: %s", new Object[] { hostPortString }); + + + String host = hostPortString.substring(1, closeBracketIndex); + if (closeBracketIndex + 1 == hostPortString.length()) { + return new String[] { host, "" }; + } + Preconditions.checkArgument(hostPortString.charAt(closeBracketIndex + 1) == ':', "Only a colon may follow a close bracket: %s", new Object[] { hostPortString }); + + for (int i = closeBracketIndex + 2; i < hostPortString.length(); i++) { + Preconditions.checkArgument(Character.isDigit(hostPortString.charAt(i)), "Port must be numeric: %s", new Object[] { hostPortString }); + } + + return new String[] { host, hostPortString.substring(closeBracketIndex + 2) }; + } + + + + + + + + + + + + public HostAndPort withDefaultPort(int defaultPort) + { + Preconditions.checkArgument(isValidPort(defaultPort)); + if ((hasPort()) || (port == defaultPort)) { + return this; + } + return new HostAndPort(host, defaultPort, hasBracketlessColons); + } + + + + + + + + + + + + + + + + public HostAndPort requireBracketsForIPv6() + { + Preconditions.checkArgument(!hasBracketlessColons, "Possible bracketless IPv6 literal: %s", new Object[] { host }); + return this; + } + + public boolean equals(@Nullable Object other) + { + if (this == other) { + return true; + } + if ((other instanceof HostAndPort)) { + HostAndPort that = (HostAndPort)other; + return (Objects.equal(host, host)) && (port == port) && (hasBracketlessColons == hasBracketlessColons); + } + + + return false; + } + + public int hashCode() + { + return Objects.hashCode(new Object[] { host, Integer.valueOf(port), Boolean.valueOf(hasBracketlessColons) }); + } + + + + public String toString() + { + StringBuilder builder = new StringBuilder(host.length() + 8); + if (host.indexOf(':') >= 0) { + builder.append('[').append(host).append(']'); + } else { + builder.append(host); + } + if (hasPort()) { + builder.append(':').append(port); + } + return builder.toString(); + } + + private static boolean isValidPort(int port) + { + return (port >= 0) && (port <= 65535); + } +} diff --git a/src/minecraft/com/google/common/net/HostSpecifier.java b/src/minecraft/com/google/common/net/HostSpecifier.java new file mode 100644 index 0000000..6cd52df --- /dev/null +++ b/src/minecraft/com/google/common/net/HostSpecifier.java @@ -0,0 +1,178 @@ +package com.google.common.net; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import java.net.InetAddress; +import java.text.ParseException; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class HostSpecifier +{ + private final String canonicalForm; + + private HostSpecifier(String canonicalForm) + { + this.canonicalForm = canonicalForm; + } + + + + + + + + + + + + + + + + + + public static HostSpecifier fromValid(String specifier) + { + HostAndPort parsedHost = HostAndPort.fromString(specifier); + Preconditions.checkArgument(!parsedHost.hasPort()); + String host = parsedHost.getHostText(); + + + + + + InetAddress addr = null; + try { + addr = InetAddresses.forString(host); + } + catch (IllegalArgumentException e) {} + + + if (addr != null) { + return new HostSpecifier(InetAddresses.toUriString(addr)); + } + + + + + InternetDomainName domain = InternetDomainName.from(host); + + if (domain.hasPublicSuffix()) { + return new HostSpecifier(domain.toString()); + } + + throw new IllegalArgumentException("Domain name does not have a recognized public suffix: " + host); + } + + + + + + + + + public static HostSpecifier from(String specifier) + throws ParseException + { + try + { + return fromValid(specifier); + + } + catch (IllegalArgumentException e) + { + + ParseException parseException = new ParseException("Invalid host specifier: " + specifier, 0); + + parseException.initCause(e); + throw parseException; + } + } + + + + + public static boolean isValid(String specifier) + { + try + { + fromValid(specifier); + return true; + } catch (IllegalArgumentException e) {} + return false; + } + + + public boolean equals(@Nullable Object other) + { + if (this == other) { + return true; + } + + if ((other instanceof HostSpecifier)) { + HostSpecifier that = (HostSpecifier)other; + return canonicalForm.equals(canonicalForm); + } + + return false; + } + + public int hashCode() + { + return canonicalForm.hashCode(); + } + + + + + + + + + public String toString() + { + return canonicalForm; + } +} diff --git a/src/minecraft/com/google/common/net/HttpHeaders.java b/src/minecraft/com/google/common/net/HttpHeaders.java new file mode 100644 index 0000000..6f830de --- /dev/null +++ b/src/minecraft/com/google/common/net/HttpHeaders.java @@ -0,0 +1,95 @@ +package com.google.common.net; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; + +@GwtCompatible +public final class HttpHeaders +{ + public static final String CACHE_CONTROL = "Cache-Control"; + public static final String CONTENT_LENGTH = "Content-Length"; + public static final String CONTENT_TYPE = "Content-Type"; + public static final String DATE = "Date"; + public static final String PRAGMA = "Pragma"; + public static final String VIA = "Via"; + public static final String WARNING = "Warning"; + public static final String ACCEPT = "Accept"; + public static final String ACCEPT_CHARSET = "Accept-Charset"; + public static final String ACCEPT_ENCODING = "Accept-Encoding"; + public static final String ACCEPT_LANGUAGE = "Accept-Language"; + public static final String ACCESS_CONTROL_REQUEST_HEADERS = "Access-Control-Request-Headers"; + public static final String ACCESS_CONTROL_REQUEST_METHOD = "Access-Control-Request-Method"; + public static final String AUTHORIZATION = "Authorization"; + public static final String CONNECTION = "Connection"; + public static final String COOKIE = "Cookie"; + public static final String EXPECT = "Expect"; + public static final String FROM = "From"; + @Beta + public static final String FOLLOW_ONLY_WHEN_PRERENDER_SHOWN = "Follow-Only-When-Prerender-Shown"; + public static final String HOST = "Host"; + public static final String IF_MATCH = "If-Match"; + public static final String IF_MODIFIED_SINCE = "If-Modified-Since"; + public static final String IF_NONE_MATCH = "If-None-Match"; + public static final String IF_RANGE = "If-Range"; + public static final String IF_UNMODIFIED_SINCE = "If-Unmodified-Since"; + public static final String LAST_EVENT_ID = "Last-Event-ID"; + public static final String MAX_FORWARDS = "Max-Forwards"; + public static final String ORIGIN = "Origin"; + public static final String PROXY_AUTHORIZATION = "Proxy-Authorization"; + public static final String RANGE = "Range"; + public static final String REFERER = "Referer"; + public static final String TE = "TE"; + public static final String UPGRADE = "Upgrade"; + public static final String USER_AGENT = "User-Agent"; + public static final String ACCEPT_RANGES = "Accept-Ranges"; + public static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers"; + public static final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods"; + public static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin"; + public static final String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials"; + public static final String ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers"; + public static final String ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age"; + public static final String AGE = "Age"; + public static final String ALLOW = "Allow"; + public static final String CONTENT_DISPOSITION = "Content-Disposition"; + public static final String CONTENT_ENCODING = "Content-Encoding"; + public static final String CONTENT_LANGUAGE = "Content-Language"; + public static final String CONTENT_LOCATION = "Content-Location"; + public static final String CONTENT_MD5 = "Content-MD5"; + public static final String CONTENT_RANGE = "Content-Range"; + public static final String CONTENT_SECURITY_POLICY = "Content-Security-Policy"; + public static final String CONTENT_SECURITY_POLICY_REPORT_ONLY = "Content-Security-Policy-Report-Only"; + public static final String ETAG = "ETag"; + public static final String EXPIRES = "Expires"; + public static final String LAST_MODIFIED = "Last-Modified"; + public static final String LINK = "Link"; + public static final String LOCATION = "Location"; + public static final String P3P = "P3P"; + public static final String PROXY_AUTHENTICATE = "Proxy-Authenticate"; + public static final String REFRESH = "Refresh"; + public static final String RETRY_AFTER = "Retry-After"; + public static final String SERVER = "Server"; + public static final String SET_COOKIE = "Set-Cookie"; + public static final String SET_COOKIE2 = "Set-Cookie2"; + public static final String STRICT_TRANSPORT_SECURITY = "Strict-Transport-Security"; + public static final String TIMING_ALLOW_ORIGIN = "Timing-Allow-Origin"; + public static final String TRAILER = "Trailer"; + public static final String TRANSFER_ENCODING = "Transfer-Encoding"; + public static final String VARY = "Vary"; + public static final String WWW_AUTHENTICATE = "WWW-Authenticate"; + public static final String DNT = "DNT"; + public static final String X_CONTENT_TYPE_OPTIONS = "X-Content-Type-Options"; + public static final String X_DO_NOT_TRACK = "X-Do-Not-Track"; + public static final String X_FORWARDED_FOR = "X-Forwarded-For"; + public static final String X_FORWARDED_PROTO = "X-Forwarded-Proto"; + public static final String X_FRAME_OPTIONS = "X-Frame-Options"; + public static final String X_POWERED_BY = "X-Powered-By"; + @Beta + public static final String PUBLIC_KEY_PINS = "Public-Key-Pins"; + @Beta + public static final String PUBLIC_KEY_PINS_REPORT_ONLY = "Public-Key-Pins-Report-Only"; + public static final String X_REQUESTED_WITH = "X-Requested-With"; + public static final String X_USER_IP = "X-User-IP"; + public static final String X_XSS_PROTECTION = "X-XSS-Protection"; + + private HttpHeaders() {} +} diff --git a/src/minecraft/com/google/common/net/InetAddresses.java b/src/minecraft/com/google/common/net/InetAddresses.java new file mode 100644 index 0000000..acd2df3 --- /dev/null +++ b/src/minecraft/com/google/common/net/InetAddresses.java @@ -0,0 +1,1011 @@ +package com.google.common.net; + +import com.google.common.annotations.Beta; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.hash.HashCode; +import com.google.common.hash.HashFunction; +import com.google.common.hash.Hashing; +import com.google.common.io.ByteArrayDataInput; +import com.google.common.io.ByteStreams; +import com.google.common.primitives.Ints; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.nio.ByteBuffer; +import java.util.Arrays; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class InetAddresses +{ + private static final int IPV4_PART_COUNT = 4; + private static final int IPV6_PART_COUNT = 8; + private static final Inet4Address LOOPBACK4 = (Inet4Address)forString("127.0.0.1"); + private static final Inet4Address ANY4 = (Inet4Address)forString("0.0.0.0"); + + + + + private InetAddresses() {} + + + + + private static Inet4Address getInet4Address(byte[] bytes) + { + Preconditions.checkArgument(bytes.length == 4, "Byte array has invalid length for an IPv4 address: %s != 4.", new Object[] { Integer.valueOf(bytes.length) }); + + + + + return (Inet4Address)bytesToInetAddress(bytes); + } + + + + + + + + + + + public static InetAddress forString(String ipString) + { + byte[] addr = ipStringToBytes(ipString); + + + if (addr == null) { + throw new IllegalArgumentException(String.format("'%s' is not an IP string literal.", new Object[] { ipString })); + } + + + return bytesToInetAddress(addr); + } + + + + + + + + public static boolean isInetAddress(String ipString) + { + return ipStringToBytes(ipString) != null; + } + + private static byte[] ipStringToBytes(String ipString) + { + boolean hasColon = false; + boolean hasDot = false; + for (int i = 0; i < ipString.length(); i++) { + char c = ipString.charAt(i); + if (c == '.') { + hasDot = true; + } else if (c == ':') { + if (hasDot) { + return null; + } + hasColon = true; + } else if (Character.digit(c, 16) == -1) { + return null; + } + } + + + if (hasColon) { + if (hasDot) { + ipString = convertDottedQuadToHex(ipString); + if (ipString == null) { + return null; + } + } + return textToNumericFormatV6(ipString); } + if (hasDot) { + return textToNumericFormatV4(ipString); + } + return null; + } + + private static byte[] textToNumericFormatV4(String ipString) { + String[] address = ipString.split("\\.", 5); + if (address.length != 4) { + return null; + } + + byte[] bytes = new byte[4]; + try { + for (int i = 0; i < bytes.length; i++) { + bytes[i] = parseOctet(address[i]); + } + } catch (NumberFormatException ex) { + return null; + } + + return bytes; + } + + private static byte[] textToNumericFormatV6(String ipString) + { + String[] parts = ipString.split(":", 10); + if ((parts.length < 3) || (parts.length > 9)) { + return null; + } + + + + int skipIndex = -1; + for (int i = 1; i < parts.length - 1; i++) { + if (parts[i].length() == 0) { + if (skipIndex >= 0) { + return null; + } + skipIndex = i; + } + } + + int partsHi; + int partsLo; + if (skipIndex >= 0) + { + int partsHi = skipIndex; + int partsLo = parts.length - skipIndex - 1; + if (parts[0].length() == 0) { partsHi--; if (partsHi != 0) + return null; + } + if (parts[(parts.length - 1)].length() == 0) { partsLo--; if (partsLo != 0) { + return null; + } + } + } + else { + partsHi = parts.length; + partsLo = 0; + } + + + + int partsSkipped = 8 - (partsHi + partsLo); + if (skipIndex >= 0 ? partsSkipped < 1 : partsSkipped != 0) { + return null; + } + + + ByteBuffer rawBytes = ByteBuffer.allocate(16); + try { + for (int i = 0; i < partsHi; i++) { + rawBytes.putShort(parseHextet(parts[i])); + } + for (int i = 0; i < partsSkipped; i++) { + rawBytes.putShort((short)0); + } + for (int i = partsLo; i > 0; i--) { + rawBytes.putShort(parseHextet(parts[(parts.length - i)])); + } + } catch (NumberFormatException ex) { + return null; + } + return rawBytes.array(); + } + + private static String convertDottedQuadToHex(String ipString) { + int lastColon = ipString.lastIndexOf(':'); + String initialPart = ipString.substring(0, lastColon + 1); + String dottedQuad = ipString.substring(lastColon + 1); + byte[] quad = textToNumericFormatV4(dottedQuad); + if (quad == null) { + return null; + } + String penultimate = Integer.toHexString((quad[0] & 0xFF) << 8 | quad[1] & 0xFF); + String ultimate = Integer.toHexString((quad[2] & 0xFF) << 8 | quad[3] & 0xFF); + return initialPart + penultimate + ":" + ultimate; + } + + private static byte parseOctet(String ipPart) + { + int octet = Integer.parseInt(ipPart); + + + if ((octet > 255) || ((ipPart.startsWith("0")) && (ipPart.length() > 1))) { + throw new NumberFormatException(); + } + return (byte)octet; + } + + private static short parseHextet(String ipPart) + { + int hextet = Integer.parseInt(ipPart, 16); + if (hextet > 65535) { + throw new NumberFormatException(); + } + return (short)hextet; + } + + + + + + + + + + + private static InetAddress bytesToInetAddress(byte[] addr) + { + try + { + return InetAddress.getByAddress(addr); + } catch (UnknownHostException e) { + throw new AssertionError(e); + } + } + + + + + + + + + + + + + + + + + + public static String toAddrString(InetAddress ip) + { + Preconditions.checkNotNull(ip); + if ((ip instanceof Inet4Address)) + { + return ip.getHostAddress(); + } + Preconditions.checkArgument(ip instanceof Inet6Address); + byte[] bytes = ip.getAddress(); + int[] hextets = new int[8]; + for (int i = 0; i < hextets.length; i++) { + hextets[i] = Ints.fromBytes(0, 0, bytes[(2 * i)], bytes[(2 * i + 1)]); + } + + compressLongestRunOfZeroes(hextets); + return hextetsToIPv6String(hextets); + } + + + + + + + + + + private static void compressLongestRunOfZeroes(int[] hextets) + { + int bestRunStart = -1; + int bestRunLength = -1; + int runStart = -1; + for (int i = 0; i < hextets.length + 1; i++) { + if ((i < hextets.length) && (hextets[i] == 0)) { + if (runStart < 0) { + runStart = i; + } + } else if (runStart >= 0) { + int runLength = i - runStart; + if (runLength > bestRunLength) { + bestRunStart = runStart; + bestRunLength = runLength; + } + runStart = -1; + } + } + if (bestRunLength >= 2) { + Arrays.fill(hextets, bestRunStart, bestRunStart + bestRunLength, -1); + } + } + + + + + + + + + + + + + + + private static String hextetsToIPv6String(int[] hextets) + { + StringBuilder buf = new StringBuilder(39); + boolean lastWasNumber = false; + for (int i = 0; i < hextets.length; i++) { + boolean thisIsNumber = hextets[i] >= 0; + if (thisIsNumber) { + if (lastWasNumber) { + buf.append(':'); + } + buf.append(Integer.toHexString(hextets[i])); + } + else if ((i == 0) || (lastWasNumber)) { + buf.append("::"); + } + + lastWasNumber = thisIsNumber; + } + return buf.toString(); + } + + + + + + + + + + + + + + + + + + + + + + + + + + public static String toUriString(InetAddress ip) + { + if ((ip instanceof Inet6Address)) { + return "[" + toAddrString(ip) + "]"; + } + return toAddrString(ip); + } + + + + + + + + + + + + + + + + public static InetAddress forUriString(String hostAddr) + { + Preconditions.checkNotNull(hostAddr); + + int expectBytes; + String ipString; + int expectBytes; + if ((hostAddr.startsWith("[")) && (hostAddr.endsWith("]"))) { + String ipString = hostAddr.substring(1, hostAddr.length() - 1); + expectBytes = 16; + } else { + ipString = hostAddr; + expectBytes = 4; + } + + + byte[] addr = ipStringToBytes(ipString); + if ((addr == null) || (addr.length != expectBytes)) { + throw new IllegalArgumentException(String.format("Not a valid URI IP literal: '%s'", new Object[] { hostAddr })); + } + + + return bytesToInetAddress(addr); + } + + + + + + + public static boolean isUriInetAddress(String ipString) + { + try + { + forUriString(ipString); + return true; + } catch (IllegalArgumentException e) {} + return false; + } + + + + + + + + + + + + + + + + + + + + + + + + + + public static boolean isCompatIPv4Address(Inet6Address ip) + { + if (!ip.isIPv4CompatibleAddress()) { + return false; + } + + byte[] bytes = ip.getAddress(); + if ((bytes[12] == 0) && (bytes[13] == 0) && (bytes[14] == 0) && ((bytes[15] == 0) || (bytes[15] == 1))) + { + return false; + } + + return true; + } + + + + + + + + public static Inet4Address getCompatIPv4Address(Inet6Address ip) + { + Preconditions.checkArgument(isCompatIPv4Address(ip), "Address '%s' is not IPv4-compatible.", new Object[] { toAddrString(ip) }); + + + return getInet4Address(Arrays.copyOfRange(ip.getAddress(), 12, 16)); + } + + + + + + + + + + + + + + + public static boolean is6to4Address(Inet6Address ip) + { + byte[] bytes = ip.getAddress(); + return (bytes[0] == 32) && (bytes[1] == 2); + } + + + + + + + + public static Inet4Address get6to4IPv4Address(Inet6Address ip) + { + Preconditions.checkArgument(is6to4Address(ip), "Address '%s' is not a 6to4 address.", new Object[] { toAddrString(ip) }); + + + return getInet4Address(Arrays.copyOfRange(ip.getAddress(), 2, 6)); + } + + + + + + + @Beta + public static final class TeredoInfo + { + private final Inet4Address server; + + + + + + private final Inet4Address client; + + + + + + private final int port; + + + + + + private final int flags; + + + + + + + public TeredoInfo(@Nullable Inet4Address server, @Nullable Inet4Address client, int port, int flags) + { + Preconditions.checkArgument((port >= 0) && (port <= 65535), "port '%s' is out of range (0 <= port <= 0xffff)", new Object[] { Integer.valueOf(port) }); + + Preconditions.checkArgument((flags >= 0) && (flags <= 65535), "flags '%s' is out of range (0 <= flags <= 0xffff)", new Object[] { Integer.valueOf(flags) }); + + + this.server = ((Inet4Address)Objects.firstNonNull(server, InetAddresses.ANY4)); + this.client = ((Inet4Address)Objects.firstNonNull(client, InetAddresses.ANY4)); + this.port = port; + this.flags = flags; + } + + public Inet4Address getServer() { + return server; + } + + public Inet4Address getClient() { + return client; + } + + public int getPort() { + return port; + } + + public int getFlags() { + return flags; + } + } + + + + + + + + + public static boolean isTeredoAddress(Inet6Address ip) + { + byte[] bytes = ip.getAddress(); + return (bytes[0] == 32) && (bytes[1] == 1) && (bytes[2] == 0) && (bytes[3] == 0); + } + + + + + + + + + public static TeredoInfo getTeredoInfo(Inet6Address ip) + { + Preconditions.checkArgument(isTeredoAddress(ip), "Address '%s' is not a Teredo address.", new Object[] { toAddrString(ip) }); + + + byte[] bytes = ip.getAddress(); + Inet4Address server = getInet4Address(Arrays.copyOfRange(bytes, 4, 8)); + + int flags = ByteStreams.newDataInput(bytes, 8).readShort() & 0xFFFF; + + + int port = (ByteStreams.newDataInput(bytes, 10).readShort() ^ 0xFFFFFFFF) & 0xFFFF; + + byte[] clientBytes = Arrays.copyOfRange(bytes, 12, 16); + for (int i = 0; i < clientBytes.length; i++) + { + clientBytes[i] = ((byte)(clientBytes[i] ^ 0xFFFFFFFF)); + } + Inet4Address client = getInet4Address(clientBytes); + + return new TeredoInfo(server, client, port, flags); + } + + + + + + + + + + + + + + + + + + + public static boolean isIsatapAddress(Inet6Address ip) + { + if (isTeredoAddress(ip)) { + return false; + } + + byte[] bytes = ip.getAddress(); + + if ((bytes[8] | 0x3) != 3) + { + + + return false; + } + + return (bytes[9] == 0) && (bytes[10] == 94) && (bytes[11] == -2); + } + + + + + + + + + public static Inet4Address getIsatapIPv4Address(Inet6Address ip) + { + Preconditions.checkArgument(isIsatapAddress(ip), "Address '%s' is not an ISATAP address.", new Object[] { toAddrString(ip) }); + + + return getInet4Address(Arrays.copyOfRange(ip.getAddress(), 12, 16)); + } + + + + + + + + + + + + + public static boolean hasEmbeddedIPv4ClientAddress(Inet6Address ip) + { + return (isCompatIPv4Address(ip)) || (is6to4Address(ip)) || (isTeredoAddress(ip)); + } + + + + + + + + + + + + + + public static Inet4Address getEmbeddedIPv4ClientAddress(Inet6Address ip) + { + if (isCompatIPv4Address(ip)) { + return getCompatIPv4Address(ip); + } + + if (is6to4Address(ip)) { + return get6to4IPv4Address(ip); + } + + if (isTeredoAddress(ip)) { + return getTeredoInfo(ip).getClient(); + } + + throw new IllegalArgumentException(String.format("'%s' has no embedded IPv4 address.", new Object[] { toAddrString(ip) })); + } + + + + + + + + + + + + + + + + + + + + + + + + public static boolean isMappedIPv4Address(String ipString) + { + byte[] bytes = ipStringToBytes(ipString); + if ((bytes != null) && (bytes.length == 16)) { + for (int i = 0; i < 10; i++) { + if (bytes[i] != 0) { + return false; + } + } + for (int i = 10; i < 12; i++) { + if (bytes[i] != -1) { + return false; + } + } + return true; + } + return false; + } + + + + + + + + + + + + + + + + + + + + + public static Inet4Address getCoercedIPv4Address(InetAddress ip) + { + if ((ip instanceof Inet4Address)) { + return (Inet4Address)ip; + } + + + byte[] bytes = ip.getAddress(); + boolean leadingBytesOfZero = true; + for (int i = 0; i < 15; i++) { + if (bytes[i] != 0) { + leadingBytesOfZero = false; + break; + } + } + if ((leadingBytesOfZero) && (bytes[15] == 1)) + return LOOPBACK4; + if ((leadingBytesOfZero) && (bytes[15] == 0)) { + return ANY4; + } + + Inet6Address ip6 = (Inet6Address)ip; + long addressAsLong = 0L; + if (hasEmbeddedIPv4ClientAddress(ip6)) { + addressAsLong = getEmbeddedIPv4ClientAddress(ip6).hashCode(); + } + else + { + addressAsLong = ByteBuffer.wrap(ip6.getAddress(), 0, 8).getLong(); + } + + + int coercedHash = Hashing.murmur3_32().hashLong(addressAsLong).asInt(); + + + coercedHash |= 0xE0000000; + + + + if (coercedHash == -1) { + coercedHash = -2; + } + + return getInet4Address(Ints.toByteArray(coercedHash)); + } + + + + + + + + + + + + + + + + + + + + + + public static int coerceToInteger(InetAddress ip) + { + return ByteStreams.newDataInput(getCoercedIPv4Address(ip).getAddress()).readInt(); + } + + + + + + + + public static Inet4Address fromInteger(int address) + { + return getInet4Address(Ints.toByteArray(address)); + } + + + + + + + + + + + public static InetAddress fromLittleEndianByteArray(byte[] addr) + throws UnknownHostException + { + byte[] reversed = new byte[addr.length]; + for (int i = 0; i < addr.length; i++) { + reversed[i] = addr[(addr.length - i - 1)]; + } + return InetAddress.getByAddress(reversed); + } + + + + + + + + + + public static InetAddress increment(InetAddress address) + { + byte[] addr = address.getAddress(); + int i = addr.length - 1; + while ((i >= 0) && (addr[i] == -1)) { + addr[i] = 0; + i--; + } + + Preconditions.checkArgument(i >= 0, "Incrementing %s would wrap.", new Object[] { address }); int + + tmp55_54 = i; byte[] tmp55_53 = addr;tmp55_53[tmp55_54] = ((byte)(tmp55_53[tmp55_54] + 1)); + return bytesToInetAddress(addr); + } + + + + + + + + + public static boolean isMaximum(InetAddress address) + { + byte[] addr = address.getAddress(); + for (int i = 0; i < addr.length; i++) { + if (addr[i] != -1) { + return false; + } + } + return true; + } +} diff --git a/src/minecraft/com/google/common/net/InternetDomainName.java b/src/minecraft/com/google/common/net/InternetDomainName.java new file mode 100644 index 0000000..d9576d0 --- /dev/null +++ b/src/minecraft/com/google/common/net/InternetDomainName.java @@ -0,0 +1,547 @@ +package com.google.common.net; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Ascii; +import com.google.common.base.CharMatcher; +import com.google.common.base.Joiner; +import com.google.common.base.Preconditions; +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.thirdparty.publicsuffix.PublicSuffixPatterns; +import java.util.List; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +public final class InternetDomainName +{ + private static final CharMatcher DOTS_MATCHER = CharMatcher.anyOf(".。.。"); + + private static final Splitter DOT_SPLITTER = Splitter.on('.'); + private static final Joiner DOT_JOINER = Joiner.on('.'); + + + + + + + private static final int NO_PUBLIC_SUFFIX_FOUND = -1; + + + + + + + private static final String DOT_REGEX = "\\."; + + + + + + + private static final int MAX_PARTS = 127; + + + + + + + private static final int MAX_LENGTH = 253; + + + + + + private static final int MAX_DOMAIN_PART_LENGTH = 63; + + + + + + private final String name; + + + + + + private final ImmutableList parts; + + + + + + private final int publicSuffixIndex; + + + + + + + InternetDomainName(String name) + { + name = Ascii.toLowerCase(DOTS_MATCHER.replaceFrom(name, '.')); + + if (name.endsWith(".")) { + name = name.substring(0, name.length() - 1); + } + + Preconditions.checkArgument(name.length() <= 253, "Domain name too long: '%s':", new Object[] { name }); + + this.name = name; + + parts = ImmutableList.copyOf(DOT_SPLITTER.split(name)); + Preconditions.checkArgument(parts.size() <= 127, "Domain has too many parts: '%s'", new Object[] { name }); + + Preconditions.checkArgument(validateSyntax(parts), "Not a valid domain name: '%s'", new Object[] { name }); + + publicSuffixIndex = findPublicSuffix(); + } + + + + + + + private int findPublicSuffix() + { + int partsSize = parts.size(); + + for (int i = 0; i < partsSize; i++) { + String ancestorName = DOT_JOINER.join(parts.subList(i, partsSize)); + + if (PublicSuffixPatterns.EXACT.containsKey(ancestorName)) { + return i; + } + + + + + if (PublicSuffixPatterns.EXCLUDED.containsKey(ancestorName)) { + return i + 1; + } + + if (matchesWildcardPublicSuffix(ancestorName)) { + return i; + } + } + + return -1; + } + + + + + + + + + + + + + + + + + + + + + public static InternetDomainName from(String domain) + { + return new InternetDomainName((String)Preconditions.checkNotNull(domain)); + } + + + + + + + private static boolean validateSyntax(List parts) + { + int lastIndex = parts.size() - 1; + + + + if (!validatePart((String)parts.get(lastIndex), true)) { + return false; + } + + for (int i = 0; i < lastIndex; i++) { + String part = (String)parts.get(i); + if (!validatePart(part, false)) { + return false; + } + } + + return true; + } + + private static final CharMatcher DASH_MATCHER = CharMatcher.anyOf("-_"); + + private static final CharMatcher PART_CHAR_MATCHER = CharMatcher.JAVA_LETTER_OR_DIGIT.or(DASH_MATCHER); + + + + + + + + + + + + + + private static boolean validatePart(String part, boolean isFinalPart) + { + if ((part.length() < 1) || (part.length() > 63)) { + return false; + } + + + + + + + + + + + + String asciiChars = CharMatcher.ASCII.retainFrom(part); + + if (!PART_CHAR_MATCHER.matchesAllOf(asciiChars)) { + return false; + } + + + + if ((DASH_MATCHER.matches(part.charAt(0))) || (DASH_MATCHER.matches(part.charAt(part.length() - 1)))) + { + return false; + } + + + + + + + + + + if ((isFinalPart) && (CharMatcher.DIGIT.matches(part.charAt(0)))) { + return false; + } + + return true; + } + + + + + + public ImmutableList parts() + { + return parts; + } + + + + + + + + + + + + + + public boolean isPublicSuffix() + { + return publicSuffixIndex == 0; + } + + + + + + + + + + + public boolean hasPublicSuffix() + { + return publicSuffixIndex != -1; + } + + + + + + + public InternetDomainName publicSuffix() + { + return hasPublicSuffix() ? ancestor(publicSuffixIndex) : null; + } + + + + + + + + + + + + + + + + + + + + public boolean isUnderPublicSuffix() + { + return publicSuffixIndex > 0; + } + + + + + + + + + + + + + + + + + + + + + public boolean isTopPrivateDomain() + { + return publicSuffixIndex == 1; + } + + + + + + + + + + + + + + + + + + + + + + + public InternetDomainName topPrivateDomain() + { + if (isTopPrivateDomain()) { + return this; + } + Preconditions.checkState(isUnderPublicSuffix(), "Not under a public suffix: %s", new Object[] { name }); + return ancestor(publicSuffixIndex - 1); + } + + + + public boolean hasParent() + { + return parts.size() > 1; + } + + + + + + + + + public InternetDomainName parent() + { + Preconditions.checkState(hasParent(), "Domain '%s' has no parent", new Object[] { name }); + return ancestor(1); + } + + + + + + + + + private InternetDomainName ancestor(int levels) + { + return from(DOT_JOINER.join(parts.subList(levels, parts.size()))); + } + + + + + + + + + + + public InternetDomainName child(String leftParts) + { + return from((String)Preconditions.checkNotNull(leftParts) + "." + name); + } + + + + + + + + + + + + + + + + + + + + + + public static boolean isValid(String name) + { + try + { + from(name); + return true; + } catch (IllegalArgumentException e) {} + return false; + } + + + + + + private static boolean matchesWildcardPublicSuffix(String domain) + { + String[] pieces = domain.split("\\.", 2); + return (pieces.length == 2) && (PublicSuffixPatterns.UNDER.containsKey(pieces[1])); + } + + + + + public String toString() + { + return name; + } + + + + + + + + + public boolean equals(@Nullable Object object) + { + if (object == this) { + return true; + } + + if ((object instanceof InternetDomainName)) { + InternetDomainName that = (InternetDomainName)object; + return name.equals(name); + } + + return false; + } + + public int hashCode() + { + return name.hashCode(); + } +} diff --git a/src/minecraft/com/google/common/net/MediaType.java b/src/minecraft/com/google/common/net/MediaType.java new file mode 100644 index 0000000..01cd9a0 --- /dev/null +++ b/src/minecraft/com/google/common/net/MediaType.java @@ -0,0 +1,718 @@ +package com.google.common.net; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Ascii; +import com.google.common.base.CharMatcher; +import com.google.common.base.Charsets; +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.base.Joiner.MapJoiner; +import com.google.common.base.Objects; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableListMultimap; +import com.google.common.collect.ImmutableListMultimap.Builder; +import com.google.common.collect.ImmutableMultiset; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multimaps; +import java.nio.charset.Charset; +import java.util.Collection; +import java.util.Map; +import java.util.Map.Entry; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +@Immutable +public final class MediaType +{ + private static final String CHARSET_ATTRIBUTE = "charset"; + private static final ImmutableListMultimap UTF_8_CONSTANT_PARAMETERS = ImmutableListMultimap.of("charset", Ascii.toLowerCase(Charsets.UTF_8.name())); + + + + private static final CharMatcher TOKEN_MATCHER = CharMatcher.ASCII.and(CharMatcher.JAVA_ISO_CONTROL.negate()).and(CharMatcher.isNot(' ')).and(CharMatcher.noneOf("()<>@,;:\\\"/[]?=")); + + + private static final CharMatcher QUOTED_TEXT_MATCHER = CharMatcher.ASCII.and(CharMatcher.noneOf("\"\\\r")); + + + + + + private static final CharMatcher LINEAR_WHITE_SPACE = CharMatcher.anyOf(" \t\r\n"); + + private static final String APPLICATION_TYPE = "application"; + + private static final String AUDIO_TYPE = "audio"; + + private static final String IMAGE_TYPE = "image"; + + private static final String TEXT_TYPE = "text"; + private static final String VIDEO_TYPE = "video"; + private static final String WILDCARD = "*"; + private static final Map KNOWN_TYPES = Maps.newHashMap(); + + private static MediaType createConstant(String type, String subtype) { + return addKnownType(new MediaType(type, subtype, ImmutableListMultimap.of())); + } + + private static MediaType createConstantUtf8(String type, String subtype) { + return addKnownType(new MediaType(type, subtype, UTF_8_CONSTANT_PARAMETERS)); + } + + private static MediaType addKnownType(MediaType mediaType) { + KNOWN_TYPES.put(mediaType, mediaType); + return mediaType; + } + + + + + + + + + + + + public static final MediaType ANY_TYPE = createConstant("*", "*"); + public static final MediaType ANY_TEXT_TYPE = createConstant("text", "*"); + public static final MediaType ANY_IMAGE_TYPE = createConstant("image", "*"); + public static final MediaType ANY_AUDIO_TYPE = createConstant("audio", "*"); + public static final MediaType ANY_VIDEO_TYPE = createConstant("video", "*"); + public static final MediaType ANY_APPLICATION_TYPE = createConstant("application", "*"); + + + public static final MediaType CACHE_MANIFEST_UTF_8 = createConstantUtf8("text", "cache-manifest"); + + public static final MediaType CSS_UTF_8 = createConstantUtf8("text", "css"); + public static final MediaType CSV_UTF_8 = createConstantUtf8("text", "csv"); + public static final MediaType HTML_UTF_8 = createConstantUtf8("text", "html"); + public static final MediaType I_CALENDAR_UTF_8 = createConstantUtf8("text", "calendar"); + public static final MediaType PLAIN_TEXT_UTF_8 = createConstantUtf8("text", "plain"); + + + + + + public static final MediaType TEXT_JAVASCRIPT_UTF_8 = createConstantUtf8("text", "javascript"); + + + + + + + public static final MediaType TSV_UTF_8 = createConstantUtf8("text", "tab-separated-values"); + public static final MediaType VCARD_UTF_8 = createConstantUtf8("text", "vcard"); + public static final MediaType WML_UTF_8 = createConstantUtf8("text", "vnd.wap.wml"); + + + + + + public static final MediaType XML_UTF_8 = createConstantUtf8("text", "xml"); + + + public static final MediaType BMP = createConstant("image", "bmp"); + + + + + + + + + + public static final MediaType CRW = createConstant("image", "x-canon-crw"); + public static final MediaType GIF = createConstant("image", "gif"); + public static final MediaType ICO = createConstant("image", "vnd.microsoft.icon"); + public static final MediaType JPEG = createConstant("image", "jpeg"); + public static final MediaType PNG = createConstant("image", "png"); + + + + + + + + + + + + + + + + + public static final MediaType PSD = createConstant("image", "vnd.adobe.photoshop"); + public static final MediaType SVG_UTF_8 = createConstantUtf8("image", "svg+xml"); + public static final MediaType TIFF = createConstant("image", "tiff"); + public static final MediaType WEBP = createConstant("image", "webp"); + + + public static final MediaType MP4_AUDIO = createConstant("audio", "mp4"); + public static final MediaType MPEG_AUDIO = createConstant("audio", "mpeg"); + public static final MediaType OGG_AUDIO = createConstant("audio", "ogg"); + public static final MediaType WEBM_AUDIO = createConstant("audio", "webm"); + + + public static final MediaType MP4_VIDEO = createConstant("video", "mp4"); + public static final MediaType MPEG_VIDEO = createConstant("video", "mpeg"); + public static final MediaType OGG_VIDEO = createConstant("video", "ogg"); + public static final MediaType QUICKTIME = createConstant("video", "quicktime"); + public static final MediaType WEBM_VIDEO = createConstant("video", "webm"); + public static final MediaType WMV = createConstant("video", "x-ms-wmv"); + + + + + + + + public static final MediaType APPLICATION_XML_UTF_8 = createConstantUtf8("application", "xml"); + public static final MediaType ATOM_UTF_8 = createConstantUtf8("application", "atom+xml"); + public static final MediaType BZIP2 = createConstant("application", "x-bzip2"); + + + + + + + + + public static final MediaType EOT = createConstant("application", "vnd.ms-fontobject"); + + + + + + + + + + public static final MediaType EPUB = createConstant("application", "epub+zip"); + public static final MediaType FORM_DATA = createConstant("application", "x-www-form-urlencoded"); + + + + + + + + + public static final MediaType KEY_ARCHIVE = createConstant("application", "pkcs12"); + + + + + + + + + + + + public static final MediaType APPLICATION_BINARY = createConstant("application", "binary"); + public static final MediaType GZIP = createConstant("application", "x-gzip"); + + + + + + public static final MediaType JAVASCRIPT_UTF_8 = createConstantUtf8("application", "javascript"); + + public static final MediaType JSON_UTF_8 = createConstantUtf8("application", "json"); + public static final MediaType KML = createConstant("application", "vnd.google-earth.kml+xml"); + public static final MediaType KMZ = createConstant("application", "vnd.google-earth.kmz"); + public static final MediaType MBOX = createConstant("application", "mbox"); + public static final MediaType MICROSOFT_EXCEL = createConstant("application", "vnd.ms-excel"); + public static final MediaType MICROSOFT_POWERPOINT = createConstant("application", "vnd.ms-powerpoint"); + + public static final MediaType MICROSOFT_WORD = createConstant("application", "msword"); + public static final MediaType OCTET_STREAM = createConstant("application", "octet-stream"); + public static final MediaType OGG_CONTAINER = createConstant("application", "ogg"); + public static final MediaType OOXML_DOCUMENT = createConstant("application", "vnd.openxmlformats-officedocument.wordprocessingml.document"); + + public static final MediaType OOXML_PRESENTATION = createConstant("application", "vnd.openxmlformats-officedocument.presentationml.presentation"); + + public static final MediaType OOXML_SHEET = createConstant("application", "vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + + public static final MediaType OPENDOCUMENT_GRAPHICS = createConstant("application", "vnd.oasis.opendocument.graphics"); + + public static final MediaType OPENDOCUMENT_PRESENTATION = createConstant("application", "vnd.oasis.opendocument.presentation"); + + public static final MediaType OPENDOCUMENT_SPREADSHEET = createConstant("application", "vnd.oasis.opendocument.spreadsheet"); + + public static final MediaType OPENDOCUMENT_TEXT = createConstant("application", "vnd.oasis.opendocument.text"); + + public static final MediaType PDF = createConstant("application", "pdf"); + public static final MediaType POSTSCRIPT = createConstant("application", "postscript"); + + + + + + public static final MediaType PROTOBUF = createConstant("application", "protobuf"); + public static final MediaType RDF_XML_UTF_8 = createConstantUtf8("application", "rdf+xml"); + public static final MediaType RTF_UTF_8 = createConstantUtf8("application", "rtf"); + + + + + + + + + + public static final MediaType SFNT = createConstant("application", "font-sfnt"); + public static final MediaType SHOCKWAVE_FLASH = createConstant("application", "x-shockwave-flash"); + + public static final MediaType SKETCHUP = createConstant("application", "vnd.sketchup.skp"); + public static final MediaType TAR = createConstant("application", "x-tar"); + + + + + + + + + + public static final MediaType WOFF = createConstant("application", "font-woff"); + public static final MediaType XHTML_UTF_8 = createConstantUtf8("application", "xhtml+xml"); + + + + + + + + public static final MediaType XRD_UTF_8 = createConstantUtf8("application", "xrd+xml"); + public static final MediaType ZIP = createConstant("application", "zip"); + + private final String type; + private final String subtype; + private final ImmutableListMultimap parameters; + + private MediaType(String type, String subtype, ImmutableListMultimap parameters) + { + this.type = type; + this.subtype = subtype; + this.parameters = parameters; + } + + public String type() + { + return type; + } + + public String subtype() + { + return subtype; + } + + public ImmutableListMultimap parameters() + { + return parameters; + } + + private Map> parametersAsMap() { + Maps.transformValues(parameters.asMap(), new Function() + { + public ImmutableMultiset apply(Collection input) { + return ImmutableMultiset.copyOf(input); + } + }); + } + + + + + + + + + public Optional charset() + { + ImmutableSet charsetValues = ImmutableSet.copyOf(parameters.get("charset")); + switch (charsetValues.size()) { + case 0: + return Optional.absent(); + case 1: + return Optional.of(Charset.forName((String)Iterables.getOnlyElement(charsetValues))); + } + throw new IllegalStateException("Multiple charset values defined: " + charsetValues); + } + + + + + + public MediaType withoutParameters() + { + return parameters.isEmpty() ? this : create(type, subtype); + } + + + + + + public MediaType withParameters(Multimap parameters) + { + return create(type, subtype, parameters); + } + + + + + + + + + public MediaType withParameter(String attribute, String value) + { + Preconditions.checkNotNull(attribute); + Preconditions.checkNotNull(value); + String normalizedAttribute = normalizeToken(attribute); + ImmutableListMultimap.Builder builder = ImmutableListMultimap.builder(); + for (Map.Entry entry : parameters.entries()) { + String key = (String)entry.getKey(); + if (!normalizedAttribute.equals(key)) { + builder.put(key, entry.getValue()); + } + } + builder.put(normalizedAttribute, normalizeParameterValue(normalizedAttribute, value)); + MediaType mediaType = new MediaType(type, subtype, builder.build()); + + return (MediaType)Objects.firstNonNull(KNOWN_TYPES.get(mediaType), mediaType); + } + + + + + + + + + + public MediaType withCharset(Charset charset) + { + Preconditions.checkNotNull(charset); + return withParameter("charset", charset.name()); + } + + public boolean hasWildcard() + { + return ("*".equals(type)) || ("*".equals(subtype)); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + public boolean is(MediaType mediaTypeRange) + { + return ((type.equals("*")) || (type.equals(type))) && ((subtype.equals("*")) || (subtype.equals(subtype))) && (parameters.entries().containsAll(parameters.entries())); + } + + + + + + + + + public static MediaType create(String type, String subtype) + { + return create(type, subtype, ImmutableListMultimap.of()); + } + + + + + + static MediaType createApplicationType(String subtype) + { + return create("application", subtype); + } + + + + + + static MediaType createAudioType(String subtype) + { + return create("audio", subtype); + } + + + + + + static MediaType createImageType(String subtype) + { + return create("image", subtype); + } + + + + + + static MediaType createTextType(String subtype) + { + return create("text", subtype); + } + + + + + + static MediaType createVideoType(String subtype) + { + return create("video", subtype); + } + + private static MediaType create(String type, String subtype, Multimap parameters) + { + Preconditions.checkNotNull(type); + Preconditions.checkNotNull(subtype); + Preconditions.checkNotNull(parameters); + String normalizedType = normalizeToken(type); + String normalizedSubtype = normalizeToken(subtype); + Preconditions.checkArgument((!"*".equals(normalizedType)) || ("*".equals(normalizedSubtype)), "A wildcard type cannot be used with a non-wildcard subtype"); + + ImmutableListMultimap.Builder builder = ImmutableListMultimap.builder(); + for (Map.Entry entry : parameters.entries()) { + String attribute = normalizeToken((String)entry.getKey()); + builder.put(attribute, normalizeParameterValue(attribute, (String)entry.getValue())); + } + MediaType mediaType = new MediaType(normalizedType, normalizedSubtype, builder.build()); + + return (MediaType)Objects.firstNonNull(KNOWN_TYPES.get(mediaType), mediaType); + } + + private static String normalizeToken(String token) { + Preconditions.checkArgument(TOKEN_MATCHER.matchesAllOf(token)); + return Ascii.toLowerCase(token); + } + + private static String normalizeParameterValue(String attribute, String value) { + return "charset".equals(attribute) ? Ascii.toLowerCase(value) : value; + } + + + + + + public static MediaType parse(String input) + { + Preconditions.checkNotNull(input); + Tokenizer tokenizer = new Tokenizer(input); + try { + String type = tokenizer.consumeToken(TOKEN_MATCHER); + tokenizer.consumeCharacter('/'); + String subtype = tokenizer.consumeToken(TOKEN_MATCHER); + ImmutableListMultimap.Builder parameters = ImmutableListMultimap.builder(); + while (tokenizer.hasMore()) { + tokenizer.consumeCharacter(';'); + tokenizer.consumeTokenIfPresent(LINEAR_WHITE_SPACE); + String attribute = tokenizer.consumeToken(TOKEN_MATCHER); + tokenizer.consumeCharacter('='); + String value; + if ('"' == tokenizer.previewChar()) { + tokenizer.consumeCharacter('"'); + StringBuilder valueBuilder = new StringBuilder(); + while ('"' != tokenizer.previewChar()) { + if ('\\' == tokenizer.previewChar()) { + tokenizer.consumeCharacter('\\'); + valueBuilder.append(tokenizer.consumeCharacter(CharMatcher.ASCII)); + } else { + valueBuilder.append(tokenizer.consumeToken(QUOTED_TEXT_MATCHER)); + } + } + String value = valueBuilder.toString(); + tokenizer.consumeCharacter('"'); + } else { + value = tokenizer.consumeToken(TOKEN_MATCHER); + } + parameters.put(attribute, value); + } + return create(type, subtype, parameters.build()); + } catch (IllegalStateException e) { + throw new IllegalArgumentException("Could not parse '" + input + "'", e); + } + } + + private static final class Tokenizer { + final String input; + int position = 0; + + Tokenizer(String input) { + this.input = input; + } + + String consumeTokenIfPresent(CharMatcher matcher) { + Preconditions.checkState(hasMore()); + int startPosition = position; + position = matcher.negate().indexIn(input, startPosition); + return hasMore() ? input.substring(startPosition, position) : input.substring(startPosition); + } + + String consumeToken(CharMatcher matcher) { + int startPosition = position; + String token = consumeTokenIfPresent(matcher); + Preconditions.checkState(position != startPosition); + return token; + } + + char consumeCharacter(CharMatcher matcher) { + Preconditions.checkState(hasMore()); + char c = previewChar(); + Preconditions.checkState(matcher.matches(c)); + position += 1; + return c; + } + + char consumeCharacter(char c) { + Preconditions.checkState(hasMore()); + Preconditions.checkState(previewChar() == c); + position += 1; + return c; + } + + char previewChar() { + Preconditions.checkState(hasMore()); + return input.charAt(position); + } + + boolean hasMore() { + return (position >= 0) && (position < input.length()); + } + } + + public boolean equals(@Nullable Object obj) { + if (obj == this) + return true; + if ((obj instanceof MediaType)) { + MediaType that = (MediaType)obj; + return (type.equals(type)) && (subtype.equals(subtype)) && (parametersAsMap().equals(that.parametersAsMap())); + } + + + + return false; + } + + public int hashCode() + { + return Objects.hashCode(new Object[] { type, subtype, parametersAsMap() }); + } + + private static final Joiner.MapJoiner PARAMETER_JOINER = Joiner.on("; ").withKeyValueSeparator("="); + + + + + public String toString() + { + StringBuilder builder = new StringBuilder().append(type).append('/').append(subtype); + if (!parameters.isEmpty()) { + builder.append("; "); + Multimap quotedParameters = Multimaps.transformValues(parameters, new Function() + { + public String apply(String value) { + return MediaType.TOKEN_MATCHER.matchesAllOf(value) ? value : MediaType.escapeAndQuote(value); + } + }); + PARAMETER_JOINER.appendTo(builder, quotedParameters.entries()); + } + return builder.toString(); + } + + private static String escapeAndQuote(String value) { + StringBuilder escaped = new StringBuilder(value.length() + 16).append('"'); + for (char ch : value.toCharArray()) { + if ((ch == '\r') || (ch == '\\') || (ch == '"')) { + escaped.append('\\'); + } + escaped.append(ch); + } + return '"'; + } +} diff --git a/src/minecraft/com/google/common/net/PercentEscaper.java b/src/minecraft/com/google/common/net/PercentEscaper.java new file mode 100644 index 0000000..3ed8de2 --- /dev/null +++ b/src/minecraft/com/google/common/net/PercentEscaper.java @@ -0,0 +1,249 @@ +package com.google.common.net; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import com.google.common.escape.UnicodeEscaper; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +public final class PercentEscaper + extends UnicodeEscaper +{ + private static final char[] PLUS_SIGN = { '+' }; + + + private static final char[] UPPER_HEX_DIGITS = "0123456789ABCDEF".toCharArray(); + + + + + + + + + + private final boolean plusForSpace; + + + + + + + + + + private final boolean[] safeOctets; + + + + + + + + + + + public PercentEscaper(String safeChars, boolean plusForSpace) + { + Preconditions.checkNotNull(safeChars); + + if (safeChars.matches(".*[0-9A-Za-z].*")) { + throw new IllegalArgumentException("Alphanumeric characters are always 'safe' and should not be explicitly specified"); + } + + + safeChars = safeChars + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + + + + + if ((plusForSpace) && (safeChars.contains(" "))) { + throw new IllegalArgumentException("plusForSpace cannot be specified when space is a 'safe' character"); + } + + this.plusForSpace = plusForSpace; + safeOctets = createSafeOctets(safeChars); + } + + + + + + private static boolean[] createSafeOctets(String safeChars) + { + int maxChar = -1; + char[] safeCharArray = safeChars.toCharArray(); + for (char c : safeCharArray) { + maxChar = Math.max(c, maxChar); + } + boolean[] octets = new boolean[maxChar + 1]; + for (char c : safeCharArray) { + octets[c] = true; + } + return octets; + } + + + + + + + protected int nextEscapeIndex(CharSequence csq, int index, int end) + { + Preconditions.checkNotNull(csq); + for (; index < end; index++) { + char c = csq.charAt(index); + if ((c >= safeOctets.length) || (safeOctets[c] == 0)) { + break; + } + } + return index; + } + + + + + + + public String escape(String s) + { + Preconditions.checkNotNull(s); + int slen = s.length(); + for (int index = 0; index < slen; index++) { + char c = s.charAt(index); + if ((c >= safeOctets.length) || (safeOctets[c] == 0)) { + return escapeSlow(s, index); + } + } + return s; + } + + + + + + + protected char[] escape(int cp) + { + if ((cp < safeOctets.length) && (safeOctets[cp] != 0)) + return null; + if ((cp == 32) && (plusForSpace)) + return PLUS_SIGN; + if (cp <= 127) + { + + char[] dest = new char[3]; + dest[0] = '%'; + dest[2] = UPPER_HEX_DIGITS[(cp & 0xF)]; + dest[1] = UPPER_HEX_DIGITS[(cp >>> 4)]; + return dest; } + if (cp <= 2047) + { + + char[] dest = new char[6]; + dest[0] = '%'; + dest[3] = '%'; + dest[5] = UPPER_HEX_DIGITS[(cp & 0xF)]; + cp >>>= 4; + dest[4] = UPPER_HEX_DIGITS[(0x8 | cp & 0x3)]; + cp >>>= 2; + dest[2] = UPPER_HEX_DIGITS[(cp & 0xF)]; + cp >>>= 4; + dest[1] = UPPER_HEX_DIGITS[(0xC | cp)]; + return dest; } + if (cp <= 65535) + { + + char[] dest = new char[9]; + dest[0] = '%'; + dest[1] = 'E'; + dest[3] = '%'; + dest[6] = '%'; + dest[8] = UPPER_HEX_DIGITS[(cp & 0xF)]; + cp >>>= 4; + dest[7] = UPPER_HEX_DIGITS[(0x8 | cp & 0x3)]; + cp >>>= 2; + dest[5] = UPPER_HEX_DIGITS[(cp & 0xF)]; + cp >>>= 4; + dest[4] = UPPER_HEX_DIGITS[(0x8 | cp & 0x3)]; + cp >>>= 2; + dest[2] = UPPER_HEX_DIGITS[cp]; + return dest; } + if (cp <= 1114111) { + char[] dest = new char[12]; + + + dest[0] = '%'; + dest[1] = 'F'; + dest[3] = '%'; + dest[6] = '%'; + dest[9] = '%'; + dest[11] = UPPER_HEX_DIGITS[(cp & 0xF)]; + cp >>>= 4; + dest[10] = UPPER_HEX_DIGITS[(0x8 | cp & 0x3)]; + cp >>>= 2; + dest[8] = UPPER_HEX_DIGITS[(cp & 0xF)]; + cp >>>= 4; + dest[7] = UPPER_HEX_DIGITS[(0x8 | cp & 0x3)]; + cp >>>= 2; + dest[5] = UPPER_HEX_DIGITS[(cp & 0xF)]; + cp >>>= 4; + dest[4] = UPPER_HEX_DIGITS[(0x8 | cp & 0x3)]; + cp >>>= 2; + dest[2] = UPPER_HEX_DIGITS[(cp & 0x7)]; + return dest; + } + + throw new IllegalArgumentException("Invalid unicode character value " + cp); + } +} diff --git a/src/minecraft/com/google/common/net/UrlEscapers.java b/src/minecraft/com/google/common/net/UrlEscapers.java new file mode 100644 index 0000000..dbb4b58 --- /dev/null +++ b/src/minecraft/com/google/common/net/UrlEscapers.java @@ -0,0 +1,168 @@ +package com.google.common.net; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.escape.Escaper; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +public final class UrlEscapers +{ + static final String URL_FORM_PARAMETER_OTHER_SAFE_CHARS = "-_.*"; + static final String URL_PATH_OTHER_SAFE_CHARS_LACKING_PLUS = "-._~!$'()*,;&=@:"; + + private UrlEscapers() {} + + public static Escaper urlFormParameterEscaper() + { + return URL_FORM_PARAMETER_ESCAPER; + } + + private static final Escaper URL_FORM_PARAMETER_ESCAPER = new PercentEscaper("-_.*", true); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static Escaper urlPathSegmentEscaper() + { + return URL_PATH_SEGMENT_ESCAPER; + } + + private static final Escaper URL_PATH_SEGMENT_ESCAPER = new PercentEscaper("-._~!$'()*,;&=@:+", false); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static Escaper urlFragmentEscaper() + { + return URL_FRAGMENT_ESCAPER; + } + + private static final Escaper URL_FRAGMENT_ESCAPER = new PercentEscaper("-._~!$'()*,;&=@:+/?", false); +} diff --git a/src/minecraft/com/google/common/net/package-info.java b/src/minecraft/com/google/common/net/package-info.java new file mode 100644 index 0000000..ef0589c --- /dev/null +++ b/src/minecraft/com/google/common/net/package-info.java @@ -0,0 +1,6 @@ +package com.google.common.net; + +import javax.annotation.ParametersAreNonnullByDefault; + +@ParametersAreNonnullByDefault +abstract interface package-info {} diff --git a/src/minecraft/com/google/common/primitives/Booleans.java b/src/minecraft/com/google/common/primitives/Booleans.java new file mode 100644 index 0000000..841ee38 --- /dev/null +++ b/src/minecraft/com/google/common/primitives/Booleans.java @@ -0,0 +1,491 @@ +package com.google.common.primitives; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.AbstractList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.RandomAccess; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public final class Booleans +{ + private Booleans() {} + + public static int hashCode(boolean value) + { + return value ? 1231 : 1237; + } + + + + + + + + + + + + + + public static int compare(boolean a, boolean b) + { + return a ? 1 : a == b ? 0 : -1; + } + + + + + + + + + + + + + + + public static boolean contains(boolean[] array, boolean target) + { + for (boolean value : array) { + if (value == target) { + return true; + } + } + return false; + } + + + + + + + + + + + + + + public static int indexOf(boolean[] array, boolean target) + { + return indexOf(array, target, 0, array.length); + } + + + private static int indexOf(boolean[] array, boolean target, int start, int end) + { + for (int i = start; i < end; i++) { + if (array[i] == target) { + return i; + } + } + return -1; + } + + + + + + + + + + + + public static int indexOf(boolean[] array, boolean[] target) + { + Preconditions.checkNotNull(array, "array"); + Preconditions.checkNotNull(target, "target"); + if (target.length == 0) { + return 0; + } + + label64: + for (int i = 0; i < array.length - target.length + 1; i++) { + for (int j = 0; j < target.length; j++) { + if (array[(i + j)] != target[j]) { + break label64; + } + } + return i; + } + return -1; + } + + + + + + + + + + public static int lastIndexOf(boolean[] array, boolean target) + { + return lastIndexOf(array, target, 0, array.length); + } + + + private static int lastIndexOf(boolean[] array, boolean target, int start, int end) + { + for (int i = end - 1; i >= start; i--) { + if (array[i] == target) { + return i; + } + } + return -1; + } + + + + + + + + + + public static boolean[] concat(boolean[]... arrays) + { + int length = 0; + for (boolean[] array : arrays) { + length += array.length; + } + boolean[] result = new boolean[length]; + int pos = 0; + for (boolean[] array : arrays) { + System.arraycopy(array, 0, result, pos, array.length); + pos += array.length; + } + return result; + } + + + + + + + + + + + + + + + + + + public static boolean[] ensureCapacity(boolean[] array, int minLength, int padding) + { + Preconditions.checkArgument(minLength >= 0, "Invalid minLength: %s", new Object[] { Integer.valueOf(minLength) }); + Preconditions.checkArgument(padding >= 0, "Invalid padding: %s", new Object[] { Integer.valueOf(padding) }); + return array.length < minLength ? copyOf(array, minLength + padding) : array; + } + + + + private static boolean[] copyOf(boolean[] original, int length) + { + boolean[] copy = new boolean[length]; + System.arraycopy(original, 0, copy, 0, Math.min(original.length, length)); + return copy; + } + + + + + + + + + + public static String join(String separator, boolean... array) + { + Preconditions.checkNotNull(separator); + if (array.length == 0) { + return ""; + } + + + StringBuilder builder = new StringBuilder(array.length * 7); + builder.append(array[0]); + for (int i = 1; i < array.length; i++) { + builder.append(separator).append(array[i]); + } + return builder.toString(); + } + + + + + + + + + + + + + + + + + public static Comparator lexicographicalComparator() + { + return LexicographicalComparator.INSTANCE; + } + + private static enum LexicographicalComparator implements Comparator { + INSTANCE; + + private LexicographicalComparator() {} + + public int compare(boolean[] left, boolean[] right) { int minLength = Math.min(left.length, right.length); + for (int i = 0; i < minLength; i++) { + int result = Booleans.compare(left[i], right[i]); + if (result != 0) { + return result; + } + } + return left.length - right.length; + } + } + + + + + + + + + + + + + + + + + + public static boolean[] toArray(Collection collection) + { + if ((collection instanceof BooleanArrayAsList)) { + return ((BooleanArrayAsList)collection).toBooleanArray(); + } + + Object[] boxedArray = collection.toArray(); + int len = boxedArray.length; + boolean[] array = new boolean[len]; + for (int i = 0; i < len; i++) + { + array[i] = ((Boolean)Preconditions.checkNotNull(boxedArray[i])).booleanValue(); + } + return array; + } + + + + + + + + + + + + + + + public static List asList(boolean... backingArray) + { + if (backingArray.length == 0) { + return Collections.emptyList(); + } + return new BooleanArrayAsList(backingArray); + } + + @GwtCompatible + private static class BooleanArrayAsList extends AbstractList implements RandomAccess, Serializable { + final boolean[] array; + final int start; + final int end; + private static final long serialVersionUID = 0L; + + BooleanArrayAsList(boolean[] array) { + this(array, 0, array.length); + } + + BooleanArrayAsList(boolean[] array, int start, int end) { + this.array = array; + this.start = start; + this.end = end; + } + + public int size() { + return end - start; + } + + public boolean isEmpty() { + return false; + } + + public Boolean get(int index) { + Preconditions.checkElementIndex(index, size()); + return Boolean.valueOf(array[(start + index)]); + } + + public boolean contains(Object target) + { + return ((target instanceof Boolean)) && (Booleans.indexOf(array, ((Boolean)target).booleanValue(), start, end) != -1); + } + + + public int indexOf(Object target) + { + if ((target instanceof Boolean)) { + int i = Booleans.indexOf(array, ((Boolean)target).booleanValue(), start, end); + if (i >= 0) { + return i - start; + } + } + return -1; + } + + public int lastIndexOf(Object target) + { + if ((target instanceof Boolean)) { + int i = Booleans.lastIndexOf(array, ((Boolean)target).booleanValue(), start, end); + if (i >= 0) { + return i - start; + } + } + return -1; + } + + public Boolean set(int index, Boolean element) { + Preconditions.checkElementIndex(index, size()); + boolean oldValue = array[(start + index)]; + + array[(start + index)] = ((Boolean)Preconditions.checkNotNull(element)).booleanValue(); + return Boolean.valueOf(oldValue); + } + + public List subList(int fromIndex, int toIndex) { + int size = size(); + Preconditions.checkPositionIndexes(fromIndex, toIndex, size); + if (fromIndex == toIndex) { + return Collections.emptyList(); + } + return new BooleanArrayAsList(array, start + fromIndex, start + toIndex); + } + + public boolean equals(Object object) { + if (object == this) { + return true; + } + if ((object instanceof BooleanArrayAsList)) { + BooleanArrayAsList that = (BooleanArrayAsList)object; + int size = size(); + if (that.size() != size) { + return false; + } + for (int i = 0; i < size; i++) { + if (array[(start + i)] != array[(start + i)]) { + return false; + } + } + return true; + } + return super.equals(object); + } + + public int hashCode() { + int result = 1; + for (int i = start; i < end; i++) { + result = 31 * result + Booleans.hashCode(array[i]); + } + return result; + } + + public String toString() { + StringBuilder builder = new StringBuilder(size() * 7); + builder.append(array[start] != 0 ? "[true" : "[false"); + for (int i = start + 1; i < end; i++) { + builder.append(array[i] != 0 ? ", true" : ", false"); + } + return ']'; + } + + boolean[] toBooleanArray() + { + int size = size(); + boolean[] result = new boolean[size]; + System.arraycopy(array, start, result, 0, size); + return result; + } + } + + + + + + + + @Beta + public static int countTrue(boolean... values) + { + int count = 0; + for (boolean value : values) { + if (value) { + count++; + } + } + return count; + } +} diff --git a/src/minecraft/com/google/common/primitives/Bytes.java b/src/minecraft/com/google/common/primitives/Bytes.java new file mode 100644 index 0000000..4fe23bb --- /dev/null +++ b/src/minecraft/com/google/common/primitives/Bytes.java @@ -0,0 +1,387 @@ +package com.google.common.primitives; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.AbstractList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.RandomAccess; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public final class Bytes +{ + private Bytes() {} + + public static int hashCode(byte value) + { + return value; + } + + + + + + + + + + public static boolean contains(byte[] array, byte target) + { + for (byte value : array) { + if (value == target) { + return true; + } + } + return false; + } + + + + + + + + + + public static int indexOf(byte[] array, byte target) + { + return indexOf(array, target, 0, array.length); + } + + + private static int indexOf(byte[] array, byte target, int start, int end) + { + for (int i = start; i < end; i++) { + if (array[i] == target) { + return i; + } + } + return -1; + } + + + + + + + + + + + + public static int indexOf(byte[] array, byte[] target) + { + Preconditions.checkNotNull(array, "array"); + Preconditions.checkNotNull(target, "target"); + if (target.length == 0) { + return 0; + } + + label64: + for (int i = 0; i < array.length - target.length + 1; i++) { + for (int j = 0; j < target.length; j++) { + if (array[(i + j)] != target[j]) { + break label64; + } + } + return i; + } + return -1; + } + + + + + + + + + + public static int lastIndexOf(byte[] array, byte target) + { + return lastIndexOf(array, target, 0, array.length); + } + + + private static int lastIndexOf(byte[] array, byte target, int start, int end) + { + for (int i = end - 1; i >= start; i--) { + if (array[i] == target) { + return i; + } + } + return -1; + } + + + + + + + + + + public static byte[] concat(byte[]... arrays) + { + int length = 0; + for (byte[] array : arrays) { + length += array.length; + } + byte[] result = new byte[length]; + int pos = 0; + for (byte[] array : arrays) { + System.arraycopy(array, 0, result, pos, array.length); + pos += array.length; + } + return result; + } + + + + + + + + + + + + + + + + + + public static byte[] ensureCapacity(byte[] array, int minLength, int padding) + { + Preconditions.checkArgument(minLength >= 0, "Invalid minLength: %s", new Object[] { Integer.valueOf(minLength) }); + Preconditions.checkArgument(padding >= 0, "Invalid padding: %s", new Object[] { Integer.valueOf(padding) }); + return array.length < minLength ? copyOf(array, minLength + padding) : array; + } + + + + private static byte[] copyOf(byte[] original, int length) + { + byte[] copy = new byte[length]; + System.arraycopy(original, 0, copy, 0, Math.min(original.length, length)); + return copy; + } + + + + + + + + + + + + + + + + public static byte[] toArray(Collection collection) + { + if ((collection instanceof ByteArrayAsList)) { + return ((ByteArrayAsList)collection).toByteArray(); + } + + Object[] boxedArray = collection.toArray(); + int len = boxedArray.length; + byte[] array = new byte[len]; + for (int i = 0; i < len; i++) + { + array[i] = ((Number)Preconditions.checkNotNull(boxedArray[i])).byteValue(); + } + return array; + } + + + + + + + + + + + + + + + public static List asList(byte... backingArray) + { + if (backingArray.length == 0) { + return Collections.emptyList(); + } + return new ByteArrayAsList(backingArray); + } + + @GwtCompatible + private static class ByteArrayAsList extends AbstractList implements RandomAccess, Serializable { + final byte[] array; + final int start; + final int end; + private static final long serialVersionUID = 0L; + + ByteArrayAsList(byte[] array) { + this(array, 0, array.length); + } + + ByteArrayAsList(byte[] array, int start, int end) { + this.array = array; + this.start = start; + this.end = end; + } + + public int size() { + return end - start; + } + + public boolean isEmpty() { + return false; + } + + public Byte get(int index) { + Preconditions.checkElementIndex(index, size()); + return Byte.valueOf(array[(start + index)]); + } + + public boolean contains(Object target) + { + return ((target instanceof Byte)) && (Bytes.indexOf(array, ((Byte)target).byteValue(), start, end) != -1); + } + + + public int indexOf(Object target) + { + if ((target instanceof Byte)) { + int i = Bytes.indexOf(array, ((Byte)target).byteValue(), start, end); + if (i >= 0) { + return i - start; + } + } + return -1; + } + + public int lastIndexOf(Object target) + { + if ((target instanceof Byte)) { + int i = Bytes.lastIndexOf(array, ((Byte)target).byteValue(), start, end); + if (i >= 0) { + return i - start; + } + } + return -1; + } + + public Byte set(int index, Byte element) { + Preconditions.checkElementIndex(index, size()); + byte oldValue = array[(start + index)]; + + array[(start + index)] = ((Byte)Preconditions.checkNotNull(element)).byteValue(); + return Byte.valueOf(oldValue); + } + + public List subList(int fromIndex, int toIndex) { + int size = size(); + Preconditions.checkPositionIndexes(fromIndex, toIndex, size); + if (fromIndex == toIndex) { + return Collections.emptyList(); + } + return new ByteArrayAsList(array, start + fromIndex, start + toIndex); + } + + public boolean equals(Object object) { + if (object == this) { + return true; + } + if ((object instanceof ByteArrayAsList)) { + ByteArrayAsList that = (ByteArrayAsList)object; + int size = size(); + if (that.size() != size) { + return false; + } + for (int i = 0; i < size; i++) { + if (array[(start + i)] != array[(start + i)]) { + return false; + } + } + return true; + } + return super.equals(object); + } + + public int hashCode() { + int result = 1; + for (int i = start; i < end; i++) { + result = 31 * result + Bytes.hashCode(array[i]); + } + return result; + } + + public String toString() { + StringBuilder builder = new StringBuilder(size() * 5); + builder.append('[').append(array[start]); + for (int i = start + 1; i < end; i++) { + builder.append(", ").append(array[i]); + } + return ']'; + } + + byte[] toByteArray() + { + int size = size(); + byte[] result = new byte[size]; + System.arraycopy(array, start, result, 0, size); + return result; + } + } +} diff --git a/src/minecraft/com/google/common/primitives/Chars.java b/src/minecraft/com/google/common/primitives/Chars.java new file mode 100644 index 0000000..9cabd8a --- /dev/null +++ b/src/minecraft/com/google/common/primitives/Chars.java @@ -0,0 +1,591 @@ +package com.google.common.primitives; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.AbstractList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.RandomAccess; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public final class Chars +{ + public static final int BYTES = 2; + + private Chars() {} + + public static int hashCode(char value) + { + return value; + } + + + + + + + + + public static char checkedCast(long value) + { + char result = (char)(int)value; + if (result != value) + { + throw new IllegalArgumentException("Out of range: " + value); + } + return result; + } + + + + + + + + + public static char saturatedCast(long value) + { + if (value > 65535L) { + return 65535; + } + if (value < 0L) { + return '\000'; + } + return (char)(int)value; + } + + + + + + + + + + + + + public static int compare(char a, char b) + { + return a - b; + } + + + + + + + + + + public static boolean contains(char[] array, char target) + { + for (char value : array) { + if (value == target) { + return true; + } + } + return false; + } + + + + + + + + + + public static int indexOf(char[] array, char target) + { + return indexOf(array, target, 0, array.length); + } + + + private static int indexOf(char[] array, char target, int start, int end) + { + for (int i = start; i < end; i++) { + if (array[i] == target) { + return i; + } + } + return -1; + } + + + + + + + + + + + + public static int indexOf(char[] array, char[] target) + { + Preconditions.checkNotNull(array, "array"); + Preconditions.checkNotNull(target, "target"); + if (target.length == 0) { + return 0; + } + + label64: + for (int i = 0; i < array.length - target.length + 1; i++) { + for (int j = 0; j < target.length; j++) { + if (array[(i + j)] != target[j]) { + break label64; + } + } + return i; + } + return -1; + } + + + + + + + + + + public static int lastIndexOf(char[] array, char target) + { + return lastIndexOf(array, target, 0, array.length); + } + + + private static int lastIndexOf(char[] array, char target, int start, int end) + { + for (int i = end - 1; i >= start; i--) { + if (array[i] == target) { + return i; + } + } + return -1; + } + + + + + + + + + public static char min(char... array) + { + Preconditions.checkArgument(array.length > 0); + char min = array[0]; + for (int i = 1; i < array.length; i++) { + if (array[i] < min) { + min = array[i]; + } + } + return min; + } + + + + + + + + + public static char max(char... array) + { + Preconditions.checkArgument(array.length > 0); + char max = array[0]; + for (int i = 1; i < array.length; i++) { + if (array[i] > max) { + max = array[i]; + } + } + return max; + } + + + + + + + + + + public static char[] concat(char[]... arrays) + { + int length = 0; + for (char[] array : arrays) { + length += array.length; + } + char[] result = new char[length]; + int pos = 0; + for (char[] array : arrays) { + System.arraycopy(array, 0, result, pos, array.length); + pos += array.length; + } + return result; + } + + + + + + + + + + + + @GwtIncompatible("doesn't work") + public static byte[] toByteArray(char value) + { + return new byte[] { (byte)(value >> '\b'), (byte)value }; + } + + + + + + + + + + + + + + + @GwtIncompatible("doesn't work") + public static char fromByteArray(byte[] bytes) + { + Preconditions.checkArgument(bytes.length >= 2, "array too small: %s < %s", new Object[] { Integer.valueOf(bytes.length), Integer.valueOf(2) }); + + return fromBytes(bytes[0], bytes[1]); + } + + + + + + + + @GwtIncompatible("doesn't work") + public static char fromBytes(byte b1, byte b2) + { + return (char)(b1 << 8 | b2 & 0xFF); + } + + + + + + + + + + + + + + + + + + public static char[] ensureCapacity(char[] array, int minLength, int padding) + { + Preconditions.checkArgument(minLength >= 0, "Invalid minLength: %s", new Object[] { Integer.valueOf(minLength) }); + Preconditions.checkArgument(padding >= 0, "Invalid padding: %s", new Object[] { Integer.valueOf(padding) }); + return array.length < minLength ? copyOf(array, minLength + padding) : array; + } + + + + private static char[] copyOf(char[] original, int length) + { + char[] copy = new char[length]; + System.arraycopy(original, 0, copy, 0, Math.min(original.length, length)); + return copy; + } + + + + + + + + + + public static String join(String separator, char... array) + { + Preconditions.checkNotNull(separator); + int len = array.length; + if (len == 0) { + return ""; + } + + StringBuilder builder = new StringBuilder(len + separator.length() * (len - 1)); + + builder.append(array[0]); + for (int i = 1; i < len; i++) { + builder.append(separator).append(array[i]); + } + return builder.toString(); + } + + + + + + + + + + + + + + + + + public static Comparator lexicographicalComparator() + { + return LexicographicalComparator.INSTANCE; + } + + private static enum LexicographicalComparator implements Comparator { + INSTANCE; + + private LexicographicalComparator() {} + + public int compare(char[] left, char[] right) { int minLength = Math.min(left.length, right.length); + for (int i = 0; i < minLength; i++) { + int result = Chars.compare(left[i], right[i]); + if (result != 0) { + return result; + } + } + return left.length - right.length; + } + } + + + + + + + + + + + + + + + public static char[] toArray(Collection collection) + { + if ((collection instanceof CharArrayAsList)) { + return ((CharArrayAsList)collection).toCharArray(); + } + + Object[] boxedArray = collection.toArray(); + int len = boxedArray.length; + char[] array = new char[len]; + for (int i = 0; i < len; i++) + { + array[i] = ((Character)Preconditions.checkNotNull(boxedArray[i])).charValue(); + } + return array; + } + + + + + + + + + + + + + + + public static List asList(char... backingArray) + { + if (backingArray.length == 0) { + return Collections.emptyList(); + } + return new CharArrayAsList(backingArray); + } + + @GwtCompatible + private static class CharArrayAsList extends AbstractList implements RandomAccess, Serializable { + final char[] array; + final int start; + final int end; + private static final long serialVersionUID = 0L; + + CharArrayAsList(char[] array) { + this(array, 0, array.length); + } + + CharArrayAsList(char[] array, int start, int end) { + this.array = array; + this.start = start; + this.end = end; + } + + public int size() { + return end - start; + } + + public boolean isEmpty() { + return false; + } + + public Character get(int index) { + Preconditions.checkElementIndex(index, size()); + return Character.valueOf(array[(start + index)]); + } + + public boolean contains(Object target) + { + return ((target instanceof Character)) && (Chars.indexOf(array, ((Character)target).charValue(), start, end) != -1); + } + + + public int indexOf(Object target) + { + if ((target instanceof Character)) { + int i = Chars.indexOf(array, ((Character)target).charValue(), start, end); + if (i >= 0) { + return i - start; + } + } + return -1; + } + + public int lastIndexOf(Object target) + { + if ((target instanceof Character)) { + int i = Chars.lastIndexOf(array, ((Character)target).charValue(), start, end); + if (i >= 0) { + return i - start; + } + } + return -1; + } + + public Character set(int index, Character element) { + Preconditions.checkElementIndex(index, size()); + char oldValue = array[(start + index)]; + + array[(start + index)] = ((Character)Preconditions.checkNotNull(element)).charValue(); + return Character.valueOf(oldValue); + } + + public List subList(int fromIndex, int toIndex) { + int size = size(); + Preconditions.checkPositionIndexes(fromIndex, toIndex, size); + if (fromIndex == toIndex) { + return Collections.emptyList(); + } + return new CharArrayAsList(array, start + fromIndex, start + toIndex); + } + + public boolean equals(Object object) { + if (object == this) { + return true; + } + if ((object instanceof CharArrayAsList)) { + CharArrayAsList that = (CharArrayAsList)object; + int size = size(); + if (that.size() != size) { + return false; + } + for (int i = 0; i < size; i++) { + if (array[(start + i)] != array[(start + i)]) { + return false; + } + } + return true; + } + return super.equals(object); + } + + public int hashCode() { + int result = 1; + for (int i = start; i < end; i++) { + result = 31 * result + Chars.hashCode(array[i]); + } + return result; + } + + public String toString() { + StringBuilder builder = new StringBuilder(size() * 3); + builder.append('[').append(array[start]); + for (int i = start + 1; i < end; i++) { + builder.append(", ").append(array[i]); + } + return ']'; + } + + char[] toCharArray() + { + int size = size(); + char[] result = new char[size]; + System.arraycopy(array, start, result, 0, size); + return result; + } + } +} diff --git a/src/minecraft/com/google/common/primitives/Doubles.java b/src/minecraft/com/google/common/primitives/Doubles.java new file mode 100644 index 0000000..f76e88a --- /dev/null +++ b/src/minecraft/com/google/common/primitives/Doubles.java @@ -0,0 +1,635 @@ +package com.google.common.primitives; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Converter; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.AbstractList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.RandomAccess; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public final class Doubles +{ + public static final int BYTES = 8; + + private Doubles() {} + + public static int hashCode(double value) + { + return Double.valueOf(value).hashCode(); + } + + + + + + + + + + + + + + + + + + + public static int compare(double a, double b) + { + return Double.compare(a, b); + } + + + + + + + + public static boolean isFinite(double value) + { + return (Double.NEGATIVE_INFINITY < value ? 1 : 0) & (value < Double.POSITIVE_INFINITY ? 1 : 0); + } + + + + + + + + + + + public static boolean contains(double[] array, double target) + { + for (double value : array) { + if (value == target) { + return true; + } + } + return false; + } + + + + + + + + + + + public static int indexOf(double[] array, double target) + { + return indexOf(array, target, 0, array.length); + } + + + private static int indexOf(double[] array, double target, int start, int end) + { + for (int i = start; i < end; i++) { + if (array[i] == target) { + return i; + } + } + return -1; + } + + + + + + + + + + + + + + + public static int indexOf(double[] array, double[] target) + { + Preconditions.checkNotNull(array, "array"); + Preconditions.checkNotNull(target, "target"); + if (target.length == 0) { + return 0; + } + + label65: + for (int i = 0; i < array.length - target.length + 1; i++) { + for (int j = 0; j < target.length; j++) { + if (array[(i + j)] != target[j]) { + break label65; + } + } + return i; + } + return -1; + } + + + + + + + + + + + public static int lastIndexOf(double[] array, double target) + { + return lastIndexOf(array, target, 0, array.length); + } + + + private static int lastIndexOf(double[] array, double target, int start, int end) + { + for (int i = end - 1; i >= start; i--) { + if (array[i] == target) { + return i; + } + } + return -1; + } + + + + + + + + + + public static double min(double... array) + { + Preconditions.checkArgument(array.length > 0); + double min = array[0]; + for (int i = 1; i < array.length; i++) { + min = Math.min(min, array[i]); + } + return min; + } + + + + + + + + + + public static double max(double... array) + { + Preconditions.checkArgument(array.length > 0); + double max = array[0]; + for (int i = 1; i < array.length; i++) { + max = Math.max(max, array[i]); + } + return max; + } + + + + + + + + + + public static double[] concat(double[]... arrays) + { + int length = 0; + for (double[] array : arrays) { + length += array.length; + } + double[] result = new double[length]; + int pos = 0; + for (double[] array : arrays) { + System.arraycopy(array, 0, result, pos, array.length); + pos += array.length; + } + return result; + } + + private static final class DoubleConverter extends Converter implements Serializable + { + static final DoubleConverter INSTANCE = new DoubleConverter(); + + private DoubleConverter() {} + + protected Double doForward(String value) { return Double.valueOf(value); } + + + protected String doBackward(Double value) + { + return value.toString(); + } + + public String toString() + { + return "Doubles.stringConverter()"; + } + + private Object readResolve() { + return INSTANCE; + } + + + + private static final long serialVersionUID = 1L; + } + + + + @Beta + public static Converter stringConverter() + { + return DoubleConverter.INSTANCE; + } + + + + + + + + + + + + + + + + + + public static double[] ensureCapacity(double[] array, int minLength, int padding) + { + Preconditions.checkArgument(minLength >= 0, "Invalid minLength: %s", new Object[] { Integer.valueOf(minLength) }); + Preconditions.checkArgument(padding >= 0, "Invalid padding: %s", new Object[] { Integer.valueOf(padding) }); + return array.length < minLength ? copyOf(array, minLength + padding) : array; + } + + + + private static double[] copyOf(double[] original, int length) + { + double[] copy = new double[length]; + System.arraycopy(original, 0, copy, 0, Math.min(original.length, length)); + return copy; + } + + + + + + + + + + + + + + + public static String join(String separator, double... array) + { + Preconditions.checkNotNull(separator); + if (array.length == 0) { + return ""; + } + + + StringBuilder builder = new StringBuilder(array.length * 12); + builder.append(array[0]); + for (int i = 1; i < array.length; i++) { + builder.append(separator).append(array[i]); + } + return builder.toString(); + } + + + + + + + + + + + + + + + + + public static Comparator lexicographicalComparator() + { + return LexicographicalComparator.INSTANCE; + } + + private static enum LexicographicalComparator implements Comparator { + INSTANCE; + + private LexicographicalComparator() {} + + public int compare(double[] left, double[] right) { int minLength = Math.min(left.length, right.length); + for (int i = 0; i < minLength; i++) { + int result = Doubles.compare(left[i], right[i]); + if (result != 0) { + return result; + } + } + return left.length - right.length; + } + } + + + + + + + + + + + + + + + + public static double[] toArray(Collection collection) + { + if ((collection instanceof DoubleArrayAsList)) { + return ((DoubleArrayAsList)collection).toDoubleArray(); + } + + Object[] boxedArray = collection.toArray(); + int len = boxedArray.length; + double[] array = new double[len]; + for (int i = 0; i < len; i++) + { + array[i] = ((Number)Preconditions.checkNotNull(boxedArray[i])).doubleValue(); + } + return array; + } + + + + + + + + + + + + + + + + + + public static List asList(double... backingArray) + { + if (backingArray.length == 0) { + return Collections.emptyList(); + } + return new DoubleArrayAsList(backingArray); + } + + @GwtCompatible + private static class DoubleArrayAsList extends AbstractList implements RandomAccess, Serializable { + final double[] array; + final int start; + final int end; + private static final long serialVersionUID = 0L; + + DoubleArrayAsList(double[] array) { + this(array, 0, array.length); + } + + DoubleArrayAsList(double[] array, int start, int end) { + this.array = array; + this.start = start; + this.end = end; + } + + public int size() { + return end - start; + } + + public boolean isEmpty() { + return false; + } + + public Double get(int index) { + Preconditions.checkElementIndex(index, size()); + return Double.valueOf(array[(start + index)]); + } + + public boolean contains(Object target) + { + return ((target instanceof Double)) && (Doubles.indexOf(array, ((Double)target).doubleValue(), start, end) != -1); + } + + + public int indexOf(Object target) + { + if ((target instanceof Double)) { + int i = Doubles.indexOf(array, ((Double)target).doubleValue(), start, end); + if (i >= 0) { + return i - start; + } + } + return -1; + } + + public int lastIndexOf(Object target) + { + if ((target instanceof Double)) { + int i = Doubles.lastIndexOf(array, ((Double)target).doubleValue(), start, end); + if (i >= 0) { + return i - start; + } + } + return -1; + } + + public Double set(int index, Double element) { + Preconditions.checkElementIndex(index, size()); + double oldValue = array[(start + index)]; + + array[(start + index)] = ((Double)Preconditions.checkNotNull(element)).doubleValue(); + return Double.valueOf(oldValue); + } + + public List subList(int fromIndex, int toIndex) { + int size = size(); + Preconditions.checkPositionIndexes(fromIndex, toIndex, size); + if (fromIndex == toIndex) { + return Collections.emptyList(); + } + return new DoubleArrayAsList(array, start + fromIndex, start + toIndex); + } + + public boolean equals(Object object) { + if (object == this) { + return true; + } + if ((object instanceof DoubleArrayAsList)) { + DoubleArrayAsList that = (DoubleArrayAsList)object; + int size = size(); + if (that.size() != size) { + return false; + } + for (int i = 0; i < size; i++) { + if (array[(start + i)] != array[(start + i)]) { + return false; + } + } + return true; + } + return super.equals(object); + } + + public int hashCode() { + int result = 1; + for (int i = start; i < end; i++) { + result = 31 * result + Doubles.hashCode(array[i]); + } + return result; + } + + public String toString() { + StringBuilder builder = new StringBuilder(size() * 12); + builder.append('[').append(array[start]); + for (int i = start + 1; i < end; i++) { + builder.append(", ").append(array[i]); + } + return ']'; + } + + double[] toDoubleArray() + { + int size = size(); + double[] result = new double[size]; + System.arraycopy(array, start, result, 0, size); + return result; + } + } + + + + + + + + + + @GwtIncompatible("regular expressions") + static final Pattern FLOATING_POINT_PATTERN = ; + + @GwtIncompatible("regular expressions") + private static Pattern fpPattern() { + String decimal = "(?:\\d++(?:\\.\\d*+)?|\\.\\d++)"; + String completeDec = decimal + "(?:[eE][+-]?\\d++)?[fFdD]?"; + String hex = "(?:\\p{XDigit}++(?:\\.\\p{XDigit}*+)?|\\.\\p{XDigit}++)"; + String completeHex = "0[xX]" + hex + "[pP][+-]?\\d++[fFdD]?"; + String fpPattern = "[+-]?(?:NaN|Infinity|" + completeDec + "|" + completeHex + ")"; + return Pattern.compile(fpPattern); + } + + + + + + + + + + + + + + + + + + + + @Nullable + @GwtIncompatible("regular expressions") + @Beta + public static Double tryParse(String string) + { + if (FLOATING_POINT_PATTERN.matcher(string).matches()) + { + try + { + return Double.valueOf(Double.parseDouble(string)); + } + catch (NumberFormatException e) {} + } + + + return null; + } +} diff --git a/src/minecraft/com/google/common/primitives/Floats.java b/src/minecraft/com/google/common/primitives/Floats.java new file mode 100644 index 0000000..e0b313c --- /dev/null +++ b/src/minecraft/com/google/common/primitives/Floats.java @@ -0,0 +1,612 @@ +package com.google.common.primitives; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Converter; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.AbstractList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.RandomAccess; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public final class Floats +{ + public static final int BYTES = 4; + + private Floats() {} + + public static int hashCode(float value) + { + return Float.valueOf(value).hashCode(); + } + + + + + + + + + + + + + + + public static int compare(float a, float b) + { + return Float.compare(a, b); + } + + + + + + + + public static boolean isFinite(float value) + { + return (Float.NEGATIVE_INFINITY < value ? 1 : 0) & (value < Float.POSITIVE_INFINITY ? 1 : 0); + } + + + + + + + + + + + public static boolean contains(float[] array, float target) + { + for (float value : array) { + if (value == target) { + return true; + } + } + return false; + } + + + + + + + + + + + public static int indexOf(float[] array, float target) + { + return indexOf(array, target, 0, array.length); + } + + + private static int indexOf(float[] array, float target, int start, int end) + { + for (int i = start; i < end; i++) { + if (array[i] == target) { + return i; + } + } + return -1; + } + + + + + + + + + + + + + + + public static int indexOf(float[] array, float[] target) + { + Preconditions.checkNotNull(array, "array"); + Preconditions.checkNotNull(target, "target"); + if (target.length == 0) { + return 0; + } + + label65: + for (int i = 0; i < array.length - target.length + 1; i++) { + for (int j = 0; j < target.length; j++) { + if (array[(i + j)] != target[j]) { + break label65; + } + } + return i; + } + return -1; + } + + + + + + + + + + + public static int lastIndexOf(float[] array, float target) + { + return lastIndexOf(array, target, 0, array.length); + } + + + private static int lastIndexOf(float[] array, float target, int start, int end) + { + for (int i = end - 1; i >= start; i--) { + if (array[i] == target) { + return i; + } + } + return -1; + } + + + + + + + + + + public static float min(float... array) + { + Preconditions.checkArgument(array.length > 0); + float min = array[0]; + for (int i = 1; i < array.length; i++) { + min = Math.min(min, array[i]); + } + return min; + } + + + + + + + + + + public static float max(float... array) + { + Preconditions.checkArgument(array.length > 0); + float max = array[0]; + for (int i = 1; i < array.length; i++) { + max = Math.max(max, array[i]); + } + return max; + } + + + + + + + + + + public static float[] concat(float[]... arrays) + { + int length = 0; + for (float[] array : arrays) { + length += array.length; + } + float[] result = new float[length]; + int pos = 0; + for (float[] array : arrays) { + System.arraycopy(array, 0, result, pos, array.length); + pos += array.length; + } + return result; + } + + private static final class FloatConverter extends Converter implements Serializable + { + static final FloatConverter INSTANCE = new FloatConverter(); + + private FloatConverter() {} + + protected Float doForward(String value) { return Float.valueOf(value); } + + + protected String doBackward(Float value) + { + return value.toString(); + } + + public String toString() + { + return "Floats.stringConverter()"; + } + + private Object readResolve() { + return INSTANCE; + } + + + + private static final long serialVersionUID = 1L; + } + + + + @Beta + public static Converter stringConverter() + { + return FloatConverter.INSTANCE; + } + + + + + + + + + + + + + + + + + + public static float[] ensureCapacity(float[] array, int minLength, int padding) + { + Preconditions.checkArgument(minLength >= 0, "Invalid minLength: %s", new Object[] { Integer.valueOf(minLength) }); + Preconditions.checkArgument(padding >= 0, "Invalid padding: %s", new Object[] { Integer.valueOf(padding) }); + return array.length < minLength ? copyOf(array, minLength + padding) : array; + } + + + + private static float[] copyOf(float[] original, int length) + { + float[] copy = new float[length]; + System.arraycopy(original, 0, copy, 0, Math.min(original.length, length)); + return copy; + } + + + + + + + + + + + + + + + public static String join(String separator, float... array) + { + Preconditions.checkNotNull(separator); + if (array.length == 0) { + return ""; + } + + + StringBuilder builder = new StringBuilder(array.length * 12); + builder.append(array[0]); + for (int i = 1; i < array.length; i++) { + builder.append(separator).append(array[i]); + } + return builder.toString(); + } + + + + + + + + + + + + + + + + + public static Comparator lexicographicalComparator() + { + return LexicographicalComparator.INSTANCE; + } + + private static enum LexicographicalComparator implements Comparator { + INSTANCE; + + private LexicographicalComparator() {} + + public int compare(float[] left, float[] right) { int minLength = Math.min(left.length, right.length); + for (int i = 0; i < minLength; i++) { + int result = Floats.compare(left[i], right[i]); + if (result != 0) { + return result; + } + } + return left.length - right.length; + } + } + + + + + + + + + + + + + + + + public static float[] toArray(Collection collection) + { + if ((collection instanceof FloatArrayAsList)) { + return ((FloatArrayAsList)collection).toFloatArray(); + } + + Object[] boxedArray = collection.toArray(); + int len = boxedArray.length; + float[] array = new float[len]; + for (int i = 0; i < len; i++) + { + array[i] = ((Number)Preconditions.checkNotNull(boxedArray[i])).floatValue(); + } + return array; + } + + + + + + + + + + + + + + + + + + public static List asList(float... backingArray) + { + if (backingArray.length == 0) { + return Collections.emptyList(); + } + return new FloatArrayAsList(backingArray); + } + + @GwtCompatible + private static class FloatArrayAsList extends AbstractList implements RandomAccess, Serializable { + final float[] array; + final int start; + final int end; + private static final long serialVersionUID = 0L; + + FloatArrayAsList(float[] array) { + this(array, 0, array.length); + } + + FloatArrayAsList(float[] array, int start, int end) { + this.array = array; + this.start = start; + this.end = end; + } + + public int size() { + return end - start; + } + + public boolean isEmpty() { + return false; + } + + public Float get(int index) { + Preconditions.checkElementIndex(index, size()); + return Float.valueOf(array[(start + index)]); + } + + public boolean contains(Object target) + { + return ((target instanceof Float)) && (Floats.indexOf(array, ((Float)target).floatValue(), start, end) != -1); + } + + + public int indexOf(Object target) + { + if ((target instanceof Float)) { + int i = Floats.indexOf(array, ((Float)target).floatValue(), start, end); + if (i >= 0) { + return i - start; + } + } + return -1; + } + + public int lastIndexOf(Object target) + { + if ((target instanceof Float)) { + int i = Floats.lastIndexOf(array, ((Float)target).floatValue(), start, end); + if (i >= 0) { + return i - start; + } + } + return -1; + } + + public Float set(int index, Float element) { + Preconditions.checkElementIndex(index, size()); + float oldValue = array[(start + index)]; + + array[(start + index)] = ((Float)Preconditions.checkNotNull(element)).floatValue(); + return Float.valueOf(oldValue); + } + + public List subList(int fromIndex, int toIndex) { + int size = size(); + Preconditions.checkPositionIndexes(fromIndex, toIndex, size); + if (fromIndex == toIndex) { + return Collections.emptyList(); + } + return new FloatArrayAsList(array, start + fromIndex, start + toIndex); + } + + public boolean equals(Object object) { + if (object == this) { + return true; + } + if ((object instanceof FloatArrayAsList)) { + FloatArrayAsList that = (FloatArrayAsList)object; + int size = size(); + if (that.size() != size) { + return false; + } + for (int i = 0; i < size; i++) { + if (array[(start + i)] != array[(start + i)]) { + return false; + } + } + return true; + } + return super.equals(object); + } + + public int hashCode() { + int result = 1; + for (int i = start; i < end; i++) { + result = 31 * result + Floats.hashCode(array[i]); + } + return result; + } + + public String toString() { + StringBuilder builder = new StringBuilder(size() * 12); + builder.append('[').append(array[start]); + for (int i = start + 1; i < end; i++) { + builder.append(", ").append(array[i]); + } + return ']'; + } + + float[] toFloatArray() + { + int size = size(); + float[] result = new float[size]; + System.arraycopy(array, start, result, 0, size); + return result; + } + } + + + + + + + + + + + + + + + + + + + + + + @Nullable + @GwtIncompatible("regular expressions") + @Beta + public static Float tryParse(String string) + { + if (Doubles.FLOATING_POINT_PATTERN.matcher(string).matches()) + { + try + { + return Float.valueOf(Float.parseFloat(string)); + } + catch (NumberFormatException e) {} + } + + + return null; + } +} diff --git a/src/minecraft/com/google/common/primitives/Ints.java b/src/minecraft/com/google/common/primitives/Ints.java new file mode 100644 index 0000000..738c516 --- /dev/null +++ b/src/minecraft/com/google/common/primitives/Ints.java @@ -0,0 +1,749 @@ +package com.google.common.primitives; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Converter; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.AbstractList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.RandomAccess; +import javax.annotation.CheckForNull; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public final class Ints +{ + public static final int BYTES = 4; + public static final int MAX_POWER_OF_TWO = 1073741824; + + public static int hashCode(int value) + { + return value; + } + + + + + + + + + public static int checkedCast(long value) + { + int result = (int)value; + if (result != value) + { + throw new IllegalArgumentException("Out of range: " + value); + } + return result; + } + + + + + + + + + public static int saturatedCast(long value) + { + if (value > 2147483647L) { + return Integer.MAX_VALUE; + } + if (value < -2147483648L) { + return Integer.MIN_VALUE; + } + return (int)value; + } + + + + + + + + + + + + + public static int compare(int a, int b) + { + return a > b ? 1 : a < b ? -1 : 0; + } + + + + + + + + + + public static boolean contains(int[] array, int target) + { + for (int value : array) { + if (value == target) { + return true; + } + } + return false; + } + + + + + + + + + + public static int indexOf(int[] array, int target) + { + return indexOf(array, target, 0, array.length); + } + + + private static int indexOf(int[] array, int target, int start, int end) + { + for (int i = start; i < end; i++) { + if (array[i] == target) { + return i; + } + } + return -1; + } + + + + + + + + + + + + public static int indexOf(int[] array, int[] target) + { + Preconditions.checkNotNull(array, "array"); + Preconditions.checkNotNull(target, "target"); + if (target.length == 0) { + return 0; + } + + label64: + for (int i = 0; i < array.length - target.length + 1; i++) { + for (int j = 0; j < target.length; j++) { + if (array[(i + j)] != target[j]) { + break label64; + } + } + return i; + } + return -1; + } + + + + + + + + + + public static int lastIndexOf(int[] array, int target) + { + return lastIndexOf(array, target, 0, array.length); + } + + + private static int lastIndexOf(int[] array, int target, int start, int end) + { + for (int i = end - 1; i >= start; i--) { + if (array[i] == target) { + return i; + } + } + return -1; + } + + + + + + + + + public static int min(int... array) + { + Preconditions.checkArgument(array.length > 0); + int min = array[0]; + for (int i = 1; i < array.length; i++) { + if (array[i] < min) { + min = array[i]; + } + } + return min; + } + + + + + + + + + public static int max(int... array) + { + Preconditions.checkArgument(array.length > 0); + int max = array[0]; + for (int i = 1; i < array.length; i++) { + if (array[i] > max) { + max = array[i]; + } + } + return max; + } + + + + + + + + + + public static int[] concat(int[]... arrays) + { + int length = 0; + for (int[] array : arrays) { + length += array.length; + } + int[] result = new int[length]; + int pos = 0; + for (int[] array : arrays) { + System.arraycopy(array, 0, result, pos, array.length); + pos += array.length; + } + return result; + } + + + + + + + + + + + + @GwtIncompatible("doesn't work") + public static byte[] toByteArray(int value) + { + return new byte[] { (byte)(value >> 24), (byte)(value >> 16), (byte)(value >> 8), (byte)value }; + } + + + + + + + + + + + + + + + + + @GwtIncompatible("doesn't work") + public static int fromByteArray(byte[] bytes) + { + Preconditions.checkArgument(bytes.length >= 4, "array too small: %s < %s", new Object[] { Integer.valueOf(bytes.length), Integer.valueOf(4) }); + + return fromBytes(bytes[0], bytes[1], bytes[2], bytes[3]); + } + + + + + + + + @GwtIncompatible("doesn't work") + public static int fromBytes(byte b1, byte b2, byte b3, byte b4) + { + return b1 << 24 | (b2 & 0xFF) << 16 | (b3 & 0xFF) << 8 | b4 & 0xFF; + } + + private static final class IntConverter extends Converter implements Serializable + { + static final IntConverter INSTANCE = new IntConverter(); + + private IntConverter() {} + + protected Integer doForward(String value) { return Integer.decode(value); } + + + protected String doBackward(Integer value) + { + return value.toString(); + } + + public String toString() + { + return "Ints.stringConverter()"; + } + + private Object readResolve() { + return INSTANCE; + } + + + + private static final long serialVersionUID = 1L; + } + + + + @Beta + public static Converter stringConverter() + { + return IntConverter.INSTANCE; + } + + + + + + + + + + + + + + + + + + public static int[] ensureCapacity(int[] array, int minLength, int padding) + { + Preconditions.checkArgument(minLength >= 0, "Invalid minLength: %s", new Object[] { Integer.valueOf(minLength) }); + Preconditions.checkArgument(padding >= 0, "Invalid padding: %s", new Object[] { Integer.valueOf(padding) }); + return array.length < minLength ? copyOf(array, minLength + padding) : array; + } + + + + private static int[] copyOf(int[] original, int length) + { + int[] copy = new int[length]; + System.arraycopy(original, 0, copy, 0, Math.min(original.length, length)); + return copy; + } + + + + + + + + + + public static String join(String separator, int... array) + { + Preconditions.checkNotNull(separator); + if (array.length == 0) { + return ""; + } + + + StringBuilder builder = new StringBuilder(array.length * 5); + builder.append(array[0]); + for (int i = 1; i < array.length; i++) { + builder.append(separator).append(array[i]); + } + return builder.toString(); + } + + + + + + + + + + + + + + + + public static Comparator lexicographicalComparator() + { + return LexicographicalComparator.INSTANCE; + } + + private static enum LexicographicalComparator implements Comparator { + INSTANCE; + + private LexicographicalComparator() {} + + public int compare(int[] left, int[] right) { int minLength = Math.min(left.length, right.length); + for (int i = 0; i < minLength; i++) { + int result = Ints.compare(left[i], right[i]); + if (result != 0) { + return result; + } + } + return left.length - right.length; + } + } + + + + + + + + + + + + + + + + public static int[] toArray(Collection collection) + { + if ((collection instanceof IntArrayAsList)) { + return ((IntArrayAsList)collection).toIntArray(); + } + + Object[] boxedArray = collection.toArray(); + int len = boxedArray.length; + int[] array = new int[len]; + for (int i = 0; i < len; i++) + { + array[i] = ((Number)Preconditions.checkNotNull(boxedArray[i])).intValue(); + } + return array; + } + + + + + + + + + + + + + + + public static List asList(int... backingArray) + { + if (backingArray.length == 0) { + return Collections.emptyList(); + } + return new IntArrayAsList(backingArray); + } + + @GwtCompatible + private static class IntArrayAsList extends AbstractList implements RandomAccess, Serializable { + final int[] array; + final int start; + final int end; + private static final long serialVersionUID = 0L; + + IntArrayAsList(int[] array) { + this(array, 0, array.length); + } + + IntArrayAsList(int[] array, int start, int end) { + this.array = array; + this.start = start; + this.end = end; + } + + public int size() { + return end - start; + } + + public boolean isEmpty() { + return false; + } + + public Integer get(int index) { + Preconditions.checkElementIndex(index, size()); + return Integer.valueOf(array[(start + index)]); + } + + public boolean contains(Object target) + { + return ((target instanceof Integer)) && (Ints.indexOf(array, ((Integer)target).intValue(), start, end) != -1); + } + + + public int indexOf(Object target) + { + if ((target instanceof Integer)) { + int i = Ints.indexOf(array, ((Integer)target).intValue(), start, end); + if (i >= 0) { + return i - start; + } + } + return -1; + } + + public int lastIndexOf(Object target) + { + if ((target instanceof Integer)) { + int i = Ints.lastIndexOf(array, ((Integer)target).intValue(), start, end); + if (i >= 0) { + return i - start; + } + } + return -1; + } + + public Integer set(int index, Integer element) { + Preconditions.checkElementIndex(index, size()); + int oldValue = array[(start + index)]; + + array[(start + index)] = ((Integer)Preconditions.checkNotNull(element)).intValue(); + return Integer.valueOf(oldValue); + } + + public List subList(int fromIndex, int toIndex) { + int size = size(); + Preconditions.checkPositionIndexes(fromIndex, toIndex, size); + if (fromIndex == toIndex) { + return Collections.emptyList(); + } + return new IntArrayAsList(array, start + fromIndex, start + toIndex); + } + + public boolean equals(Object object) { + if (object == this) { + return true; + } + if ((object instanceof IntArrayAsList)) { + IntArrayAsList that = (IntArrayAsList)object; + int size = size(); + if (that.size() != size) { + return false; + } + for (int i = 0; i < size; i++) { + if (array[(start + i)] != array[(start + i)]) { + return false; + } + } + return true; + } + return super.equals(object); + } + + public int hashCode() { + int result = 1; + for (int i = start; i < end; i++) { + result = 31 * result + Ints.hashCode(array[i]); + } + return result; + } + + public String toString() { + StringBuilder builder = new StringBuilder(size() * 5); + builder.append('[').append(array[start]); + for (int i = start + 1; i < end; i++) { + builder.append(", ").append(array[i]); + } + return ']'; + } + + int[] toIntArray() + { + int size = size(); + int[] result = new int[size]; + System.arraycopy(array, start, result, 0, size); + return result; + } + } + + + + private static final byte[] asciiDigits = new byte['€']; + + static { + Arrays.fill(asciiDigits, (byte)-1); + for (int i = 0; i <= 9; i++) { + asciiDigits[(48 + i)] = ((byte)i); + } + for (int i = 0; i <= 26; i++) { + asciiDigits[(65 + i)] = ((byte)(10 + i)); + asciiDigits[(97 + i)] = ((byte)(10 + i)); + } + } + + private static int digit(char c) { + return c < '€' ? asciiDigits[c] : -1; + } + + + + + + + + + + + + + + + + + + + + + @CheckForNull + @Beta + @GwtIncompatible("TODO") + public static Integer tryParse(String string) + { + return tryParse(string, 10); + } + + + + + + + + + + + + + + + + + + + + + + + @CheckForNull + @GwtIncompatible("TODO") + static Integer tryParse(String string, int radix) + { + if (((String)Preconditions.checkNotNull(string)).isEmpty()) { + return null; + } + if ((radix < 2) || (radix > 36)) { + throw new IllegalArgumentException("radix must be between MIN_RADIX and MAX_RADIX but was " + radix); + } + + boolean negative = string.charAt(0) == '-'; + int index = negative ? 1 : 0; + if (index == string.length()) { + return null; + } + int digit = digit(string.charAt(index++)); + if ((digit < 0) || (digit >= radix)) { + return null; + } + int accum = -digit; + + int cap = Integer.MIN_VALUE / radix; + + while (index < string.length()) { + digit = digit(string.charAt(index++)); + if ((digit < 0) || (digit >= radix) || (accum < cap)) { + return null; + } + accum *= radix; + if (accum < Integer.MIN_VALUE + digit) { + return null; + } + accum -= digit; + } + + if (negative) + return Integer.valueOf(accum); + if (accum == Integer.MIN_VALUE) { + return null; + } + return Integer.valueOf(-accum); + } + + private Ints() {} +} diff --git a/src/minecraft/com/google/common/primitives/Longs.java b/src/minecraft/com/google/common/primitives/Longs.java new file mode 100644 index 0000000..419f420 --- /dev/null +++ b/src/minecraft/com/google/common/primitives/Longs.java @@ -0,0 +1,669 @@ +package com.google.common.primitives; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Converter; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.AbstractList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.RandomAccess; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public final class Longs +{ + public static final int BYTES = 8; + public static final long MAX_POWER_OF_TWO = 4611686018427387904L; + + private Longs() {} + + public static int hashCode(long value) + { + return (int)(value ^ value >>> 32); + } + + + + + + + + + + + + + public static int compare(long a, long b) + { + return a > b ? 1 : a < b ? -1 : 0; + } + + + + + + + + + + public static boolean contains(long[] array, long target) + { + for (long value : array) { + if (value == target) { + return true; + } + } + return false; + } + + + + + + + + + + public static int indexOf(long[] array, long target) + { + return indexOf(array, target, 0, array.length); + } + + + private static int indexOf(long[] array, long target, int start, int end) + { + for (int i = start; i < end; i++) { + if (array[i] == target) { + return i; + } + } + return -1; + } + + + + + + + + + + + + public static int indexOf(long[] array, long[] target) + { + Preconditions.checkNotNull(array, "array"); + Preconditions.checkNotNull(target, "target"); + if (target.length == 0) { + return 0; + } + + label65: + for (int i = 0; i < array.length - target.length + 1; i++) { + for (int j = 0; j < target.length; j++) { + if (array[(i + j)] != target[j]) { + break label65; + } + } + return i; + } + return -1; + } + + + + + + + + + + public static int lastIndexOf(long[] array, long target) + { + return lastIndexOf(array, target, 0, array.length); + } + + + private static int lastIndexOf(long[] array, long target, int start, int end) + { + for (int i = end - 1; i >= start; i--) { + if (array[i] == target) { + return i; + } + } + return -1; + } + + + + + + + + + public static long min(long... array) + { + Preconditions.checkArgument(array.length > 0); + long min = array[0]; + for (int i = 1; i < array.length; i++) { + if (array[i] < min) { + min = array[i]; + } + } + return min; + } + + + + + + + + + public static long max(long... array) + { + Preconditions.checkArgument(array.length > 0); + long max = array[0]; + for (int i = 1; i < array.length; i++) { + if (array[i] > max) { + max = array[i]; + } + } + return max; + } + + + + + + + + + + public static long[] concat(long[]... arrays) + { + int length = 0; + for (long[] array : arrays) { + length += array.length; + } + long[] result = new long[length]; + int pos = 0; + for (long[] array : arrays) { + System.arraycopy(array, 0, result, pos, array.length); + pos += array.length; + } + return result; + } + + + + + + + + + + + + + + public static byte[] toByteArray(long value) + { + byte[] result = new byte[8]; + for (int i = 7; i >= 0; i--) { + result[i] = ((byte)(int)(value & 0xFF)); + value >>= 8; + } + return result; + } + + + + + + + + + + + + + + public static long fromByteArray(byte[] bytes) + { + Preconditions.checkArgument(bytes.length >= 8, "array too small: %s < %s", new Object[] { Integer.valueOf(bytes.length), Integer.valueOf(8) }); + + return fromBytes(bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]); + } + + + + + + + + + + public static long fromBytes(byte b1, byte b2, byte b3, byte b4, byte b5, byte b6, byte b7, byte b8) + { + return (b1 & 0xFF) << 56 | (b2 & 0xFF) << 48 | (b3 & 0xFF) << 40 | (b4 & 0xFF) << 32 | (b5 & 0xFF) << 24 | (b6 & 0xFF) << 16 | (b7 & 0xFF) << 8 | b8 & 0xFF; + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + @Beta + public static Long tryParse(String string) + { + if (((String)Preconditions.checkNotNull(string)).isEmpty()) { + return null; + } + boolean negative = string.charAt(0) == '-'; + int index = negative ? 1 : 0; + if (index == string.length()) { + return null; + } + int digit = string.charAt(index++) - '0'; + if ((digit < 0) || (digit > 9)) { + return null; + } + long accum = -digit; + while (index < string.length()) { + digit = string.charAt(index++) - '0'; + if ((digit < 0) || (digit > 9) || (accum < -922337203685477580L)) { + return null; + } + accum *= 10L; + if (accum < Long.MIN_VALUE + digit) { + return null; + } + accum -= digit; + } + + if (negative) + return Long.valueOf(accum); + if (accum == Long.MIN_VALUE) { + return null; + } + return Long.valueOf(-accum); + } + + private static final class LongConverter extends Converter implements Serializable + { + static final LongConverter INSTANCE = new LongConverter(); + + private LongConverter() {} + + protected Long doForward(String value) { return Long.decode(value); } + + + protected String doBackward(Long value) + { + return value.toString(); + } + + public String toString() + { + return "Longs.stringConverter()"; + } + + private Object readResolve() { + return INSTANCE; + } + + + + private static final long serialVersionUID = 1L; + } + + + + @Beta + public static Converter stringConverter() + { + return LongConverter.INSTANCE; + } + + + + + + + + + + + + + + + + + + public static long[] ensureCapacity(long[] array, int minLength, int padding) + { + Preconditions.checkArgument(minLength >= 0, "Invalid minLength: %s", new Object[] { Integer.valueOf(minLength) }); + Preconditions.checkArgument(padding >= 0, "Invalid padding: %s", new Object[] { Integer.valueOf(padding) }); + return array.length < minLength ? copyOf(array, minLength + padding) : array; + } + + + + private static long[] copyOf(long[] original, int length) + { + long[] copy = new long[length]; + System.arraycopy(original, 0, copy, 0, Math.min(original.length, length)); + return copy; + } + + + + + + + + + + public static String join(String separator, long... array) + { + Preconditions.checkNotNull(separator); + if (array.length == 0) { + return ""; + } + + + StringBuilder builder = new StringBuilder(array.length * 10); + builder.append(array[0]); + for (int i = 1; i < array.length; i++) { + builder.append(separator).append(array[i]); + } + return builder.toString(); + } + + + + + + + + + + + + + + + + + public static Comparator lexicographicalComparator() + { + return LexicographicalComparator.INSTANCE; + } + + private static enum LexicographicalComparator implements Comparator { + INSTANCE; + + private LexicographicalComparator() {} + + public int compare(long[] left, long[] right) { int minLength = Math.min(left.length, right.length); + for (int i = 0; i < minLength; i++) { + int result = Longs.compare(left[i], right[i]); + if (result != 0) { + return result; + } + } + return left.length - right.length; + } + } + + + + + + + + + + + + + + + + public static long[] toArray(Collection collection) + { + if ((collection instanceof LongArrayAsList)) { + return ((LongArrayAsList)collection).toLongArray(); + } + + Object[] boxedArray = collection.toArray(); + int len = boxedArray.length; + long[] array = new long[len]; + for (int i = 0; i < len; i++) + { + array[i] = ((Number)Preconditions.checkNotNull(boxedArray[i])).longValue(); + } + return array; + } + + + + + + + + + + + + + + + public static List asList(long... backingArray) + { + if (backingArray.length == 0) { + return Collections.emptyList(); + } + return new LongArrayAsList(backingArray); + } + + @GwtCompatible + private static class LongArrayAsList extends AbstractList implements RandomAccess, Serializable { + final long[] array; + final int start; + final int end; + private static final long serialVersionUID = 0L; + + LongArrayAsList(long[] array) { + this(array, 0, array.length); + } + + LongArrayAsList(long[] array, int start, int end) { + this.array = array; + this.start = start; + this.end = end; + } + + public int size() { + return end - start; + } + + public boolean isEmpty() { + return false; + } + + public Long get(int index) { + Preconditions.checkElementIndex(index, size()); + return Long.valueOf(array[(start + index)]); + } + + public boolean contains(Object target) + { + return ((target instanceof Long)) && (Longs.indexOf(array, ((Long)target).longValue(), start, end) != -1); + } + + + public int indexOf(Object target) + { + if ((target instanceof Long)) { + int i = Longs.indexOf(array, ((Long)target).longValue(), start, end); + if (i >= 0) { + return i - start; + } + } + return -1; + } + + public int lastIndexOf(Object target) + { + if ((target instanceof Long)) { + int i = Longs.lastIndexOf(array, ((Long)target).longValue(), start, end); + if (i >= 0) { + return i - start; + } + } + return -1; + } + + public Long set(int index, Long element) { + Preconditions.checkElementIndex(index, size()); + long oldValue = array[(start + index)]; + + array[(start + index)] = ((Long)Preconditions.checkNotNull(element)).longValue(); + return Long.valueOf(oldValue); + } + + public List subList(int fromIndex, int toIndex) { + int size = size(); + Preconditions.checkPositionIndexes(fromIndex, toIndex, size); + if (fromIndex == toIndex) { + return Collections.emptyList(); + } + return new LongArrayAsList(array, start + fromIndex, start + toIndex); + } + + public boolean equals(Object object) { + if (object == this) { + return true; + } + if ((object instanceof LongArrayAsList)) { + LongArrayAsList that = (LongArrayAsList)object; + int size = size(); + if (that.size() != size) { + return false; + } + for (int i = 0; i < size; i++) { + if (array[(start + i)] != array[(start + i)]) { + return false; + } + } + return true; + } + return super.equals(object); + } + + public int hashCode() { + int result = 1; + for (int i = start; i < end; i++) { + result = 31 * result + Longs.hashCode(array[i]); + } + return result; + } + + public String toString() { + StringBuilder builder = new StringBuilder(size() * 10); + builder.append('[').append(array[start]); + for (int i = start + 1; i < end; i++) { + builder.append(", ").append(array[i]); + } + return ']'; + } + + long[] toLongArray() + { + int size = size(); + long[] result = new long[size]; + System.arraycopy(array, start, result, 0, size); + return result; + } + } +} diff --git a/src/minecraft/com/google/common/primitives/ParseRequest.java b/src/minecraft/com/google/common/primitives/ParseRequest.java new file mode 100644 index 0000000..5ad2fa0 --- /dev/null +++ b/src/minecraft/com/google/common/primitives/ParseRequest.java @@ -0,0 +1,57 @@ +package com.google.common.primitives; + +import com.google.common.annotations.GwtCompatible; + + + + + + + + + + + + + + + + +@GwtCompatible +final class ParseRequest +{ + final String rawValue; + final int radix; + + private ParseRequest(String rawValue, int radix) + { + this.rawValue = rawValue; + this.radix = radix; + } + + static ParseRequest fromString(String stringValue) { + if (stringValue.length() == 0) { + throw new NumberFormatException("empty string"); + } + + + + + char firstChar = stringValue.charAt(0); + int radix; String rawValue; int radix; if ((stringValue.startsWith("0x")) || (stringValue.startsWith("0X"))) { + String rawValue = stringValue.substring(2); + radix = 16; } else { int radix; + if (firstChar == '#') { + String rawValue = stringValue.substring(1); + radix = 16; } else { int radix; + if ((firstChar == '0') && (stringValue.length() > 1)) { + String rawValue = stringValue.substring(1); + radix = 8; + } else { + rawValue = stringValue; + radix = 10; + } + } } + return new ParseRequest(rawValue, radix); + } +} diff --git a/src/minecraft/com/google/common/primitives/Primitives.java b/src/minecraft/com/google/common/primitives/Primitives.java new file mode 100644 index 0000000..56508e5 --- /dev/null +++ b/src/minecraft/com/google/common/primitives/Primitives.java @@ -0,0 +1,136 @@ +package com.google.common.primitives; + +import com.google.common.base.Preconditions; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public final class Primitives +{ + private static final Map, Class> PRIMITIVE_TO_WRAPPER_TYPE; + private static final Map, Class> WRAPPER_TO_PRIMITIVE_TYPE; + + static + { + Map, Class> primToWrap = new HashMap(16); + Map, Class> wrapToPrim = new HashMap(16); + + add(primToWrap, wrapToPrim, Boolean.TYPE, Boolean.class); + add(primToWrap, wrapToPrim, Byte.TYPE, Byte.class); + add(primToWrap, wrapToPrim, Character.TYPE, Character.class); + add(primToWrap, wrapToPrim, Double.TYPE, Double.class); + add(primToWrap, wrapToPrim, Float.TYPE, Float.class); + add(primToWrap, wrapToPrim, Integer.TYPE, Integer.class); + add(primToWrap, wrapToPrim, Long.TYPE, Long.class); + add(primToWrap, wrapToPrim, Short.TYPE, Short.class); + add(primToWrap, wrapToPrim, Void.TYPE, Void.class); + + PRIMITIVE_TO_WRAPPER_TYPE = Collections.unmodifiableMap(primToWrap); + WRAPPER_TO_PRIMITIVE_TYPE = Collections.unmodifiableMap(wrapToPrim); + } + + private static void add(Map, Class> forward, Map, Class> backward, Class key, Class value) + { + forward.put(key, value); + backward.put(value, key); + } + + + + + + + + public static Set> allPrimitiveTypes() + { + return PRIMITIVE_TO_WRAPPER_TYPE.keySet(); + } + + + + + + + public static Set> allWrapperTypes() + { + return WRAPPER_TO_PRIMITIVE_TYPE.keySet(); + } + + + + + + + public static boolean isWrapperType(Class type) + { + return WRAPPER_TO_PRIMITIVE_TYPE.containsKey(Preconditions.checkNotNull(type)); + } + + + + + + + + + + public static Class wrap(Class type) + { + Preconditions.checkNotNull(type); + + + + Class wrapped = (Class)PRIMITIVE_TO_WRAPPER_TYPE.get(type); + return wrapped == null ? type : wrapped; + } + + + + + + + + + + public static Class unwrap(Class type) + { + Preconditions.checkNotNull(type); + + + + Class unwrapped = (Class)WRAPPER_TO_PRIMITIVE_TYPE.get(type); + return unwrapped == null ? type : unwrapped; + } + + private Primitives() {} +} diff --git a/src/minecraft/com/google/common/primitives/Shorts.java b/src/minecraft/com/google/common/primitives/Shorts.java new file mode 100644 index 0000000..d29f133 --- /dev/null +++ b/src/minecraft/com/google/common/primitives/Shorts.java @@ -0,0 +1,635 @@ +package com.google.common.primitives; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Converter; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.util.AbstractList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.RandomAccess; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public final class Shorts +{ + public static final int BYTES = 2; + public static final short MAX_POWER_OF_TWO = 16384; + + private Shorts() {} + + public static int hashCode(short value) + { + return value; + } + + + + + + + + + + public static short checkedCast(long value) + { + short result = (short)(int)value; + if (result != value) + { + throw new IllegalArgumentException("Out of range: " + value); + } + return result; + } + + + + + + + + + public static short saturatedCast(long value) + { + if (value > 32767L) { + return Short.MAX_VALUE; + } + if (value < -32768L) { + return Short.MIN_VALUE; + } + return (short)(int)value; + } + + + + + + + + + + + + + public static int compare(short a, short b) + { + return a - b; + } + + + + + + + + + + public static boolean contains(short[] array, short target) + { + for (short value : array) { + if (value == target) { + return true; + } + } + return false; + } + + + + + + + + + + public static int indexOf(short[] array, short target) + { + return indexOf(array, target, 0, array.length); + } + + + private static int indexOf(short[] array, short target, int start, int end) + { + for (int i = start; i < end; i++) { + if (array[i] == target) { + return i; + } + } + return -1; + } + + + + + + + + + + + + public static int indexOf(short[] array, short[] target) + { + Preconditions.checkNotNull(array, "array"); + Preconditions.checkNotNull(target, "target"); + if (target.length == 0) { + return 0; + } + + label64: + for (int i = 0; i < array.length - target.length + 1; i++) { + for (int j = 0; j < target.length; j++) { + if (array[(i + j)] != target[j]) { + break label64; + } + } + return i; + } + return -1; + } + + + + + + + + + + public static int lastIndexOf(short[] array, short target) + { + return lastIndexOf(array, target, 0, array.length); + } + + + private static int lastIndexOf(short[] array, short target, int start, int end) + { + for (int i = end - 1; i >= start; i--) { + if (array[i] == target) { + return i; + } + } + return -1; + } + + + + + + + + + public static short min(short... array) + { + Preconditions.checkArgument(array.length > 0); + short min = array[0]; + for (int i = 1; i < array.length; i++) { + if (array[i] < min) { + min = array[i]; + } + } + return min; + } + + + + + + + + + public static short max(short... array) + { + Preconditions.checkArgument(array.length > 0); + short max = array[0]; + for (int i = 1; i < array.length; i++) { + if (array[i] > max) { + max = array[i]; + } + } + return max; + } + + + + + + + + + + public static short[] concat(short[]... arrays) + { + int length = 0; + for (short[] array : arrays) { + length += array.length; + } + short[] result = new short[length]; + int pos = 0; + for (short[] array : arrays) { + System.arraycopy(array, 0, result, pos, array.length); + pos += array.length; + } + return result; + } + + + + + + + + + + + + + @GwtIncompatible("doesn't work") + public static byte[] toByteArray(short value) + { + return new byte[] { (byte)(value >> 8), (byte)value }; + } + + + + + + + + + + + + + + + @GwtIncompatible("doesn't work") + public static short fromByteArray(byte[] bytes) + { + Preconditions.checkArgument(bytes.length >= 2, "array too small: %s < %s", new Object[] { Integer.valueOf(bytes.length), Integer.valueOf(2) }); + + return fromBytes(bytes[0], bytes[1]); + } + + + + + + + + @GwtIncompatible("doesn't work") + public static short fromBytes(byte b1, byte b2) + { + return (short)(b1 << 8 | b2 & 0xFF); + } + + private static final class ShortConverter extends Converter implements Serializable + { + static final ShortConverter INSTANCE = new ShortConverter(); + + private ShortConverter() {} + + protected Short doForward(String value) { return Short.decode(value); } + + + protected String doBackward(Short value) + { + return value.toString(); + } + + public String toString() + { + return "Shorts.stringConverter()"; + } + + private Object readResolve() { + return INSTANCE; + } + + + + private static final long serialVersionUID = 1L; + } + + + + @Beta + public static Converter stringConverter() + { + return ShortConverter.INSTANCE; + } + + + + + + + + + + + + + + + + + + public static short[] ensureCapacity(short[] array, int minLength, int padding) + { + Preconditions.checkArgument(minLength >= 0, "Invalid minLength: %s", new Object[] { Integer.valueOf(minLength) }); + Preconditions.checkArgument(padding >= 0, "Invalid padding: %s", new Object[] { Integer.valueOf(padding) }); + return array.length < minLength ? copyOf(array, minLength + padding) : array; + } + + + + private static short[] copyOf(short[] original, int length) + { + short[] copy = new short[length]; + System.arraycopy(original, 0, copy, 0, Math.min(original.length, length)); + return copy; + } + + + + + + + + + + public static String join(String separator, short... array) + { + Preconditions.checkNotNull(separator); + if (array.length == 0) { + return ""; + } + + + StringBuilder builder = new StringBuilder(array.length * 6); + builder.append(array[0]); + for (int i = 1; i < array.length; i++) { + builder.append(separator).append(array[i]); + } + return builder.toString(); + } + + + + + + + + + + + + + + + + + public static Comparator lexicographicalComparator() + { + return LexicographicalComparator.INSTANCE; + } + + private static enum LexicographicalComparator implements Comparator { + INSTANCE; + + private LexicographicalComparator() {} + + public int compare(short[] left, short[] right) { int minLength = Math.min(left.length, right.length); + for (int i = 0; i < minLength; i++) { + int result = Shorts.compare(left[i], right[i]); + if (result != 0) { + return result; + } + } + return left.length - right.length; + } + } + + + + + + + + + + + + + + + + public static short[] toArray(Collection collection) + { + if ((collection instanceof ShortArrayAsList)) { + return ((ShortArrayAsList)collection).toShortArray(); + } + + Object[] boxedArray = collection.toArray(); + int len = boxedArray.length; + short[] array = new short[len]; + for (int i = 0; i < len; i++) + { + array[i] = ((Number)Preconditions.checkNotNull(boxedArray[i])).shortValue(); + } + return array; + } + + + + + + + + + + + + + + + public static List asList(short... backingArray) + { + if (backingArray.length == 0) { + return Collections.emptyList(); + } + return new ShortArrayAsList(backingArray); + } + + @GwtCompatible + private static class ShortArrayAsList extends AbstractList implements RandomAccess, Serializable { + final short[] array; + final int start; + final int end; + private static final long serialVersionUID = 0L; + + ShortArrayAsList(short[] array) { + this(array, 0, array.length); + } + + ShortArrayAsList(short[] array, int start, int end) { + this.array = array; + this.start = start; + this.end = end; + } + + public int size() { + return end - start; + } + + public boolean isEmpty() { + return false; + } + + public Short get(int index) { + Preconditions.checkElementIndex(index, size()); + return Short.valueOf(array[(start + index)]); + } + + public boolean contains(Object target) + { + return ((target instanceof Short)) && (Shorts.indexOf(array, ((Short)target).shortValue(), start, end) != -1); + } + + + public int indexOf(Object target) + { + if ((target instanceof Short)) { + int i = Shorts.indexOf(array, ((Short)target).shortValue(), start, end); + if (i >= 0) { + return i - start; + } + } + return -1; + } + + public int lastIndexOf(Object target) + { + if ((target instanceof Short)) { + int i = Shorts.lastIndexOf(array, ((Short)target).shortValue(), start, end); + if (i >= 0) { + return i - start; + } + } + return -1; + } + + public Short set(int index, Short element) { + Preconditions.checkElementIndex(index, size()); + short oldValue = array[(start + index)]; + + array[(start + index)] = ((Short)Preconditions.checkNotNull(element)).shortValue(); + return Short.valueOf(oldValue); + } + + public List subList(int fromIndex, int toIndex) { + int size = size(); + Preconditions.checkPositionIndexes(fromIndex, toIndex, size); + if (fromIndex == toIndex) { + return Collections.emptyList(); + } + return new ShortArrayAsList(array, start + fromIndex, start + toIndex); + } + + public boolean equals(Object object) { + if (object == this) { + return true; + } + if ((object instanceof ShortArrayAsList)) { + ShortArrayAsList that = (ShortArrayAsList)object; + int size = size(); + if (that.size() != size) { + return false; + } + for (int i = 0; i < size; i++) { + if (array[(start + i)] != array[(start + i)]) { + return false; + } + } + return true; + } + return super.equals(object); + } + + public int hashCode() { + int result = 1; + for (int i = start; i < end; i++) { + result = 31 * result + Shorts.hashCode(array[i]); + } + return result; + } + + public String toString() { + StringBuilder builder = new StringBuilder(size() * 6); + builder.append('[').append(array[start]); + for (int i = start + 1; i < end; i++) { + builder.append(", ").append(array[i]); + } + return ']'; + } + + short[] toShortArray() + { + int size = size(); + short[] result = new short[size]; + System.arraycopy(array, start, result, 0, size); + return result; + } + } +} diff --git a/src/minecraft/com/google/common/primitives/SignedBytes.java b/src/minecraft/com/google/common/primitives/SignedBytes.java new file mode 100644 index 0000000..6b6dd93 --- /dev/null +++ b/src/minecraft/com/google/common/primitives/SignedBytes.java @@ -0,0 +1,202 @@ +package com.google.common.primitives; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.Comparator; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public final class SignedBytes +{ + public static final byte MAX_POWER_OF_TWO = 64; + + private SignedBytes() {} + + public static byte checkedCast(long value) + { + byte result = (byte)(int)value; + if (result != value) + { + throw new IllegalArgumentException("Out of range: " + value); + } + return result; + } + + + + + + + + + public static byte saturatedCast(long value) + { + if (value > 127L) { + return Byte.MAX_VALUE; + } + if (value < -128L) { + return Byte.MIN_VALUE; + } + return (byte)(int)value; + } + + + + + + + + + + + + + + + public static int compare(byte a, byte b) + { + return a - b; + } + + + + + + + + + public static byte min(byte... array) + { + Preconditions.checkArgument(array.length > 0); + byte min = array[0]; + for (int i = 1; i < array.length; i++) { + if (array[i] < min) { + min = array[i]; + } + } + return min; + } + + + + + + + + + public static byte max(byte... array) + { + Preconditions.checkArgument(array.length > 0); + byte max = array[0]; + for (int i = 1; i < array.length; i++) { + if (array[i] > max) { + max = array[i]; + } + } + return max; + } + + + + + + + + + + public static String join(String separator, byte... array) + { + Preconditions.checkNotNull(separator); + if (array.length == 0) { + return ""; + } + + + StringBuilder builder = new StringBuilder(array.length * 5); + builder.append(array[0]); + for (int i = 1; i < array.length; i++) { + builder.append(separator).append(array[i]); + } + return builder.toString(); + } + + + + + + + + + + + + + + + + + public static Comparator lexicographicalComparator() + { + return LexicographicalComparator.INSTANCE; + } + + private static enum LexicographicalComparator implements Comparator { + INSTANCE; + + private LexicographicalComparator() {} + + public int compare(byte[] left, byte[] right) { int minLength = Math.min(left.length, right.length); + for (int i = 0; i < minLength; i++) { + int result = SignedBytes.compare(left[i], right[i]); + if (result != 0) { + return result; + } + } + return left.length - right.length; + } + } +} diff --git a/src/minecraft/com/google/common/primitives/UnsignedBytes.java b/src/minecraft/com/google/common/primitives/UnsignedBytes.java new file mode 100644 index 0000000..9548407 --- /dev/null +++ b/src/minecraft/com/google/common/primitives/UnsignedBytes.java @@ -0,0 +1,441 @@ +package com.google.common.primitives; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import java.lang.reflect.Field; +import java.nio.ByteOrder; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.Comparator; +import sun.misc.Unsafe; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public final class UnsignedBytes +{ + public static final byte MAX_POWER_OF_TWO = -128; + public static final byte MAX_VALUE = -1; + private static final int UNSIGNED_MASK = 255; + + private UnsignedBytes() {} + + public static int toInt(byte value) + { + return value & 0xFF; + } + + + + + + + + + + + public static byte checkedCast(long value) + { + if (value >> 8 != 0L) + { + throw new IllegalArgumentException("Out of range: " + value); + } + return (byte)(int)value; + } + + + + + + + + + public static byte saturatedCast(long value) + { + if (value > toInt((byte)-1)) { + return -1; + } + if (value < 0L) { + return 0; + } + return (byte)(int)value; + } + + + + + + + + + + + + public static int compare(byte a, byte b) + { + return toInt(a) - toInt(b); + } + + + + + + + + + public static byte min(byte... array) + { + Preconditions.checkArgument(array.length > 0); + int min = toInt(array[0]); + for (int i = 1; i < array.length; i++) { + int next = toInt(array[i]); + if (next < min) { + min = next; + } + } + return (byte)min; + } + + + + + + + + + public static byte max(byte... array) + { + Preconditions.checkArgument(array.length > 0); + int max = toInt(array[0]); + for (int i = 1; i < array.length; i++) { + int next = toInt(array[i]); + if (next > max) { + max = next; + } + } + return (byte)max; + } + + + + + + @Beta + public static String toString(byte x) + { + return toString(x, 10); + } + + + + + + + + + + + @Beta + public static String toString(byte x, int radix) + { + Preconditions.checkArgument((radix >= 2) && (radix <= 36), "radix (%s) must be between Character.MIN_RADIX and Character.MAX_RADIX", new Object[] { Integer.valueOf(radix) }); + + + return Integer.toString(toInt(x), radix); + } + + + + + + + + + + @Beta + public static byte parseUnsignedByte(String string) + { + return parseUnsignedByte(string, 10); + } + + + + + + + + + + + + + @Beta + public static byte parseUnsignedByte(String string, int radix) + { + int parse = Integer.parseInt((String)Preconditions.checkNotNull(string), radix); + + if (parse >> 8 == 0) { + return (byte)parse; + } + throw new NumberFormatException("out of range: " + parse); + } + + + + + + + + + + + public static String join(String separator, byte... array) + { + Preconditions.checkNotNull(separator); + if (array.length == 0) { + return ""; + } + + + StringBuilder builder = new StringBuilder(array.length * (3 + separator.length())); + builder.append(toInt(array[0])); + for (int i = 1; i < array.length; i++) { + builder.append(separator).append(toString(array[i])); + } + return builder.toString(); + } + + + + + + + + + + + + + + + + + public static Comparator lexicographicalComparator() + { + return LexicographicalComparatorHolder.BEST_COMPARATOR; + } + + @VisibleForTesting + static Comparator lexicographicalComparatorJavaImpl() { + return UnsignedBytes.LexicographicalComparatorHolder.PureJavaComparator.INSTANCE; + } + + + + + + + + @VisibleForTesting + static class LexicographicalComparatorHolder + { + static final String UNSAFE_COMPARATOR_NAME = LexicographicalComparatorHolder.class.getName() + "$UnsafeComparator"; + + + static final Comparator BEST_COMPARATOR = getBestComparator(); + LexicographicalComparatorHolder() {} + + @VisibleForTesting + static enum UnsafeComparator implements Comparator { INSTANCE; + + static { BIG_ENDIAN = ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN); + + + + + + + + + + + + + + + + + + + + + + + + + + + + theUnsafe = getUnsafe(); + + BYTE_ARRAY_BASE_OFFSET = theUnsafe.arrayBaseOffset([B.class); + + + if (theUnsafe.arrayIndexScale([B.class) != 1) { + throw new AssertionError(); + } + } + + + static final boolean BIG_ENDIAN; + + static final Unsafe theUnsafe; + static final int BYTE_ARRAY_BASE_OFFSET; + private static Unsafe getUnsafe() + { + try + { + return Unsafe.getUnsafe(); + } catch (SecurityException tryReflectionInstead) { + try { + (Unsafe)AccessController.doPrivileged(new PrivilegedExceptionAction() + { + public Unsafe run() throws Exception { + Class k = Unsafe.class; + for (Field f : k.getDeclaredFields()) { + f.setAccessible(true); + Object x = f.get(null); + if (k.isInstance(x)) + return (Unsafe)k.cast(x); + } + throw new NoSuchFieldError("the Unsafe"); + } + }); + } catch (PrivilegedActionException e) { throw new RuntimeException("Could not initialize intrinsics", e.getCause()); + } + } + } + + public int compare(byte[] left, byte[] right) { + int minLength = Math.min(left.length, right.length); + int minWords = minLength / 8; + + + + + + + for (int i = 0; i < minWords * 8; i += 8) { + long lw = theUnsafe.getLong(left, BYTE_ARRAY_BASE_OFFSET + i); + long rw = theUnsafe.getLong(right, BYTE_ARRAY_BASE_OFFSET + i); + if (lw != rw) { + if (BIG_ENDIAN) { + return UnsignedLongs.compare(lw, rw); + } + + + + + + + + + int n = Long.numberOfTrailingZeros(lw ^ rw) & 0xFFFFFFF8; + return (int)((lw >>> n & 0xFF) - (rw >>> n & 0xFF)); + } + } + + + for (int i = minWords * 8; i < minLength; i++) { + int result = UnsignedBytes.compare(left[i], right[i]); + if (result != 0) { + return result; + } + } + return left.length - right.length; + } + + private UnsafeComparator() {} } + + static enum PureJavaComparator implements Comparator { INSTANCE; + + private PureJavaComparator() {} + public int compare(byte[] left, byte[] right) { int minLength = Math.min(left.length, right.length); + for (int i = 0; i < minLength; i++) { + int result = UnsignedBytes.compare(left[i], right[i]); + if (result != 0) { + return result; + } + } + return left.length - right.length; + } + } + + + + static Comparator getBestComparator() + { + try + { + Class theClass = Class.forName(UNSAFE_COMPARATOR_NAME); + + + + return (Comparator)theClass.getEnumConstants()[0]; + } + catch (Throwable t) {} + + return UnsignedBytes.lexicographicalComparatorJavaImpl(); + } + } +} diff --git a/src/minecraft/com/google/common/primitives/UnsignedInteger.java b/src/minecraft/com/google/common/primitives/UnsignedInteger.java new file mode 100644 index 0000000..a4fcd40 --- /dev/null +++ b/src/minecraft/com/google/common/primitives/UnsignedInteger.java @@ -0,0 +1,261 @@ +package com.google.common.primitives; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.annotations.GwtIncompatible; +import com.google.common.base.Preconditions; +import java.math.BigInteger; +import javax.annotation.CheckReturnValue; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(emulated=true) +public final class UnsignedInteger + extends Number + implements Comparable +{ + public static final UnsignedInteger ZERO = fromIntBits(0); + public static final UnsignedInteger ONE = fromIntBits(1); + public static final UnsignedInteger MAX_VALUE = fromIntBits(-1); + + private final int value; + + private UnsignedInteger(int value) + { + this.value = (value & 0xFFFFFFFF); + } + + + + + + + + + + + + + public static UnsignedInteger fromIntBits(int bits) + { + return new UnsignedInteger(bits); + } + + + + + public static UnsignedInteger valueOf(long value) + { + Preconditions.checkArgument((value & 0xFFFFFFFF) == value, "value (%s) is outside the range for an unsigned integer value", new Object[] { Long.valueOf(value) }); + + return fromIntBits((int)value); + } + + + + + + + public static UnsignedInteger valueOf(BigInteger value) + { + Preconditions.checkNotNull(value); + Preconditions.checkArgument((value.signum() >= 0) && (value.bitLength() <= 32), "value (%s) is outside the range for an unsigned integer value", new Object[] { value }); + + return fromIntBits(value.intValue()); + } + + + + + + + + public static UnsignedInteger valueOf(String string) + { + return valueOf(string, 10); + } + + + + + + + + public static UnsignedInteger valueOf(String string, int radix) + { + return fromIntBits(UnsignedInts.parseUnsignedInt(string, radix)); + } + + + + + + + @CheckReturnValue + public UnsignedInteger plus(UnsignedInteger val) + { + return fromIntBits(value + checkNotNullvalue); + } + + + + + + + @CheckReturnValue + public UnsignedInteger minus(UnsignedInteger val) + { + return fromIntBits(value - checkNotNullvalue); + } + + + + + + + + @CheckReturnValue + @GwtIncompatible("Does not truncate correctly") + public UnsignedInteger times(UnsignedInteger val) + { + return fromIntBits(value * checkNotNullvalue); + } + + + + + + + @CheckReturnValue + public UnsignedInteger dividedBy(UnsignedInteger val) + { + return fromIntBits(UnsignedInts.divide(value, checkNotNullvalue)); + } + + + + + + + @CheckReturnValue + public UnsignedInteger mod(UnsignedInteger val) + { + return fromIntBits(UnsignedInts.remainder(value, checkNotNullvalue)); + } + + + + + + + + + public int intValue() + { + return value; + } + + + + + public long longValue() + { + return UnsignedInts.toLong(value); + } + + + + + + public float floatValue() + { + return (float)longValue(); + } + + + + + + public double doubleValue() + { + return longValue(); + } + + + + public BigInteger bigIntegerValue() + { + return BigInteger.valueOf(longValue()); + } + + + + + + + public int compareTo(UnsignedInteger other) + { + Preconditions.checkNotNull(other); + return UnsignedInts.compare(value, value); + } + + public int hashCode() + { + return value; + } + + public boolean equals(@Nullable Object obj) + { + if ((obj instanceof UnsignedInteger)) { + UnsignedInteger other = (UnsignedInteger)obj; + return value == value; + } + return false; + } + + + + + public String toString() + { + return toString(10); + } + + + + + + public String toString(int radix) + { + return UnsignedInts.toString(value, radix); + } +} diff --git a/src/minecraft/com/google/common/primitives/UnsignedInts.java b/src/minecraft/com/google/common/primitives/UnsignedInts.java new file mode 100644 index 0000000..b8108b2 --- /dev/null +++ b/src/minecraft/com/google/common/primitives/UnsignedInts.java @@ -0,0 +1,276 @@ +package com.google.common.primitives; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.util.Comparator; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +public final class UnsignedInts +{ + static final long INT_MASK = 4294967295L; + + private UnsignedInts() {} + + static int flip(int value) + { + return value ^ 0x80000000; + } + + + + + + + + + + public static int compare(int a, int b) + { + return Ints.compare(flip(a), flip(b)); + } + + + + public static long toLong(int value) + { + return value & 0xFFFFFFFF; + } + + + + + + + + + public static int min(int... array) + { + Preconditions.checkArgument(array.length > 0); + int min = flip(array[0]); + for (int i = 1; i < array.length; i++) { + int next = flip(array[i]); + if (next < min) { + min = next; + } + } + return flip(min); + } + + + + + + + + + public static int max(int... array) + { + Preconditions.checkArgument(array.length > 0); + int max = flip(array[0]); + for (int i = 1; i < array.length; i++) { + int next = flip(array[i]); + if (next > max) { + max = next; + } + } + return flip(max); + } + + + + + + + + + public static String join(String separator, int... array) + { + Preconditions.checkNotNull(separator); + if (array.length == 0) { + return ""; + } + + + StringBuilder builder = new StringBuilder(array.length * 5); + builder.append(toString(array[0])); + for (int i = 1; i < array.length; i++) { + builder.append(separator).append(toString(array[i])); + } + return builder.toString(); + } + + + + + + + + + + + + + public static Comparator lexicographicalComparator() + { + return LexicographicalComparator.INSTANCE; + } + + static enum LexicographicalComparator implements Comparator { + INSTANCE; + + private LexicographicalComparator() {} + + public int compare(int[] left, int[] right) { int minLength = Math.min(left.length, right.length); + for (int i = 0; i < minLength; i++) { + if (left[i] != right[i]) { + return UnsignedInts.compare(left[i], right[i]); + } + } + return left.length - right.length; + } + } + + + + + + + + + public static int divide(int dividend, int divisor) + { + return (int)(toLong(dividend) / toLong(divisor)); + } + + + + + + + + + public static int remainder(int dividend, int divisor) + { + return (int)(toLong(dividend) % toLong(divisor)); + } + + + + + + + + + + + + + + + + public static int decode(String stringValue) + { + ParseRequest request = ParseRequest.fromString(stringValue); + try + { + return parseUnsignedInt(rawValue, radix); + } catch (NumberFormatException e) { + NumberFormatException decodeException = new NumberFormatException("Error parsing value: " + stringValue); + + decodeException.initCause(e); + throw decodeException; + } + } + + + + + + + + public static int parseUnsignedInt(String s) + { + return parseUnsignedInt(s, 10); + } + + + + + + + + + + + + public static int parseUnsignedInt(String string, int radix) + { + Preconditions.checkNotNull(string); + long result = Long.parseLong(string, radix); + if ((result & 0xFFFFFFFF) != result) { + throw new NumberFormatException("Input " + string + " in base " + radix + " is not in the range of an unsigned integer"); + } + + return (int)result; + } + + + + public static String toString(int x) + { + return toString(x, 10); + } + + + + + + + + + + public static String toString(int x, int radix) + { + long asLong = x & 0xFFFFFFFF; + return Long.toString(asLong, radix); + } +} diff --git a/src/minecraft/com/google/common/primitives/UnsignedLong.java b/src/minecraft/com/google/common/primitives/UnsignedLong.java new file mode 100644 index 0000000..a068eaf --- /dev/null +++ b/src/minecraft/com/google/common/primitives/UnsignedLong.java @@ -0,0 +1,269 @@ +package com.google.common.primitives; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.io.Serializable; +import java.math.BigInteger; +import javax.annotation.CheckReturnValue; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible(serializable=true) +public final class UnsignedLong + extends Number + implements Comparable, Serializable +{ + private static final long UNSIGNED_MASK = Long.MAX_VALUE; + public static final UnsignedLong ZERO = new UnsignedLong(0L); + public static final UnsignedLong ONE = new UnsignedLong(1L); + public static final UnsignedLong MAX_VALUE = new UnsignedLong(-1L); + private final long value; + + private UnsignedLong(long value) + { + this.value = value; + } + + + + + + + + + + + + + + + public static UnsignedLong fromLongBits(long bits) + { + return new UnsignedLong(bits); + } + + + + + + + public static UnsignedLong valueOf(long value) + { + Preconditions.checkArgument(value >= 0L, "value (%s) is outside the range for an unsigned long value", new Object[] { Long.valueOf(value) }); + + return fromLongBits(value); + } + + + + + + + public static UnsignedLong valueOf(BigInteger value) + { + Preconditions.checkNotNull(value); + Preconditions.checkArgument((value.signum() >= 0) && (value.bitLength() <= 64), "value (%s) is outside the range for an unsigned long value", new Object[] { value }); + + return fromLongBits(value.longValue()); + } + + + + + + + + public static UnsignedLong valueOf(String string) + { + return valueOf(string, 10); + } + + + + + + + + + public static UnsignedLong valueOf(String string, int radix) + { + return fromLongBits(UnsignedLongs.parseUnsignedLong(string, radix)); + } + + + + + + + public UnsignedLong plus(UnsignedLong val) + { + return fromLongBits(value + checkNotNullvalue); + } + + + + + + + public UnsignedLong minus(UnsignedLong val) + { + return fromLongBits(value - checkNotNullvalue); + } + + + + + + + @CheckReturnValue + public UnsignedLong times(UnsignedLong val) + { + return fromLongBits(value * checkNotNullvalue); + } + + + + + + @CheckReturnValue + public UnsignedLong dividedBy(UnsignedLong val) + { + return fromLongBits(UnsignedLongs.divide(value, checkNotNullvalue)); + } + + + + + + @CheckReturnValue + public UnsignedLong mod(UnsignedLong val) + { + return fromLongBits(UnsignedLongs.remainder(value, checkNotNullvalue)); + } + + + + + public int intValue() + { + return (int)value; + } + + + + + + + + + public long longValue() + { + return value; + } + + + + + + + public float floatValue() + { + float fValue = (float)(value & 0x7FFFFFFFFFFFFFFF); + if (value < 0L) { + fValue += 9.223372E18F; + } + return fValue; + } + + + + + + + public double doubleValue() + { + double dValue = value & 0x7FFFFFFFFFFFFFFF; + if (value < 0L) { + dValue += 9.223372036854776E18D; + } + return dValue; + } + + + + public BigInteger bigIntegerValue() + { + BigInteger bigInt = BigInteger.valueOf(value & 0x7FFFFFFFFFFFFFFF); + if (value < 0L) { + bigInt = bigInt.setBit(63); + } + return bigInt; + } + + public int compareTo(UnsignedLong o) + { + Preconditions.checkNotNull(o); + return UnsignedLongs.compare(value, value); + } + + public int hashCode() + { + return Longs.hashCode(value); + } + + public boolean equals(@Nullable Object obj) + { + if ((obj instanceof UnsignedLong)) { + UnsignedLong other = (UnsignedLong)obj; + return value == value; + } + return false; + } + + + + + public String toString() + { + return UnsignedLongs.toString(value); + } + + + + + + public String toString(int radix) + { + return UnsignedLongs.toString(value, radix); + } +} diff --git a/src/minecraft/com/google/common/primitives/UnsignedLongs.java b/src/minecraft/com/google/common/primitives/UnsignedLongs.java new file mode 100644 index 0000000..d40fc6b --- /dev/null +++ b/src/minecraft/com/google/common/primitives/UnsignedLongs.java @@ -0,0 +1,395 @@ +package com.google.common.primitives; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Preconditions; +import java.math.BigInteger; +import java.util.Comparator; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +public final class UnsignedLongs +{ + public static final long MAX_VALUE = -1L; + + private UnsignedLongs() {} + + private static long flip(long a) + { + return a ^ 0x8000000000000000; + } + + + + + + + + + + public static int compare(long a, long b) + { + return Longs.compare(flip(a), flip(b)); + } + + + + + + + + + public static long min(long... array) + { + Preconditions.checkArgument(array.length > 0); + long min = flip(array[0]); + for (int i = 1; i < array.length; i++) { + long next = flip(array[i]); + if (next < min) { + min = next; + } + } + return flip(min); + } + + + + + + + + + public static long max(long... array) + { + Preconditions.checkArgument(array.length > 0); + long max = flip(array[0]); + for (int i = 1; i < array.length; i++) { + long next = flip(array[i]); + if (next > max) { + max = next; + } + } + return flip(max); + } + + + + + + + + + public static String join(String separator, long... array) + { + Preconditions.checkNotNull(separator); + if (array.length == 0) { + return ""; + } + + + StringBuilder builder = new StringBuilder(array.length * 5); + builder.append(toString(array[0])); + for (int i = 1; i < array.length; i++) { + builder.append(separator).append(toString(array[i])); + } + return builder.toString(); + } + + + + + + + + + + + + + + public static Comparator lexicographicalComparator() + { + return LexicographicalComparator.INSTANCE; + } + + static enum LexicographicalComparator implements Comparator { + INSTANCE; + + private LexicographicalComparator() {} + + public int compare(long[] left, long[] right) { int minLength = Math.min(left.length, right.length); + for (int i = 0; i < minLength; i++) { + if (left[i] != right[i]) { + return UnsignedLongs.compare(left[i], right[i]); + } + } + return left.length - right.length; + } + } + + + + + + + + + public static long divide(long dividend, long divisor) + { + if (divisor < 0L) { + if (compare(dividend, divisor) < 0) { + return 0L; + } + return 1L; + } + + + + if (dividend >= 0L) { + return dividend / divisor; + } + + + + + + + + long quotient = (dividend >>> 1) / divisor << 1; + long rem = dividend - quotient * divisor; + return quotient + (compare(rem, divisor) >= 0 ? 1 : 0); + } + + + + + + + + + + public static long remainder(long dividend, long divisor) + { + if (divisor < 0L) { + if (compare(dividend, divisor) < 0) { + return dividend; + } + return dividend - divisor; + } + + + + if (dividend >= 0L) { + return dividend % divisor; + } + + + + + + + + long quotient = (dividend >>> 1) / divisor << 1; + long rem = dividend - quotient * divisor; + return rem - (compare(rem, divisor) >= 0 ? divisor : 0L); + } + + + + + + + + + public static long parseUnsignedLong(String s) + { + return parseUnsignedLong(s, 10); + } + + + + + + + + + + + + + + + + + public static long decode(String stringValue) + { + ParseRequest request = ParseRequest.fromString(stringValue); + try + { + return parseUnsignedLong(rawValue, radix); + } catch (NumberFormatException e) { + NumberFormatException decodeException = new NumberFormatException("Error parsing value: " + stringValue); + + decodeException.initCause(e); + throw decodeException; + } + } + + + + + + + + + + + + public static long parseUnsignedLong(String s, int radix) + { + Preconditions.checkNotNull(s); + if (s.length() == 0) { + throw new NumberFormatException("empty string"); + } + if ((radix < 2) || (radix > 36)) { + throw new NumberFormatException("illegal radix: " + radix); + } + + int max_safe_pos = maxSafeDigits[radix] - 1; + long value = 0L; + for (int pos = 0; pos < s.length(); pos++) { + int digit = Character.digit(s.charAt(pos), radix); + if (digit == -1) { + throw new NumberFormatException(s); + } + if ((pos > max_safe_pos) && (overflowInParse(value, digit, radix))) { + throw new NumberFormatException("Too large for unsigned long: " + s); + } + value = value * radix + digit; + } + + return value; + } + + + + + + + private static boolean overflowInParse(long current, int digit, int radix) + { + if (current >= 0L) { + if (current < maxValueDivs[radix]) { + return false; + } + if (current > maxValueDivs[radix]) { + return true; + } + + return digit > maxValueMods[radix]; + } + + + return true; + } + + + + public static String toString(long x) + { + return toString(x, 10); + } + + + + + + + + + + public static String toString(long x, int radix) + { + Preconditions.checkArgument((radix >= 2) && (radix <= 36), "radix (%s) must be between Character.MIN_RADIX and Character.MAX_RADIX", new Object[] { Integer.valueOf(radix) }); + + if (x == 0L) + { + return "0"; + } + char[] buf = new char[64]; + int i = buf.length; + if (x < 0L) + { + + long quotient = divide(x, radix); + long rem = x - quotient * radix; + buf[(--i)] = Character.forDigit((int)rem, radix); + x = quotient; + } + + while (x > 0L) { + buf[(--i)] = Character.forDigit((int)(x % radix), radix); + x /= radix; + } + + return new String(buf, i, buf.length - i); + } + + + + private static final long[] maxValueDivs = new long[37]; + private static final int[] maxValueMods = new int[37]; + private static final int[] maxSafeDigits = new int[37]; + + static { BigInteger overflow = new BigInteger("10000000000000000", 16); + for (int i = 2; i <= 36; i++) { + maxValueDivs[i] = divide(-1L, i); + maxValueMods[i] = ((int)remainder(-1L, i)); + maxSafeDigits[i] = (overflow.toString(i).length() - 1); + } + } +} diff --git a/src/minecraft/com/google/common/primitives/package-info.java b/src/minecraft/com/google/common/primitives/package-info.java new file mode 100644 index 0000000..13671c9 --- /dev/null +++ b/src/minecraft/com/google/common/primitives/package-info.java @@ -0,0 +1,6 @@ +package com.google.common.primitives; + +import javax.annotation.ParametersAreNonnullByDefault; + +@ParametersAreNonnullByDefault +abstract interface package-info {} diff --git a/src/minecraft/com/google/common/reflect/AbstractInvocationHandler.java b/src/minecraft/com/google/common/reflect/AbstractInvocationHandler.java new file mode 100644 index 0000000..00e68c1 --- /dev/null +++ b/src/minecraft/com/google/common/reflect/AbstractInvocationHandler.java @@ -0,0 +1,133 @@ +package com.google.common.reflect; + +import com.google.common.annotations.Beta; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.Arrays; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public abstract class AbstractInvocationHandler + implements InvocationHandler +{ + private static final Object[] NO_ARGS = new Object[0]; + + + + + + + + public AbstractInvocationHandler() {} + + + + + + + public final Object invoke(Object proxy, Method method, @Nullable Object[] args) + throws Throwable + { + if (args == null) { + args = NO_ARGS; + } + if ((args.length == 0) && (method.getName().equals("hashCode"))) { + return Integer.valueOf(hashCode()); + } + if ((args.length == 1) && (method.getName().equals("equals")) && (method.getParameterTypes()[0] == Object.class)) + { + + Object arg = args[0]; + if (arg == null) { + return Boolean.valueOf(false); + } + if (proxy == arg) { + return Boolean.valueOf(true); + } + return Boolean.valueOf((isProxyOfSameInterfaces(arg, proxy.getClass())) && (equals(Proxy.getInvocationHandler(arg)))); + } + + if ((args.length == 0) && (method.getName().equals("toString"))) { + return toString(); + } + return handleInvocation(proxy, method, args); + } + + + + + + + + + + protected abstract Object handleInvocation(Object paramObject, Method paramMethod, Object[] paramArrayOfObject) + throws Throwable; + + + + + + + + + public boolean equals(Object obj) + { + return super.equals(obj); + } + + + + + public int hashCode() + { + return super.hashCode(); + } + + + + + + public String toString() + { + return super.toString(); + } + + private static boolean isProxyOfSameInterfaces(Object arg, Class proxyClass) { + return (proxyClass.isInstance(arg)) || ((Proxy.isProxyClass(arg.getClass())) && (Arrays.equals(arg.getClass().getInterfaces(), proxyClass.getInterfaces()))); + } +} diff --git a/src/minecraft/com/google/common/reflect/ClassPath.java b/src/minecraft/com/google/common/reflect/ClassPath.java new file mode 100644 index 0000000..e6f95d6 --- /dev/null +++ b/src/minecraft/com/google/common/reflect/ClassPath.java @@ -0,0 +1,444 @@ +package com.google.common.reflect; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.CharMatcher; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.base.Splitter; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSet.Builder; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.ImmutableSortedSet.Builder; +import com.google.common.collect.Maps; +import com.google.common.collect.Ordering; +import com.google.common.collect.Sets; +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Enumeration; +import java.util.LinkedHashMap; +import java.util.Map.Entry; +import java.util.Set; +import java.util.jar.Attributes; +import java.util.jar.Attributes.Name; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.jar.Manifest; +import java.util.logging.Logger; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class ClassPath +{ + private static final Logger logger = Logger.getLogger(ClassPath.class.getName()); + + private static final Predicate IS_TOP_LEVEL = new Predicate() { + public boolean apply(ClassPath.ClassInfo info) { + return className.indexOf('$') == -1; + } + }; + + + private static final Splitter CLASS_PATH_ATTRIBUTE_SEPARATOR = Splitter.on(" ").omitEmptyStrings(); + + private static final String CLASS_FILE_NAME_EXTENSION = ".class"; + + private final ImmutableSet resources; + + private ClassPath(ImmutableSet resources) + { + this.resources = resources; + } + + + + + + + + + public static ClassPath from(ClassLoader classloader) + throws IOException + { + Scanner scanner = new Scanner(); + for (Map.Entry entry : getClassPathEntries(classloader).entrySet()) { + scanner.scan((URI)entry.getKey(), (ClassLoader)entry.getValue()); + } + return new ClassPath(scanner.getResources()); + } + + + + + public ImmutableSet getResources() + { + return resources; + } + + + + + + public ImmutableSet getAllClasses() + { + return FluentIterable.from(resources).filter(ClassInfo.class).toSet(); + } + + public ImmutableSet getTopLevelClasses() + { + return FluentIterable.from(resources).filter(ClassInfo.class).filter(IS_TOP_LEVEL).toSet(); + } + + public ImmutableSet getTopLevelClasses(String packageName) + { + Preconditions.checkNotNull(packageName); + ImmutableSet.Builder builder = ImmutableSet.builder(); + for (ClassInfo classInfo : getTopLevelClasses()) { + if (classInfo.getPackageName().equals(packageName)) { + builder.add(classInfo); + } + } + return builder.build(); + } + + + + + public ImmutableSet getTopLevelClassesRecursive(String packageName) + { + Preconditions.checkNotNull(packageName); + String packagePrefix = packageName + '.'; + ImmutableSet.Builder builder = ImmutableSet.builder(); + for (ClassInfo classInfo : getTopLevelClasses()) { + if (classInfo.getName().startsWith(packagePrefix)) { + builder.add(classInfo); + } + } + return builder.build(); + } + + + + @Beta + public static class ResourceInfo + { + private final String resourceName; + + final ClassLoader loader; + + + static ResourceInfo of(String resourceName, ClassLoader loader) + { + if (resourceName.endsWith(".class")) { + return new ClassPath.ClassInfo(resourceName, loader); + } + return new ResourceInfo(resourceName, loader); + } + + ResourceInfo(String resourceName, ClassLoader loader) + { + this.resourceName = ((String)Preconditions.checkNotNull(resourceName)); + this.loader = ((ClassLoader)Preconditions.checkNotNull(loader)); + } + + public final URL url() + { + return (URL)Preconditions.checkNotNull(loader.getResource(resourceName), "Failed to load resource: %s", new Object[] { resourceName }); + } + + + public final String getResourceName() + { + return resourceName; + } + + public int hashCode() { + return resourceName.hashCode(); + } + + public boolean equals(Object obj) { + if ((obj instanceof ResourceInfo)) { + ResourceInfo that = (ResourceInfo)obj; + return (resourceName.equals(resourceName)) && (loader == loader); + } + + return false; + } + + public String toString() + { + return resourceName; + } + } + + + @Beta + public static final class ClassInfo + extends ClassPath.ResourceInfo + { + private final String className; + + + ClassInfo(String resourceName, ClassLoader loader) + { + super(loader); + className = ClassPath.getClassName(resourceName); + } + + + + + + + public String getPackageName() + { + return Reflection.getPackageName(className); + } + + + + + + + public String getSimpleName() + { + int lastDollarSign = className.lastIndexOf('$'); + if (lastDollarSign != -1) { + String innerClassName = className.substring(lastDollarSign + 1); + + + return CharMatcher.DIGIT.trimLeadingFrom(innerClassName); + } + String packageName = getPackageName(); + if (packageName.isEmpty()) { + return className; + } + + + return className.substring(packageName.length() + 1); + } + + + + + + + public String getName() + { + return className; + } + + + + + + public Class load() + { + try + { + return loader.loadClass(className); + } + catch (ClassNotFoundException e) { + throw new IllegalStateException(e); + } + } + + public String toString() { + return className; + } + } + + @VisibleForTesting + static ImmutableMap getClassPathEntries(ClassLoader classloader) { + LinkedHashMap entries = Maps.newLinkedHashMap(); + + ClassLoader parent = classloader.getParent(); + if (parent != null) { + entries.putAll(getClassPathEntries(parent)); + } + if ((classloader instanceof URLClassLoader)) { + URLClassLoader urlClassLoader = (URLClassLoader)classloader; + for (URL entry : urlClassLoader.getURLs()) { + URI uri; + try { + uri = entry.toURI(); + } catch (URISyntaxException e) { + throw new IllegalArgumentException(e); + } + if (!entries.containsKey(uri)) { + entries.put(uri, classloader); + } + } + } + return ImmutableMap.copyOf(entries); } + + @VisibleForTesting + static final class Scanner { Scanner() {} + + private final ImmutableSortedSet.Builder resources = new ImmutableSortedSet.Builder(Ordering.usingToString()); + + private final Set scannedUris = Sets.newHashSet(); + + ImmutableSortedSet getResources() { + return resources.build(); + } + + void scan(URI uri, ClassLoader classloader) throws IOException { + if ((uri.getScheme().equals("file")) && (scannedUris.add(uri))) { + scanFrom(new File(uri), classloader); + } + } + + @VisibleForTesting + void scanFrom(File file, ClassLoader classloader) throws IOException { + if (!file.exists()) { + return; + } + if (file.isDirectory()) { + scanDirectory(file, classloader); + } else { + scanJar(file, classloader); + } + } + + private void scanDirectory(File directory, ClassLoader classloader) throws IOException { + scanDirectory(directory, classloader, "", ImmutableSet.of()); + } + + private void scanDirectory(File directory, ClassLoader classloader, String packagePrefix, ImmutableSet ancestors) + throws IOException + { + File canonical = directory.getCanonicalFile(); + if (ancestors.contains(canonical)) + { + return; + } + File[] files = directory.listFiles(); + if (files == null) { + ClassPath.logger.warning("Cannot read directory " + directory); + + return; + } + ImmutableSet newAncestors = ImmutableSet.builder().addAll(ancestors).add(canonical).build(); + + + + for (File f : files) { + String name = f.getName(); + if (f.isDirectory()) { + scanDirectory(f, classloader, packagePrefix + name + "/", newAncestors); + } else { + String resourceName = packagePrefix + name; + if (!resourceName.equals("META-INF/MANIFEST.MF")) { + resources.add(ClassPath.ResourceInfo.of(resourceName, classloader)); + } + } + } + } + + private void scanJar(File file, ClassLoader classloader) throws IOException { + JarFile jarFile; + try { + jarFile = new JarFile(file); + } + catch (IOException e) { + return; + } + try { + for (URI uri : getClassPathFromManifest(file, jarFile.getManifest())) { + scan(uri, classloader); + } + Enumeration entries = jarFile.entries(); + while (entries.hasMoreElements()) { + JarEntry entry = (JarEntry)entries.nextElement(); + if ((!entry.isDirectory()) && (!entry.getName().equals("META-INF/MANIFEST.MF"))) + { + + resources.add(ClassPath.ResourceInfo.of(entry.getName(), classloader)); } + } + return; + } finally { + try { jarFile.close(); + } + catch (IOException ignored) {} + } + } + + + + + + @VisibleForTesting + static ImmutableSet getClassPathFromManifest(File jarFile, @Nullable Manifest manifest) + { + if (manifest == null) { + return ImmutableSet.of(); + } + ImmutableSet.Builder builder = ImmutableSet.builder(); + String classpathAttribute = manifest.getMainAttributes().getValue(Attributes.Name.CLASS_PATH.toString()); + + if (classpathAttribute != null) { + for (String path : ClassPath.CLASS_PATH_ATTRIBUTE_SEPARATOR.split(classpathAttribute)) { + URI uri; + try { + uri = getClassPathEntry(jarFile, path); + } + catch (URISyntaxException e) { + ClassPath.logger.warning("Invalid Class-Path entry: " + path); } + continue; + + builder.add(uri); + } + } + return builder.build(); + } + + + + + + @VisibleForTesting + static URI getClassPathEntry(File jarFile, String path) + throws URISyntaxException + { + URI uri = new URI(path); + if (uri.isAbsolute()) { + return uri; + } + return new File(jarFile.getParentFile(), path.replace('/', File.separatorChar)).toURI(); + } + } + + @VisibleForTesting + static String getClassName(String filename) { + int classNameEnd = filename.length() - ".class".length(); + return filename.substring(0, classNameEnd).replace('/', '.'); + } +} diff --git a/src/minecraft/com/google/common/reflect/Element.java b/src/minecraft/com/google/common/reflect/Element.java new file mode 100644 index 0000000..bfbf280 --- /dev/null +++ b/src/minecraft/com/google/common/reflect/Element.java @@ -0,0 +1,168 @@ +package com.google.common.reflect; + +import com.google.common.base.Preconditions; +import java.lang.annotation.Annotation; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Member; +import java.lang.reflect.Modifier; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + +class Element + extends AccessibleObject + implements Member +{ + private final AccessibleObject accessibleObject; + private final Member member; + + Element(M member) + { + Preconditions.checkNotNull(member); + accessibleObject = member; + this.member = ((Member)member); + } + + public TypeToken getOwnerType() { + return TypeToken.of(getDeclaringClass()); + } + + public final boolean isAnnotationPresent(Class annotationClass) { + return accessibleObject.isAnnotationPresent(annotationClass); + } + + public final A getAnnotation(Class annotationClass) { + return accessibleObject.getAnnotation(annotationClass); + } + + public final Annotation[] getAnnotations() { + return accessibleObject.getAnnotations(); + } + + public final Annotation[] getDeclaredAnnotations() { + return accessibleObject.getDeclaredAnnotations(); + } + + public final void setAccessible(boolean flag) throws SecurityException { + accessibleObject.setAccessible(flag); + } + + public final boolean isAccessible() { + return accessibleObject.isAccessible(); + } + + public Class getDeclaringClass() { + return member.getDeclaringClass(); + } + + public final String getName() { + return member.getName(); + } + + public final int getModifiers() { + return member.getModifiers(); + } + + public final boolean isSynthetic() { + return member.isSynthetic(); + } + + public final boolean isPublic() + { + return Modifier.isPublic(getModifiers()); + } + + public final boolean isProtected() + { + return Modifier.isProtected(getModifiers()); + } + + public final boolean isPackagePrivate() + { + return (!isPrivate()) && (!isPublic()) && (!isProtected()); + } + + public final boolean isPrivate() + { + return Modifier.isPrivate(getModifiers()); + } + + public final boolean isStatic() + { + return Modifier.isStatic(getModifiers()); + } + + + + + + + + public final boolean isFinal() + { + return Modifier.isFinal(getModifiers()); + } + + public final boolean isAbstract() + { + return Modifier.isAbstract(getModifiers()); + } + + public final boolean isNative() + { + return Modifier.isNative(getModifiers()); + } + + public final boolean isSynchronized() + { + return Modifier.isSynchronized(getModifiers()); + } + + final boolean isVolatile() + { + return Modifier.isVolatile(getModifiers()); + } + + final boolean isTransient() + { + return Modifier.isTransient(getModifiers()); + } + + public boolean equals(@Nullable Object obj) { + if ((obj instanceof Element)) { + Element that = (Element)obj; + return (getOwnerType().equals(that.getOwnerType())) && (member.equals(member)); + } + return false; + } + + public int hashCode() { + return member.hashCode(); + } + + public String toString() { + return member.toString(); + } +} diff --git a/src/minecraft/com/google/common/reflect/ImmutableTypeToInstanceMap.java b/src/minecraft/com/google/common/reflect/ImmutableTypeToInstanceMap.java new file mode 100644 index 0000000..1ed3e6b --- /dev/null +++ b/src/minecraft/com/google/common/reflect/ImmutableTypeToInstanceMap.java @@ -0,0 +1,138 @@ +package com.google.common.reflect; + +import com.google.common.annotations.Beta; +import com.google.common.collect.ForwardingMap; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMap.Builder; +import java.util.Map; + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class ImmutableTypeToInstanceMap + extends ForwardingMap, B> + implements TypeToInstanceMap +{ + private final ImmutableMap, B> delegate; + + public static ImmutableTypeToInstanceMap of() + { + return new ImmutableTypeToInstanceMap(ImmutableMap.of()); + } + + public static Builder builder() + { + return new Builder(null); + } + + + + + + + + + + + + + + + + + @Beta + public static final class Builder + { + private final ImmutableMap.Builder, B> mapBuilder = ImmutableMap.builder(); + + + + private Builder() {} + + + + public Builder put(Class key, T value) + { + mapBuilder.put(TypeToken.of(key), value); + return this; + } + + + + + public Builder put(TypeToken key, T value) + { + mapBuilder.put(key.rejectTypeVariables(), value); + return this; + } + + + + + + + public ImmutableTypeToInstanceMap build() + { + return new ImmutableTypeToInstanceMap(mapBuilder.build(), null); + } + } + + + private ImmutableTypeToInstanceMap(ImmutableMap, B> delegate) + { + this.delegate = delegate; + } + + public T getInstance(TypeToken type) { + return trustedGet(type.rejectTypeVariables()); + } + + + + + + public T putInstance(TypeToken type, T value) + { + throw new UnsupportedOperationException(); + } + + public T getInstance(Class type) { + return trustedGet(TypeToken.of(type)); + } + + + + + + public T putInstance(Class type, T value) + { + throw new UnsupportedOperationException(); + } + + protected Map, B> delegate() { + return delegate; + } + + private T trustedGet(TypeToken type) + { + return delegate.get(type); + } +} diff --git a/src/minecraft/com/google/common/reflect/Invokable.java b/src/minecraft/com/google/common/reflect/Invokable.java new file mode 100644 index 0000000..f6294cc --- /dev/null +++ b/src/minecraft/com/google/common/reflect/Invokable.java @@ -0,0 +1,330 @@ +package com.google.common.reflect; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableList.Builder; +import java.lang.annotation.Annotation; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Constructor; +import java.lang.reflect.GenericDeclaration; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.util.Arrays; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public abstract class Invokable + extends Element + implements GenericDeclaration +{ + Invokable(M member) + { + super(member); + } + + public static Invokable from(Method method) + { + return new MethodInvokable(method); + } + + public static Invokable from(Constructor constructor) + { + return new ConstructorInvokable(constructor); + } + + + + + + + + + public abstract boolean isOverridable(); + + + + + + + + public abstract boolean isVarArgs(); + + + + + + + + public final R invoke(@Nullable T receiver, Object... args) + throws InvocationTargetException, IllegalAccessException + { + return invokeInternal(receiver, (Object[])Preconditions.checkNotNull(args)); + } + + + + public final TypeToken getReturnType() + { + return TypeToken.of(getGenericReturnType()); + } + + + + + + public final ImmutableList getParameters() + { + Type[] parameterTypes = getGenericParameterTypes(); + Annotation[][] annotations = getParameterAnnotations(); + ImmutableList.Builder builder = ImmutableList.builder(); + for (int i = 0; i < parameterTypes.length; i++) { + builder.add(new Parameter(this, i, TypeToken.of(parameterTypes[i]), annotations[i])); + } + + return builder.build(); + } + + public final ImmutableList> getExceptionTypes() + { + ImmutableList.Builder> builder = ImmutableList.builder(); + for (Type type : getGenericExceptionTypes()) + { + + TypeToken exceptionType = TypeToken.of(type); + + builder.add(exceptionType); + } + return builder.build(); + } + + + + + + + public final Invokable returning(Class returnType) + { + return returning(TypeToken.of(returnType)); + } + + public final Invokable returning(TypeToken returnType) + { + if (!returnType.isAssignableFrom(getReturnType())) { + throw new IllegalArgumentException("Invokable is known to return " + getReturnType() + ", not " + returnType); + } + + + Invokable specialized = this; + return specialized; + } + + public final Class getDeclaringClass() + { + return super.getDeclaringClass(); + } + + + + public TypeToken getOwnerType() + { + return TypeToken.of(getDeclaringClass()); + } + + abstract Object invokeInternal(@Nullable Object paramObject, Object[] paramArrayOfObject) throws InvocationTargetException, IllegalAccessException; + + abstract Type[] getGenericParameterTypes(); + + abstract Type[] getGenericExceptionTypes(); + + abstract Annotation[][] getParameterAnnotations(); + + abstract Type getGenericReturnType(); + + static class MethodInvokable + extends Invokable + { + final Method method; + + MethodInvokable(Method method) + { + super(); + this.method = method; + } + + final Object invokeInternal(@Nullable Object receiver, Object[] args) throws InvocationTargetException, IllegalAccessException + { + return method.invoke(receiver, args); + } + + Type getGenericReturnType() { + return method.getGenericReturnType(); + } + + Type[] getGenericParameterTypes() { + return method.getGenericParameterTypes(); + } + + Type[] getGenericExceptionTypes() { + return method.getGenericExceptionTypes(); + } + + final Annotation[][] getParameterAnnotations() { + return method.getParameterAnnotations(); + } + + public final TypeVariable[] getTypeParameters() { + return method.getTypeParameters(); + } + + public final boolean isOverridable() { + return (!isFinal()) && (!isPrivate()) && (!isStatic()) && (!Modifier.isFinal(getDeclaringClass().getModifiers())); + } + + public final boolean isVarArgs() + { + return method.isVarArgs(); + } + } + + static class ConstructorInvokable extends Invokable + { + final Constructor constructor; + + ConstructorInvokable(Constructor constructor) { + super(); + this.constructor = constructor; + } + + final Object invokeInternal(@Nullable Object receiver, Object[] args) throws InvocationTargetException, IllegalAccessException + { + try { + return constructor.newInstance(args); + } catch (InstantiationException e) { + throw new RuntimeException(constructor + " failed.", e); + } + } + + Type getGenericReturnType() + { + Class declaringClass = getDeclaringClass(); + TypeVariable[] typeParams = declaringClass.getTypeParameters(); + if (typeParams.length > 0) { + return Types.newParameterizedType(declaringClass, typeParams); + } + return declaringClass; + } + + Type[] getGenericParameterTypes() + { + Type[] types = constructor.getGenericParameterTypes(); + if ((types.length > 0) && (mayNeedHiddenThis())) { + Class[] rawParamTypes = constructor.getParameterTypes(); + if ((types.length == rawParamTypes.length) && (rawParamTypes[0] == getDeclaringClass().getEnclosingClass())) + { + + return (Type[])Arrays.copyOfRange(types, 1, types.length); + } + } + return types; + } + + Type[] getGenericExceptionTypes() { + return constructor.getGenericExceptionTypes(); + } + + final Annotation[][] getParameterAnnotations() { + return constructor.getParameterAnnotations(); + } + + + + + + + + + + public final TypeVariable[] getTypeParameters() + { + TypeVariable[] declaredByClass = getDeclaringClass().getTypeParameters(); + TypeVariable[] declaredByConstructor = constructor.getTypeParameters(); + TypeVariable[] result = new TypeVariable[declaredByClass.length + declaredByConstructor.length]; + + System.arraycopy(declaredByClass, 0, result, 0, declaredByClass.length); + System.arraycopy(declaredByConstructor, 0, result, declaredByClass.length, declaredByConstructor.length); + + + + return result; + } + + public final boolean isOverridable() { + return false; + } + + public final boolean isVarArgs() { + return constructor.isVarArgs(); + } + + private boolean mayNeedHiddenThis() { + Class declaringClass = constructor.getDeclaringClass(); + if (declaringClass.getEnclosingConstructor() != null) + { + return true; + } + Method enclosingMethod = declaringClass.getEnclosingMethod(); + if (enclosingMethod != null) + { + return !Modifier.isStatic(enclosingMethod.getModifiers()); + } + + + + + + + return (declaringClass.getEnclosingClass() != null) && (!Modifier.isStatic(declaringClass.getModifiers())); + } + } +} diff --git a/src/minecraft/com/google/common/reflect/MutableTypeToInstanceMap.java b/src/minecraft/com/google/common/reflect/MutableTypeToInstanceMap.java new file mode 100644 index 0000000..d14722e --- /dev/null +++ b/src/minecraft/com/google/common/reflect/MutableTypeToInstanceMap.java @@ -0,0 +1,143 @@ +package com.google.common.reflect; + +import com.google.common.annotations.Beta; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.ForwardingMap; +import com.google.common.collect.ForwardingMapEntry; +import com.google.common.collect.ForwardingSet; +import com.google.common.collect.Iterators; +import com.google.common.collect.Maps; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class MutableTypeToInstanceMap + extends ForwardingMap, B> + implements TypeToInstanceMap +{ + private final Map, B> backingMap; + + public MutableTypeToInstanceMap() + { + backingMap = Maps.newHashMap(); + } + + @Nullable + public T getInstance(Class type) { + return trustedGet(TypeToken.of(type)); + } + + @Nullable + public T putInstance(Class type, @Nullable T value) + { + return trustedPut(TypeToken.of(type), value); + } + + @Nullable + public T getInstance(TypeToken type) + { + return trustedGet(type.rejectTypeVariables()); + } + + @Nullable + public T putInstance(TypeToken type, @Nullable T value) + { + return trustedPut(type.rejectTypeVariables(), value); + } + + public B put(TypeToken key, B value) + { + throw new UnsupportedOperationException("Please use putInstance() instead."); + } + + public void putAll(Map, ? extends B> map) + { + throw new UnsupportedOperationException("Please use putInstance() instead."); + } + + public Set, B>> entrySet() { + return UnmodifiableEntry.transformEntries(super.entrySet()); + } + + protected Map, B> delegate() { + return backingMap; + } + + @Nullable + private T trustedPut(TypeToken type, @Nullable T value) + { + return backingMap.put(type, value); + } + + @Nullable + private T trustedGet(TypeToken type) + { + return backingMap.get(type); + } + + private static final class UnmodifiableEntry extends ForwardingMapEntry + { + private final Map.Entry delegate; + + static Set> transformEntries(Set> entries) { + new ForwardingSet() { + protected Set> delegate() { + return val$entries; + } + + public Iterator> iterator() { return MutableTypeToInstanceMap.UnmodifiableEntry.transformEntries(super.iterator()); } + + public Object[] toArray() { + return standardToArray(); + } + + public T[] toArray(T[] array) { return standardToArray(array); } + }; + } + + private static Iterator> transformEntries(Iterator> entries) + { + Iterators.transform(entries, new Function() { + public Map.Entry apply(Map.Entry entry) { + return new MutableTypeToInstanceMap.UnmodifiableEntry(entry, null); + } + }); + } + + private UnmodifiableEntry(Map.Entry delegate) { + this.delegate = ((Map.Entry)Preconditions.checkNotNull(delegate)); + } + + protected Map.Entry delegate() { + return delegate; + } + + public V setValue(V value) { + throw new UnsupportedOperationException(); + } + } +} diff --git a/src/minecraft/com/google/common/reflect/Parameter.java b/src/minecraft/com/google/common/reflect/Parameter.java new file mode 100644 index 0000000..39ff294 --- /dev/null +++ b/src/minecraft/com/google/common/reflect/Parameter.java @@ -0,0 +1,103 @@ +package com.google.common.reflect; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedElement; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class Parameter + implements AnnotatedElement +{ + private final Invokable declaration; + private final int position; + private final TypeToken type; + private final ImmutableList annotations; + + Parameter(Invokable declaration, int position, TypeToken type, Annotation[] annotations) + { + this.declaration = declaration; + this.position = position; + this.type = type; + this.annotations = ImmutableList.copyOf(annotations); + } + + public TypeToken getType() + { + return type; + } + + public Invokable getDeclaringInvokable() + { + return declaration; + } + + public boolean isAnnotationPresent(Class annotationType) { + return getAnnotation(annotationType) != null; + } + + @Nullable + public A getAnnotation(Class annotationType) + { + Preconditions.checkNotNull(annotationType); + for (Annotation annotation : annotations) { + if (annotationType.isInstance(annotation)) { + return (Annotation)annotationType.cast(annotation); + } + } + return null; + } + + public Annotation[] getAnnotations() { + return getDeclaredAnnotations(); + } + + public Annotation[] getDeclaredAnnotations() { + return (Annotation[])annotations.toArray(new Annotation[annotations.size()]); + } + + public boolean equals(@Nullable Object obj) { + if ((obj instanceof Parameter)) { + Parameter that = (Parameter)obj; + return (position == position) && (declaration.equals(declaration)); + } + return false; + } + + public int hashCode() { + return position; + } + + public String toString() { + return type + " arg" + position; + } +} diff --git a/src/minecraft/com/google/common/reflect/Reflection.java b/src/minecraft/com/google/common/reflect/Reflection.java new file mode 100644 index 0000000..977f0ef --- /dev/null +++ b/src/minecraft/com/google/common/reflect/Reflection.java @@ -0,0 +1,98 @@ +package com.google.common.reflect; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Proxy; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class Reflection +{ + public static String getPackageName(Class clazz) + { + return getPackageName(clazz.getName()); + } + + + + + + public static String getPackageName(String classFullName) + { + int lastDot = classFullName.lastIndexOf('.'); + return lastDot < 0 ? "" : classFullName.substring(0, lastDot); + } + + + + + + + + + + + + + public static void initialize(Class... classes) + { + for (Class clazz : classes) { + try { + Class.forName(clazz.getName(), true, clazz.getClassLoader()); + } catch (ClassNotFoundException e) { + throw new AssertionError(e); + } + } + } + + + + + + + + + + + + public static T newProxy(Class interfaceType, InvocationHandler handler) + { + Preconditions.checkNotNull(handler); + Preconditions.checkArgument(interfaceType.isInterface(), "%s is not an interface", new Object[] { interfaceType }); + Object object = Proxy.newProxyInstance(interfaceType.getClassLoader(), new Class[] { interfaceType }, handler); + + + + return interfaceType.cast(object); + } + + private Reflection() {} +} diff --git a/src/minecraft/com/google/common/reflect/TypeCapture.java b/src/minecraft/com/google/common/reflect/TypeCapture.java new file mode 100644 index 0000000..c252154 --- /dev/null +++ b/src/minecraft/com/google/common/reflect/TypeCapture.java @@ -0,0 +1,38 @@ +package com.google.common.reflect; + +import com.google.common.base.Preconditions; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; + + + + + + + + + + + + + + + + + + + + + +abstract class TypeCapture +{ + TypeCapture() {} + + final Type capture() + { + Type superclass = getClass().getGenericSuperclass(); + Preconditions.checkArgument(superclass instanceof ParameterizedType, "%s isn't parameterized", new Object[] { superclass }); + + return ((ParameterizedType)superclass).getActualTypeArguments()[0]; + } +} diff --git a/src/minecraft/com/google/common/reflect/TypeParameter.java b/src/minecraft/com/google/common/reflect/TypeParameter.java new file mode 100644 index 0000000..130f90e --- /dev/null +++ b/src/minecraft/com/google/common/reflect/TypeParameter.java @@ -0,0 +1,67 @@ +package com.google.common.reflect; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public abstract class TypeParameter + extends TypeCapture +{ + final TypeVariable typeVariable; + + protected TypeParameter() + { + Type type = capture(); + Preconditions.checkArgument(type instanceof TypeVariable, "%s should be a type variable.", new Object[] { type }); + typeVariable = ((TypeVariable)type); + } + + public final int hashCode() { + return typeVariable.hashCode(); + } + + public final boolean equals(@Nullable Object o) { + if ((o instanceof TypeParameter)) { + TypeParameter that = (TypeParameter)o; + return typeVariable.equals(typeVariable); + } + return false; + } + + public String toString() { + return typeVariable.toString(); + } +} diff --git a/src/minecraft/com/google/common/reflect/TypeResolver.java b/src/minecraft/com/google/common/reflect/TypeResolver.java new file mode 100644 index 0000000..f6afbc6 --- /dev/null +++ b/src/minecraft/com/google/common/reflect/TypeResolver.java @@ -0,0 +1,500 @@ +package com.google.common.reflect; + +import com.google.common.annotations.Beta; +import com.google.common.base.Joiner; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMap.Builder; +import com.google.common.collect.Maps; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; +import java.util.Arrays; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.atomic.AtomicInteger; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class TypeResolver +{ + private final TypeTable typeTable; + + public TypeResolver() + { + typeTable = new TypeTable(); + } + + private TypeResolver(TypeTable typeTable) { + this.typeTable = typeTable; + } + + static TypeResolver accordingTo(Type type) { + return new TypeResolver().where(TypeMappingIntrospector.getTypeMappings(type)); + } + + + + + + + + + + + + + + + + + + + + public TypeResolver where(Type formal, Type actual) + { + Map mappings = Maps.newHashMap(); + populateTypeMappings(mappings, (Type)Preconditions.checkNotNull(formal), (Type)Preconditions.checkNotNull(actual)); + return where(mappings); + } + + TypeResolver where(Map mappings) + { + return new TypeResolver(typeTable.where(mappings)); + } + + private static void populateTypeMappings(Map mappings, Type from, final Type to) + { + if (from.equals(to)) { + return; + } + new TypeVisitor() + { + void visitTypeVariable(TypeVariable typeVariable) { val$mappings.put(new TypeResolver.TypeVariableKey(typeVariable), to); } + + void visitWildcardType(WildcardType fromWildcardType) { + WildcardType toWildcardType = (WildcardType)TypeResolver.expectArgument(WildcardType.class, to); + Type[] fromUpperBounds = fromWildcardType.getUpperBounds(); + Type[] toUpperBounds = toWildcardType.getUpperBounds(); + Type[] fromLowerBounds = fromWildcardType.getLowerBounds(); + Type[] toLowerBounds = toWildcardType.getLowerBounds(); + Preconditions.checkArgument((fromUpperBounds.length == toUpperBounds.length) && (fromLowerBounds.length == toLowerBounds.length), "Incompatible type: %s vs. %s", new Object[] { fromWildcardType, to }); + + + + for (int i = 0; i < fromUpperBounds.length; i++) { + TypeResolver.populateTypeMappings(val$mappings, fromUpperBounds[i], toUpperBounds[i]); + } + for (int i = 0; i < fromLowerBounds.length; i++) + TypeResolver.populateTypeMappings(val$mappings, fromLowerBounds[i], toLowerBounds[i]); + } + + void visitParameterizedType(ParameterizedType fromParameterizedType) { + ParameterizedType toParameterizedType = (ParameterizedType)TypeResolver.expectArgument(ParameterizedType.class, to); + Preconditions.checkArgument(fromParameterizedType.getRawType().equals(toParameterizedType.getRawType()), "Inconsistent raw type: %s vs. %s", new Object[] { fromParameterizedType, to }); + + Type[] fromArgs = fromParameterizedType.getActualTypeArguments(); + Type[] toArgs = toParameterizedType.getActualTypeArguments(); + Preconditions.checkArgument(fromArgs.length == toArgs.length, "%s not compatible with %s", new Object[] { fromParameterizedType, toParameterizedType }); + + for (int i = 0; i < fromArgs.length; i++) + TypeResolver.populateTypeMappings(val$mappings, fromArgs[i], toArgs[i]); + } + + void visitGenericArrayType(GenericArrayType fromArrayType) { + Type componentType = Types.getComponentType(to); + Preconditions.checkArgument(componentType != null, "%s is not an array type.", new Object[] { to }); + TypeResolver.populateTypeMappings(val$mappings, fromArrayType.getGenericComponentType(), componentType); + } + + + + + void visitClass(Class fromClass) { throw new IllegalArgumentException("No type mapping from " + fromClass); } }.visit(new Type[] { from }); + } + + + + + + + public Type resolveType(Type type) + { + Preconditions.checkNotNull(type); + if ((type instanceof TypeVariable)) + return typeTable.resolve((TypeVariable)type); + if ((type instanceof ParameterizedType)) + return resolveParameterizedType((ParameterizedType)type); + if ((type instanceof GenericArrayType)) + return resolveGenericArrayType((GenericArrayType)type); + if ((type instanceof WildcardType)) { + return resolveWildcardType((WildcardType)type); + } + + return type; + } + + private Type[] resolveTypes(Type[] types) + { + Type[] result = new Type[types.length]; + for (int i = 0; i < types.length; i++) { + result[i] = resolveType(types[i]); + } + return result; + } + + private WildcardType resolveWildcardType(WildcardType type) { + Type[] lowerBounds = type.getLowerBounds(); + Type[] upperBounds = type.getUpperBounds(); + return new Types.WildcardTypeImpl(resolveTypes(lowerBounds), resolveTypes(upperBounds)); + } + + private Type resolveGenericArrayType(GenericArrayType type) + { + Type componentType = type.getGenericComponentType(); + Type resolvedComponentType = resolveType(componentType); + return Types.newArrayType(resolvedComponentType); + } + + private ParameterizedType resolveParameterizedType(ParameterizedType type) { + Type owner = type.getOwnerType(); + Type resolvedOwner = owner == null ? null : resolveType(owner); + Type resolvedRawType = resolveType(type.getRawType()); + + Type[] args = type.getActualTypeArguments(); + Type[] resolvedArgs = resolveTypes(args); + return Types.newParameterizedTypeWithOwner(resolvedOwner, (Class)resolvedRawType, resolvedArgs); + } + + private static T expectArgument(Class type, Object arg) + { + try { + return type.cast(arg); + } catch (ClassCastException e) { + throw new IllegalArgumentException(arg + " is not a " + type.getSimpleName()); + } + } + + private static class TypeTable + { + private final ImmutableMap map; + + TypeTable() { + map = ImmutableMap.of(); + } + + private TypeTable(ImmutableMap map) { + this.map = map; + } + + final TypeTable where(Map mappings) + { + ImmutableMap.Builder builder = ImmutableMap.builder(); + builder.putAll(map); + for (Map.Entry mapping : mappings.entrySet()) { + TypeResolver.TypeVariableKey variable = (TypeResolver.TypeVariableKey)mapping.getKey(); + Type type = (Type)mapping.getValue(); + Preconditions.checkArgument(!variable.equalsType(type), "Type variable %s bound to itself", new Object[] { variable }); + builder.put(variable, type); + } + return new TypeTable(builder.build()); + } + + final Type resolve(final TypeVariable var) { + final TypeTable unguarded = this; + TypeTable guarded = new TypeTable() + { + public Type resolveInternal(TypeVariable intermediateVar, TypeResolver.TypeTable forDependent) { + if (intermediateVar.getGenericDeclaration().equals(var.getGenericDeclaration())) { + return intermediateVar; + } + return unguarded.resolveInternal(intermediateVar, forDependent); + } + }; + return resolveInternal(var, guarded); + } + + + + + + + + + Type resolveInternal(TypeVariable var, TypeTable forDependants) + { + Type type = (Type)map.get(new TypeResolver.TypeVariableKey(var)); + if (type == null) { + Type[] bounds = var.getBounds(); + if (bounds.length == 0) { + return var; + } + Type[] resolvedBounds = new TypeResolver(forDependants, null).resolveTypes(bounds); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + if ((Types.NativeTypeVariableEquals.NATIVE_TYPE_VARIABLE_ONLY) && (Arrays.equals(bounds, resolvedBounds))) + { + return var; + } + return Types.newArtificialTypeVariable(var.getGenericDeclaration(), var.getName(), resolvedBounds); + } + + + return new TypeResolver(forDependants, null).resolveType(type); + } + } + + private static final class TypeMappingIntrospector extends TypeVisitor + { + private static final TypeResolver.WildcardCapturer wildcardCapturer = new TypeResolver.WildcardCapturer(null); + + private final Map mappings = Maps.newHashMap(); + + + private TypeMappingIntrospector() {} + + + static ImmutableMap getTypeMappings(Type contextType) + { + TypeMappingIntrospector introspector = new TypeMappingIntrospector(); + introspector.visit(new Type[] { wildcardCapturer.capture(contextType) }); + return ImmutableMap.copyOf(mappings); + } + + void visitClass(Class clazz) { + visit(new Type[] { clazz.getGenericSuperclass() }); + visit(clazz.getGenericInterfaces()); + } + + void visitParameterizedType(ParameterizedType parameterizedType) { + Class rawClass = (Class)parameterizedType.getRawType(); + TypeVariable[] vars = rawClass.getTypeParameters(); + Type[] typeArgs = parameterizedType.getActualTypeArguments(); + Preconditions.checkState(vars.length == typeArgs.length); + for (int i = 0; i < vars.length; i++) { + map(new TypeResolver.TypeVariableKey(vars[i]), typeArgs[i]); + } + visit(new Type[] { rawClass }); + visit(new Type[] { parameterizedType.getOwnerType() }); + } + + void visitTypeVariable(TypeVariable t) { + visit(t.getBounds()); + } + + void visitWildcardType(WildcardType t) { + visit(t.getUpperBounds()); + } + + private void map(TypeResolver.TypeVariableKey var, Type arg) { + if (mappings.containsKey(var)) + { + + + + + return; + } + + for (Type t = arg; t != null; t = (Type)mappings.get(TypeResolver.TypeVariableKey.forLookup(t))) { + if (var.equalsType(t)) + { + + + + for (Type x = arg; x != null; x = (Type)mappings.remove(TypeResolver.TypeVariableKey.forLookup(x))) {} + return; + } + } + mappings.put(var, arg); + } + } + + + + + private static final class WildcardCapturer + { + private WildcardCapturer() {} + + + + private final AtomicInteger id = new AtomicInteger(); + + Type capture(Type type) { + Preconditions.checkNotNull(type); + if ((type instanceof Class)) { + return type; + } + if ((type instanceof TypeVariable)) { + return type; + } + if ((type instanceof GenericArrayType)) { + GenericArrayType arrayType = (GenericArrayType)type; + return Types.newArrayType(capture(arrayType.getGenericComponentType())); + } + if ((type instanceof ParameterizedType)) { + ParameterizedType parameterizedType = (ParameterizedType)type; + return Types.newParameterizedTypeWithOwner(captureNullable(parameterizedType.getOwnerType()), (Class)parameterizedType.getRawType(), capture(parameterizedType.getActualTypeArguments())); + } + + + + if ((type instanceof WildcardType)) { + WildcardType wildcardType = (WildcardType)type; + Type[] lowerBounds = wildcardType.getLowerBounds(); + if (lowerBounds.length == 0) { + Type[] upperBounds = wildcardType.getUpperBounds(); + String name = "capture#" + id.incrementAndGet() + "-of ? extends " + Joiner.on('&').join(upperBounds); + + return Types.newArtificialTypeVariable(WildcardCapturer.class, name, wildcardType.getUpperBounds()); + } + + + return type; + } + + throw new AssertionError("must have been one of the known types"); + } + + private Type captureNullable(@Nullable Type type) { + if (type == null) { + return null; + } + return capture(type); + } + + private Type[] capture(Type[] types) { + Type[] result = new Type[types.length]; + for (int i = 0; i < types.length; i++) { + result[i] = capture(types[i]); + } + return result; + } + } + + + + + + + + static final class TypeVariableKey + { + private final TypeVariable var; + + + + + + + + TypeVariableKey(TypeVariable var) + { + this.var = ((TypeVariable)Preconditions.checkNotNull(var)); + } + + public int hashCode() { + return Objects.hashCode(new Object[] { var.getGenericDeclaration(), var.getName() }); + } + + public boolean equals(Object obj) { + if ((obj instanceof TypeVariableKey)) { + TypeVariableKey that = (TypeVariableKey)obj; + return equalsTypeVariable(var); + } + return false; + } + + public String toString() + { + return var.toString(); + } + + static Object forLookup(Type t) + { + if ((t instanceof TypeVariable)) { + return new TypeVariableKey((TypeVariable)t); + } + return null; + } + + + + + + boolean equalsType(Type type) + { + if ((type instanceof TypeVariable)) { + return equalsTypeVariable((TypeVariable)type); + } + return false; + } + + private boolean equalsTypeVariable(TypeVariable that) + { + return (var.getGenericDeclaration().equals(that.getGenericDeclaration())) && (var.getName().equals(that.getName())); + } + } +} diff --git a/src/minecraft/com/google/common/reflect/TypeToInstanceMap.java b/src/minecraft/com/google/common/reflect/TypeToInstanceMap.java new file mode 100644 index 0000000..5777554 --- /dev/null +++ b/src/minecraft/com/google/common/reflect/TypeToInstanceMap.java @@ -0,0 +1,22 @@ +package com.google.common.reflect; + +import com.google.common.annotations.Beta; +import java.util.Map; +import javax.annotation.Nullable; + +@Beta +public abstract interface TypeToInstanceMap + extends Map, B> +{ + @Nullable + public abstract T getInstance(Class paramClass); + + @Nullable + public abstract T putInstance(Class paramClass, @Nullable T paramT); + + @Nullable + public abstract T getInstance(TypeToken paramTypeToken); + + @Nullable + public abstract T putInstance(TypeToken paramTypeToken, @Nullable T paramT); +} diff --git a/src/minecraft/com/google/common/reflect/TypeToken.java b/src/minecraft/com/google/common/reflect/TypeToken.java new file mode 100644 index 0000000..ec747fa --- /dev/null +++ b/src/minecraft/com/google/common/reflect/TypeToken.java @@ -0,0 +1 @@ +null \ No newline at end of file diff --git a/src/minecraft/com/google/common/reflect/TypeVisitor.java b/src/minecraft/com/google/common/reflect/TypeVisitor.java new file mode 100644 index 0000000..feb7bd6 --- /dev/null +++ b/src/minecraft/com/google/common/reflect/TypeVisitor.java @@ -0,0 +1,109 @@ +package com.google.common.reflect; + +import com.google.common.collect.Sets; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; +import java.util.Set; +import javax.annotation.concurrent.NotThreadSafe; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@NotThreadSafe +abstract class TypeVisitor +{ + private final Set visited = Sets.newHashSet(); + + + TypeVisitor() {} + + public final void visit(Type... types) + { + for (Type type : types) { + if ((type != null) && (visited.add(type))) + { + + + boolean succeeded = false; + try { + if ((type instanceof TypeVariable)) { + visitTypeVariable((TypeVariable)type); + } else if ((type instanceof WildcardType)) { + visitWildcardType((WildcardType)type); + } else if ((type instanceof ParameterizedType)) { + visitParameterizedType((ParameterizedType)type); + } else if ((type instanceof Class)) { + visitClass((Class)type); + } else if ((type instanceof GenericArrayType)) { + visitGenericArrayType((GenericArrayType)type); + } else { + throw new AssertionError("Unknown type: " + type); + } + succeeded = true; + } finally { + if (!succeeded) { + visited.remove(type); + } + } + } + } + } + + void visitClass(Class t) {} + + void visitGenericArrayType(GenericArrayType t) {} + + void visitParameterizedType(ParameterizedType t) {} + + void visitTypeVariable(TypeVariable t) {} + + void visitWildcardType(WildcardType t) {} +} diff --git a/src/minecraft/com/google/common/reflect/Types.java b/src/minecraft/com/google/common/reflect/Types.java new file mode 100644 index 0000000..bfc8265 --- /dev/null +++ b/src/minecraft/com/google/common/reflect/Types.java @@ -0,0 +1,509 @@ +package com.google.common.reflect; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicates; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableList.Builder; +import com.google.common.collect.Iterables; +import java.io.Serializable; +import java.lang.reflect.Array; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.GenericDeclaration; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; +import java.util.Arrays; +import java.util.Collection; +import java.util.concurrent.atomic.AtomicReference; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + +final class Types +{ + private static final Function TYPE_TO_STRING = new Function() + { + public String apply(Type from) { + return Types.toString(from); + } + }; + + private static final Joiner COMMA_JOINER = Joiner.on(", ").useForNull("null"); + + static Type newArrayType(Type componentType) + { + if ((componentType instanceof WildcardType)) { + WildcardType wildcard = (WildcardType)componentType; + Type[] lowerBounds = wildcard.getLowerBounds(); + Preconditions.checkArgument(lowerBounds.length <= 1, "Wildcard cannot have more than one lower bounds."); + if (lowerBounds.length == 1) { + return supertypeOf(newArrayType(lowerBounds[0])); + } + Type[] upperBounds = wildcard.getUpperBounds(); + Preconditions.checkArgument(upperBounds.length == 1, "Wildcard should have only one upper bound."); + return subtypeOf(newArrayType(upperBounds[0])); + } + + return JavaVersion.CURRENT.newArrayType(componentType); + } + + + + + + static ParameterizedType newParameterizedTypeWithOwner(@Nullable Type ownerType, Class rawType, Type... arguments) + { + if (ownerType == null) { + return newParameterizedType(rawType, arguments); + } + + Preconditions.checkNotNull(arguments); + Preconditions.checkArgument(rawType.getEnclosingClass() != null, "Owner type for unenclosed %s", new Object[] { rawType }); + return new ParameterizedTypeImpl(ownerType, rawType, arguments); + } + + + + + + + static ParameterizedType newParameterizedType(Class rawType, Type... arguments) { return new ParameterizedTypeImpl(ClassOwnership.JVM_BEHAVIOR.getOwnerType(rawType), rawType, arguments); } + + private static abstract enum ClassOwnership { private ClassOwnership() {} + + @Nullable + abstract Class getOwnerType(Class paramClass); + + OWNED_BY_ENCLOSING_CLASS, + + + + + + + LOCAL_CLASS_HAS_NO_OWNER; + + + + + + + + + + + + + + static final ClassOwnership JVM_BEHAVIOR = detectJvmBehavior(); + + private static ClassOwnership detectJvmBehavior() + { + Class subclass = new 1LocalClass() {}.getClass(); + ParameterizedType parameterizedType = (ParameterizedType)subclass.getGenericSuperclass(); + + for (ClassOwnership behavior : values()) { + if (behavior.getOwnerType(1LocalClass.class) == parameterizedType.getOwnerType()) { + return behavior; + } + } + throw new AssertionError(); + } + } + + + + + + static TypeVariable newArtificialTypeVariable(D declaration, String name, Type... bounds) + { + return new TypeVariableImpl(declaration, name, bounds.length == 0 ? new Type[] { Object.class } : bounds); + } + + + + + + @VisibleForTesting + static WildcardType subtypeOf(Type upperBound) + { + return new WildcardTypeImpl(new Type[0], new Type[] { upperBound }); + } + + @VisibleForTesting + static WildcardType supertypeOf(Type lowerBound) { + return new WildcardTypeImpl(new Type[] { lowerBound }, new Type[] { Object.class }); + } + + + + + + + + + + static String toString(Type type) + { + return (type instanceof Class) ? ((Class)type).getName() : type.toString(); + } + + @Nullable + static Type getComponentType(Type type) + { + Preconditions.checkNotNull(type); + AtomicReference result = new AtomicReference(); + new TypeVisitor() { + void visitTypeVariable(TypeVariable t) { + val$result.set(Types.subtypeOfComponentType(t.getBounds())); + } + + void visitWildcardType(WildcardType t) { val$result.set(Types.subtypeOfComponentType(t.getUpperBounds())); } + + void visitGenericArrayType(GenericArrayType t) { + val$result.set(t.getGenericComponentType()); + } + + void visitClass(Class t) { val$result.set(t.getComponentType()); } }.visit(new Type[] { type }); + + + return (Type)result.get(); + } + + + + @Nullable + private static Type subtypeOfComponentType(Type[] bounds) + { + for (Type bound : bounds) { + Type componentType = getComponentType(bound); + if (componentType != null) + { + + if ((componentType instanceof Class)) { + Class componentClass = (Class)componentType; + if (componentClass.isPrimitive()) { + return componentClass; + } + } + return subtypeOf(componentType); + } + } + return null; + } + + private static final class GenericArrayTypeImpl implements GenericArrayType, Serializable + { + private final Type componentType; + private static final long serialVersionUID = 0L; + + GenericArrayTypeImpl(Type componentType) { + this.componentType = Types.JavaVersion.CURRENT.usedInGenericType(componentType); + } + + public Type getGenericComponentType() { + return componentType; + } + + public String toString() { + return Types.toString(componentType) + "[]"; + } + + public int hashCode() { + return componentType.hashCode(); + } + + public boolean equals(Object obj) { + if ((obj instanceof GenericArrayType)) { + GenericArrayType that = (GenericArrayType)obj; + return Objects.equal(getGenericComponentType(), that.getGenericComponentType()); + } + + return false; + } + } + + + private static final class ParameterizedTypeImpl + implements ParameterizedType, Serializable + { + private final Type ownerType; + private final ImmutableList argumentsList; + private final Class rawType; + private static final long serialVersionUID = 0L; + + ParameterizedTypeImpl(@Nullable Type ownerType, Class rawType, Type[] typeArguments) + { + Preconditions.checkNotNull(rawType); + Preconditions.checkArgument(typeArguments.length == rawType.getTypeParameters().length); + Types.disallowPrimitiveType(typeArguments, "type parameter"); + this.ownerType = ownerType; + this.rawType = rawType; + argumentsList = Types.JavaVersion.CURRENT.usedInGenericType(typeArguments); + } + + public Type[] getActualTypeArguments() { + return Types.toArray(argumentsList); + } + + public Type getRawType() { + return rawType; + } + + public Type getOwnerType() { + return ownerType; + } + + public String toString() { + StringBuilder builder = new StringBuilder(); + if (ownerType != null) { + builder.append(Types.toString(ownerType)).append('.'); + } + builder.append(rawType.getName()).append('<').append(Types.COMMA_JOINER.join(Iterables.transform(argumentsList, Types.TYPE_TO_STRING))).append('>'); + + + + return builder.toString(); + } + + public int hashCode() { + return (ownerType == null ? 0 : ownerType.hashCode()) ^ argumentsList.hashCode() ^ rawType.hashCode(); + } + + public boolean equals(Object other) + { + if (!(other instanceof ParameterizedType)) { + return false; + } + ParameterizedType that = (ParameterizedType)other; + return (getRawType().equals(that.getRawType())) && (Objects.equal(getOwnerType(), that.getOwnerType())) && (Arrays.equals(getActualTypeArguments(), that.getActualTypeArguments())); + } + } + + + private static final class TypeVariableImpl + implements TypeVariable + { + private final D genericDeclaration; + + private final String name; + + private final ImmutableList bounds; + + + TypeVariableImpl(D genericDeclaration, String name, Type[] bounds) + { + Types.disallowPrimitiveType(bounds, "bound for type variable"); + this.genericDeclaration = ((GenericDeclaration)Preconditions.checkNotNull(genericDeclaration)); + this.name = ((String)Preconditions.checkNotNull(name)); + this.bounds = ImmutableList.copyOf(bounds); + } + + public Type[] getBounds() { + return Types.toArray(bounds); + } + + public D getGenericDeclaration() { + return genericDeclaration; + } + + public String getName() { + return name; + } + + public String toString() { + return name; + } + + public int hashCode() { + return genericDeclaration.hashCode() ^ name.hashCode(); + } + + public boolean equals(Object obj) { + if (Types.NativeTypeVariableEquals.NATIVE_TYPE_VARIABLE_ONLY) + { + if ((obj instanceof TypeVariableImpl)) { + TypeVariableImpl that = (TypeVariableImpl)obj; + return (name.equals(that.getName())) && (genericDeclaration.equals(that.getGenericDeclaration())) && (bounds.equals(bounds)); + } + + + return false; + } + + if ((obj instanceof TypeVariable)) { + TypeVariable that = (TypeVariable)obj; + return (name.equals(that.getName())) && (genericDeclaration.equals(that.getGenericDeclaration())); + } + + return false; + } + } + + static final class WildcardTypeImpl implements WildcardType, Serializable + { + private final ImmutableList lowerBounds; + private final ImmutableList upperBounds; + private static final long serialVersionUID = 0L; + + WildcardTypeImpl(Type[] lowerBounds, Type[] upperBounds) { + Types.disallowPrimitiveType(lowerBounds, "lower bound for wildcard"); + Types.disallowPrimitiveType(upperBounds, "upper bound for wildcard"); + this.lowerBounds = Types.JavaVersion.CURRENT.usedInGenericType(lowerBounds); + this.upperBounds = Types.JavaVersion.CURRENT.usedInGenericType(upperBounds); + } + + public Type[] getLowerBounds() { + return Types.toArray(lowerBounds); + } + + public Type[] getUpperBounds() { + return Types.toArray(upperBounds); + } + + public boolean equals(Object obj) { + if ((obj instanceof WildcardType)) { + WildcardType that = (WildcardType)obj; + return (lowerBounds.equals(Arrays.asList(that.getLowerBounds()))) && (upperBounds.equals(Arrays.asList(that.getUpperBounds()))); + } + + return false; + } + + public int hashCode() { + return lowerBounds.hashCode() ^ upperBounds.hashCode(); + } + + public String toString() { + StringBuilder builder = new StringBuilder("?"); + for (Type lowerBound : lowerBounds) { + builder.append(" super ").append(Types.toString(lowerBound)); + } + for (Type upperBound : Types.filterUpperBounds(upperBounds)) { + builder.append(" extends ").append(Types.toString(upperBound)); + } + return builder.toString(); + } + } + + + private static Type[] toArray(Collection types) + { + return (Type[])types.toArray(new Type[types.size()]); + } + + private static Iterable filterUpperBounds(Iterable bounds) { + return Iterables.filter(bounds, Predicates.not(Predicates.equalTo(Object.class))); + } + + private static void disallowPrimitiveType(Type[] types, String usedAs) + { + for (Type type : types) { + if ((type instanceof Class)) { + Class cls = (Class)type; + Preconditions.checkArgument(!cls.isPrimitive(), "Primitive type '%s' used as %s", new Object[] { cls, usedAs }); + } + } + } + + + + + + + + static Class getArrayClass(Class componentType) { return Array.newInstance(componentType, 0).getClass(); } + + private Types() {} + + static abstract enum JavaVersion { private JavaVersion() {} + abstract Type newArrayType(Type paramType); + JAVA6, + + + + + + + + + + + + + + + JAVA7; + + + + + + + + + + + + + + static final JavaVersion CURRENT = (new TypeCapture() {}.capture() instanceof Class) ? JAVA7 : JAVA6; + + + abstract Type usedInGenericType(Type paramType); + + final ImmutableList usedInGenericType(Type[] types) + { + ImmutableList.Builder builder = ImmutableList.builder(); + for (Type type : types) { + builder.add(usedInGenericType(type)); + } + return builder.build(); + } + } + + + + + + + + + + + static final class NativeTypeVariableEquals + { + static final boolean NATIVE_TYPE_VARIABLE_ONLY = !NativeTypeVariableEquals.class.getTypeParameters()[0].equals(Types.newArtificialTypeVariable(NativeTypeVariableEquals.class, "X", new Type[0])); + + NativeTypeVariableEquals() {} + } +} diff --git a/src/minecraft/com/google/common/reflect/package-info.java b/src/minecraft/com/google/common/reflect/package-info.java new file mode 100644 index 0000000..1c024e7 --- /dev/null +++ b/src/minecraft/com/google/common/reflect/package-info.java @@ -0,0 +1,6 @@ +package com.google.common.reflect; + +import javax.annotation.ParametersAreNonnullByDefault; + +@ParametersAreNonnullByDefault +abstract interface package-info {} diff --git a/src/minecraft/com/google/common/util/concurrent/AbstractCheckedFuture.java b/src/minecraft/com/google/common/util/concurrent/AbstractCheckedFuture.java new file mode 100644 index 0000000..5ab5379 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/AbstractCheckedFuture.java @@ -0,0 +1,117 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public abstract class AbstractCheckedFuture + extends ForwardingListenableFuture.SimpleForwardingListenableFuture + implements CheckedFuture +{ + protected AbstractCheckedFuture(ListenableFuture delegate) + { + super(delegate); + } + + + + + + + + + + + + + + + + protected abstract X mapException(Exception paramException); + + + + + + + + + + + + + + + public V checkedGet() + throws Exception + { + try + { + return get(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw mapException(e); + } catch (CancellationException e) { + throw mapException(e); + } catch (ExecutionException e) { + throw mapException(e); + } + } + + + + + + + + + + + + + + + public V checkedGet(long timeout, TimeUnit unit) + throws TimeoutException, Exception + { + try + { + return get(timeout, unit); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw mapException(e); + } catch (CancellationException e) { + throw mapException(e); + } catch (ExecutionException e) { + throw mapException(e); + } + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/AbstractExecutionThreadService.java b/src/minecraft/com/google/common/util/concurrent/AbstractExecutionThreadService.java new file mode 100644 index 0000000..ce2a733 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/AbstractExecutionThreadService.java @@ -0,0 +1,232 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.base.Supplier; +import com.google.common.base.Throwables; +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.logging.Level; +import java.util.logging.Logger; + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public abstract class AbstractExecutionThreadService + implements Service +{ + private static final Logger logger = Logger.getLogger(AbstractExecutionThreadService.class.getName()); + + + + private final Service delegate = new AbstractService() { + protected final void doStart() { + Executor executor = MoreExecutors.renamingDecorator(executor(), new Supplier() { + public String get() { + return serviceName(); + } + }); + executor.execute(new Runnable() + { + public void run() { + try { + startUp(); + notifyStarted(); + + if (isRunning()) { + try { + AbstractExecutionThreadService.this.run(); + } catch (Throwable t) { + try { + shutDown(); + } catch (Exception ignored) { + AbstractExecutionThreadService.logger.log(Level.WARNING, "Error while attempting to shut down the service after failure.", ignored); + } + + + throw t; + } + } + + shutDown(); + notifyStopped(); + } catch (Throwable t) { + notifyFailed(t); + throw Throwables.propagate(t); + } + } + }); + } + + protected void doStop() { + triggerShutdown(); + } + }; + + + + + + + + + protected AbstractExecutionThreadService() {} + + + + + + + + + protected void startUp() + throws Exception + {} + + + + + + + + protected abstract void run() + throws Exception; + + + + + + + + protected void shutDown() + throws Exception + {} + + + + + + + + protected void triggerShutdown() {} + + + + + + + + protected Executor executor() + { + new Executor() + { + public void execute(Runnable command) { + MoreExecutors.newThread(serviceName(), command).start(); + } + }; + } + + public String toString() { + return serviceName() + " [" + state() + "]"; + } + + public final boolean isRunning() { + return delegate.isRunning(); + } + + public final Service.State state() { + return delegate.state(); + } + + + + public final void addListener(Service.Listener listener, Executor executor) + { + delegate.addListener(listener, executor); + } + + + + public final Throwable failureCause() + { + return delegate.failureCause(); + } + + + + public final Service startAsync() + { + delegate.startAsync(); + return this; + } + + + + public final Service stopAsync() + { + delegate.stopAsync(); + return this; + } + + + + public final void awaitRunning() + { + delegate.awaitRunning(); + } + + + public final void awaitRunning(long timeout, TimeUnit unit) + throws TimeoutException + { + delegate.awaitRunning(timeout, unit); + } + + + + public final void awaitTerminated() + { + delegate.awaitTerminated(); + } + + + public final void awaitTerminated(long timeout, TimeUnit unit) + throws TimeoutException + { + delegate.awaitTerminated(timeout, unit); + } + + + + + + + + + protected String serviceName() + { + return getClass().getSimpleName(); + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/AbstractFuture.java b/src/minecraft/com/google/common/util/concurrent/AbstractFuture.java new file mode 100644 index 0000000..0dadbba --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/AbstractFuture.java @@ -0,0 +1,396 @@ +package com.google.common.util.concurrent; + +import com.google.common.base.Preconditions; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.locks.AbstractQueuedSynchronizer; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class AbstractFuture + implements ListenableFuture +{ + private final Sync sync = new Sync(); + + + private final ExecutionList executionList = new ExecutionList(); + + + + + + + + + + + protected AbstractFuture() {} + + + + + + + + + + + public V get(long timeout, TimeUnit unit) + throws InterruptedException, TimeoutException, ExecutionException + { + return sync.get(unit.toNanos(timeout)); + } + + + + + + + + + + + + + + + + public V get() + throws InterruptedException, ExecutionException + { + return sync.get(); + } + + public boolean isDone() + { + return sync.isDone(); + } + + public boolean isCancelled() + { + return sync.isCancelled(); + } + + public boolean cancel(boolean mayInterruptIfRunning) + { + if (!sync.cancel(mayInterruptIfRunning)) { + return false; + } + executionList.execute(); + if (mayInterruptIfRunning) { + interruptTask(); + } + return true; + } + + + + + + + + + + protected void interruptTask() {} + + + + + + + + + protected final boolean wasInterrupted() + { + return sync.wasInterrupted(); + } + + + + + + + public void addListener(Runnable listener, Executor exec) + { + executionList.add(listener, exec); + } + + + + + + + + + + protected boolean set(@Nullable V value) + { + boolean result = sync.set(value); + if (result) { + executionList.execute(); + } + return result; + } + + + + + + + + + + protected boolean setException(Throwable throwable) + { + boolean result = sync.setException((Throwable)Preconditions.checkNotNull(throwable)); + if (result) { + executionList.execute(); + } + return result; + } + + + + static final class Sync + extends AbstractQueuedSynchronizer + { + private static final long serialVersionUID = 0L; + + + static final int RUNNING = 0; + + + static final int COMPLETING = 1; + + + static final int COMPLETED = 2; + + + static final int CANCELLED = 4; + + + static final int INTERRUPTED = 8; + + + private V value; + + + private Throwable exception; + + + + Sync() {} + + + + protected int tryAcquireShared(int ignored) + { + if (isDone()) { + return 1; + } + return -1; + } + + + + + + protected boolean tryReleaseShared(int finalState) + { + setState(finalState); + return true; + } + + + + + + + + V get(long nanos) + throws TimeoutException, CancellationException, ExecutionException, InterruptedException + { + if (!tryAcquireSharedNanos(-1, nanos)) { + throw new TimeoutException("Timeout waiting for task."); + } + + return getValue(); + } + + + + + + + + + V get() + throws CancellationException, ExecutionException, InterruptedException + { + acquireSharedInterruptibly(-1); + return getValue(); + } + + + + + private V getValue() + throws CancellationException, ExecutionException + { + int state = getState(); + switch (state) { + case 2: + if (exception != null) { + throw new ExecutionException(exception); + } + return value; + + + case 4: + case 8: + throw AbstractFuture.cancellationExceptionWithCause("Task was cancelled.", exception); + } + + + throw new IllegalStateException("Error, synchronizer in invalid state: " + state); + } + + + + + + + boolean isDone() + { + return (getState() & 0xE) != 0; + } + + + + boolean isCancelled() + { + return (getState() & 0xC) != 0; + } + + + + boolean wasInterrupted() + { + return getState() == 8; + } + + + + boolean set(@Nullable V v) + { + return complete(v, null, 2); + } + + + + boolean setException(Throwable t) + { + return complete(null, t, 2); + } + + + + boolean cancel(boolean interrupt) + { + return complete(null, null, interrupt ? 8 : 4); + } + + + + + + + + + + + + + + private boolean complete(@Nullable V v, @Nullable Throwable t, int finalState) + { + boolean doCompletion = compareAndSetState(0, 1); + if (doCompletion) + { + + value = v; + + exception = ((finalState & 0xC) != 0 ? new CancellationException("Future.cancel() was called.") : t); + + releaseShared(finalState); + } else if (getState() == 1) + { + + acquireShared(-1); + } + return doCompletion; + } + } + + static final CancellationException cancellationExceptionWithCause(@Nullable String message, @Nullable Throwable cause) + { + CancellationException exception = new CancellationException(message); + exception.initCause(cause); + return exception; + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/AbstractIdleService.java b/src/minecraft/com/google/common/util/concurrent/AbstractIdleService.java new file mode 100644 index 0000000..3084570 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/AbstractIdleService.java @@ -0,0 +1,184 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.base.Supplier; +import com.google.common.base.Throwables; +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public abstract class AbstractIdleService + implements Service +{ + private final Supplier threadNameSupplier = new Supplier() { + public String get() { + return serviceName() + " " + state(); + } + }; + + + private final Service delegate = new AbstractService() { + protected final void doStart() { + MoreExecutors.renamingDecorator(executor(), threadNameSupplier).execute(new Runnable() + { + public void run() { + try { + startUp(); + notifyStarted(); + } catch (Throwable t) { + notifyFailed(t); + throw Throwables.propagate(t); + } + } + }); + } + + protected final void doStop() { + MoreExecutors.renamingDecorator(executor(), threadNameSupplier).execute(new Runnable() + { + public void run() { + try { + shutDown(); + notifyStopped(); + } catch (Throwable t) { + notifyFailed(t); + throw Throwables.propagate(t); + } + } + }); + } + }; + + + + protected AbstractIdleService() {} + + + + protected abstract void startUp() + throws Exception; + + + + protected abstract void shutDown() + throws Exception; + + + + protected Executor executor() + { + new Executor() { + public void execute(Runnable command) { + MoreExecutors.newThread((String)threadNameSupplier.get(), command).start(); + } + }; + } + + public String toString() { + return serviceName() + " [" + state() + "]"; + } + + public final boolean isRunning() { + return delegate.isRunning(); + } + + public final Service.State state() { + return delegate.state(); + } + + + + public final void addListener(Service.Listener listener, Executor executor) + { + delegate.addListener(listener, executor); + } + + + + public final Throwable failureCause() + { + return delegate.failureCause(); + } + + + + public final Service startAsync() + { + delegate.startAsync(); + return this; + } + + + + public final Service stopAsync() + { + delegate.stopAsync(); + return this; + } + + + + public final void awaitRunning() + { + delegate.awaitRunning(); + } + + + public final void awaitRunning(long timeout, TimeUnit unit) + throws TimeoutException + { + delegate.awaitRunning(timeout, unit); + } + + + + public final void awaitTerminated() + { + delegate.awaitTerminated(); + } + + + public final void awaitTerminated(long timeout, TimeUnit unit) + throws TimeoutException + { + delegate.awaitTerminated(timeout, unit); + } + + + + + + + protected String serviceName() + { + return getClass().getSimpleName(); + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/AbstractListeningExecutorService.java b/src/minecraft/com/google/common/util/concurrent/AbstractListeningExecutorService.java new file mode 100644 index 0000000..0c477c8 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/AbstractListeningExecutorService.java @@ -0,0 +1,60 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import java.util.concurrent.AbstractExecutorService; +import java.util.concurrent.Callable; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public abstract class AbstractListeningExecutorService + extends AbstractExecutorService + implements ListeningExecutorService +{ + public AbstractListeningExecutorService() {} + + protected final ListenableFutureTask newTaskFor(Runnable runnable, T value) + { + return ListenableFutureTask.create(runnable, value); + } + + protected final ListenableFutureTask newTaskFor(Callable callable) { + return ListenableFutureTask.create(callable); + } + + public ListenableFuture submit(Runnable task) { + return (ListenableFuture)super.submit(task); + } + + public ListenableFuture submit(Runnable task, @Nullable T result) { + return (ListenableFuture)super.submit(task, result); + } + + public ListenableFuture submit(Callable task) { + return (ListenableFuture)super.submit(task); + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/AbstractScheduledService.java b/src/minecraft/com/google/common/util/concurrent/AbstractScheduledService.java new file mode 100644 index 0000000..3881236 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/AbstractScheduledService.java @@ -0,0 +1,514 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import com.google.common.base.Throwables; +import java.util.concurrent.Callable; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.locks.ReentrantLock; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.concurrent.GuardedBy; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public abstract class AbstractScheduledService + implements Service +{ + private static final Logger logger = Logger.getLogger(AbstractScheduledService.class.getName()); + + protected AbstractScheduledService() {} + + + protected abstract void runOneIteration() + throws Exception; + + + protected void startUp() + throws Exception + {} + + + protected void shutDown() + throws Exception + {} + + + protected abstract Scheduler scheduler(); + + + public static abstract class Scheduler + { + public static Scheduler newFixedDelaySchedule(long initialDelay, long delay, final TimeUnit unit) + { + new Scheduler(initialDelay) + { + public Future schedule(AbstractService service, ScheduledExecutorService executor, Runnable task) + { + return executor.scheduleWithFixedDelay(task, val$initialDelay, unit, val$unit); + } + }; + } + + + + + + + + + + public static Scheduler newFixedRateSchedule(long initialDelay, long period, final TimeUnit unit) + { + new Scheduler(initialDelay) + { + public Future schedule(AbstractService service, ScheduledExecutorService executor, Runnable task) + { + return executor.scheduleAtFixedRate(task, val$initialDelay, unit, val$unit); + } + }; + } + + + abstract Future schedule(AbstractService paramAbstractService, ScheduledExecutorService paramScheduledExecutorService, Runnable paramRunnable); + + + private Scheduler() {} + } + + + private final AbstractService delegate = new AbstractService() + { + private volatile Future runningTask; + + + + private volatile ScheduledExecutorService executorService; + + + private final ReentrantLock lock = new ReentrantLock(); + + private final Runnable task = new Runnable() { + public void run() { + lock.lock(); + try { + runOneIteration(); + } catch (Throwable t) { + try { + shutDown(); + } catch (Exception ignored) { + AbstractScheduledService.logger.log(Level.WARNING, "Error while attempting to shut down the service after failure.", ignored); + } + + notifyFailed(t); + throw Throwables.propagate(t); + } finally { + lock.unlock(); + } + } + }; + + protected final void doStart() { + executorService = MoreExecutors.renamingDecorator(executor(), new Supplier() { + public String get() { + return serviceName() + " " + state(); + } + }); + executorService.execute(new Runnable() { + public void run() { + lock.lock(); + try { + startUp(); + runningTask = scheduler().schedule(delegate, executorService, task); + notifyStarted(); + } catch (Throwable t) { + notifyFailed(t); + throw Throwables.propagate(t); + } finally { + lock.unlock(); + } + } + }); + } + + protected final void doStop() { + runningTask.cancel(false); + executorService.execute(new Runnable() { + public void run() { + try { + lock.lock(); + try { + if (state() != Service.State.STOPPING) { + return; + } + + + + + shutDown(); + } finally { + lock.unlock(); + } + notifyStopped(); + } catch (Throwable t) { + notifyFailed(t); + throw Throwables.propagate(t); + } + } + }); + } + }; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + protected ScheduledExecutorService executor() + { + final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() + { + public Thread newThread(Runnable runnable) { + return MoreExecutors.newThread(serviceName(), runnable); + + + } + + + + }); + addListener(new Service.Listener() { + public void terminated(Service.State from) { + executor.shutdown(); + } + + public void failed(Service.State from, Throwable failure) { executor.shutdown(); } }, MoreExecutors.sameThreadExecutor()); + + return executor; + } + + + + + + + protected String serviceName() + { + return getClass().getSimpleName(); + } + + public String toString() { + return serviceName() + " [" + state() + "]"; + } + + public final boolean isRunning() { + return delegate.isRunning(); + } + + public final Service.State state() { + return delegate.state(); + } + + + + public final void addListener(Service.Listener listener, Executor executor) + { + delegate.addListener(listener, executor); + } + + + + public final Throwable failureCause() + { + return delegate.failureCause(); + } + + + + public final Service startAsync() + { + delegate.startAsync(); + return this; + } + + + + public final Service stopAsync() + { + delegate.stopAsync(); + return this; + } + + + + public final void awaitRunning() + { + delegate.awaitRunning(); + } + + + public final void awaitRunning(long timeout, TimeUnit unit) + throws TimeoutException + { + delegate.awaitRunning(timeout, unit); + } + + + + public final void awaitTerminated() + { + delegate.awaitTerminated(); + } + + + public final void awaitTerminated(long timeout, TimeUnit unit) + throws TimeoutException + { + delegate.awaitTerminated(timeout, unit); + } + + + + + @Beta + public static abstract class CustomScheduler + extends AbstractScheduledService.Scheduler + { + public CustomScheduler() + { + super(); + } + + + + + + private class ReschedulableCallable + extends ForwardingFuture + implements Callable + { + private final Runnable wrappedRunnable; + + + + + private final ScheduledExecutorService executor; + + + + private final AbstractService service; + + + + private final ReentrantLock lock = new ReentrantLock(); + + @GuardedBy("lock") + private Future currentFuture; + + + ReschedulableCallable(AbstractService service, ScheduledExecutorService executor, Runnable runnable) + { + wrappedRunnable = runnable; + this.executor = executor; + this.service = service; + } + + public Void call() throws Exception + { + wrappedRunnable.run(); + reschedule(); + return null; + } + + + + + + + + public void reschedule() + { + lock.lock(); + try { + if ((currentFuture == null) || (!currentFuture.isCancelled())) { + AbstractScheduledService.CustomScheduler.Schedule schedule = getNextSchedule(); + currentFuture = executor.schedule(this, delay, unit); + } + + + } + catch (Throwable e) + { + + service.notifyFailed(e); + } finally { + lock.unlock(); + } + } + + + + + public boolean cancel(boolean mayInterruptIfRunning) + { + lock.lock(); + try { + return currentFuture.cancel(mayInterruptIfRunning); + } finally { + lock.unlock(); + } + } + + protected Future delegate() + { + throw new UnsupportedOperationException("Only cancel is supported by this future"); + } + } + + + final Future schedule(AbstractService service, ScheduledExecutorService executor, Runnable runnable) + { + ReschedulableCallable task = new ReschedulableCallable(service, executor, runnable); + task.reschedule(); + return task; + } + + + + protected abstract Schedule getNextSchedule() + throws Exception; + + + + @Beta + protected static final class Schedule + { + private final long delay; + + private final TimeUnit unit; + + + public Schedule(long delay, TimeUnit unit) + { + this.delay = delay; + this.unit = ((TimeUnit)Preconditions.checkNotNull(unit)); + } + } + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/AbstractService.java b/src/minecraft/com/google/common/util/concurrent/AbstractService.java new file mode 100644 index 0000000..35f8a58 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/AbstractService.java @@ -0,0 +1,548 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import javax.annotation.Nullable; +import javax.annotation.concurrent.GuardedBy; +import javax.annotation.concurrent.Immutable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public abstract class AbstractService + implements Service +{ + private static final ListenerCallQueue.Callback STARTING_CALLBACK = new ListenerCallQueue.Callback("starting()") + { + void call(Service.Listener listener) { + listener.starting(); + } + }; + private static final ListenerCallQueue.Callback RUNNING_CALLBACK = new ListenerCallQueue.Callback("running()") + { + void call(Service.Listener listener) { + listener.running(); + } + }; + private static final ListenerCallQueue.Callback STOPPING_FROM_STARTING_CALLBACK = stoppingCallback(Service.State.STARTING); + + private static final ListenerCallQueue.Callback STOPPING_FROM_RUNNING_CALLBACK = stoppingCallback(Service.State.RUNNING); + + + private static final ListenerCallQueue.Callback TERMINATED_FROM_NEW_CALLBACK = terminatedCallback(Service.State.NEW); + + private static final ListenerCallQueue.Callback TERMINATED_FROM_RUNNING_CALLBACK = terminatedCallback(Service.State.RUNNING); + + private static final ListenerCallQueue.Callback TERMINATED_FROM_STOPPING_CALLBACK = terminatedCallback(Service.State.STOPPING); + + private static ListenerCallQueue.Callback terminatedCallback(final Service.State from) + { + new ListenerCallQueue.Callback("terminated({from = " + from + "})") { + void call(Service.Listener listener) { + listener.terminated(from); + } + }; + } + + private static ListenerCallQueue.Callback stoppingCallback(final Service.State from) { + new ListenerCallQueue.Callback("stopping({from = " + from + "})") { + void call(Service.Listener listener) { + listener.stopping(from); + } + }; + } + + private final Monitor monitor = new Monitor(); + + private final Monitor.Guard isStartable = new Monitor.Guard(monitor) { + public boolean isSatisfied() { + return state() == Service.State.NEW; + } + }; + + private final Monitor.Guard isStoppable = new Monitor.Guard(monitor) { + public boolean isSatisfied() { + return state().compareTo(Service.State.RUNNING) <= 0; + } + }; + + private final Monitor.Guard hasReachedRunning = new Monitor.Guard(monitor) { + public boolean isSatisfied() { + return state().compareTo(Service.State.RUNNING) >= 0; + } + }; + + private final Monitor.Guard isStopped = new Monitor.Guard(monitor) { + public boolean isSatisfied() { + return state().isTerminal(); + } + }; + + + + @GuardedBy("monitor") + private final List> listeners = Collections.synchronizedList(new ArrayList()); + + + + + + + + + + + + @GuardedBy("monitor") + private volatile StateSnapshot snapshot = new StateSnapshot(Service.State.NEW); + + + + + + + + protected AbstractService() {} + + + + + + + protected abstract void doStart(); + + + + + + + protected abstract void doStop(); + + + + + + + public final Service startAsync() + { + if (monitor.enterIf(isStartable)) { + try { + snapshot = new StateSnapshot(Service.State.STARTING); + starting(); + doStart(); + } + catch (Throwable startupFailure) { + notifyFailed(startupFailure); + } finally { + monitor.leave(); + executeListeners(); + } + } else { + throw new IllegalStateException("Service " + this + " has already been started"); + } + return this; + } + + public final Service stopAsync() { + if (monitor.enterIf(isStoppable)) { + try { + Service.State previous = state(); + switch (10.$SwitchMap$com$google$common$util$concurrent$Service$State[previous.ordinal()]) { + case 1: + snapshot = new StateSnapshot(Service.State.TERMINATED); + terminated(Service.State.NEW); + break; + case 2: + snapshot = new StateSnapshot(Service.State.STARTING, true, null); + stopping(Service.State.STARTING); + break; + case 3: + snapshot = new StateSnapshot(Service.State.STOPPING); + stopping(Service.State.RUNNING); + doStop(); + break; + + case 4: + case 5: + case 6: + throw new AssertionError("isStoppable is incorrectly implemented, saw: " + previous); + default: + throw new AssertionError("Unexpected state: " + previous); + } + } + catch (Throwable shutdownFailure) + { + notifyFailed(shutdownFailure); + } finally { + monitor.leave(); + executeListeners(); + } + } + return this; + } + + public final void awaitRunning() { + monitor.enterWhenUninterruptibly(hasReachedRunning); + try { + checkCurrentState(Service.State.RUNNING); + } finally { + monitor.leave(); + } + } + + public final void awaitRunning(long timeout, TimeUnit unit) throws TimeoutException { + if (monitor.enterWhenUninterruptibly(hasReachedRunning, timeout, unit)) { + try { + checkCurrentState(Service.State.RUNNING); + } finally { + monitor.leave(); + + } + + } + else + { + throw new TimeoutException("Timed out waiting for " + this + " to reach the RUNNING state. " + "Current state: " + state()); + } + } + + public final void awaitTerminated() + { + monitor.enterWhenUninterruptibly(isStopped); + try { + checkCurrentState(Service.State.TERMINATED); + } finally { + monitor.leave(); + } + } + + public final void awaitTerminated(long timeout, TimeUnit unit) throws TimeoutException { + if (monitor.enterWhenUninterruptibly(isStopped, timeout, unit)) { + try { + checkCurrentState(Service.State.TERMINATED); + } finally { + monitor.leave(); + + } + + } + else + { + throw new TimeoutException("Timed out waiting for " + this + " to reach a terminal state. " + "Current state: " + state()); + } + } + + + @GuardedBy("monitor") + private void checkCurrentState(Service.State expected) + { + Service.State actual = state(); + if (actual != expected) { + if (actual == Service.State.FAILED) + { + throw new IllegalStateException("Expected the service to be " + expected + ", but the service has FAILED", failureCause()); + } + + throw new IllegalStateException("Expected the service to be " + expected + ", but was " + actual); + } + } + + + + + + + + protected final void notifyStarted() + { + monitor.enter(); + + try + { + if (snapshot.state != Service.State.STARTING) { + IllegalStateException failure = new IllegalStateException("Cannot notifyStarted() when the service is " + snapshot.state); + + notifyFailed(failure); + throw failure; + } + + if (snapshot.shutdownWhenStartupFinishes) { + snapshot = new StateSnapshot(Service.State.STOPPING); + + + doStop(); + } else { + snapshot = new StateSnapshot(Service.State.RUNNING); + running(); + } + } finally { + monitor.leave(); + executeListeners(); + } + } + + + + + + + + protected final void notifyStopped() + { + monitor.enter(); + + try + { + Service.State previous = snapshot.state; + if ((previous != Service.State.STOPPING) && (previous != Service.State.RUNNING)) { + IllegalStateException failure = new IllegalStateException("Cannot notifyStopped() when the service is " + previous); + + notifyFailed(failure); + throw failure; + } + snapshot = new StateSnapshot(Service.State.TERMINATED); + terminated(previous); + } finally { + monitor.leave(); + executeListeners(); + } + } + + + + + + protected final void notifyFailed(Throwable cause) + { + Preconditions.checkNotNull(cause); + + monitor.enter(); + try { + Service.State previous = state(); + switch (10.$SwitchMap$com$google$common$util$concurrent$Service$State[previous.ordinal()]) { + case 1: + case 5: + throw new IllegalStateException("Failed while in state:" + previous, cause); + case 2: + case 3: + case 4: + snapshot = new StateSnapshot(Service.State.FAILED, false, cause); + failed(previous, cause); + break; + case 6: + break; + + default: + throw new AssertionError("Unexpected state: " + previous); + } + } finally { + monitor.leave(); + executeListeners(); + } + } + + public final boolean isRunning() + { + return state() == Service.State.RUNNING; + } + + public final Service.State state() + { + return snapshot.externalState(); + } + + + + + public final Throwable failureCause() + { + return snapshot.failureCause(); + } + + + + + public final void addListener(Service.Listener listener, Executor executor) + { + Preconditions.checkNotNull(listener, "listener"); + Preconditions.checkNotNull(executor, "executor"); + monitor.enter(); + try { + if (!state().isTerminal()) { + listeners.add(new ListenerCallQueue(listener, executor)); + } + } finally { + monitor.leave(); + } + } + + public String toString() { + return getClass().getSimpleName() + " [" + state() + "]"; + } + + + + + private void executeListeners() + { + if (!monitor.isOccupiedByCurrentThread()) + { + for (int i = 0; i < listeners.size(); i++) { + ((ListenerCallQueue)listeners.get(i)).execute(); + } + } + } + + @GuardedBy("monitor") + private void starting() { + STARTING_CALLBACK.enqueueOn(listeners); + } + + @GuardedBy("monitor") + private void running() { + RUNNING_CALLBACK.enqueueOn(listeners); + } + + @GuardedBy("monitor") + private void stopping(Service.State from) { + if (from == Service.State.STARTING) { + STOPPING_FROM_STARTING_CALLBACK.enqueueOn(listeners); + } else if (from == Service.State.RUNNING) { + STOPPING_FROM_RUNNING_CALLBACK.enqueueOn(listeners); + } else { + throw new AssertionError(); + } + } + + @GuardedBy("monitor") + private void terminated(Service.State from) { + switch (10.$SwitchMap$com$google$common$util$concurrent$Service$State[from.ordinal()]) { + case 1: + TERMINATED_FROM_NEW_CALLBACK.enqueueOn(listeners); + break; + case 3: + TERMINATED_FROM_RUNNING_CALLBACK.enqueueOn(listeners); + break; + case 4: + TERMINATED_FROM_STOPPING_CALLBACK.enqueueOn(listeners); + break; + case 2: + case 5: + case 6: + default: + throw new AssertionError(); + } + } + + @GuardedBy("monitor") + private void failed(final Service.State from, final Throwable cause) + { + new ListenerCallQueue.Callback("failed({from = " + from + ", cause = " + cause + "})") + { + void call(Service.Listener listener) { listener.failed(from, cause); } }.enqueueOn(listeners); + } + + + + + + + @Immutable + private static final class StateSnapshot + { + final Service.State state; + + + + + + final boolean shutdownWhenStartupFinishes; + + + + + + @Nullable + final Throwable failure; + + + + + + StateSnapshot(Service.State internalState) + { + this(internalState, false, null); + } + + StateSnapshot(Service.State internalState, boolean shutdownWhenStartupFinishes, @Nullable Throwable failure) + { + Preconditions.checkArgument((!shutdownWhenStartupFinishes) || (internalState == Service.State.STARTING), "shudownWhenStartupFinishes can only be set if state is STARTING. Got %s instead.", new Object[] { internalState }); + + + Preconditions.checkArgument(((failure != null ? 1 : 0) ^ (internalState == Service.State.FAILED ? 1 : 0)) == 0, "A failure cause should be set if and only if the state is failed. Got %s and %s instead.", new Object[] { internalState, failure }); + + + state = internalState; + this.shutdownWhenStartupFinishes = shutdownWhenStartupFinishes; + this.failure = failure; + } + + Service.State externalState() + { + if ((shutdownWhenStartupFinishes) && (state == Service.State.STARTING)) { + return Service.State.STOPPING; + } + return state; + } + + + Throwable failureCause() + { + Preconditions.checkState(state == Service.State.FAILED, "failureCause() is only valid if the service has failed, service is %s", new Object[] { state }); + + return failure; + } + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/AsyncFunction.java b/src/minecraft/com/google/common/util/concurrent/AsyncFunction.java new file mode 100644 index 0000000..d4cf22b --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/AsyncFunction.java @@ -0,0 +1,7 @@ +package com.google.common.util.concurrent; + +public abstract interface AsyncFunction +{ + public abstract ListenableFuture apply(I paramI) + throws Exception; +} diff --git a/src/minecraft/com/google/common/util/concurrent/AsyncSettableFuture.java b/src/minecraft/com/google/common/util/concurrent/AsyncSettableFuture.java new file mode 100644 index 0000000..ccea185 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/AsyncSettableFuture.java @@ -0,0 +1,100 @@ +package com.google.common.util.concurrent; + +import com.google.common.base.Preconditions; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +final class AsyncSettableFuture + extends ForwardingListenableFuture +{ + public static AsyncSettableFuture create() + { + return new AsyncSettableFuture(); + } + + private final NestedFuture nested = new NestedFuture(null); + private final ListenableFuture dereferenced = Futures.dereference(nested); + + private AsyncSettableFuture() {} + + protected ListenableFuture delegate() { + return dereferenced; + } + + + + + public boolean setFuture(ListenableFuture future) + { + return nested.setFuture((ListenableFuture)Preconditions.checkNotNull(future)); + } + + + + + + public boolean setValue(@Nullable V value) + { + return setFuture(Futures.immediateFuture(value)); + } + + + + + + public boolean setException(Throwable exception) + { + return setFuture(Futures.immediateFailedFuture(exception)); + } + + + + + + + + + + + public boolean isSet() { return nested.isDone(); } + + private static final class NestedFuture extends AbstractFuture> { + private NestedFuture() {} + + boolean setFuture(ListenableFuture value) { boolean result = set(value); + if (isCancelled()) { + value.cancel(wasInterrupted()); + } + return result; + } + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/AtomicDouble.java b/src/minecraft/com/google/common/util/concurrent/AtomicDouble.java new file mode 100644 index 0000000..1fc627e --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/AtomicDouble.java @@ -0,0 +1,254 @@ +package com.google.common.util.concurrent; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.concurrent.atomic.AtomicLongFieldUpdater; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class AtomicDouble + extends Number + implements Serializable +{ + private static final long serialVersionUID = 0L; + private volatile transient long value; + private static final AtomicLongFieldUpdater updater = AtomicLongFieldUpdater.newUpdater(AtomicDouble.class, "value"); + + + + + + + public AtomicDouble(double initialValue) + { + value = Double.doubleToRawLongBits(initialValue); + } + + + + + + + public AtomicDouble() {} + + + + + + public final double get() + { + return Double.longBitsToDouble(value); + } + + + + + + public final void set(double newValue) + { + long next = Double.doubleToRawLongBits(newValue); + value = next; + } + + + + + + public final void lazySet(double newValue) + { + set(newValue); + } + + + + + + + + + + public final double getAndSet(double newValue) + { + long next = Double.doubleToRawLongBits(newValue); + return Double.longBitsToDouble(updater.getAndSet(this, next)); + } + + + + + + + + + + + public final boolean compareAndSet(double expect, double update) + { + return updater.compareAndSet(this, Double.doubleToRawLongBits(expect), Double.doubleToRawLongBits(update)); + } + + + + + + + + + + + + + + + + + + public final boolean weakCompareAndSet(double expect, double update) + { + return updater.weakCompareAndSet(this, Double.doubleToRawLongBits(expect), Double.doubleToRawLongBits(update)); + } + + + + + + + + public final double getAndAdd(double delta) + { + for (;;) + { + long current = value; + double currentVal = Double.longBitsToDouble(current); + double nextVal = currentVal + delta; + long next = Double.doubleToRawLongBits(nextVal); + if (updater.compareAndSet(this, current, next)) { + return currentVal; + } + } + } + + + + + + public final double addAndGet(double delta) + { + for (;;) + { + long current = value; + double currentVal = Double.longBitsToDouble(current); + double nextVal = currentVal + delta; + long next = Double.doubleToRawLongBits(nextVal); + if (updater.compareAndSet(this, current, next)) { + return nextVal; + } + } + } + + + + + public String toString() + { + return Double.toString(get()); + } + + + + + public int intValue() + { + return (int)get(); + } + + + + + public long longValue() + { + return get(); + } + + + + + public float floatValue() + { + return (float)get(); + } + + + + public double doubleValue() + { + return get(); + } + + + + + + private void writeObject(ObjectOutputStream s) + throws IOException + { + s.defaultWriteObject(); + + s.writeDouble(get()); + } + + + + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException + { + s.defaultReadObject(); + + set(s.readDouble()); + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/AtomicDoubleArray.java b/src/minecraft/com/google/common/util/concurrent/AtomicDoubleArray.java new file mode 100644 index 0000000..b6b868b --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/AtomicDoubleArray.java @@ -0,0 +1,268 @@ +package com.google.common.util.concurrent; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.concurrent.atomic.AtomicLongArray; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class AtomicDoubleArray + implements Serializable +{ + private static final long serialVersionUID = 0L; + private transient AtomicLongArray longs; + + public AtomicDoubleArray(int length) + { + longs = new AtomicLongArray(length); + } + + + + + + + + public AtomicDoubleArray(double[] array) + { + int len = array.length; + long[] longArray = new long[len]; + for (int i = 0; i < len; i++) { + longArray[i] = Double.doubleToRawLongBits(array[i]); + } + longs = new AtomicLongArray(longArray); + } + + + + + + public final int length() + { + return longs.length(); + } + + + + + + + public final double get(int i) + { + return Double.longBitsToDouble(longs.get(i)); + } + + + + + + + public final void set(int i, double newValue) + { + long next = Double.doubleToRawLongBits(newValue); + longs.set(i, next); + } + + + + + + + public final void lazySet(int i, double newValue) + { + set(i, newValue); + } + + + + + + + + + + + + public final double getAndSet(int i, double newValue) + { + long next = Double.doubleToRawLongBits(newValue); + return Double.longBitsToDouble(longs.getAndSet(i, next)); + } + + + + + + + + + + + + + public final boolean compareAndSet(int i, double expect, double update) + { + return longs.compareAndSet(i, Double.doubleToRawLongBits(expect), Double.doubleToRawLongBits(update)); + } + + + + + + + + + + + + + + + + + + + + public final boolean weakCompareAndSet(int i, double expect, double update) + { + return longs.weakCompareAndSet(i, Double.doubleToRawLongBits(expect), Double.doubleToRawLongBits(update)); + } + + + + + + + + + public final double getAndAdd(int i, double delta) + { + for (;;) + { + long current = longs.get(i); + double currentVal = Double.longBitsToDouble(current); + double nextVal = currentVal + delta; + long next = Double.doubleToRawLongBits(nextVal); + if (longs.compareAndSet(i, current, next)) { + return currentVal; + } + } + } + + + + + + + public double addAndGet(int i, double delta) + { + for (;;) + { + long current = longs.get(i); + double currentVal = Double.longBitsToDouble(current); + double nextVal = currentVal + delta; + long next = Double.doubleToRawLongBits(nextVal); + if (longs.compareAndSet(i, current, next)) { + return nextVal; + } + } + } + + + + + public String toString() + { + int iMax = length() - 1; + if (iMax == -1) { + return "[]"; + } + + + StringBuilder b = new StringBuilder(19 * (iMax + 1)); + b.append('['); + for (int i = 0;; i++) { + b.append(Double.longBitsToDouble(longs.get(i))); + if (i == iMax) { + return ']'; + } + b.append(',').append(' '); + } + } + + + + + + + private void writeObject(ObjectOutputStream s) + throws IOException + { + s.defaultWriteObject(); + + + int length = length(); + s.writeInt(length); + + + for (int i = 0; i < length; i++) { + s.writeDouble(get(i)); + } + } + + + + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException + { + s.defaultReadObject(); + + + int length = s.readInt(); + longs = new AtomicLongArray(length); + + + for (int i = 0; i < length; i++) { + set(i, s.readDouble()); + } + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/AtomicLongMap.java b/src/minecraft/com/google/common/util/concurrent/AtomicLongMap.java new file mode 100644 index 0000000..3ca0de9 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/AtomicLongMap.java @@ -0,0 +1,431 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.Maps; +import java.util.Collections; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public final class AtomicLongMap +{ + private final ConcurrentHashMap map; + private transient Map asMap; + + private AtomicLongMap(ConcurrentHashMap map) + { + this.map = ((ConcurrentHashMap)Preconditions.checkNotNull(map)); + } + + + + public static AtomicLongMap create() + { + return new AtomicLongMap(new ConcurrentHashMap()); + } + + + + public static AtomicLongMap create(Map m) + { + AtomicLongMap result = create(); + result.putAll(m); + return result; + } + + + + + public long get(K key) + { + AtomicLong atomic = (AtomicLong)map.get(key); + return atomic == null ? 0L : atomic.get(); + } + + + + public long incrementAndGet(K key) + { + return addAndGet(key, 1L); + } + + + + public long decrementAndGet(K key) + { + return addAndGet(key, -1L); + } + + + + + + public long addAndGet(K key, long delta) + { + AtomicLong atomic = (AtomicLong)map.get(key); + if (atomic == null) { + atomic = (AtomicLong)map.putIfAbsent(key, new AtomicLong(delta)); + if (atomic == null) { + return delta; + } + } + + for (;;) + { + long oldValue = atomic.get(); + if (oldValue == 0L) + { + if (!map.replace(key, atomic, new AtomicLong(delta))) break; + return delta; + } + + + + + long newValue = oldValue + delta; + if (atomic.compareAndSet(oldValue, newValue)) { + return newValue; + } + } + } + + + + + + public long getAndIncrement(K key) + { + return getAndAdd(key, 1L); + } + + + + public long getAndDecrement(K key) + { + return getAndAdd(key, -1L); + } + + + + + + public long getAndAdd(K key, long delta) + { + AtomicLong atomic = (AtomicLong)map.get(key); + if (atomic == null) { + atomic = (AtomicLong)map.putIfAbsent(key, new AtomicLong(delta)); + if (atomic == null) { + return 0L; + } + } + + for (;;) + { + long oldValue = atomic.get(); + if (oldValue == 0L) + { + if (!map.replace(key, atomic, new AtomicLong(delta))) break; + return 0L; + } + + + + + long newValue = oldValue + delta; + if (atomic.compareAndSet(oldValue, newValue)) { + return oldValue; + } + } + } + + + + + + + + public long put(K key, long newValue) + { + AtomicLong atomic = (AtomicLong)map.get(key); + if (atomic == null) { + atomic = (AtomicLong)map.putIfAbsent(key, new AtomicLong(newValue)); + if (atomic == null) { + return 0L; + } + } + + for (;;) + { + long oldValue = atomic.get(); + if (oldValue == 0L) + { + if (!map.replace(key, atomic, new AtomicLong(newValue))) break; + return 0L; + } + + + + + if (atomic.compareAndSet(oldValue, newValue)) { + return oldValue; + } + } + } + + + + + + + + + public void putAll(Map m) + { + for (Map.Entry entry : m.entrySet()) { + put(entry.getKey(), ((Long)entry.getValue()).longValue()); + } + } + + + + + public long remove(K key) + { + AtomicLong atomic = (AtomicLong)map.get(key); + if (atomic == null) { + return 0L; + } + for (;;) + { + long oldValue = atomic.get(); + if ((oldValue == 0L) || (atomic.compareAndSet(oldValue, 0L))) + { + map.remove(key, atomic); + + return oldValue; + } + } + } + + + + + + + public void removeAllZeros() + { + for (K key : map.keySet()) { + AtomicLong atomic = (AtomicLong)map.get(key); + if ((atomic != null) && (atomic.get() == 0L)) { + map.remove(key, atomic); + } + } + } + + + + + + public long sum() + { + long sum = 0L; + for (AtomicLong value : map.values()) { + sum += value.get(); + } + return sum; + } + + + + + + public Map asMap() + { + Map result = asMap; + return result == null ? (this.asMap = createAsMap()) : result; + } + + private Map createAsMap() { + Collections.unmodifiableMap(Maps.transformValues(map, new Function() + { + public Long apply(AtomicLong atomic) + { + return Long.valueOf(atomic.get()); + } + })); + } + + + + public boolean containsKey(Object key) + { + return map.containsKey(key); + } + + + + + public int size() + { + return map.size(); + } + + + + public boolean isEmpty() + { + return map.isEmpty(); + } + + + + + + + public void clear() + { + map.clear(); + } + + public String toString() + { + return map.toString(); + } + + + + + + + + + + long putIfAbsent(K key, long newValue) + { + AtomicLong atomic; + + + + + + + + + long oldValue; + + + + + + + + + do + { + atomic = (AtomicLong)map.get(key); + if (atomic == null) { + atomic = (AtomicLong)map.putIfAbsent(key, new AtomicLong(newValue)); + if (atomic == null) { + return 0L; + } + } + + + oldValue = atomic.get(); + if (oldValue != 0L) + break; + } while (!map.replace(key, atomic, new AtomicLong(newValue))); + return 0L; + + + + + + return oldValue; + } + + + + + + + + + + boolean replace(K key, long expectedOldValue, long newValue) + { + if (expectedOldValue == 0L) { + return putIfAbsent(key, newValue) == 0L; + } + AtomicLong atomic = (AtomicLong)map.get(key); + return atomic == null ? false : atomic.compareAndSet(expectedOldValue, newValue); + } + + + + + + boolean remove(K key, long value) + { + AtomicLong atomic = (AtomicLong)map.get(key); + if (atomic == null) { + return false; + } + + long oldValue = atomic.get(); + if (oldValue != value) { + return false; + } + + if ((oldValue == 0L) || (atomic.compareAndSet(oldValue, 0L))) + { + map.remove(key, atomic); + + return true; + } + + + return false; + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/Atomics.java b/src/minecraft/com/google/common/util/concurrent/Atomics.java new file mode 100644 index 0000000..6a227ef --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/Atomics.java @@ -0,0 +1,73 @@ +package com.google.common.util.concurrent; + +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.atomic.AtomicReferenceArray; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public final class Atomics +{ + private Atomics() {} + + public static AtomicReference newReference() + { + return new AtomicReference(); + } + + + + + + + public static AtomicReference newReference(@Nullable V initialValue) + { + return new AtomicReference(initialValue); + } + + + + + + + public static AtomicReferenceArray newReferenceArray(int length) + { + return new AtomicReferenceArray(length); + } + + + + + + + + public static AtomicReferenceArray newReferenceArray(E[] array) + { + return new AtomicReferenceArray(array); + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/Callables.java b/src/minecraft/com/google/common/util/concurrent/Callables.java new file mode 100644 index 0000000..2dcdeae --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/Callables.java @@ -0,0 +1,116 @@ +package com.google.common.util.concurrent; + +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import java.util.concurrent.Callable; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public final class Callables +{ + private Callables() {} + + public static Callable returning(@Nullable T value) + { + new Callable() { + public T call() { + return val$value; + } + }; + } + + + + + + + + + + + static Callable threadRenaming(final Callable callable, Supplier nameSupplier) + { + Preconditions.checkNotNull(nameSupplier); + Preconditions.checkNotNull(callable); + new Callable() { + public T call() throws Exception { + Thread currentThread = Thread.currentThread(); + String oldName = currentThread.getName(); + boolean restoreName = Callables.trySetName((String)val$nameSupplier.get(), currentThread); + try { + return callable.call(); + } finally { + if (restoreName) { + Callables.trySetName(oldName, currentThread); + } + } + } + }; + } + + + + + + + + + + static Runnable threadRenaming(final Runnable task, Supplier nameSupplier) + { + Preconditions.checkNotNull(nameSupplier); + Preconditions.checkNotNull(task); + new Runnable() { + public void run() { + Thread currentThread = Thread.currentThread(); + String oldName = currentThread.getName(); + boolean restoreName = Callables.trySetName((String)val$nameSupplier.get(), currentThread); + try { + task.run(); + } finally { + if (restoreName) { + Callables.trySetName(oldName, currentThread); + } + } + } + }; + } + + + + private static boolean trySetName(String threadName, Thread currentThread) + { + try + { + currentThread.setName(threadName); + return true; + } catch (SecurityException e) {} + return false; + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/CheckedFuture.java b/src/minecraft/com/google/common/util/concurrent/CheckedFuture.java new file mode 100644 index 0000000..9baed4d --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/CheckedFuture.java @@ -0,0 +1,16 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +@Beta +public abstract interface CheckedFuture + extends ListenableFuture +{ + public abstract V checkedGet() + throws Exception; + + public abstract V checkedGet(long paramLong, TimeUnit paramTimeUnit) + throws TimeoutException, Exception; +} diff --git a/src/minecraft/com/google/common/util/concurrent/CycleDetectingLockFactory.java b/src/minecraft/com/google/common/util/concurrent/CycleDetectingLockFactory.java new file mode 100644 index 0000000..af97da9 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/CycleDetectingLockFactory.java @@ -0,0 +1,1034 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import com.google.common.collect.MapMaker; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; +import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; +import javax.annotation.concurrent.ThreadSafe; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@ThreadSafe +public class CycleDetectingLockFactory +{ + @Beta + @ThreadSafe + public static abstract interface Policy + { + public abstract void handlePotentialDeadlock(CycleDetectingLockFactory.PotentialDeadlockException paramPotentialDeadlockException); + } + + @Beta + public static abstract enum Policies + implements CycleDetectingLockFactory.Policy + { + THROW, + + + + + + + + + + + + + WARN, + + + + + + + + + + + + + + + + + DISABLED; + + + + private Policies() {} + } + + + + public static CycleDetectingLockFactory newInstance(Policy policy) + { + return new CycleDetectingLockFactory(policy); + } + + + + public ReentrantLock newReentrantLock(String lockName) + { + return newReentrantLock(lockName, false); + } + + + + + + public ReentrantLock newReentrantLock(String lockName, boolean fair) + { + return policy == Policies.DISABLED ? new ReentrantLock(fair) : new CycleDetectingReentrantLock(new LockGraphNode(lockName), fair, null); + } + + + + + + public ReentrantReadWriteLock newReentrantReadWriteLock(String lockName) + { + return newReentrantReadWriteLock(lockName, false); + } + + + + + + + public ReentrantReadWriteLock newReentrantReadWriteLock(String lockName, boolean fair) + { + return policy == Policies.DISABLED ? new ReentrantReadWriteLock(fair) : new CycleDetectingReentrantReadWriteLock(new LockGraphNode(lockName), fair, null); + } + + + + + + private static final ConcurrentMap, Map> lockGraphNodesPerType = new MapMaker().weakKeys().makeMap(); + + + + + + + + public static > WithExplicitOrdering newInstanceWithExplicitOrdering(Class enumClass, Policy policy) + { + Preconditions.checkNotNull(enumClass); + Preconditions.checkNotNull(policy); + + Map lockGraphNodes = getOrCreateNodes(enumClass); + + return new WithExplicitOrdering(policy, lockGraphNodes); + } + + private static Map getOrCreateNodes(Class clazz) + { + Map existing = (Map)lockGraphNodesPerType.get(clazz); + + if (existing != null) { + return existing; + } + Map created = createNodes(clazz); + existing = (Map)lockGraphNodesPerType.putIfAbsent(clazz, created); + return (Map)Objects.firstNonNull(existing, created); + } + + + + + + + @VisibleForTesting + static > Map createNodes(Class clazz) + { + EnumMap map = Maps.newEnumMap(clazz); + E[] keys = (Enum[])clazz.getEnumConstants(); + int numKeys = keys.length; + ArrayList nodes = Lists.newArrayListWithCapacity(numKeys); + + + for (E key : keys) { + LockGraphNode node = new LockGraphNode(getLockName(key)); + nodes.add(node); + map.put(key, node); + } + + for (int i = 1; i < numKeys; i++) { + ((LockGraphNode)nodes.get(i)).checkAcquiredLocks(Policies.THROW, nodes.subList(0, i)); + } + + for (int i = 0; i < numKeys - 1; i++) { + ((LockGraphNode)nodes.get(i)).checkAcquiredLocks(Policies.DISABLED, nodes.subList(i + 1, numKeys)); + } + + return Collections.unmodifiableMap(map); + } + + + + + + private static String getLockName(Enum rank) + { + return rank.getDeclaringClass().getSimpleName() + "." + rank.name(); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @Beta + public static final class WithExplicitOrdering> + extends CycleDetectingLockFactory + { + private final Map lockGraphNodes; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @VisibleForTesting + WithExplicitOrdering(CycleDetectingLockFactory.Policy policy, Map lockGraphNodes) + { + super(null); + this.lockGraphNodes = lockGraphNodes; + } + + + + public ReentrantLock newReentrantLock(E rank) + { + return newReentrantLock(rank, false); + } + + + + + + + + + + public ReentrantLock newReentrantLock(E rank, boolean fair) + { + return policy == CycleDetectingLockFactory.Policies.DISABLED ? new ReentrantLock(fair) : new CycleDetectingLockFactory.CycleDetectingReentrantLock(this, (CycleDetectingLockFactory.LockGraphNode)lockGraphNodes.get(rank), fair, null); + } + + + + + public ReentrantReadWriteLock newReentrantReadWriteLock(E rank) + { + return newReentrantReadWriteLock(rank, false); + } + + + + + + + + + + + public ReentrantReadWriteLock newReentrantReadWriteLock(E rank, boolean fair) + { + return policy == CycleDetectingLockFactory.Policies.DISABLED ? new ReentrantReadWriteLock(fair) : new CycleDetectingLockFactory.CycleDetectingReentrantReadWriteLock(this, (CycleDetectingLockFactory.LockGraphNode)lockGraphNodes.get(rank), fair, null); + } + } + + + + + + private static final Logger logger = Logger.getLogger(CycleDetectingLockFactory.class.getName()); + + final Policy policy; + + private CycleDetectingLockFactory(Policy policy) + { + this.policy = ((Policy)Preconditions.checkNotNull(policy)); + } + + + + + + + + + + private static final ThreadLocal> acquiredLocks = new ThreadLocal() + { + protected ArrayList initialValue() { + return Lists.newArrayListWithCapacity(3); + } + }; + + + + + + + + + + + + + + + private static class ExampleStackTrace + extends IllegalStateException + { + static final StackTraceElement[] EMPTY_STACK_TRACE = new StackTraceElement[0]; + + + static Set EXCLUDED_CLASS_NAMES = ImmutableSet.of(CycleDetectingLockFactory.class.getName(), ExampleStackTrace.class.getName(), CycleDetectingLockFactory.LockGraphNode.class.getName()); + + + + ExampleStackTrace(CycleDetectingLockFactory.LockGraphNode node1, CycleDetectingLockFactory.LockGraphNode node2) + { + super(); + StackTraceElement[] origStackTrace = getStackTrace(); + int i = 0; for (int n = origStackTrace.length; i < n; i++) { + if (CycleDetectingLockFactory.WithExplicitOrdering.class.getName().equals(origStackTrace[i].getClassName())) + { + + setStackTrace(EMPTY_STACK_TRACE); + break; + } + if (!EXCLUDED_CLASS_NAMES.contains(origStackTrace[i].getClassName())) { + setStackTrace((StackTraceElement[])Arrays.copyOfRange(origStackTrace, i, n)); + break; + } + } + } + } + + + + + + + + + + + + + + @Beta + public static final class PotentialDeadlockException + extends CycleDetectingLockFactory.ExampleStackTrace + { + private final CycleDetectingLockFactory.ExampleStackTrace conflictingStackTrace; + + + + + + + + + + + + + + private PotentialDeadlockException(CycleDetectingLockFactory.LockGraphNode node1, CycleDetectingLockFactory.LockGraphNode node2, CycleDetectingLockFactory.ExampleStackTrace conflictingStackTrace) + { + super(node2); + this.conflictingStackTrace = conflictingStackTrace; + initCause(conflictingStackTrace); + } + + public CycleDetectingLockFactory.ExampleStackTrace getConflictingStackTrace() { + return conflictingStackTrace; + } + + + + + + public String getMessage() + { + StringBuilder message = new StringBuilder(super.getMessage()); + for (Throwable t = conflictingStackTrace; t != null; t = t.getCause()) { + message.append(", ").append(t.getMessage()); + } + return message.toString(); + } + } + + + + + + + + private static abstract interface CycleDetectingLock + { + public abstract CycleDetectingLockFactory.LockGraphNode getLockGraphNode(); + + + + + + + public abstract boolean isAcquiredByCurrentThread(); + } + + + + + + + private static class LockGraphNode + { + final Map allowedPriorLocks = new MapMaker().weakKeys().makeMap(); + + + + + + + final Map disallowedPriorLocks = new MapMaker().weakKeys().makeMap(); + + final String lockName; + + LockGraphNode(String lockName) + { + this.lockName = ((String)Preconditions.checkNotNull(lockName)); + } + + String getLockName() { + return lockName; + } + + void checkAcquiredLocks(CycleDetectingLockFactory.Policy policy, List acquiredLocks) + { + int i = 0; for (int size = acquiredLocks.size(); i < size; i++) { + checkAcquiredLock(policy, (LockGraphNode)acquiredLocks.get(i)); + } + } + + + + + + + + + + + + + + + + void checkAcquiredLock(CycleDetectingLockFactory.Policy policy, LockGraphNode acquiredLock) + { + Preconditions.checkState(this != acquiredLock, "Attempted to acquire multiple locks with the same rank " + acquiredLock.getLockName()); + + + + + if (allowedPriorLocks.containsKey(acquiredLock)) + { + + + return; + } + CycleDetectingLockFactory.PotentialDeadlockException previousDeadlockException = (CycleDetectingLockFactory.PotentialDeadlockException)disallowedPriorLocks.get(acquiredLock); + + if (previousDeadlockException != null) + { + + + CycleDetectingLockFactory.PotentialDeadlockException exception = new CycleDetectingLockFactory.PotentialDeadlockException(acquiredLock, this, previousDeadlockException.getConflictingStackTrace(), null); + + + policy.handlePotentialDeadlock(exception); + return; + } + + + Set seen = Sets.newIdentityHashSet(); + CycleDetectingLockFactory.ExampleStackTrace path = acquiredLock.findPathTo(this, seen); + + if (path == null) + { + + + + + + + + allowedPriorLocks.put(acquiredLock, new CycleDetectingLockFactory.ExampleStackTrace(acquiredLock, this)); + + } + else + { + CycleDetectingLockFactory.PotentialDeadlockException exception = new CycleDetectingLockFactory.PotentialDeadlockException(acquiredLock, this, path, null); + + disallowedPriorLocks.put(acquiredLock, exception); + policy.handlePotentialDeadlock(exception); + } + } + + + + + + + + + + + @Nullable + private CycleDetectingLockFactory.ExampleStackTrace findPathTo(LockGraphNode node, Set seen) + { + if (!seen.add(this)) { + return null; + } + CycleDetectingLockFactory.ExampleStackTrace found = (CycleDetectingLockFactory.ExampleStackTrace)allowedPriorLocks.get(node); + if (found != null) { + return found; + } + + + for (Map.Entry entry : allowedPriorLocks.entrySet()) { + LockGraphNode preAcquiredLock = (LockGraphNode)entry.getKey(); + found = preAcquiredLock.findPathTo(node, seen); + if (found != null) + { + + + CycleDetectingLockFactory.ExampleStackTrace path = new CycleDetectingLockFactory.ExampleStackTrace(preAcquiredLock, this); + + path.setStackTrace(((CycleDetectingLockFactory.ExampleStackTrace)entry.getValue()).getStackTrace()); + path.initCause(found); + return path; + } + } + return null; + } + } + + + + + private void aboutToAcquire(CycleDetectingLock lock) + { + if (!lock.isAcquiredByCurrentThread()) { + ArrayList acquiredLockList = (ArrayList)acquiredLocks.get(); + LockGraphNode node = lock.getLockGraphNode(); + node.checkAcquiredLocks(policy, acquiredLockList); + acquiredLockList.add(node); + } + } + + + + + + + private void lockStateChanged(CycleDetectingLock lock) + { + if (!lock.isAcquiredByCurrentThread()) { + ArrayList acquiredLockList = (ArrayList)acquiredLocks.get(); + LockGraphNode node = lock.getLockGraphNode(); + + + for (int i = acquiredLockList.size() - 1; i >= 0; i--) { + if (acquiredLockList.get(i) == node) { + acquiredLockList.remove(i); + break; + } + } + } + } + + final class CycleDetectingReentrantLock + extends ReentrantLock implements CycleDetectingLockFactory.CycleDetectingLock + { + private final CycleDetectingLockFactory.LockGraphNode lockGraphNode; + + private CycleDetectingReentrantLock(CycleDetectingLockFactory.LockGraphNode lockGraphNode, boolean fair) + { + super(); + this.lockGraphNode = ((CycleDetectingLockFactory.LockGraphNode)Preconditions.checkNotNull(lockGraphNode)); + } + + + + public CycleDetectingLockFactory.LockGraphNode getLockGraphNode() + { + return lockGraphNode; + } + + public boolean isAcquiredByCurrentThread() + { + return isHeldByCurrentThread(); + } + + + + public void lock() + { + CycleDetectingLockFactory.this.aboutToAcquire(this); + try { + super.lock(); + } finally { + CycleDetectingLockFactory.this.lockStateChanged(this); + } + } + + public void lockInterruptibly() throws InterruptedException + { + CycleDetectingLockFactory.this.aboutToAcquire(this); + try { + super.lockInterruptibly(); + } finally { + CycleDetectingLockFactory.this.lockStateChanged(this); + } + } + + public boolean tryLock() + { + CycleDetectingLockFactory.this.aboutToAcquire(this); + try { + return super.tryLock(); + } finally { + CycleDetectingLockFactory.this.lockStateChanged(this); + } + } + + public boolean tryLock(long timeout, TimeUnit unit) + throws InterruptedException + { + CycleDetectingLockFactory.this.aboutToAcquire(this); + try { + return super.tryLock(timeout, unit); + } finally { + CycleDetectingLockFactory.this.lockStateChanged(this); + } + } + + public void unlock() + { + try { + super.unlock(); + } finally { + CycleDetectingLockFactory.this.lockStateChanged(this); + } + } + } + + + final class CycleDetectingReentrantReadWriteLock + extends ReentrantReadWriteLock + implements CycleDetectingLockFactory.CycleDetectingLock + { + private final CycleDetectingLockFactory.CycleDetectingReentrantReadLock readLock; + + private final CycleDetectingLockFactory.CycleDetectingReentrantWriteLock writeLock; + + private final CycleDetectingLockFactory.LockGraphNode lockGraphNode; + + + private CycleDetectingReentrantReadWriteLock(CycleDetectingLockFactory.LockGraphNode lockGraphNode, boolean fair) + { + super(); + readLock = new CycleDetectingLockFactory.CycleDetectingReentrantReadLock(CycleDetectingLockFactory.this, this); + writeLock = new CycleDetectingLockFactory.CycleDetectingReentrantWriteLock(CycleDetectingLockFactory.this, this); + this.lockGraphNode = ((CycleDetectingLockFactory.LockGraphNode)Preconditions.checkNotNull(lockGraphNode)); + } + + + + public ReentrantReadWriteLock.ReadLock readLock() + { + return readLock; + } + + public ReentrantReadWriteLock.WriteLock writeLock() + { + return writeLock; + } + + + + public CycleDetectingLockFactory.LockGraphNode getLockGraphNode() + { + return lockGraphNode; + } + + public boolean isAcquiredByCurrentThread() + { + return (isWriteLockedByCurrentThread()) || (getReadHoldCount() > 0); + } + } + + private class CycleDetectingReentrantReadLock + extends ReentrantReadWriteLock.ReadLock + { + final CycleDetectingLockFactory.CycleDetectingReentrantReadWriteLock readWriteLock; + + CycleDetectingReentrantReadLock(CycleDetectingLockFactory.CycleDetectingReentrantReadWriteLock readWriteLock) + { + super(); + this.readWriteLock = readWriteLock; + } + + public void lock() + { + CycleDetectingLockFactory.this.aboutToAcquire(readWriteLock); + try { + super.lock(); + } finally { + CycleDetectingLockFactory.this.lockStateChanged(readWriteLock); + } + } + + public void lockInterruptibly() throws InterruptedException + { + CycleDetectingLockFactory.this.aboutToAcquire(readWriteLock); + try { + super.lockInterruptibly(); + } finally { + CycleDetectingLockFactory.this.lockStateChanged(readWriteLock); + } + } + + public boolean tryLock() + { + CycleDetectingLockFactory.this.aboutToAcquire(readWriteLock); + try { + return super.tryLock(); + } finally { + CycleDetectingLockFactory.this.lockStateChanged(readWriteLock); + } + } + + public boolean tryLock(long timeout, TimeUnit unit) + throws InterruptedException + { + CycleDetectingLockFactory.this.aboutToAcquire(readWriteLock); + try { + return super.tryLock(timeout, unit); + } finally { + CycleDetectingLockFactory.this.lockStateChanged(readWriteLock); + } + } + + public void unlock() + { + try { + super.unlock(); + } finally { + CycleDetectingLockFactory.this.lockStateChanged(readWriteLock); + } + } + } + + private class CycleDetectingReentrantWriteLock + extends ReentrantReadWriteLock.WriteLock + { + final CycleDetectingLockFactory.CycleDetectingReentrantReadWriteLock readWriteLock; + + CycleDetectingReentrantWriteLock(CycleDetectingLockFactory.CycleDetectingReentrantReadWriteLock readWriteLock) + { + super(); + this.readWriteLock = readWriteLock; + } + + public void lock() + { + CycleDetectingLockFactory.this.aboutToAcquire(readWriteLock); + try { + super.lock(); + } finally { + CycleDetectingLockFactory.this.lockStateChanged(readWriteLock); + } + } + + public void lockInterruptibly() throws InterruptedException + { + CycleDetectingLockFactory.this.aboutToAcquire(readWriteLock); + try { + super.lockInterruptibly(); + } finally { + CycleDetectingLockFactory.this.lockStateChanged(readWriteLock); + } + } + + public boolean tryLock() + { + CycleDetectingLockFactory.this.aboutToAcquire(readWriteLock); + try { + return super.tryLock(); + } finally { + CycleDetectingLockFactory.this.lockStateChanged(readWriteLock); + } + } + + public boolean tryLock(long timeout, TimeUnit unit) + throws InterruptedException + { + CycleDetectingLockFactory.this.aboutToAcquire(readWriteLock); + try { + return super.tryLock(timeout, unit); + } finally { + CycleDetectingLockFactory.this.lockStateChanged(readWriteLock); + } + } + + public void unlock() + { + try { + super.unlock(); + } finally { + CycleDetectingLockFactory.this.lockStateChanged(readWriteLock); + } + } + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/ExecutionError.java b/src/minecraft/com/google/common/util/concurrent/ExecutionError.java new file mode 100644 index 0000000..121e671 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/ExecutionError.java @@ -0,0 +1,62 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.GwtCompatible; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public class ExecutionError + extends Error +{ + private static final long serialVersionUID = 0L; + + protected ExecutionError() {} + + protected ExecutionError(@Nullable String message) + { + super(message); + } + + + + public ExecutionError(@Nullable String message, @Nullable Error cause) + { + super(message, cause); + } + + + + public ExecutionError(@Nullable Error cause) + { + super(cause); + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/ExecutionList.java b/src/minecraft/com/google/common/util/concurrent/ExecutionList.java new file mode 100644 index 0000000..1d75b00 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/ExecutionList.java @@ -0,0 +1,177 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import java.util.concurrent.Executor; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; +import javax.annotation.concurrent.GuardedBy; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public final class ExecutionList +{ + @VisibleForTesting + static final Logger log = Logger.getLogger(ExecutionList.class.getName()); + + + + + + + + @GuardedBy("this") + private RunnableExecutorPair runnables; + + + + + + + + @GuardedBy("this") + private boolean executed; + + + + + + + + public ExecutionList() {} + + + + + + + + public void add(Runnable runnable, Executor executor) + { + Preconditions.checkNotNull(runnable, "Runnable was null."); + Preconditions.checkNotNull(executor, "Executor was null."); + + + + + synchronized (this) { + if (!executed) { + runnables = new RunnableExecutorPair(runnable, executor, runnables); + return; + } + } + + + + + executeListener(runnable, executor); + } + + + + + + + + + public void execute() + { + RunnableExecutorPair list; + + + + + + + synchronized (this) { + if (executed) { + return; + } + executed = true; + list = runnables; + runnables = null; + } + + + + + + + + + + RunnableExecutorPair reversedList = null; + while (list != null) { + RunnableExecutorPair tmp = list; + list = next; + next = reversedList; + reversedList = tmp; + } + while (reversedList != null) { + executeListener(runnable, executor); + reversedList = next; + } + } + + + + private static void executeListener(Runnable runnable, Executor executor) + { + try + { + executor.execute(runnable); + + } + catch (RuntimeException e) + { + log.log(Level.SEVERE, "RuntimeException while executing runnable " + runnable + " with executor " + executor, e); + } + } + + private static final class RunnableExecutorPair { + final Runnable runnable; + final Executor executor; + @Nullable + RunnableExecutorPair next; + + RunnableExecutorPair(Runnable runnable, Executor executor, RunnableExecutorPair next) { + this.runnable = runnable; + this.executor = executor; + this.next = next; + } + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/FakeTimeLimiter.java b/src/minecraft/com/google/common/util/concurrent/FakeTimeLimiter.java new file mode 100644 index 0000000..de0e9d1 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/FakeTimeLimiter.java @@ -0,0 +1,53 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class FakeTimeLimiter + implements TimeLimiter +{ + public FakeTimeLimiter() {} + + public T newProxy(T target, Class interfaceType, long timeoutDuration, TimeUnit timeoutUnit) + { + Preconditions.checkNotNull(target); + Preconditions.checkNotNull(interfaceType); + Preconditions.checkNotNull(timeoutUnit); + return target; + } + + public T callWithTimeout(Callable callable, long timeoutDuration, TimeUnit timeoutUnit, boolean amInterruptible) + throws Exception + { + Preconditions.checkNotNull(timeoutUnit); + return callable.call(); + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/ForwardingBlockingQueue.java b/src/minecraft/com/google/common/util/concurrent/ForwardingBlockingQueue.java new file mode 100644 index 0000000..c65015e --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/ForwardingBlockingQueue.java @@ -0,0 +1,74 @@ +package com.google.common.util.concurrent; + +import com.google.common.collect.ForwardingQueue; +import java.util.Collection; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.TimeUnit; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class ForwardingBlockingQueue + extends ForwardingQueue + implements BlockingQueue +{ + protected ForwardingBlockingQueue() {} + + protected abstract BlockingQueue delegate(); + + public int drainTo(Collection c, int maxElements) + { + return delegate().drainTo(c, maxElements); + } + + public int drainTo(Collection c) { + return delegate().drainTo(c); + } + + public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException + { + return delegate().offer(e, timeout, unit); + } + + public E poll(long timeout, TimeUnit unit) throws InterruptedException + { + return delegate().poll(timeout, unit); + } + + public void put(E e) throws InterruptedException { + delegate().put(e); + } + + public int remainingCapacity() { + return delegate().remainingCapacity(); + } + + public E take() throws InterruptedException { + return delegate().take(); + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/ForwardingCheckedFuture.java b/src/minecraft/com/google/common/util/concurrent/ForwardingCheckedFuture.java new file mode 100644 index 0000000..a7c563d --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/ForwardingCheckedFuture.java @@ -0,0 +1,78 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public abstract class ForwardingCheckedFuture + extends ForwardingListenableFuture + implements CheckedFuture +{ + public ForwardingCheckedFuture() {} + + public V checkedGet() + throws Exception + { + return delegate().checkedGet(); + } + + public V checkedGet(long timeout, TimeUnit unit) throws TimeoutException, Exception + { + return delegate().checkedGet(timeout, unit); + } + + + + protected abstract CheckedFuture delegate(); + + + + @Beta + public static abstract class SimpleForwardingCheckedFuture + extends ForwardingCheckedFuture + { + private final CheckedFuture delegate; + + + + protected SimpleForwardingCheckedFuture(CheckedFuture delegate) + { + this.delegate = ((CheckedFuture)Preconditions.checkNotNull(delegate)); + } + + protected final CheckedFuture delegate() + { + return delegate; + } + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/ForwardingExecutorService.java b/src/minecraft/com/google/common/util/concurrent/ForwardingExecutorService.java new file mode 100644 index 0000000..86091a0 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/ForwardingExecutorService.java @@ -0,0 +1,117 @@ +package com.google.common.util.concurrent; + +import com.google.common.collect.ForwardingObject; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + + + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class ForwardingExecutorService + extends ForwardingObject + implements ExecutorService +{ + protected ForwardingExecutorService() {} + + protected abstract ExecutorService delegate(); + + public boolean awaitTermination(long timeout, TimeUnit unit) + throws InterruptedException + { + return delegate().awaitTermination(timeout, unit); + } + + public List> invokeAll(Collection> tasks) + throws InterruptedException + { + return delegate().invokeAll(tasks); + } + + + public List> invokeAll(Collection> tasks, long timeout, TimeUnit unit) + throws InterruptedException + { + return delegate().invokeAll(tasks, timeout, unit); + } + + public T invokeAny(Collection> tasks) + throws InterruptedException, ExecutionException + { + return delegate().invokeAny(tasks); + } + + + public T invokeAny(Collection> tasks, long timeout, TimeUnit unit) + throws InterruptedException, ExecutionException, TimeoutException + { + return delegate().invokeAny(tasks, timeout, unit); + } + + public boolean isShutdown() + { + return delegate().isShutdown(); + } + + public boolean isTerminated() + { + return delegate().isTerminated(); + } + + public void shutdown() + { + delegate().shutdown(); + } + + public List shutdownNow() + { + return delegate().shutdownNow(); + } + + public void execute(Runnable command) + { + delegate().execute(command); + } + + public Future submit(Callable task) { + return delegate().submit(task); + } + + public Future submit(Runnable task) + { + return delegate().submit(task); + } + + public Future submit(Runnable task, T result) + { + return delegate().submit(task, result); + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/ForwardingFuture.java b/src/minecraft/com/google/common/util/concurrent/ForwardingFuture.java new file mode 100644 index 0000000..010d787 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/ForwardingFuture.java @@ -0,0 +1,95 @@ +package com.google.common.util.concurrent; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ForwardingObject; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class ForwardingFuture + extends ForwardingObject + implements Future +{ + protected ForwardingFuture() {} + + protected abstract Future delegate(); + + public boolean cancel(boolean mayInterruptIfRunning) + { + return delegate().cancel(mayInterruptIfRunning); + } + + public boolean isCancelled() + { + return delegate().isCancelled(); + } + + public boolean isDone() + { + return delegate().isDone(); + } + + public V get() throws InterruptedException, ExecutionException + { + return delegate().get(); + } + + public V get(long timeout, TimeUnit unit) + throws InterruptedException, ExecutionException, TimeoutException + { + return delegate().get(timeout, unit); + } + + + + + + public static abstract class SimpleForwardingFuture + extends ForwardingFuture + { + private final Future delegate; + + + + + + protected SimpleForwardingFuture(Future delegate) + { + this.delegate = ((Future)Preconditions.checkNotNull(delegate)); + } + + protected final Future delegate() + { + return delegate; + } + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/ForwardingListenableFuture.java b/src/minecraft/com/google/common/util/concurrent/ForwardingListenableFuture.java new file mode 100644 index 0000000..9811f3e --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/ForwardingListenableFuture.java @@ -0,0 +1,74 @@ +package com.google.common.util.concurrent; + +import com.google.common.base.Preconditions; +import java.util.concurrent.Executor; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class ForwardingListenableFuture + extends ForwardingFuture + implements ListenableFuture +{ + protected ForwardingListenableFuture() {} + + protected abstract ListenableFuture delegate(); + + public void addListener(Runnable listener, Executor exec) + { + delegate().addListener(listener, exec); + } + + + + + + + public static abstract class SimpleForwardingListenableFuture + extends ForwardingListenableFuture + { + private final ListenableFuture delegate; + + + + + + protected SimpleForwardingListenableFuture(ListenableFuture delegate) + { + this.delegate = ((ListenableFuture)Preconditions.checkNotNull(delegate)); + } + + protected final ListenableFuture delegate() + { + return delegate; + } + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/ForwardingListeningExecutorService.java b/src/minecraft/com/google/common/util/concurrent/ForwardingListeningExecutorService.java new file mode 100644 index 0000000..da85eed --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/ForwardingListeningExecutorService.java @@ -0,0 +1,52 @@ +package com.google.common.util.concurrent; + +import java.util.concurrent.Callable; + + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class ForwardingListeningExecutorService + extends ForwardingExecutorService + implements ListeningExecutorService +{ + protected ForwardingListeningExecutorService() {} + + protected abstract ListeningExecutorService delegate(); + + public ListenableFuture submit(Callable task) + { + return delegate().submit(task); + } + + public ListenableFuture submit(Runnable task) + { + return delegate().submit(task); + } + + public ListenableFuture submit(Runnable task, T result) + { + return delegate().submit(task, result); + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/FutureCallback.java b/src/minecraft/com/google/common/util/concurrent/FutureCallback.java new file mode 100644 index 0000000..6fe1791 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/FutureCallback.java @@ -0,0 +1,10 @@ +package com.google.common.util.concurrent; + +import javax.annotation.Nullable; + +public abstract interface FutureCallback +{ + public abstract void onSuccess(@Nullable V paramV); + + public abstract void onFailure(Throwable paramThrowable); +} diff --git a/src/minecraft/com/google/common/util/concurrent/FutureFallback.java b/src/minecraft/com/google/common/util/concurrent/FutureFallback.java new file mode 100644 index 0000000..39bc5d8 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/FutureFallback.java @@ -0,0 +1,10 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; + +@Beta +public abstract interface FutureFallback +{ + public abstract ListenableFuture create(Throwable paramThrowable) + throws Exception; +} diff --git a/src/minecraft/com/google/common/util/concurrent/Futures.java b/src/minecraft/com/google/common/util/concurrent/Futures.java new file mode 100644 index 0000000..cfa14d6 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/Futures.java @@ -0,0 +1,1730 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableList.Builder; +import com.google.common.collect.Lists; +import com.google.common.collect.Ordering; +import com.google.common.collect.Queues; +import com.google.common.collect.Sets; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.UndeclaredThrowableException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class Futures +{ + private Futures() {} + + public static CheckedFuture makeChecked(ListenableFuture future, Function mapper) + { + return new MappingCheckedFuture((ListenableFuture)Preconditions.checkNotNull(future), mapper); + } + + private static abstract class ImmediateFuture + implements ListenableFuture + { + private static final Logger log = Logger.getLogger(ImmediateFuture.class.getName()); + + private ImmediateFuture() {} + + public void addListener(Runnable listener, Executor executor) { + Preconditions.checkNotNull(listener, "Runnable was null."); + Preconditions.checkNotNull(executor, "Executor was null."); + try { + executor.execute(listener); + } + catch (RuntimeException e) + { + log.log(Level.SEVERE, "RuntimeException while executing runnable " + listener + " with executor " + executor, e); + } + } + + + public boolean cancel(boolean mayInterruptIfRunning) + { + return false; + } + + public abstract V get() + throws ExecutionException; + + public V get(long timeout, TimeUnit unit) throws ExecutionException + { + Preconditions.checkNotNull(unit); + return get(); + } + + public boolean isCancelled() + { + return false; + } + + + + public boolean isDone() { return true; } + } + + private static class ImmediateSuccessfulFuture extends Futures.ImmediateFuture { + @Nullable + private final V value; + + ImmediateSuccessfulFuture(@Nullable V value) { + super(); + this.value = value; + } + + public V get() + { + return value; + } + } + + private static class ImmediateSuccessfulCheckedFuture extends Futures.ImmediateFuture implements CheckedFuture { + @Nullable + private final V value; + + ImmediateSuccessfulCheckedFuture(@Nullable V value) { + super(); + this.value = value; + } + + public V get() + { + return value; + } + + public V checkedGet() + { + return value; + } + + public V checkedGet(long timeout, TimeUnit unit) + { + Preconditions.checkNotNull(unit); + return value; + } + } + + private static class ImmediateFailedFuture extends Futures.ImmediateFuture { + private final Throwable thrown; + + ImmediateFailedFuture(Throwable thrown) { + super(); + this.thrown = thrown; + } + + public V get() throws ExecutionException + { + throw new ExecutionException(thrown); + } + } + + private static class ImmediateCancelledFuture extends Futures.ImmediateFuture { + private final CancellationException thrown; + + ImmediateCancelledFuture() { + super(); + thrown = new CancellationException("Immediate cancelled future."); + } + + public boolean isCancelled() + { + return true; + } + + public V get() + { + throw AbstractFuture.cancellationExceptionWithCause("Task was cancelled.", thrown); + } + } + + private static class ImmediateFailedCheckedFuture extends Futures.ImmediateFuture implements CheckedFuture + { + private final X thrown; + + ImmediateFailedCheckedFuture(X thrown) + { + super(); + this.thrown = thrown; + } + + public V get() throws ExecutionException + { + throw new ExecutionException(thrown); + } + + public V checkedGet() throws Exception + { + throw thrown; + } + + public V checkedGet(long timeout, TimeUnit unit) throws Exception + { + Preconditions.checkNotNull(unit); + throw thrown; + } + } + + + + + + + public static ListenableFuture immediateFuture(@Nullable V value) + { + return new ImmediateSuccessfulFuture(value); + } + + + + + + + + + + public static CheckedFuture immediateCheckedFuture(@Nullable V value) + { + return new ImmediateSuccessfulCheckedFuture(value); + } + + + + + + + + + + + public static ListenableFuture immediateFailedFuture(Throwable throwable) + { + Preconditions.checkNotNull(throwable); + return new ImmediateFailedFuture(throwable); + } + + + + + + + public static ListenableFuture immediateCancelledFuture() + { + return new ImmediateCancelledFuture(); + } + + + + + + + + + + + + public static CheckedFuture immediateFailedCheckedFuture(X exception) + { + Preconditions.checkNotNull(exception); + return new ImmediateFailedCheckedFuture(exception); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static ListenableFuture withFallback(ListenableFuture input, FutureFallback fallback) + { + return withFallback(input, fallback, MoreExecutors.sameThreadExecutor()); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static ListenableFuture withFallback(ListenableFuture input, FutureFallback fallback, Executor executor) + { + Preconditions.checkNotNull(fallback); + return new FallbackFuture(input, fallback, executor); + } + + + + private static class FallbackFuture + extends AbstractFuture + { + private volatile ListenableFuture running; + + + + FallbackFuture(ListenableFuture input, final FutureFallback fallback, Executor executor) + { + running = input; + Futures.addCallback(running, new FutureCallback() + { + public void onSuccess(V value) { + set(value); + } + + public void onFailure(Throwable t) + { + if (isCancelled()) { + return; + } + try { + running = fallback.create(t); + if (isCancelled()) { + running.cancel(wasInterrupted()); + return; + } + Futures.addCallback(running, new FutureCallback() + { + public void onSuccess(V value) { + set(value); + } + + public void onFailure(Throwable t) + { + if (running.isCancelled()) { + cancel(false); + } else + setException(t); } }, MoreExecutors.sameThreadExecutor()); + + } + catch (Throwable e) + { + setException(e); } } }, executor); + } + + + + + public boolean cancel(boolean mayInterruptIfRunning) + { + if (super.cancel(mayInterruptIfRunning)) { + running.cancel(mayInterruptIfRunning); + return true; + } + return false; + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static ListenableFuture transform(ListenableFuture input, AsyncFunction function) + { + return transform(input, function, MoreExecutors.sameThreadExecutor()); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static ListenableFuture transform(ListenableFuture input, AsyncFunction function, Executor executor) + { + ChainingListenableFuture output = new ChainingListenableFuture(function, input, null); + + input.addListener(output, executor); + return output; + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static ListenableFuture transform(ListenableFuture input, Function function) + { + return transform(input, function, MoreExecutors.sameThreadExecutor()); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static ListenableFuture transform(ListenableFuture input, Function function, Executor executor) + { + Preconditions.checkNotNull(function); + AsyncFunction wrapperFunction = new AsyncFunction() + { + public ListenableFuture apply(I input) { + O output = val$function.apply(input); + return Futures.immediateFuture(output); + } + }; + return transform(input, wrapperFunction, executor); + } + + + + + + + + + + + + + + + + + + + + + + + + + public static Future lazyTransform(Future input, final Function function) + { + Preconditions.checkNotNull(input); + Preconditions.checkNotNull(function); + new Future() + { + public boolean cancel(boolean mayInterruptIfRunning) + { + return val$input.cancel(mayInterruptIfRunning); + } + + public boolean isCancelled() + { + return val$input.isCancelled(); + } + + public boolean isDone() + { + return val$input.isDone(); + } + + public O get() throws InterruptedException, ExecutionException + { + return applyTransformation(val$input.get()); + } + + public O get(long timeout, TimeUnit unit) + throws InterruptedException, ExecutionException, TimeoutException + { + return applyTransformation(val$input.get(timeout, unit)); + } + + private O applyTransformation(I input) throws ExecutionException { + try { + return function.apply(input); + } catch (Throwable t) { + throw new ExecutionException(t); + } + } + }; + } + + + + + + + private static class ChainingListenableFuture + extends AbstractFuture + implements Runnable + { + private AsyncFunction function; + + + + + + private ListenableFuture inputFuture; + + + + + + private volatile ListenableFuture outputFuture; + + + + + private final CountDownLatch outputCreated = new CountDownLatch(1); + + + private ChainingListenableFuture(AsyncFunction function, ListenableFuture inputFuture) + { + this.function = ((AsyncFunction)Preconditions.checkNotNull(function)); + this.inputFuture = ((ListenableFuture)Preconditions.checkNotNull(inputFuture)); + } + + + + + + public boolean cancel(boolean mayInterruptIfRunning) + { + if (super.cancel(mayInterruptIfRunning)) + { + + cancel(inputFuture, mayInterruptIfRunning); + cancel(outputFuture, mayInterruptIfRunning); + return true; + } + return false; + } + + private void cancel(@Nullable Future future, boolean mayInterruptIfRunning) + { + if (future != null) { + future.cancel(mayInterruptIfRunning); + } + } + + public void run() + { + try { + I sourceResult; + try { + sourceResult = Uninterruptibles.getUninterruptibly(inputFuture); + + } + catch (CancellationException e) + { + cancel(false); return; + } + catch (ExecutionException e) + { + setException(e.getCause()); return; + } + + + final ListenableFuture outputFuture = this.outputFuture = (ListenableFuture)Preconditions.checkNotNull(function.apply(sourceResult), "AsyncFunction may not return null."); + + + if (isCancelled()) { + outputFuture.cancel(wasInterrupted()); + this.outputFuture = null; + } + else { + outputFuture.addListener(new Runnable() + { + public void run() { + try { + set(Uninterruptibles.getUninterruptibly(outputFuture)); + + } + catch (CancellationException e) + { + cancel(false); + } + catch (ExecutionException e) + { + setException(e.getCause()); + } + finally { + outputFuture = null; } } }, MoreExecutors.sameThreadExecutor()); + } + + } + catch (UndeclaredThrowableException e) + { + setException(e.getCause()); + } + catch (Throwable t) + { + setException(t); + } + finally { + function = null; + inputFuture = null; + + outputCreated.countDown(); + } + } + } + + + + + + + + + + + + + + + + + + + + + + + + public static ListenableFuture dereference(ListenableFuture> nested) + { + return transform(nested, DEREFERENCER); + } + + + + + private static final AsyncFunction, Object> DEREFERENCER = new AsyncFunction() + { + public ListenableFuture apply(ListenableFuture input) { + return input; + } + }; + + + + + + + + + + + + + + + + + + @Beta + public static ListenableFuture> allAsList(ListenableFuture... futures) + { + return listFuture(ImmutableList.copyOf(futures), true, MoreExecutors.sameThreadExecutor()); + } + + + + + + + + + + + + + + + + + + + @Beta + public static ListenableFuture> allAsList(Iterable> futures) + { + return listFuture(ImmutableList.copyOf(futures), true, MoreExecutors.sameThreadExecutor()); + } + + + + + + + + + + + public static ListenableFuture nonCancellationPropagating(ListenableFuture future) + { + return new NonCancellationPropagatingFuture(future); + } + + + private static class NonCancellationPropagatingFuture + extends AbstractFuture + { + NonCancellationPropagatingFuture(final ListenableFuture delegate) + { + Preconditions.checkNotNull(delegate); + Futures.addCallback(delegate, new FutureCallback() + { + public void onSuccess(V result) { + set(result); + } + + public void onFailure(Throwable t) + { + if (delegate.isCancelled()) { + cancel(false); + } else + setException(t); } }, MoreExecutors.sameThreadExecutor()); + } + } + + + + + + + + + + + + + + + + + + + + @Beta + public static ListenableFuture> successfulAsList(ListenableFuture... futures) + { + return listFuture(ImmutableList.copyOf(futures), false, MoreExecutors.sameThreadExecutor()); + } + + + + + + + + + + + + + + + + + + @Beta + public static ListenableFuture> successfulAsList(Iterable> futures) + { + return listFuture(ImmutableList.copyOf(futures), false, MoreExecutors.sameThreadExecutor()); + } + + + + + + + + + + + + + + + + + + @Beta + public static ImmutableList> inCompletionOrder(Iterable> futures) + { + ConcurrentLinkedQueue> delegates = Queues.newConcurrentLinkedQueue(); + + ImmutableList.Builder> listBuilder = ImmutableList.builder(); + + + + + + + + + + + SerializingExecutor executor = new SerializingExecutor(MoreExecutors.sameThreadExecutor()); + for (final ListenableFuture future : futures) { + AsyncSettableFuture delegate = AsyncSettableFuture.create(); + + delegates.add(delegate); + future.addListener(new Runnable() + { + public void run() { ((AsyncSettableFuture)val$delegates.remove()).setFuture(future); } }, executor); + + + listBuilder.add(delegate); + } + return listBuilder.build(); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static void addCallback(ListenableFuture future, FutureCallback callback) + { + addCallback(future, callback, MoreExecutors.sameThreadExecutor()); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static void addCallback(ListenableFuture future, final FutureCallback callback, Executor executor) + { + Preconditions.checkNotNull(callback); + Runnable callbackListener = new Runnable() + { + public void run() + { + V value; + try + { + value = Uninterruptibles.getUninterruptibly(val$future); + } catch (ExecutionException e) { + callback.onFailure(e.getCause()); + return; + } catch (RuntimeException e) { + callback.onFailure(e); + return; + } catch (Error e) { + callback.onFailure(e); + return; + } + callback.onSuccess(value); + } + }; + future.addListener(callbackListener, executor); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static V get(Future future, Class exceptionClass) + throws Exception + { + Preconditions.checkNotNull(future); + Preconditions.checkArgument(!RuntimeException.class.isAssignableFrom(exceptionClass), "Futures.get exception type (%s) must not be a RuntimeException", new Object[] { exceptionClass }); + + try + { + return future.get(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw newWithCause(exceptionClass, e); + } catch (ExecutionException e) { + wrapAndThrowExceptionOrError(e.getCause(), exceptionClass); + throw new AssertionError(); + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static V get(Future future, long timeout, TimeUnit unit, Class exceptionClass) + throws Exception + { + Preconditions.checkNotNull(future); + Preconditions.checkNotNull(unit); + Preconditions.checkArgument(!RuntimeException.class.isAssignableFrom(exceptionClass), "Futures.get exception type (%s) must not be a RuntimeException", new Object[] { exceptionClass }); + + try + { + return future.get(timeout, unit); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw newWithCause(exceptionClass, e); + } catch (TimeoutException e) { + throw newWithCause(exceptionClass, e); + } catch (ExecutionException e) { + wrapAndThrowExceptionOrError(e.getCause(), exceptionClass); + throw new AssertionError(); + } + } + + private static void wrapAndThrowExceptionOrError(Throwable cause, Class exceptionClass) throws Exception + { + if ((cause instanceof Error)) { + throw new ExecutionError((Error)cause); + } + if ((cause instanceof RuntimeException)) { + throw new UncheckedExecutionException(cause); + } + throw newWithCause(exceptionClass, cause); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static V getUnchecked(Future future) + { + Preconditions.checkNotNull(future); + try { + return Uninterruptibles.getUninterruptibly(future); + } catch (ExecutionException e) { + wrapAndThrowUnchecked(e.getCause()); + throw new AssertionError(); + } + } + + private static void wrapAndThrowUnchecked(Throwable cause) { + if ((cause instanceof Error)) { + throw new ExecutionError((Error)cause); + } + + + + + + throw new UncheckedExecutionException(cause); + } + + + + + + + + + + + + + + + + + + + + + private static X newWithCause(Class exceptionClass, Throwable cause) + { + List> constructors = Arrays.asList(exceptionClass.getConstructors()); + + for (Constructor constructor : preferringStrings(constructors)) { + X instance = (Exception)newFromConstructor(constructor, cause); + if (instance != null) { + if (instance.getCause() == null) { + instance.initCause(cause); + } + return instance; + } + } + throw new IllegalArgumentException("No appropriate constructor for exception of type " + exceptionClass + " in response to chained exception", cause); + } + + + + private static List> preferringStrings(List> constructors) + { + return WITH_STRING_PARAM_FIRST.sortedCopy(constructors); + } + + private static final Ordering> WITH_STRING_PARAM_FIRST = Ordering.natural().onResultOf(new Function() + { + public Boolean apply(Constructor input) { + return Boolean.valueOf(Arrays.asList(input.getParameterTypes()).contains(String.class)); + } + }).reverse(); + + + + + + @Nullable + private static X newFromConstructor(Constructor constructor, Throwable cause) + { + Class[] paramTypes = constructor.getParameterTypes(); + Object[] params = new Object[paramTypes.length]; + for (int i = 0; i < paramTypes.length; i++) { + Class paramType = paramTypes[i]; + if (paramType.equals(String.class)) { + params[i] = cause.toString(); + } else if (paramType.equals(Throwable.class)) { + params[i] = cause; + } else { + return null; + } + } + try { + return constructor.newInstance(params); + } catch (IllegalArgumentException e) { + return null; + } catch (InstantiationException e) { + return null; + } catch (IllegalAccessException e) { + return null; + } catch (InvocationTargetException e) {} + return null; + } + + private static abstract interface FutureCombiner + { + public abstract C combine(List> paramList); + } + + private static class CombinedFuture extends AbstractFuture { + private static final Logger logger = Logger.getLogger(CombinedFuture.class.getName()); + + ImmutableCollection> futures; + + final boolean allMustSucceed; + final AtomicInteger remaining; + Futures.FutureCombiner combiner; + List> values; + final Object seenExceptionsLock = new Object(); + + Set seenExceptions; + + + CombinedFuture(ImmutableCollection> futures, boolean allMustSucceed, Executor listenerExecutor, Futures.FutureCombiner combiner) + { + this.futures = futures; + this.allMustSucceed = allMustSucceed; + remaining = new AtomicInteger(futures.size()); + this.combiner = combiner; + values = Lists.newArrayListWithCapacity(futures.size()); + init(listenerExecutor); + } + + + + + protected void init(Executor listenerExecutor) + { + addListener(new Runnable() + { + public void run() + { + if (isCancelled()) { + for (ListenableFuture future : futures) { + future.cancel(wasInterrupted()); + } + } + + + futures = null; + + + + values = null; + + + combiner = null; } }, MoreExecutors.sameThreadExecutor()); + + + + + + + if (futures.isEmpty()) { + set(combiner.combine(ImmutableList.of())); + return; + } + + + for (int i = 0; i < futures.size(); i++) { + values.add(null); + } + + + + + + + + + + int i = 0; + for (final ListenableFuture listenable : futures) { + final int index = i++; + listenable.addListener(new Runnable() + { + + public void run() { Futures.CombinedFuture.this.setOneValue(index, listenable); } }, listenerExecutor); + } + } + + + + + + + + + private void setExceptionAndMaybeLog(Throwable throwable) + { + boolean visibleFromOutputFuture = false; + boolean firstTimeSeeingThisException = true; + if (allMustSucceed) + { + + visibleFromOutputFuture = super.setException(throwable); + + synchronized (seenExceptionsLock) { + if (seenExceptions == null) { + seenExceptions = Sets.newHashSet(); + } + firstTimeSeeingThisException = seenExceptions.add(throwable); + } + } + + if (((throwable instanceof Error)) || ((allMustSucceed) && (!visibleFromOutputFuture) && (firstTimeSeeingThisException))) + { + logger.log(Level.SEVERE, "input future failed.", throwable); + } + } + + + + private void setOneValue(int index, Future future) + { + List> localValues = values; + + + + + + + + if ((isDone()) || (localValues == null)) + { + + + + Preconditions.checkState((allMustSucceed) || (isCancelled()), "Future was done before all dependencies completed"); + } + + try + { + Preconditions.checkState(future.isDone(), "Tried to set value from future which is not done"); + + V returnValue = Uninterruptibles.getUninterruptibly(future); + if (localValues != null) + localValues.set(index, Optional.fromNullable(returnValue)); + } catch (CancellationException e) { int newRemaining; + Futures.FutureCombiner localCombiner; + if (allMustSucceed) + { + + cancel(false); } + } catch (ExecutionException e) { int newRemaining; + Futures.FutureCombiner localCombiner; + setExceptionAndMaybeLog(e.getCause()); } catch (Throwable t) { int newRemaining; + Futures.FutureCombiner localCombiner; + setExceptionAndMaybeLog(t); } finally { int newRemaining; + Futures.FutureCombiner localCombiner; + int newRemaining = remaining.decrementAndGet(); + Preconditions.checkState(newRemaining >= 0, "Less than 0 remaining futures"); + if (newRemaining == 0) { + Futures.FutureCombiner localCombiner = combiner; + if ((localCombiner != null) && (localValues != null)) { + set(localCombiner.combine(localValues)); + } else { + Preconditions.checkState(isDone()); + } + } + } + } + } + + + + + private static ListenableFuture> listFuture(ImmutableList> futures, boolean allMustSucceed, Executor listenerExecutor) + { + new CombinedFuture(futures, allMustSucceed, listenerExecutor, new FutureCombiner() + { + + public List combine(List> values) + { + List result = Lists.newArrayList(); + for (Optional element : values) { + result.add(element != null ? element.orNull() : null); + } + return Collections.unmodifiableList(result); + } + }); + } + + + + private static class MappingCheckedFuture + extends AbstractCheckedFuture + { + final Function mapper; + + + + MappingCheckedFuture(ListenableFuture delegate, Function mapper) + { + super(); + + this.mapper = ((Function)Preconditions.checkNotNull(mapper)); + } + + protected X mapException(Exception e) + { + return (Exception)mapper.apply(e); + } + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/JdkFutureAdapters.java b/src/minecraft/com/google/common/util/concurrent/JdkFutureAdapters.java new file mode 100644 index 0000000..8e0a0dc --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/JdkFutureAdapters.java @@ -0,0 +1,183 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicBoolean; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class JdkFutureAdapters +{ + public static ListenableFuture listenInPoolThread(Future future) + { + if ((future instanceof ListenableFuture)) { + return (ListenableFuture)future; + } + return new ListenableFutureAdapter(future); + } + + + + + + + + + + + + + + + + + + + + + + + + + + public static ListenableFuture listenInPoolThread(Future future, Executor executor) + { + Preconditions.checkNotNull(executor); + if ((future instanceof ListenableFuture)) { + return (ListenableFuture)future; + } + return new ListenableFutureAdapter(future, executor); + } + + + + + + private JdkFutureAdapters() {} + + + + + private static class ListenableFutureAdapter + extends ForwardingFuture + implements ListenableFuture + { + private static final ThreadFactory threadFactory = new ThreadFactoryBuilder().setDaemon(true).setNameFormat("ListenableFutureAdapter-thread-%d").build(); + + + + + private static final Executor defaultAdapterExecutor = Executors.newCachedThreadPool(threadFactory); + + + private final Executor adapterExecutor; + + + private final ExecutionList executionList = new ExecutionList(); + + + + private final AtomicBoolean hasListeners = new AtomicBoolean(false); + + private final Future delegate; + + ListenableFutureAdapter(Future delegate) + { + this(delegate, defaultAdapterExecutor); + } + + ListenableFutureAdapter(Future delegate, Executor adapterExecutor) { + this.delegate = ((Future)Preconditions.checkNotNull(delegate)); + this.adapterExecutor = ((Executor)Preconditions.checkNotNull(adapterExecutor)); + } + + protected Future delegate() + { + return delegate; + } + + public void addListener(Runnable listener, Executor exec) + { + executionList.add(listener, exec); + + + + if (hasListeners.compareAndSet(false, true)) { + if (delegate.isDone()) + { + + executionList.execute(); + return; + } + + adapterExecutor.execute(new Runnable() + { + + + public void run() + { + + try + { + + Uninterruptibles.getUninterruptibly(delegate); + } catch (Error e) { + throw e; + } + catch (Throwable e) {} + + + executionList.execute(); + } + }); + } + } + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/ListenableFuture.java b/src/minecraft/com/google/common/util/concurrent/ListenableFuture.java new file mode 100644 index 0000000..cbe7c90 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/ListenableFuture.java @@ -0,0 +1,10 @@ +package com.google.common.util.concurrent; + +import java.util.concurrent.Executor; +import java.util.concurrent.Future; + +public abstract interface ListenableFuture + extends Future +{ + public abstract void addListener(Runnable paramRunnable, Executor paramExecutor); +} diff --git a/src/minecraft/com/google/common/util/concurrent/ListenableFutureTask.java b/src/minecraft/com/google/common/util/concurrent/ListenableFutureTask.java new file mode 100644 index 0000000..8f4266d --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/ListenableFutureTask.java @@ -0,0 +1,93 @@ +package com.google.common.util.concurrent; + +import java.util.concurrent.Callable; +import java.util.concurrent.Executor; +import java.util.concurrent.FutureTask; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public class ListenableFutureTask + extends FutureTask + implements ListenableFuture +{ + private final ExecutionList executionList = new ExecutionList(); + + + + + + + + public static ListenableFutureTask create(Callable callable) + { + return new ListenableFutureTask(callable); + } + + + + + + + + + + + + + + public static ListenableFutureTask create(Runnable runnable, @Nullable V result) + { + return new ListenableFutureTask(runnable, result); + } + + ListenableFutureTask(Callable callable) { + super(callable); + } + + ListenableFutureTask(Runnable runnable, @Nullable V result) { + super(runnable, result); + } + + public void addListener(Runnable listener, Executor exec) + { + executionList.add(listener, exec); + } + + + + + protected void done() + { + executionList.execute(); + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/ListenableScheduledFuture.java b/src/minecraft/com/google/common/util/concurrent/ListenableScheduledFuture.java new file mode 100644 index 0000000..4205d5f --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/ListenableScheduledFuture.java @@ -0,0 +1,9 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import java.util.concurrent.ScheduledFuture; + +@Beta +public abstract interface ListenableScheduledFuture + extends ScheduledFuture, ListenableFuture +{} diff --git a/src/minecraft/com/google/common/util/concurrent/ListenerCallQueue.java b/src/minecraft/com/google/common/util/concurrent/ListenerCallQueue.java new file mode 100644 index 0000000..fd30cb2 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/ListenerCallQueue.java @@ -0,0 +1,137 @@ +package com.google.common.util.concurrent; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Queues; +import java.util.Queue; +import java.util.concurrent.Executor; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.concurrent.GuardedBy; + + + + + + + + + + + + + + + + + + + + + + + + + + + +final class ListenerCallQueue + implements Runnable +{ + private static final Logger logger = Logger.getLogger(ListenerCallQueue.class.getName()); + private final L listener; + private final Executor executor; + + static abstract class Callback { private final String methodCall; + + Callback(String methodCall) { this.methodCall = methodCall; } + + + abstract void call(L paramL); + + void enqueueOn(Iterable> queues) + { + for (ListenerCallQueue queue : queues) { + queue.add(this); + } + } + } + + + + @GuardedBy("this") + private final Queue> waitQueue = Queues.newArrayDeque(); + @GuardedBy("this") + private boolean isThreadScheduled; + + ListenerCallQueue(L listener, Executor executor) { this.listener = Preconditions.checkNotNull(listener); + this.executor = ((Executor)Preconditions.checkNotNull(executor)); + } + + synchronized void add(Callback callback) + { + waitQueue.add(callback); + } + + void execute() + { + boolean scheduleTaskRunner = false; + synchronized (this) { + if (!isThreadScheduled) { + isThreadScheduled = true; + scheduleTaskRunner = true; + } + } + if (scheduleTaskRunner) { + try { + executor.execute(this); + } + catch (RuntimeException e) { + synchronized (this) { + isThreadScheduled = false; + } + + logger.log(Level.SEVERE, "Exception while running callbacks for " + listener + " on " + executor, e); + + + throw e; + } + } + } + + public void run() { + boolean stillRunning = true; + try { + for (;;) { + Callback nextToRun; + synchronized (this) { + Preconditions.checkState(isThreadScheduled); + nextToRun = (Callback)waitQueue.poll(); + if (nextToRun == null) { + isThreadScheduled = false; + stillRunning = false; + break; + } + } + + try + { + nextToRun.call(listener); + } + catch (RuntimeException e) { + logger.log(Level.SEVERE, "Exception while executing callback: " + listener + "." + methodCall, e); + } + } + } + finally + { + if (stillRunning) + { + + + synchronized (this) { + isThreadScheduled = false; + } + } + } + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/ListeningExecutorService.java b/src/minecraft/com/google/common/util/concurrent/ListeningExecutorService.java new file mode 100644 index 0000000..1976fcd --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/ListeningExecutorService.java @@ -0,0 +1,24 @@ +package com.google.common.util.concurrent; + +import java.util.Collection; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + +public abstract interface ListeningExecutorService + extends ExecutorService +{ + public abstract ListenableFuture submit(Callable paramCallable); + + public abstract ListenableFuture submit(Runnable paramRunnable); + + public abstract ListenableFuture submit(Runnable paramRunnable, T paramT); + + public abstract List> invokeAll(Collection> paramCollection) + throws InterruptedException; + + public abstract List> invokeAll(Collection> paramCollection, long paramLong, TimeUnit paramTimeUnit) + throws InterruptedException; +} diff --git a/src/minecraft/com/google/common/util/concurrent/ListeningScheduledExecutorService.java b/src/minecraft/com/google/common/util/concurrent/ListeningScheduledExecutorService.java new file mode 100644 index 0000000..3dfef9d --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/ListeningScheduledExecutorService.java @@ -0,0 +1,19 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import java.util.concurrent.Callable; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +@Beta +public abstract interface ListeningScheduledExecutorService + extends ScheduledExecutorService, ListeningExecutorService +{ + public abstract ListenableScheduledFuture schedule(Runnable paramRunnable, long paramLong, TimeUnit paramTimeUnit); + + public abstract ListenableScheduledFuture schedule(Callable paramCallable, long paramLong, TimeUnit paramTimeUnit); + + public abstract ListenableScheduledFuture scheduleAtFixedRate(Runnable paramRunnable, long paramLong1, long paramLong2, TimeUnit paramTimeUnit); + + public abstract ListenableScheduledFuture scheduleWithFixedDelay(Runnable paramRunnable, long paramLong1, long paramLong2, TimeUnit paramTimeUnit); +} diff --git a/src/minecraft/com/google/common/util/concurrent/Monitor.java b/src/minecraft/com/google/common/util/concurrent/Monitor.java new file mode 100644 index 0000000..a1e28e7 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/Monitor.java @@ -0,0 +1,1159 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.base.Throwables; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; +import javax.annotation.concurrent.GuardedBy; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class Monitor +{ + private final boolean fair; + private final ReentrantLock lock; + + @Beta + public static abstract class Guard + { + final Monitor monitor; + final Condition condition; + @GuardedBy("monitor.lock") + int waiterCount = 0; + + @GuardedBy("monitor.lock") + Guard next; + + + protected Guard(Monitor monitor) + { + this.monitor = ((Monitor)Preconditions.checkNotNull(monitor, "monitor")); + condition = lock.newCondition(); + } + + + + + + + + + + + + public abstract boolean isSatisfied(); + } + + + + + + + + + + + @GuardedBy("lock") + private Guard activeGuards = null; + + + + + + public Monitor() + { + this(false); + } + + + + + + + public Monitor(boolean fair) + { + this.fair = fair; + lock = new ReentrantLock(fair); + } + + + + public void enter() + { + lock.lock(); + } + + + public void enterInterruptibly() + throws InterruptedException + { + lock.lockInterruptibly(); + } + + + + + + public boolean enter(long time, TimeUnit unit) + { + long timeoutNanos = unit.toNanos(time); + ReentrantLock lock = this.lock; + if ((!fair) && (lock.tryLock())) { + return true; + } + long deadline = System.nanoTime() + timeoutNanos; + boolean interrupted = Thread.interrupted(); + + try + { + return lock.tryLock(timeoutNanos, TimeUnit.NANOSECONDS); + } catch (InterruptedException interrupt) { + for (;;) { interrupted = true; + timeoutNanos = deadline - System.nanoTime(); + } + } + finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + + + + + public boolean enterInterruptibly(long time, TimeUnit unit) + throws InterruptedException + { + return lock.tryLock(time, unit); + } + + + + + + + + public boolean tryEnter() + { + return lock.tryLock(); + } + + + public void enterWhen(Guard guard) + throws InterruptedException + { + if (monitor != this) { + throw new IllegalMonitorStateException(); + } + ReentrantLock lock = this.lock; + boolean signalBeforeWaiting = lock.isHeldByCurrentThread(); + lock.lockInterruptibly(); + + boolean satisfied = false; + try { + if (!guard.isSatisfied()) { + await(guard, signalBeforeWaiting); + } + satisfied = true; + } finally { + if (!satisfied) { + leave(); + } + } + } + + + + public void enterWhenUninterruptibly(Guard guard) + { + if (monitor != this) { + throw new IllegalMonitorStateException(); + } + ReentrantLock lock = this.lock; + boolean signalBeforeWaiting = lock.isHeldByCurrentThread(); + lock.lock(); + + boolean satisfied = false; + try { + if (!guard.isSatisfied()) { + awaitUninterruptibly(guard, signalBeforeWaiting); + } + satisfied = true; + } finally { + if (!satisfied) { + leave(); + } + } + } + + + + + + + public boolean enterWhen(Guard guard, long time, TimeUnit unit) + throws InterruptedException + { + long timeoutNanos = unit.toNanos(time); + if (monitor != this) { + throw new IllegalMonitorStateException(); + } + ReentrantLock lock = this.lock; + boolean reentrant = lock.isHeldByCurrentThread(); + if ((fair) || (!lock.tryLock())) { + long deadline = System.nanoTime() + timeoutNanos; + if (!lock.tryLock(time, unit)) { + return false; + } + timeoutNanos = deadline - System.nanoTime(); + } + + boolean satisfied = false; + boolean threw = true; + try { + satisfied = (guard.isSatisfied()) || (awaitNanos(guard, timeoutNanos, reentrant)); + threw = false; + return satisfied; + } finally { + if (!satisfied) { + try + { + if ((threw) && (!reentrant)) { + signalNextWaiter(); + } + } finally { + lock.unlock(); + } + } + } + } + + /* Error */ + public boolean enterWhenUninterruptibly(Guard guard, long time, TimeUnit unit) + { + // Byte code: + // 0: aload 4 + // 2: lload_2 + // 3: invokevirtual 10 java/util/concurrent/TimeUnit:toNanos (J)J + // 6: lstore 5 + // 8: aload_1 + // 9: getfield 19 com/google/common/util/concurrent/Monitor$Guard:monitor Lcom/google/common/util/concurrent/Monitor; + // 12: aload_0 + // 13: if_acmpeq +11 -> 24 + // 16: new 20 java/lang/IllegalMonitorStateException + // 19: dup + // 20: invokespecial 21 java/lang/IllegalMonitorStateException: ()V + // 23: athrow + // 24: aload_0 + // 25: getfield 1 com/google/common/util/concurrent/Monitor:lock Ljava/util/concurrent/locks/ReentrantLock; + // 28: astore 7 + // 30: invokestatic 12 java/lang/System:nanoTime ()J + // 33: lload 5 + // 35: ladd + // 36: lstore 8 + // 38: aload 7 + // 40: invokevirtual 22 java/util/concurrent/locks/ReentrantLock:isHeldByCurrentThread ()Z + // 43: istore 10 + // 45: invokestatic 13 java/lang/Thread:interrupted ()Z + // 48: istore 11 + // 50: aload_0 + // 51: getfield 5 com/google/common/util/concurrent/Monitor:fair Z + // 54: ifne +11 -> 65 + // 57: aload 7 + // 59: invokevirtual 11 java/util/concurrent/locks/ReentrantLock:tryLock ()Z + // 62: ifne +61 -> 123 + // 65: iconst_0 + // 66: istore 12 + // 68: aload 7 + // 70: lload 5 + // 72: getstatic 14 java/util/concurrent/TimeUnit:NANOSECONDS Ljava/util/concurrent/TimeUnit; + // 75: invokevirtual 15 java/util/concurrent/locks/ReentrantLock:tryLock (JLjava/util/concurrent/TimeUnit;)Z + // 78: istore 12 + // 80: iload 12 + // 82: ifne +20 -> 102 + // 85: iconst_0 + // 86: istore 13 + // 88: iload 11 + // 90: ifeq +9 -> 99 + // 93: invokestatic 16 java/lang/Thread:currentThread ()Ljava/lang/Thread; + // 96: invokevirtual 17 java/lang/Thread:interrupt ()V + // 99: iload 13 + // 101: ireturn + // 102: goto +8 -> 110 + // 105: astore 13 + // 107: iconst_1 + // 108: istore 11 + // 110: lload 8 + // 112: invokestatic 12 java/lang/System:nanoTime ()J + // 115: lsub + // 116: lstore 5 + // 118: iload 12 + // 120: ifeq -52 -> 68 + // 123: iconst_0 + // 124: istore 12 + // 126: aload_1 + // 127: invokevirtual 23 com/google/common/util/concurrent/Monitor$Guard:isSatisfied ()Z + // 130: ifne +15 -> 145 + // 133: aload_0 + // 134: aload_1 + // 135: lload 5 + // 137: iload 10 + // 139: invokespecial 27 com/google/common/util/concurrent/Monitor:awaitNanos (Lcom/google/common/util/concurrent/Monitor$Guard;JZ)Z + // 142: ifeq +7 -> 149 + // 145: iconst_1 + // 146: goto +4 -> 150 + // 149: iconst_0 + // 150: dup + // 151: istore 12 + // 153: istore 13 + // 155: iload 12 + // 157: ifne +8 -> 165 + // 160: aload 7 + // 162: invokevirtual 29 java/util/concurrent/locks/ReentrantLock:unlock ()V + // 165: iload 11 + // 167: ifeq +9 -> 176 + // 170: invokestatic 16 java/lang/Thread:currentThread ()Ljava/lang/Thread; + // 173: invokevirtual 17 java/lang/Thread:interrupt ()V + // 176: iload 13 + // 178: ireturn + // 179: astore 13 + // 181: iconst_1 + // 182: istore 11 + // 184: iconst_0 + // 185: istore 10 + // 187: lload 8 + // 189: invokestatic 12 java/lang/System:nanoTime ()J + // 192: lsub + // 193: lstore 5 + // 195: goto -69 -> 126 + // 198: astore 14 + // 200: iload 12 + // 202: ifne +8 -> 210 + // 205: aload 7 + // 207: invokevirtual 29 java/util/concurrent/locks/ReentrantLock:unlock ()V + // 210: aload 14 + // 212: athrow + // 213: astore 15 + // 215: iload 11 + // 217: ifeq +9 -> 226 + // 220: invokestatic 16 java/lang/Thread:currentThread ()Ljava/lang/Thread; + // 223: invokevirtual 17 java/lang/Thread:interrupt ()V + // 226: aload 15 + // 228: athrow + // Line number table: + // Java source line #513 -> byte code offset #0 + // Java source line #514 -> byte code offset #8 + // Java source line #515 -> byte code offset #16 + // Java source line #517 -> byte code offset #24 + // Java source line #518 -> byte code offset #30 + // Java source line #519 -> byte code offset #38 + // Java source line #520 -> byte code offset #45 + // Java source line #522 -> byte code offset #50 + // Java source line #523 -> byte code offset #65 + // Java source line #526 -> byte code offset #68 + // Java source line #527 -> byte code offset #80 + // Java source line #528 -> byte code offset #85 + // Java source line #555 -> byte code offset #88 + // Java source line #556 -> byte code offset #93 + // Java source line #532 -> byte code offset #102 + // Java source line #530 -> byte code offset #105 + // Java source line #531 -> byte code offset #107 + // Java source line #533 -> byte code offset #110 + // Java source line #534 -> byte code offset #118 + // Java source line #537 -> byte code offset #123 + // Java source line #541 -> byte code offset #126 + // Java source line #550 -> byte code offset #155 + // Java source line #551 -> byte code offset #160 + // Java source line #555 -> byte code offset #165 + // Java source line #556 -> byte code offset #170 + // Java source line #543 -> byte code offset #179 + // Java source line #544 -> byte code offset #181 + // Java source line #545 -> byte code offset #184 + // Java source line #546 -> byte code offset #187 + // Java source line #547 -> byte code offset #195 + // Java source line #550 -> byte code offset #198 + // Java source line #551 -> byte code offset #205 + // Java source line #555 -> byte code offset #213 + // Java source line #556 -> byte code offset #220 + // Local variable table: + // start length slot name signature + // 0 229 0 this Monitor + // 0 229 1 guard Guard + // 0 229 2 time long + // 0 229 4 unit TimeUnit + // 6 188 5 timeoutNanos long + // 28 178 7 lock ReentrantLock + // 36 152 8 deadline long + // 43 143 10 signalBeforeWaiting boolean + // 48 168 11 interrupted boolean + // 66 53 12 locked boolean + // 124 77 12 satisfied boolean + // 86 14 13 bool1 boolean + // 105 72 13 interrupt InterruptedException + // 153 24 13 bool2 boolean + // 179 3 13 interrupt InterruptedException + // 198 13 14 localObject1 Object + // 213 14 15 localObject2 Object + // Exception table: + // from to target type + // 68 88 105 java/lang/InterruptedException + // 126 155 179 java/lang/InterruptedException + // 126 155 198 finally + // 179 200 198 finally + // 50 88 213 finally + // 102 165 213 finally + // 179 215 213 finally + } + + public boolean enterIf(Guard guard) + { + if (monitor != this) { + throw new IllegalMonitorStateException(); + } + ReentrantLock lock = this.lock; + lock.lock(); + + boolean satisfied = false; + try { + return satisfied = guard.isSatisfied(); + } finally { + if (!satisfied) { + lock.unlock(); + } + } + } + + + + + + public boolean enterIfInterruptibly(Guard guard) + throws InterruptedException + { + if (monitor != this) { + throw new IllegalMonitorStateException(); + } + ReentrantLock lock = this.lock; + lock.lockInterruptibly(); + + boolean satisfied = false; + try { + return satisfied = guard.isSatisfied(); + } finally { + if (!satisfied) { + lock.unlock(); + } + } + } + + + + + + + public boolean enterIf(Guard guard, long time, TimeUnit unit) + { + if (monitor != this) { + throw new IllegalMonitorStateException(); + } + if (!enter(time, unit)) { + return false; + } + + boolean satisfied = false; + try { + return satisfied = guard.isSatisfied(); + } finally { + if (!satisfied) { + lock.unlock(); + } + } + } + + + + + + + public boolean enterIfInterruptibly(Guard guard, long time, TimeUnit unit) + throws InterruptedException + { + if (monitor != this) { + throw new IllegalMonitorStateException(); + } + ReentrantLock lock = this.lock; + if (!lock.tryLock(time, unit)) { + return false; + } + + boolean satisfied = false; + try { + return satisfied = guard.isSatisfied(); + } finally { + if (!satisfied) { + lock.unlock(); + } + } + } + + + + + + + + + public boolean tryEnterIf(Guard guard) + { + if (monitor != this) { + throw new IllegalMonitorStateException(); + } + ReentrantLock lock = this.lock; + if (!lock.tryLock()) { + return false; + } + + boolean satisfied = false; + try { + return satisfied = guard.isSatisfied(); + } finally { + if (!satisfied) { + lock.unlock(); + } + } + } + + + + public void waitFor(Guard guard) + throws InterruptedException + { + if (!(monitor == this & lock.isHeldByCurrentThread())) { + throw new IllegalMonitorStateException(); + } + if (!guard.isSatisfied()) { + await(guard, true); + } + } + + + + + public void waitForUninterruptibly(Guard guard) + { + if (!(monitor == this & lock.isHeldByCurrentThread())) { + throw new IllegalMonitorStateException(); + } + if (!guard.isSatisfied()) { + awaitUninterruptibly(guard, true); + } + } + + + + + + public boolean waitFor(Guard guard, long time, TimeUnit unit) + throws InterruptedException + { + long timeoutNanos = unit.toNanos(time); + if (!(monitor == this & lock.isHeldByCurrentThread())) { + throw new IllegalMonitorStateException(); + } + return (guard.isSatisfied()) || (awaitNanos(guard, timeoutNanos, true)); + } + + + + + + + public boolean waitForUninterruptibly(Guard guard, long time, TimeUnit unit) + { + long timeoutNanos = unit.toNanos(time); + if (!(monitor == this & lock.isHeldByCurrentThread())) { + throw new IllegalMonitorStateException(); + } + if (guard.isSatisfied()) { + return true; + } + boolean signalBeforeWaiting = true; + long deadline = System.nanoTime() + timeoutNanos; + boolean interrupted = Thread.interrupted(); + + try + { + return awaitNanos(guard, timeoutNanos, signalBeforeWaiting); + } catch (InterruptedException interrupt) { + for (;;) { interrupted = true; + if (guard.isSatisfied()) { + return true; + } + signalBeforeWaiting = false; + timeoutNanos = deadline - System.nanoTime(); + } + } + finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + + + + public void leave() + { + ReentrantLock lock = this.lock; + try + { + if (lock.getHoldCount() == 1) { + signalNextWaiter(); + } + } finally { + lock.unlock(); + } + } + + + + public boolean isFair() + { + return fair; + } + + + + + public boolean isOccupied() + { + return lock.isLocked(); + } + + + + + public boolean isOccupiedByCurrentThread() + { + return lock.isHeldByCurrentThread(); + } + + + + + public int getOccupiedDepth() + { + return lock.getHoldCount(); + } + + + + + + + public int getQueueLength() + { + return lock.getQueueLength(); + } + + + + + + + public boolean hasQueuedThreads() + { + return lock.hasQueuedThreads(); + } + + + + + + + public boolean hasQueuedThread(Thread thread) + { + return lock.hasQueuedThread(thread); + } + + + + + + + public boolean hasWaiters(Guard guard) + { + return getWaitQueueLength(guard) > 0; + } + + + + + + + public int getWaitQueueLength(Guard guard) + { + if (monitor != this) { + throw new IllegalMonitorStateException(); + } + lock.lock(); + try { + return waiterCount; + } finally { + lock.unlock(); + } + } + + + + + + + + + + + + + + + + + + + + + + + + + @GuardedBy("lock") + private void signalNextWaiter() + { + for (Guard guard = activeGuards; guard != null; guard = next) { + if (isSatisfied(guard)) { + condition.signal(); + break; + } + } + } + + + + + + + + + + + + + + + + + + + + + + @GuardedBy("lock") + private boolean isSatisfied(Guard guard) + { + try + { + return guard.isSatisfied(); + } catch (Throwable throwable) { + signalAllWaiters(); + throw Throwables.propagate(throwable); + } + } + + + + @GuardedBy("lock") + private void signalAllWaiters() + { + for (Guard guard = activeGuards; guard != null; guard = next) { + condition.signalAll(); + } + } + + + + @GuardedBy("lock") + private void beginWaitingFor(Guard guard) + { + int waiters = waiterCount++; + if (waiters == 0) + { + next = activeGuards; + activeGuards = guard; + } + } + + + + @GuardedBy("lock") + private void endWaitingFor(Guard guard) + { + int waiters = --waiterCount; + if (waiters == 0) + { + Guard p = activeGuards; for (Guard pred = null;; p = next) { + if (p == guard) { + if (pred == null) { + activeGuards = next; + } else { + next = next; + } + next = null; + break; + } + pred = p; + } + } + } + + + + + + + + + + + + + + + + @GuardedBy("lock") + private void await(Guard guard, boolean signalBeforeWaiting) + throws InterruptedException + { + if (signalBeforeWaiting) { + signalNextWaiter(); + } + beginWaitingFor(guard); + try { + do { + condition.await(); + } while (!guard.isSatisfied()); + } finally { + endWaitingFor(guard); + } + } + + @GuardedBy("lock") + private void awaitUninterruptibly(Guard guard, boolean signalBeforeWaiting) { + if (signalBeforeWaiting) { + signalNextWaiter(); + } + beginWaitingFor(guard); + try { + do { + condition.awaitUninterruptibly(); + } while (!guard.isSatisfied()); + } finally { + endWaitingFor(guard); + } + } + + @GuardedBy("lock") + private boolean awaitNanos(Guard guard, long nanos, boolean signalBeforeWaiting) throws InterruptedException + { + if (signalBeforeWaiting) { + signalNextWaiter(); + } + beginWaitingFor(guard); + try { + boolean bool; + do { if (nanos < 0L) { + return false; + } + nanos = condition.awaitNanos(nanos); + } while (!guard.isSatisfied()); + return true; + } finally { + endWaitingFor(guard); + } + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/MoreExecutors.java b/src/minecraft/com/google/common/util/concurrent/MoreExecutors.java new file mode 100644 index 0000000..5b3ac55 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/MoreExecutors.java @@ -0,0 +1,940 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import com.google.common.base.Throwables; +import com.google.common.collect.Lists; +import com.google.common.collect.Queues; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Callable; +import java.util.concurrent.Delayed; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public final class MoreExecutors +{ + private MoreExecutors() {} + + @Beta + public static ExecutorService getExitingExecutorService(ThreadPoolExecutor executor, long terminationTimeout, TimeUnit timeUnit) + { + return new Application().getExitingExecutorService(executor, terminationTimeout, timeUnit); + } + + + + + + + + + + + + + + + + + + + @Beta + public static ScheduledExecutorService getExitingScheduledExecutorService(ScheduledThreadPoolExecutor executor, long terminationTimeout, TimeUnit timeUnit) + { + return new Application().getExitingScheduledExecutorService(executor, terminationTimeout, timeUnit); + } + + + + + + + + + + + + + + @Beta + public static void addDelayedShutdownHook(ExecutorService service, long terminationTimeout, TimeUnit timeUnit) + { + new Application().addDelayedShutdownHook(service, terminationTimeout, timeUnit); + } + + + + + + + + + + + + + + + + + @Beta + public static ExecutorService getExitingExecutorService(ThreadPoolExecutor executor) + { + return new Application().getExitingExecutorService(executor); + } + + + + + + + + + + + + + + + + + @Beta + public static ScheduledExecutorService getExitingScheduledExecutorService(ScheduledThreadPoolExecutor executor) + { + return new Application().getExitingScheduledExecutorService(executor); + } + + @VisibleForTesting + static class Application { + Application() {} + + final ExecutorService getExitingExecutorService(ThreadPoolExecutor executor, long terminationTimeout, TimeUnit timeUnit) { + MoreExecutors.useDaemonThreadFactory(executor); + ExecutorService service = Executors.unconfigurableExecutorService(executor); + addDelayedShutdownHook(service, terminationTimeout, timeUnit); + return service; + } + + final ScheduledExecutorService getExitingScheduledExecutorService(ScheduledThreadPoolExecutor executor, long terminationTimeout, TimeUnit timeUnit) + { + MoreExecutors.useDaemonThreadFactory(executor); + ScheduledExecutorService service = Executors.unconfigurableScheduledExecutorService(executor); + addDelayedShutdownHook(service, terminationTimeout, timeUnit); + return service; + } + + final void addDelayedShutdownHook(final ExecutorService service, final long terminationTimeout, TimeUnit timeUnit) + { + Preconditions.checkNotNull(service); + Preconditions.checkNotNull(timeUnit); + addShutdownHook(MoreExecutors.newThread("DelayedShutdownHook-for-" + service, new Runnable() + { + + public void run() + { + + try + { + + service.shutdown(); + service.awaitTermination(terminationTimeout, val$timeUnit); + } + catch (InterruptedException ignored) {} + } + })); + } + + final ExecutorService getExitingExecutorService(ThreadPoolExecutor executor) + { + return getExitingExecutorService(executor, 120L, TimeUnit.SECONDS); + } + + final ScheduledExecutorService getExitingScheduledExecutorService(ScheduledThreadPoolExecutor executor) + { + return getExitingScheduledExecutorService(executor, 120L, TimeUnit.SECONDS); + } + + @VisibleForTesting + void addShutdownHook(Thread hook) { Runtime.getRuntime().addShutdownHook(hook); } + } + + private static void useDaemonThreadFactory(ThreadPoolExecutor executor) + { + executor.setThreadFactory(new ThreadFactoryBuilder().setDaemon(true).setThreadFactory(executor.getThreadFactory()).build()); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static ListeningExecutorService sameThreadExecutor() + { + return new SameThreadExecutorService(null); + } + + + + + + private static class SameThreadExecutorService + extends AbstractListeningExecutorService + { + private final Lock lock = new ReentrantLock(); + + + private final Condition termination = lock.newCondition(); + + + + + + + + + private int runningTasks = 0; + private boolean shutdown = false; + + private SameThreadExecutorService() {} + + public void execute(Runnable command) { startTask(); + try { + command.run(); + } finally { + endTask(); + } + } + + public boolean isShutdown() + { + lock.lock(); + try { + return shutdown; + } finally { + lock.unlock(); + } + } + + public void shutdown() + { + lock.lock(); + try { + shutdown = true; + } finally { + lock.unlock(); + } + } + + + public List shutdownNow() + { + shutdown(); + return Collections.emptyList(); + } + + public boolean isTerminated() + { + lock.lock(); + try { + return (shutdown) && (runningTasks == 0); + } finally { + lock.unlock(); + } + } + + /* Error */ + public boolean awaitTermination(long timeout, TimeUnit unit) + throws InterruptedException + { + // Byte code: + // 0: aload_3 + // 1: lload_1 + // 2: invokevirtual 17 java/util/concurrent/TimeUnit:toNanos (J)J + // 5: lstore 4 + // 7: aload_0 + // 8: getfield 5 com/google/common/util/concurrent/MoreExecutors$SameThreadExecutorService:lock Ljava/util/concurrent/locks/Lock; + // 11: invokeinterface 13 1 0 + // 16: aload_0 + // 17: invokevirtual 18 com/google/common/util/concurrent/MoreExecutors$SameThreadExecutorService:isTerminated ()Z + // 20: ifeq +18 -> 38 + // 23: iconst_1 + // 24: istore 6 + // 26: aload_0 + // 27: getfield 5 com/google/common/util/concurrent/MoreExecutors$SameThreadExecutorService:lock Ljava/util/concurrent/locks/Lock; + // 30: invokeinterface 14 1 0 + // 35: iload 6 + // 37: ireturn + // 38: lload 4 + // 40: lconst_0 + // 41: lcmp + // 42: ifgt +18 -> 60 + // 45: iconst_0 + // 46: istore 6 + // 48: aload_0 + // 49: getfield 5 com/google/common/util/concurrent/MoreExecutors$SameThreadExecutorService:lock Ljava/util/concurrent/locks/Lock; + // 52: invokeinterface 14 1 0 + // 57: iload 6 + // 59: ireturn + // 60: aload_0 + // 61: getfield 7 com/google/common/util/concurrent/MoreExecutors$SameThreadExecutorService:termination Ljava/util/concurrent/locks/Condition; + // 64: lload 4 + // 66: invokeinterface 19 3 0 + // 71: lstore 4 + // 73: goto -57 -> 16 + // 76: astore 7 + // 78: aload_0 + // 79: getfield 5 com/google/common/util/concurrent/MoreExecutors$SameThreadExecutorService:lock Ljava/util/concurrent/locks/Lock; + // 82: invokeinterface 14 1 0 + // 87: aload 7 + // 89: athrow + // Line number table: + // Java source line #343 -> byte code offset #0 + // Java source line #344 -> byte code offset #7 + // Java source line #347 -> byte code offset #16 + // Java source line #348 -> byte code offset #23 + // Java source line #356 -> byte code offset #26 + // Java source line #349 -> byte code offset #38 + // Java source line #350 -> byte code offset #45 + // Java source line #356 -> byte code offset #48 + // Java source line #352 -> byte code offset #60 + // Java source line #356 -> byte code offset #76 + // Local variable table: + // start length slot name signature + // 0 90 0 this SameThreadExecutorService + // 0 90 1 timeout long + // 0 90 3 unit TimeUnit + // 5 67 4 nanos long + // 24 34 6 bool boolean + // 76 12 7 localObject Object + // Exception table: + // from to target type + // 16 26 76 finally + // 38 48 76 finally + // 60 78 76 finally + } + + private void startTask() + { + lock.lock(); + try { + if (isShutdown()) { + throw new RejectedExecutionException("Executor already shutdown"); + } + runningTasks += 1; + } finally { + lock.unlock(); + } + } + + + + private void endTask() + { + lock.lock(); + try { + runningTasks -= 1; + if (isTerminated()) { + termination.signalAll(); + } + } finally { + lock.unlock(); + } + } + } + + + + + + + + + + + + + + + + + + + + public static ListeningExecutorService listeningDecorator(ExecutorService delegate) + { + return (delegate instanceof ScheduledExecutorService) ? new ScheduledListeningDecorator((ScheduledExecutorService)delegate) : (delegate instanceof ListeningExecutorService) ? (ListeningExecutorService)delegate : new ListeningDecorator(delegate); + } + + + + + + + + + + + + + + + + + + + + + + + + + public static ListeningScheduledExecutorService listeningDecorator(ScheduledExecutorService delegate) + { + return (delegate instanceof ListeningScheduledExecutorService) ? (ListeningScheduledExecutorService)delegate : new ScheduledListeningDecorator(delegate); + } + + private static class ListeningDecorator + extends AbstractListeningExecutorService + { + private final ExecutorService delegate; + + ListeningDecorator(ExecutorService delegate) + { + this.delegate = ((ExecutorService)Preconditions.checkNotNull(delegate)); + } + + public boolean awaitTermination(long timeout, TimeUnit unit) + throws InterruptedException + { + return delegate.awaitTermination(timeout, unit); + } + + public boolean isShutdown() + { + return delegate.isShutdown(); + } + + public boolean isTerminated() + { + return delegate.isTerminated(); + } + + public void shutdown() + { + delegate.shutdown(); + } + + public List shutdownNow() + { + return delegate.shutdownNow(); + } + + public void execute(Runnable command) + { + delegate.execute(command); + } + } + + private static class ScheduledListeningDecorator extends MoreExecutors.ListeningDecorator implements ListeningScheduledExecutorService + { + final ScheduledExecutorService delegate; + + ScheduledListeningDecorator(ScheduledExecutorService delegate) + { + super(); + this.delegate = ((ScheduledExecutorService)Preconditions.checkNotNull(delegate)); + } + + + public ListenableScheduledFuture schedule(Runnable command, long delay, TimeUnit unit) + { + ListenableFutureTask task = ListenableFutureTask.create(command, null); + + ScheduledFuture scheduled = delegate.schedule(task, delay, unit); + return new ListenableScheduledTask(task, scheduled); + } + + + public ListenableScheduledFuture schedule(Callable callable, long delay, TimeUnit unit) + { + ListenableFutureTask task = ListenableFutureTask.create(callable); + ScheduledFuture scheduled = delegate.schedule(task, delay, unit); + return new ListenableScheduledTask(task, scheduled); + } + + + public ListenableScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) + { + NeverSuccessfulListenableFutureTask task = new NeverSuccessfulListenableFutureTask(command); + + ScheduledFuture scheduled = delegate.scheduleAtFixedRate(task, initialDelay, period, unit); + + return new ListenableScheduledTask(task, scheduled); + } + + + public ListenableScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) + { + NeverSuccessfulListenableFutureTask task = new NeverSuccessfulListenableFutureTask(command); + + ScheduledFuture scheduled = delegate.scheduleWithFixedDelay(task, initialDelay, delay, unit); + + return new ListenableScheduledTask(task, scheduled); + } + + + private static final class ListenableScheduledTask + extends ForwardingListenableFuture.SimpleForwardingListenableFuture + implements ListenableScheduledFuture + { + private final ScheduledFuture scheduledDelegate; + + public ListenableScheduledTask(ListenableFuture listenableDelegate, ScheduledFuture scheduledDelegate) + { + super(); + this.scheduledDelegate = scheduledDelegate; + } + + public boolean cancel(boolean mayInterruptIfRunning) + { + boolean cancelled = super.cancel(mayInterruptIfRunning); + if (cancelled) + { + scheduledDelegate.cancel(mayInterruptIfRunning); + } + + + return cancelled; + } + + public long getDelay(TimeUnit unit) + { + return scheduledDelegate.getDelay(unit); + } + + public int compareTo(Delayed other) + { + return scheduledDelegate.compareTo(other); + } + } + + private static final class NeverSuccessfulListenableFutureTask extends AbstractFuture implements Runnable + { + private final Runnable delegate; + + public NeverSuccessfulListenableFutureTask(Runnable delegate) + { + this.delegate = ((Runnable)Preconditions.checkNotNull(delegate)); + } + + public void run() { + try { + delegate.run(); + } catch (Throwable t) { + setException(t); + throw Throwables.propagate(t); + } + } + } + } + + + + + + + + + + + + + + + + + static T invokeAnyImpl(ListeningExecutorService executorService, Collection> tasks, boolean timed, long nanos) + throws InterruptedException, ExecutionException, TimeoutException + { + Preconditions.checkNotNull(executorService); + int ntasks = tasks.size(); + Preconditions.checkArgument(ntasks > 0); + List> futures = Lists.newArrayListWithCapacity(ntasks); + BlockingQueue> futureQueue = Queues.newLinkedBlockingQueue(); + + + + + + + + + try + { + ExecutionException ee = null; + long lastTime = timed ? System.nanoTime() : 0L; + Iterator> it = tasks.iterator(); + + futures.add(submitAndAddQueueListener(executorService, (Callable)it.next(), futureQueue)); + ntasks--; + int active = 1; + for (;;) + { + Future f = (Future)futureQueue.poll(); + long now; if (f == null) + if (ntasks > 0) { + ntasks--; + futures.add(submitAndAddQueueListener(executorService, (Callable)it.next(), futureQueue)); + active++; + } else { if (active == 0) + break; + if (timed) { + f = (Future)futureQueue.poll(nanos, TimeUnit.NANOSECONDS); + if (f == null) { + throw new TimeoutException(); + } + now = System.nanoTime(); + nanos -= now - lastTime; + lastTime = now; + } else { + f = (Future)futureQueue.take(); + } + } + if (f != null) { + active--; + try { Iterator i$; + Future f; return f.get(); + } catch (ExecutionException eex) { + ee = eex; + } catch (RuntimeException rex) { + ee = new ExecutionException(rex); + } + } + } + + if (ee == null) { + ee = new ExecutionException(null); + } + throw ee; + } finally { + for (Future f : futures) { + f.cancel(true); + } + } + } + + + + + + private static ListenableFuture submitAndAddQueueListener(ListeningExecutorService executorService, Callable task, BlockingQueue> queue) + { + final ListenableFuture future = executorService.submit(task); + future.addListener(new Runnable() + { + public void run() { val$queue.add(future); } }, sameThreadExecutor()); + + + return future; + } + + + + + + + + + @Beta + public static ThreadFactory platformThreadFactory() + { + if (!isAppEngine()) { + return Executors.defaultThreadFactory(); + } + try { + return (ThreadFactory)Class.forName("com.google.appengine.api.ThreadManager").getMethod("currentRequestThreadFactory", new Class[0]).invoke(null, new Object[0]); + } + catch (IllegalAccessException e) + { + throw new RuntimeException("Couldn't invoke ThreadManager.currentRequestThreadFactory", e); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Couldn't invoke ThreadManager.currentRequestThreadFactory", e); + } catch (NoSuchMethodException e) { + throw new RuntimeException("Couldn't invoke ThreadManager.currentRequestThreadFactory", e); + } catch (InvocationTargetException e) { + throw Throwables.propagate(e.getCause()); + } + } + + private static boolean isAppEngine() { + if (System.getProperty("com.google.appengine.runtime.environment") == null) { + return false; + } + try + { + return Class.forName("com.google.apphosting.api.ApiProxy").getMethod("getCurrentEnvironment", new Class[0]).invoke(null, new Object[0]) != null; + + } + catch (ClassNotFoundException e) + { + return false; + } + catch (InvocationTargetException e) { + return false; + } + catch (IllegalAccessException e) { + return false; + } + catch (NoSuchMethodException e) {} + return false; + } + + + + + + static Thread newThread(String name, Runnable runnable) + { + Preconditions.checkNotNull(name); + Preconditions.checkNotNull(runnable); + Thread result = platformThreadFactory().newThread(runnable); + try { + result.setName(name); + } + catch (SecurityException e) {} + + return result; + } + + + + + + + + + + + + + + + + static Executor renamingDecorator(Executor executor, final Supplier nameSupplier) + { + Preconditions.checkNotNull(executor); + Preconditions.checkNotNull(nameSupplier); + if (isAppEngine()) + { + return executor; + } + new Executor() { + public void execute(Runnable command) { + val$executor.execute(Callables.threadRenaming(command, nameSupplier)); + } + }; + } + + + + + + + + + + + + + + static ExecutorService renamingDecorator(ExecutorService service, final Supplier nameSupplier) + { + Preconditions.checkNotNull(service); + Preconditions.checkNotNull(nameSupplier); + if (isAppEngine()) + { + return service; + } + new WrappingExecutorService(service) { + protected Callable wrapTask(Callable callable) { + return Callables.threadRenaming(callable, nameSupplier); + } + + protected Runnable wrapTask(Runnable command) { return Callables.threadRenaming(command, nameSupplier); } + }; + } + + + + + + + + + + + + + + + static ScheduledExecutorService renamingDecorator(ScheduledExecutorService service, final Supplier nameSupplier) + { + Preconditions.checkNotNull(service); + Preconditions.checkNotNull(nameSupplier); + if (isAppEngine()) + { + return service; + } + new WrappingScheduledExecutorService(service) { + protected Callable wrapTask(Callable callable) { + return Callables.threadRenaming(callable, nameSupplier); + } + + protected Runnable wrapTask(Runnable command) { return Callables.threadRenaming(command, nameSupplier); } + }; + } + + + + + + + + + + + + + + + + + + + + + + + + + + + @Beta + public static boolean shutdownAndAwaitTermination(ExecutorService service, long timeout, TimeUnit unit) + { + Preconditions.checkNotNull(unit); + + service.shutdown(); + try { + long halfTimeoutNanos = TimeUnit.NANOSECONDS.convert(timeout, unit) / 2L; + + if (!service.awaitTermination(halfTimeoutNanos, TimeUnit.NANOSECONDS)) + { + service.shutdownNow(); + + service.awaitTermination(halfTimeoutNanos, TimeUnit.NANOSECONDS); + } + } + catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + + service.shutdownNow(); + } + return service.isTerminated(); + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/RateLimiter.java b/src/minecraft/com/google/common/util/concurrent/RateLimiter.java new file mode 100644 index 0000000..887528c --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/RateLimiter.java @@ -0,0 +1,733 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.base.Ticker; +import java.util.concurrent.TimeUnit; +import javax.annotation.concurrent.ThreadSafe; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@ThreadSafe +@Beta +public abstract class RateLimiter +{ + private final SleepingTicker ticker; + private final long offsetNanos; + double storedPermits; + double maxPermits; + volatile double stableIntervalMicros; + + public static RateLimiter create(double permitsPerSecond) + { + return create(SleepingTicker.SYSTEM_TICKER, permitsPerSecond); + } + + @VisibleForTesting + static RateLimiter create(SleepingTicker ticker, double permitsPerSecond) { + RateLimiter rateLimiter = new Bursty(ticker, 1.0D); + rateLimiter.setRate(permitsPerSecond); + return rateLimiter; + } + + + + + + + + + + + + + + + + + + + + + + + public static RateLimiter create(double permitsPerSecond, long warmupPeriod, TimeUnit unit) + { + return create(SleepingTicker.SYSTEM_TICKER, permitsPerSecond, warmupPeriod, unit); + } + + @VisibleForTesting + static RateLimiter create(SleepingTicker ticker, double permitsPerSecond, long warmupPeriod, TimeUnit unit) + { + RateLimiter rateLimiter = new WarmingUp(ticker, warmupPeriod, unit); + rateLimiter.setRate(permitsPerSecond); + return rateLimiter; + } + + @VisibleForTesting + static RateLimiter createWithCapacity(SleepingTicker ticker, double permitsPerSecond, long maxBurstBuildup, TimeUnit unit) + { + double maxBurstSeconds = unit.toNanos(maxBurstBuildup) / 1.0E9D; + Bursty rateLimiter = new Bursty(ticker, maxBurstSeconds); + rateLimiter.setRate(permitsPerSecond); + return rateLimiter; + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + private final Object mutex = new Object(); + + + + + + private long nextFreeTicketMicros = 0L; + + private RateLimiter(SleepingTicker ticker) { + this.ticker = ticker; + offsetNanos = ticker.read(); + } + + + + + + + + + + + + + + + + + + + public final void setRate(double permitsPerSecond) + { + Preconditions.checkArgument((permitsPerSecond > 0.0D) && (!Double.isNaN(permitsPerSecond)), "rate must be positive"); + + synchronized (mutex) { + resync(readSafeMicros()); + double stableIntervalMicros = TimeUnit.SECONDS.toMicros(1L) / permitsPerSecond; + this.stableIntervalMicros = stableIntervalMicros; + doSetRate(permitsPerSecond, stableIntervalMicros); + } + } + + + + + abstract void doSetRate(double paramDouble1, double paramDouble2); + + + + + public final double getRate() + { + return TimeUnit.SECONDS.toMicros(1L) / stableIntervalMicros; + } + + + + + + + + + + public double acquire() + { + return acquire(1); + } + + + + + + + + + public double acquire(int permits) + { + long microsToWait = reserve(permits); + ticker.sleepMicrosUninterruptibly(microsToWait); + return 1.0D * microsToWait / TimeUnit.SECONDS.toMicros(1L); + } + + + + + + + + + long reserve() + { + return reserve(1); + } + + + + + + + long reserve(int permits) + { + checkPermits(permits); + synchronized (mutex) { + return reserveNextTicket(permits, readSafeMicros()); + } + } + + + + + + + + + + + + + public boolean tryAcquire(long timeout, TimeUnit unit) + { + return tryAcquire(1, timeout, unit); + } + + + + + + + + + + + public boolean tryAcquire(int permits) + { + return tryAcquire(permits, 0L, TimeUnit.MICROSECONDS); + } + + + + + + + + + + + public boolean tryAcquire() + { + return tryAcquire(1, 0L, TimeUnit.MICROSECONDS); + } + + + + + + + + + + + + public boolean tryAcquire(int permits, long timeout, TimeUnit unit) + { + long timeoutMicros = unit.toMicros(timeout); + checkPermits(permits); + long microsToWait; + synchronized (mutex) { + long nowMicros = readSafeMicros(); + if (nextFreeTicketMicros > nowMicros + timeoutMicros) { + return false; + } + microsToWait = reserveNextTicket(permits, nowMicros); + } + + ticker.sleepMicrosUninterruptibly(microsToWait); + return true; + } + + private static void checkPermits(int permits) { + Preconditions.checkArgument(permits > 0, "Requested permits must be positive"); + } + + + + + + private long reserveNextTicket(double requiredPermits, long nowMicros) + { + resync(nowMicros); + long microsToNextFreeTicket = Math.max(0L, nextFreeTicketMicros - nowMicros); + double storedPermitsToSpend = Math.min(requiredPermits, storedPermits); + double freshPermits = requiredPermits - storedPermitsToSpend; + + long waitMicros = storedPermitsToWaitTime(storedPermits, storedPermitsToSpend) + (freshPermits * stableIntervalMicros); + + + nextFreeTicketMicros += waitMicros; + storedPermits -= storedPermitsToSpend; + return microsToNextFreeTicket; + } + + + + + + abstract long storedPermitsToWaitTime(double paramDouble1, double paramDouble2); + + + + + + private void resync(long nowMicros) + { + if (nowMicros > nextFreeTicketMicros) { + storedPermits = Math.min(maxPermits, storedPermits + (nowMicros - nextFreeTicketMicros) / stableIntervalMicros); + + nextFreeTicketMicros = nowMicros; + } + } + + private long readSafeMicros() { + return TimeUnit.NANOSECONDS.toMicros(ticker.read() - offsetNanos); + } + + public String toString() + { + return String.format("RateLimiter[stableRate=%3.1fqps]", new Object[] { Double.valueOf(1000000.0D / stableIntervalMicros) }); + } + + + + + + + + + + + + + + + + + + + + + + private static class WarmingUp + extends RateLimiter + { + final long warmupPeriodMicros; + + + + + + + + + + + + + + + + + + + + private double slope; + + + + + + + + + + + + + + + + + + + + private double halfPermits; + + + + + + + + + + + + + + + + + + + + + WarmingUp(RateLimiter.SleepingTicker ticker, long warmupPeriod, TimeUnit timeUnit) + { + super(null); + warmupPeriodMicros = timeUnit.toMicros(warmupPeriod); + } + + void doSetRate(double permitsPerSecond, double stableIntervalMicros) + { + double oldMaxPermits = maxPermits; + maxPermits = (warmupPeriodMicros / stableIntervalMicros); + halfPermits = (maxPermits / 2.0D); + + double coldIntervalMicros = stableIntervalMicros * 3.0D; + slope = ((coldIntervalMicros - stableIntervalMicros) / halfPermits); + if (oldMaxPermits == Double.POSITIVE_INFINITY) + { + storedPermits = 0.0D; + } else { + storedPermits = (oldMaxPermits == 0.0D ? maxPermits : storedPermits * maxPermits / oldMaxPermits); + } + } + + + + long storedPermitsToWaitTime(double storedPermits, double permitsToTake) + { + double availablePermitsAboveHalf = storedPermits - halfPermits; + long micros = 0L; + + if (availablePermitsAboveHalf > 0.0D) { + double permitsAboveHalfToTake = Math.min(availablePermitsAboveHalf, permitsToTake); + micros = (permitsAboveHalfToTake * (permitsToTime(availablePermitsAboveHalf) + permitsToTime(availablePermitsAboveHalf - permitsAboveHalfToTake)) / 2.0D); + + permitsToTake -= permitsAboveHalfToTake; + } + + micros = (micros + stableIntervalMicros * permitsToTake); + return micros; + } + + private double permitsToTime(double permits) { + return stableIntervalMicros + permits * slope; + } + } + + + + private static class Bursty + extends RateLimiter + { + final double maxBurstSeconds; + + + + Bursty(RateLimiter.SleepingTicker ticker, double maxBurstSeconds) + { + super(null); + this.maxBurstSeconds = maxBurstSeconds; + } + + void doSetRate(double permitsPerSecond, double stableIntervalMicros) + { + double oldMaxPermits = maxPermits; + maxPermits = (maxBurstSeconds * permitsPerSecond); + storedPermits = (oldMaxPermits == 0.0D ? 0.0D : storedPermits * maxPermits / oldMaxPermits); + } + + + + long storedPermitsToWaitTime(double storedPermits, double permitsToTake) + { + return 0L; + } + } + + @VisibleForTesting + static abstract class SleepingTicker + extends Ticker + { + static final SleepingTicker SYSTEM_TICKER = new SleepingTicker() + { + public long read() { + return systemTicker().read(); + } + + public void sleepMicrosUninterruptibly(long micros) + { + if (micros > 0L) { + Uninterruptibles.sleepUninterruptibly(micros, TimeUnit.MICROSECONDS); + } + } + }; + + SleepingTicker() {} + + abstract void sleepMicrosUninterruptibly(long paramLong); + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/Runnables.java b/src/minecraft/com/google/common/util/concurrent/Runnables.java new file mode 100644 index 0000000..7a6ffcf --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/Runnables.java @@ -0,0 +1,45 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +public final class Runnables +{ + private static final Runnable EMPTY_RUNNABLE = new Runnable() + { + public void run() {} + }; + + + + + public static Runnable doNothing() + { + return EMPTY_RUNNABLE; + } + + private Runnables() {} +} diff --git a/src/minecraft/com/google/common/util/concurrent/SerializingExecutor.java b/src/minecraft/com/google/common/util/concurrent/SerializingExecutor.java new file mode 100644 index 0000000..d62891d --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/SerializingExecutor.java @@ -0,0 +1,167 @@ +package com.google.common.util.concurrent; + +import com.google.common.base.Preconditions; +import java.util.ArrayDeque; +import java.util.Queue; +import java.util.concurrent.Executor; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.concurrent.GuardedBy; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +final class SerializingExecutor + implements Executor +{ + private static final Logger log = Logger.getLogger(SerializingExecutor.class.getName()); + + + private final Executor executor; + + + @GuardedBy("internalLock") + private final Queue waitQueue = new ArrayDeque(); + + + + + + + + + + @GuardedBy("internalLock") + private boolean isThreadScheduled = false; + + + + private final TaskRunner taskRunner = new TaskRunner(null); + + + + + + public SerializingExecutor(Executor executor) + { + Preconditions.checkNotNull(executor, "'executor' must not be null."); + this.executor = executor; + } + + private final Object internalLock = new Object() { + public String toString() { + return "SerializingExecutor lock: " + super.toString(); + } + }; + + + + + + public void execute(Runnable r) + { + Preconditions.checkNotNull(r, "'r' must not be null."); + boolean scheduleTaskRunner = false; + synchronized (internalLock) { + waitQueue.add(r); + + if (!isThreadScheduled) { + isThreadScheduled = true; + scheduleTaskRunner = true; + } + } + if (scheduleTaskRunner) { + boolean threw = true; + try { + executor.execute(taskRunner); + threw = false; + } finally { + if (threw) { + synchronized (internalLock) + { + + + + isThreadScheduled = false; + } + } + } + } + } + + + + private class TaskRunner + implements Runnable + { + private TaskRunner() {} + + + public void run() + { + boolean stillRunning = true; + try { + for (;;) { + Preconditions.checkState(isThreadScheduled); + Runnable nextToRun; + synchronized (internalLock) { + nextToRun = (Runnable)waitQueue.poll(); + if (nextToRun == null) { + isThreadScheduled = false; + stillRunning = false; + break; + } + } + + try + { + nextToRun.run(); + } + catch (RuntimeException e) { + SerializingExecutor.log.log(Level.SEVERE, "Exception while executing runnable " + nextToRun, e); + } + } + } + finally { + if (stillRunning) + { + + + synchronized (internalLock) { + isThreadScheduled = false; + } + } + } + } + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/Service.java b/src/minecraft/com/google/common/util/concurrent/Service.java new file mode 100644 index 0000000..dfff6b1 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/Service.java @@ -0,0 +1,242 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public abstract interface Service +{ + public abstract Service startAsync(); + + public abstract boolean isRunning(); + + public abstract State state(); + + public abstract Service stopAsync(); + + public abstract void awaitRunning(); + + public abstract void awaitRunning(long paramLong, TimeUnit paramTimeUnit) + throws TimeoutException; + + public abstract void awaitTerminated(); + + public abstract void awaitTerminated(long paramLong, TimeUnit paramTimeUnit) + throws TimeoutException; + + public abstract Throwable failureCause(); + + public abstract void addListener(Listener paramListener, Executor paramExecutor); + + @Beta + public static abstract class Listener + { + public Listener() {} + + public void starting() {} + + public void running() {} + + public void stopping(Service.State from) {} + + public void terminated(Service.State from) {} + + public void failed(Service.State from, Throwable failure) {} + } + + @Beta + public static abstract enum State + { + NEW, + + + + + + + + + STARTING, + + + + + + + + + RUNNING, + + + + + + + + + STOPPING, + + + + + + + + + + TERMINATED, + + + + + + + + + + FAILED; + + private State() {} + + abstract boolean isTerminal(); + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/ServiceManager.java b/src/minecraft/com/google/common/util/concurrent/ServiceManager.java new file mode 100644 index 0000000..ab4a024 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/ServiceManager.java @@ -0,0 +1,804 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.base.Function; +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicates; +import com.google.common.base.Stopwatch; +import com.google.common.base.Supplier; +import com.google.common.collect.Collections2; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMap.Builder; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSetMultimap; +import com.google.common.collect.ImmutableSetMultimap.Builder; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimaps; +import com.google.common.collect.Multiset; +import com.google.common.collect.Ordering; +import com.google.common.collect.SetMultimap; +import com.google.common.collect.Sets; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Collections; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.concurrent.GuardedBy; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class ServiceManager +{ + private static final Logger logger = Logger.getLogger(ServiceManager.class.getName()); + private static final ListenerCallQueue.Callback HEALTHY_CALLBACK = new ListenerCallQueue.Callback("healthy()") { + void call(ServiceManager.Listener listener) { + listener.healthy(); + } + }; + private static final ListenerCallQueue.Callback STOPPED_CALLBACK = new ListenerCallQueue.Callback("stopped()") { + void call(ServiceManager.Listener listener) { + listener.stopped(); + } + }; + + + + + + + private final ServiceManagerState state; + + + + + + + private final ImmutableList services; + + + + + + + + @Beta + public static abstract class Listener + { + public Listener() {} + + + + + + + public void healthy() {} + + + + + + + public void stopped() {} + + + + + + + public void failure(Service service) {} + } + + + + + + + public ServiceManager(Iterable services) + { + ImmutableList copy = ImmutableList.copyOf(services); + if (copy.isEmpty()) + { + + logger.log(Level.WARNING, "ServiceManager configured with no services. Is your application configured properly?", new EmptyServiceManagerWarning(null)); + + + copy = ImmutableList.of(new NoOpService(null)); + } + state = new ServiceManagerState(copy); + this.services = copy; + WeakReference stateReference = new WeakReference(state); + + Executor sameThreadExecutor = MoreExecutors.sameThreadExecutor(); + for (Service service : copy) + { + + + + + + + + service.addListener(new ServiceListener(service, stateReference), sameThreadExecutor); + + + Preconditions.checkArgument(service.state() == Service.State.NEW, "Can only manage NEW services, %s", new Object[] { service }); + } + + + state.markReady(); + } + + + + + + + + + + + + + + + + + + + + + + + + public void addListener(Listener listener, Executor executor) + { + state.addListener(listener, executor); + } + + + + + + + + + + + + + + + + + public void addListener(Listener listener) + { + state.addListener(listener, MoreExecutors.sameThreadExecutor()); + } + + + + + + + + + public ServiceManager startAsync() + { + for (Service service : services) { + Service.State state = service.state(); + Preconditions.checkState(state == Service.State.NEW, "Service %s is %s, cannot start it.", new Object[] { service, state }); + } + for (Service service : services) { + try { + service.startAsync(); + + } + catch (IllegalStateException e) + { + + logger.log(Level.WARNING, "Unable to start Service " + service, e); + } + } + return this; + } + + + + + + + + + public void awaitHealthy() + { + state.awaitHealthy(); + } + + + + + + + + + + + public void awaitHealthy(long timeout, TimeUnit unit) + throws TimeoutException + { + state.awaitHealthy(timeout, unit); + } + + + + + + + public ServiceManager stopAsync() + { + for (Service service : services) { + service.stopAsync(); + } + return this; + } + + + + + + public void awaitStopped() + { + state.awaitStopped(); + } + + + + + + + + + public void awaitStopped(long timeout, TimeUnit unit) + throws TimeoutException + { + state.awaitStopped(timeout, unit); + } + + + + + + + public boolean isHealthy() + { + for (Service service : services) { + if (!service.isRunning()) { + return false; + } + } + return true; + } + + + + + + + public ImmutableMultimap servicesByState() + { + return state.servicesByState(); + } + + + + + + + + public ImmutableMap startupTimes() + { + return state.startupTimes(); + } + + public String toString() { + return Objects.toStringHelper(ServiceManager.class).add("services", Collections2.filter(services, Predicates.not(Predicates.instanceOf(NoOpService.class)))).toString(); + } + + + + + + + private static final class ServiceManagerState + { + final Monitor monitor = new Monitor(); + @GuardedBy("monitor") + final SetMultimap servicesByState = Multimaps.newSetMultimap(new EnumMap(Service.State.class), new Supplier() + { + + public Set get() + { + return Sets.newLinkedHashSet(); + } + }); + + + + + + + + @GuardedBy("monitor") + final Multiset states = servicesByState.keys(); + + @GuardedBy("monitor") + final Map startupTimers = Maps.newIdentityHashMap(); + + + + + + @GuardedBy("monitor") + boolean ready; + + + + + + @GuardedBy("monitor") + boolean transitioned; + + + + + + final int numberOfServices; + + + + + + final Monitor.Guard awaitHealthGuard = new Monitor.Guard(monitor) + { + public boolean isSatisfied() { + return (states.count(Service.State.RUNNING) == numberOfServices) || (states.contains(Service.State.STOPPING)) || (states.contains(Service.State.TERMINATED)) || (states.contains(Service.State.FAILED)); + } + }; + + + + + + + + final Monitor.Guard stoppedGuard = new Monitor.Guard(monitor) { + public boolean isSatisfied() { + return states.count(Service.State.TERMINATED) + states.count(Service.State.FAILED) == numberOfServices; + } + }; + + @GuardedBy("monitor") + final List> listeners = Collections.synchronizedList(new ArrayList()); + + + + + + + + + ServiceManagerState(ImmutableCollection services) + { + numberOfServices = services.size(); + servicesByState.putAll(Service.State.NEW, services); + for (Service service : services) { + startupTimers.put(service, Stopwatch.createUnstarted()); + } + } + + + + + void markReady() + { + monitor.enter(); + try { + if (!transitioned) + { + ready = true; + } + else { + List servicesInBadStates = Lists.newArrayList(); + for (Service service : servicesByState().values()) { + if (service.state() != Service.State.NEW) { + servicesInBadStates.add(service); + } + } + throw new IllegalArgumentException("Services started transitioning asynchronously before the ServiceManager was constructed: " + servicesInBadStates); + } + } + finally { + monitor.leave(); + } + } + + void addListener(ServiceManager.Listener listener, Executor executor) { + Preconditions.checkNotNull(listener, "listener"); + Preconditions.checkNotNull(executor, "executor"); + monitor.enter(); + try + { + if (!stoppedGuard.isSatisfied()) { + listeners.add(new ListenerCallQueue(listener, executor)); + } + } finally { + monitor.leave(); + } + } + + void awaitHealthy() { + monitor.enterWhenUninterruptibly(awaitHealthGuard); + try { + checkHealthy(); + } finally { + monitor.leave(); + } + } + + void awaitHealthy(long timeout, TimeUnit unit) throws TimeoutException { + monitor.enter(); + try { + if (!monitor.waitForUninterruptibly(awaitHealthGuard, timeout, unit)) { + throw new TimeoutException("Timeout waiting for the services to become healthy. The following services have not started: " + Multimaps.filterKeys(servicesByState, Predicates.in(ImmutableSet.of(Service.State.NEW, Service.State.STARTING)))); + } + + + checkHealthy(); + } finally { + monitor.leave(); + } + } + + void awaitStopped() { + monitor.enterWhenUninterruptibly(stoppedGuard); + monitor.leave(); + } + + void awaitStopped(long timeout, TimeUnit unit) throws TimeoutException { + monitor.enter(); + try { + if (!monitor.waitForUninterruptibly(stoppedGuard, timeout, unit)) { + throw new TimeoutException("Timeout waiting for the services to stop. The following services have not stopped: " + Multimaps.filterKeys(servicesByState, Predicates.not(Predicates.in(ImmutableSet.of(Service.State.TERMINATED, Service.State.FAILED))))); + } + + } + finally + { + monitor.leave(); + } + } + + ImmutableMultimap servicesByState() { + ImmutableSetMultimap.Builder builder = ImmutableSetMultimap.builder(); + monitor.enter(); + try { + for (Map.Entry entry : servicesByState.entries()) { + if (!(entry.getValue() instanceof ServiceManager.NoOpService)) { + builder.put(entry.getKey(), entry.getValue()); + } + } + } finally { + monitor.leave(); + } + return builder.build(); + } + + ImmutableMap startupTimes() + { + monitor.enter(); + List> loadTimes; + try { loadTimes = Lists.newArrayListWithCapacity(states.size() - states.count(Service.State.NEW) + states.count(Service.State.STARTING)); + + for (Map.Entry entry : startupTimers.entrySet()) { + Service service = (Service)entry.getKey(); + Stopwatch stopWatch = (Stopwatch)entry.getValue(); + + + + + if ((!stopWatch.isRunning()) && (!servicesByState.containsEntry(Service.State.NEW, service)) && (!(service instanceof ServiceManager.NoOpService))) + { + loadTimes.add(Maps.immutableEntry(service, Long.valueOf(stopWatch.elapsed(TimeUnit.MILLISECONDS)))); + } + } + } finally { + monitor.leave(); + } + Collections.sort(loadTimes, Ordering.natural().onResultOf(new Function() + { + public Long apply(Map.Entry input) { + return (Long)input.getValue(); + } + })); + ImmutableMap.Builder builder = ImmutableMap.builder(); + for (Map.Entry entry : loadTimes) { + builder.put(entry); + } + return builder.build(); + } + + + + + + + + + + + + void transitionService(Service service, Service.State from, Service.State to) + { + Preconditions.checkNotNull(service); + Preconditions.checkArgument(from != to); + monitor.enter(); + try { + transitioned = true; + if (!ready) { + return; + } + + Preconditions.checkState(servicesByState.remove(from, service), "Service %s not at the expected location in the state map %s", new Object[] { service, from }); + + Preconditions.checkState(servicesByState.put(to, service), "Service %s in the state map unexpectedly at %s", new Object[] { service, to }); + + + Stopwatch stopwatch = (Stopwatch)startupTimers.get(service); + if (from == Service.State.NEW) { + stopwatch.start(); + } + if ((to.compareTo(Service.State.RUNNING) >= 0) && (stopwatch.isRunning())) + { + stopwatch.stop(); + if (!(service instanceof ServiceManager.NoOpService)) { + ServiceManager.logger.log(Level.FINE, "Started {0} in {1}.", new Object[] { service, stopwatch }); + } + } + + + + if (to == Service.State.FAILED) { + fireFailedListeners(service); + } + + if (states.count(Service.State.RUNNING) == numberOfServices) + { + + fireHealthyListeners(); + } else if (states.count(Service.State.TERMINATED) + states.count(Service.State.FAILED) == numberOfServices) { + fireStoppedListeners(); + } + } finally { + monitor.leave(); + + executeListeners(); + } + } + + @GuardedBy("monitor") + void fireStoppedListeners() { + ServiceManager.STOPPED_CALLBACK.enqueueOn(listeners); + } + + @GuardedBy("monitor") + void fireHealthyListeners() { + ServiceManager.HEALTHY_CALLBACK.enqueueOn(listeners); + } + + @GuardedBy("monitor") + void fireFailedListeners(final Service service) { + new ListenerCallQueue.Callback("failed({service=" + service + "})") + { + void call(ServiceManager.Listener listener) { listener.failure(service); } }.enqueueOn(listeners); + } + + + + void executeListeners() + { + Preconditions.checkState(!monitor.isOccupiedByCurrentThread(), "It is incorrect to execute listeners with the monitor held."); + + + for (int i = 0; i < listeners.size(); i++) { + ((ListenerCallQueue)listeners.get(i)).execute(); + } + } + + @GuardedBy("monitor") + void checkHealthy() { + if (states.count(Service.State.RUNNING) != numberOfServices) { + throw new IllegalStateException("Expected to be healthy after starting. The following services are not running: " + Multimaps.filterKeys(servicesByState, Predicates.not(Predicates.equalTo(Service.State.RUNNING)))); + } + } + } + + + + private static final class ServiceListener + extends Service.Listener + { + final Service service; + + + final WeakReference state; + + + + ServiceListener(Service service, WeakReference state) + { + this.service = service; + this.state = state; + } + + public void starting() { + ServiceManager.ServiceManagerState state = (ServiceManager.ServiceManagerState)this.state.get(); + if (state != null) { + state.transitionService(service, Service.State.NEW, Service.State.STARTING); + if (!(service instanceof ServiceManager.NoOpService)) { + ServiceManager.logger.log(Level.FINE, "Starting {0}.", service); + } + } + } + + public void running() { + ServiceManager.ServiceManagerState state = (ServiceManager.ServiceManagerState)this.state.get(); + if (state != null) { + state.transitionService(service, Service.State.STARTING, Service.State.RUNNING); + } + } + + public void stopping(Service.State from) { + ServiceManager.ServiceManagerState state = (ServiceManager.ServiceManagerState)this.state.get(); + if (state != null) { + state.transitionService(service, from, Service.State.STOPPING); + } + } + + public void terminated(Service.State from) { + ServiceManager.ServiceManagerState state = (ServiceManager.ServiceManagerState)this.state.get(); + if (state != null) { + if (!(service instanceof ServiceManager.NoOpService)) { + ServiceManager.logger.log(Level.FINE, "Service {0} has terminated. Previous state was: {1}", new Object[] { service, from }); + } + + state.transitionService(service, from, Service.State.TERMINATED); + } + } + + public void failed(Service.State from, Throwable failure) { + ServiceManager.ServiceManagerState state = (ServiceManager.ServiceManagerState)this.state.get(); + if (state != null) + { + + if (!(service instanceof ServiceManager.NoOpService)) { + ServiceManager.logger.log(Level.SEVERE, "Service " + service + " has failed in the " + from + " state.", failure); + } + + state.transitionService(service, from, Service.State.FAILED); + } + } + } + + + + private static final class NoOpService + extends AbstractService + { + private NoOpService() {} + + + + protected void doStart() { notifyStarted(); } + protected void doStop() { notifyStopped(); } + } + + private static final class EmptyServiceManagerWarning + extends Throwable + { + private EmptyServiceManagerWarning() {} + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/SettableFuture.java b/src/minecraft/com/google/common/util/concurrent/SettableFuture.java new file mode 100644 index 0000000..a8471bf --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/SettableFuture.java @@ -0,0 +1,70 @@ +package com.google.common.util.concurrent; + +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + +public final class SettableFuture + extends AbstractFuture +{ + public static SettableFuture create() + { + return new SettableFuture(); + } + + + + + + + + private SettableFuture() {} + + + + + + + + public boolean set(@Nullable V value) + { + return super.set(value); + } + + + + + + + + + + + + public boolean setException(Throwable throwable) + { + return super.setException(throwable); + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/SimpleTimeLimiter.java b/src/minecraft/com/google/common/util/concurrent/SimpleTimeLimiter.java new file mode 100644 index 0000000..8530179 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/SimpleTimeLimiter.java @@ -0,0 +1,195 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.collect.ObjectArrays; +import com.google.common.collect.Sets; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class SimpleTimeLimiter + implements TimeLimiter +{ + private final ExecutorService executor; + + public SimpleTimeLimiter(ExecutorService executor) + { + this.executor = ((ExecutorService)Preconditions.checkNotNull(executor)); + } + + + + + + + + + + public SimpleTimeLimiter() + { + this(Executors.newCachedThreadPool()); + } + + + public T newProxy(final T target, Class interfaceType, final long timeoutDuration, TimeUnit timeoutUnit) + { + Preconditions.checkNotNull(target); + Preconditions.checkNotNull(interfaceType); + Preconditions.checkNotNull(timeoutUnit); + Preconditions.checkArgument(timeoutDuration > 0L, "bad timeout: %s", new Object[] { Long.valueOf(timeoutDuration) }); + Preconditions.checkArgument(interfaceType.isInterface(), "interfaceType must be an interface type"); + + + final Set interruptibleMethods = findInterruptibleMethods(interfaceType); + + + InvocationHandler handler = new InvocationHandler() + { + public Object invoke(Object obj, final Method method, final Object[] args) throws Throwable + { + Callable callable = new Callable() + { + public Object call() throws Exception { + try { + return method.invoke(val$target, args); + } catch (InvocationTargetException e) { + SimpleTimeLimiter.throwCause(e, false); + throw new AssertionError("can't get here"); + } + } + }; + return callWithTimeout(callable, timeoutDuration, interruptibleMethods, val$interruptibleMethods.contains(method)); + } + + }; + return newProxy(interfaceType, handler); + } + + + public T callWithTimeout(Callable callable, long timeoutDuration, TimeUnit timeoutUnit, boolean amInterruptible) + throws Exception + { + Preconditions.checkNotNull(callable); + Preconditions.checkNotNull(timeoutUnit); + Preconditions.checkArgument(timeoutDuration > 0L, "timeout must be positive: %s", new Object[] { Long.valueOf(timeoutDuration) }); + + Future future = executor.submit(callable); + try { + if (amInterruptible) { + try { + return future.get(timeoutDuration, timeoutUnit); + } catch (InterruptedException e) { + future.cancel(true); + throw e; + } + } + return Uninterruptibles.getUninterruptibly(future, timeoutDuration, timeoutUnit); + } + catch (ExecutionException e) + { + throw throwCause(e, true); + } catch (TimeoutException e) { + future.cancel(true); + throw new UncheckedTimeoutException(e); + } + } + + private static Exception throwCause(Exception e, boolean combineStackTraces) throws Exception + { + Throwable cause = e.getCause(); + if (cause == null) { + throw e; + } + if (combineStackTraces) { + StackTraceElement[] combined = (StackTraceElement[])ObjectArrays.concat(cause.getStackTrace(), e.getStackTrace(), StackTraceElement.class); + + cause.setStackTrace(combined); + } + if ((cause instanceof Exception)) { + throw ((Exception)cause); + } + if ((cause instanceof Error)) { + throw ((Error)cause); + } + + throw e; + } + + private static Set findInterruptibleMethods(Class interfaceType) { + Set set = Sets.newHashSet(); + for (Method m : interfaceType.getMethods()) { + if (declaresInterruptedEx(m)) { + set.add(m); + } + } + return set; + } + + private static boolean declaresInterruptedEx(Method method) { + for (Class exType : method.getExceptionTypes()) + { + if (exType == InterruptedException.class) { + return true; + } + } + return false; + } + + + private static T newProxy(Class interfaceType, InvocationHandler handler) + { + Object object = Proxy.newProxyInstance(interfaceType.getClassLoader(), new Class[] { interfaceType }, handler); + + return interfaceType.cast(object); + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/Striped.java b/src/minecraft/com/google/common/util/concurrent/Striped.java new file mode 100644 index 0000000..7f7e3c1 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/Striped.java @@ -0,0 +1,487 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import com.google.common.collect.MapMaker; +import com.google.common.math.IntMath; +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.math.RoundingMode; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.Semaphore; +import java.util.concurrent.atomic.AtomicReferenceArray; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public abstract class Striped +{ + private static final int LARGE_LAZY_CUTOFF = 1024; + + private Striped() {} + + public abstract L get(Object paramObject); + + public abstract L getAt(int paramInt); + + abstract int indexFor(Object paramObject); + + public abstract int size(); + + public Iterable bulkGet(Iterable keys) + { + Object[] array = Iterables.toArray(keys, Object.class); + if (array.length == 0) { + return ImmutableList.of(); + } + int[] stripes = new int[array.length]; + for (int i = 0; i < array.length; i++) { + stripes[i] = indexFor(array[i]); + } + Arrays.sort(stripes); + + int previousStripe = stripes[0]; + array[0] = getAt(previousStripe); + for (int i = 1; i < array.length; i++) { + int currentStripe = stripes[i]; + if (currentStripe == previousStripe) { + array[i] = array[(i - 1)]; + } else { + array[i] = getAt(currentStripe); + previousStripe = currentStripe; + } + } + + + + + + + + + + + + + + + + + + + List asList = Arrays.asList(array); + return Collections.unmodifiableList(asList); + } + + + + + + + + + + public static Striped lock(int stripes) + { + new CompactStriped(stripes, new Supplier() + { + public Lock get() { return new Striped.PaddedLock(); } }, null); + } + + + + + + + + + + public static Striped lazyWeakLock(int stripes) + { + lazy(stripes, new Supplier() { + public Lock get() { + return new ReentrantLock(false); + } + }); + } + + private static Striped lazy(int stripes, Supplier supplier) { + return stripes < 1024 ? new SmallLazyStriped(stripes, supplier) : new LargeLazyStriped(stripes, supplier); + } + + + + + + + + + + + public static Striped semaphore(int stripes, int permits) + { + new CompactStriped(stripes, new Supplier() + { + public Semaphore get() { return new Striped.PaddedSemaphore(val$permits); } }, null); + } + + + + + + + + + + + public static Striped lazyWeakSemaphore(int stripes, int permits) + { + lazy(stripes, new Supplier() { + public Semaphore get() { + return new Semaphore(val$permits, false); + } + }); + } + + + + + + + + public static Striped readWriteLock(int stripes) + { + return new CompactStriped(stripes, READ_WRITE_LOCK_SUPPLIER, null); + } + + + + + + + + public static Striped lazyWeakReadWriteLock(int stripes) + { + return lazy(stripes, READ_WRITE_LOCK_SUPPLIER); + } + + + private static final Supplier READ_WRITE_LOCK_SUPPLIER = new Supplier() + { + + public ReadWriteLock get() { return new ReentrantReadWriteLock(); } + }; + private static final int ALL_SET = -1; + + private static abstract class PowerOfTwoStriped extends Striped { + final int mask; + + PowerOfTwoStriped(int stripes) { + super(); + Preconditions.checkArgument(stripes > 0, "Stripes must be positive"); + mask = (stripes > 1073741824 ? -1 : Striped.ceilToPowerOfTwo(stripes) - 1); + } + + final int indexFor(Object key) { + int hash = Striped.smear(key.hashCode()); + return hash & mask; + } + + public final L get(Object key) { + return getAt(indexFor(key)); + } + } + + + private static class CompactStriped + extends Striped.PowerOfTwoStriped + { + private final Object[] array; + + + private CompactStriped(int stripes, Supplier supplier) + { + super(); + Preconditions.checkArgument(stripes <= 1073741824, "Stripes must be <= 2^30)"); + + array = new Object[mask + 1]; + for (int i = 0; i < array.length; i++) { + array[i] = supplier.get(); + } + } + + public L getAt(int index) + { + return array[index]; + } + + public int size() { + return array.length; + } + } + + + @VisibleForTesting + static class SmallLazyStriped + extends Striped.PowerOfTwoStriped + { + final AtomicReferenceArray> locks; + + final Supplier supplier; + final int size; + final ReferenceQueue queue = new ReferenceQueue(); + + SmallLazyStriped(int stripes, Supplier supplier) { + super(); + size = (mask == -1 ? Integer.MAX_VALUE : mask + 1); + locks = new AtomicReferenceArray(size); + this.supplier = supplier; + } + + public L getAt(int index) { + if (size != Integer.MAX_VALUE) { + Preconditions.checkElementIndex(index, size()); + } + ArrayReference existingRef = (ArrayReference)locks.get(index); + L existing = existingRef == null ? null : existingRef.get(); + if (existing != null) { + return existing; + } + L created = supplier.get(); + ArrayReference newRef = new ArrayReference(created, index, queue); + while (!locks.compareAndSet(index, existingRef, newRef)) + { + existingRef = (ArrayReference)locks.get(index); + existing = existingRef == null ? null : existingRef.get(); + if (existing != null) { + return existing; + } + } + drainQueue(); + return created; + } + + + private void drainQueue() + { + Reference ref; + + while ((ref = queue.poll()) != null) + { + ArrayReference arrayRef = (ArrayReference)ref; + + + locks.compareAndSet(index, arrayRef, null); + } + } + + public int size() { + return size; + } + + private static final class ArrayReference extends WeakReference { + final int index; + + ArrayReference(L referent, int index, ReferenceQueue queue) { + super(queue); + this.index = index; + } + } + } + + + @VisibleForTesting + static class LargeLazyStriped + extends Striped.PowerOfTwoStriped + { + final ConcurrentMap locks; + final Supplier supplier; + final int size; + + LargeLazyStriped(int stripes, Supplier supplier) + { + super(); + size = (mask == -1 ? Integer.MAX_VALUE : mask + 1); + this.supplier = supplier; + locks = new MapMaker().weakValues().makeMap(); + } + + public L getAt(int index) { + if (size != Integer.MAX_VALUE) { + Preconditions.checkElementIndex(index, size()); + } + L existing = locks.get(Integer.valueOf(index)); + if (existing != null) { + return existing; + } + L created = supplier.get(); + existing = locks.putIfAbsent(Integer.valueOf(index), created); + return Objects.firstNonNull(existing, created); + } + + public int size() { + return size; + } + } + + + + + + private static int ceilToPowerOfTwo(int x) + { + return 1 << IntMath.log2(x, RoundingMode.CEILING); + } + + + + + + + + + + private static int smear(int hashCode) + { + hashCode ^= hashCode >>> 20 ^ hashCode >>> 12; + return hashCode ^ hashCode >>> 7 ^ hashCode >>> 4; + } + + + private static class PaddedLock + extends ReentrantLock + { + long q1; + long q2; + long q3; + + PaddedLock() + { + super(); + } + } + + private static class PaddedSemaphore extends Semaphore { + long q1; + long q2; + long q3; + + PaddedSemaphore(int permits) { + super(false); + } + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/ThreadFactoryBuilder.java b/src/minecraft/com/google/common/util/concurrent/ThreadFactoryBuilder.java new file mode 100644 index 0000000..8fbe0e0 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/ThreadFactoryBuilder.java @@ -0,0 +1,179 @@ +package com.google.common.util.concurrent; + +import com.google.common.base.Preconditions; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public final class ThreadFactoryBuilder +{ + private String nameFormat = null; + private Boolean daemon = null; + private Integer priority = null; + private Thread.UncaughtExceptionHandler uncaughtExceptionHandler = null; + private ThreadFactory backingThreadFactory = null; + + + + + + + + + + public ThreadFactoryBuilder() {} + + + + + + + + + public ThreadFactoryBuilder setNameFormat(String nameFormat) + { + String.format(nameFormat, new Object[] { Integer.valueOf(0) }); + this.nameFormat = nameFormat; + return this; + } + + + + + + + + public ThreadFactoryBuilder setDaemon(boolean daemon) + { + this.daemon = Boolean.valueOf(daemon); + return this; + } + + + + + + + + + + public ThreadFactoryBuilder setPriority(int priority) + { + Preconditions.checkArgument(priority >= 1, "Thread priority (%s) must be >= %s", new Object[] { Integer.valueOf(priority), Integer.valueOf(1) }); + + Preconditions.checkArgument(priority <= 10, "Thread priority (%s) must be <= %s", new Object[] { Integer.valueOf(priority), Integer.valueOf(10) }); + + this.priority = Integer.valueOf(priority); + return this; + } + + + + + + + + + + public ThreadFactoryBuilder setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler uncaughtExceptionHandler) + { + this.uncaughtExceptionHandler = ((Thread.UncaughtExceptionHandler)Preconditions.checkNotNull(uncaughtExceptionHandler)); + return this; + } + + + + + + + + + + + + + public ThreadFactoryBuilder setThreadFactory(ThreadFactory backingThreadFactory) + { + this.backingThreadFactory = ((ThreadFactory)Preconditions.checkNotNull(backingThreadFactory)); + return this; + } + + + + + + + + + public ThreadFactory build() + { + return build(this); + } + + private static ThreadFactory build(ThreadFactoryBuilder builder) { + final String nameFormat = builder.nameFormat; + final Boolean daemon = builder.daemon; + final Integer priority = builder.priority; + final Thread.UncaughtExceptionHandler uncaughtExceptionHandler = builder.uncaughtExceptionHandler; + + ThreadFactory backingThreadFactory = builder.backingThreadFactory != null ? builder.backingThreadFactory : Executors.defaultThreadFactory(); + + + + final AtomicLong count = nameFormat != null ? new AtomicLong(0L) : null; + new ThreadFactory() { + public Thread newThread(Runnable runnable) { + Thread thread = val$backingThreadFactory.newThread(runnable); + if (nameFormat != null) { + thread.setName(String.format(nameFormat, new Object[] { Long.valueOf(count.getAndIncrement()) })); + } + if (daemon != null) { + thread.setDaemon(daemon.booleanValue()); + } + if (priority != null) { + thread.setPriority(priority.intValue()); + } + if (uncaughtExceptionHandler != null) { + thread.setUncaughtExceptionHandler(uncaughtExceptionHandler); + } + return thread; + } + }; + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/TimeLimiter.java b/src/minecraft/com/google/common/util/concurrent/TimeLimiter.java new file mode 100644 index 0000000..8ab23d0 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/TimeLimiter.java @@ -0,0 +1,14 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; + +@Beta +public abstract interface TimeLimiter +{ + public abstract T newProxy(T paramT, Class paramClass, long paramLong, TimeUnit paramTimeUnit); + + public abstract T callWithTimeout(Callable paramCallable, long paramLong, TimeUnit paramTimeUnit, boolean paramBoolean) + throws Exception; +} diff --git a/src/minecraft/com/google/common/util/concurrent/UncaughtExceptionHandlers.java b/src/minecraft/com/google/common/util/concurrent/UncaughtExceptionHandlers.java new file mode 100644 index 0000000..923a9ae --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/UncaughtExceptionHandlers.java @@ -0,0 +1,76 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.VisibleForTesting; +import java.io.PrintStream; +import java.util.logging.Level; +import java.util.logging.Logger; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public final class UncaughtExceptionHandlers +{ + private UncaughtExceptionHandlers() {} + + public static Thread.UncaughtExceptionHandler systemExit() { return new Exiter(Runtime.getRuntime()); } + + @VisibleForTesting + static final class Exiter implements Thread.UncaughtExceptionHandler { + private static final Logger logger = Logger.getLogger(Exiter.class.getName()); + private final Runtime runtime; + + Exiter(Runtime runtime) + { + this.runtime = runtime; + } + + public void uncaughtException(Thread t, Throwable e) + { + try { + logger.log(Level.SEVERE, String.format("Caught an exception in %s. Shutting down.", new Object[] { t }), e); + } + catch (Throwable errorInLogging) + { + System.err.println(e.getMessage()); + System.err.println(errorInLogging.getMessage()); + } finally { + runtime.exit(1); + } + } + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/UncheckedExecutionException.java b/src/minecraft/com/google/common/util/concurrent/UncheckedExecutionException.java new file mode 100644 index 0000000..33d1cf9 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/UncheckedExecutionException.java @@ -0,0 +1,67 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.GwtCompatible; +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@GwtCompatible +public class UncheckedExecutionException + extends RuntimeException +{ + private static final long serialVersionUID = 0L; + + protected UncheckedExecutionException() {} + + protected UncheckedExecutionException(@Nullable String message) + { + super(message); + } + + + + public UncheckedExecutionException(@Nullable String message, @Nullable Throwable cause) + { + super(message, cause); + } + + + + public UncheckedExecutionException(@Nullable Throwable cause) + { + super(cause); + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/UncheckedTimeoutException.java b/src/minecraft/com/google/common/util/concurrent/UncheckedTimeoutException.java new file mode 100644 index 0000000..ee9705a --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/UncheckedTimeoutException.java @@ -0,0 +1,41 @@ +package com.google.common.util.concurrent; + +import javax.annotation.Nullable; + + + + + + + + + + + + + + + + + + +public class UncheckedTimeoutException + extends RuntimeException +{ + private static final long serialVersionUID = 0L; + + public UncheckedTimeoutException() {} + + public UncheckedTimeoutException(@Nullable String message) + { + super(message); + } + + public UncheckedTimeoutException(@Nullable Throwable cause) { + super(cause); + } + + public UncheckedTimeoutException(@Nullable String message, @Nullable Throwable cause) { + super(message, cause); + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/Uninterruptibles.java b/src/minecraft/com/google/common/util/concurrent/Uninterruptibles.java new file mode 100644 index 0000000..da8d08d --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/Uninterruptibles.java @@ -0,0 +1,444 @@ +package com.google.common.util.concurrent; + +import com.google.common.annotations.Beta; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +public final class Uninterruptibles +{ + public static void awaitUninterruptibly(CountDownLatch latch) + { + boolean interrupted = false; + + try + { + latch.await(); + } catch (InterruptedException e) { + for (;;) { + interrupted = true; + } + } + finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + + /* Error */ + public static boolean awaitUninterruptibly(CountDownLatch latch, long timeout, java.util.concurrent.TimeUnit unit) + { + // Byte code: + // 0: iconst_0 + // 1: istore 4 + // 3: aload_3 + // 4: lload_1 + // 5: invokevirtual 5 java/util/concurrent/TimeUnit:toNanos (J)J + // 8: lstore 5 + // 10: invokestatic 6 java/lang/System:nanoTime ()J + // 13: lload 5 + // 15: ladd + // 16: lstore 7 + // 18: aload_0 + // 19: lload 5 + // 21: getstatic 7 java/util/concurrent/TimeUnit:NANOSECONDS Ljava/util/concurrent/TimeUnit; + // 24: invokevirtual 8 java/util/concurrent/CountDownLatch:await (JLjava/util/concurrent/TimeUnit;)Z + // 27: istore 9 + // 29: iload 4 + // 31: ifeq +9 -> 40 + // 34: invokestatic 2 java/lang/Thread:currentThread ()Ljava/lang/Thread; + // 37: invokevirtual 3 java/lang/Thread:interrupt ()V + // 40: iload 9 + // 42: ireturn + // 43: astore 9 + // 45: iconst_1 + // 46: istore 4 + // 48: lload 7 + // 50: invokestatic 6 java/lang/System:nanoTime ()J + // 53: lsub + // 54: lstore 5 + // 56: goto -38 -> 18 + // 59: astore 10 + // 61: iload 4 + // 63: ifeq +9 -> 72 + // 66: invokestatic 2 java/lang/Thread:currentThread ()Ljava/lang/Thread; + // 69: invokevirtual 3 java/lang/Thread:interrupt ()V + // 72: aload 10 + // 74: athrow + // Line number table: + // Java source line #75 -> byte code offset #0 + // Java source line #77 -> byte code offset #3 + // Java source line #78 -> byte code offset #10 + // Java source line #83 -> byte code offset #18 + // Java source line #90 -> byte code offset #29 + // Java source line #91 -> byte code offset #34 + // Java source line #84 -> byte code offset #43 + // Java source line #85 -> byte code offset #45 + // Java source line #86 -> byte code offset #48 + // Java source line #87 -> byte code offset #56 + // Java source line #90 -> byte code offset #59 + // Java source line #91 -> byte code offset #66 + // Local variable table: + // start length slot name signature + // 0 75 0 latch CountDownLatch + // 0 75 1 timeout long + // 0 75 3 unit java.util.concurrent.TimeUnit + // 1 61 4 interrupted boolean + // 8 47 5 remainingNanos long + // 16 33 7 end long + // 27 14 9 bool1 boolean + // 43 3 9 e InterruptedException + // 59 14 10 localObject Object + // Exception table: + // from to target type + // 18 29 43 java/lang/InterruptedException + // 3 29 59 finally + // 43 61 59 finally + } + + public static void joinUninterruptibly(Thread toJoin) + { + boolean interrupted = false; + + try + { + toJoin.join(); + } catch (InterruptedException e) { + for (;;) { + interrupted = true; + } + } + finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + + + + + + + + + + + + + public static V getUninterruptibly(Future future) + throws ExecutionException + { + boolean interrupted = false; + + try + { + return future.get(); + } catch (InterruptedException e) { + for (;;) { interrupted = true; + } + } + finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + + /* Error */ + public static V getUninterruptibly(Future future, long timeout, java.util.concurrent.TimeUnit unit) + throws ExecutionException, java.util.concurrent.TimeoutException + { + // Byte code: + // 0: iconst_0 + // 1: istore 4 + // 3: aload_3 + // 4: lload_1 + // 5: invokevirtual 5 java/util/concurrent/TimeUnit:toNanos (J)J + // 8: lstore 5 + // 10: invokestatic 6 java/lang/System:nanoTime ()J + // 13: lload 5 + // 15: ladd + // 16: lstore 7 + // 18: aload_0 + // 19: lload 5 + // 21: getstatic 7 java/util/concurrent/TimeUnit:NANOSECONDS Ljava/util/concurrent/TimeUnit; + // 24: invokeinterface 11 4 0 + // 29: astore 9 + // 31: iload 4 + // 33: ifeq +9 -> 42 + // 36: invokestatic 2 java/lang/Thread:currentThread ()Ljava/lang/Thread; + // 39: invokevirtual 3 java/lang/Thread:interrupt ()V + // 42: aload 9 + // 44: areturn + // 45: astore 9 + // 47: iconst_1 + // 48: istore 4 + // 50: lload 7 + // 52: invokestatic 6 java/lang/System:nanoTime ()J + // 55: lsub + // 56: lstore 5 + // 58: goto -40 -> 18 + // 61: astore 10 + // 63: iload 4 + // 65: ifeq +9 -> 74 + // 68: invokestatic 2 java/lang/Thread:currentThread ()Ljava/lang/Thread; + // 71: invokevirtual 3 java/lang/Thread:interrupt ()V + // 74: aload 10 + // 76: athrow + // Line number table: + // Java source line #163 -> byte code offset #0 + // Java source line #165 -> byte code offset #3 + // Java source line #166 -> byte code offset #10 + // Java source line #171 -> byte code offset #18 + // Java source line #178 -> byte code offset #31 + // Java source line #179 -> byte code offset #36 + // Java source line #172 -> byte code offset #45 + // Java source line #173 -> byte code offset #47 + // Java source line #174 -> byte code offset #50 + // Java source line #175 -> byte code offset #58 + // Java source line #178 -> byte code offset #61 + // Java source line #179 -> byte code offset #68 + // Local variable table: + // start length slot name signature + // 0 77 0 future Future + // 0 77 1 timeout long + // 0 77 3 unit java.util.concurrent.TimeUnit + // 1 63 4 interrupted boolean + // 8 49 5 remainingNanos long + // 16 35 7 end long + // 29 14 9 localObject1 Object + // 45 3 9 e InterruptedException + // 61 14 10 localObject2 Object + // Exception table: + // from to target type + // 18 31 45 java/lang/InterruptedException + // 3 31 61 finally + // 45 63 61 finally + } + + /* Error */ + public static void joinUninterruptibly(Thread toJoin, long timeout, java.util.concurrent.TimeUnit unit) + { + // Byte code: + // 0: aload_0 + // 1: invokestatic 12 com/google/common/base/Preconditions:checkNotNull (Ljava/lang/Object;)Ljava/lang/Object; + // 4: pop + // 5: iconst_0 + // 6: istore 4 + // 8: aload_3 + // 9: lload_1 + // 10: invokevirtual 5 java/util/concurrent/TimeUnit:toNanos (J)J + // 13: lstore 5 + // 15: invokestatic 6 java/lang/System:nanoTime ()J + // 18: lload 5 + // 20: ladd + // 21: lstore 7 + // 23: getstatic 7 java/util/concurrent/TimeUnit:NANOSECONDS Ljava/util/concurrent/TimeUnit; + // 26: aload_0 + // 27: lload 5 + // 29: invokevirtual 13 java/util/concurrent/TimeUnit:timedJoin (Ljava/lang/Thread;J)V + // 32: iload 4 + // 34: ifeq +9 -> 43 + // 37: invokestatic 2 java/lang/Thread:currentThread ()Ljava/lang/Thread; + // 40: invokevirtual 3 java/lang/Thread:interrupt ()V + // 43: return + // 44: astore 9 + // 46: iconst_1 + // 47: istore 4 + // 49: lload 7 + // 51: invokestatic 6 java/lang/System:nanoTime ()J + // 54: lsub + // 55: lstore 5 + // 57: goto -34 -> 23 + // 60: astore 10 + // 62: iload 4 + // 64: ifeq +9 -> 73 + // 67: invokestatic 2 java/lang/Thread:currentThread ()Ljava/lang/Thread; + // 70: invokevirtual 3 java/lang/Thread:interrupt ()V + // 73: aload 10 + // 75: athrow + // Line number table: + // Java source line #191 -> byte code offset #0 + // Java source line #192 -> byte code offset #5 + // Java source line #194 -> byte code offset #8 + // Java source line #195 -> byte code offset #15 + // Java source line #199 -> byte code offset #23 + // Java source line #207 -> byte code offset #32 + // Java source line #208 -> byte code offset #37 + // Java source line #201 -> byte code offset #44 + // Java source line #202 -> byte code offset #46 + // Java source line #203 -> byte code offset #49 + // Java source line #204 -> byte code offset #57 + // Java source line #207 -> byte code offset #60 + // Java source line #208 -> byte code offset #67 + // Local variable table: + // start length slot name signature + // 0 76 0 toJoin Thread + // 0 76 1 timeout long + // 0 76 3 unit java.util.concurrent.TimeUnit + // 6 57 4 interrupted boolean + // 13 43 5 remainingNanos long + // 21 29 7 end long + // 44 3 9 e InterruptedException + // 60 14 10 localObject Object + // Exception table: + // from to target type + // 23 32 44 java/lang/InterruptedException + // 8 32 60 finally + // 44 62 60 finally + } + + public static E takeUninterruptibly(BlockingQueue queue) + { + boolean interrupted = false; + + try + { + return queue.take(); + } catch (InterruptedException e) { + for (;;) { interrupted = true; + } + } + finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + + + + + + + + + + public static void putUninterruptibly(BlockingQueue queue, E element) + { + boolean interrupted = false; + + try + { + queue.put(element); + } catch (InterruptedException e) { + for (;;) { + interrupted = true; + } + } + finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } + + /* Error */ + public static void sleepUninterruptibly(long sleepFor, java.util.concurrent.TimeUnit unit) + { + // Byte code: + // 0: iconst_0 + // 1: istore_3 + // 2: aload_2 + // 3: lload_0 + // 4: invokevirtual 5 java/util/concurrent/TimeUnit:toNanos (J)J + // 7: lstore 4 + // 9: invokestatic 6 java/lang/System:nanoTime ()J + // 12: lload 4 + // 14: ladd + // 15: lstore 6 + // 17: getstatic 7 java/util/concurrent/TimeUnit:NANOSECONDS Ljava/util/concurrent/TimeUnit; + // 20: lload 4 + // 22: invokevirtual 16 java/util/concurrent/TimeUnit:sleep (J)V + // 25: iload_3 + // 26: ifeq +9 -> 35 + // 29: invokestatic 2 java/lang/Thread:currentThread ()Ljava/lang/Thread; + // 32: invokevirtual 3 java/lang/Thread:interrupt ()V + // 35: return + // 36: astore 8 + // 38: iconst_1 + // 39: istore_3 + // 40: lload 6 + // 42: invokestatic 6 java/lang/System:nanoTime ()J + // 45: lsub + // 46: lstore 4 + // 48: goto -31 -> 17 + // 51: astore 9 + // 53: iload_3 + // 54: ifeq +9 -> 63 + // 57: invokestatic 2 java/lang/Thread:currentThread ()Ljava/lang/Thread; + // 60: invokevirtual 3 java/lang/Thread:interrupt ()V + // 63: aload 9 + // 65: athrow + // Line number table: + // Java source line #266 -> byte code offset #0 + // Java source line #268 -> byte code offset #2 + // Java source line #269 -> byte code offset #9 + // Java source line #273 -> byte code offset #17 + // Java source line #281 -> byte code offset #25 + // Java source line #282 -> byte code offset #29 + // Java source line #275 -> byte code offset #36 + // Java source line #276 -> byte code offset #38 + // Java source line #277 -> byte code offset #40 + // Java source line #278 -> byte code offset #48 + // Java source line #281 -> byte code offset #51 + // Java source line #282 -> byte code offset #57 + // Local variable table: + // start length slot name signature + // 0 66 0 sleepFor long + // 0 66 2 unit java.util.concurrent.TimeUnit + // 1 53 3 interrupted boolean + // 7 40 4 remainingNanos long + // 15 26 6 end long + // 36 3 8 e InterruptedException + // 51 13 9 localObject Object + // Exception table: + // from to target type + // 17 25 36 java/lang/InterruptedException + // 2 25 51 finally + // 36 53 51 finally + } + + private Uninterruptibles() {} +} diff --git a/src/minecraft/com/google/common/util/concurrent/WrappingExecutorService.java b/src/minecraft/com/google/common/util/concurrent/WrappingExecutorService.java new file mode 100644 index 0000000..e2f4b12 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/WrappingExecutorService.java @@ -0,0 +1,166 @@ +package com.google.common.util.concurrent; + +import com.google.common.base.Preconditions; +import com.google.common.base.Throwables; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableList.Builder; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + + + + + + + + + + + + + + + + + + + + + + + + + + + +abstract class WrappingExecutorService + implements ExecutorService +{ + private final ExecutorService delegate; + + protected WrappingExecutorService(ExecutorService delegate) + { + this.delegate = ((ExecutorService)Preconditions.checkNotNull(delegate)); + } + + + + + + protected abstract Callable wrapTask(Callable paramCallable); + + + + + + protected Runnable wrapTask(Runnable command) + { + final Callable wrapped = wrapTask(Executors.callable(command, null)); + + new Runnable() { + public void run() { + try { + wrapped.call(); + } catch (Exception e) { + Throwables.propagate(e); + } + } + }; + } + + + + + + + private final ImmutableList> wrapTasks(Collection> tasks) + { + ImmutableList.Builder> builder = ImmutableList.builder(); + for (Callable task : tasks) { + builder.add(wrapTask(task)); + } + return builder.build(); + } + + + public final void execute(Runnable command) + { + delegate.execute(wrapTask(command)); + } + + public final Future submit(Callable task) + { + return delegate.submit(wrapTask((Callable)Preconditions.checkNotNull(task))); + } + + public final Future submit(Runnable task) + { + return delegate.submit(wrapTask(task)); + } + + public final Future submit(Runnable task, T result) + { + return delegate.submit(wrapTask(task), result); + } + + public final List> invokeAll(Collection> tasks) + throws InterruptedException + { + return delegate.invokeAll(wrapTasks(tasks)); + } + + + public final List> invokeAll(Collection> tasks, long timeout, TimeUnit unit) + throws InterruptedException + { + return delegate.invokeAll(wrapTasks(tasks), timeout, unit); + } + + public final T invokeAny(Collection> tasks) + throws InterruptedException, ExecutionException + { + return delegate.invokeAny(wrapTasks(tasks)); + } + + + public final T invokeAny(Collection> tasks, long timeout, TimeUnit unit) + throws InterruptedException, ExecutionException, TimeoutException + { + return delegate.invokeAny(wrapTasks(tasks), timeout, unit); + } + + + + public final void shutdown() + { + delegate.shutdown(); + } + + public final List shutdownNow() + { + return delegate.shutdownNow(); + } + + public final boolean isShutdown() + { + return delegate.isShutdown(); + } + + public final boolean isTerminated() + { + return delegate.isTerminated(); + } + + public final boolean awaitTermination(long timeout, TimeUnit unit) + throws InterruptedException + { + return delegate.awaitTermination(timeout, unit); + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/WrappingScheduledExecutorService.java b/src/minecraft/com/google/common/util/concurrent/WrappingScheduledExecutorService.java new file mode 100644 index 0000000..04f25b7 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/WrappingScheduledExecutorService.java @@ -0,0 +1,61 @@ +package com.google.common.util.concurrent; + +import java.util.concurrent.Callable; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + + + + + + + + + + + + + + + + + + + + + +abstract class WrappingScheduledExecutorService + extends WrappingExecutorService + implements ScheduledExecutorService +{ + final ScheduledExecutorService delegate; + + protected WrappingScheduledExecutorService(ScheduledExecutorService delegate) + { + super(delegate); + this.delegate = delegate; + } + + public final ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit) + { + return delegate.schedule(wrapTask(command), delay, unit); + } + + public final ScheduledFuture schedule(Callable task, long delay, TimeUnit unit) + { + return delegate.schedule(wrapTask(task), delay, unit); + } + + + public final ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) + { + return delegate.scheduleAtFixedRate(wrapTask(command), initialDelay, period, unit); + } + + + public final ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) + { + return delegate.scheduleWithFixedDelay(wrapTask(command), initialDelay, delay, unit); + } +} diff --git a/src/minecraft/com/google/common/util/concurrent/package-info.java b/src/minecraft/com/google/common/util/concurrent/package-info.java new file mode 100644 index 0000000..7495a00 --- /dev/null +++ b/src/minecraft/com/google/common/util/concurrent/package-info.java @@ -0,0 +1,6 @@ +package com.google.common.util.concurrent; + +import javax.annotation.ParametersAreNonnullByDefault; + +@ParametersAreNonnullByDefault +abstract interface package-info {} diff --git a/src/minecraft/com/google/common/xml/XmlEscapers.java b/src/minecraft/com/google/common/xml/XmlEscapers.java new file mode 100644 index 0000000..c77f27c --- /dev/null +++ b/src/minecraft/com/google/common/xml/XmlEscapers.java @@ -0,0 +1,149 @@ +package com.google.common.xml; + +import com.google.common.annotations.Beta; +import com.google.common.annotations.GwtCompatible; +import com.google.common.escape.Escaper; +import com.google.common.escape.Escapers; +import com.google.common.escape.Escapers.Builder; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@Beta +@GwtCompatible +public class XmlEscapers +{ + private static final char MIN_ASCII_CONTROL_CHAR = '\000'; + private static final char MAX_ASCII_CONTROL_CHAR = '\037'; + private static final Escaper XML_ESCAPER; + private static final Escaper XML_CONTENT_ESCAPER; + private static final Escaper XML_ATTRIBUTE_ESCAPER; + + private XmlEscapers() {} + + public static Escaper xmlContentEscaper() + { + return XML_CONTENT_ESCAPER; + } + + + + + + + + + + + + + + + + + + public static Escaper xmlAttributeEscaper() + { + return XML_ATTRIBUTE_ESCAPER; + } + + + + static + { + Escapers.Builder builder = Escapers.builder(); + + + + + builder.setSafeRange('\000', 65535); + + builder.setUnsafeReplacement(""); + + + + + + + for (char c = '\000'; c <= '\037'; c = (char)(c + '\001')) { + if ((c != '\t') && (c != '\n') && (c != '\r')) { + builder.addEscape(c, ""); + } + } + + + + builder.addEscape('&', "&"); + builder.addEscape('<', "<"); + builder.addEscape('>', ">"); + XML_CONTENT_ESCAPER = builder.build(); + builder.addEscape('\'', "'"); + builder.addEscape('"', """); + XML_ESCAPER = builder.build(); + builder.addEscape('\t', " "); + builder.addEscape('\n', " "); + builder.addEscape('\r', " "); + XML_ATTRIBUTE_ESCAPER = builder.build(); + } +} diff --git a/src/minecraft/com/google/common/xml/package-info.java b/src/minecraft/com/google/common/xml/package-info.java new file mode 100644 index 0000000..9086dc1 --- /dev/null +++ b/src/minecraft/com/google/common/xml/package-info.java @@ -0,0 +1,6 @@ +package com.google.common.xml; + +import javax.annotation.ParametersAreNonnullByDefault; + +@ParametersAreNonnullByDefault +abstract interface package-info {} diff --git a/src/minecraft/com/google/gson/DefaultDateTypeAdapter.java b/src/minecraft/com/google/gson/DefaultDateTypeAdapter.java new file mode 100644 index 0000000..c761c33 --- /dev/null +++ b/src/minecraft/com/google/gson/DefaultDateTypeAdapter.java @@ -0,0 +1,119 @@ +package com.google.gson; + +import java.lang.reflect.Type; +import java.sql.Timestamp; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Locale; +import java.util.TimeZone; + + + + + + + + + + + + + + + + + + + + + + + + + +final class DefaultDateTypeAdapter + implements JsonSerializer, JsonDeserializer +{ + private final DateFormat enUsFormat; + private final DateFormat localFormat; + private final DateFormat iso8601Format; + + DefaultDateTypeAdapter() + { + this(DateFormat.getDateTimeInstance(2, 2, Locale.US), DateFormat.getDateTimeInstance(2, 2)); + } + + DefaultDateTypeAdapter(String datePattern) + { + this(new SimpleDateFormat(datePattern, Locale.US), new SimpleDateFormat(datePattern)); + } + + DefaultDateTypeAdapter(int style) { + this(DateFormat.getDateInstance(style, Locale.US), DateFormat.getDateInstance(style)); + } + + public DefaultDateTypeAdapter(int dateStyle, int timeStyle) { + this(DateFormat.getDateTimeInstance(dateStyle, timeStyle, Locale.US), DateFormat.getDateTimeInstance(dateStyle, timeStyle)); + } + + DefaultDateTypeAdapter(DateFormat enUsFormat, DateFormat localFormat) + { + this.enUsFormat = enUsFormat; + this.localFormat = localFormat; + iso8601Format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); + iso8601Format.setTimeZone(TimeZone.getTimeZone("UTC")); + } + + + public JsonElement serialize(java.util.Date src, Type typeOfSrc, JsonSerializationContext context) + { + synchronized (localFormat) { + String dateFormatAsString = enUsFormat.format(src); + return new JsonPrimitive(dateFormatAsString); + } + } + + public java.util.Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException + { + if (!(json instanceof JsonPrimitive)) { + throw new JsonParseException("The date should be a string value"); + } + java.util.Date date = deserializeToDate(json); + if (typeOfT == java.util.Date.class) + return date; + if (typeOfT == Timestamp.class) + return new Timestamp(date.getTime()); + if (typeOfT == java.sql.Date.class) { + return new java.sql.Date(date.getTime()); + } + throw new IllegalArgumentException(getClass() + " cannot deserialize to " + typeOfT); + } + + private java.util.Date deserializeToDate(JsonElement json) + { + synchronized (localFormat) { + try { + return localFormat.parse(json.getAsString()); + } + catch (ParseException ignored) { + try { + return enUsFormat.parse(json.getAsString()); + } + catch (ParseException ignored) { + try { + return iso8601Format.parse(json.getAsString()); + } catch (ParseException e) { + throw new JsonSyntaxException(json.getAsString(), e); + } + } + } + } + } + + public String toString() { StringBuilder sb = new StringBuilder(); + sb.append(DefaultDateTypeAdapter.class.getSimpleName()); + sb.append('(').append(localFormat.getClass().getSimpleName()).append(')'); + return sb.toString(); + } +} diff --git a/src/minecraft/com/google/gson/ExclusionStrategy.java b/src/minecraft/com/google/gson/ExclusionStrategy.java new file mode 100644 index 0000000..99fb164 --- /dev/null +++ b/src/minecraft/com/google/gson/ExclusionStrategy.java @@ -0,0 +1,8 @@ +package com.google.gson; + +public abstract interface ExclusionStrategy +{ + public abstract boolean shouldSkipField(FieldAttributes paramFieldAttributes); + + public abstract boolean shouldSkipClass(Class paramClass); +} diff --git a/src/minecraft/com/google/gson/FieldAttributes.java b/src/minecraft/com/google/gson/FieldAttributes.java new file mode 100644 index 0000000..69dfed0 --- /dev/null +++ b/src/minecraft/com/google/gson/FieldAttributes.java @@ -0,0 +1,157 @@ +package com.google.gson; + +import com.google.gson.internal..Gson.Preconditions; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Type; +import java.util.Arrays; +import java.util.Collection; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public final class FieldAttributes +{ + private final Field field; + + public FieldAttributes(Field f) + { + .Gson.Preconditions.checkNotNull(f); + field = f; + } + + + + public Class getDeclaringClass() + { + return field.getDeclaringClass(); + } + + + + public String getName() + { + return field.getName(); + } + + + + + + + + + + + + + + + + + public Type getDeclaredType() + { + return field.getGenericType(); + } + + + + + + + + + + + + + + + + + public Class getDeclaredClass() + { + return field.getType(); + } + + + + + + + + public T getAnnotation(Class annotation) + { + return field.getAnnotation(annotation); + } + + + + + + + public Collection getAnnotations() + { + return Arrays.asList(field.getAnnotations()); + } + + + + + + + + + + + public boolean hasModifier(int modifier) + { + return (field.getModifiers() & modifier) != 0; + } + + + + + + + Object get(Object instance) + throws IllegalAccessException + { + return field.get(instance); + } + + + + + + boolean isSynthetic() + { + return field.isSynthetic(); + } +} diff --git a/src/minecraft/com/google/gson/FieldNamingPolicy.java b/src/minecraft/com/google/gson/FieldNamingPolicy.java new file mode 100644 index 0000000..ac98436 --- /dev/null +++ b/src/minecraft/com/google/gson/FieldNamingPolicy.java @@ -0,0 +1,166 @@ +package com.google.gson; + +import java.lang.reflect.Field; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public enum FieldNamingPolicy + implements FieldNamingStrategy +{ + IDENTITY, + + + + + + + + + + + + + + + + UPPER_CAMEL_CASE, + + + + + + + + + + + + + + + + + + + UPPER_CAMEL_CASE_WITH_SPACES, + + + + + + + + + + + + + + + + + + LOWER_CASE_WITH_UNDERSCORES, + + + + + + + + + + + + + + + + + + + + + + + LOWER_CASE_WITH_DASHES; + + + + + private FieldNamingPolicy() {} + + + + private static String separateCamelCase(String name, String separator) + { + StringBuilder translation = new StringBuilder(); + for (int i = 0; i < name.length(); i++) { + char character = name.charAt(i); + if ((Character.isUpperCase(character)) && (translation.length() != 0)) { + translation.append(separator); + } + translation.append(character); + } + return translation.toString(); + } + + + + private static String upperCaseFirstLetter(String name) + { + StringBuilder fieldNameBuilder = new StringBuilder(); + int index = 0; + char firstCharacter = name.charAt(index); + + while ((index < name.length() - 1) && + (!Character.isLetter(firstCharacter))) + { + + + fieldNameBuilder.append(firstCharacter); + firstCharacter = name.charAt(++index); + } + + if (index == name.length()) { + return fieldNameBuilder.toString(); + } + + if (!Character.isUpperCase(firstCharacter)) { + String modifiedTarget = modifyString(Character.toUpperCase(firstCharacter), name, ++index); + return modifiedTarget; + } + return name; + } + + private static String modifyString(char firstCharacter, String srcString, int indexOfSubstring) + { + return indexOfSubstring < srcString.length() ? firstCharacter + srcString.substring(indexOfSubstring) : String.valueOf(firstCharacter); + } +} diff --git a/src/minecraft/com/google/gson/FieldNamingStrategy.java b/src/minecraft/com/google/gson/FieldNamingStrategy.java new file mode 100644 index 0000000..8ac9928 --- /dev/null +++ b/src/minecraft/com/google/gson/FieldNamingStrategy.java @@ -0,0 +1,8 @@ +package com.google.gson; + +import java.lang.reflect.Field; + +public abstract interface FieldNamingStrategy +{ + public abstract String translateName(Field paramField); +} diff --git a/src/minecraft/com/google/gson/Gson.java b/src/minecraft/com/google/gson/Gson.java new file mode 100644 index 0000000..54aba48 --- /dev/null +++ b/src/minecraft/com/google/gson/Gson.java @@ -0,0 +1,900 @@ +package com.google.gson; + +import com.google.gson.internal.ConstructorConstructor; +import com.google.gson.internal.Excluder; +import com.google.gson.internal.Primitives; +import com.google.gson.internal.Streams; +import com.google.gson.internal.bind.ArrayTypeAdapter; +import com.google.gson.internal.bind.CollectionTypeAdapterFactory; +import com.google.gson.internal.bind.DateTypeAdapter; +import com.google.gson.internal.bind.JsonTreeReader; +import com.google.gson.internal.bind.JsonTreeWriter; +import com.google.gson.internal.bind.MapTypeAdapterFactory; +import com.google.gson.internal.bind.ObjectTypeAdapter; +import com.google.gson.internal.bind.ReflectiveTypeAdapterFactory; +import com.google.gson.internal.bind.SqlDateTypeAdapter; +import com.google.gson.internal.bind.TimeTypeAdapter; +import com.google.gson.internal.bind.TypeAdapters; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import com.google.gson.stream.MalformedJsonException; +import java.io.EOFException; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; +import java.lang.reflect.Type; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public final class Gson +{ + static final boolean DEFAULT_JSON_NON_EXECUTABLE = false; + private static final String JSON_NON_EXECUTABLE_PREFIX = ")]}'\n"; + private final ThreadLocal, FutureTypeAdapter>> calls = new ThreadLocal(); + + + private final Map, TypeAdapter> typeTokenCache = Collections.synchronizedMap(new HashMap()); + + private final List factories; + + private final ConstructorConstructor constructorConstructor; + + private final boolean serializeNulls; + + private final boolean htmlSafe; + private final boolean generateNonExecutableJson; + private final boolean prettyPrinting; + final JsonDeserializationContext deserializationContext = new JsonDeserializationContext() + { + public T deserialize(JsonElement json, Type typeOfT) throws JsonParseException { + return fromJson(json, typeOfT); + } + }; + + final JsonSerializationContext serializationContext = new JsonSerializationContext() { + public JsonElement serialize(Object src) { + return toJsonTree(src); + } + + public JsonElement serialize(Object src, Type typeOfSrc) { return toJsonTree(src, typeOfSrc); } + }; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public Gson() + { + this(Excluder.DEFAULT, FieldNamingPolicy.IDENTITY, Collections.emptyMap(), false, false, false, true, false, false, LongSerializationPolicy.DEFAULT, Collections.emptyList()); + } + + + + + + + + + Gson(Excluder excluder, FieldNamingStrategy fieldNamingPolicy, Map> instanceCreators, boolean serializeNulls, boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe, boolean prettyPrinting, boolean serializeSpecialFloatingPointValues, LongSerializationPolicy longSerializationPolicy, List typeAdapterFactories) + { + constructorConstructor = new ConstructorConstructor(instanceCreators); + this.serializeNulls = serializeNulls; + generateNonExecutableJson = generateNonExecutableGson; + this.htmlSafe = htmlSafe; + this.prettyPrinting = prettyPrinting; + + List factories = new ArrayList(); + + + factories.add(TypeAdapters.JSON_ELEMENT_FACTORY); + factories.add(ObjectTypeAdapter.FACTORY); + + + factories.add(excluder); + + + factories.addAll(typeAdapterFactories); + + + factories.add(TypeAdapters.STRING_FACTORY); + factories.add(TypeAdapters.INTEGER_FACTORY); + factories.add(TypeAdapters.BOOLEAN_FACTORY); + factories.add(TypeAdapters.BYTE_FACTORY); + factories.add(TypeAdapters.SHORT_FACTORY); + factories.add(TypeAdapters.newFactory(Long.TYPE, Long.class, longAdapter(longSerializationPolicy))); + + factories.add(TypeAdapters.newFactory(Double.TYPE, Double.class, doubleAdapter(serializeSpecialFloatingPointValues))); + + factories.add(TypeAdapters.newFactory(Float.TYPE, Float.class, floatAdapter(serializeSpecialFloatingPointValues))); + + factories.add(TypeAdapters.NUMBER_FACTORY); + factories.add(TypeAdapters.CHARACTER_FACTORY); + factories.add(TypeAdapters.STRING_BUILDER_FACTORY); + factories.add(TypeAdapters.STRING_BUFFER_FACTORY); + factories.add(TypeAdapters.newFactory(BigDecimal.class, TypeAdapters.BIG_DECIMAL)); + factories.add(TypeAdapters.newFactory(BigInteger.class, TypeAdapters.BIG_INTEGER)); + factories.add(TypeAdapters.URL_FACTORY); + factories.add(TypeAdapters.URI_FACTORY); + factories.add(TypeAdapters.UUID_FACTORY); + factories.add(TypeAdapters.LOCALE_FACTORY); + factories.add(TypeAdapters.INET_ADDRESS_FACTORY); + factories.add(TypeAdapters.BIT_SET_FACTORY); + factories.add(DateTypeAdapter.FACTORY); + factories.add(TypeAdapters.CALENDAR_FACTORY); + factories.add(TimeTypeAdapter.FACTORY); + factories.add(SqlDateTypeAdapter.FACTORY); + factories.add(TypeAdapters.TIMESTAMP_FACTORY); + factories.add(ArrayTypeAdapter.FACTORY); + factories.add(TypeAdapters.ENUM_FACTORY); + factories.add(TypeAdapters.CLASS_FACTORY); + + + factories.add(new CollectionTypeAdapterFactory(constructorConstructor)); + factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization)); + factories.add(new ReflectiveTypeAdapterFactory(constructorConstructor, fieldNamingPolicy, excluder)); + + + this.factories = Collections.unmodifiableList(factories); + } + + private TypeAdapter doubleAdapter(boolean serializeSpecialFloatingPointValues) { + if (serializeSpecialFloatingPointValues) { + return TypeAdapters.DOUBLE; + } + new TypeAdapter() { + public Double read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + return Double.valueOf(in.nextDouble()); + } + + public void write(JsonWriter out, Number value) throws IOException { if (value == null) { + out.nullValue(); + return; + } + double doubleValue = value.doubleValue(); + Gson.this.checkValidFloatingPoint(doubleValue); + out.value(value); + } + }; + } + + private TypeAdapter floatAdapter(boolean serializeSpecialFloatingPointValues) { + if (serializeSpecialFloatingPointValues) { + return TypeAdapters.FLOAT; + } + new TypeAdapter() { + public Float read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + return Float.valueOf((float)in.nextDouble()); + } + + public void write(JsonWriter out, Number value) throws IOException { if (value == null) { + out.nullValue(); + return; + } + float floatValue = value.floatValue(); + Gson.this.checkValidFloatingPoint(floatValue); + out.value(value); + } + }; + } + + private void checkValidFloatingPoint(double value) { + if ((Double.isNaN(value)) || (Double.isInfinite(value))) { + throw new IllegalArgumentException(value + " is not a valid double value as per JSON specification. To override this" + " behavior, use GsonBuilder.serializeSpecialFloatingPointValues() method."); + } + } + + + private TypeAdapter longAdapter(LongSerializationPolicy longSerializationPolicy) + { + if (longSerializationPolicy == LongSerializationPolicy.DEFAULT) { + return TypeAdapters.LONG; + } + new TypeAdapter() { + public Number read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + return Long.valueOf(in.nextLong()); + } + + public void write(JsonWriter out, Number value) throws IOException { if (value == null) { + out.nullValue(); + return; + } + out.value(value.toString()); + } + }; + } + + + + + + + + public TypeAdapter getAdapter(TypeToken type) + { + TypeAdapter cached = (TypeAdapter)typeTokenCache.get(type); + if (cached != null) { + return cached; + } + + Map, FutureTypeAdapter> threadCalls = (Map)calls.get(); + boolean requiresThreadLocalCleanup = false; + if (threadCalls == null) { + threadCalls = new HashMap(); + calls.set(threadCalls); + requiresThreadLocalCleanup = true; + } + + + FutureTypeAdapter ongoingCall = (FutureTypeAdapter)threadCalls.get(type); + if (ongoingCall != null) { + return ongoingCall; + } + try + { + FutureTypeAdapter call = new FutureTypeAdapter(); + threadCalls.put(type, call); + + for (TypeAdapterFactory factory : factories) { + TypeAdapter candidate = factory.create(this, type); + if (candidate != null) { + call.setDelegate(candidate); + typeTokenCache.put(type, candidate); + return candidate; + } + } + throw new IllegalArgumentException("GSON cannot handle " + type); + } finally { + threadCalls.remove(type); + + if (requiresThreadLocalCleanup) { + calls.remove(); + } + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public TypeAdapter getDelegateAdapter(TypeAdapterFactory skipPast, TypeToken type) + { + boolean skipPastFound = false; + + for (TypeAdapterFactory factory : factories) { + if (!skipPastFound) { + if (factory == skipPast) { + skipPastFound = true; + } + } + else + { + TypeAdapter candidate = factory.create(this, type); + if (candidate != null) + return candidate; + } + } + throw new IllegalArgumentException("GSON cannot serialize " + type); + } + + + + + + + public TypeAdapter getAdapter(Class type) + { + return getAdapter(TypeToken.get(type)); + } + + + + + + + + + + + + + + public JsonElement toJsonTree(Object src) + { + if (src == null) { + return JsonNull.INSTANCE; + } + return toJsonTree(src, src.getClass()); + } + + + + + + + + + + + + + + + + + public JsonElement toJsonTree(Object src, Type typeOfSrc) + { + JsonTreeWriter writer = new JsonTreeWriter(); + toJson(src, typeOfSrc, writer); + return writer.get(); + } + + + + + + + + + + + + + + public String toJson(Object src) + { + if (src == null) { + return toJson(JsonNull.INSTANCE); + } + return toJson(src, src.getClass()); + } + + + + + + + + + + + + + + + + public String toJson(Object src, Type typeOfSrc) + { + StringWriter writer = new StringWriter(); + toJson(src, typeOfSrc, writer); + return writer.toString(); + } + + + + + + + + + + + + + + public void toJson(Object src, Appendable writer) + throws JsonIOException + { + if (src != null) { + toJson(src, src.getClass(), writer); + } else { + toJson(JsonNull.INSTANCE, writer); + } + } + + + + + + + + + + + + + + + public void toJson(Object src, Type typeOfSrc, Appendable writer) + throws JsonIOException + { + try + { + JsonWriter jsonWriter = newJsonWriter(Streams.writerForAppendable(writer)); + toJson(src, typeOfSrc, jsonWriter); + } catch (IOException e) { + throw new JsonIOException(e); + } + } + + + + + + public void toJson(Object src, Type typeOfSrc, JsonWriter writer) + throws JsonIOException + { + TypeAdapter adapter = getAdapter(TypeToken.get(typeOfSrc)); + boolean oldLenient = writer.isLenient(); + writer.setLenient(true); + boolean oldHtmlSafe = writer.isHtmlSafe(); + writer.setHtmlSafe(htmlSafe); + boolean oldSerializeNulls = writer.getSerializeNulls(); + writer.setSerializeNulls(serializeNulls); + try { + adapter.write(writer, src); + } catch (IOException e) { + throw new JsonIOException(e); + } finally { + writer.setLenient(oldLenient); + writer.setHtmlSafe(oldHtmlSafe); + writer.setSerializeNulls(oldSerializeNulls); + } + } + + + + + + + + public String toJson(JsonElement jsonElement) + { + StringWriter writer = new StringWriter(); + toJson(jsonElement, writer); + return writer.toString(); + } + + + + + + + public void toJson(JsonElement jsonElement, Appendable writer) + throws JsonIOException + { + try + { + JsonWriter jsonWriter = newJsonWriter(Streams.writerForAppendable(writer)); + toJson(jsonElement, jsonWriter); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + + + private JsonWriter newJsonWriter(Writer writer) + throws IOException + { + if (generateNonExecutableJson) { + writer.write(")]}'\n"); + } + JsonWriter jsonWriter = new JsonWriter(writer); + if (prettyPrinting) { + jsonWriter.setIndent(" "); + } + jsonWriter.setSerializeNulls(serializeNulls); + return jsonWriter; + } + + + + public void toJson(JsonElement jsonElement, JsonWriter writer) + throws JsonIOException + { + boolean oldLenient = writer.isLenient(); + writer.setLenient(true); + boolean oldHtmlSafe = writer.isHtmlSafe(); + writer.setHtmlSafe(htmlSafe); + boolean oldSerializeNulls = writer.getSerializeNulls(); + writer.setSerializeNulls(serializeNulls); + try { + Streams.write(jsonElement, writer); + } catch (IOException e) { + throw new JsonIOException(e); + } finally { + writer.setLenient(oldLenient); + writer.setHtmlSafe(oldHtmlSafe); + writer.setSerializeNulls(oldSerializeNulls); + } + } + + + + + + + + + + + + + + + + + public T fromJson(String json, Class classOfT) + throws JsonSyntaxException + { + Object object = fromJson(json, classOfT); + return Primitives.wrap(classOfT).cast(object); + } + + + + + + + + + + + + + + + + + + + public T fromJson(String json, Type typeOfT) + throws JsonSyntaxException + { + if (json == null) { + return null; + } + StringReader reader = new StringReader(json); + T target = fromJson(reader, typeOfT); + return target; + } + + + + + + + + + + + + + + + + + + public T fromJson(Reader json, Class classOfT) + throws JsonSyntaxException, JsonIOException + { + JsonReader jsonReader = new JsonReader(json); + Object object = fromJson(jsonReader, classOfT); + assertFullConsumption(object, jsonReader); + return Primitives.wrap(classOfT).cast(object); + } + + + + + + + + + + + + + + + + + + + + public T fromJson(Reader json, Type typeOfT) + throws JsonIOException, JsonSyntaxException + { + JsonReader jsonReader = new JsonReader(json); + T object = fromJson(jsonReader, typeOfT); + assertFullConsumption(object, jsonReader); + return object; + } + + private static void assertFullConsumption(Object obj, JsonReader reader) { + try { + if ((obj != null) && (reader.peek() != JsonToken.END_DOCUMENT)) { + throw new JsonIOException("JSON document was not fully consumed."); + } + } catch (MalformedJsonException e) { + throw new JsonSyntaxException(e); + } catch (IOException e) { + throw new JsonIOException(e); + } + } + + + + + + + + + public T fromJson(JsonReader reader, Type typeOfT) + throws JsonIOException, JsonSyntaxException + { + boolean isEmpty = true; + boolean oldLenient = reader.isLenient(); + reader.setLenient(true); + try { + reader.peek(); + isEmpty = false; + TypeToken typeToken = TypeToken.get(typeOfT); + typeAdapter = getAdapter(typeToken); + T object = typeAdapter.read(reader); + return object; + } + catch (EOFException e) + { + TypeAdapter typeAdapter; + + if (isEmpty) { + return null; + } + throw new JsonSyntaxException(e); + } catch (IllegalStateException e) { + throw new JsonSyntaxException(e); + } + catch (IOException e) { + throw new JsonSyntaxException(e); + } finally { + reader.setLenient(oldLenient); + } + } + + + + + + + + + + + + + + + + public T fromJson(JsonElement json, Class classOfT) + throws JsonSyntaxException + { + Object object = fromJson(json, classOfT); + return Primitives.wrap(classOfT).cast(object); + } + + + + + + + + + + + + + + + + + + + public T fromJson(JsonElement json, Type typeOfT) + throws JsonSyntaxException + { + if (json == null) { + return null; + } + return fromJson(new JsonTreeReader(json), typeOfT); + } + + static class FutureTypeAdapter extends TypeAdapter { private TypeAdapter delegate; + + FutureTypeAdapter() {} + + public void setDelegate(TypeAdapter typeAdapter) { if (delegate != null) { + throw new AssertionError(); + } + delegate = typeAdapter; + } + + public T read(JsonReader in) throws IOException { + if (delegate == null) { + throw new IllegalStateException(); + } + return delegate.read(in); + } + + public void write(JsonWriter out, T value) throws IOException { + if (delegate == null) { + throw new IllegalStateException(); + } + delegate.write(out, value); + } + } + + public String toString() + { + return "{serializeNulls:" + serializeNulls + "factories:" + factories + ",instanceCreators:" + constructorConstructor + "}"; + } +} diff --git a/src/minecraft/com/google/gson/GsonBuilder.java b/src/minecraft/com/google/gson/GsonBuilder.java new file mode 100644 index 0000000..e6cd2d2 --- /dev/null +++ b/src/minecraft/com/google/gson/GsonBuilder.java @@ -0,0 +1,566 @@ +package com.google.gson; + +import com.google.gson.internal..Gson.Preconditions; +import com.google.gson.internal.Excluder; +import com.google.gson.internal.bind.TypeAdapters; +import com.google.gson.reflect.TypeToken; +import java.lang.reflect.Type; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public final class GsonBuilder +{ + private Excluder excluder = Excluder.DEFAULT; + private LongSerializationPolicy longSerializationPolicy = LongSerializationPolicy.DEFAULT; + private FieldNamingStrategy fieldNamingPolicy = FieldNamingPolicy.IDENTITY; + private final Map> instanceCreators = new HashMap(); + + private final List factories = new ArrayList(); + + private final List hierarchyFactories = new ArrayList(); + private boolean serializeNulls; + private String datePattern; + private int dateStyle = 2; + private int timeStyle = 2; + private boolean complexMapKeySerialization; + private boolean serializeSpecialFloatingPointValues; + private boolean escapeHtmlChars = true; + + + + + private boolean prettyPrinting; + + + + private boolean generateNonExecutableJson; + + + + + public GsonBuilder() {} + + + + + public GsonBuilder setVersion(double ignoreVersionsAfter) + { + excluder = excluder.withVersion(ignoreVersionsAfter); + return this; + } + + + + + + + + + + + + public GsonBuilder excludeFieldsWithModifiers(int... modifiers) + { + excluder = excluder.withModifiers(modifiers); + return this; + } + + + + + + + + + + public GsonBuilder generateNonExecutableJson() + { + generateNonExecutableJson = true; + return this; + } + + + + + + + public GsonBuilder excludeFieldsWithoutExposeAnnotation() + { + excluder = excluder.excludeFieldsWithoutExposeAnnotation(); + return this; + } + + + + + + + + public GsonBuilder serializeNulls() + { + serializeNulls = true; + return this; + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public GsonBuilder enableComplexMapKeySerialization() + { + complexMapKeySerialization = true; + return this; + } + + + + + + + public GsonBuilder disableInnerClassSerialization() + { + excluder = excluder.disableInnerClassSerialization(); + return this; + } + + + + + + + + + public GsonBuilder setLongSerializationPolicy(LongSerializationPolicy serializationPolicy) + { + longSerializationPolicy = serializationPolicy; + return this; + } + + + + + + + + + public GsonBuilder setFieldNamingPolicy(FieldNamingPolicy namingConvention) + { + fieldNamingPolicy = namingConvention; + return this; + } + + + + + + + + + public GsonBuilder setFieldNamingStrategy(FieldNamingStrategy fieldNamingStrategy) + { + fieldNamingPolicy = fieldNamingStrategy; + return this; + } + + + + + + + + + + + public GsonBuilder setExclusionStrategies(ExclusionStrategy... strategies) + { + for (ExclusionStrategy strategy : strategies) { + excluder = excluder.withExclusionStrategy(strategy, true, true); + } + return this; + } + + + + + + + + + + + + + public GsonBuilder addSerializationExclusionStrategy(ExclusionStrategy strategy) + { + excluder = excluder.withExclusionStrategy(strategy, true, false); + return this; + } + + + + + + + + + + + + + public GsonBuilder addDeserializationExclusionStrategy(ExclusionStrategy strategy) + { + excluder = excluder.withExclusionStrategy(strategy, false, true); + return this; + } + + + + + + + public GsonBuilder setPrettyPrinting() + { + prettyPrinting = true; + return this; + } + + + + + + + + public GsonBuilder disableHtmlEscaping() + { + escapeHtmlChars = false; + return this; + } + + + + + + + + + + + + + + + + + + public GsonBuilder setDateFormat(String pattern) + { + datePattern = pattern; + return this; + } + + + + + + + + + + + + + + + public GsonBuilder setDateFormat(int style) + { + dateStyle = style; + datePattern = null; + return this; + } + + + + + + + + + + + + + + + + public GsonBuilder setDateFormat(int dateStyle, int timeStyle) + { + this.dateStyle = dateStyle; + this.timeStyle = timeStyle; + datePattern = null; + return this; + } + + + + + + + + + + + + + + + + + + public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) + { + .Gson.Preconditions.checkArgument(((typeAdapter instanceof JsonSerializer)) || ((typeAdapter instanceof JsonDeserializer)) || ((typeAdapter instanceof InstanceCreator)) || ((typeAdapter instanceof TypeAdapter))); + + + + if ((typeAdapter instanceof InstanceCreator)) { + instanceCreators.put(type, (InstanceCreator)typeAdapter); + } + if (((typeAdapter instanceof JsonSerializer)) || ((typeAdapter instanceof JsonDeserializer))) { + TypeToken typeToken = TypeToken.get(type); + factories.add(TreeTypeAdapter.newFactoryWithMatchRawType(typeToken, typeAdapter)); + } + if ((typeAdapter instanceof TypeAdapter)) { + factories.add(TypeAdapters.newFactory(TypeToken.get(type), (TypeAdapter)typeAdapter)); + } + return this; + } + + + + + + + + + public GsonBuilder registerTypeAdapterFactory(TypeAdapterFactory factory) + { + factories.add(factory); + return this; + } + + + + + + + + + + + + + + + + public GsonBuilder registerTypeHierarchyAdapter(Class baseType, Object typeAdapter) + { + .Gson.Preconditions.checkArgument(((typeAdapter instanceof JsonSerializer)) || ((typeAdapter instanceof JsonDeserializer)) || ((typeAdapter instanceof TypeAdapter))); + + + if (((typeAdapter instanceof JsonDeserializer)) || ((typeAdapter instanceof JsonSerializer))) { + hierarchyFactories.add(0, TreeTypeAdapter.newTypeHierarchyFactory(baseType, typeAdapter)); + } + + if ((typeAdapter instanceof TypeAdapter)) { + factories.add(TypeAdapters.newTypeHierarchyFactory(baseType, (TypeAdapter)typeAdapter)); + } + return this; + } + + + + + + + + + + + + + + + + + + + + + public GsonBuilder serializeSpecialFloatingPointValues() + { + serializeSpecialFloatingPointValues = true; + return this; + } + + + + + + + public Gson create() + { + List factories = new ArrayList(); + factories.addAll(this.factories); + Collections.reverse(factories); + factories.addAll(hierarchyFactories); + addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, factories); + + return new Gson(excluder, fieldNamingPolicy, instanceCreators, serializeNulls, complexMapKeySerialization, generateNonExecutableJson, escapeHtmlChars, prettyPrinting, serializeSpecialFloatingPointValues, longSerializationPolicy, factories); + } + + + + private void addTypeAdaptersForDate(String datePattern, int dateStyle, int timeStyle, List factories) + { + DefaultDateTypeAdapter dateTypeAdapter; + + if ((datePattern != null) && (!"".equals(datePattern.trim()))) { + dateTypeAdapter = new DefaultDateTypeAdapter(datePattern); } else { DefaultDateTypeAdapter dateTypeAdapter; + if ((dateStyle != 2) && (timeStyle != 2)) + dateTypeAdapter = new DefaultDateTypeAdapter(dateStyle, timeStyle); else { + return; + } + } + DefaultDateTypeAdapter dateTypeAdapter; + factories.add(TreeTypeAdapter.newFactory(TypeToken.get(java.util.Date.class), dateTypeAdapter)); + factories.add(TreeTypeAdapter.newFactory(TypeToken.get(Timestamp.class), dateTypeAdapter)); + factories.add(TreeTypeAdapter.newFactory(TypeToken.get(java.sql.Date.class), dateTypeAdapter)); + } +} diff --git a/src/minecraft/com/google/gson/InstanceCreator.java b/src/minecraft/com/google/gson/InstanceCreator.java new file mode 100644 index 0000000..1078bcf --- /dev/null +++ b/src/minecraft/com/google/gson/InstanceCreator.java @@ -0,0 +1,8 @@ +package com.google.gson; + +import java.lang.reflect.Type; + +public abstract interface InstanceCreator +{ + public abstract T createInstance(Type paramType); +} diff --git a/src/minecraft/com/google/gson/JsonArray.java b/src/minecraft/com/google/gson/JsonArray.java new file mode 100644 index 0000000..8643734 --- /dev/null +++ b/src/minecraft/com/google/gson/JsonArray.java @@ -0,0 +1,291 @@ +package com.google.gson; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + + + + + + + + + + + + + + + + + + + + + + + + +public final class JsonArray + extends JsonElement + implements Iterable +{ + private final List elements; + + public JsonArray() + { + elements = new ArrayList(); + } + + JsonArray deepCopy() + { + JsonArray result = new JsonArray(); + for (JsonElement element : elements) { + result.add(element.deepCopy()); + } + return result; + } + + + + + + public void add(JsonElement element) + { + if (element == null) { + element = JsonNull.INSTANCE; + } + elements.add(element); + } + + + + + + public void addAll(JsonArray array) + { + elements.addAll(elements); + } + + + + + + public int size() + { + return elements.size(); + } + + + + + + + public Iterator iterator() + { + return elements.iterator(); + } + + + + + + + + + public JsonElement get(int i) + { + return (JsonElement)elements.get(i); + } + + + + + + + + + + public Number getAsNumber() + { + if (elements.size() == 1) { + return ((JsonElement)elements.get(0)).getAsNumber(); + } + throw new IllegalStateException(); + } + + + + + + + + + + public String getAsString() + { + if (elements.size() == 1) { + return ((JsonElement)elements.get(0)).getAsString(); + } + throw new IllegalStateException(); + } + + + + + + + + + + public double getAsDouble() + { + if (elements.size() == 1) { + return ((JsonElement)elements.get(0)).getAsDouble(); + } + throw new IllegalStateException(); + } + + + + + + + + + + + public BigDecimal getAsBigDecimal() + { + if (elements.size() == 1) { + return ((JsonElement)elements.get(0)).getAsBigDecimal(); + } + throw new IllegalStateException(); + } + + + + + + + + + + + public BigInteger getAsBigInteger() + { + if (elements.size() == 1) { + return ((JsonElement)elements.get(0)).getAsBigInteger(); + } + throw new IllegalStateException(); + } + + + + + + + + + + public float getAsFloat() + { + if (elements.size() == 1) { + return ((JsonElement)elements.get(0)).getAsFloat(); + } + throw new IllegalStateException(); + } + + + + + + + + + + public long getAsLong() + { + if (elements.size() == 1) { + return ((JsonElement)elements.get(0)).getAsLong(); + } + throw new IllegalStateException(); + } + + + + + + + + + + public int getAsInt() + { + if (elements.size() == 1) { + return ((JsonElement)elements.get(0)).getAsInt(); + } + throw new IllegalStateException(); + } + + public byte getAsByte() + { + if (elements.size() == 1) { + return ((JsonElement)elements.get(0)).getAsByte(); + } + throw new IllegalStateException(); + } + + public char getAsCharacter() + { + if (elements.size() == 1) { + return ((JsonElement)elements.get(0)).getAsCharacter(); + } + throw new IllegalStateException(); + } + + + + + + + + + + public short getAsShort() + { + if (elements.size() == 1) { + return ((JsonElement)elements.get(0)).getAsShort(); + } + throw new IllegalStateException(); + } + + + + + + + + + + public boolean getAsBoolean() + { + if (elements.size() == 1) { + return ((JsonElement)elements.get(0)).getAsBoolean(); + } + throw new IllegalStateException(); + } + + public boolean equals(Object o) + { + return (o == this) || (((o instanceof JsonArray)) && (elements.equals(elements))); + } + + public int hashCode() + { + return elements.hashCode(); + } +} diff --git a/src/minecraft/com/google/gson/JsonDeserializationContext.java b/src/minecraft/com/google/gson/JsonDeserializationContext.java new file mode 100644 index 0000000..a804478 --- /dev/null +++ b/src/minecraft/com/google/gson/JsonDeserializationContext.java @@ -0,0 +1,9 @@ +package com.google.gson; + +import java.lang.reflect.Type; + +public abstract interface JsonDeserializationContext +{ + public abstract T deserialize(JsonElement paramJsonElement, Type paramType) + throws JsonParseException; +} diff --git a/src/minecraft/com/google/gson/JsonDeserializer.java b/src/minecraft/com/google/gson/JsonDeserializer.java new file mode 100644 index 0000000..4922b49 --- /dev/null +++ b/src/minecraft/com/google/gson/JsonDeserializer.java @@ -0,0 +1,9 @@ +package com.google.gson; + +import java.lang.reflect.Type; + +public abstract interface JsonDeserializer +{ + public abstract T deserialize(JsonElement paramJsonElement, Type paramType, JsonDeserializationContext paramJsonDeserializationContext) + throws JsonParseException; +} diff --git a/src/minecraft/com/google/gson/JsonElement.java b/src/minecraft/com/google/gson/JsonElement.java new file mode 100644 index 0000000..70cce2d --- /dev/null +++ b/src/minecraft/com/google/gson/JsonElement.java @@ -0,0 +1,330 @@ +package com.google.gson; + +import com.google.gson.internal.Streams; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.io.StringWriter; +import java.math.BigDecimal; +import java.math.BigInteger; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class JsonElement +{ + public JsonElement() {} + + abstract JsonElement deepCopy(); + + public boolean isJsonArray() + { + return this instanceof JsonArray; + } + + + + + + public boolean isJsonObject() + { + return this instanceof JsonObject; + } + + + + + + public boolean isJsonPrimitive() + { + return this instanceof JsonPrimitive; + } + + + + + + + public boolean isJsonNull() + { + return this instanceof JsonNull; + } + + + + + + + + + + public JsonObject getAsJsonObject() + { + if (isJsonObject()) { + return (JsonObject)this; + } + throw new IllegalStateException("Not a JSON Object: " + this); + } + + + + + + + + + + public JsonArray getAsJsonArray() + { + if (isJsonArray()) { + return (JsonArray)this; + } + throw new IllegalStateException("This is not a JSON Array."); + } + + + + + + + + + + public JsonPrimitive getAsJsonPrimitive() + { + if (isJsonPrimitive()) { + return (JsonPrimitive)this; + } + throw new IllegalStateException("This is not a JSON Primitive."); + } + + + + + + + + + + + public JsonNull getAsJsonNull() + { + if (isJsonNull()) { + return (JsonNull)this; + } + throw new IllegalStateException("This is not a JSON Null."); + } + + + + + + + + + + public boolean getAsBoolean() + { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + + + + + + + + + Boolean getAsBooleanWrapper() + { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + + + + + + + + + public Number getAsNumber() + { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + + + + + + + + + public String getAsString() + { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + + + + + + + + + public double getAsDouble() + { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + + + + + + + + + public float getAsFloat() + { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + + + + + + + + + public long getAsLong() + { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + + + + + + + + + public int getAsInt() + { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + + + + + + + + + + public byte getAsByte() + { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + + + + + + + + + + public char getAsCharacter() + { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + + + + + + + + + + public BigDecimal getAsBigDecimal() + { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + + + + + + + + + + public BigInteger getAsBigInteger() + { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + + + + + + + + + public short getAsShort() + { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + + + public String toString() + { + try + { + StringWriter stringWriter = new StringWriter(); + JsonWriter jsonWriter = new JsonWriter(stringWriter); + jsonWriter.setLenient(true); + Streams.write(this, jsonWriter); + return stringWriter.toString(); + } catch (IOException e) { + throw new AssertionError(e); + } + } +} diff --git a/src/minecraft/com/google/gson/JsonIOException.java b/src/minecraft/com/google/gson/JsonIOException.java new file mode 100644 index 0000000..668417d --- /dev/null +++ b/src/minecraft/com/google/gson/JsonIOException.java @@ -0,0 +1,45 @@ +package com.google.gson; + + + + + + + + + + + +public final class JsonIOException + extends JsonParseException +{ + private static final long serialVersionUID = 1L; + + + + + + + + + + + public JsonIOException(String msg) + { + super(msg); + } + + public JsonIOException(String msg, Throwable cause) { + super(msg, cause); + } + + + + + + + public JsonIOException(Throwable cause) + { + super(cause); + } +} diff --git a/src/minecraft/com/google/gson/JsonNull.java b/src/minecraft/com/google/gson/JsonNull.java new file mode 100644 index 0000000..bd4bc07 --- /dev/null +++ b/src/minecraft/com/google/gson/JsonNull.java @@ -0,0 +1,63 @@ +package com.google.gson; + + + + + + + + + + + + + + + + + + + + + + + + + + + +public final class JsonNull + extends JsonElement +{ + public static final JsonNull INSTANCE = new JsonNull(); + + + + + @Deprecated + public JsonNull() {} + + + + + JsonNull deepCopy() + { + return INSTANCE; + } + + + + + public int hashCode() + { + return JsonNull.class.hashCode(); + } + + + + + public boolean equals(Object other) + { + return (this == other) || ((other instanceof JsonNull)); + } +} diff --git a/src/minecraft/com/google/gson/JsonObject.java b/src/minecraft/com/google/gson/JsonObject.java new file mode 100644 index 0000000..7873482 --- /dev/null +++ b/src/minecraft/com/google/gson/JsonObject.java @@ -0,0 +1,195 @@ +package com.google.gson; + +import com.google.gson.internal.LinkedTreeMap; +import java.util.Map.Entry; +import java.util.Set; + + + + + + + + + + + + + + + + + + + + + + + + +public final class JsonObject + extends JsonElement +{ + private final LinkedTreeMap members = new LinkedTreeMap(); + + public JsonObject() {} + + JsonObject deepCopy() { + JsonObject result = new JsonObject(); + for (Map.Entry entry : members.entrySet()) { + result.add((String)entry.getKey(), ((JsonElement)entry.getValue()).deepCopy()); + } + return result; + } + + + + + + + + + public void add(String property, JsonElement value) + { + if (value == null) { + value = JsonNull.INSTANCE; + } + members.put(property, value); + } + + + + + + + + public JsonElement remove(String property) + { + return (JsonElement)members.remove(property); + } + + + + + + + + public void addProperty(String property, String value) + { + add(property, createJsonElement(value)); + } + + + + + + + + public void addProperty(String property, Number value) + { + add(property, createJsonElement(value)); + } + + + + + + + + public void addProperty(String property, Boolean value) + { + add(property, createJsonElement(value)); + } + + + + + + + + public void addProperty(String property, Character value) + { + add(property, createJsonElement(value)); + } + + + + + + + private JsonElement createJsonElement(Object value) + { + return value == null ? JsonNull.INSTANCE : new JsonPrimitive(value); + } + + + + + + + public Set> entrySet() + { + return members.entrySet(); + } + + + + + + + public boolean has(String memberName) + { + return members.containsKey(memberName); + } + + + + + + + public JsonElement get(String memberName) + { + return (JsonElement)members.get(memberName); + } + + + + + + + public JsonPrimitive getAsJsonPrimitive(String memberName) + { + return (JsonPrimitive)members.get(memberName); + } + + + + + + + public JsonArray getAsJsonArray(String memberName) + { + return (JsonArray)members.get(memberName); + } + + + + + + + public JsonObject getAsJsonObject(String memberName) + { + return (JsonObject)members.get(memberName); + } + + public boolean equals(Object o) + { + return (o == this) || (((o instanceof JsonObject)) && (members.equals(members))); + } + + + public int hashCode() + { + return members.hashCode(); + } +} diff --git a/src/minecraft/com/google/gson/JsonParseException.java b/src/minecraft/com/google/gson/JsonParseException.java new file mode 100644 index 0000000..452786d --- /dev/null +++ b/src/minecraft/com/google/gson/JsonParseException.java @@ -0,0 +1,64 @@ +package com.google.gson; + + + + + + + + + + + + + + + + + +public class JsonParseException + extends RuntimeException +{ + static final long serialVersionUID = -4086729973971783390L; + + + + + + + + + + + + + + + + + + public JsonParseException(String msg) + { + super(msg); + } + + + + + + + public JsonParseException(String msg, Throwable cause) + { + super(msg, cause); + } + + + + + + + public JsonParseException(Throwable cause) + { + super(cause); + } +} diff --git a/src/minecraft/com/google/gson/JsonParser.java b/src/minecraft/com/google/gson/JsonParser.java new file mode 100644 index 0000000..65f3d41 --- /dev/null +++ b/src/minecraft/com/google/gson/JsonParser.java @@ -0,0 +1,93 @@ +package com.google.gson; + +import com.google.gson.internal.Streams; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.MalformedJsonException; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public final class JsonParser +{ + public JsonParser() {} + + public JsonElement parse(String json) + throws JsonSyntaxException + { + return parse(new StringReader(json)); + } + + + + + + + public JsonElement parse(Reader json) + throws JsonIOException, JsonSyntaxException + { + try + { + JsonReader jsonReader = new JsonReader(json); + JsonElement element = parse(jsonReader); + if ((!element.isJsonNull()) && (jsonReader.peek() != JsonToken.END_DOCUMENT)) { + throw new JsonSyntaxException("Did not consume the entire document."); + } + return element; + } catch (MalformedJsonException e) { + throw new JsonSyntaxException(e); + } catch (IOException e) { + throw new JsonIOException(e); + } catch (NumberFormatException e) { + throw new JsonSyntaxException(e); + } + } + + + + + + + public JsonElement parse(JsonReader json) + throws JsonIOException, JsonSyntaxException + { + boolean lenient = json.isLenient(); + json.setLenient(true); + try { + return Streams.parse(json); + } catch (StackOverflowError e) { + throw new JsonParseException("Failed parsing JSON source: " + json + " to Json", e); + } catch (OutOfMemoryError e) { + throw new JsonParseException("Failed parsing JSON source: " + json + " to Json", e); + } finally { + json.setLenient(lenient); + } + } +} diff --git a/src/minecraft/com/google/gson/JsonPrimitive.java b/src/minecraft/com/google/gson/JsonPrimitive.java new file mode 100644 index 0000000..b831045 --- /dev/null +++ b/src/minecraft/com/google/gson/JsonPrimitive.java @@ -0,0 +1,341 @@ +package com.google.gson; + +import com.google.gson.internal..Gson.Preconditions; +import com.google.gson.internal.LazilyParsedNumber; +import java.math.BigDecimal; +import java.math.BigInteger; + + + + + + + + + + + + + + + + + + + + + + + + + +public final class JsonPrimitive + extends JsonElement +{ + private static final Class[] PRIMITIVE_TYPES = { Integer.TYPE, Long.TYPE, Short.TYPE, Float.TYPE, Double.TYPE, Byte.TYPE, Boolean.TYPE, Character.TYPE, Integer.class, Long.class, Short.class, Float.class, Double.class, Byte.class, Boolean.class, Character.class }; + + + + + private Object value; + + + + + public JsonPrimitive(Boolean bool) + { + setValue(bool); + } + + + + + + public JsonPrimitive(Number number) + { + setValue(number); + } + + + + + + public JsonPrimitive(String string) + { + setValue(string); + } + + + + + + + public JsonPrimitive(Character c) + { + setValue(c); + } + + + + + + + JsonPrimitive(Object primitive) + { + setValue(primitive); + } + + JsonPrimitive deepCopy() + { + return this; + } + + void setValue(Object primitive) { + if ((primitive instanceof Character)) + { + + char c = ((Character)primitive).charValue(); + value = String.valueOf(c); + } else { + .Gson.Preconditions.checkArgument(((primitive instanceof Number)) || (isPrimitiveOrString(primitive))); + + value = primitive; + } + } + + + + + + public boolean isBoolean() + { + return value instanceof Boolean; + } + + + + + + + Boolean getAsBooleanWrapper() + { + return (Boolean)value; + } + + + + + + + public boolean getAsBoolean() + { + if (isBoolean()) { + return getAsBooleanWrapper().booleanValue(); + } + + return Boolean.parseBoolean(getAsString()); + } + + + + + + + public boolean isNumber() + { + return value instanceof Number; + } + + + + + + + + public Number getAsNumber() + { + return (value instanceof String) ? new LazilyParsedNumber((String)value) : (Number)value; + } + + + + + + public boolean isString() + { + return value instanceof String; + } + + + + + + + public String getAsString() + { + if (isNumber()) + return getAsNumber().toString(); + if (isBoolean()) { + return getAsBooleanWrapper().toString(); + } + return (String)value; + } + + + + + + + + + public double getAsDouble() + { + return isNumber() ? getAsNumber().doubleValue() : Double.parseDouble(getAsString()); + } + + + + + + + + public BigDecimal getAsBigDecimal() + { + return (value instanceof BigDecimal) ? (BigDecimal)value : new BigDecimal(value.toString()); + } + + + + + + + + public BigInteger getAsBigInteger() + { + return (value instanceof BigInteger) ? (BigInteger)value : new BigInteger(value.toString()); + } + + + + + + + + + public float getAsFloat() + { + return isNumber() ? getAsNumber().floatValue() : Float.parseFloat(getAsString()); + } + + + + + + + + public long getAsLong() + { + return isNumber() ? getAsNumber().longValue() : Long.parseLong(getAsString()); + } + + + + + + + + public short getAsShort() + { + return isNumber() ? getAsNumber().shortValue() : Short.parseShort(getAsString()); + } + + + + + + + + public int getAsInt() + { + return isNumber() ? getAsNumber().intValue() : Integer.parseInt(getAsString()); + } + + public byte getAsByte() + { + return isNumber() ? getAsNumber().byteValue() : Byte.parseByte(getAsString()); + } + + public char getAsCharacter() + { + return getAsString().charAt(0); + } + + private static boolean isPrimitiveOrString(Object target) { + if ((target instanceof String)) { + return true; + } + + Class classOfPrimitive = target.getClass(); + for (Class standardPrimitive : PRIMITIVE_TYPES) { + if (standardPrimitive.isAssignableFrom(classOfPrimitive)) { + return true; + } + } + return false; + } + + public int hashCode() + { + if (this.value == null) { + return 31; + } + + if (isIntegral(this)) { + long value = getAsNumber().longValue(); + return (int)(value ^ value >>> 32); + } + if ((this.value instanceof Number)) { + long value = Double.doubleToLongBits(getAsNumber().doubleValue()); + return (int)(value ^ value >>> 32); + } + return this.value.hashCode(); + } + + public boolean equals(Object obj) + { + if (this == obj) { + return true; + } + if ((obj == null) || (getClass() != obj.getClass())) { + return false; + } + JsonPrimitive other = (JsonPrimitive)obj; + if (value == null) { + return value == null; + } + if ((isIntegral(this)) && (isIntegral(other))) { + return getAsNumber().longValue() == other.getAsNumber().longValue(); + } + if (((value instanceof Number)) && ((value instanceof Number))) { + double a = getAsNumber().doubleValue(); + + + double b = other.getAsNumber().doubleValue(); + return (a == b) || ((Double.isNaN(a)) && (Double.isNaN(b))); + } + return value.equals(value); + } + + + + + private static boolean isIntegral(JsonPrimitive primitive) + { + if ((value instanceof Number)) { + Number number = (Number)value; + return ((number instanceof BigInteger)) || ((number instanceof Long)) || ((number instanceof Integer)) || ((number instanceof Short)) || ((number instanceof Byte)); + } + + return false; + } +} diff --git a/src/minecraft/com/google/gson/JsonSerializationContext.java b/src/minecraft/com/google/gson/JsonSerializationContext.java new file mode 100644 index 0000000..3a8cc3d --- /dev/null +++ b/src/minecraft/com/google/gson/JsonSerializationContext.java @@ -0,0 +1,10 @@ +package com.google.gson; + +import java.lang.reflect.Type; + +public abstract interface JsonSerializationContext +{ + public abstract JsonElement serialize(Object paramObject); + + public abstract JsonElement serialize(Object paramObject, Type paramType); +} diff --git a/src/minecraft/com/google/gson/JsonSerializer.java b/src/minecraft/com/google/gson/JsonSerializer.java new file mode 100644 index 0000000..b5d531f --- /dev/null +++ b/src/minecraft/com/google/gson/JsonSerializer.java @@ -0,0 +1,8 @@ +package com.google.gson; + +import java.lang.reflect.Type; + +public abstract interface JsonSerializer +{ + public abstract JsonElement serialize(T paramT, Type paramType, JsonSerializationContext paramJsonSerializationContext); +} diff --git a/src/minecraft/com/google/gson/JsonStreamParser.java b/src/minecraft/com/google/gson/JsonStreamParser.java new file mode 100644 index 0000000..0161fa5 --- /dev/null +++ b/src/minecraft/com/google/gson/JsonStreamParser.java @@ -0,0 +1,122 @@ +package com.google.gson; + +import com.google.gson.internal.Streams; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.MalformedJsonException; +import java.io.EOFException; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.util.Iterator; +import java.util.NoSuchElementException; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public final class JsonStreamParser + implements Iterator +{ + private final JsonReader parser; + private final Object lock; + + public JsonStreamParser(String json) + { + this(new StringReader(json)); + } + + + + + public JsonStreamParser(Reader reader) + { + parser = new JsonReader(reader); + parser.setLenient(true); + lock = new Object(); + } + + + + + + + public JsonElement next() + throws JsonParseException + { + if (!hasNext()) { + throw new NoSuchElementException(); + } + try + { + return Streams.parse(parser); + } catch (StackOverflowError e) { + throw new JsonParseException("Failed parsing JSON source to Json", e); + } catch (OutOfMemoryError e) { + throw new JsonParseException("Failed parsing JSON source to Json", e); + } catch (JsonParseException e) { + throw ((e.getCause() instanceof EOFException) ? new NoSuchElementException() : e); + } + } + + + + + + public boolean hasNext() + { + synchronized (lock) { + try { + return parser.peek() != JsonToken.END_DOCUMENT; + } catch (MalformedJsonException e) { + throw new JsonSyntaxException(e); + } catch (IOException e) { + throw new JsonIOException(e); + } + } + } + + + + + + public void remove() + { + throw new UnsupportedOperationException(); + } +} diff --git a/src/minecraft/com/google/gson/JsonSyntaxException.java b/src/minecraft/com/google/gson/JsonSyntaxException.java new file mode 100644 index 0000000..e10bc66 --- /dev/null +++ b/src/minecraft/com/google/gson/JsonSyntaxException.java @@ -0,0 +1,47 @@ +package com.google.gson; + + + + + + + + + + + +public final class JsonSyntaxException + extends JsonParseException +{ + private static final long serialVersionUID = 1L; + + + + + + + + + + + + public JsonSyntaxException(String msg) + { + super(msg); + } + + public JsonSyntaxException(String msg, Throwable cause) { + super(msg, cause); + } + + + + + + + + public JsonSyntaxException(Throwable cause) + { + super(cause); + } +} diff --git a/src/minecraft/com/google/gson/LongSerializationPolicy.java b/src/minecraft/com/google/gson/LongSerializationPolicy.java new file mode 100644 index 0000000..fc6c36b --- /dev/null +++ b/src/minecraft/com/google/gson/LongSerializationPolicy.java @@ -0,0 +1,10 @@ +package com.google.gson; + +public enum LongSerializationPolicy +{ + DEFAULT, STRING; + + private LongSerializationPolicy() {} + + public abstract JsonElement serialize(Long paramLong); +} diff --git a/src/minecraft/com/google/gson/TreeTypeAdapter.java b/src/minecraft/com/google/gson/TreeTypeAdapter.java new file mode 100644 index 0000000..5fe3565 --- /dev/null +++ b/src/minecraft/com/google/gson/TreeTypeAdapter.java @@ -0,0 +1,137 @@ +package com.google.gson; + +import com.google.gson.internal..Gson.Preconditions; +import com.google.gson.internal.Streams; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; + + + + + + + + + + + + + + + + + + + + + + +final class TreeTypeAdapter + extends TypeAdapter +{ + private final JsonSerializer serializer; + private final JsonDeserializer deserializer; + private final Gson gson; + private final TypeToken typeToken; + private final TypeAdapterFactory skipPast; + private TypeAdapter delegate; + + private TreeTypeAdapter(JsonSerializer serializer, JsonDeserializer deserializer, Gson gson, TypeToken typeToken, TypeAdapterFactory skipPast) + { + this.serializer = serializer; + this.deserializer = deserializer; + this.gson = gson; + this.typeToken = typeToken; + this.skipPast = skipPast; + } + + public T read(JsonReader in) throws IOException { + if (deserializer == null) { + return delegate().read(in); + } + JsonElement value = Streams.parse(in); + if (value.isJsonNull()) { + return null; + } + return deserializer.deserialize(value, typeToken.getType(), gson.deserializationContext); + } + + public void write(JsonWriter out, T value) throws IOException { + if (serializer == null) { + delegate().write(out, value); + return; + } + if (value == null) { + out.nullValue(); + return; + } + JsonElement tree = serializer.serialize(value, typeToken.getType(), gson.serializationContext); + Streams.write(tree, out); + } + + private TypeAdapter delegate() { + TypeAdapter d = delegate; + return this.delegate = gson.getDelegateAdapter(skipPast, typeToken); + } + + + + + + public static TypeAdapterFactory newFactory(TypeToken exactType, Object typeAdapter) + { + return new SingleTypeFactory(typeAdapter, exactType, false, null, null); + } + + + + + + + public static TypeAdapterFactory newFactoryWithMatchRawType(TypeToken exactType, Object typeAdapter) + { + boolean matchRawType = exactType.getType() == exactType.getRawType(); + return new SingleTypeFactory(typeAdapter, exactType, matchRawType, null, null); + } + + + + + + public static TypeAdapterFactory newTypeHierarchyFactory(Class hierarchyType, Object typeAdapter) + { + return new SingleTypeFactory(typeAdapter, null, false, hierarchyType, null); + } + + private static class SingleTypeFactory implements TypeAdapterFactory + { + private final TypeToken exactType; + private final boolean matchRawType; + private final Class hierarchyType; + private final JsonSerializer serializer; + private final JsonDeserializer deserializer; + + private SingleTypeFactory(Object typeAdapter, TypeToken exactType, boolean matchRawType, Class hierarchyType) { + serializer = ((typeAdapter instanceof JsonSerializer) ? (JsonSerializer)typeAdapter : null); + + + deserializer = ((typeAdapter instanceof JsonDeserializer) ? (JsonDeserializer)typeAdapter : null); + + + .Gson.Preconditions.checkArgument((serializer != null) || (deserializer != null)); + this.exactType = exactType; + this.matchRawType = matchRawType; + this.hierarchyType = hierarchyType; + } + + public TypeAdapter create(Gson gson, TypeToken type) + { + boolean matches = exactType != null ? false : (exactType.equals(type)) || ((matchRawType) && (exactType.getType() == type.getRawType())) ? true : hierarchyType.isAssignableFrom(type.getRawType()); + + + return matches ? new TreeTypeAdapter(serializer, deserializer, gson, type, this, null) : null; + } + } +} diff --git a/src/minecraft/com/google/gson/TypeAdapter.java b/src/minecraft/com/google/gson/TypeAdapter.java new file mode 100644 index 0000000..fe7302b --- /dev/null +++ b/src/minecraft/com/google/gson/TypeAdapter.java @@ -0,0 +1,286 @@ +package com.google.gson; + +import com.google.gson.internal.bind.JsonTreeReader; +import com.google.gson.internal.bind.JsonTreeWriter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public abstract class TypeAdapter +{ + public TypeAdapter() {} + + public abstract void write(JsonWriter paramJsonWriter, T paramT) + throws IOException; + + public final void toJson(Writer out, T value) + throws IOException + { + JsonWriter writer = new JsonWriter(out); + write(writer, value); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public final TypeAdapter nullSafe() + { + new TypeAdapter() { + public void write(JsonWriter out, T value) throws IOException { + if (value == null) { + out.nullValue(); + } else + TypeAdapter.this.write(out, value); + } + + public T read(JsonReader reader) throws IOException { + if (reader.peek() == JsonToken.NULL) { + reader.nextNull(); + return null; + } + return TypeAdapter.this.read(reader); + } + }; + } + + + + + + + + + + public final String toJson(T value) + throws IOException + { + StringWriter stringWriter = new StringWriter(); + toJson(stringWriter, value); + return stringWriter.toString(); + } + + + + + + + public final JsonElement toJsonTree(T value) + { + try + { + JsonTreeWriter jsonWriter = new JsonTreeWriter(); + write(jsonWriter, value); + return jsonWriter.get(); + } catch (IOException e) { + throw new JsonIOException(e); + } + } + + + + + + + + public abstract T read(JsonReader paramJsonReader) + throws IOException; + + + + + + + + public final T fromJson(Reader in) + throws IOException + { + JsonReader reader = new JsonReader(in); + return read(reader); + } + + + + + + + + + public final T fromJson(String json) + throws IOException + { + return fromJson(new StringReader(json)); + } + + + + + + public final T fromJsonTree(JsonElement jsonTree) + { + try + { + JsonReader jsonReader = new JsonTreeReader(jsonTree); + return read(jsonReader); + } catch (IOException e) { + throw new JsonIOException(e); + } + } +} diff --git a/src/minecraft/com/google/gson/TypeAdapterFactory.java b/src/minecraft/com/google/gson/TypeAdapterFactory.java new file mode 100644 index 0000000..b240e53 --- /dev/null +++ b/src/minecraft/com/google/gson/TypeAdapterFactory.java @@ -0,0 +1,8 @@ +package com.google.gson; + +import com.google.gson.reflect.TypeToken; + +public abstract interface TypeAdapterFactory +{ + public abstract TypeAdapter create(Gson paramGson, TypeToken paramTypeToken); +} diff --git a/src/minecraft/com/google/gson/annotations/Expose.java b/src/minecraft/com/google/gson/annotations/Expose.java new file mode 100644 index 0000000..ae28be6 --- /dev/null +++ b/src/minecraft/com/google/gson/annotations/Expose.java @@ -0,0 +1,15 @@ +package com.google.gson.annotations; + +import java.lang.annotation.Annotation; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({java.lang.annotation.ElementType.FIELD}) +public @interface Expose +{ + boolean serialize() default true; + + boolean deserialize() default true; +} diff --git a/src/minecraft/com/google/gson/annotations/SerializedName.java b/src/minecraft/com/google/gson/annotations/SerializedName.java new file mode 100644 index 0000000..3a94343 --- /dev/null +++ b/src/minecraft/com/google/gson/annotations/SerializedName.java @@ -0,0 +1,13 @@ +package com.google.gson.annotations; + +import java.lang.annotation.Annotation; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({java.lang.annotation.ElementType.FIELD}) +public @interface SerializedName +{ + String value(); +} diff --git a/src/minecraft/com/google/gson/annotations/Since.java b/src/minecraft/com/google/gson/annotations/Since.java new file mode 100644 index 0000000..19290aa --- /dev/null +++ b/src/minecraft/com/google/gson/annotations/Since.java @@ -0,0 +1,13 @@ +package com.google.gson.annotations; + +import java.lang.annotation.Annotation; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.TYPE}) +public @interface Since +{ + double value(); +} diff --git a/src/minecraft/com/google/gson/annotations/Until.java b/src/minecraft/com/google/gson/annotations/Until.java new file mode 100644 index 0000000..ca5e3b1 --- /dev/null +++ b/src/minecraft/com/google/gson/annotations/Until.java @@ -0,0 +1,13 @@ +package com.google.gson.annotations; + +import java.lang.annotation.Annotation; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.TYPE}) +public @interface Until +{ + double value(); +} diff --git a/src/minecraft/com/google/gson/internal/.java b/src/minecraft/com/google/gson/internal/.java new file mode 100644 index 0000000..ec747fa --- /dev/null +++ b/src/minecraft/com/google/gson/internal/.java @@ -0,0 +1 @@ +null \ No newline at end of file diff --git a/src/minecraft/com/google/gson/internal/ConstructorConstructor.java b/src/minecraft/com/google/gson/internal/ConstructorConstructor.java new file mode 100644 index 0000000..230191d --- /dev/null +++ b/src/minecraft/com/google/gson/internal/ConstructorConstructor.java @@ -0,0 +1,220 @@ +package com.google.gson.internal; + +import com.google.gson.InstanceCreator; +import com.google.gson.JsonIOException; +import com.google.gson.reflect.TypeToken; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collection; +import java.util.EnumSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.Map; +import java.util.Queue; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.TreeMap; +import java.util.TreeSet; + + + + + + + + + + + + + + + + + + + +public final class ConstructorConstructor +{ + private final Map> instanceCreators; + + public ConstructorConstructor(Map> instanceCreators) + { + this.instanceCreators = instanceCreators; + } + + public ObjectConstructor get(TypeToken typeToken) { + final Type type = typeToken.getType(); + Class rawType = typeToken.getRawType(); + + + + + final InstanceCreator typeCreator = (InstanceCreator)instanceCreators.get(type); + if (typeCreator != null) { + new ObjectConstructor() { + public T construct() { + return typeCreator.createInstance(type); + } + }; + } + + + + final InstanceCreator rawTypeCreator = (InstanceCreator)instanceCreators.get(rawType); + + if (rawTypeCreator != null) { + new ObjectConstructor() { + public T construct() { + return rawTypeCreator.createInstance(type); + } + }; + } + + ObjectConstructor defaultConstructor = newDefaultConstructor(rawType); + if (defaultConstructor != null) { + return defaultConstructor; + } + + ObjectConstructor defaultImplementation = newDefaultImplementationConstructor(type, rawType); + if (defaultImplementation != null) { + return defaultImplementation; + } + + + return newUnsafeAllocator(type, rawType); + } + + private ObjectConstructor newDefaultConstructor(Class rawType) { + try { + final Constructor constructor = rawType.getDeclaredConstructor(new Class[0]); + if (!constructor.isAccessible()) { + constructor.setAccessible(true); + } + new ObjectConstructor() + { + public T construct() { + try { + Object[] args = null; + return constructor.newInstance(args); + } + catch (InstantiationException e) { + throw new RuntimeException("Failed to invoke " + constructor + " with no args", e); + } + catch (InvocationTargetException e) + { + throw new RuntimeException("Failed to invoke " + constructor + " with no args", e.getTargetException()); + } + catch (IllegalAccessException e) { + throw new AssertionError(e); + } + } + }; + } catch (NoSuchMethodException e) {} + return null; + } + + + + + + + + private ObjectConstructor newDefaultImplementationConstructor(final Type type, Class rawType) + { + if (Collection.class.isAssignableFrom(rawType)) { + if (SortedSet.class.isAssignableFrom(rawType)) + new ObjectConstructor() { + public T construct() { + return new TreeSet(); + } + }; + if (EnumSet.class.isAssignableFrom(rawType)) { + new ObjectConstructor() + { + public T construct() { + if ((type instanceof ParameterizedType)) { + Type elementType = ((ParameterizedType)type).getActualTypeArguments()[0]; + if ((elementType instanceof Class)) { + return EnumSet.noneOf((Class)elementType); + } + throw new JsonIOException("Invalid EnumSet type: " + type.toString()); + } + + throw new JsonIOException("Invalid EnumSet type: " + type.toString()); + } + }; + } + if (Set.class.isAssignableFrom(rawType)) + new ObjectConstructor() { + public T construct() { + return new LinkedHashSet(); + } + }; + if (Queue.class.isAssignableFrom(rawType)) { + new ObjectConstructor() { + public T construct() { + return new LinkedList(); + } + }; + } + new ObjectConstructor() { + public T construct() { + return new ArrayList(); + } + }; + } + + + if (Map.class.isAssignableFrom(rawType)) { + if (SortedMap.class.isAssignableFrom(rawType)) + new ObjectConstructor() { + public T construct() { + return new TreeMap(); + } + }; + if (((type instanceof ParameterizedType)) && (!String.class.isAssignableFrom(TypeToken.get(((ParameterizedType)type).getActualTypeArguments()[0]).getRawType()))) + { + new ObjectConstructor() { + public T construct() { + return new LinkedHashMap(); + } + }; + } + new ObjectConstructor() { + public T construct() { + return new LinkedTreeMap(); + } + }; + } + + + return null; + } + + private ObjectConstructor newUnsafeAllocator(final Type type, final Class rawType) + { + new ObjectConstructor() { + private final UnsafeAllocator unsafeAllocator = UnsafeAllocator.create(); + + public T construct() { + try { + return unsafeAllocator.newInstance(rawType); + } + catch (Exception e) { + throw new RuntimeException("Unable to invoke no-args constructor for " + type + ". " + "Register an InstanceCreator with Gson for this type may fix this problem.", e); + } + } + }; + } + + public String toString() + { + return instanceCreators.toString(); + } +} diff --git a/src/minecraft/com/google/gson/internal/Excluder.java b/src/minecraft/com/google/gson/internal/Excluder.java new file mode 100644 index 0000000..73a1cb1 --- /dev/null +++ b/src/minecraft/com/google/gson/internal/Excluder.java @@ -0,0 +1,251 @@ +package com.google.gson.internal; + +import com.google.gson.ExclusionStrategy; +import com.google.gson.FieldAttributes; +import com.google.gson.Gson; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.Since; +import com.google.gson.annotations.Until; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public final class Excluder + implements TypeAdapterFactory, Cloneable +{ + private static final double IGNORE_VERSIONS = -1.0D; + public static final Excluder DEFAULT = new Excluder(); + + private double version = -1.0D; + private int modifiers = 136; + private boolean serializeInnerClasses = true; + private boolean requireExpose; + private List serializationStrategies = Collections.emptyList(); + private List deserializationStrategies = Collections.emptyList(); + + public Excluder() {} + + protected Excluder clone() { try { return (Excluder)super.clone(); + } catch (CloneNotSupportedException e) { + throw new AssertionError(); + } + } + + public Excluder withVersion(double ignoreVersionsAfter) { + Excluder result = clone(); + version = ignoreVersionsAfter; + return result; + } + + public Excluder withModifiers(int... modifiers) { + Excluder result = clone(); + modifiers = 0; + for (int modifier : modifiers) { + modifiers |= modifier; + } + return result; + } + + public Excluder disableInnerClassSerialization() { + Excluder result = clone(); + serializeInnerClasses = false; + return result; + } + + public Excluder excludeFieldsWithoutExposeAnnotation() { + Excluder result = clone(); + requireExpose = true; + return result; + } + + public Excluder withExclusionStrategy(ExclusionStrategy exclusionStrategy, boolean serialization, boolean deserialization) + { + Excluder result = clone(); + if (serialization) { + serializationStrategies = new ArrayList(serializationStrategies); + serializationStrategies.add(exclusionStrategy); + } + if (deserialization) { + deserializationStrategies = new ArrayList(deserializationStrategies); + + deserializationStrategies.add(exclusionStrategy); + } + return result; + } + + public TypeAdapter create(final Gson gson, final TypeToken type) { + Class rawType = type.getRawType(); + final boolean skipSerialize = excludeClass(rawType, true); + final boolean skipDeserialize = excludeClass(rawType, false); + + if ((!skipSerialize) && (!skipDeserialize)) { + return null; + } + + new TypeAdapter() + { + private TypeAdapter delegate; + + public T read(JsonReader in) throws IOException { + if (skipDeserialize) { + in.skipValue(); + return null; + } + return delegate().read(in); + } + + public void write(JsonWriter out, T value) throws IOException { + if (skipSerialize) { + out.nullValue(); + return; + } + delegate().write(out, value); + } + + private TypeAdapter delegate() { + TypeAdapter d = delegate; + return this.delegate = gson.getDelegateAdapter(Excluder.this, type); + } + }; + } + + + public boolean excludeField(Field field, boolean serialize) + { + if ((modifiers & field.getModifiers()) != 0) { + return true; + } + + if ((version != -1.0D) && (!isValidVersion((Since)field.getAnnotation(Since.class), (Until)field.getAnnotation(Until.class)))) + { + return true; + } + + if (field.isSynthetic()) { + return true; + } + + if (requireExpose) { + Expose annotation = (Expose)field.getAnnotation(Expose.class); + if ((annotation == null) || (serialize ? !annotation.serialize() : !annotation.deserialize())) { + return true; + } + } + + if ((!serializeInnerClasses) && (isInnerClass(field.getType()))) { + return true; + } + + if (isAnonymousOrLocal(field.getType())) { + return true; + } + + List list = serialize ? serializationStrategies : deserializationStrategies; + FieldAttributes fieldAttributes; if (!list.isEmpty()) { + fieldAttributes = new FieldAttributes(field); + for (ExclusionStrategy exclusionStrategy : list) { + if (exclusionStrategy.shouldSkipField(fieldAttributes)) { + return true; + } + } + } + + return false; + } + + public boolean excludeClass(Class clazz, boolean serialize) { + if ((version != -1.0D) && (!isValidVersion((Since)clazz.getAnnotation(Since.class), (Until)clazz.getAnnotation(Until.class)))) + { + return true; + } + + if ((!serializeInnerClasses) && (isInnerClass(clazz))) { + return true; + } + + if (isAnonymousOrLocal(clazz)) { + return true; + } + + List list = serialize ? serializationStrategies : deserializationStrategies; + for (ExclusionStrategy exclusionStrategy : list) { + if (exclusionStrategy.shouldSkipClass(clazz)) { + return true; + } + } + + return false; + } + + private boolean isAnonymousOrLocal(Class clazz) { + return (!Enum.class.isAssignableFrom(clazz)) && ((clazz.isAnonymousClass()) || (clazz.isLocalClass())); + } + + private boolean isInnerClass(Class clazz) + { + return (clazz.isMemberClass()) && (!isStatic(clazz)); + } + + private boolean isStatic(Class clazz) { + return (clazz.getModifiers() & 0x8) != 0; + } + + private boolean isValidVersion(Since since, Until until) { + return (isValidSince(since)) && (isValidUntil(until)); + } + + private boolean isValidSince(Since annotation) { + if (annotation != null) { + double annotationVersion = annotation.value(); + if (annotationVersion > version) { + return false; + } + } + return true; + } + + private boolean isValidUntil(Until annotation) { + if (annotation != null) { + double annotationVersion = annotation.value(); + if (annotationVersion <= version) { + return false; + } + } + return true; + } +} diff --git a/src/minecraft/com/google/gson/internal/JsonReaderInternalAccess.java b/src/minecraft/com/google/gson/internal/JsonReaderInternalAccess.java new file mode 100644 index 0000000..5867886 --- /dev/null +++ b/src/minecraft/com/google/gson/internal/JsonReaderInternalAccess.java @@ -0,0 +1,14 @@ +package com.google.gson.internal; + +import com.google.gson.stream.JsonReader; +import java.io.IOException; + +public abstract class JsonReaderInternalAccess +{ + public static JsonReaderInternalAccess INSTANCE; + + public JsonReaderInternalAccess() {} + + public abstract void promoteNameToValue(JsonReader paramJsonReader) + throws IOException; +} diff --git a/src/minecraft/com/google/gson/internal/LazilyParsedNumber.java b/src/minecraft/com/google/gson/internal/LazilyParsedNumber.java new file mode 100644 index 0000000..05091a1 --- /dev/null +++ b/src/minecraft/com/google/gson/internal/LazilyParsedNumber.java @@ -0,0 +1,78 @@ +package com.google.gson.internal; + +import java.io.ObjectStreamException; +import java.math.BigDecimal; + + + + + + + + + + + + + + + + + + +public final class LazilyParsedNumber + extends Number +{ + private final String value; + + public LazilyParsedNumber(String value) + { + this.value = value; + } + + public int intValue() + { + try { + return Integer.parseInt(value); + } catch (NumberFormatException e) { + try { + return (int)Long.parseLong(value); + } catch (NumberFormatException nfe) {} } + return new BigDecimal(value).intValue(); + } + + + public long longValue() + { + try + { + return Long.parseLong(value); + } catch (NumberFormatException e) {} + return new BigDecimal(value).longValue(); + } + + + public float floatValue() + { + return Float.parseFloat(value); + } + + public double doubleValue() + { + return Double.parseDouble(value); + } + + public String toString() + { + return value; + } + + + + + private Object writeReplace() + throws ObjectStreamException + { + return new BigDecimal(value); + } +} diff --git a/src/minecraft/com/google/gson/internal/LinkedTreeMap.java b/src/minecraft/com/google/gson/internal/LinkedTreeMap.java new file mode 100644 index 0000000..ec747fa --- /dev/null +++ b/src/minecraft/com/google/gson/internal/LinkedTreeMap.java @@ -0,0 +1 @@ +null \ No newline at end of file diff --git a/src/minecraft/com/google/gson/internal/ObjectConstructor.java b/src/minecraft/com/google/gson/internal/ObjectConstructor.java new file mode 100644 index 0000000..d0ebcde --- /dev/null +++ b/src/minecraft/com/google/gson/internal/ObjectConstructor.java @@ -0,0 +1,6 @@ +package com.google.gson.internal; + +public abstract interface ObjectConstructor +{ + public abstract T construct(); +} diff --git a/src/minecraft/com/google/gson/internal/Primitives.java b/src/minecraft/com/google/gson/internal/Primitives.java new file mode 100644 index 0000000..4420d4c --- /dev/null +++ b/src/minecraft/com/google/gson/internal/Primitives.java @@ -0,0 +1,119 @@ +package com.google.gson.internal; + +import java.lang.reflect.Type; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public final class Primitives +{ + private static final Map, Class> PRIMITIVE_TO_WRAPPER_TYPE; + private static final Map, Class> WRAPPER_TO_PRIMITIVE_TYPE; + + static + { + Map, Class> primToWrap = new HashMap(16); + Map, Class> wrapToPrim = new HashMap(16); + + add(primToWrap, wrapToPrim, Boolean.TYPE, Boolean.class); + add(primToWrap, wrapToPrim, Byte.TYPE, Byte.class); + add(primToWrap, wrapToPrim, Character.TYPE, Character.class); + add(primToWrap, wrapToPrim, Double.TYPE, Double.class); + add(primToWrap, wrapToPrim, Float.TYPE, Float.class); + add(primToWrap, wrapToPrim, Integer.TYPE, Integer.class); + add(primToWrap, wrapToPrim, Long.TYPE, Long.class); + add(primToWrap, wrapToPrim, Short.TYPE, Short.class); + add(primToWrap, wrapToPrim, Void.TYPE, Void.class); + + PRIMITIVE_TO_WRAPPER_TYPE = Collections.unmodifiableMap(primToWrap); + WRAPPER_TO_PRIMITIVE_TYPE = Collections.unmodifiableMap(wrapToPrim); + } + + private static void add(Map, Class> forward, Map, Class> backward, Class key, Class value) + { + forward.put(key, value); + backward.put(value, key); + } + + + + public static boolean isPrimitive(Type type) + { + return PRIMITIVE_TO_WRAPPER_TYPE.containsKey(type); + } + + + + + + + public static boolean isWrapperType(Type type) + { + return WRAPPER_TO_PRIMITIVE_TYPE.containsKey(.Gson.Preconditions.checkNotNull(type)); + } + + + + + + + + + + + + + public static Class wrap(Class type) + { + Class wrapped = (Class)PRIMITIVE_TO_WRAPPER_TYPE.get(.Gson.Preconditions.checkNotNull(type)); + + return wrapped == null ? type : wrapped; + } + + + + + + + + + + + + public static Class unwrap(Class type) + { + Class unwrapped = (Class)WRAPPER_TO_PRIMITIVE_TYPE.get(.Gson.Preconditions.checkNotNull(type)); + + return unwrapped == null ? type : unwrapped; + } + + private Primitives() {} +} diff --git a/src/minecraft/com/google/gson/internal/Streams.java b/src/minecraft/com/google/gson/internal/Streams.java new file mode 100644 index 0000000..cf21a80 --- /dev/null +++ b/src/minecraft/com/google/gson/internal/Streams.java @@ -0,0 +1,114 @@ +package com.google.gson.internal; + +import com.google.gson.JsonElement; +import com.google.gson.JsonIOException; +import com.google.gson.JsonNull; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSyntaxException; +import com.google.gson.TypeAdapter; +import com.google.gson.internal.bind.TypeAdapters; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import com.google.gson.stream.MalformedJsonException; +import java.io.EOFException; +import java.io.IOException; +import java.io.Writer; + + + + + + + + + + + + + + + + + +public final class Streams +{ + public Streams() {} + + public static JsonElement parse(JsonReader reader) + throws JsonParseException + { + boolean isEmpty = true; + try { + reader.peek(); + isEmpty = false; + return (JsonElement)TypeAdapters.JSON_ELEMENT.read(reader); + + } + catch (EOFException e) + { + + if (isEmpty) { + return JsonNull.INSTANCE; + } + + throw new JsonSyntaxException(e); + } catch (MalformedJsonException e) { + throw new JsonSyntaxException(e); + } catch (IOException e) { + throw new JsonIOException(e); + } catch (NumberFormatException e) { + throw new JsonSyntaxException(e); + } + } + + + public static void write(JsonElement element, JsonWriter writer) + throws IOException + { + TypeAdapters.JSON_ELEMENT.write(writer, element); + } + + public static Writer writerForAppendable(Appendable appendable) { + return (appendable instanceof Writer) ? (Writer)appendable : new AppendableWriter(appendable, null); + } + + + private static final class AppendableWriter + extends Writer + { + private final Appendable appendable; + + private final CurrentWrite currentWrite = new CurrentWrite(); + + private AppendableWriter(Appendable appendable) { + this.appendable = appendable; + } + + public void write(char[] chars, int offset, int length) throws IOException { + currentWrite.chars = chars; + appendable.append(currentWrite, offset, offset + length); + } + + public void write(int i) throws IOException { + appendable.append((char)i); + } + + public void flush() {} + + public void close() {} + + static class CurrentWrite implements CharSequence { + char[] chars; + + CurrentWrite() {} + + public int length() { return chars.length; } + + public char charAt(int i) { + return chars[i]; + } + + public CharSequence subSequence(int start, int end) { return new String(chars, start, end - start); } + } + } +} diff --git a/src/minecraft/com/google/gson/internal/UnsafeAllocator.java b/src/minecraft/com/google/gson/internal/UnsafeAllocator.java new file mode 100644 index 0000000..6cea32f --- /dev/null +++ b/src/minecraft/com/google/gson/internal/UnsafeAllocator.java @@ -0,0 +1,104 @@ +package com.google.gson.internal; + +import java.io.ObjectInputStream; +import java.io.ObjectStreamClass; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + + + + + + + + + + + + + + + + + + + + + +public abstract class UnsafeAllocator +{ + public UnsafeAllocator() {} + + public abstract T newInstance(Class paramClass) + throws Exception; + + public static UnsafeAllocator create() + { + try + { + Class unsafeClass = Class.forName("sun.misc.Unsafe"); + Field f = unsafeClass.getDeclaredField("theUnsafe"); + f.setAccessible(true); + final Object unsafe = f.get(null); + Method allocateInstance = unsafeClass.getMethod("allocateInstance", new Class[] { Class.class }); + new UnsafeAllocator() + { + public T newInstance(Class c) throws Exception + { + return val$allocateInstance.invoke(unsafe, new Object[] { c }); + } + + + }; + + } + catch (Exception ignored) + { + + try + { + Method newInstance = ObjectInputStream.class.getDeclaredMethod("newInstance", new Class[] { Class.class, Class.class }); + + newInstance.setAccessible(true); + new UnsafeAllocator() + { + public T newInstance(Class c) throws Exception + { + return val$newInstance.invoke(null, new Object[] { c, Object.class }); + } + + + }; + + } + catch (Exception ignored) + { + + try + { + Method getConstructorId = ObjectStreamClass.class.getDeclaredMethod("getConstructorId", new Class[] { Class.class }); + + getConstructorId.setAccessible(true); + final int constructorId = ((Integer)getConstructorId.invoke(null, new Object[] { Object.class })).intValue(); + Method newInstance = ObjectStreamClass.class.getDeclaredMethod("newInstance", new Class[] { Class.class, Integer.TYPE }); + + newInstance.setAccessible(true); + new UnsafeAllocator() + { + public T newInstance(Class c) throws Exception + { + return val$newInstance.invoke(null, new Object[] { c, Integer.valueOf(constructorId) }); + } + }; + } + catch (Exception ignored) {} + } + } + new UnsafeAllocator() + { + public T newInstance(Class c) { + throw new UnsupportedOperationException("Cannot allocate " + c); + } + }; + } +} diff --git a/src/minecraft/com/google/gson/internal/bind/ArrayTypeAdapter.java b/src/minecraft/com/google/gson/internal/bind/ArrayTypeAdapter.java new file mode 100644 index 0000000..dbaddfd --- /dev/null +++ b/src/minecraft/com/google/gson/internal/bind/ArrayTypeAdapter.java @@ -0,0 +1,97 @@ +package com.google.gson.internal.bind; + +import com.google.gson.Gson; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.internal..Gson.Types; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.lang.reflect.Array; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; + + + + + + + + + + + + + + + + + + + +public final class ArrayTypeAdapter + extends TypeAdapter +{ + public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() + { + public TypeAdapter create(Gson gson, TypeToken typeToken) { + Type type = typeToken.getType(); + if ((!(type instanceof GenericArrayType)) && ((!(type instanceof Class)) || (!((Class)type).isArray()))) { + return null; + } + + Type componentType = .Gson.Types.getArrayComponentType(type); + TypeAdapter componentTypeAdapter = gson.getAdapter(TypeToken.get(componentType)); + return new ArrayTypeAdapter(gson, componentTypeAdapter, .Gson.Types.getRawType(componentType)); + } + }; + + private final Class componentType; + private final TypeAdapter componentTypeAdapter; + + public ArrayTypeAdapter(Gson context, TypeAdapter componentTypeAdapter, Class componentType) + { + this.componentTypeAdapter = new TypeAdapterRuntimeTypeWrapper(context, componentTypeAdapter, componentType); + + this.componentType = componentType; + } + + public Object read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + + List list = new ArrayList(); + in.beginArray(); + while (in.hasNext()) { + E instance = componentTypeAdapter.read(in); + list.add(instance); + } + in.endArray(); + Object array = Array.newInstance(componentType, list.size()); + for (int i = 0; i < list.size(); i++) { + Array.set(array, i, list.get(i)); + } + return array; + } + + public void write(JsonWriter out, Object array) throws IOException + { + if (array == null) { + out.nullValue(); + return; + } + + out.beginArray(); + int i = 0; for (int length = Array.getLength(array); i < length; i++) { + E value = Array.get(array, i); + componentTypeAdapter.write(out, value); + } + out.endArray(); + } +} diff --git a/src/minecraft/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java b/src/minecraft/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java new file mode 100644 index 0000000..db56191 --- /dev/null +++ b/src/minecraft/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java @@ -0,0 +1,101 @@ +package com.google.gson.internal.bind; + +import com.google.gson.Gson; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.internal..Gson.Types; +import com.google.gson.internal.ConstructorConstructor; +import com.google.gson.internal.ObjectConstructor; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.Collection; + + + + + + + + + + + + + + + + + +public final class CollectionTypeAdapterFactory + implements TypeAdapterFactory +{ + private final ConstructorConstructor constructorConstructor; + + public CollectionTypeAdapterFactory(ConstructorConstructor constructorConstructor) + { + this.constructorConstructor = constructorConstructor; + } + + public TypeAdapter create(Gson gson, TypeToken typeToken) { + Type type = typeToken.getType(); + + Class rawType = typeToken.getRawType(); + if (!Collection.class.isAssignableFrom(rawType)) { + return null; + } + + Type elementType = .Gson.Types.getCollectionElementType(type, rawType); + TypeAdapter elementTypeAdapter = gson.getAdapter(TypeToken.get(elementType)); + ObjectConstructor constructor = constructorConstructor.get(typeToken); + + + TypeAdapter result = new Adapter(gson, elementType, elementTypeAdapter, constructor); + return result; + } + + private static final class Adapter extends TypeAdapter> + { + private final TypeAdapter elementTypeAdapter; + private final ObjectConstructor> constructor; + + public Adapter(Gson context, Type elementType, TypeAdapter elementTypeAdapter, ObjectConstructor> constructor) + { + this.elementTypeAdapter = new TypeAdapterRuntimeTypeWrapper(context, elementTypeAdapter, elementType); + + this.constructor = constructor; + } + + public Collection read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + + Collection collection = (Collection)constructor.construct(); + in.beginArray(); + while (in.hasNext()) { + E instance = elementTypeAdapter.read(in); + collection.add(instance); + } + in.endArray(); + return collection; + } + + public void write(JsonWriter out, Collection collection) throws IOException { + if (collection == null) { + out.nullValue(); + return; + } + + out.beginArray(); + for (E element : collection) { + elementTypeAdapter.write(out, element); + } + out.endArray(); + } + } +} diff --git a/src/minecraft/com/google/gson/internal/bind/DateTypeAdapter.java b/src/minecraft/com/google/gson/internal/bind/DateTypeAdapter.java new file mode 100644 index 0000000..4e8bf12 --- /dev/null +++ b/src/minecraft/com/google/gson/internal/bind/DateTypeAdapter.java @@ -0,0 +1,93 @@ +package com.google.gson.internal.bind; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + + + + + + + + + + + + + + + + + + + + + +public final class DateTypeAdapter + extends TypeAdapter +{ + public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() + { + + public TypeAdapter create(Gson gson, TypeToken typeToken) { return typeToken.getRawType() == Date.class ? new DateTypeAdapter() : null; } }; + + public DateTypeAdapter() {} + + private final DateFormat enUsFormat = DateFormat.getDateTimeInstance(2, 2, Locale.US); + + private final DateFormat localFormat = DateFormat.getDateTimeInstance(2, 2); + + private final DateFormat iso8601Format = buildIso8601Format(); + + private static DateFormat buildIso8601Format() { + DateFormat iso8601Format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); + iso8601Format.setTimeZone(TimeZone.getTimeZone("UTC")); + return iso8601Format; + } + + public Date read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + return deserializeToDate(in.nextString()); + } + + private synchronized Date deserializeToDate(String json) { + try { + return localFormat.parse(json); + } + catch (ParseException ignored) { + try { + return enUsFormat.parse(json); + } + catch (ParseException ignored) { + try { + return iso8601Format.parse(json); + } catch (ParseException e) { + throw new JsonSyntaxException(json, e); + } + } + } } + + public synchronized void write(JsonWriter out, Date value) throws IOException { if (value == null) { + out.nullValue(); + return; + } + String dateFormatAsString = enUsFormat.format(value); + out.value(dateFormatAsString); + } +} diff --git a/src/minecraft/com/google/gson/internal/bind/JsonTreeReader.java b/src/minecraft/com/google/gson/internal/bind/JsonTreeReader.java new file mode 100644 index 0000000..3f08bfd --- /dev/null +++ b/src/minecraft/com/google/gson/internal/bind/JsonTreeReader.java @@ -0,0 +1,226 @@ +package com.google.gson.internal.bind; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import java.io.IOException; +import java.io.Reader; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; + + + + + + + + + + + + + + + + + + + + +public final class JsonTreeReader + extends JsonReader +{ + private static final Reader UNREADABLE_READER = new Reader() { + public int read(char[] buffer, int offset, int count) throws IOException { + throw new AssertionError(); + } + + public void close() throws IOException { throw new AssertionError(); } + }; + + private static final Object SENTINEL_CLOSED = new Object(); + + private final List stack = new ArrayList(); + + public JsonTreeReader(JsonElement element) { + super(UNREADABLE_READER); + stack.add(element); + } + + public void beginArray() throws IOException { + expect(JsonToken.BEGIN_ARRAY); + JsonArray array = (JsonArray)peekStack(); + stack.add(array.iterator()); + } + + public void endArray() throws IOException { + expect(JsonToken.END_ARRAY); + popStack(); + popStack(); + } + + public void beginObject() throws IOException { + expect(JsonToken.BEGIN_OBJECT); + JsonObject object = (JsonObject)peekStack(); + stack.add(object.entrySet().iterator()); + } + + public void endObject() throws IOException { + expect(JsonToken.END_OBJECT); + popStack(); + popStack(); + } + + public boolean hasNext() throws IOException { + JsonToken token = peek(); + return (token != JsonToken.END_OBJECT) && (token != JsonToken.END_ARRAY); + } + + public JsonToken peek() throws IOException { + if (stack.isEmpty()) { + return JsonToken.END_DOCUMENT; + } + + Object o = peekStack(); + if ((o instanceof Iterator)) { + boolean isObject = stack.get(stack.size() - 2) instanceof JsonObject; + Iterator iterator = (Iterator)o; + if (iterator.hasNext()) { + if (isObject) { + return JsonToken.NAME; + } + stack.add(iterator.next()); + return peek(); + } + + return isObject ? JsonToken.END_OBJECT : JsonToken.END_ARRAY; + } + if ((o instanceof JsonObject)) + return JsonToken.BEGIN_OBJECT; + if ((o instanceof JsonArray)) + return JsonToken.BEGIN_ARRAY; + if ((o instanceof JsonPrimitive)) { + JsonPrimitive primitive = (JsonPrimitive)o; + if (primitive.isString()) + return JsonToken.STRING; + if (primitive.isBoolean()) + return JsonToken.BOOLEAN; + if (primitive.isNumber()) { + return JsonToken.NUMBER; + } + throw new AssertionError(); + } + if ((o instanceof JsonNull)) + return JsonToken.NULL; + if (o == SENTINEL_CLOSED) { + throw new IllegalStateException("JsonReader is closed"); + } + throw new AssertionError(); + } + + private Object peekStack() + { + return stack.get(stack.size() - 1); + } + + private Object popStack() { + return stack.remove(stack.size() - 1); + } + + private void expect(JsonToken expected) throws IOException { + if (peek() != expected) { + throw new IllegalStateException("Expected " + expected + " but was " + peek()); + } + } + + public String nextName() throws IOException { + expect(JsonToken.NAME); + Iterator i = (Iterator)peekStack(); + Map.Entry entry = (Map.Entry)i.next(); + stack.add(entry.getValue()); + return (String)entry.getKey(); + } + + public String nextString() throws IOException { + JsonToken token = peek(); + if ((token != JsonToken.STRING) && (token != JsonToken.NUMBER)) { + throw new IllegalStateException("Expected " + JsonToken.STRING + " but was " + token); + } + return ((JsonPrimitive)popStack()).getAsString(); + } + + public boolean nextBoolean() throws IOException { + expect(JsonToken.BOOLEAN); + return ((JsonPrimitive)popStack()).getAsBoolean(); + } + + public void nextNull() throws IOException { + expect(JsonToken.NULL); + popStack(); + } + + public double nextDouble() throws IOException { + JsonToken token = peek(); + if ((token != JsonToken.NUMBER) && (token != JsonToken.STRING)) { + throw new IllegalStateException("Expected " + JsonToken.NUMBER + " but was " + token); + } + double result = ((JsonPrimitive)peekStack()).getAsDouble(); + if ((!isLenient()) && ((Double.isNaN(result)) || (Double.isInfinite(result)))) { + throw new NumberFormatException("JSON forbids NaN and infinities: " + result); + } + popStack(); + return result; + } + + public long nextLong() throws IOException { + JsonToken token = peek(); + if ((token != JsonToken.NUMBER) && (token != JsonToken.STRING)) { + throw new IllegalStateException("Expected " + JsonToken.NUMBER + " but was " + token); + } + long result = ((JsonPrimitive)peekStack()).getAsLong(); + popStack(); + return result; + } + + public int nextInt() throws IOException { + JsonToken token = peek(); + if ((token != JsonToken.NUMBER) && (token != JsonToken.STRING)) { + throw new IllegalStateException("Expected " + JsonToken.NUMBER + " but was " + token); + } + int result = ((JsonPrimitive)peekStack()).getAsInt(); + popStack(); + return result; + } + + public void close() throws IOException { + stack.clear(); + stack.add(SENTINEL_CLOSED); + } + + public void skipValue() throws IOException { + if (peek() == JsonToken.NAME) { + nextName(); + } else { + popStack(); + } + } + + public String toString() { + return getClass().getSimpleName(); + } + + public void promoteNameToValue() throws IOException { + expect(JsonToken.NAME); + Iterator i = (Iterator)peekStack(); + Map.Entry entry = (Map.Entry)i.next(); + stack.add(entry.getValue()); + stack.add(new JsonPrimitive((String)entry.getKey())); + } +} diff --git a/src/minecraft/com/google/gson/internal/bind/JsonTreeWriter.java b/src/minecraft/com/google/gson/internal/bind/JsonTreeWriter.java new file mode 100644 index 0000000..c9325e1 --- /dev/null +++ b/src/minecraft/com/google/gson/internal/bind/JsonTreeWriter.java @@ -0,0 +1,200 @@ +package com.google.gson.internal.bind; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.List; + + + + + + + + + + + + + + + + + + +public final class JsonTreeWriter + extends JsonWriter +{ + private static final Writer UNWRITABLE_WRITER = new Writer() { + public void write(char[] buffer, int offset, int counter) { + throw new AssertionError(); + } + + public void flush() throws IOException { throw new AssertionError(); } + + public void close() throws IOException { + throw new AssertionError(); + } + }; + + private static final JsonPrimitive SENTINEL_CLOSED = new JsonPrimitive("closed"); + + + private final List stack = new ArrayList(); + + + private String pendingName; + + + private JsonElement product = JsonNull.INSTANCE; + + public JsonTreeWriter() { + super(UNWRITABLE_WRITER); + } + + + + public JsonElement get() + { + if (!stack.isEmpty()) { + throw new IllegalStateException("Expected one JSON element but was " + stack); + } + return product; + } + + private JsonElement peek() { + return (JsonElement)stack.get(stack.size() - 1); + } + + private void put(JsonElement value) { + if (pendingName != null) { + if ((!value.isJsonNull()) || (getSerializeNulls())) { + JsonObject object = (JsonObject)peek(); + object.add(pendingName, value); + } + pendingName = null; + } else if (stack.isEmpty()) { + product = value; + } else { + JsonElement element = peek(); + if ((element instanceof JsonArray)) { + ((JsonArray)element).add(value); + } else { + throw new IllegalStateException(); + } + } + } + + public JsonWriter beginArray() throws IOException { + JsonArray array = new JsonArray(); + put(array); + stack.add(array); + return this; + } + + public JsonWriter endArray() throws IOException { + if ((stack.isEmpty()) || (pendingName != null)) { + throw new IllegalStateException(); + } + JsonElement element = peek(); + if ((element instanceof JsonArray)) { + stack.remove(stack.size() - 1); + return this; + } + throw new IllegalStateException(); + } + + public JsonWriter beginObject() throws IOException { + JsonObject object = new JsonObject(); + put(object); + stack.add(object); + return this; + } + + public JsonWriter endObject() throws IOException { + if ((stack.isEmpty()) || (pendingName != null)) { + throw new IllegalStateException(); + } + JsonElement element = peek(); + if ((element instanceof JsonObject)) { + stack.remove(stack.size() - 1); + return this; + } + throw new IllegalStateException(); + } + + public JsonWriter name(String name) throws IOException { + if ((stack.isEmpty()) || (pendingName != null)) { + throw new IllegalStateException(); + } + JsonElement element = peek(); + if ((element instanceof JsonObject)) { + pendingName = name; + return this; + } + throw new IllegalStateException(); + } + + public JsonWriter value(String value) throws IOException { + if (value == null) { + return nullValue(); + } + put(new JsonPrimitive(value)); + return this; + } + + public JsonWriter nullValue() throws IOException { + put(JsonNull.INSTANCE); + return this; + } + + public JsonWriter value(boolean value) throws IOException { + put(new JsonPrimitive(Boolean.valueOf(value))); + return this; + } + + public JsonWriter value(double value) throws IOException { + if ((!isLenient()) && ((Double.isNaN(value)) || (Double.isInfinite(value)))) { + throw new IllegalArgumentException("JSON forbids NaN and infinities: " + value); + } + put(new JsonPrimitive(Double.valueOf(value))); + return this; + } + + public JsonWriter value(long value) throws IOException { + put(new JsonPrimitive(Long.valueOf(value))); + return this; + } + + public JsonWriter value(Number value) throws IOException { + if (value == null) { + return nullValue(); + } + + if (!isLenient()) { + double d = value.doubleValue(); + if ((Double.isNaN(d)) || (Double.isInfinite(d))) { + throw new IllegalArgumentException("JSON forbids NaN and infinities: " + value); + } + } + + put(new JsonPrimitive(value)); + return this; + } + + public void flush() throws IOException + {} + + public void close() throws IOException { + if (!stack.isEmpty()) { + throw new IOException("Incomplete document"); + } + stack.add(SENTINEL_CLOSED); + } +} diff --git a/src/minecraft/com/google/gson/internal/bind/MapTypeAdapterFactory.java b/src/minecraft/com/google/gson/internal/bind/MapTypeAdapterFactory.java new file mode 100644 index 0000000..ac40f94 --- /dev/null +++ b/src/minecraft/com/google/gson/internal/bind/MapTypeAdapterFactory.java @@ -0,0 +1,263 @@ +package com.google.gson.internal.bind; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSyntaxException; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.internal..Gson.Types; +import com.google.gson.internal.ConstructorConstructor; +import com.google.gson.internal.JsonReaderInternalAccess; +import com.google.gson.internal.ObjectConstructor; +import com.google.gson.internal.Streams; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +public final class MapTypeAdapterFactory + implements TypeAdapterFactory +{ + private final ConstructorConstructor constructorConstructor; + private final boolean complexMapKeySerialization; + + public MapTypeAdapterFactory(ConstructorConstructor constructorConstructor, boolean complexMapKeySerialization) + { + this.constructorConstructor = constructorConstructor; + this.complexMapKeySerialization = complexMapKeySerialization; + } + + public TypeAdapter create(Gson gson, TypeToken typeToken) { + Type type = typeToken.getType(); + + Class rawType = typeToken.getRawType(); + if (!Map.class.isAssignableFrom(rawType)) { + return null; + } + + Class rawTypeOfSrc = .Gson.Types.getRawType(type); + Type[] keyAndValueTypes = .Gson.Types.getMapKeyAndValueTypes(type, rawTypeOfSrc); + TypeAdapter keyAdapter = getKeyAdapter(gson, keyAndValueTypes[0]); + TypeAdapter valueAdapter = gson.getAdapter(TypeToken.get(keyAndValueTypes[1])); + ObjectConstructor constructor = constructorConstructor.get(typeToken); + + + + TypeAdapter result = new Adapter(gson, keyAndValueTypes[0], keyAdapter, keyAndValueTypes[1], valueAdapter, constructor); + + return result; + } + + + + private TypeAdapter getKeyAdapter(Gson context, Type keyType) + { + return (keyType == Boolean.TYPE) || (keyType == Boolean.class) ? TypeAdapters.BOOLEAN_AS_STRING : context.getAdapter(TypeToken.get(keyType)); + } + + + private final class Adapter + extends TypeAdapter> + { + private final TypeAdapter keyTypeAdapter; + private final TypeAdapter valueTypeAdapter; + private final ObjectConstructor> constructor; + + public Adapter(Type context, TypeAdapter keyType, Type keyTypeAdapter, TypeAdapter valueType, ObjectConstructor> valueTypeAdapter) + { + this.keyTypeAdapter = new TypeAdapterRuntimeTypeWrapper(context, keyTypeAdapter, keyType); + + this.valueTypeAdapter = new TypeAdapterRuntimeTypeWrapper(context, valueTypeAdapter, valueType); + + this.constructor = constructor; + } + + public Map read(JsonReader in) throws IOException { + JsonToken peek = in.peek(); + if (peek == JsonToken.NULL) { + in.nextNull(); + return null; + } + + Map map = (Map)constructor.construct(); + + if (peek == JsonToken.BEGIN_ARRAY) { + in.beginArray(); + while (in.hasNext()) { + in.beginArray(); + K key = keyTypeAdapter.read(in); + V value = valueTypeAdapter.read(in); + V replaced = map.put(key, value); + if (replaced != null) { + throw new JsonSyntaxException("duplicate key: " + key); + } + in.endArray(); + } + in.endArray(); + } else { + in.beginObject(); + while (in.hasNext()) { + JsonReaderInternalAccess.INSTANCE.promoteNameToValue(in); + K key = keyTypeAdapter.read(in); + V value = valueTypeAdapter.read(in); + V replaced = map.put(key, value); + if (replaced != null) { + throw new JsonSyntaxException("duplicate key: " + key); + } + } + in.endObject(); + } + return map; + } + + public void write(JsonWriter out, Map map) throws IOException { + if (map == null) { + out.nullValue(); + return; + } + + if (!complexMapKeySerialization) { + out.beginObject(); + for (Map.Entry entry : map.entrySet()) { + out.name(String.valueOf(entry.getKey())); + valueTypeAdapter.write(out, entry.getValue()); + } + out.endObject(); + return; + } + + boolean hasComplexKeys = false; + List keys = new ArrayList(map.size()); + + List values = new ArrayList(map.size()); + for (Map.Entry entry : map.entrySet()) { + JsonElement keyElement = keyTypeAdapter.toJsonTree(entry.getKey()); + keys.add(keyElement); + values.add(entry.getValue()); + hasComplexKeys |= ((keyElement.isJsonArray()) || (keyElement.isJsonObject())); + } + + if (hasComplexKeys) { + out.beginArray(); + for (int i = 0; i < keys.size(); i++) { + out.beginArray(); + Streams.write((JsonElement)keys.get(i), out); + valueTypeAdapter.write(out, values.get(i)); + out.endArray(); + } + out.endArray(); + } else { + out.beginObject(); + for (int i = 0; i < keys.size(); i++) { + JsonElement keyElement = (JsonElement)keys.get(i); + out.name(keyToString(keyElement)); + valueTypeAdapter.write(out, values.get(i)); + } + out.endObject(); + } + } + + private String keyToString(JsonElement keyElement) { + if (keyElement.isJsonPrimitive()) { + JsonPrimitive primitive = keyElement.getAsJsonPrimitive(); + if (primitive.isNumber()) + return String.valueOf(primitive.getAsNumber()); + if (primitive.isBoolean()) + return Boolean.toString(primitive.getAsBoolean()); + if (primitive.isString()) { + return primitive.getAsString(); + } + throw new AssertionError(); + } + if (keyElement.isJsonNull()) { + return "null"; + } + throw new AssertionError(); + } + } +} diff --git a/src/minecraft/com/google/gson/internal/bind/ObjectTypeAdapter.java b/src/minecraft/com/google/gson/internal/bind/ObjectTypeAdapter.java new file mode 100644 index 0000000..a0e4231 --- /dev/null +++ b/src/minecraft/com/google/gson/internal/bind/ObjectTypeAdapter.java @@ -0,0 +1,109 @@ +package com.google.gson.internal.bind; + +import com.google.gson.Gson; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.internal.LinkedTreeMap; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + + + + + + + + + + + + + + + + + + + + +public final class ObjectTypeAdapter + extends TypeAdapter +{ + public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() + { + public TypeAdapter create(Gson gson, TypeToken type) { + if (type.getRawType() == Object.class) { + return new ObjectTypeAdapter(gson, null); + } + return null; + } + }; + private final Gson gson; + + private ObjectTypeAdapter(Gson gson) + { + this.gson = gson; + } + + public Object read(JsonReader in) throws IOException { + JsonToken token = in.peek(); + switch (2.$SwitchMap$com$google$gson$stream$JsonToken[token.ordinal()]) { + case 1: + List list = new ArrayList(); + in.beginArray(); + while (in.hasNext()) { + list.add(read(in)); + } + in.endArray(); + return list; + + case 2: + Map map = new LinkedTreeMap(); + in.beginObject(); + while (in.hasNext()) { + map.put(in.nextName(), read(in)); + } + in.endObject(); + return map; + + case 3: + return in.nextString(); + + case 4: + return Double.valueOf(in.nextDouble()); + + case 5: + return Boolean.valueOf(in.nextBoolean()); + + case 6: + in.nextNull(); + return null; + } + + throw new IllegalStateException(); + } + + public void write(JsonWriter out, Object value) + throws IOException + { + if (value == null) { + out.nullValue(); + return; + } + + TypeAdapter typeAdapter = gson.getAdapter(value.getClass()); + if ((typeAdapter instanceof ObjectTypeAdapter)) { + out.beginObject(); + out.endObject(); + return; + } + + typeAdapter.write(out, value); + } +} diff --git a/src/minecraft/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java b/src/minecraft/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java new file mode 100644 index 0000000..fcad55a --- /dev/null +++ b/src/minecraft/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java @@ -0,0 +1,204 @@ +package com.google.gson.internal.bind; + +import com.google.gson.FieldNamingStrategy; +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.annotations.SerializedName; +import com.google.gson.internal..Gson.Types; +import com.google.gson.internal.ConstructorConstructor; +import com.google.gson.internal.Excluder; +import com.google.gson.internal.ObjectConstructor; +import com.google.gson.internal.Primitives; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Type; +import java.util.LinkedHashMap; +import java.util.Map; + + + + + + + + + + + + + + + + + + +public final class ReflectiveTypeAdapterFactory + implements TypeAdapterFactory +{ + private final ConstructorConstructor constructorConstructor; + private final FieldNamingStrategy fieldNamingPolicy; + private final Excluder excluder; + + public ReflectiveTypeAdapterFactory(ConstructorConstructor constructorConstructor, FieldNamingStrategy fieldNamingPolicy, Excluder excluder) + { + this.constructorConstructor = constructorConstructor; + this.fieldNamingPolicy = fieldNamingPolicy; + this.excluder = excluder; + } + + public boolean excludeField(Field f, boolean serialize) { + return (!excluder.excludeClass(f.getType(), serialize)) && (!excluder.excludeField(f, serialize)); + } + + private String getFieldName(Field f) { + SerializedName serializedName = (SerializedName)f.getAnnotation(SerializedName.class); + return serializedName == null ? fieldNamingPolicy.translateName(f) : serializedName.value(); + } + + public TypeAdapter create(Gson gson, TypeToken type) { + Class raw = type.getRawType(); + + if (!Object.class.isAssignableFrom(raw)) { + return null; + } + + ObjectConstructor constructor = constructorConstructor.get(type); + return new Adapter(constructor, getBoundFields(gson, type, raw), null); + } + + + private BoundField createBoundField(final Gson context, final Field field, String name, final TypeToken fieldType, boolean serialize, boolean deserialize) + { + final boolean isPrimitive = Primitives.isPrimitive(fieldType.getRawType()); + + + new BoundField(name, serialize, deserialize) { + final TypeAdapter typeAdapter = context.getAdapter(fieldType); + + void write(JsonWriter writer, Object value) throws IOException, IllegalAccessException + { + Object fieldValue = field.get(value); + TypeAdapter t = new TypeAdapterRuntimeTypeWrapper(context, typeAdapter, fieldType.getType()); + + t.write(writer, fieldValue); + } + + void read(JsonReader reader, Object value) throws IOException, IllegalAccessException { + Object fieldValue = typeAdapter.read(reader); + if ((fieldValue != null) || (!isPrimitive)) { + field.set(value, fieldValue); + } + } + }; + } + + private Map getBoundFields(Gson context, TypeToken type, Class raw) { + Map result = new LinkedHashMap(); + if (raw.isInterface()) { + return result; + } + + Type declaredType = type.getType(); + while (raw != Object.class) { + Field[] fields = raw.getDeclaredFields(); + for (Field field : fields) { + boolean serialize = excludeField(field, true); + boolean deserialize = excludeField(field, false); + if ((serialize) || (deserialize)) + { + + field.setAccessible(true); + Type fieldType = .Gson.Types.resolve(type.getType(), raw, field.getGenericType()); + BoundField boundField = createBoundField(context, field, getFieldName(field), TypeToken.get(fieldType), serialize, deserialize); + + BoundField previous = (BoundField)result.put(name, boundField); + if (previous != null) { + throw new IllegalArgumentException(declaredType + " declares multiple JSON fields named " + name); + } + } + } + type = TypeToken.get(.Gson.Types.resolve(type.getType(), raw, raw.getGenericSuperclass())); + raw = type.getRawType(); + } + return result; + } + + static abstract class BoundField { + final String name; + final boolean serialized; + final boolean deserialized; + + protected BoundField(String name, boolean serialized, boolean deserialized) { + this.name = name; + this.serialized = serialized; + this.deserialized = deserialized; + } + + abstract void write(JsonWriter paramJsonWriter, Object paramObject) throws IOException, IllegalAccessException; + + abstract void read(JsonReader paramJsonReader, Object paramObject) throws IOException, IllegalAccessException; + } + + public static final class Adapter extends TypeAdapter { + private final ObjectConstructor constructor; + private final Map boundFields; + + private Adapter(ObjectConstructor constructor, Map boundFields) { this.constructor = constructor; + this.boundFields = boundFields; + } + + public T read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + + T instance = constructor.construct(); + try + { + in.beginObject(); + while (in.hasNext()) { + String name = in.nextName(); + ReflectiveTypeAdapterFactory.BoundField field = (ReflectiveTypeAdapterFactory.BoundField)boundFields.get(name); + if ((field == null) || (!deserialized)) { + in.skipValue(); + } else { + field.read(in, instance); + } + } + } catch (IllegalStateException e) { + throw new JsonSyntaxException(e); + } catch (IllegalAccessException e) { + throw new AssertionError(e); + } + in.endObject(); + return instance; + } + + public void write(JsonWriter out, T value) throws IOException { + if (value == null) { + out.nullValue(); + return; + } + + out.beginObject(); + try { + for (ReflectiveTypeAdapterFactory.BoundField boundField : boundFields.values()) { + if (serialized) { + out.name(name); + boundField.write(out, value); + } + } + } catch (IllegalAccessException e) { + throw new AssertionError(); + } + out.endObject(); + } + } +} diff --git a/src/minecraft/com/google/gson/internal/bind/SqlDateTypeAdapter.java b/src/minecraft/com/google/gson/internal/bind/SqlDateTypeAdapter.java new file mode 100644 index 0000000..e58da2f --- /dev/null +++ b/src/minecraft/com/google/gson/internal/bind/SqlDateTypeAdapter.java @@ -0,0 +1,67 @@ +package com.google.gson.internal.bind; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; + + + + + + + + + + + + + + + + + + + + + +public final class SqlDateTypeAdapter + extends TypeAdapter +{ + public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() + { + public TypeAdapter create(Gson gson, TypeToken typeToken) { + return typeToken.getRawType() == java.sql.Date.class ? new SqlDateTypeAdapter() : null; + } + }; + + + private final DateFormat format = new SimpleDateFormat("MMM d, yyyy"); + + public SqlDateTypeAdapter() {} + + public synchronized java.sql.Date read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + try { + long utilDate = format.parse(in.nextString()).getTime(); + return new java.sql.Date(utilDate); + } catch (ParseException e) { + throw new JsonSyntaxException(e); + } + } + + public synchronized void write(JsonWriter out, java.sql.Date value) throws IOException + { + out.value(value == null ? null : format.format(value)); + } +} diff --git a/src/minecraft/com/google/gson/internal/bind/TimeTypeAdapter.java b/src/minecraft/com/google/gson/internal/bind/TimeTypeAdapter.java new file mode 100644 index 0000000..74716e2 --- /dev/null +++ b/src/minecraft/com/google/gson/internal/bind/TimeTypeAdapter.java @@ -0,0 +1,66 @@ +package com.google.gson.internal.bind; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.sql.Time; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + + + + + + + + + + + + + + + + + + + + + +public final class TimeTypeAdapter + extends TypeAdapter