Archiviert
13
0

Refactor package caching, account for some edge cases

Dieser Commit ist enthalten in:
Dan Mulloy 2016-11-29 19:39:11 -05:00
Ursprung 4afb38aae1
Commit d175a7655e
3 geänderte Dateien mit 53 neuen und 41 gelöschten Zeilen

Datei anzeigen

@ -1,20 +1,19 @@
/* /**
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol. * ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
* Copyright (C) 2012 Kristian S. Stangeland * Copyright (C) 2012 Kristian S. Stangeland
* *
* This program is free software; you can redistribute it and/or modify it under the terms of the * This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of * GNU General Public License as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version. * the License, or (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along with this program; * You should have received a copy of the GNU General Public License along with this program;
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA * 02111-1307 USA
*/ */
package com.comphenix.protocol.utility; package com.comphenix.protocol.utility;
import java.util.Map; import java.util.Map;
@ -33,7 +32,7 @@ class CachedPackage {
private final Map<String, Optional<Class<?>>> cache; private final Map<String, Optional<Class<?>>> cache;
private final String packageName; private final String packageName;
private final ClassSource source; private final ClassSource source;
/** /**
* Construct a new cached package. * Construct a new cached package.
* @param packageName - the name of the current package. * @param packageName - the name of the current package.
@ -44,16 +43,20 @@ class CachedPackage {
this.cache = Maps.newConcurrentMap(); this.cache = Maps.newConcurrentMap();
this.source = source; this.source = source;
} }
/** /**
* Associate a given class with a class name. * Associate a given class with a class name.
* @param className - class name. * @param className - class name.
* @param clazz - type of class. * @param clazz - type of class.
*/ */
public void setPackageClass(String className, Class<?> clazz) { public void setPackageClass(String className, Class<?> clazz) {
cache.put(className, Optional.<Class<?>>fromNullable(clazz)); if (clazz != null) {
cache.put(className, Optional.<Class<?>> of(clazz));
} else {
cache.remove(className);
}
} }
/** /**
* Retrieve the class object of a specific class in the current package. * Retrieve the class object of a specific class in the current package.
* @param className - the specific class. * @param className - the specific class.
@ -61,28 +64,30 @@ class CachedPackage {
* @throws RuntimeException If we are unable to find the given class. * @throws RuntimeException If we are unable to find the given class.
*/ */
public Class<?> getPackageClass(String className) { public Class<?> getPackageClass(String className) {
try { Preconditions.checkNotNull(className, "className cannot be null!");
Optional<Class<?>> result = cache.get(Preconditions.checkNotNull(className, "className cannot be NULL"));
// Concurrency is not a problem - we don't care if we look up a class twice // See if we've already looked it up
if (result == null) { if (cache.containsKey(className)) {
// Look up the class dynamically Optional<Class<?>> result = cache.get(className);
result = Optional.<Class<?>>fromNullable(source.loadClass(combine(packageName, className)));
if (!result.isPresent())
throw new IllegalArgumentException("Source " + source + " returned NULL for " + className);
cache.put(className, result);
}
// Class has been looked for and hasn't been found in the past
if (!result.isPresent()) { if (!result.isPresent()) {
throw new ClassNotFoundException(); throw new RuntimeException("Cannot find class " + className);
} }
return result.get(); return result.get();
} catch (ClassNotFoundException e) { }
setPackageClass(className, null);
throw new RuntimeException("Cannot find class " + combine(packageName, className), e); try {
// Try looking it up
Class<?> clazz = source.loadClass(combine(packageName, className));
if (clazz == null) {
throw new IllegalArgumentException("Source " + source + " returned null for " + className);
}
cache.put(className, Optional.<Class<?>> of(clazz));
return clazz;
} catch (ClassNotFoundException ex) {
cache.put(className, Optional.<Class<?>> absent());
throw new RuntimeException("Cannot find class " + className, ex);
} }
} }

Datei anzeigen

@ -63,8 +63,8 @@ import com.comphenix.protocol.reflect.fuzzy.FuzzyClassContract;
import com.comphenix.protocol.reflect.fuzzy.FuzzyFieldContract; import com.comphenix.protocol.reflect.fuzzy.FuzzyFieldContract;
import com.comphenix.protocol.reflect.fuzzy.FuzzyMatchers; import com.comphenix.protocol.reflect.fuzzy.FuzzyMatchers;
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract; import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
import com.comphenix.protocol.utility.RemappedClassSource.RemapperUnavaibleException; import com.comphenix.protocol.utility.RemappedClassSource.RemapperUnavailableException;
import com.comphenix.protocol.utility.RemappedClassSource.RemapperUnavaibleException.Reason; import com.comphenix.protocol.utility.RemappedClassSource.RemapperUnavailableException.Reason;
import com.comphenix.protocol.wrappers.nbt.NbtFactory; import com.comphenix.protocol.wrappers.nbt.NbtFactory;
import com.comphenix.protocol.wrappers.nbt.NbtType; import com.comphenix.protocol.wrappers.nbt.NbtType;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
@ -934,6 +934,9 @@ public class MinecraftReflection {
return getMinecraftClass("MinecraftServer"); return getMinecraftClass("MinecraftServer");
} catch (RuntimeException e) { } catch (RuntimeException e) {
useFallbackServer(); useFallbackServer();
// Reset cache and try again
setMinecraftClass("MinecraftServer", null);
return getMinecraftClass("MinecraftServer"); return getMinecraftClass("MinecraftServer");
} }
} }
@ -982,8 +985,10 @@ public class MinecraftReflection {
try { try {
return getMinecraftClass("ServerConfigurationManager", "PlayerList"); return getMinecraftClass("ServerConfigurationManager", "PlayerList");
} catch (RuntimeException e) { } catch (RuntimeException e) {
// Try again
useFallbackServer(); useFallbackServer();
// Reset cache and try again
setMinecraftClass("ServerConfigurationManager", null);
return getMinecraftClass("ServerConfigurationManager"); return getMinecraftClass("ServerConfigurationManager");
} }
} }
@ -1628,8 +1633,10 @@ public class MinecraftReflection {
try { try {
return getMinecraftClass("AttributeModifier"); return getMinecraftClass("AttributeModifier");
} catch (RuntimeException e) { } catch (RuntimeException e) {
// Initialize first
getAttributeSnapshotClass(); getAttributeSnapshotClass();
// Reset cache and try again
setMinecraftClass("AttributeModifier", null);
return getMinecraftClass("AttributeModifier"); return getMinecraftClass("AttributeModifier");
} }
} }
@ -2108,7 +2115,7 @@ public class MinecraftReflection {
// Attempt to use MCPC // Attempt to use MCPC
try { try {
return classSource = new RemappedClassSource().initialize(); return classSource = new RemappedClassSource().initialize();
} catch (RemapperUnavaibleException e) { } catch (RemapperUnavailableException e) {
if (e.getReason() != Reason.MCPC_NOT_PRESENT) if (e.getReason() != Reason.MCPC_NOT_PRESENT)
reporter.reportWarning(MinecraftReflection.class, Report.newBuilder(REPORT_CANNOT_FIND_MCPC_REMAPPER)); reporter.reportWarning(MinecraftReflection.class, Report.newBuilder(REPORT_CANNOT_FIND_MCPC_REMAPPER));
} catch (Exception e) { } catch (Exception e) {

Datei anzeigen

@ -28,7 +28,7 @@ import org.bukkit.Server;
import com.comphenix.protocol.reflect.FieldUtils; import com.comphenix.protocol.reflect.FieldUtils;
import com.comphenix.protocol.reflect.MethodUtils; import com.comphenix.protocol.reflect.MethodUtils;
import com.comphenix.protocol.utility.RemappedClassSource.RemapperUnavaibleException.Reason; import com.comphenix.protocol.utility.RemappedClassSource.RemapperUnavailableException.Reason;
class RemappedClassSource extends ClassSource { class RemappedClassSource extends ClassSource {
private Object classRemapper; private Object classRemapper;
@ -53,7 +53,7 @@ class RemappedClassSource extends ClassSource {
/** /**
* Attempt to load the MCPC remapper. * Attempt to load the MCPC remapper.
* @return TRUE if we succeeded, FALSE otherwise. * @return TRUE if we succeeded, FALSE otherwise.
* @throws RemapperUnavaibleException If the remapper is not present. * @throws RemapperUnavailableException If the remapper is not present.
*/ */
public RemappedClassSource initialize() { public RemappedClassSource initialize() {
try { try {
@ -64,14 +64,14 @@ class RemappedClassSource extends ClassSource {
String version = server.getVersion(); String version = server.getVersion();
if (!version.contains("MCPC") && !version.contains("Cauldron")) { if (!version.contains("MCPC") && !version.contains("Cauldron")) {
throw new RemapperUnavaibleException(Reason.MCPC_NOT_PRESENT); throw new RemapperUnavailableException(Reason.MCPC_NOT_PRESENT);
} }
// Obtain the Class remapper used by MCPC+/Cauldron // Obtain the Class remapper used by MCPC+/Cauldron
this.classRemapper = FieldUtils.readField(getClass().getClassLoader(), "remapper", true); this.classRemapper = FieldUtils.readField(getClass().getClassLoader(), "remapper", true);
if (this.classRemapper == null) { if (this.classRemapper == null) {
throw new RemapperUnavaibleException(Reason.REMAPPER_DISABLED); throw new RemapperUnavailableException(Reason.REMAPPER_DISABLED);
} }
// Initialize some fields and methods used by the Jar Remapper // Initialize some fields and methods used by the Jar Remapper
@ -82,7 +82,7 @@ class RemappedClassSource extends ClassSource {
return this; return this;
} catch (RemapperUnavaibleException e) { } catch (RemapperUnavailableException e) {
throw e; throw e;
} catch (Exception e) { } catch (Exception e) {
// Damn it // Damn it
@ -115,7 +115,7 @@ class RemappedClassSource extends ClassSource {
} }
} }
public static class RemapperUnavaibleException extends RuntimeException { public static class RemapperUnavailableException extends RuntimeException {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public enum Reason { public enum Reason {
@ -139,7 +139,7 @@ class RemappedClassSource extends ClassSource {
private final Reason reason; private final Reason reason;
public RemapperUnavaibleException(Reason reason) { public RemapperUnavailableException(Reason reason) {
super(reason.getMessage()); super(reason.getMessage());
this.reason = reason; this.reason = reason;
} }