001 /* 002 Copyright (c) 2009 Olivier Chafik, All Rights Reserved 003 004 This file is part of JNAerator (http://jnaerator.googlecode.com/). 005 006 JNAerator is free software: you can redistribute it and/or modify 007 it under the terms of the GNU Lesser General Public License as published by 008 the Free Software Foundation, either version 3 of the License, or 009 (at your option) any later version. 010 011 JNAerator is distributed in the hope that it will be useful, 012 but WITHOUT ANY WARRANTY; without even the implied warranty of 013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 GNU Lesser General Public License for more details. 015 016 You should have received a copy of the GNU Lesser General Public License 017 along with JNAerator. If not, see <http://www.gnu.org/licenses/>. 018 */ 019 package com.ochafik.lang.jnaerator.runtime; 020 021 import java.io.File; 022 import java.io.FileOutputStream; 023 import java.io.IOException; 024 import java.io.InputStream; 025 import java.io.OutputStream; 026 import java.net.URL; 027 import java.net.URLConnection; 028 import java.net.URLDecoder; 029 import java.util.ArrayList; 030 import java.util.Iterator; 031 import java.util.List; 032 033 import com.ochafik.net.URLUtils; 034 import com.sun.jna.Platform; 035 036 /** 037 * @see http://landonf.bikemonkey.org/static/soylatte/ 038 * @author ochafik 039 * 040 */ 041 public class LibraryExtractor { 042 public static String getCurrentOSAndArchString() { 043 String os = System.getProperty("os.name"), arch = System.getProperty("os.arch"); 044 045 if (os.equals("Mac OS X")) { 046 os = "darwin"; 047 arch = "fat"; 048 //arch = Platform.is64Bit() ? "64" : "32"; 049 } else if (os.startsWith("Windows")) { 050 return "win" + (Platform.is64Bit() ? "64" : "32"); 051 } else if (os.matches("SunOS|Solaris")) 052 os = "solaris"; 053 054 return os + "-" + arch; 055 } 056 public static String getLibraryPath(String libraryName, boolean extractAllLibraries, Class<?> cl) { 057 try { 058 String customPath = System.getProperty("library." + libraryName); 059 if (customPath == null) 060 customPath = System.getenv(libraryName.toUpperCase() + "_LIBRARY"); 061 if (customPath != null) { 062 File f = new File(customPath); 063 if (!f.exists()) 064 System.err.println("Library file '" + customPath + "' does not exist !"); 065 else 066 return f.getAbsolutePath(); 067 } 068 //ClassLoader cl = LibraryExtractor.class.getClassLoader(); 069 String prefix = "(?i)" + (Platform.isWindows() || Platform.isWindowsCE() ? "" : "lib") + libraryName + "[^A-Za-z_].*"; 070 String libsuffix = "(?i).*\\.(so|dll|dylib|jnilib)"; 071 String othersuffix = "(?i).*\\.(pdb)"; 072 073 URL sourceURL = null; 074 List<URL> otherURLs = new ArrayList<URL>(); 075 076 077 String arch = getCurrentOSAndArchString(); 078 //System.out.println("libURL = " + libURL); 079 List<URL> list = URLUtils.listFiles(URLUtils.getResource(cl, "libraries/" + arch), null); 080 if (list.isEmpty()) { 081 for (URL u : URLUtils.listFiles(URLUtils.getResource(cl, "libraries"), null)) { 082 String f = u.getFile(); 083 int i = f.lastIndexOf('/'); 084 if (i >= 0) 085 f = f.substring(i + 1); 086 if (arch.startsWith(f)) { 087 list = URLUtils.listFiles(u, null); 088 break; 089 } 090 } 091 092 } 093 for (File f : new File(".").listFiles()) 094 if (f.isFile()) 095 list.add(f.toURI().toURL()); 096 097 for (URL url : list) { 098 String fileName = new File(url.toString()).getName(); 099 boolean pref = fileName.matches(prefix), suff = fileName.matches(libsuffix); 100 if (pref && suff) 101 sourceURL = url; 102 else if (suff || fileName.matches(othersuffix)) 103 otherURLs.add(url); 104 } 105 List<File> files = new ArrayList<File>(); 106 if (extractAllLibraries) { 107 for (URL url : otherURLs) 108 files.add(extract(url)); 109 } 110 111 if (sourceURL == null) 112 return libraryName; 113 else { 114 File file = extract(sourceURL); 115 files.add(file); 116 117 int lastSize; 118 do { 119 lastSize = files.size(); 120 for (Iterator<File> it = files.iterator(); it.hasNext();) { 121 File f = it.next(); 122 if (!f.getName().matches(libsuffix)) 123 continue; 124 125 try { 126 System.load(f.toString()); 127 it.remove(); 128 } catch (Throwable ex) { 129 System.err.println("Loading " + f.getName() + " failed (" + ex + ")"); 130 } 131 } 132 } while (files.size() < lastSize); 133 134 return file.getCanonicalPath(); 135 } 136 } catch (Throwable ex) { 137 System.err.println("ERROR: Failed to extract library " + libraryName); 138 ex.printStackTrace(); 139 return libraryName; 140 } 141 } 142 private static File extract(URL url) throws IOException { 143 File localFile; 144 if ("file".equals(url.getProtocol())) 145 localFile = new File(URLDecoder.decode(url.getFile(), "UTF-8")); 146 else { 147 File f = new File(System.getProperty("user.home")); 148 f = new File(f, ".jnaerator"); 149 f = new File(f, "extractedLibraries"); 150 if (!f.exists()) 151 f.mkdirs(); 152 153 localFile = new File(f, new File(url.getFile()).getName()); 154 URLConnection c = url.openConnection(); 155 if (localFile.exists() && localFile.lastModified() > c.getLastModified()) { 156 c.getInputStream().close(); 157 } else { 158 System.out.println("Extracting " + url); 159 InputStream in = c.getInputStream(); 160 OutputStream out = new FileOutputStream(localFile); 161 int len; 162 byte[] b = new byte[1024]; 163 while ((len = in.read(b)) > 0) 164 out.write(b, 0, len); 165 out.close(); 166 in.close(); 167 } 168 } 169 return localFile; 170 } 171 public static void loadLibrary(String libraryName, boolean extractAllLibraries, Class<?> cl) { 172 System.loadLibrary(getLibraryPath(libraryName, extractAllLibraries, cl)); 173 } 174 }