/*
Copyright 2014 Lisovik Denis (Лисовик Денис) ckyberlis@gmail.com
This file is part of PPLoader.
PPLoader 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 3 of the License, or
(at your option) any later version.
PPLoader 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with PPLoader. If not, see <http://www.gnu.org/licenses/>
*/
package org.cyberlis.pyloader;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;
import org.bukkit.plugin.PluginLoader;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPluginLoader;
/**
*
*/
public class ReflectionHelper {
private static Map<Pattern, PluginLoader> fileAssociations = null;
private static JavaPluginLoader javapluginloader = null;
private static Map<String, ?> javaLoaders = null;
/**
* Retrieve SimplePluginManager.fileAssociations. inform the user if they're too cool for us
* (ie, they're using a different plugin manager)
* @param pm PluginManager to attempt to retrieve fileAssociations from
* @param errorstr string to print if we fail when we print reason we failed
* @return fileAssociations map
*/
@SuppressWarnings("unchecked")
public static Map<Pattern, PluginLoader> getFileAssociations(PluginManager pm, String errorstr) {
if (fileAssociations != null)
return fileAssociations;
Class<?> pmclass = null;
try {
pmclass = Class.forName("org.bukkit.plugin.SimplePluginManager");
} catch (ClassNotFoundException e) {
printerr("Did not find SimplePluginManager", errorstr);
} catch (Throwable t) {
printerr("Error while checking for SimplePluginManager", errorstr);
t.printStackTrace();
}
Field fieldFileAssociations = null;
if (pmclass != null) {
try {
fieldFileAssociations = pmclass.getDeclaredField("fileAssociations");
} catch (SecurityException e) {
printerr("SecurityException while checking for fileAssociations field in SimplePluginManager", errorstr);
e.printStackTrace();
} catch (NoSuchFieldException e) {
printerr("SimplePluginManager does not have fileAssociations field", errorstr);
} catch (Throwable t) {
printerr("Error while checking for fileAssociations field in SimplePluginManager", errorstr);
t.printStackTrace();
}
}
if (fieldFileAssociations != null) {
try {
fieldFileAssociations.setAccessible(true);
fileAssociations = (Map<Pattern, PluginLoader>) fieldFileAssociations.get(pm);
} catch (ClassCastException e) {
printerr("fileAssociations is not of type Map<Pattern, PluginLoader>", errorstr);
} catch (Throwable t) {
printerr("Error while getting fileAssociations from PluginManager", errorstr);
t.printStackTrace();
}
}
return fileAssociations;
}
/**
* Retrieve JavaPluginLoader from SimplePluginManager file associations
* @param pm plugin manager
* @return java plugin loader if found
*/
public static JavaPluginLoader getJavaPluginLoader(PluginManager pm) {
if (javapluginloader != null)
return javapluginloader;
getFileAssociations(pm, null);
for (Entry<Pattern, PluginLoader> entry : fileAssociations.entrySet()) {
if (entry.getKey().pattern().equals("\\.jar$"))
javapluginloader = (JavaPluginLoader) entry.getValue();
}
return javapluginloader;
}
/**
* Retrieve loaders field from JavaPluginLoader instance
* @param pm plugin manager to search for JavaPluginLoader in (if necessary)
* @return loaders field retrieved
*/
@SuppressWarnings("unchecked")
public static Map<String, ?> getJavaLoaders(PluginManager pm) {
if (javaLoaders != null)
return javaLoaders;
getJavaPluginLoader(pm);
if (javapluginloader == null)
return null;
try {
Field fieldLoaders = JavaPluginLoader.class.getDeclaredField("loaders");
fieldLoaders.setAccessible(true);
javaLoaders = (Map<String, ?>) fieldLoaders.get(javapluginloader);
return javaLoaders;
} catch (Throwable t) {
t.printStackTrace();
return null;
}
}
/**
* Use JavaPluginLoader.loaders field to determine if JavaPluginLoader has loaded a plugin (false if unable to determine)
* @param pm plugin manager to retrieve JavaPluginLoader instance from, if necessary
* @param name name of plugin to search for
* @return whether plugin is loaded
*/
public static boolean isJavaPluginLoaded(PluginManager pm, String name) {
getJavaLoaders(pm);
if (javaLoaders == null)
return false;
return javaLoaders.containsKey(name);
}
/**
* Set a private value. This version guesses the class with getClass().
* @param obj object to set the field in
* @param fieldName name of field to set
* @param newValue new value to set the field to
* @throws IllegalArgumentException can be thrown when setting the field
* @throws IllegalAccessException can be thrown when setting the field
* @throws SecurityException can be thrown when retrieving the field object
* @throws NoSuchFieldException can be thrown when retrieving the field object
*/
public static void setPrivateValue(Object obj, String fieldName, Object newValue) throws IllegalArgumentException, SecurityException, IllegalAccessException, NoSuchFieldException {
setPrivateValue(obj.getClass(), obj, fieldName, newValue);
}
/**
* Set a private value.
* @param containingClass class containing the field
* @param obj object to set the field in
* @param fieldName name of field to set
* @param newValue new value to set the field to
* @throws IllegalArgumentException can be thrown when setting the field
* @throws IllegalAccessException can be thrown when setting the field
* @throws SecurityException can be thrown when retrieving the field object
* @throws NoSuchFieldException can be thrown when retrieving the field object
*/
public static void setPrivateValue(Class<?> containingClass, Object obj, String fieldName, Object newValue) throws IllegalArgumentException, IllegalAccessException, SecurityException, NoSuchFieldException {
Field field = containingClass.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, newValue);
}
private static void printerr(String cause, String issue) {
if (issue != null)
System.err.println("PythonLoader: "+cause+", "+issue);
}
}