/* * This file is part of NucleusFramework for Bukkit, licensed under the MIT License (MIT). * * Copyright (c) JCThePants (www.jcwhatever.com) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.jcwhatever.nucleus.internal.managed.reflection; import com.jcwhatever.nucleus.managed.reflection.IReflection; import com.jcwhatever.nucleus.managed.reflection.Reflection; import com.jcwhatever.nucleus.utils.PreCon; import java.util.Map; import java.util.WeakHashMap; import java.util.regex.Pattern; /** * Internal implementation of {@link IReflection}. */ class ReflectionContext implements IReflection { static final String CRAFT_BASE_PACKAGE = "org.bukkit.craftbukkit"; static final String NMS_BASE_PACKAGE = "net.minecraft.server"; static final Pattern CRAFT_BASE_PACKAGE_PATTERN = Pattern.compile(CRAFT_BASE_PACKAGE); static final Pattern NMS_BASE_PACKAGE_PATTERN = Pattern.compile(NMS_BASE_PACKAGE); static final Map<Class<?>, CachedReflectedType> _typeCache = new WeakHashMap<>(30); static final Map<String, CachedReflectedType> _typeNameCache = new WeakHashMap<>(30); final String _nmsVersion; /** * Constructor. * * @param nmsVersion The nms version the instance is for. This is the version * package name used by the NMS classes. (i.e v1_8_R1) */ public ReflectionContext(String nmsVersion) { PreCon.notNullOrEmpty(nmsVersion); _nmsVersion = nmsVersion; } @Override public ReflectedType type(String className) { PreCon.notNullOrEmpty(className); CachedReflectedType type = _typeNameCache.get(className); if (type != null) return new ReflectedType(type); Class<?> clazz = classFromName(className); type = new CachedReflectedType(clazz); _typeNameCache.put(className, type); _typeCache.put(clazz, type); return new ReflectedType(type); } @Override public ReflectedType nmsType(String nmsClassName) { PreCon.notNullOrEmpty(nmsClassName); nmsClassName = NMS_BASE_PACKAGE + '.' + _nmsVersion + '.' + nmsClassName; return type(nmsClassName); } @Override public ReflectedType craftType(String craftClassName) { PreCon.notNullOrEmpty(craftClassName); craftClassName = CRAFT_BASE_PACKAGE + '.' + _nmsVersion + '.' + craftClassName; return type(craftClassName); } @Override public ReflectedType type(Class<?> clazz) { CachedReflectedType type = _typeCache.get(clazz); if (type != null) return new ReflectedType(type); type = new CachedReflectedType(clazz); _typeCache.put(clazz, type); return new ReflectedType(type); } /* * Gets a class from a class name. * * For primitive types, use the primitive name ie "int". * * For NMS and CraftBukkit classes, use the class name without * the craft package version. * * All other types, use full class name. */ private Class<?> classFromName(String versionlessClassName) { Class<?> primitive = Reflection.NAMES_TO_PRIMITIVES.get(versionlessClassName); if (primitive != null) return primitive; // try the name first try { return Class.forName(versionlessClassName); } catch (ClassNotFoundException ignore) {} // try alternatives String className; if (versionlessClassName.startsWith(CRAFT_BASE_PACKAGE)) { className = getCraftClassName(versionlessClassName); } else className = versionlessClassName.startsWith(NMS_BASE_PACKAGE) ? getNMSClassName(versionlessClassName) : versionlessClassName; try { return Class.forName(className); } catch (ClassNotFoundException e) { e.printStackTrace(); throw new RuntimeException("Failed to find class " + className); } } /* * Get the current CraftBukkit class name using a class name without a version. * * If the package name is org.bukkit.craftbukkit.v1_7_R0.CraftServer, then * the correct input is org.bukkit.craftbukkit.CraftServer */ private String getCraftClassName(String versionlessClassName) { return CRAFT_BASE_PACKAGE + CRAFT_BASE_PACKAGE_PATTERN.matcher(versionlessClassName) .replaceFirst(""); } /* * Get the current NMS class name using a class name without a version. * * If the package name is net.minecraft.server.v1_8_R1.CraftServer, then * the correct input is net.minecraft.server.CraftServer */ private String getNMSClassName(String versionlessClassName) { return NMS_BASE_PACKAGE + NMS_BASE_PACKAGE_PATTERN.matcher(versionlessClassName) .replaceFirst(""); } }