OSDN Git Service

ran gdx-tools HeaderFixer tool
[mikumikustudio/libgdx-mikumikustudio.git] / extensions / gdx-jnigen / src / com / badlogic / gdx / jnigen / JniGenSharedLibraryLoader.java
1 /*******************************************************************************\r
2  * Copyright 2011 See AUTHORS file.\r
3  * \r
4  * Licensed under the Apache License, Version 2.0 (the "License");\r
5  * you may not use this file except in compliance with the License.\r
6  * You may obtain a copy of the License at\r
7  * \r
8  *   http://www.apache.org/licenses/LICENSE-2.0\r
9  * \r
10  * Unless required by applicable law or agreed to in writing, software\r
11  * distributed under the License is distributed on an "AS IS" BASIS,\r
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  * See the License for the specific language governing permissions and\r
14  * limitations under the License.\r
15  ******************************************************************************/
16
17 package com.badlogic.gdx.jnigen;\r
18 \r
19 import java.io.File;\r
20 import java.io.FileInputStream;\r
21 import java.io.FileNotFoundException;\r
22 import java.io.FileOutputStream;\r
23 import java.io.IOException;\r
24 import java.io.InputStream;\r
25 import java.util.HashSet;\r
26 import java.util.Set;\r
27 import java.util.zip.CRC32;\r
28 import java.util.zip.ZipEntry;\r
29 import java.util.zip.ZipFile;\r
30 \r
31 /** Loads shared libraries from a natives jar file (desktop) or arm folders (Android). For desktop projects, have the natives jar\r
32  * in the classpath, for Android projects put the shared libraries in the libs/armeabi and libs/armeabi-v7a folders.\r
33  * \r
34  * See {@link AntScriptGenerator}.\r
35  * \r
36  * @author mzechner */\r
37 public class JniGenSharedLibraryLoader {\r
38         private static Set<String> loadedLibraries = new HashSet<String>();\r
39         private String nativesJar;\r
40 \r
41         public JniGenSharedLibraryLoader () {\r
42         }\r
43 \r
44         /** Fetches the natives from the given natives jar file. Used for testing a shared lib on the fly, see MyJniClass.\r
45          * @param nativesJar */\r
46         public JniGenSharedLibraryLoader (String nativesJar) {\r
47                 this.nativesJar = nativesJar;\r
48         }\r
49 \r
50         /** Returns a CRC of the remaining bytes in the stream. */\r
51         public String crc (InputStream input) {\r
52                 if (input == null) return "" + System.nanoTime(); // fallback\r
53                 CRC32 crc = new CRC32();\r
54                 byte[] buffer = new byte[4096];\r
55                 try {\r
56                         while (true) {\r
57                                 int length = input.read(buffer);\r
58                                 if (length == -1) break;\r
59                                 crc.update(buffer, 0, length);\r
60                         }\r
61                 } catch (Exception ex) {\r
62                         try {\r
63                                 input.close();\r
64                         } catch (Exception ignored) {\r
65                         }\r
66                 }\r
67                 return Long.toString(crc.getValue());\r
68         }\r
69 \r
70         private boolean loadLibrary (String sharedLibName) {\r
71                 String path = extractLibrary(sharedLibName);\r
72                 if (path != null) System.load(path);\r
73                 return path != null;\r
74         }\r
75 \r
76         private String extractLibrary (String sharedLibName) {\r
77                 String srcCrc = crc(JniGenSharedLibraryLoader.class.getResourceAsStream("/" + sharedLibName));\r
78                 File nativesDir = new File(System.getProperty("java.io.tmpdir") + "/jnigen/" + srcCrc);\r
79                 File nativeFile = new File(nativesDir, sharedLibName);\r
80                 \r
81                 String extractedCrc = null;\r
82                 if (nativeFile.exists()) {\r
83                         try {\r
84                                 extractedCrc = crc(new FileInputStream(nativeFile));\r
85                         } catch (FileNotFoundException ignored) {\r
86                         }\r
87                 }\r
88                 \r
89                 if(extractedCrc == null || !extractedCrc.equals(srcCrc)) {\r
90                         try {\r
91                                 // Extract native from classpath to temp dir.\r
92                                 InputStream input = null;\r
93                                 if (nativesJar == null)\r
94                                         input = JniGenSharedLibraryLoader.class.getResourceAsStream("/" + sharedLibName);\r
95                                 else\r
96                                         input = getFromJar(nativesJar, sharedLibName);\r
97                                 if (input == null) return null;\r
98                                 nativesDir.mkdirs();\r
99                                 FileOutputStream output = new FileOutputStream(nativeFile);\r
100                                 byte[] buffer = new byte[4096];\r
101                                 while (true) {\r
102                                         int length = input.read(buffer);\r
103                                         if (length == -1) break;\r
104                                         output.write(buffer, 0, length);\r
105                                 }\r
106                                 input.close();\r
107                                 output.close();\r
108                         } catch (IOException ex) {\r
109                                 ex.printStackTrace();\r
110                                 throw new RuntimeException(ex);\r
111                         }\r
112                 }\r
113                 return nativeFile.exists() ? nativeFile.getAbsolutePath() : null;\r
114         }\r
115 \r
116         private InputStream getFromJar (String jarFile, String sharedLibrary) throws IOException {\r
117                 ZipFile file = new ZipFile(nativesJar);\r
118                 ZipEntry entry = file.getEntry(sharedLibrary);\r
119                 return file.getInputStream(entry);\r
120         }\r
121 \r
122         /** Loads a shared library with the given name for the platform the application is running on. The name should not contain a\r
123          * prefix (e.g. 'lib') or suffix (e.g. '.dll).\r
124          * @param sharedLibName */\r
125         public synchronized void load (String sharedLibName) {\r
126                 if (loadedLibraries.contains(sharedLibName)) return;\r
127 \r
128                 boolean isWindows = System.getProperty("os.name").contains("Windows");\r
129                 boolean isLinux = System.getProperty("os.name").contains("Linux");\r
130                 boolean isMac = System.getProperty("os.name").contains("Mac");\r
131                 boolean isAndroid = false;\r
132                 boolean is64Bit = System.getProperty("os.arch").equals("amd64");\r
133                 String vm = System.getProperty("java.vm.name");\r
134                 if (vm != null && vm.contains("Dalvik")) {\r
135                         isAndroid = true;\r
136                         isWindows = false;\r
137                         isLinux = false;\r
138                         isMac = false;\r
139                         is64Bit = false;\r
140                 }\r
141 \r
142                 boolean loaded = false;\r
143                 if (isWindows) {\r
144                         if (!is64Bit)\r
145                                 loaded = loadLibrary(sharedLibName + ".dll");\r
146                         else\r
147                                 loaded = loadLibrary(sharedLibName + "64.dll");\r
148                 }\r
149                 if (isLinux) {\r
150                         if (!is64Bit)\r
151                                 loaded = loadLibrary("lib" + sharedLibName + ".so");\r
152                         else\r
153                                 loaded = loadLibrary("lib" + sharedLibName + "64.so");\r
154                 }\r
155                 if (isMac) {\r
156                         loaded = loadLibrary("lib" + sharedLibName + ".dylib");\r
157                 }\r
158                 if (isAndroid) {\r
159                         System.loadLibrary(sharedLibName);\r
160                         loaded = true;\r
161                 }\r
162                 if (loaded) loadedLibraries.add(sharedLibName);\r
163         }\r
164 }