1 /*
   2  * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package java.nicl;
  24 
  25 import java.io.File;
  26 import jdk.internal.nicl.Errno;
  27 import jdk.internal.nicl.NativeLibraryImpl;
  28 import jdk.internal.nicl.types.BindingRegistry;
  29 import jdk.internal.nicl.types.Function;
  30 import jdk.internal.nicl.types.Type;
  31 import jdk.internal.nicl.types.LayoutTypeImpl;
  32 
  33 import java.lang.invoke.MethodHandle;
  34 import java.lang.invoke.MethodType;
  35 import java.nicl.types.LayoutType;
  36 
  37 public final class NativeLibrary {
  38     private static final Errno ERRNO = Errno.platformHasErrno() ? new Errno() : null;
  39 
  40     // don't create
  41     private NativeLibrary() {}
  42 
  43     /**
  44      * Create a raw, uncivilized version of the interface
  45      *
  46      * @param c the class to bind
  47      * @param lib the library in which to look for native symbols
  48      * @return
  49      */
  50     @Deprecated
  51     public static <T> T bindRaw(Class<T> c, Library lib) {
  52         SecurityManager security = System.getSecurityManager();
  53         if (security != null) {
  54             security.checkPermission(new RuntimePermission("java.nicl.bindRaw"));
  55         }
  56         return NativeLibraryImpl.bindRaw(c, lib);
  57     }
  58 
  59     /**
  60      * Create a raw, uncivilized version of the interface
  61      *
  62      * @param c the class to bind
  63      * @return
  64      */
  65     public static <T> T bindRaw(Class<T> c) {
  66         SecurityManager security = System.getSecurityManager();
  67         if (security != null) {
  68             security.checkPermission(new RuntimePermission("java.nicl.bindRaw"));
  69         }
  70         return NativeLibraryImpl.bindRaw(c);
  71     }
  72 
  73     /**
  74      * Create a civilized version of the interface
  75      *
  76      * @param c the raw, uncivilized version of the interface
  77      * @return
  78      */
  79     @Deprecated
  80     public static Object bind(Class<?> c) {
  81         SecurityManager security = System.getSecurityManager();
  82         if (security != null) {
  83             security.checkPermission(new RuntimePermission("java.nicl.bind"));
  84         }
  85         return NativeLibraryImpl.bind(c);
  86     }
  87 
  88     /**
  89      * Create a civilized version of the interface
  90      *
  91      * @param c the raw, uncivilized version of the interface
  92      * @param lib the library in which to look for native symbols
  93      * @return
  94      */
  95     @Deprecated
  96     public static Object bind(Class<?> c, Library lib) {
  97         SecurityManager security = System.getSecurityManager();
  98         if (security != null) {
  99             security.checkPermission(new RuntimePermission("java.nicl.bind"));
 100         }
 101         return NativeLibraryImpl.bind(c, lib);
 102     }
 103 
 104     /**
 105      * Lookup a method handle for a native function with the specified arguments
 106      *
 107      * @param libs the libraries in which to look for native symbols
 108      * @param symbolName the name of the symbol to look up
 109      * @param methodType the type of the returned method handle
 110      * @param isVarArgs true if the function is a varargs method
 111      * @return a method handle which, when invoked, will call the target native function
 112      * @throws NoSuchMethodException
 113      * @throws IllegalAccessException
 114      */
 115     public static MethodHandle lookupNativeMethod(Library[] libs, String symbolName, MethodType methodType, boolean isVarArgs) throws NoSuchMethodException, IllegalAccessException {
 116         SecurityManager security = System.getSecurityManager();
 117         if (security != null) {
 118             security.checkPermission(new RuntimePermission("java.nicl.lookupNative", symbolName));
 119         }
 120         return NativeLibraryImpl.lookupNativeMethod(libs, symbolName, methodType, isVarArgs);
 121     }
 122 
 123     public static MethodHandle lookupNativeMethod(Library lib, String symbolName, MethodType methodType, boolean isVarArgs) throws NoSuchMethodException, IllegalAccessException {
 124         return lookupNativeMethod(new Library[] { lib }, symbolName, methodType, isVarArgs);
 125     }
 126 
 127     public static Library loadLibrary(String name) {
 128         SecurityManager security = System.getSecurityManager();
 129         if (security != null) {
 130             security.checkLink(name);
 131         }
 132         return NativeLibraryImpl.loadLibrary(name);
 133     }
 134 
 135     public static Library loadLibraryFile(String name) {
 136         SecurityManager security = System.getSecurityManager();
 137         if (security != null) {
 138             security.checkLink(name);
 139         }
 140         if (!(new File(name).isAbsolute())) {
 141             throw new UnsatisfiedLinkError(
 142                 "Expecting an absolute path of the library: " + name);
 143         }
 144         return NativeLibraryImpl.loadLibraryFile(name);
 145     }
 146 
 147     public static Library getDefaultLibrary() {
 148         SecurityManager security = System.getSecurityManager();
 149         if (security != null) {
 150             security.checkPermission(new RuntimePermission("java.nicl.getDefaultLibrary"));
 151         }
 152         return NativeLibraryImpl.getDefaultLibrary();
 153     }
 154 
 155     public static <T> LayoutType<T> createLayout(Class<T> c) {
 156         return LayoutTypeImpl.create(c);
 157     }
 158 
 159     public static int errno() {
 160         if (ERRNO == null) {
 161             throw new UnsupportedOperationException();
 162         }
 163 
 164         return ERRNO.errno();
 165     }
 166 
 167     public static void throwErrnoException(String msg) throws Exception {
 168         throw new Exception(msg + ": " + ERRNO.strerror(errno()));
 169     }
 170 
 171     public static void throwErrnoException() throws Exception {
 172         throw new Exception(ERRNO.strerror(errno()));
 173     }
 174 
 175     /**
 176      * Lookup a method handle for a native function with the specified arguments
 177      *
 178      * @param lib the library in which to look for the function
 179      * @param symbol the name of the symbol to look up
 180      * @param type the type descriptor of the native function
 181      */
 182     public static MethodHandle lookupNativeMethod(Library lib, String symbol, String type)
 183         throws NoSuchMethodException, IllegalAccessException {
 184         Function fn = (Function) Type.of(type);
 185         MethodType mt = BindingRegistry.getInstance().defaultMethodType(fn);
 186         return lookupNativeMethod(lib, symbol, mt, fn.isVarArg());
 187     }
 188 }