001/* 002 * Copyright (C) Photon Vision. 003 * 004 * This program is free software: you can redistribute it and/or modify 005 * it under the terms of the GNU General Public License as published by 006 * the Free Software Foundation, either version 3 of the License, or 007 * (at your option) any later version. 008 * 009 * This program is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 012 * GNU General Public License for more details. 013 * 014 * You should have received a copy of the GNU General Public License 015 * along with this program. If not, see <https://www.gnu.org/licenses/>. 016 */ 017 018package org.photonvision.jni; 019 020import java.io.File; 021import java.io.FileOutputStream; 022import java.io.IOException; 023import java.util.List; 024import org.photonvision.common.hardware.Platform; 025import org.photonvision.common.logging.LogGroup; 026import org.photonvision.common.logging.Logger; 027 028public abstract class PhotonJNICommon { 029 public abstract boolean isLoaded(); 030 031 public abstract void setLoaded(boolean state); 032 033 protected static Logger logger = null; 034 035 protected static synchronized void forceLoad( 036 PhotonJNICommon instance, Class<?> clazz, List<String> libraries) throws IOException { 037 if (instance.isLoaded()) return; 038 if (logger == null) logger = new Logger(clazz, LogGroup.Camera); 039 040 for (var libraryName : libraries) { 041 try { 042 // We always extract the shared object (we could hash each so, but that's a lot of work) 043 var arch_name = Platform.getNativeLibraryFolderName(); 044 var nativeLibName = System.mapLibraryName(libraryName); 045 var in = clazz.getResourceAsStream("/nativelibraries/" + arch_name + "/" + nativeLibName); 046 047 if (in == null) { 048 instance.setLoaded(false); 049 return; 050 } 051 052 // It's important that we don't mangle the names of these files on Windows at least 053 File temp = new File(System.getProperty("java.io.tmpdir"), nativeLibName); 054 FileOutputStream fos = new FileOutputStream(temp); 055 056 int read = -1; 057 byte[] buffer = new byte[1024]; 058 while ((read = in.read(buffer)) != -1) { 059 fos.write(buffer, 0, read); 060 } 061 fos.close(); 062 in.close(); 063 064 System.load(temp.getAbsolutePath()); 065 066 logger.info("Successfully loaded shared object " + temp.getName()); 067 068 } catch (UnsatisfiedLinkError e) { 069 logger.error("Couldn't load shared object " + libraryName, e); 070 e.printStackTrace(); 071 // logger.error(System.getProperty("java.library.path")); 072 instance.setLoaded(false); 073 return; 074 } 075 } 076 instance.setLoaded(true); 077 } 078 079 protected static synchronized void forceLoad( 080 PhotonJNICommon instance, Class<?> clazz, String libraryName) throws IOException { 081 forceLoad(instance, clazz, List.of(libraryName)); 082 } 083}