OSDN Git Service

Change build system ant to sbt.
[mikumikustudio/MikuMikuStudio.git] / desktop / src / main / java / com / jme3 / system / Natives.java
1 /*
2  * Copyright (c) 2009-2010 jMonkeyEngine
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17  *   may be used to endorse or promote products derived from this software
18  *   without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 package com.jme3.system;
33
34 import java.io.*;
35 import java.net.MalformedURLException;
36 import java.net.URL;
37 import java.net.URLConnection;
38 import java.util.logging.Level;
39 import java.util.logging.Logger;
40
41 /**
42  * Helper class for extracting the natives (dll, so) from the jars.
43  * This class should only be used internally.
44  */
45 public class Natives {
46
47     private static final Logger logger = Logger.getLogger(Natives.class.getName());
48     private static final byte[] buf = new byte[1024];
49     private static File workingDir = new File("").getAbsoluteFile();
50  
51     public static void setExtractionDir(String name) {
52         workingDir = new File(name).getAbsoluteFile();
53     }
54
55     protected static void extractNativeLib(String sysName, String name) throws IOException {
56         extractNativeLib(sysName, name, false, true);
57     }
58
59     protected static void extractNativeLib(String sysName, String name, boolean load) throws IOException {
60         extractNativeLib(sysName, name, load, true);
61     }
62     
63     protected static void extractNativeLib(String sysName, String name, boolean load, boolean warning) throws IOException {
64         String fullname = System.mapLibraryName(name);
65
66         String path = "native/" + sysName + "/" + fullname;
67         URL url = Thread.currentThread().getContextClassLoader().getResource(path);
68         
69         if (url == null) {
70             if (sysName.equals("macosx")) {
71                 fullname = fullname.replace(".dylib", ".jnilib");
72                 String path2 = "native/" + sysName + "/" + fullname;
73                 // logger.warning("retry "+path2);
74                 url = Thread.currentThread().getContextClassLoader().getResource(path2);
75                 if (url == null) {
76                     if (!warning) {
77                         logger.log(Level.WARNING, "Cannot locate native library: {0}/{1}",
78                                 new String[]{sysName, fullname});
79                     }
80                     return;
81                 }
82             } else {
83                 if (!warning) {
84                     logger.log(Level.WARNING, "Cannot locate native library: {0}/{1}",
85                             new String[]{sysName, fullname});
86                 }
87                 return;
88             }
89         }
90         
91         URLConnection conn = url.openConnection();
92         InputStream in = conn.getInputStream();
93         File targetFile = new File(workingDir, fullname);
94         // logger.info("targetFile = "+targetFile.getPath());
95         if (targetFile.exists()){
96             // OK, compare last modified date of this file to 
97             // file in jar
98             long targetLastModified = targetFile.lastModified();
99             long sourceLastModified = conn.getLastModified();
100             
101             // Allow ~1 second range for OSes that only support low precision
102             if (targetLastModified + 1000 > sourceLastModified){
103                 logger.log(Level.FINE, "Not copying library {0}. Latest already extracted.", fullname);
104                 // return;
105             }
106         }
107         try {
108             OutputStream out = new FileOutputStream(targetFile);
109             int len;
110             while ((len = in.read(buf)) > 0) {
111                 out.write(buf, 0, len);
112             }
113             in.close();
114             out.close();
115             
116             // NOTE: On OSes that support "Date Created" property, 
117             // this will cause the last modified date to be lower than
118             // date created which makes no sense
119             targetFile.setLastModified(conn.getLastModified());
120         } catch (FileNotFoundException ex) {
121             if (ex.getMessage().contains("used by another process")) {
122                 return;
123             }
124
125             throw ex;
126         } finally {
127             if (load) {
128                 logger.log(Level.INFO, "Load native library {0}", targetFile.getAbsolutePath());
129                 System.load(targetFile.getAbsolutePath());
130             }
131         }
132         logger.log(Level.FINE, "Copied {0} to {1}", new Object[]{fullname, targetFile});
133     }
134
135     private static String getExtractionDir() {
136         URL temp = Natives.class.getResource("");
137         if (temp != null) {
138             StringBuilder sb = new StringBuilder(temp.toString());
139             if (sb.indexOf("jar:") == 0) {
140                 sb.delete(0, 4);
141                 sb.delete(sb.indexOf("!"), sb.length());
142                 sb.delete(sb.lastIndexOf("/") + 1, sb.length());
143             }
144             try {
145                 return new URL(sb.toString()).toString();
146             } catch (MalformedURLException ex) {
147                 return null;
148             }
149         }
150         return null;
151     }
152     
153     protected static boolean isUsingNativeBullet(){
154         try {
155             Class clazz = Class.forName("com.jme3.bullet.util.NativeMeshUtil");
156             return clazz != null;
157         } catch (ClassNotFoundException ex) {
158             return false;
159         }
160     }
161
162     protected static void extractNativeLibs(Platform platform, AppSettings settings) throws IOException {
163         String renderer = settings.getRenderer();
164         String audioRenderer = settings.getAudioRenderer();
165         boolean needLWJGL = false;
166         boolean needOAL = false;
167         boolean needJInput = false;
168         boolean needNativeBullet = isUsingNativeBullet();
169         if (renderer != null) {
170             if (renderer.startsWith("LWJGL")) {
171                 needLWJGL = true;
172             }
173         }
174         if (audioRenderer != null) {
175             if (audioRenderer.equals("LWJGL")) {
176                 needLWJGL = true;
177                 needOAL = true;
178             }
179         }
180         needJInput = settings.useJoysticks();
181
182         if (needLWJGL) {
183             logger.log(Level.INFO, "Extraction Directory #1: {0}", getExtractionDir());
184             logger.log(Level.INFO, "Extraction Directory #2: {0}", workingDir.toString());
185 //            logger.log(Level.INFO, "Extraction Directory #3: {0}", System.getProperty("user.dir"));
186             // LWJGL supports this feature where
187             // it can load libraries from this path.
188             // This is a fallback method in case the OS doesn't load
189             // native libraries from the working directory (e.g Linux).
190             System.setProperty("org.lwjgl.librarypath", workingDir.toString());
191         }
192
193         switch (platform) {
194             case Windows64:
195                 if (needLWJGL) {
196                     extractNativeLib("windows", "lwjgl64");
197                 }
198                 if (needOAL) {
199                     extractNativeLib("windows", "OpenAL64");
200                 }
201                 if (needJInput) {
202                     extractNativeLib("windows", "jinput-dx8_64");
203                     extractNativeLib("windows", "jinput-raw_64");
204                 }
205                 if (needNativeBullet) {
206                     extractNativeLib("windows", "bulletjme64", true, false);
207                 }
208                 break;
209             case Windows32:
210                 if (needLWJGL) {
211                     extractNativeLib("windows", "lwjgl");
212                 }
213                 if (needOAL) {
214                     extractNativeLib("windows", "OpenAL32");
215                 }
216                 if (needJInput) {
217                     extractNativeLib("windows", "jinput-dx8");
218                     extractNativeLib("windows", "jinput-raw");
219                 }
220                 if (needNativeBullet) {
221                     extractNativeLib("windows", "bulletjme", true, false);
222                 }
223                 break;
224             case Linux64:
225                 if (needLWJGL) {
226                     extractNativeLib("linux", "lwjgl64");
227                 }
228                 if (needJInput) {
229                     extractNativeLib("linux", "jinput-linux64");
230                 }
231                 if (needOAL) {
232                     extractNativeLib("linux", "openal64");
233                 }
234                 if (needNativeBullet) {
235                     extractNativeLib("linux", "bulletjme64", true, false);
236                 }
237                 break;
238             case Linux32:
239                 if (needLWJGL) {
240                     extractNativeLib("linux", "lwjgl");
241                 }
242                 if (needJInput) {
243                     extractNativeLib("linux", "jinput-linux");
244                 }
245                 if (needOAL) {
246                     extractNativeLib("linux", "openal");
247                 }
248                 if (needNativeBullet) {
249                     extractNativeLib("linux", "bulletjme", true, false);
250                 }
251                 break;
252             case SolarisAMD64:
253                 if (needLWJGL) {
254                     extractNativeLib("solaris", "lwjgl64");
255                 }
256 //                if (needJInput) {
257 //                    extractNativeLib("solaris", "jinput-linux64");
258 //                }
259                 if (needOAL) {
260                     extractNativeLib("solaris", "openal64");
261                 }
262                 if (needNativeBullet) {
263                     extractNativeLib("solaris", "bulletjme64", true, false);
264                 }
265                 break;
266             case SolarisX86:
267                 if (needLWJGL) {
268                     extractNativeLib("solaris", "lwjgl");
269                 }
270 //                if (needJInput) {
271 //                    extractNativeLib("solaris", "jinput-linux");
272 //                }
273                 if (needOAL) {
274                     extractNativeLib("solaris", "openal");
275                 }
276                 if (needNativeBullet) {
277                     extractNativeLib("solaris", "bulletjme", true, false);
278                 }
279                 break;
280             case MacOSX_PPC32:
281             case MacOSX32:
282             case MacOSX_PPC64:
283             case MacOSX64:
284                 if (needLWJGL) {
285                     extractNativeLib("macosx", "lwjgl");
286                 }
287                 if (needOAL)
288                     extractNativeLib("macosx", "openal");
289                 if (needJInput) {
290                     extractNativeLib("macosx", "jinput-osx");
291                 }
292                 if (needNativeBullet) {
293                     extractNativeLib("macosx", "bulletjme", true, false);
294                 }
295                 break;
296         }
297     }
298 }