/*
* 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;
}
}