/* Copyright 2008-2010 Gephi Authors : Mathieu Bastian <mathieu.bastian@gephi.org> Website : http://www.gephi.org This file is part of Gephi. DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. Copyright 2011 Gephi Consortium. All rights reserved. The contents of this file are subject to the terms of either the GNU General Public License Version 3 only ("GPL") or the Common Development and Distribution License("CDDL") (collectively, the "License"). You may not use this file except in compliance with the License. You can obtain a copy of the License at http://gephi.org/about/legal/license-notice/ or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the specific language governing permissions and limitations under the License. When distributing the software, include this License Header Notice in each file and include the License files at /cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the License Header, with the fields enclosed by brackets [] replaced by your own identifying information: "Portions Copyrighted [year] [name of copyright owner]" If you wish your version of this file to be governed by only the CDDL or only the GPL Version 3, indicate your decision by adding "[Contributor] elects to include this software in this distribution under the [CDDL or GPL Version 3] license." If you do not indicate a single choice of license, a recipient has the option to distribute your version of this file under either the CDDL, the GPL Version 3 or to extend the choice of license to its licensees as provided above. However, if you add GPL Version 3 code and therefore, elected the GPL Version 3 license, then the option applies only if the new code is made subject to such option by the copyright holder. Contributor(s): Portions Copyrighted 2011 Gephi Consortium. */ package org.gephi.lib.jogl; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.text.MessageFormat; import javax.swing.SwingUtilities; import org.openide.DialogDisplayer; import org.openide.NotifyDescriptor; import org.openide.modules.InstalledFileLocator; import org.openide.modules.ModuleInstall; import org.openide.util.Exceptions; import org.openide.util.NbBundle; /** * Manages the JOGL natives loading. Thanks to Michael Bien, Lilian Chamontin and Kenneth Russell. * * @author Mathieu Bastan */ public class JOGLNativesInstaller extends ModuleInstall { private NativeLibInfo nativeLibInfo; //Compatible nativeLibInfo with OS/Arch private boolean exitOnFatalError = true; public void restored() { if (findCompatibleOsAndArch()) { String nativeArch = nativeLibInfo.getSubDirectoryPath(); File joglDistFolder = InstalledFileLocator.getDefault().locate("modules/lib/" + nativeArch, "org.gephi.lib.jogl", false); if (joglDistFolder != null) { loadNatives(joglDistFolder); } else { fatalError(String.format(NbBundle.getMessage(JOGLNativesInstaller.class, "JOGLNativesInstaller_error1"), new Object[]{nativeArch})); } } } //============================================================= //============================================================= private boolean findCompatibleOsAndArch() { String osName = System.getProperty("os.name"); String osArch = System.getProperty("os.arch"); if (checkOSAndArch(osName, osArch)) { return true; } else { fatalError(String.format(NbBundle.getMessage(JOGLNativesInstaller.class, "JOGLNativesInstaller_error2"), new Object[]{osName, osArch})); } return false; } boolean checkOSAndArch(String osName, String osArch) { for (int i = 0; i < allNativeLibInfo.length; i++) { NativeLibInfo info = allNativeLibInfo[i]; if (info.matchesOSAndArch(osName, osArch)) { nativeLibInfo = info; return true; } } return false; } private void loadNatives(final File nativeLibDir) { try { // back to the EDT SwingUtilities.invokeAndWait(new Runnable() { public void run() { System.out.println("Loading native libraries"); // disable JOGL and GlueGen runtime library loading from elsewhere com.sun.opengl.impl.NativeLibLoader.disableLoading(); com.sun.gluegen.runtime.NativeLibLoader.disableLoading(); // Open GlueGen runtime library optimistically. Note that // currently we do not need this on any platform except X11 // ones, because JOGL doesn't use the GlueGen NativeLibrary // class anywhere except the DRIHack class, but if for // example we add JOAL support then we will need this on // every platform. loadLibrary(nativeLibDir, "gluegen-rt"); Class driHackClass = null; if (nativeLibInfo.mayNeedDRIHack()) { // Run the DRI hack try { driHackClass = Class.forName("com.sun.opengl.impl.x11.DRIHack"); driHackClass.getMethod("begin", new Class[]{}).invoke(null, new Object[]{}); } catch (Exception e) { e.printStackTrace(); } } // Load core JOGL native library loadLibrary(nativeLibDir, "jogl"); if (nativeLibInfo.mayNeedDRIHack()) { // End DRI hack try { driHackClass.getMethod("end", new Class[]{}).invoke(null, new Object[]{}); } catch (Exception e) { e.printStackTrace(); } } if (!nativeLibInfo.isMacOS()) { // borrowed from NativeLibLoader // Must pre-load JAWT on all non-Mac platforms to // ensure references from jogl_awt shared object // will succeed since JAWT shared object isn't in // default library path try { System.loadLibrary("jawt"); } catch (UnsatisfiedLinkError ex) { // Accessibility technologies load JAWT themselves; safe to continue // as long as JAWT is loaded by any loader if (ex.getMessage().indexOf("already loaded") == -1) { fatalError(String.format(NbBundle.getMessage(JOGLNativesInstaller.class, "JOGLNativesInstaller_error3"), new Object[]{})); } } } // Load AWT-specific native code loadLibrary(nativeLibDir, "jogl_awt"); } }); } catch (InterruptedException ex) { Exceptions.printStackTrace(ex); } catch (InvocationTargetException ex) { Exceptions.printStackTrace(ex); } } private void loadLibrary(File installDir, String libName) { String nativeLibName = nativeLibInfo.getNativeLibName(libName); try { System.load(new File(installDir, nativeLibName).getPath()); } catch (UnsatisfiedLinkError ex) { // should be safe to continue as long as the native is loaded by any loader if (ex.getMessage().indexOf("already loaded") == -1) { fatalError(String.format(NbBundle.getMessage(JOGLNativesInstaller.class, "JOGLNativesInstaller_error4"), new Object[]{nativeLibName})); } } } private void fatalError(String error) { Exception ex = new Exception(error); NotifyDescriptor.Exception e = new NotifyDescriptor.Exception(ex); DialogDisplayer.getDefault().notify(e); if (exitOnFatalError) { System.exit(1); } } private static class NativeLibInfo { private String osName; private String osArch; private String osNameAndArchPair; private String nativePrefix; private String nativeSuffix; public NativeLibInfo(String osName, String osArch, String osNameAndArchPair, String nativePrefix, String nativeSuffix) { this.osName = osName; this.osArch = osArch; this.osNameAndArchPair = osNameAndArchPair; this.nativePrefix = nativePrefix; this.nativeSuffix = nativeSuffix; } public boolean matchesOSAndArch(String osName, String osArch) { if (osName.toLowerCase().startsWith(this.osName)) { if ((this.osArch == null) || (osArch.toLowerCase().equals(this.osArch))) { return true; } } return false; } public boolean matchesNativeLib(String fileName) { if (fileName.toLowerCase().endsWith(nativeSuffix)) { return true; } return false; } public String formatNativeJarName(String nativeJarPattern) { return MessageFormat.format(nativeJarPattern, new Object[]{osNameAndArchPair}); } public String getNativeLibName(String baseName) { return nativePrefix + baseName + nativeSuffix; } public boolean isMacOS() { return (osName.equals("mac")); } public boolean mayNeedDRIHack() { return (!isMacOS() && !osName.equals("win")); } public String getSubDirectoryPath() { return osNameAndArchPair; } } private static final NativeLibInfo[] allNativeLibInfo = { new NativeLibInfo("win", "x86", "windows-i586", "", ".dll"), new NativeLibInfo("win", "amd64", "windows-amd64", "", ".dll"), new NativeLibInfo("win", "x86_64", "windows-amd64", "", ".dll"), new NativeLibInfo("mac", "ppc", "macosx-ppc", "lib", ".jnilib"), new NativeLibInfo("mac", "i386", "macosx-universal", "lib", ".jnilib"), new NativeLibInfo("mac", "x86_64", "macosx-universal", "lib", ".jnilib"), new NativeLibInfo("linux", "i386", "linux-i586", "lib", ".so"), new NativeLibInfo("linux", "x86", "linux-i586", "lib", ".so"), new NativeLibInfo("linux", "amd64", "linux-amd64", "lib", ".so"), new NativeLibInfo("linux", "x86_64", "linux-amd64", "lib", ".so"), new NativeLibInfo("sunos", "sparc", "solaris-sparc", "lib", ".so"), new NativeLibInfo("sunos", "sparcv9", "solaris-sparcv9", "lib", ".so"), new NativeLibInfo("sunos", "x86", "solaris-i586", "lib", ".so"), new NativeLibInfo("sunos", "amd64", "solaris-amd64", "lib", ".so"), new NativeLibInfo("sunos", "x86_64", "solaris-amd64", "lib", ".so") }; }