/* JUG Java Uuid Generator * * Copyright (c) 2002-2004 Tatu Saloranta, tatu.saloranta@iki.fi * * Copyright (c) 2002 Tatu Saloranta, tatu.saloranta@iki.fi * * Licensed under the License specified in the file LICENSE which is * included with the source code. * You may not use this file except in compliance with the License. * * 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.safehaus.uuid; import java.io.*; import java.security.*; import java.util.*; /** * Proxy class that uses JNI-based functionality to obtain information * about local interfaces. *<p> * Note that there are two different places where platform-dependant * native code libraries can be located under: * <ul> * <li>System-dependant standard library location (in unix systems * often something like /lib or /usr/lib). This is not the default; * if you want to enable this loading, you need to call * {@link #setUseStdLibDir} before accessing any access method in * this class. * <li>Application dependant directory; often located in same directory * as app, or one of sub-directories. This is default setting; default * sub-directory (under current directory when starting app that uses * JUG) is specified as {@link #sDefaultLibSubdir} * </ul> */ public class NativeInterfaces { protected final static String sDefaultLibSubdir = "jug-native"; /** * Path to dir that contains native lib code. If not specified, * {@link #sDefaultLibSubdir} is used. */ private static File sLibDir = null; /** * Whether native code is to be loaded from system-dependant standard * library location or not. Default is false, meaning that standard * location is NOT used. */ private static boolean sUseStdLibDir = false; /// Whether native library has already been loaded private static boolean mNativeLoaded = false; /** * Method that allows overriding of default library directory, to * allow loading of native interface access code from specific * application dependant location. */ public synchronized static void setLibDir(File f) { sLibDir = f; } public synchronized static void setUseStdLibDir(boolean b) { sUseStdLibDir = b; } protected synchronized static void checkLoad() { if (!mNativeLoaded) { String os = System.getProperty("os.name").trim().toLowerCase(); String arch = System.getProperty("os.arch").trim().toLowerCase(); String realOS = null, realArch = null; /* Let's try to figure canonical OS name, just in case some * JVMs use funny values (unlikely) */ if (os.indexOf("windows") >= 0) { realOS = "win"; } else if (os.indexOf("linux") >= 0) { realOS = "linux"; } else if (os.indexOf("solaris") >= 0 || os.indexOf("sunos") >= 0) { realOS = "solaris"; } else if (os.indexOf("mac os x") >= 0 || os.indexOf("macosx") >= 0) { realOS = "macosx"; } else if (os.indexOf("bsd") >= 0) { if (os.indexOf("freebsd") >= 0) { realOS = "freebsd"; } else if (os.indexOf("netbsd") >= 0) { realOS = "netbsd"; } else if (os.indexOf("openbsd") >= 0) { realOS = "openbsd"; } else { // default realOS = "bsd"; } } else if (os.indexOf("aix") >= 0) { realOS = "aix"; } else if (os.indexOf("hp ux") >= 0) { realOS = "hpux"; } else { throw new Error("No native ethernet access library for OS '"+os+"'."); } /* And ditto for arch value... here it's more likely weird * values exist? */ if (arch.indexOf("x86") >= 0 || arch.indexOf("sparc") >= 0 || arch.indexOf("ppc") >= 0) { realArch = arch; // Apparently 'i386' means x86 architecture in JVM lingo? } else if (arch.indexOf("86") >= 0 || arch.indexOf("amd") >= 0) { realArch = "x86"; } else { throw new Error("No native ethernet access library for hardware platform with value '"+arch+"'."); } /* Still not really guaranteed to work; not all combinations * of os + arch are either valid, or have matching library * (notably, linux+sparc and solaris+x86 are missing?) */ String libName = realOS + "_" + realArch + "_" + "EtherAddr"; if (sUseStdLibDir) { loadStdLib(libName); } else { loadAppLib(libName); } mNativeLoaded = true; } } private static void loadStdLib(String libName) { try { System.loadLibrary(libName); } catch (SecurityException sex) { throw new Error("Trying to load library '"+libName+"': error; "+sex.toString()); } catch (UnsatisfiedLinkError uex) { throw new Error("Trying to load library '"+libName+"': error; "+uex.toString()); } } private static void loadAppLib(String libName) { String realLibName = System.mapLibraryName(libName); String prefix = "Tried to load library '"+libName +"' (filename assumed to be '"+realLibName+"')"; try { File f; if (sLibDir == null) { f = new File(sDefaultLibSubdir); f = new File(f, realLibName); } else { f = new File(sLibDir, realLibName); } // Let's first check if such a file exists... try { f = f.getCanonicalFile(); } catch (IOException ie) { throw new Error(prefix+": checking existence of '"+f.getAbsolutePath()+"': "+ie.toString()); } System.load(f.getAbsolutePath()); // Uncomment for debugging: //System.err.println("DEBUG: "+prefix+": Ok."); } catch (SecurityException sex) { throw new Error(prefix+": error; "+sex.toString()); } catch (UnsatisfiedLinkError unsatisfiedex) { throw new Error(prefix+": error; "+unsatisfiedex.toString()); } } public static org.safehaus.uuid.EthernetAddress getPrimaryInterface() { checkLoad(); try { com.ccg.net.ethernet.EthernetAddress ea = com.ccg.net.ethernet.EthernetAddress.getPrimaryAdapter(); if (ea != null) { return new org.safehaus.uuid.EthernetAddress(ea.getBytes()); } } catch (UnsatisfiedLinkError ue) { /* Should never happen as checkLoad() should have taken * care of the problems */ throw new Error(ue.toString()); } return null; } public static org.safehaus.uuid.EthernetAddress[] getAllInterfaces() { org.safehaus.uuid.EthernetAddress[] eas = null; checkLoad(); try { Collection c = com.ccg.net.ethernet.EthernetAddress.getAllAdapters(); eas = new org.safehaus.uuid.EthernetAddress[c.size()]; Iterator it = c.iterator(); for (int i = 0; it.hasNext(); ++i) { com.ccg.net.ethernet.EthernetAddress ea = (com.ccg.net.ethernet.EthernetAddress) it.next(); eas[i] = new org.safehaus.uuid.EthernetAddress(ea.getBytes()); } } catch (UnsatisfiedLinkError ue) { /* Should never happen as checkLoad() should have taken * care of the problems */ throw new Error(ue.toString()); } return eas; } /** * Test driver to test if native ethernet adapter/interface access * works ok. Tries to get the primary interface and output it; prints * out error message if access fails. */ public static void main(String[] args) { if (args.length > 0 && args[0].equalsIgnoreCase("lib")) { System.out.println("Trying to access primary ethernet interface using system-dependant library loading (use 'app' argument for other test)"); setUseStdLibDir(true); } else { System.out.println("Trying to access primary ethernet interface using system independent code loading (use 'lib' argument for other test)"); setUseStdLibDir(false); } System.out.println("Trying to access primary ethernet interface:"); try { org.safehaus.uuid.EthernetAddress pea = getPrimaryInterface(); System.out.println("Ok, the interface MAC-address is: " +pea.toString()); } catch (Throwable t) { System.out.println("Failed, error given: "+t.toString()); } } }