diff --git a/.classpath b/.classpath
index f80d362..4445cfe 100644
--- a/.classpath
+++ b/.classpath
@@ -3,6 +3,7 @@
-
+
+
diff --git a/.project b/.project
index 13b2083..b84c1fe 100644
--- a/.project
+++ b/.project
@@ -1,17 +1,23 @@
-
-
- jywrapper
-
-
-
-
-
- org.eclipse.jdt.core.javabuilder
-
-
-
-
-
- org.eclipse.jdt.core.javanature
-
-
+
+
+ jywrapper
+
+
+
+
+
+ org.python.pydev.PyDevBuilder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.python.pydev.pythonNature
+
+
diff --git a/src/main/java/net/abhinavsarkar/jywrapper/JyWrapper.java b/src/main/java/net/abhinavsarkar/jywrapper/JyWrapper.java
index bf4de37..28f9e46 100644
--- a/src/main/java/net/abhinavsarkar/jywrapper/JyWrapper.java
+++ b/src/main/java/net/abhinavsarkar/jywrapper/JyWrapper.java
@@ -1,89 +1,92 @@
-package net.abhinavsarkar.jywrapper;
-
-import static net.abhinavsarkar.jywrapper.Messages._;
-
-
-import net.abhinavsarkar.jywrapper.annotation.Wraps;
-import net.abhinavsarkar.jywrapper.exception.PythonImportNotFoundException;
-
-import org.python.core.PyFunction;
-import org.python.core.PyModule;
-import org.python.core.PyObject;
-import org.python.core.PyType;
-
-/**
- * @author Abhinav Sarkar
- *
- * @param The type of the java class to wrap the Python class/module with.
- */
-public final class JyWrapper {
-
- private JyWrapper() {
- }
-
- public static T wrap(final Class javaClass) {
- final Wraps annotation = javaClass.getAnnotation(Wraps.class);
- if (annotation == null) {
- throw new PythonImportNotFoundException(_("JyWrapper.7", javaClass)); //$NON-NLS-1$
- }
-
- return wrap(javaClass, annotation.value());
- }
-
- /**
- * @param pyImportName The full import name of the Python class/module
- * to wrap.
- * @return An instance of {@link UninitedPyObjectWrapper}, ready to be
- * initialized.
- * @throws IllegalStateException Thrown if the java Class to be used to
- * wrap the Python module/class, has not been supplied by earlier
- * calling {@link JyWrapper#with(Class)}.
- * @throws IllegalArgumentException Thrown if the pyImportName parameter
- * is null.
- */
- public static T wrap(final Class javaClass, final String pyImportName) {
- if (javaClass == null) {
- throw new IllegalStateException(_("JyWrapper.6", "javaClass")); //$NON-NLS-1$ //$NON-NLS-2$
- }
- if (pyImportName == null) {
- throw new IllegalArgumentException(_("JyWrapper.6", "pyImportName")); //$NON-NLS-1$ //$NON-NLS-2$
- }
-
- final PyObject pyImport = PyImportLoader.loadPyImport(pyImportName);
- if (!(pyImport instanceof PyType || pyImport instanceof PyModule)) {
- throw new IllegalArgumentException(_("JyWrapper.5", pyImportName)); //$NON-NLS-1$
- }
- return Util.py2Java(pyImport, javaClass);
- }
-
- /**
- * @param The return type of the {@link PyCallable} instance.
- * @param pyImportName The full import name of the Python function to wrap.
- * @param returnType The class of the return type.
- * @return An instance of {@link PyCallable} which wraps the
- * Python function given in parameter.
- * @throws IllegalArgumentException Thrown if the any of the parameters
- * supplied are null or if the pyImportName parameter supplied does not
- * correspond to a Python function.
- */
- public static PyCallable wrapPyFunction(
- final String pyImportName, final Class returnType) {
- if (pyImportName == null) {
- throw new IllegalArgumentException(_("JyWrapper.6", "pyImportName")); //$NON-NLS-1$ //$NON-NLS-2$
- }
- if (returnType == null) {
- throw new IllegalArgumentException(_("JyWrapper.6", "returnType")); //$NON-NLS-1$ //$NON-NLS-2$
- }
-
- final PyObject pyImport = PyImportLoader.loadPyImport(pyImportName);
- if (!(pyImport instanceof PyFunction)) {
- throw new IllegalArgumentException(_("JyWrapper.0", pyImportName)); //$NON-NLS-1$
- }
-
- @SuppressWarnings("unchecked")
- final PyCallable newInstance = PyObjectProxy.newInstance(
- pyImport, PyCallable.class);
- return newInstance;
- }
-
-}
+package net.abhinavsarkar.jywrapper;
+
+import static net.abhinavsarkar.jywrapper.Messages._;
+
+
+import net.abhinavsarkar.jywrapper.annotation.Wraps;
+import net.abhinavsarkar.jywrapper.exception.PythonImportNotFoundException;
+
+import org.python.core.PyClass;
+import org.python.core.PyFunction;
+import org.python.core.PyModule;
+import org.python.core.PyObject;
+import org.python.core.PyType;
+
+/**
+ * @author Abhinav Sarkar
+ *
+ * @param The type of the java class to wrap the Python class/module with.
+ */
+public final class JyWrapper {
+
+ private JyWrapper() {
+ }
+
+ public static T wrap(final Class javaClass) {
+ final Wraps annotation = javaClass.getAnnotation(Wraps.class);
+ if (annotation == null) {
+ throw new PythonImportNotFoundException(_("JyWrapper.7", javaClass)); //$NON-NLS-1$
+ }
+
+ return wrap(javaClass, annotation.value());
+ }
+
+ /**
+ * @param pyImportName The full import name of the Python class/module
+ * to wrap.
+ * @return An instance of {@link UninitedPyObjectWrapper}, ready to be
+ * initialized.
+ * @throws IllegalStateException Thrown if the java Class to be used to
+ * wrap the Python module/class, has not been supplied by earlier
+ * calling {@link JyWrapper#with(Class)}.
+ * @throws IllegalArgumentException Thrown if the pyImportName parameter
+ * is null.
+ */
+ public static T wrap(final Class javaClass, final String pyImportName) {
+ if (javaClass == null) {
+ throw new IllegalStateException(_("JyWrapper.6", "javaClass")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ if (pyImportName == null) {
+ throw new IllegalArgumentException(_("JyWrapper.6", "pyImportName")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ final PyObject pyImport = PyImportLoader.loadPyImport(pyImportName);
+ if (!(pyImport instanceof PyType
+ || pyImport instanceof PyModule
+ || pyImport instanceof PyClass)) {
+ throw new IllegalArgumentException(_("JyWrapper.5", pyImportName)); //$NON-NLS-1$
+ }
+ return Util.py2Java(pyImport, javaClass);
+ }
+
+ /**
+ * @param The return type of the {@link PyCallable} instance.
+ * @param pyImportName The full import name of the Python function to wrap.
+ * @param returnType The class of the return type.
+ * @return An instance of {@link PyCallable} which wraps the
+ * Python function given in parameter.
+ * @throws IllegalArgumentException Thrown if the any of the parameters
+ * supplied are null or if the pyImportName parameter supplied does not
+ * correspond to a Python function.
+ */
+ public static PyCallable wrapPyFunction(
+ final String pyImportName, final Class returnType) {
+ if (pyImportName == null) {
+ throw new IllegalArgumentException(_("JyWrapper.6", "pyImportName")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ if (returnType == null) {
+ throw new IllegalArgumentException(_("JyWrapper.6", "returnType")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ final PyObject pyImport = PyImportLoader.loadPyImport(pyImportName);
+ if (!(pyImport instanceof PyFunction)) {
+ throw new IllegalArgumentException(_("JyWrapper.0", pyImportName)); //$NON-NLS-1$
+ }
+
+ @SuppressWarnings("unchecked")
+ final PyCallable newInstance = PyObjectProxy.newInstance(
+ pyImport, PyCallable.class);
+ return newInstance;
+ }
+
+}
diff --git a/src/main/java/net/abhinavsarkar/jywrapper/Messages.java b/src/main/java/net/abhinavsarkar/jywrapper/Messages.java
index b51c668..755184d 100644
--- a/src/main/java/net/abhinavsarkar/jywrapper/Messages.java
+++ b/src/main/java/net/abhinavsarkar/jywrapper/Messages.java
@@ -1,28 +1,28 @@
-package net.abhinavsarkar.jywrapper;
-
-import java.text.MessageFormat;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
-
-final class Messages {
- private static final String BUNDLE_NAME = "net.abhinavsarkar.jywrapper.messages"; //$NON-NLS-1$
-
- private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
- .getBundle(BUNDLE_NAME);
-
- private Messages() {
- }
-
- public static String getString(String key) {
- try {
- return RESOURCE_BUNDLE.getString(key);
- } catch (MissingResourceException e) {
- return '!' + key + '!';
- }
- }
-
- public static String _(final String messageKey, final Object... arguments) {
- return new MessageFormat(getString(messageKey))
- .format(arguments, new StringBuffer(), null).toString();
- }
-}
+package net.abhinavsarkar.jywrapper;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+final class Messages {
+ private static final String BUNDLE_NAME = "net.abhinavsarkar.jywrapper.messages"; //$NON-NLS-1$
+
+ private static final ResourceBundle RESOURCE_BUNDLE =
+ ResourceBundle.getBundle(BUNDLE_NAME);
+
+ private Messages() {
+ }
+
+ public static String getString(final String key) {
+ try {
+ return RESOURCE_BUNDLE.getString(key);
+ } catch (final MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+
+ public static String _(final String messageKey, final Object... arguments) {
+ return new MessageFormat(getString(messageKey))
+ .format(arguments, new StringBuffer(), null).toString();
+ }
+}
diff --git a/src/main/java/net/abhinavsarkar/jywrapper/PyAttributeType.java b/src/main/java/net/abhinavsarkar/jywrapper/PyAttributeType.java
index 497bf12..6af6f75 100644
--- a/src/main/java/net/abhinavsarkar/jywrapper/PyAttributeType.java
+++ b/src/main/java/net/abhinavsarkar/jywrapper/PyAttributeType.java
@@ -1,17 +1,18 @@
-package net.abhinavsarkar.jywrapper;
-
-import net.abhinavsarkar.jywrapper.PyObjectProxy.MemberType;
-
-public enum PyAttributeType {
- GETTER(MemberType.GETTER), SETTER(MemberType.SETTER), CONST(MemberType.CONST);
-
- private final MemberType memberType;
-
- private PyAttributeType(MemberType memberType) {
- this.memberType = memberType;
- }
-
- public MemberType getMemberType() {
- return memberType;
- }
-}
+package net.abhinavsarkar.jywrapper;
+
+import net.abhinavsarkar.jywrapper.PyObjectProxy.MemberType;
+
+public enum PyAttributeType {
+
+ GETTER(MemberType.GETTER), SETTER(MemberType.SETTER), CONST(MemberType.CONST);
+
+ private final MemberType memberType;
+
+ private PyAttributeType(final MemberType memberType) {
+ this.memberType = memberType;
+ }
+
+ MemberType getMemberType() {
+ return memberType;
+ }
+}
diff --git a/src/main/java/net/abhinavsarkar/jywrapper/PyImportLoader.java b/src/main/java/net/abhinavsarkar/jywrapper/PyImportLoader.java
index 8298af9..1a9e05a 100644
--- a/src/main/java/net/abhinavsarkar/jywrapper/PyImportLoader.java
+++ b/src/main/java/net/abhinavsarkar/jywrapper/PyImportLoader.java
@@ -1,62 +1,62 @@
-package net.abhinavsarkar.jywrapper;
-
-import static net.abhinavsarkar.jywrapper.Messages._;
-
-import java.util.concurrent.ConcurrentHashMap;
-
-import net.abhinavsarkar.jywrapper.exception.PythonImportNotFoundException;
-
-import org.python.core.Py;
-import org.python.core.PyException;
-import org.python.core.PyObject;
-import org.python.core.PySystemState;
-
-/**
- * @author AbhinavSarkar
- *
- */
-public final class PyImportLoader {
-
- private static final PyObject importer = new PySystemState().getBuiltins()
- .__getitem__(Py.newString("__import__")); //$NON-NLS-1$
-
- private static final ConcurrentHashMap loadedPyImports =
- new ConcurrentHashMap();
-
- private PyImportLoader() {
- }
-
- /**
- * @param fullImportName
- * @return
- * @throws PythonImportNotFoundException
- */
- public static PyObject loadPyImport(String fullImportName)
- throws PythonImportNotFoundException {
- if (!loadedPyImports.containsKey(fullImportName)) {
- int i = fullImportName.lastIndexOf('.');
- String errorMsg = _("PyImportLoader.1", fullImportName); //$NON-NLS-1$
- PyObject pyImport;
- if (i == -1) {
- String pyModuleName = fullImportName;
- try {
- pyImport = importer.__call__(Py.newString(pyModuleName));
- } catch (PyException pye) {
- throw new PythonImportNotFoundException(errorMsg, pye);
- }
- } else {
- String pyModuleName = fullImportName.substring(0, i);
- String pyClassName = fullImportName.substring(i + 1);
-
- try {
- pyImport = importer.__call__(Py.newString(pyModuleName))
- .__getattr__(pyClassName);
- } catch (PyException pye) {
- throw new PythonImportNotFoundException(errorMsg, pye);
- }
- }
- loadedPyImports.putIfAbsent(fullImportName, pyImport);
- }
- return loadedPyImports.get(fullImportName);
- }
-}
+package net.abhinavsarkar.jywrapper;
+
+import static net.abhinavsarkar.jywrapper.Messages._;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+import net.abhinavsarkar.jywrapper.exception.PythonImportNotFoundException;
+
+import org.python.core.Py;
+import org.python.core.PyException;
+import org.python.core.PyObject;
+import org.python.core.PySystemState;
+
+/**
+ * @author AbhinavSarkar
+ *
+ */
+public final class PyImportLoader {
+
+ private static final PyObject importer = new PySystemState().getBuiltins()
+ .__getitem__(Py.newString("__import__")); //$NON-NLS-1$
+
+ private static final ConcurrentHashMap loadedPyImports =
+ new ConcurrentHashMap();
+
+ private PyImportLoader() {
+ }
+
+ /**
+ * @param fullImportName
+ * @return
+ * @throws PythonImportNotFoundException
+ */
+ public static PyObject loadPyImport(final String fullImportName)
+ throws PythonImportNotFoundException {
+ if (!loadedPyImports.containsKey(fullImportName)) {
+ final int i = fullImportName.lastIndexOf('.');
+ final String errorMsg = _("PyImportLoader.1", fullImportName); //$NON-NLS-1$
+ PyObject pyImport;
+ if (i == -1) {
+ final String pyModuleName = fullImportName;
+ try {
+ pyImport = importer.__call__(Py.newString(pyModuleName));
+ } catch (final PyException pye) {
+ throw new PythonImportNotFoundException(errorMsg, pye);
+ }
+ } else {
+ final String pyModuleName = fullImportName.substring(0, i);
+ final String pyClassName = fullImportName.substring(i + 1);
+
+ try {
+ pyImport = importer.__call__(Py.newString(pyModuleName))
+ .__getattr__(pyClassName);
+ } catch (final PyException pye) {
+ throw new PythonImportNotFoundException(errorMsg, pye);
+ }
+ }
+ loadedPyImports.putIfAbsent(fullImportName, pyImport);
+ }
+ return loadedPyImports.get(fullImportName);
+ }
+}
diff --git a/src/main/java/net/abhinavsarkar/jywrapper/PyMethodType.java b/src/main/java/net/abhinavsarkar/jywrapper/PyMethodType.java
index 0782b06..c35c721 100644
--- a/src/main/java/net/abhinavsarkar/jywrapper/PyMethodType.java
+++ b/src/main/java/net/abhinavsarkar/jywrapper/PyMethodType.java
@@ -1,20 +1,20 @@
-package net.abhinavsarkar.jywrapper;
-
-import net.abhinavsarkar.jywrapper.PyObjectProxy.MemberType;
-
-public enum PyMethodType {
- INIT(MemberType.INIT),
- DIRECT(MemberType.DIRECT),
- UNDERSCORED(MemberType.UNDERSCORED),
- NUMERIC(MemberType.NUMERIC);
-
- private final MemberType memberType;
-
- private PyMethodType(MemberType memberType) {
- this.memberType = memberType;
- }
-
- public MemberType getMemberType() {
- return memberType;
- }
-}
+package net.abhinavsarkar.jywrapper;
+
+import net.abhinavsarkar.jywrapper.PyObjectProxy.MemberType;
+
+public enum PyMethodType {
+ INIT (MemberType.INIT),
+ DIRECT (MemberType.DIRECT),
+ UNDERSCORED (MemberType.UNDERSCORED),
+ NUMERIC (MemberType.NUMERIC);
+
+ private final MemberType memberType;
+
+ private PyMethodType(final MemberType memberType) {
+ this.memberType = memberType;
+ }
+
+ MemberType getMemberType() {
+ return memberType;
+ }
+}
diff --git a/src/main/java/net/abhinavsarkar/jywrapper/PyObjectProxy.java b/src/main/java/net/abhinavsarkar/jywrapper/PyObjectProxy.java
index 70bafc3..6c9efe6 100644
--- a/src/main/java/net/abhinavsarkar/jywrapper/PyObjectProxy.java
+++ b/src/main/java/net/abhinavsarkar/jywrapper/PyObjectProxy.java
@@ -1,584 +1,599 @@
-/**
- *
- */
-package net.abhinavsarkar.jywrapper;
-
-import static net.abhinavsarkar.jywrapper.Messages._;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.util.concurrent.ConcurrentHashMap;
-
-import net.abhinavsarkar.jywrapper.annotation.PyAttribute;
-import net.abhinavsarkar.jywrapper.annotation.PyMethod;
-import net.abhinavsarkar.jywrapper.exception.PythonImportInstantiationError;
-
-import org.python.core.Py;
-import org.python.core.PyException;
-import org.python.core.PyFunction;
-import org.python.core.PyModule;
-import org.python.core.PyObject;
-import org.python.core.PyProperty;
-import org.python.core.PyProxy;
-import org.python.core.PyType;
-
-final class PyObjectProxy implements InvocationHandler {
-
- private static final String JAVA_COMPARE_METHOD_NAME = "compareTo"; //$NON-NLS-1$
-
- private static final String GETTER_METHOD_PREFIX = "get"; //$NON-NLS-1$
-
- private static final String SETTER_METHOD_PREFIX = "set"; //$NON-NLS-1$
-
- private static final String CONST_METHOD_PREFIX = "const"; //$NON-NLS-1$
-
- private static enum JavaSpecialMethod {
- equals("__eq__"), hashCode("__hash__"), toString("__str__"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-
- private final String pyEquiv;
-
- private JavaSpecialMethod(final String pyEquiv) {
- this.pyEquiv = pyEquiv;
- }
-
- public static Object invoke(final PyObject pyObject, final Method method,
- final Object[] args) throws NoSuchMethodException {
- try {
- return invokePyMethod(pyObject, method.getReturnType(),
- JavaSpecialMethod.valueOf(method.getName()).pyEquiv, args);
- } catch (final IllegalArgumentException ex) {
- throw new NoSuchMethodException();
- }
- }
- }
-
- private static enum NumericMethod {
- add ("__add__"), //$NON-NLS-1$
- subtract ("__sub__"), //$NON-NLS-1$
- multiply ("__mul__"), //$NON-NLS-1$
- divide ("__div__"), //$NON-NLS-1$
- divideAndRemainder ("__divmod__"), //$NON-NLS-1$
- remainder ("__mod__"), //$NON-NLS-1$
- pow ("__pow__"), //$NON-NLS-1$
- negate ("__neg__"), //$NON-NLS-1$
- plus ("__pos__"), //$NON-NLS-1$
- abs ("__abs__"), //$NON-NLS-1$
- and ("__and__"), //$NON-NLS-1$
- or ("__or__"), //$NON-NLS-1$
- xor ("__xor__"), //$NON-NLS-1$
- invert ("__invert__"), //$NON-NLS-1$
- intValue ("__int__"), //$NON-NLS-1$
- longValue ("__long__"), //$NON-NLS-1$
- floatValue ("__float__"); //$NON-NLS-1$
-
- private final String pyEquiv;
-
- private NumericMethod(final String pyEquiv) {
- this.pyEquiv = pyEquiv;
- }
-
- public static Object invoke(final PyObject pyObject, final Method method,
- final Object[] args) throws NoSuchMethodException {
- try {
- return findAndInvokePyMethod(pyObject,
- method.getReturnType(),
- NumericMethod.valueOf(method.getName()).pyEquiv, args);
- } catch (final IllegalArgumentException ex) {
- throw new NoSuchMethodException();
- }
- }
- }
-
- private static enum PyProxyInterfaceMethod {
- _setPyInstance, _setPySystemState, __initProxy__, _getPySystemState,
- _getPyInstance {
- @Override
- public Object invoke(final PyObject pyObject) {
- return new Throwable().getStackTrace()[4].getClassName()
- .startsWith("org.python") ? pyObject : null;
- }
- };
-
- public Object invoke(final PyObject pyObject) {
- return Void.TYPE;
- }
- }
-
- static enum MemberType {
- INIT {
- @Override
- public Object invoke(final PyObject pyObject, final Class> javaClass,
- final Method method, final Object[] args, final String pyImportName)
- throws NoSuchMethodException {
- final PyMethod annotation = method.getAnnotation(PyMethod.class);
-
- if (annotation != null
- && annotation.type() == PyMethodType.INIT) {
- synchronized (pyObject) {
- return initialize(pyObject, pyImportName, javaClass, args);
- }
- }
- throw new NoSuchMethodException(
- _("JyWrapper.15", "initialization method", //$NON-NLS-1$ //$NON-NLS-2$
- method.getName(), pyImportName));
- }
- },
- CALL {
- @Override
- public Object invoke(final PyObject pyObject, final Class> javaClass,
- final Method method, final Object[] args, final String pyImportName)
- throws NoSuchMethodException {
- if (javaClass.equals(PyCallable.class)
- && pyObject instanceof PyFunction
- && "call".equals(method.getName())) { //$NON-NLS-1$
- return invokePyMethod(pyObject, method.getReturnType(),
- "__call__", (Object[]) args[0]); //$NON-NLS-1$
- }
- throw new NoSuchMethodException();
- }
- },
- DIRECT {
- @Override
- public Object invoke(final PyObject pyObject, final Class> javaClass,
- final Method method, final Object[] args, final String pyImportName)
- throws NoSuchMethodException {
- String methodName = method.getName();
- final PyMethod annotation = method.getAnnotation(PyMethod.class);
- if (annotation != null
- && annotation.type() == PyMethodType.DIRECT) {
- final String name = annotation.method();
- if (!"".equals(name)) { //$NON-NLS-1$
- methodName = name;
- }
- }
- try {
- return findAndInvokePyMethod(pyObject,
- method.getReturnType(), methodName, args);
- } catch (final NoSuchMethodException e) {
- throw new NoSuchMethodException(
- _("JyWrapper.15", "direct method", //$NON-NLS-1$ //$NON-NLS-2$
- methodName, pyImportName));
- }
- }
- },
- UNDERSCORED {
- @Override
- public Object invoke(final PyObject pyObject, final Class> javaClass,
- final Method method, final Object[] args, final String pyImportName)
- throws NoSuchMethodException {
- try {
- return findAndInvokePyMethod(pyObject,
- method.getReturnType(),
- Util.camelCase2UnderScore(method.getName()), args);
- } catch (final NoSuchMethodException e) {
- throw new NoSuchMethodException(
- _("JyWrapper.15", "underscored method", //$NON-NLS-1$ //$NON-NLS-2$
- method.getName(), pyImportName));
- }
- }
- },
- COMPARE {
- @Override
- public Object invoke(final PyObject pyObject, final Class> javaClass,
- final Method method, final Object[] args, final String pyImportName)
- throws NoSuchMethodException {
- for (final RichComparisonOperator compOp : RichComparisonOperator.values()) {
- try {
- if ((Boolean) findAndInvokePyMethod(pyObject,
- Boolean.class, compOp.name(), args)) {
- return compOp.returnValue();
- }
- } catch (final PyException e) {
- if (e.type.equals(Py.NotImplementedError)) {
- // the comparison operator is not implemented. move on.
- continue;
- }
- throw e;
- }
- }
-
- try {
- return (Integer) findAndInvokePyMethod(
- pyObject, Integer.class, "__cmp__", args); //$NON-NLS-1$
- } catch (final PyException e) {
- if (!e.type.equals(Py.NotImplementedError)) {
- throw e;
- }
- }
- throw new NoSuchMethodException(_("JyWrapper.11")); //$NON-NLS-1$
- }
- },
- SPECIAL {
- @Override
- public Object invoke(final PyObject pyObject, final Class> javaClass,
- final Method method, final Object[] args, final String pyImportName)
- throws NoSuchMethodException {
- return JavaSpecialMethod.invoke(pyObject, method, args);
- }
- },
- PYPROXY_INTERFACE {
- @Override
- public Object invoke(final PyObject pyObject, final Class> javaClass,
- final Method method, final Object[] args, final String pyImportName)
- throws NoSuchMethodException {
- try {
- return PyProxyInterfaceMethod.valueOf(method.getName())
- .invoke(pyObject);
- } catch (final IllegalArgumentException ex) {
- throw new NoSuchMethodException();
- }
- }
- },
- GETTER {
- @Override
- public Object invoke(final PyObject pyObject, final Class> javaClass,
- final Method method, final Object[] args, final String pyImportName)
- throws NoSuchMethodException {
- final PyAttribute annotation = method.getAnnotation(PyAttribute.class);
- final String methodName = method.getName();
- PyObject attrValue = null;
- String attrName = methodName;
-
- if (annotation != null
- && annotation.type() == PyAttributeType.GETTER) {
- attrName = annotation.attribute();
- if (!"".equals(attrName)) { //$NON-NLS-1$
- synchronized (pyObject) {
- attrValue = pyObject.__findattr__(attrName);
- }
- }
- }
-
- if (attrValue == null && methodName.startsWith(GETTER_METHOD_PREFIX)) {
- attrName = Util.camelCase2UnderScore(methodName)
- .substring(GETTER_METHOD_PREFIX.length() + 1);
- synchronized (pyObject) {
- attrValue = pyObject.__findattr__(attrName);
- }
- }
-
- if (attrValue != null) {
- if (PyProperty.class.isAssignableFrom(attrValue.getClass())) {
- throw new IllegalArgumentException(_("JyWrapper.12", attrName)); //$NON-NLS-1$
- }
- return Util.py2Java(attrValue, method.getReturnType());
- }
-
- throw new NoSuchMethodException(
- _("JyWrapper.15", "instance attribute", //$NON-NLS-1$ //$NON-NLS-2$
- methodName, pyImportName));
- }
- },
- SETTER {
- @Override
- public Object invoke(final PyObject pyObject, final Class> javaClass,
- final Method method, final Object[] args, final String pyImportName)
- throws NoSuchMethodException, IllegalAccessException {
- final String methodName = method.getName();
- final PyAttribute annotation = method.getAnnotation(PyAttribute.class);
- String attrName = null;
-
- if (annotation != null
- && annotation.type() == PyAttributeType.SETTER) {
- attrName = annotation.attribute();
- if ("".equals(attrName)) { //$NON-NLS-1$
- attrName = null;
- }
- }
-
- if (attrName == null
- && methodName.startsWith(SETTER_METHOD_PREFIX)
- && args.length == 1) {
- attrName = Util.camelCase2UnderScore(methodName).substring(
- SETTER_METHOD_PREFIX.length() + 1);
- }
-
- if (attrName != null) {
- PyObject attrValue;
- synchronized (pyObject) {
- attrValue = pyObject.__findattr__(attrName);
- }
- if (attrValue != null) {
- if (PyProperty.class.isAssignableFrom(attrValue.getClass())) {
- throw new IllegalArgumentException(
- _("JyWrapper.14", attrName)); //$NON-NLS-1$
- }
- }
- try {
- final PyObject pyArgs = Py.java2py(args[0]);
- synchronized (pyObject) {
- pyObject.__setattr__(attrName, pyArgs);
- }
- return Void.TYPE;
- } catch (final PyException e) {
- if (e.type.equals(Py.AttributeError)
- && e.value.toString().equals(
- "can't set attribute")) { //$NON-NLS-1$
- throw new IllegalAccessException(
- _("JyWrapper.13", attrName)); //$NON-NLS-1$
- }
- throw e;
- }
- }
-
- throw new NoSuchMethodException(
- _("JyWrapper.15", "instance attribute", //$NON-NLS-1$ //$NON-NLS-2$
- methodName, pyImportName));
- }
- },
- CONST {
- @Override
- public Object invoke(final PyObject pyObject, final Class> javaClass,
- final Method method, final Object[] args, final String pyImportName)
- throws NoSuchMethodException {
- final PyAttribute annotation = method.getAnnotation(PyAttribute.class);
- final String methodName = method.getName();
- PyObject attrValue = null;
-
- if (annotation != null
- && annotation.type() == PyAttributeType.CONST) {
- final String attrName = annotation.attribute();
- if (!"".equals(attrName)) { //$NON-NLS-1$
- synchronized (pyObject) {
- attrValue = pyObject.__findattr__(attrName);
- }
- } else {
- synchronized (pyObject) {
- attrValue = pyObject.__findattr__(methodName);
- }
- }
- }
-
- if (attrValue == null
- && methodName.startsWith(CONST_METHOD_PREFIX)) {
- final String attrName = methodName
- .substring(CONST_METHOD_PREFIX.length());
- synchronized (pyObject) {
- attrValue = pyObject.__findattr__(attrName);
- }
- }
-
- if (attrValue != null) {
- return Util.py2Java(attrValue, method.getReturnType());
- }
-
- throw new NoSuchMethodException(
- _("JyWrapper.15", "constant", //$NON-NLS-1$ //$NON-NLS-2$
- methodName, pyImportName));
- }
- },
- NUMERIC {
- @Override
- public Object invoke(final PyObject pyObject, final Class> javaClass,
- final Method method, final Object[] args, final String pyImportName)
- throws NoSuchMethodException {
- try {
- return NumericMethod.invoke(pyObject, method, args);
- } catch (final NoSuchMethodException e) {
- throw new NoSuchMethodException(
- _("JyWrapper.15", "eqivalent numeric method", //$NON-NLS-1$ //$NON-NLS-2$
- method.getName(), pyImportName));
- }
- }
- },
- NO_SUCH_METHOD {
- @Override
- public Object invoke(final PyObject pyObject, final Class> javaClass,
- final Method method, final Object[] args, final String pyImportName)
- throws NoSuchMethodException {
- throw new NoSuchMethodException(
- _("JyWrapper.15", "method", method.getName(), pyImportName)); //$NON-NLS-1$ //$NON-NLS-2$
- }
- };
-
- public abstract Object invoke(PyObject pyObject, Class> javaClass,
- Method method, Object[] args, String pyImportName)
- throws NoSuchMethodException, IllegalAccessException;
- }
-
- private static enum RichComparisonOperator {
- __eq__(0), __lt__(-1), __gt__(1);
-
- private int returnValue;
-
- public int returnValue() { return returnValue; }
-
- private RichComparisonOperator(final int returnValue) {
- this.returnValue = returnValue;
- }
- }
-
- private final PyObject pyObject;
-
- private final Class> javaClass;
-
- private final String pyImportName;
-
- private static final ConcurrentHashMap METHOD_JUMP_TABLE =
- new ConcurrentHashMap();
-
- private PyObjectProxy(final PyObject pyObject, final Class> javaClass) {
- this.pyObject = pyObject;
- this.javaClass = javaClass;
- this.pyImportName = Util.getPyImportName(this.pyObject);
- }
-
- public static T newInstance(final PyObject pyObject,
- final Class javaClass) {
- if (javaClass.isInterface()) {
- ClassLoader classLoader = javaClass.getClassLoader();
- if (classLoader == null) {
- classLoader = ClassLoader.getSystemClassLoader();
- }
-
- @SuppressWarnings("unchecked")
- final T newProxyInstance = (T) Proxy.newProxyInstance(
- classLoader,
- new Class[] { javaClass, PyProxy.class },
- new PyObjectProxy(pyObject, javaClass));
- return newProxyInstance;
- } else {
- throw new IllegalArgumentException(_("JyWrapper.8", javaClass.getName())); //$NON-NLS-1$
- }
- }
-
- public Object invoke(final Object proxy, final Method method, final Object[] args)
- throws NoSuchMethodException, IllegalAccessException {
- final PyMethod pyMethodAnnotation = method.getAnnotation(PyMethod.class);
- if (pyMethodAnnotation != null) {
- return pyMethodAnnotation.type().getMemberType()
- .invoke(pyObject, javaClass, method, args, pyImportName);
- }
-
- final PyAttribute pyAttributeAnnotation = method.getAnnotation(PyAttribute.class);
- if (pyAttributeAnnotation != null) {
- return pyAttributeAnnotation.type().getMemberType()
- .invoke(pyObject, javaClass, method, args, pyImportName);
- }
-
- final String methodName = method.getName();
- if (!METHOD_JUMP_TABLE.containsKey(method)) {
- if (Comparable.class.isAssignableFrom(javaClass)
- && JAVA_COMPARE_METHOD_NAME.equals(methodName)) {
- //check if the method is "compareTo"
- METHOD_JUMP_TABLE.putIfAbsent(method, MemberType.COMPARE);
- } else {
- //check if the method is one of the special methods
- try {
- JavaSpecialMethod.valueOf(methodName);
- METHOD_JUMP_TABLE.putIfAbsent(method, MemberType.SPECIAL);
- } catch (final IllegalArgumentException ex) {
- //the method is not one of the special methods. move on.
-
- //check if the method is one of the PyProxy interface methods
- try {
- PyProxyInterfaceMethod.valueOf(methodName);
- METHOD_JUMP_TABLE.putIfAbsent(method, MemberType.PYPROXY_INTERFACE);
- } catch (final IllegalArgumentException e) {
- //the method is not one of the PyProxy interface methods.
- //move on.
- }
- }
- }
- }
-
- //check if the method has already been registered in the jump table
- //if so invoke it using the method type registered in the table
- if (METHOD_JUMP_TABLE.containsKey(method)) {
- return METHOD_JUMP_TABLE.get(method)
- .invoke(pyObject, javaClass, method, args, pyImportName);
- }
-
- // try each method types one by one to guess the correct one
- for (final MemberType methodType : MemberType.values()) {
- try {
- final Object retVal = methodType.invoke(
- pyObject, javaClass, method, args, pyImportName);
- METHOD_JUMP_TABLE.putIfAbsent(method, methodType);
- return retVal;
- } catch (final NoSuchMethodException ex) {
- continue;
- }
- }
-
- //all checks failed. throw NoSuchMethodException
- METHOD_JUMP_TABLE.putIfAbsent(method, MemberType.NO_SUCH_METHOD);
- throw new NoSuchMethodException(
- _("JyWrapper.15", "method", methodName, pyImportName)); //$NON-NLS-1$ //$NON-NLS-2$
- }
-
- /**
- * @param args Arguments to initialize the underlying Python class.
- * @param pyImport
- * @param pyImportName
- * @param javaClass
- * @return An initialized (wrapped) Python class instance, ready to be used.
- */
- private static T initialize(final PyObject pyImport, final String pyImportName,
- final Class javaClass, final Object... args) {
- if (javaClass == null) {
- throw new IllegalStateException(_("JyWrapper.6", "javaClass")); //$NON-NLS-1$ //$NON-NLS-2$
- }
- if (pyImportName == null) {
- throw new IllegalArgumentException(_("JyWrapper.6", "pyImportName")); //$NON-NLS-1$ //$NON-NLS-2$
- }
-
- if (pyImport instanceof PyModule) {
- throw new PythonImportInstantiationError(_("JyWrapper.4", pyImportName)); //$NON-NLS-1$
- }
- if (!(pyImport instanceof PyType)) {
- throw new PythonImportInstantiationError(_("JyWrapper.9")); //$NON-NLS-1$
- }
-
- try {
- return Util.py2Java(pyImport.__call__(Util.convertArgs(args)), javaClass);
- } catch (final PyException e) {
- if (e.type.equals(Py.TypeError)) {
- throw new PythonImportInstantiationError(
- _("JyWrapper.3", pyImportName), e); //$NON-NLS-1$
- }
- throw e;
- } catch (final IllegalArgumentException e) {
- throw new IllegalArgumentException(
- _("JyWrapper.2", pyImportName, javaClass.getName())); //$NON-NLS-1$
- }
- }
-
- private static Object findAndInvokePyMethod(final PyObject pyObject,
- final Class> javaReturnType, final String methodName, final Object[] args)
- throws NoSuchMethodException {
- PyObject pyAttr;
- synchronized (pyObject) {
- pyAttr = pyObject.__findattr__(methodName);
- }
- if (pyAttr instanceof org.python.core.PyMethod || pyAttr instanceof PyFunction) {
- return invokePyMethod(pyObject, javaReturnType, methodName, args);
- } else {
- throw new NoSuchMethodException();
- }
- }
-
- private static Object invokePyMethod(final PyObject pyObject,
- final Class> javaReturnType, final String methodName, final Object[] args) {
- PyObject pyReturnValue;
- try {
- final PyObject[] pyArgs = Util.convertArgs(args);
- synchronized (pyObject) {
- pyReturnValue = pyObject.invoke(methodName, pyArgs);
- }
- } catch (final PyException e) {
- if (e.type.equals(Py.TypeError)) {
- throw new IllegalArgumentException(
- _("JyWrapper.10", methodName), e); //$NON-NLS-1$
- }
- throw e;
- }
-
- if (pyReturnValue == Py.None) {
- return "void".equals(javaReturnType.getName()) ? Void.TYPE : null; //$NON-NLS-1$
- }
- return Util.py2Java(pyReturnValue, javaReturnType);
- }
-
+/**
+ *
+ */
+package net.abhinavsarkar.jywrapper;
+
+import static net.abhinavsarkar.jywrapper.Messages._;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.EnumSet;
+import java.util.concurrent.ConcurrentHashMap;
+
+import net.abhinavsarkar.jywrapper.annotation.PyAttribute;
+import net.abhinavsarkar.jywrapper.annotation.PyMethod;
+import net.abhinavsarkar.jywrapper.exception.PythonImportInstantiationError;
+
+import org.python.core.Py;
+import org.python.core.PyClass;
+import org.python.core.PyException;
+import org.python.core.PyFunction;
+import org.python.core.PyModule;
+import org.python.core.PyObject;
+import org.python.core.PyProperty;
+import org.python.core.PyProxy;
+import org.python.core.PyType;
+
+final class PyObjectProxy implements InvocationHandler {
+
+ private static final String JAVA_COMPARE_METHOD_NAME = "compareTo"; //$NON-NLS-1$
+
+ private static final String INIT_METHOD_NAME = "initialize"; //$NON-NLS-1$
+
+ private static final String GETTER_METHOD_PREFIX = "get"; //$NON-NLS-1$
+
+ private static final String SETTER_METHOD_PREFIX = "set"; //$NON-NLS-1$
+
+ private static final String CONST_METHOD_PREFIX = "const"; //$NON-NLS-1$
+
+ private static final EnumSet NON_ANNOTATED_MEMBERS =
+ EnumSet.of(MemberType.COMPARE, MemberType.SPECIAL, MemberType.PYPROXY_INTERFACE);
+
+ private static enum JavaSpecialMethod {
+ equals("__eq__"), hashCode("__hash__"), toString("__str__"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ private final String pyEquiv;
+
+ private JavaSpecialMethod(final String pyEquiv) {
+ this.pyEquiv = pyEquiv;
+ }
+
+ public static Object invoke(final PyObject pyObject, final Method method,
+ final Object[] args) throws NoSuchMethodException {
+ try {
+ return invokePyMethod(pyObject, method.getReturnType(),
+ JavaSpecialMethod.valueOf(method.getName()).pyEquiv, args);
+ } catch (final IllegalArgumentException ex) {
+ throw new NoSuchMethodException();
+ }
+ }
+ }
+
+ private static enum NumericMethod {
+ add ("__add__"), //$NON-NLS-1$
+ subtract ("__sub__"), //$NON-NLS-1$
+ multiply ("__mul__"), //$NON-NLS-1$
+ divide ("__div__"), //$NON-NLS-1$
+ divideAndRemainder ("__divmod__"), //$NON-NLS-1$
+ remainder ("__mod__"), //$NON-NLS-1$
+ pow ("__pow__"), //$NON-NLS-1$
+ negate ("__neg__"), //$NON-NLS-1$
+ plus ("__pos__"), //$NON-NLS-1$
+ abs ("__abs__"), //$NON-NLS-1$
+ and ("__and__"), //$NON-NLS-1$
+ or ("__or__"), //$NON-NLS-1$
+ xor ("__xor__"), //$NON-NLS-1$
+ invert ("__invert__"), //$NON-NLS-1$
+ intValue ("__int__"), //$NON-NLS-1$
+ longValue ("__long__"), //$NON-NLS-1$
+ floatValue ("__float__"); //$NON-NLS-1$
+
+ private final String pyEquiv;
+
+ private NumericMethod(final String pyEquiv) {
+ this.pyEquiv = pyEquiv;
+ }
+
+ public static Object invoke(final PyObject pyObject, final Method method,
+ final Object[] args) throws NoSuchMethodException {
+ try {
+ return findAndInvokePyMethod(
+ pyObject, method.getReturnType(),
+ NumericMethod.valueOf(method.getName()).pyEquiv, args);
+ } catch (final IllegalArgumentException ex) {
+ throw new NoSuchMethodException();
+ }
+ }
+ }
+
+ private static enum PyProxyInterfaceMethod {
+ _setPyInstance, _setPySystemState, __initProxy__, _getPySystemState,
+ _getPyInstance {
+ @Override
+ public Object invoke(final PyObject pyObject) {
+ return new Throwable().getStackTrace()[4].getClassName()
+ .startsWith("org.python") ? pyObject : null;
+ }
+ };
+
+ public Object invoke(final PyObject pyObject) {
+ return null;
+ }
+ }
+
+ static enum MemberType {
+ INIT {
+ @Override
+ public Object invoke(final PyObject pyObject, final Class> javaClass,
+ final Method method, final Object[] args, final String pyImportName)
+ throws NoSuchMethodException {
+ final PyMethod annotation = method.getAnnotation(PyMethod.class);
+
+ if (annotation != null && annotation.type() == PyMethodType.INIT) {
+ synchronized (pyObject) {
+ return initialize(pyObject, pyImportName, javaClass, args);
+ }
+ }
+
+ final String methodName = method.getName();
+ if (INIT_METHOD_NAME.equals(methodName)) {
+ synchronized (pyObject) {
+ return initialize(pyObject, pyImportName, javaClass, args);
+ }
+ }
+
+ throw new NoSuchMethodException(
+ _("JyWrapper.15", "initialization method", //$NON-NLS-1$ //$NON-NLS-2$
+ methodName, pyImportName));
+ }
+ },
+ CALL {
+ @Override
+ public Object invoke(final PyObject pyObject, final Class> javaClass,
+ final Method method, final Object[] args, final String pyImportName)
+ throws NoSuchMethodException {
+ if (javaClass.equals(PyCallable.class)
+ && pyObject instanceof PyFunction
+ && "call".equals(method.getName())) { //$NON-NLS-1$
+ return invokePyMethod(pyObject, method.getReturnType(),
+ "__call__", (Object[]) args[0]); //$NON-NLS-1$
+ }
+ throw new NoSuchMethodException();
+ }
+ },
+ DIRECT {
+ @Override
+ public Object invoke(final PyObject pyObject, final Class> javaClass,
+ final Method method, final Object[] args, final String pyImportName)
+ throws NoSuchMethodException {
+ String methodName = method.getName();
+
+ final PyMethod annotation = method.getAnnotation(PyMethod.class);
+ if (annotation != null && annotation.type() == PyMethodType.DIRECT) {
+ final String name = annotation.method();
+ if (!"".equals(name)) { //$NON-NLS-1$
+ methodName = name;
+ }
+ }
+ try {
+ return findAndInvokePyMethod(
+ pyObject, method.getReturnType(), methodName, args);
+ } catch (final NoSuchMethodException e) {
+ throw new NoSuchMethodException(
+ _("JyWrapper.15", "direct method", //$NON-NLS-1$ //$NON-NLS-2$
+ methodName, pyImportName));
+ }
+ }
+ },
+ UNDERSCORED {
+ @Override
+ public Object invoke(final PyObject pyObject, final Class> javaClass,
+ final Method method, final Object[] args, final String pyImportName)
+ throws NoSuchMethodException {
+ try {
+ return findAndInvokePyMethod(
+ pyObject, method.getReturnType(),
+ Util.camelCase2UnderScore(method.getName()), args);
+ } catch (final NoSuchMethodException e) {
+ throw new NoSuchMethodException(
+ _("JyWrapper.15", "underscored method", //$NON-NLS-1$ //$NON-NLS-2$
+ method.getName(), pyImportName));
+ }
+ }
+ },
+ COMPARE {
+ @Override
+ public Object invoke(final PyObject pyObject, final Class> javaClass,
+ final Method method, final Object[] args, final String pyImportName)
+ throws NoSuchMethodException {
+ for (final RichComparisonOperator compOp : RichComparisonOperator.values()) {
+ try {
+ if ((Boolean) findAndInvokePyMethod(
+ pyObject, Boolean.class, compOp.name(), args)) {
+ return compOp.returnValue();
+ }
+ } catch (final PyException e) {
+ if (e.type.equals(Py.NotImplementedError)) {
+ // the comparison operator is not implemented. move on.
+ continue;
+ }
+ throw e;
+ }
+ }
+
+ try {
+ return findAndInvokePyMethod(
+ pyObject, Integer.class, "__cmp__", args); //$NON-NLS-1$
+ } catch (final PyException e) {
+ if (!e.type.equals(Py.NotImplementedError)) {
+ throw e;
+ }
+ }
+ throw new NoSuchMethodException(_("JyWrapper.11")); //$NON-NLS-1$
+ }
+ },
+ SPECIAL {
+ @Override
+ public Object invoke(final PyObject pyObject, final Class> javaClass,
+ final Method method, final Object[] args, final String pyImportName)
+ throws NoSuchMethodException {
+ return JavaSpecialMethod.invoke(pyObject, method, args);
+ }
+ },
+ PYPROXY_INTERFACE {
+ @Override
+ public Object invoke(final PyObject pyObject, final Class> javaClass,
+ final Method method, final Object[] args, final String pyImportName)
+ throws NoSuchMethodException {
+ try {
+ return PyProxyInterfaceMethod.valueOf(method.getName())
+ .invoke(pyObject);
+ } catch (final IllegalArgumentException ex) {
+ throw new NoSuchMethodException();
+ }
+ }
+ },
+ GETTER {
+ @Override
+ public Object invoke(final PyObject pyObject, final Class> javaClass,
+ final Method method, final Object[] args, final String pyImportName)
+ throws NoSuchMethodException {
+ final PyAttribute annotation = method.getAnnotation(PyAttribute.class);
+ final String methodName = method.getName();
+ PyObject attrValue = null;
+ String attrName = methodName;
+
+ if (annotation != null && annotation.type() == PyAttributeType.GETTER) {
+ attrName = annotation.attribute();
+ if (!"".equals(attrName)) { //$NON-NLS-1$
+ synchronized (pyObject) {
+ attrValue = pyObject.__findattr__(attrName);
+ }
+ }
+ }
+
+ if (attrValue == null && methodName.startsWith(GETTER_METHOD_PREFIX)) {
+ attrName = Util.camelCase2UnderScore(methodName)
+ .substring(GETTER_METHOD_PREFIX.length() + 1);
+ synchronized (pyObject) {
+ attrValue = pyObject.__findattr__(attrName);
+ }
+ }
+
+ if (attrValue != null) {
+ if (PyProperty.class.isAssignableFrom(attrValue.getClass())) {
+ throw new IllegalArgumentException(_("JyWrapper.12", attrName)); //$NON-NLS-1$
+ }
+ return Util.py2Java(attrValue, method.getReturnType());
+ }
+
+ throw new NoSuchMethodException(
+ _("JyWrapper.15", "instance attribute", //$NON-NLS-1$ //$NON-NLS-2$
+ methodName, pyImportName));
+ }
+ },
+ SETTER {
+ @Override
+ public Object invoke(final PyObject pyObject, final Class> javaClass,
+ final Method method, final Object[] args, final String pyImportName)
+ throws NoSuchMethodException, IllegalAccessException {
+ final String methodName = method.getName();
+ final PyAttribute annotation = method.getAnnotation(PyAttribute.class);
+ String attrName = null;
+
+ if (annotation != null && annotation.type() == PyAttributeType.SETTER) {
+ attrName = annotation.attribute();
+ if ("".equals(attrName)) { //$NON-NLS-1$
+ attrName = null;
+ }
+ }
+
+ if (attrName == null
+ && methodName.startsWith(SETTER_METHOD_PREFIX)
+ && args.length == 1) {
+ attrName = Util.camelCase2UnderScore(methodName)
+ .substring(SETTER_METHOD_PREFIX.length() + 1);
+ }
+
+ if (attrName != null) {
+ PyObject attrValue;
+ synchronized (pyObject) {
+ attrValue = pyObject.__findattr__(attrName);
+ }
+ if (attrValue != null) {
+ if (PyProperty.class.isAssignableFrom(attrValue.getClass())) {
+ throw new IllegalArgumentException(
+ _("JyWrapper.14", attrName)); //$NON-NLS-1$
+ }
+ }
+ try {
+ final PyObject pyArgs = Py.java2py(args[0]);
+ synchronized (pyObject) {
+ pyObject.__setattr__(attrName, pyArgs);
+ }
+ return Void.TYPE;
+ } catch (final PyException e) {
+ if (e.type.equals(Py.AttributeError)
+ && e.value.toString().equals( "can't set attribute")) { //$NON-NLS-1$
+ throw new IllegalAccessException(
+ _("JyWrapper.13", attrName)); //$NON-NLS-1$
+ }
+ throw e;
+ }
+ }
+
+ throw new NoSuchMethodException(
+ _("JyWrapper.15", "instance attribute", //$NON-NLS-1$ //$NON-NLS-2$
+ methodName, pyImportName));
+ }
+ },
+ CONST {
+ @Override
+ public Object invoke(final PyObject pyObject, final Class> javaClass,
+ final Method method, final Object[] args, final String pyImportName)
+ throws NoSuchMethodException {
+ final PyAttribute annotation = method.getAnnotation(PyAttribute.class);
+ final String methodName = method.getName();
+ PyObject attrValue = null;
+
+ if (annotation != null
+ && annotation.type() == PyAttributeType.CONST) {
+ final String attrName = annotation.attribute();
+ if (!"".equals(attrName)) { //$NON-NLS-1$
+ synchronized (pyObject) {
+ attrValue = pyObject.__findattr__(attrName);
+ }
+ } else {
+ synchronized (pyObject) {
+ attrValue = pyObject.__findattr__(methodName);
+ }
+ }
+ }
+
+ if (attrValue == null
+ && methodName.startsWith(CONST_METHOD_PREFIX)) {
+ final String attrName = methodName
+ .substring(CONST_METHOD_PREFIX.length());
+ synchronized (pyObject) {
+ attrValue = pyObject.__findattr__(attrName);
+ }
+ }
+
+ if (attrValue != null) {
+ return Util.py2Java(attrValue, method.getReturnType());
+ }
+
+ throw new NoSuchMethodException(
+ _("JyWrapper.15", "constant", //$NON-NLS-1$ //$NON-NLS-2$
+ methodName, pyImportName));
+ }
+ },
+ NUMERIC {
+ @Override
+ public Object invoke(final PyObject pyObject, final Class> javaClass,
+ final Method method, final Object[] args, final String pyImportName)
+ throws NoSuchMethodException {
+ try {
+ return NumericMethod.invoke(pyObject, method, args);
+ } catch (final NoSuchMethodException e) {
+ throw new NoSuchMethodException(
+ _("JyWrapper.15", "eqivalent numeric method", //$NON-NLS-1$ //$NON-NLS-2$
+ method.getName(), pyImportName));
+ }
+ }
+ },
+ NO_SUCH_METHOD {
+ @Override
+ public Object invoke(final PyObject pyObject, final Class> javaClass,
+ final Method method, final Object[] args, final String pyImportName)
+ throws NoSuchMethodException {
+ throw new NoSuchMethodException(
+ _("JyWrapper.15", "method", method.getName(), pyImportName)); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ };
+
+ public abstract Object invoke(PyObject pyObject, Class> javaClass,
+ Method method, Object[] args, String pyImportName)
+ throws NoSuchMethodException, IllegalAccessException;
+ }
+
+ private static enum RichComparisonOperator {
+ __eq__(0), __lt__(-1), __gt__(1);
+
+ private int returnValue;
+
+ public int returnValue() { return returnValue; }
+
+ private RichComparisonOperator(final int returnValue) {
+ this.returnValue = returnValue;
+ }
+ }
+
+ private final PyObject pyObject;
+
+ private final Class> javaClass;
+
+ private final String pyImportName;
+
+ private static final ConcurrentHashMap METHOD_JUMP_TABLE =
+ new ConcurrentHashMap();
+
+ private PyObjectProxy(final PyObject pyObject, final Class> javaClass) {
+ this.pyObject = pyObject;
+ this.javaClass = javaClass;
+ this.pyImportName = Util.getPyImportName(this.pyObject);
+ }
+
+ public static T newInstance(final PyObject pyObject,
+ final Class javaClass) {
+ if (javaClass.isInterface()) {
+ ClassLoader classLoader = javaClass.getClassLoader();
+ if (classLoader == null) {
+ classLoader = ClassLoader.getSystemClassLoader();
+ }
+
+ @SuppressWarnings("unchecked")
+ final T newProxyInstance = (T) Proxy.newProxyInstance(
+ classLoader,
+ new Class[] { javaClass, PyProxy.class },
+ new PyObjectProxy(pyObject, javaClass));
+ return newProxyInstance;
+ } else {
+ throw new IllegalArgumentException(_("JyWrapper.8", javaClass.getName())); //$NON-NLS-1$
+ }
+ }
+
+ public Object invoke(final Object proxy, final Method method, final Object[] args)
+ throws NoSuchMethodException, IllegalAccessException {
+ final PyMethod pyMethodAnnotation = method.getAnnotation(PyMethod.class);
+ if (pyMethodAnnotation != null) {
+ return pyMethodAnnotation.type().getMemberType()
+ .invoke(pyObject, javaClass, method, args, pyImportName);
+ }
+
+ final PyAttribute pyAttributeAnnotation = method.getAnnotation(PyAttribute.class);
+ if (pyAttributeAnnotation != null) {
+ return pyAttributeAnnotation.type().getMemberType()
+ .invoke(pyObject, javaClass, method, args, pyImportName);
+ }
+
+ final String methodName = method.getName();
+ if (!METHOD_JUMP_TABLE.containsKey(method)) {
+ //check if the method is "compareTo"
+ if (Comparable.class.isAssignableFrom(javaClass)
+ && JAVA_COMPARE_METHOD_NAME.equals(methodName)) {
+ METHOD_JUMP_TABLE.putIfAbsent(method, MemberType.COMPARE);
+ } else {
+ //check if the method is one of the special methods
+ try {
+ JavaSpecialMethod.valueOf(methodName);
+ METHOD_JUMP_TABLE.putIfAbsent(method, MemberType.SPECIAL);
+ } catch (final IllegalArgumentException ex) {
+ //the method is not one of the special methods. move on.
+
+ //check if the method is one of the PyProxy interface methods
+ try {
+ PyProxyInterfaceMethod.valueOf(methodName);
+ METHOD_JUMP_TABLE.putIfAbsent(method, MemberType.PYPROXY_INTERFACE);
+ } catch (final IllegalArgumentException e) {
+ //the method is not one of the PyProxy interface methods.
+ //move on.
+ }
+ }
+ }
+ }
+
+ //check if the method has already been registered in the jump table
+ //if so invoke it using the method type registered in the table
+ if (METHOD_JUMP_TABLE.containsKey(method)) {
+ return METHOD_JUMP_TABLE.get(method)
+ .invoke(pyObject, javaClass, method, args, pyImportName);
+ }
+
+ // try each method types one by one to guess the correct one
+ for (final MemberType methodType : MemberType.values()) {
+ if (NON_ANNOTATED_MEMBERS.contains(methodType)) {
+ continue;
+ }
+
+ try {
+ final Object retVal = methodType.invoke(
+ pyObject, javaClass, method, args, pyImportName);
+ METHOD_JUMP_TABLE.putIfAbsent(method, methodType);
+ return retVal;
+ } catch (final NoSuchMethodException ex) {
+ continue;
+ }
+ }
+
+ //all checks failed. throw NoSuchMethodException
+ METHOD_JUMP_TABLE.putIfAbsent(method, MemberType.NO_SUCH_METHOD);
+ throw new NoSuchMethodException(
+ _("JyWrapper.15", "method", methodName, pyImportName)); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /**
+ * @param args Arguments to initialize the underlying Python class.
+ * @param pyImport
+ * @param pyImportName
+ * @param javaClass
+ * @return An initialized (wrapped) Python class instance, ready to be used.
+ */
+ private static T initialize(final PyObject pyImport, final String pyImportName,
+ final Class javaClass, final Object... args) {
+ if (javaClass == null) {
+ throw new IllegalStateException(_("JyWrapper.6", "javaClass")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ if (pyImportName == null) {
+ throw new IllegalArgumentException(_("JyWrapper.6", "pyImportName")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ if (pyImport instanceof PyModule) {
+ throw new PythonImportInstantiationError(_("JyWrapper.4", pyImportName)); //$NON-NLS-1$
+ }
+ if (!(pyImport instanceof PyType || pyImport instanceof PyClass)) {
+ throw new PythonImportInstantiationError(_("JyWrapper.9")); //$NON-NLS-1$
+ }
+
+ try {
+ return Util.py2Java(pyImport.__call__(Util.convertArgs(args)), javaClass);
+ } catch (final PyException e) {
+ if (e.type.equals(Py.TypeError)) {
+ throw new PythonImportInstantiationError(
+ _("JyWrapper.3", pyImportName), e); //$NON-NLS-1$
+ }
+ throw e;
+ } catch (final IllegalArgumentException e) {
+ throw new IllegalArgumentException(
+ _("JyWrapper.2", pyImportName, javaClass.getName())); //$NON-NLS-1$
+ }
+ }
+
+ private static Object findAndInvokePyMethod(final PyObject pyObject,
+ final Class> javaReturnType, final String methodName, final Object[] args)
+ throws NoSuchMethodException {
+ PyObject pyAttr;
+ synchronized (pyObject) {
+ pyAttr = pyObject.__findattr__(methodName);
+ }
+ if (pyAttr instanceof org.python.core.PyMethod || pyAttr instanceof PyFunction) {
+ return invokePyMethod(pyObject, javaReturnType, methodName, args);
+ } else {
+ throw new NoSuchMethodException();
+ }
+ }
+
+ private static Object invokePyMethod(final PyObject pyObject,
+ final Class> javaReturnType, final String methodName, final Object[] args) {
+ PyObject pyReturnValue;
+ try {
+ final PyObject[] pyArgs = Util.convertArgs(args);
+ synchronized (pyObject) {
+ pyReturnValue = pyObject.invoke(methodName, pyArgs);
+ }
+ } catch (final PyException e) {
+ if (e.type.equals(Py.TypeError)) {
+ throw new IllegalArgumentException(
+ _("JyWrapper.10", methodName), e); //$NON-NLS-1$
+ }
+ throw e;
+ }
+
+ if (pyReturnValue == Py.None) {
+ return "void".equals(javaReturnType.getName()) ? Void.TYPE : null; //$NON-NLS-1$
+ }
+ return Util.py2Java(pyReturnValue, javaReturnType);
+ }
+
}
\ No newline at end of file
diff --git a/src/main/java/net/abhinavsarkar/jywrapper/Util.java b/src/main/java/net/abhinavsarkar/jywrapper/Util.java
index a61db5c..220659a 100644
--- a/src/main/java/net/abhinavsarkar/jywrapper/Util.java
+++ b/src/main/java/net/abhinavsarkar/jywrapper/Util.java
@@ -1,75 +1,86 @@
-package net.abhinavsarkar.jywrapper;
-
-import static net.abhinavsarkar.jywrapper.Messages._;
-
-import org.python.core.Py;
-import org.python.core.PyFunction;
-import org.python.core.PyModule;
-import org.python.core.PyObject;
-import org.python.core.PyString;
-import org.python.core.PyType;
-
-final class Util {
-
- private Util() {
- }
-
- static T py2Java(final PyObject pyObject, final Class javaClass) {
- final Object javaWrapper = pyObject.__tojava__(javaClass);
- if (javaWrapper == Py.NoConversion) {
- if (javaClass.isInterface()) {
- return PyObjectProxy.newInstance(pyObject, javaClass);
- } else {
- throw new IllegalArgumentException(
- _("JyWrapper.1", pyObject, javaClass.getName())); //$NON-NLS-1$
- }
- } else {
- @SuppressWarnings("unchecked")
- final T t = (T) javaWrapper;
- return t;
- }
- }
-
- static PyObject[] convertArgs(final Object[] args) {
- if (args == null || args.length == 0) {
- return new PyObject[0];
- }
- if (args.length == 1) {
- return new PyObject[] { Py.java2py(args[0]) };
- }
-
- final PyObject[] pyArgs = new PyObject[args.length];
- for (int i = args.length; --i >= 0;) {
- pyArgs[i] = Py.java2py(args[i]);
- }
- return pyArgs;
- }
-
- static String getPyImportName(final PyObject pyObject) {
- synchronized (pyObject) {
- if (pyObject instanceof PyType) {
- final PyType pyType = (PyType) pyObject;
- final PyObject module = pyType.getModule();
- if (module instanceof PyString
- && !module.toString().equals("__builtin__")) { //$NON-NLS-1$
- return String.format("%s.%s", module.toString(), //$NON-NLS-1$
- pyType.getName());
- }
- return pyType.getName();
- } else if (pyObject instanceof PyModule) {
- return ((PyModule) pyObject).toString();
- } else if (pyObject instanceof PyFunction) {
- final PyFunction pyFunction = (PyFunction) pyObject;
- return String.format("%s.%s", pyFunction.__module__, //$NON-NLS-1$
- pyFunction.__name__);
- } else {
- return getPyImportName(pyObject.getType());
- }
- }
- }
-
- static String camelCase2UnderScore(final String word) {
- return word.replaceAll("([A-Z])", "_$1").toLowerCase(); //$NON-NLS-1$ //$NON-NLS-2$
- }
-
-}
+package net.abhinavsarkar.jywrapper;
+
+import static net.abhinavsarkar.jywrapper.Messages._;
+
+import org.python.core.Py;
+import org.python.core.PyClass;
+import org.python.core.PyFunction;
+import org.python.core.PyModule;
+import org.python.core.PyObject;
+import org.python.core.PyString;
+import org.python.core.PyType;
+
+final class Util {
+
+ private Util() {
+ }
+
+ static T py2Java(final PyObject pyObject, final Class javaClass) {
+ final Object javaWrapper = pyObject.__tojava__(javaClass);
+ if (javaWrapper == Py.NoConversion) {
+ if (javaClass.isInterface()) {
+ return PyObjectProxy.newInstance(pyObject, javaClass);
+ } else {
+ throw new IllegalArgumentException(
+ _("JyWrapper.1", pyObject, javaClass.getName())); //$NON-NLS-1$
+ }
+ } else {
+ @SuppressWarnings("unchecked")
+ final T t = (T) javaWrapper;
+ return t;
+ }
+ }
+
+ static PyObject[] convertArgs(final Object[] args) {
+ if (args == null || args.length == 0) {
+ return new PyObject[0];
+ }
+ if (args.length == 1) {
+ return new PyObject[] { Py.java2py(args[0]) };
+ }
+
+ final PyObject[] pyArgs = new PyObject[args.length];
+ for (int i = args.length; --i >= 0;) {
+ pyArgs[i] = Py.java2py(args[i]);
+ }
+ return pyArgs;
+ }
+
+ static String getPyImportName(final PyObject pyObject) {
+ synchronized (pyObject) {
+ if (pyObject instanceof PyType) {
+ final PyType pyType = (PyType) pyObject;
+ final PyObject module = pyType.getModule();
+ if (module instanceof PyString
+ && !module.toString().equals("__builtin__")) { //$NON-NLS-1$
+ return String.format("%s.%s", module.toString(), //$NON-NLS-1$
+ pyType.getName());
+ }
+ return pyType.getName();
+ } else if (pyObject instanceof PyClass) {
+ final PyClass pyClass = (PyClass) pyObject;
+ final PyObject mod = pyClass.__dict__.__finditem__("__module__");
+ String smod;
+ if (mod == null || !(mod instanceof PyString)) {
+ smod = "";
+ } else {
+ smod = ((PyString) mod).toString();
+ }
+ return smod + "." + pyClass.__name__;
+ } else if (pyObject instanceof PyModule) {
+ return ((PyModule) pyObject).toString();
+ } else if (pyObject instanceof PyFunction) {
+ final PyFunction pyFunction = (PyFunction) pyObject;
+ return String.format(
+ "%s.%s", pyFunction.__module__, pyFunction.__name__); //$NON-NLS-1$
+ } else {
+ return getPyImportName(pyObject.getType());
+ }
+ }
+ }
+
+ static String camelCase2UnderScore(final String word) {
+ return word.replaceAll("([A-Z])", "_$1").toLowerCase(); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+}
diff --git a/src/main/java/net/abhinavsarkar/jywrapper/messages.properties b/src/main/java/net/abhinavsarkar/jywrapper/messages.properties
index b1a4bab..559e274 100644
--- a/src/main/java/net/abhinavsarkar/jywrapper/messages.properties
+++ b/src/main/java/net/abhinavsarkar/jywrapper/messages.properties
@@ -1,17 +1,17 @@
-JyWrapper.0="{0}" is not a Python Function
-JyWrapper.1=Cannot convert Python object: {0} to a Java object of class {1}
-JyWrapper.2=Cannot convert Python Type {0} to Java Class {1}
-JyWrapper.3=Cannot not instantiate the Python type: {0}
-JyWrapper.4=Python module {0} can be instantiated statically only
-JyWrapper.5={0} is not a Python Type or Module
-JyWrapper.6=parameter "{0}" is null
-JyWrapper.7=No Python import name annotated on the Java Class {0}
-JyWrapper.8={0} is not an Interface
-JyWrapper.9=Cannot instantiate a Python non type
-JyWrapper.10=Instance method "{0}" called on a Python Type
-JyWrapper.11=No comparison methods found in the backing Python object
-JyWrapper.12=Trying to get instance attribute "{0}" from a Python Type
-JyWrapper.13=Can''t set attribute: {0}
-JyWrapper.14=Trying to set instance attribute "{0}" in a python class
-JyWrapper.15=No {0} named "{1}" in the backing Python Type {2}
-PyImportLoader.1=Python Import "{0}" not found in pythonpath
+JyWrapper.0="{0}" is not a Python Function
+JyWrapper.1=Cannot convert Python object: {0} to a Java object of class {1}
+JyWrapper.2=Cannot convert Python Type {0} to Java Class {1}
+JyWrapper.3=Cannot not instantiate the Python type: {0}
+JyWrapper.4=Python module {0} can be instantiated statically only
+JyWrapper.5={0} is not a Python Type, Class or Module
+JyWrapper.6=parameter "{0}" is null
+JyWrapper.7=No Python import name annotated on the Java Class {0}
+JyWrapper.8={0} is not an Interface
+JyWrapper.9=Cannot instantiate a non Python Type or Class
+JyWrapper.10=Instance method "{0}" called on a Python Type
+JyWrapper.11=No comparison methods found in the backing Python object
+JyWrapper.12=Trying to get instance attribute "{0}" from a Python Type
+JyWrapper.13=Can''t set attribute: {0}
+JyWrapper.14=Trying to set instance attribute "{0}" in a python class
+JyWrapper.15=No {0} named "{1}" in the backing Python Type {2}
+PyImportLoader.1=Python Import "{0}" not found in pythonpath