Alternative @SidedProxy setter for Scala.

This commit is contained in:
Florian Nücke committed 2013-05-08 05:36:28 +02:00
1 parent 49111e9c5c
commit 23b070c7d0
1 file changed
+47
@@ -1,6 +1,8 @@
package cpw.mods.fml.common;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public interface ILanguageAdapter {
public Object getNewInstance(FMLModContainer container, Class<?> objectClass, ClassLoader classLoader) throws Exception;
@@ -24,6 +26,51 @@ public interface ILanguageAdapter {
@Override
public void setProxy(Field target, Class<?> proxyTarget, Object proxy) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException
{
try
{
// Check if the target class is a singleton, if so its
// implementation's class name is the actual classname
// postfixed with a $.
final Class<?> targetSingleton = Class.forName(proxyTarget.getName() + "$", true, proxyTarget.getClassLoader());
// Get the instance via the MODULE$ field which is
// automatically generated by the scala compiler for
// singletons.
final Object targetInstance = targetSingleton.getField("MODULE$").get(null);
// Find setter function. We do it this way because we can't
// necessarily use proxyTarget.getMethod(proxy.getClass()), as
// it might be a subclass and not the exact parameter type.
// All fields are private in scala, wrapped by a getter and
// setter named <fieldname> and <fieldname>_$eq. To those
// familiar with scala.reflect.BeanProperty: these will always
// be there, set<Fieldname> and get<Fieldname> will always
// only be generated *additionally*.
final String setterName = target.getName() + "_$eq";
for (Method setter : proxyTarget.getMethods())
{
Class<?>[] setterParameters = setter.getParameterTypes();
if (setterName.equals(setter.getName()) &&
// Some more validation.
setterParameters.length == 1 &&
setterParameters[0].isAssignableFrom(proxy.getClass()))
{
// Here goes nothing... if this invocation fails we'll
// just fall back to the original functionality.
setter.invoke(targetInstance, proxy);
return;
}
}
}
catch (ClassNotFoundException e)
{
FMLLog.fine("This scala class is not a singleton (scala object), falling back to old proxy setter.");
}
catch (InvocationTargetException e)
{
FMLLog.fine("There's a problem with this proxy's setter, falling back to old proxy setter.");
}
Field field = proxyTarget.getField("INSTANCE");
Object scalaObject = field.get(null);
target.set(scalaObject, proxy);