• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package org.clearsilver.jni;
18 
19 import java.io.File;
20 import java.util.regex.Pattern;
21 
22 /**
23  * Loads the ClearSilver JNI library.
24  *
25  * <p>By default, it attempts to load the library 'clearsilver-jni' from the
26  * path specified in the 'java.library.path' system property. However, this
27  * can be overriden by calling {@link #setLibraryName(String)} and
28  * {@link #setLibrarySearchPaths(String[])}.</p>
29  *
30  * <p>If this fails, the JVM exits with a code of 1. However, this strategy
31  * can be changed using {@link #setFailureCallback(Runnable)}.</p>
32  */
33 public final class JNI {
34 
35   /**
36    * Failure callback strategy that writes a message to sysout, then calls
37    * System.exit(1).
38    */
39   public static Runnable EXIT_JVM = new Runnable() {
40     public void run() {
41       System.err.println("Could not load '" + libraryName + "'. Searched:");
42       String platformLibraryName = System.mapLibraryName(libraryName);
43       for (String path : librarySearchPaths) {
44         System.err.println("  " +
45             new File(path, platformLibraryName).getAbsolutePath());
46       }
47       System.err.println(
48           "Try specifying -Djava.library.path=[directory] or calling "
49               + JNI.class.getName() + ".setLibrarySearchPaths(String...)");
50       System.exit(1);
51     }
52   };
53 
54   /**
55    * Failure callback strategy that throws an UnsatisfiedLinkError, which
56    * should be caught be client code.
57    */
58   public static Runnable THROW_ERROR = new Runnable() {
59     public void run() {
60       throw new UnsatisfiedLinkError("Could not load '" + libraryName + "'");
61     }
62   };
63 
64   private static Runnable failureCallback = EXIT_JVM;
65 
66   private static Object callbackLock = new Object();
67 
68   private static String libraryName = "clearsilver-jni";
69 
70   private static String[] librarySearchPaths
71       = System.getProperty("java.library.path", ".").split(
72           Pattern.quote(File.pathSeparator));
73 
74   private static volatile boolean successfullyLoadedLibrary;
75 
76   /**
77    * Attempts to load the ClearSilver JNI library.
78    *
79    * @see #setFailureCallback(Runnable)
80    */
loadLibrary()81   public static void loadLibrary() {
82 
83     // Library already loaded? Great - nothing to do.
84     if (successfullyLoadedLibrary) {
85       return;
86     }
87 
88     synchronized (callbackLock) {
89 
90       // Search librarySearchPaths...
91       String platformLibraryName = System.mapLibraryName(libraryName);
92       for (String path : librarySearchPaths) {
93         try {
94           // Attempt to load the library in that path.
95           System.load(new File(path, platformLibraryName).getAbsolutePath());
96           // If we got here, it worked. We're done.
97           successfullyLoadedLibrary = true;
98           return;
99         } catch (UnsatisfiedLinkError e) {
100           // Library not found. Continue loop.
101         }
102       }
103 
104       // Still here? Couldn't load library. Fail.
105       if (failureCallback != null) {
106         failureCallback.run();
107       }
108     }
109 
110   }
111 
112   /**
113    * Sets a callback for what should happen if the JNI library cannot
114    * be loaded. The default is {@link #EXIT_JVM}.
115    *
116    * @see #EXIT_JVM
117    * @see #THROW_ERROR
118    */
setFailureCallback(Runnable failureCallback)119   public static void setFailureCallback(Runnable failureCallback) {
120     synchronized(callbackLock) {
121       JNI.failureCallback = failureCallback;
122     }
123   }
124 
125   /**
126    * Set name of JNI library to load. Default is 'clearsilver-jni'.
127    */
setLibraryName(String libraryName)128   public static void setLibraryName(String libraryName) {
129     JNI.libraryName = libraryName;
130   }
131 
132   /**
133    * Sets locations where JNI library is searched.
134    */
setLibrarySearchPaths(String... paths)135   public static void setLibrarySearchPaths(String... paths) {
136     JNI.librarySearchPaths = paths;
137   }
138 
139 }
140