001 package org.bridj;
002
003 import java.util.ArrayList;
004 import java.util.HashMap;
005 import java.util.List;
006 import java.util.Map;
007
008 /**
009 * Collection of handles to natively-bound classes and methods (which native resources can be released all at once).
010 * @author ochafik
011 */
012 public class NativeEntities {
013 static class CBInfo {
014 long handle;
015 int size;
016 public CBInfo(long handle, int size) {
017 this.handle = handle;
018 this.size = size;
019 }
020
021 }
022 Map<Class<?>, CBInfo>
023 functions = new HashMap<Class<?>, CBInfo>(),
024 virtualMethods = new HashMap<Class<?>, CBInfo>(),
025 //getters = new HashMap<Class<?>, CBInfo>(),
026 //setters = new HashMap<Class<?>, CBInfo>(),
027 javaToNativeCallbacks = new HashMap<Class<?>, CBInfo>(),
028 //cppMethods = new HashMap<Class<?>, CBInfo>(),
029 objcMethodInfos = new HashMap<Class<?>, CBInfo>();
030
031 /**
032 * Helper class to build a NativeEntities instance easily.
033 */
034 public static class Builder {
035 List<MethodCallInfo>
036 functionInfos = new ArrayList<MethodCallInfo>(),
037 virtualMethods = new ArrayList<MethodCallInfo>(),
038 javaToNativeCallbacks = new ArrayList<MethodCallInfo>(),
039 //getters = new ArrayList<MethodCallInfo>(),
040 cppMethodInfos = new ArrayList<MethodCallInfo>(),
041 objcMethodInfos = new ArrayList<MethodCallInfo>();
042 //List<MethodCallInfo> getterInfos = new ArrayList<MethodCallInfo>();
043
044 public void addFunction(MethodCallInfo info) {
045 functionInfos.add(info);
046 }
047 public void addVirtualMethod(MethodCallInfo info) {
048 virtualMethods.add(info);
049 }
050 /*public void addGetter(MethodCallInfo info) {
051 getters.add(info);
052 }
053 public void addSetter(MethodCallInfo info) {
054 getters.add(info);
055 }*/
056 public void addJavaToNativeCallback(MethodCallInfo info) {
057 javaToNativeCallbacks.add(info);
058 }
059 public void addMethodFunction(MethodCallInfo info) {
060 cppMethodInfos.add(info);
061 }//*/
062 public void addObjCMethod(MethodCallInfo info) {
063 objcMethodInfos.add(info);
064 }
065 }
066
067 /**
068 * Free everything (native callbacks, bindings, etc...).<br>
069 * Called automatically by {@link NativeEntities#finalize()} upon garbage collection.
070 */
071 public void release() {
072 if (BridJ.debugNeverFree)
073 return;
074
075 for (CBInfo callbacks : functions.values())
076 JNI.freeCFunctionBindings(callbacks.handle, callbacks.size);
077
078 /*
079 for (CBInfo callbacks : cppMethods.values())
080 JNI.freeCPPMethodBindings(callbacks.handle, callbacks.size);
081 //*/
082 for (CBInfo callbacks : javaToNativeCallbacks.values())
083 JNI.freeJavaToCCallbacks(callbacks.handle, callbacks.size);
084
085 for (CBInfo callbacks : virtualMethods.values())
086 JNI.freeVirtualMethodBindings(callbacks.handle, callbacks.size);
087
088 //for (CBInfo callbacks : getters.values())
089 // JNI.freeGetters(callbacks.handle, callbacks.size);
090
091 for (CBInfo callbacks : objcMethodInfos.values())
092 JNI.freeObjCMethodBindings(callbacks.handle, callbacks.size);
093 }
094 @Override
095 public void finalize() {
096 release();
097 }
098 public void addDefinitions(Class<?> type, Builder builder) {
099 int n;
100 try {
101
102 n = builder.functionInfos.size();
103 if (n != 0)
104 functions.put(type, new CBInfo(JNI.bindJavaMethodsToCFunctions(builder.functionInfos.toArray(new MethodCallInfo[n])), n));
105
106 n = builder.virtualMethods.size();
107 if (n != 0)
108 virtualMethods.put(type, new CBInfo(JNI.bindJavaMethodsToVirtualMethods(builder.virtualMethods.toArray(new MethodCallInfo[n])), n));
109
110 n = builder.javaToNativeCallbacks.size();
111 if (n != 0)
112 javaToNativeCallbacks.put(type, new CBInfo(JNI.bindJavaToCCallbacks(builder.javaToNativeCallbacks.toArray(new MethodCallInfo[n])), n));
113
114 /*
115 n = builder.cppMethodInfos.size();
116 if (n != 0)
117 cppMethods.put(type, new CBInfo(JNI.bindJavaMethodsToCPPMethods(builder.cppMethodInfos.toArray(new MethodCallInfo[n])), n));
118 //*/
119 n = builder.objcMethodInfos.size();
120 if (n != 0)
121 objcMethodInfos.put(type, new CBInfo(JNI.bindJavaMethodsToObjCMethods(builder.objcMethodInfos.toArray(new MethodCallInfo[n])), n));
122
123 /*n = builder.getters.size();
124 if (n != 0)
125 getters.put(type, new CBInfo(JNI.bindGetters(builder.getters.toArray(new MethodCallInfo[n])), n));
126 */
127 } catch (Throwable th) {
128 assert BridJ.error("Failed to add native definitions for class " + type.getName(), th);
129 }
130 }
131 }