/* 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());
}
}
}