/*-------------------------------------------------------------------------- * Copyright 2007 Taro L. Saito * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *--------------------------------------------------------------------------*/ //-------------------------------------- // SQLite JDBC Project // // SQLite.java // Since: 2007/05/10 // // $URL$ // $Author$ //-------------------------------------- package org.sqlite; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.security.DigestInputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Properties; /** * Set the system properties, org.sqlite.lib.path, org.sqlite.lib.name, * appropriately so that the SQLite JDBC driver can find *.dll, *.jnilib and * *.so files, according to the current OS (win, linux, mac). * * The library files are automatically extracted from this project's package * (JAR). * * usage: call {@link #initialize()} before using SQLite JDBC driver. * * @author leo * */ public class SQLiteJDBCLoader { private static boolean extracted = false; public static boolean initialize() { loadSQLiteNativeLibrary(); return extracted; } static boolean getPureJavaFlag() { return Boolean.parseBoolean(System.getProperty("sqlite.purejava", "false")); } public static boolean isPureJavaMode() { return !isNativeMode(); } public static boolean isNativeMode() { if (getPureJavaFlag()) return false; // load the driver initialize(); return extracted; } /** * Computes the MD5 value of the input stream * * @param input * @return * @throws IOException * @throws NoSuchAlgorithmException */ static String md5sum(InputStream input) throws IOException { BufferedInputStream in = new BufferedInputStream(input); try { MessageDigest digest = java.security.MessageDigest.getInstance("MD5"); DigestInputStream digestInputStream = new DigestInputStream(in, digest); for (; digestInputStream.read() >= 0;) { } ByteArrayOutputStream md5out = new ByteArrayOutputStream(); md5out.write(digest.digest()); return md5out.toString(); } catch (NoSuchAlgorithmException e) { throw new IllegalStateException("MD5 algorithm is not available: " + e); } finally { in.close(); } } /** * Extract the specified library file to the target folder * * @param libFolderForCurrentOS * @param libraryFileName * @param targetFolder * @return */ private static boolean extractAndLoadLibraryFile(String libFolderForCurrentOS, String libraryFileName, String targetFolder) { String nativeLibraryFilePath = libFolderForCurrentOS + "/" + libraryFileName; final String prefix = "sqlite-" + getVersion() + "-"; String extractedLibFileName = prefix + libraryFileName; File extractedLibFile = new File(targetFolder, extractedLibFileName); try { if (extractedLibFile.exists()) { // test md5sum value String md5sum1 = md5sum(SQLiteJDBCLoader.class.getResourceAsStream(nativeLibraryFilePath)); String md5sum2 = md5sum(new FileInputStream(extractedLibFile)); if (md5sum1.equals(md5sum2)) { return loadNativeLibrary(targetFolder, extractedLibFileName); } else { // remove old native library file boolean deletionSucceeded = extractedLibFile.delete(); if (!deletionSucceeded) { throw new IOException("failed to remove existing native library file: " + extractedLibFile.getAbsolutePath()); } } } // extract file into the current directory InputStream reader = SQLiteJDBCLoader.class.getResourceAsStream(nativeLibraryFilePath); FileOutputStream writer = new FileOutputStream(extractedLibFile); byte[] buffer = new byte[1024]; int bytesRead = 0; while ((bytesRead = reader.read(buffer)) != -1) { writer.write(buffer, 0, bytesRead); } writer.close(); reader.close(); if (!System.getProperty("os.name").contains("Windows")) { try { Runtime.getRuntime().exec(new String[] { "chmod", "755", extractedLibFile.getAbsolutePath() }) .waitFor(); } catch (Throwable e) {} } return loadNativeLibrary(targetFolder, extractedLibFileName); } catch (IOException e) { System.err.println(e.getMessage()); return false; } } private static synchronized boolean loadNativeLibrary(String path, String name) { File libPath = new File(path, name); if (libPath.exists()) { try { System.load(new File(path, name).getAbsolutePath()); return true; } catch (UnsatisfiedLinkError e) { System.err.println(e); return false; } } else return false; } private static void loadSQLiteNativeLibrary() { if (extracted) return; boolean runInPureJavaMode = getPureJavaFlag(); if (runInPureJavaMode) { extracted = false; return; } // Try loading library from org.sqlite.lib.path library path */ String sqliteNativeLibraryPath = System.getProperty("org.sqlite.lib.path"); String sqliteNativeLibraryName = System.getProperty("org.sqlite.lib.name"); if (sqliteNativeLibraryName == null) sqliteNativeLibraryName = System.mapLibraryName("sqlitejdbc"); if (sqliteNativeLibraryPath != null) { if (loadNativeLibrary(sqliteNativeLibraryPath, sqliteNativeLibraryName)) { extracted = true; return; } } // Load the os-dependent library from a jar file sqliteNativeLibraryPath = "/native/" + OSInfo.getNativeLibFolderPathForCurrentOS(); if (SQLiteJDBCLoader.class.getResource(sqliteNativeLibraryPath + "/" + sqliteNativeLibraryName) == null) { // use nested VM version return; } // temporary library folder String tempFolder = new File(System.getProperty("java.io.tmpdir")).getAbsolutePath(); // Try extracting the library from jar if (extractAndLoadLibraryFile(sqliteNativeLibraryPath, sqliteNativeLibraryName, tempFolder)) { extracted = true; return; } extracted = false; return; } private static void getNativeLibraryFolderForTheCurrentOS() { String osName = OSInfo.getOSName(); String archName = OSInfo.getArchName(); } public static int getMajorVersion() { String[] c = getVersion().split("\\."); return (c.length > 0) ? Integer.parseInt(c[0]) : 1; } public static int getMinorVersion() { String[] c = getVersion().split("\\."); return (c.length > 1) ? Integer.parseInt(c[1]) : 0; } public static String getVersion() { URL versionFile = SQLiteJDBCLoader.class.getResource("/META-INF/maven/org.xerial/sqlite-jdbc/pom.properties"); if (versionFile == null) versionFile = SQLiteJDBCLoader.class.getResource("/META-INF/maven/org.xerial/sqlite-jdbc/VERSION"); String version = "unknown"; try { if (versionFile != null) { Properties versionData = new Properties(); versionData.load(versionFile.openStream()); version = versionData.getProperty("version", version); version = version.trim().replaceAll("[^0-9\\.]", ""); } } catch (IOException e) { System.err.println(e); } return version; } }