001/* 002 * BridJ - Dynamic and blazing-fast native interop for Java. 003 * http://bridj.googlecode.com/ 004 * 005 * Copyright (c) 2010-2013, Olivier Chafik (http://ochafik.com/) 006 * All rights reserved. 007 * 008 * Redistribution and use in source and binary forms, with or without 009 * modification, are permitted provided that the following conditions are met: 010 * 011 * * Redistributions of source code must retain the above copyright 012 * notice, this list of conditions and the following disclaimer. 013 * * Redistributions in binary form must reproduce the above copyright 014 * notice, this list of conditions and the following disclaimer in the 015 * documentation and/or other materials provided with the distribution. 016 * * Neither the name of Olivier Chafik nor the 017 * names of its contributors may be used to endorse or promote products 018 * derived from this software without specific prior written permission. 019 * 020 * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY 021 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 022 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 023 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY 024 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 025 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 026 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 027 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 028 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 029 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 030 */ 031package org.bridj; 032 033import java.util.ArrayList; 034import java.util.HashMap; 035import java.util.List; 036import java.util.Map; 037 038/** 039 * Collection of handles to natively-bound classes and methods (which native 040 * resources can be released all at once). 041 * 042 * @author ochafik 043 */ 044public class NativeEntities { 045 046 static class CBInfo { 047 048 long handle; 049 int size; 050 051 public CBInfo(long handle, int size) { 052 this.handle = handle; 053 this.size = size; 054 } 055 } 056 Map<Class<?>, CBInfo> functions = new HashMap<Class<?>, CBInfo>(), 057 virtualMethods = new HashMap<Class<?>, CBInfo>(), 058 //getters = new HashMap<Class<?>, CBInfo>(), 059 //setters = new HashMap<Class<?>, CBInfo>(), 060 javaToNativeCallbacks = new HashMap<Class<?>, CBInfo>(), 061 //cppMethods = new HashMap<Class<?>, CBInfo>(), 062 objcMethodInfos = new HashMap<Class<?>, CBInfo>(); 063 064 /** 065 * Helper class to build a NativeEntities instance easily. 066 */ 067 public static class Builder { 068 069 List<MethodCallInfo> functionInfos = new ArrayList<MethodCallInfo>(), 070 virtualMethods = new ArrayList<MethodCallInfo>(), 071 javaToNativeCallbacks = new ArrayList<MethodCallInfo>(), 072 //getters = new ArrayList<MethodCallInfo>(), 073 cppMethodInfos = new ArrayList<MethodCallInfo>(), 074 objcMethodInfos = new ArrayList<MethodCallInfo>(); 075 //List<MethodCallInfo> getterInfos = new ArrayList<MethodCallInfo>(); 076 077 public void addFunction(MethodCallInfo info) { 078 functionInfos.add(info); 079 } 080 081 public void addVirtualMethod(MethodCallInfo info) { 082 virtualMethods.add(info); 083 } 084 /*public void addGetter(MethodCallInfo info) { 085 getters.add(info); 086 } 087 public void addSetter(MethodCallInfo info) { 088 getters.add(info); 089 }*/ 090 091 public void addJavaToNativeCallback(MethodCallInfo info) { 092 javaToNativeCallbacks.add(info); 093 } 094 095 public void addMethodFunction(MethodCallInfo info) { 096 cppMethodInfos.add(info); 097 }//*/ 098 099 public void addObjCMethod(MethodCallInfo info) { 100 objcMethodInfos.add(info); 101 } 102 } 103 104 /** 105 * Free everything (native callbacks, bindings, etc...).<br> 106 * Called automatically by {@link NativeEntities#finalize()} upon garbage 107 * collection. 108 */ 109 public void release() { 110 if (BridJ.debugNeverFree) { 111 return; 112 } 113 114 for (CBInfo callbacks : functions.values()) { 115 JNI.freeCFunctionBindings(callbacks.handle, callbacks.size); 116 } 117 118 /* 119 for (CBInfo callbacks : cppMethods.values()) 120 JNI.freeCPPMethodBindings(callbacks.handle, callbacks.size); 121 //*/ 122 for (CBInfo callbacks : javaToNativeCallbacks.values()) { 123 JNI.freeJavaToCCallbacks(callbacks.handle, callbacks.size); 124 } 125 126 for (CBInfo callbacks : virtualMethods.values()) { 127 JNI.freeVirtualMethodBindings(callbacks.handle, callbacks.size); 128 } 129 130 //for (CBInfo callbacks : getters.values()) 131 // JNI.freeGetters(callbacks.handle, callbacks.size); 132 133 for (CBInfo callbacks : objcMethodInfos.values()) { 134 JNI.freeObjCMethodBindings(callbacks.handle, callbacks.size); 135 } 136 } 137 138 @Override 139 public void finalize() { 140 release(); 141 } 142 143 public void addDefinitions(Class<?> type, Builder builder) { 144 int n; 145 try { 146 147 n = builder.functionInfos.size(); 148 if (n != 0) { 149 functions.put(type, new CBInfo(JNI.bindJavaMethodsToCFunctions(builder.functionInfos.toArray(new MethodCallInfo[n])), n)); 150 } 151 152 n = builder.virtualMethods.size(); 153 if (n != 0) { 154 virtualMethods.put(type, new CBInfo(JNI.bindJavaMethodsToVirtualMethods(builder.virtualMethods.toArray(new MethodCallInfo[n])), n)); 155 } 156 157 n = builder.javaToNativeCallbacks.size(); 158 if (n != 0) { 159 javaToNativeCallbacks.put(type, new CBInfo(JNI.bindJavaToCCallbacks(builder.javaToNativeCallbacks.toArray(new MethodCallInfo[n])), n)); 160 } 161 162 /* 163 n = builder.cppMethodInfos.size(); 164 if (n != 0) 165 cppMethods.put(type, new CBInfo(JNI.bindJavaMethodsToCPPMethods(builder.cppMethodInfos.toArray(new MethodCallInfo[n])), n)); 166 //*/ 167 n = builder.objcMethodInfos.size(); 168 if (n != 0) { 169 objcMethodInfos.put(type, new CBInfo(JNI.bindJavaMethodsToObjCMethods(builder.objcMethodInfos.toArray(new MethodCallInfo[n])), n)); 170 } 171 172 /*n = builder.getters.size(); 173 if (n != 0) 174 getters.put(type, new CBInfo(JNI.bindGetters(builder.getters.toArray(new MethodCallInfo[n])), n)); 175 */ 176 } catch (Throwable th) { 177 assert BridJ.error("Failed to add native definitions for class " + type.getName(), th); 178 } 179 } 180}