cdef parse_definition(definition): # not a function, just a field if definition[0] != '(': return definition, None # it's a function! argdef, ret = definition[1:].split(')') args = [] while len(argdef): c = argdef[0] # read the array char prefix = '' if c == '[': prefix = c argdef = argdef[1:] c = argdef[0] # native type if c in 'ZBCSIJFD': args.append(prefix + c) argdef = argdef[1:] continue # java class if c == 'L': c, argdef = argdef.split(';', 1) args.append(prefix + c + ';') return ret, args cdef void check_exception(JNIEnv *j_env) except *: cdef jthrowable exc = j_env[0].ExceptionOccurred(j_env) if exc: j_env[0].ExceptionDescribe(j_env) j_env[0].ExceptionClear(j_env) raise JavaException('JVM exception occured') cdef dict assignable_from = {} cdef void check_assignable_from(JNIEnv *env, JavaClass jc, bytes signature) except *: cdef jclass cls # if we have a JavaObject, it's always ok. if signature == 'java/lang/Object': return # if the signature is a direct match, it's ok too :) if jc.__javaclass__ == signature: return # if we already did the test before, use the cache result! result = assignable_from.get((jc.__javaclass__, signature), None) if result is None: # we got an object that doesn't match with the signature # check if we can use it. cls = env[0].FindClass(env, signature) if cls == NULL: raise JavaException('Unable to found the class for {0!r}'.format( signature)) result = bool(env[0].IsAssignableFrom(env, jc.j_cls, cls)) env[0].ExceptionClear(env) print 'CHECK FOR', jc.__javaclass__, signature, result assignable_from[(jc.__javaclass__, signature)] = bool(result) if result is False: raise JavaException('Invalid instance of {0!r} passed for a {1!r}'.format( jc.__javaclass__, signature)) cdef bytes lookup_java_object_name(JNIEnv *j_env, jobject j_obj): from reflect import ensureclass, autoclass ensureclass('java.lang.Object') ensureclass('java.lang.Class') cdef JavaClass obj = autoclass('java.lang.Object')(noinstance=True) obj.instanciate_from(create_local_ref(j_env, j_obj)) cls = obj.getClass() name = cls.getName() ensureclass(name) return name.replace('.', '/') cdef int calculate_score(sign_args, args) except *: cdef int index cdef int score = 0 cdef bytes r cdef JavaClass jc if len(args) != len(sign_args): return -1 score += 10 for index in range(len(sign_args)): r = sign_args[index] arg = args[index] if r == 'Z': if not isinstance(arg, bool): return -1 score += 10 continue if r == 'B': if not isinstance(arg, int): return -1 score += 10 continue if r == 'C': if not isinstance(arg, str) or len(arg) != 1: return -1 score += 10 continue if r == 'S' or r == 'I' or r == 'J': if isinstance(arg, int): score += 10 continue elif isinstance(arg, float): score += 5 continue else: return -1 if r == 'F' or r == 'D': if isinstance(arg, int): score += 5 continue elif isinstance(arg, float): score += 10 continue else: return -1 if r[0] == 'L': r = r[1:-1] if arg is None: score += 10 continue # if it's a string, accept any python string if r == 'java/lang/String' and isinstance(arg, basestring): score += 10 continue # if it's a generic object, accept python string, or any java # class/object if r == 'java/lang/Object': if isinstance(arg, JavaClass) or isinstance(arg, JavaObject): score += 10 continue elif isinstance(arg, basestring): score += 5 continue return -1 # if we pass a JavaClass, ensure the definition is matching # XXX FIXME what if we use a subclass or something ? if isinstance(arg, JavaClass): jc = arg if jc.__javaclass__ == r: score += 10 else: try: check_assignable_from(jc, r) except: return -1 score += 5 continue # always accept unknow object, but can be dangerous too. if isinstance(arg, JavaObject): score += 1 continue # native type? not accepted return -1 if r[0] == '[': if arg is None: return 10 if not isinstance(arg, tuple) and not isinstance(arg, list): return -1 # calculate the score for our subarray subscore = calculate_score([r[1:]] * len(arg), arg) if subscore == -1: return -1 # look like the array is matching, accept it. score += 10 continue return score