/* * Copyright (C) 2010 Google Inc. * * 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. */ package org.clearsilver.jni; import java.io.File; import java.util.regex.Pattern; /** * Loads the ClearSilver JNI library. * * <p>By default, it attempts to load the library 'clearsilver-jni' from the * path specified in the 'java.library.path' system property. However, this * can be overriden by calling {@link #setLibraryName(String)} and * {@link #setLibrarySearchPaths(String[])}.</p> * * <p>If this fails, the JVM exits with a code of 1. However, this strategy * can be changed using {@link #setFailureCallback(Runnable)}.</p> */ public final class JNI { /** * Failure callback strategy that writes a message to sysout, then calls * System.exit(1). */ public static Runnable EXIT_JVM = new Runnable() { public void run() { System.err.println("Could not load '" + libraryName + "'. Searched:"); String platformLibraryName = System.mapLibraryName(libraryName); for (String path : librarySearchPaths) { System.err.println(" " + new File(path, platformLibraryName).getAbsolutePath()); } System.err.println( "Try specifying -Djava.library.path=[directory] or calling " + JNI.class.getName() + ".setLibrarySearchPaths(String...)"); System.exit(1); } }; /** * Failure callback strategy that throws an UnsatisfiedLinkError, which * should be caught be client code. */ public static Runnable THROW_ERROR = new Runnable() { public void run() { throw new UnsatisfiedLinkError("Could not load '" + libraryName + "'"); } }; private static Runnable failureCallback = EXIT_JVM; private static Object callbackLock = new Object(); private static String libraryName = "clearsilver-jni"; private static String[] librarySearchPaths = System.getProperty("java.library.path", ".").split( Pattern.quote(File.pathSeparator)); private static volatile boolean successfullyLoadedLibrary; /** * Attempts to load the ClearSilver JNI library. * * @see #setFailureCallback(Runnable) */ public static void loadLibrary() { // Library already loaded? Great - nothing to do. if (successfullyLoadedLibrary) { return; } synchronized (callbackLock) { // Search librarySearchPaths... String platformLibraryName = System.mapLibraryName(libraryName); for (String path : librarySearchPaths) { try { // Attempt to load the library in that path. System.load(new File(path, platformLibraryName).getAbsolutePath()); // If we got here, it worked. We're done. successfullyLoadedLibrary = true; return; } catch (UnsatisfiedLinkError e) { // Library not found. Continue loop. } } // Still here? Couldn't load library. Fail. if (failureCallback != null) { failureCallback.run(); } } } /** * Sets a callback for what should happen if the JNI library cannot * be loaded. The default is {@link #EXIT_JVM}. * * @see #EXIT_JVM * @see #THROW_ERROR */ public static void setFailureCallback(Runnable failureCallback) { synchronized(callbackLock) { JNI.failureCallback = failureCallback; } } /** * Set name of JNI library to load. Default is 'clearsilver-jni'. */ public static void setLibraryName(String libraryName) { JNI.libraryName = libraryName; } /** * Sets locations where JNI library is searched. */ public static void setLibrarySearchPaths(String... paths) { JNI.librarySearchPaths = paths; } }