Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (C) 2008-2010 Wayne Meissner
*
* This file is part of the JNR project.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 jnr.ffi;
import java.io.File;
import java.io.FilenameFilter;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@SuppressWarnings({ "deprecation" ,"rawtypes" })
public abstract class Platform {
private static final java.util.Locale LOCALE = java.util.Locale.ENGLISH;
private final OS os;
private final CPU cpu;
private final int addressSize;
private final int longSize;
protected final Pattern libPattern;
private static final class SingletonHolder {
static final Platform PLATFORM = determinePlatform();
}
/**
* The common names of supported operating systems.
*/
public enum OS {
/*
* Note The names of the enum values are used in other parts of the
* code to determine where to find the native stub library. Do not rename.
*/
/** MacOSX */
DARWIN,
/** FreeBSD */
FREEBSD,
/** NetBSD */
NETBSD,
/** OpenBSD */
OPENBSD,
/** DragonFly */
DRAGONFLY,
/** Linux */
LINUX,
/** Solaris (and OpenSolaris) */
SOLARIS,
/** The evil borg operating system */
WINDOWS,
/** IBM AIX */
AIX,
/** IBM zOS **/
ZLINUX,
/** No idea what the operating system is */
UNKNOWN;
@Override
public String toString() {
return name().toLowerCase(LOCALE);
}
}
/**
* The supported CPU architectures.
*/
public enum CPU {
/*
* Note The names of the enum values are used in other parts of the
* code to determine where to find the native stub library. Do NOT rename.
*/
/** 32 bit legacy Intel */
I386,
/** 64 bit AMD (aka EM64T/X64) */
X86_64,
/** 32 bit Power PC */
PPC,
/** 64 bit Power PC */
PPC64,
/** 64 bit Power PC little endian */
PPC64LE,
/** 32 bit Sun sparc */
SPARC,
/** 64 bit Sun sparc */
SPARCV9,
/** IBM zSeries S/390 */
S390X,
/** 32 bit MIPS (used by nestedvm) */
MIPS32,
/** 32 bit ARM */
ARM,
/** 64 bit ARM */
AARCH64,
/**
* Unknown CPU architecture. A best effort will be made to infer architecture
* specific values such as address and long size.
*/
UNKNOWN;
/**
* Returns a {@code String} object representing this {@code CPU} object.
*
* @return the name of the cpu architecture as a lower case {@code String}.
*/
@Override
public String toString() {
return name().toLowerCase(LOCALE);
}
}
/**
* Determines the operating system jffi is running on
*
* @return An member of the OS enum.
*/
private static OS determineOS() {
String osName = System.getProperty("os.name").split(" ")[0];
if (startsWithIgnoreCase(osName, "mac") || startsWithIgnoreCase(osName, "darwin")) {
return OS.DARWIN;
} else if (startsWithIgnoreCase(osName, "linux")) {
return OS.LINUX;
} else if (startsWithIgnoreCase(osName, "sunos") || startsWithIgnoreCase(osName, "solaris")) {
return OS.SOLARIS;
} else if (startsWithIgnoreCase(osName, "aix")) {
return OS.AIX;
} else if (startsWithIgnoreCase(osName, "openbsd")) {
return OS.OPENBSD;
} else if (startsWithIgnoreCase(osName, "freebsd")) {
return OS.FREEBSD;
} else if (startsWithIgnoreCase(osName, "dragonfly")) {
return OS.DRAGONFLY;
} else if (startsWithIgnoreCase(osName, "windows")) {
return OS.WINDOWS;
} else {
return OS.UNKNOWN;
}
}
/**
* Determines the Platform that best describes the OS
*
* @param os The operating system.
* @return An instance of Platform
*/
private static Platform determinePlatform(OS os) {
switch (os) {
case DARWIN:
return new Darwin();
case LINUX:
return new Linux();
case WINDOWS:
return new Windows();
case UNKNOWN:
return new Unsupported(os);
default:
return new Default(os);
}
}
private static Platform determinePlatform() {
String providerName = System.getProperty("jnr.ffi.provider");
try {
Class c = Class.forName(providerName + "$Platform");
return (Platform) c.newInstance();
} catch (ClassNotFoundException ex) {
return determinePlatform(determineOS());
} catch (IllegalAccessException ex) {
throw new ExceptionInInitializerError(ex);
} catch (InstantiationException ex) {
throw new ExceptionInInitializerError(ex);
}
}
private static CPU determineCPU() {
String archString = System.getProperty("os.arch");
if (equalsIgnoreCase("x86", archString) ||
equalsIgnoreCase("i386", archString) ||
equalsIgnoreCase("i86pc", archString) ||
equalsIgnoreCase("i686", archString)) {
return CPU.I386;
} else if (equalsIgnoreCase("x86_64", archString) || equalsIgnoreCase("amd64", archString)) {
return CPU.X86_64;
} else if (equalsIgnoreCase("ppc", archString) || equalsIgnoreCase("powerpc", archString)) {
return CPU.PPC;
} else if (equalsIgnoreCase("ppc64", archString) || equalsIgnoreCase("powerpc64", archString)) {
if ("little".equals(System.getProperty("sun.cpu.endian"))) {
return CPU.PPC64LE;
}
return CPU.PPC64;
} else if (equalsIgnoreCase("ppc64le", archString) || equalsIgnoreCase("powerpc64le", archString)) {
return CPU.PPC64LE;
} else if (equalsIgnoreCase("s390", archString) || equalsIgnoreCase("s390x", archString)) {
return CPU.S390X;
} else if (equalsIgnoreCase("aarch64", archString)) {
return CPU.AARCH64;
} else if (equalsIgnoreCase("arm", archString) || equalsIgnoreCase("armv7l", archString)) {
return CPU.ARM;
}
// Try to find by lookup up in the CPU list
for (CPU cpu : CPU.values()) {
if (equalsIgnoreCase(cpu.name(), archString)) {
return cpu;
}
}
return CPU.UNKNOWN;
}
public Platform(OS os, CPU cpu, int addressSize, int longSize, String libPattern) {
this.os = os;
this.cpu = cpu;
this.addressSize = addressSize;
this.longSize = longSize;
this.libPattern = Pattern.compile(libPattern);
}
private Platform(OS os) {
this.os = os;
this.cpu = determineCPU();
String libpattern;
switch (os) {
case WINDOWS:
libpattern = ".*\\.dll$";
break;
case DARWIN:
libpattern = "lib.*\\.(dylib|jnilib)$";
break;
default:
libpattern = "lib.*\\.so.*$";
break;
}
libPattern = Pattern.compile(libpattern);
this.addressSize = calculateAddressSize(cpu);
this.longSize = os == OS.WINDOWS ? 32 : addressSize;
}
private static int calculateAddressSize(CPU cpu) {
Integer dataModel = Integer.getInteger("sun.arch.data.model");
if (dataModel == null || dataModel != 32 && dataModel != 64) {
switch (cpu) {
case I386:
case PPC:
case SPARC:
dataModel = 32;
break;
case X86_64:
case PPC64:
case PPC64LE:
case SPARCV9:
case S390X:
case AARCH64:
dataModel = 64;
break;
default:
throw new ExceptionInInitializerError("Cannot determine cpu address size");
}
}
return dataModel;
}
/**
* Gets the native Platform
*
* @return The current platform.
*/
public static Platform getNativePlatform() {
return SingletonHolder.PLATFORM;
}
@Deprecated
public static Platform getPlatform() {
return SingletonHolder.PLATFORM;
}
/**
* Gets the current Operating System.
*
* @return A OS value representing the current Operating System.
*/
public final OS getOS() {
return os;
}
/**
* Gets the current processor architecture the JVM is running on.
*
* @return A CPU value representing the current processor architecture.
*/
public final CPU getCPU() {
return cpu;
}
public final boolean isBSD() {
return os == OS.FREEBSD || os == OS.OPENBSD || os == OS.NETBSD || os == OS.DARWIN || os == OS.DRAGONFLY;
}
public final boolean isUnix() {
return os != OS.WINDOWS;
}
/**
* Gets the size of a C 'long' on the native platform.
*
* @return the size of a long in bits
* @deprecated Use {@link Runtime#longSize()} instead.
*/
public final int longSize() {
return longSize;
}
/**
* Gets the size of a C address/pointer on the native platform.
*
* @return the size of a pointer in bits
* @deprecated Use {@link Runtime#addressSize()} instead.
*/
public final int addressSize() {
return addressSize;
}
/**
* Gets the name of this Platform.
*
* @return The name of this platform.
*/
public String getName() {
return cpu + "-" + os;
}
/**
* Returns the platform specific standard C library name
*
* @return The standard C library name
*/
public String getStandardCLibraryName() {
switch (os) {
case LINUX:
return "libc.so.6";
case SOLARIS:
return "c";
case DRAGONFLY:
case FREEBSD:
case NETBSD:
return "c";
case AIX:
return addressSize == 32
? "libc.a(shr.o)"
: "libc.a(shr_64.o)";
case WINDOWS:
return "msvcrt";
default:
return "c";
}
}
/**
* Maps from a generic library name (e.g. "c") to the platform specific library name.
*
* @param libName The library name to map
* @return The mapped library name.
*/
public String mapLibraryName(String libName) {
//
// A specific version was requested - use as is for search
//
if (libPattern.matcher(libName).find()) {
return libName;
}
return System.mapLibraryName(libName);
}
/**
* Searches through a list of directories for a native library.
*
* @param libName the base name (e.g. "c") of the library to locate
* @param libraryPath the list of directories to search
* @return the path of the library
*/
public String locateLibrary(String libName, List libraryPath) {
String mappedName = mapLibraryName(libName);
for (String path : libraryPath) {
File libFile = new File(path, mappedName);
if (libFile.exists()) {
return libFile.getAbsolutePath();
}
}
// Default to letting the system search for it
return mappedName;
}
private static class Supported extends Platform {
public Supported(OS os) {
super(os);
}
}
private static class Unsupported extends Platform {
public Unsupported(OS os) {
super(os);
}
}
private static final class Default extends Supported {
public Default(OS os) {
super(os);
}
}
/**
* A {@link Platform} subclass representing the MacOS system.
*/
private static final class Darwin extends Supported {
public Darwin() {
super(OS.DARWIN);
}
@Override
public String mapLibraryName(String libName) {
//
// A specific version was requested - use as is for search
//
if (libPattern.matcher(libName).find()) {
return libName;
}
return "lib" + libName + ".dylib";
}
@Override
public String getName() {
return "Darwin";
}
}
/**
* A {@link Platform} subclass representing the Linux operating system.
*/
static final class Linux extends Supported {
public Linux() {
super(OS.LINUX);
}
@Override
public String locateLibrary(final String libName, List libraryPaths) {
Pattern exclude;
// there are /libx32 directories in wild on ubuntu 14.04 and the
// oracle-java8-installer package
if (getCPU() == CPU.X86_64) {
exclude = Pattern.compile(".*(lib[a-z]*32|i[0-9]86).*");
}
else {
exclude = Pattern.compile(".*(lib[a-z]*64|amd64|x86_64).*");
}
final Pattern versionedLibPattern = Pattern.compile("lib" + libName + "\\.so((?:\\.[0-9]+)*)$");
FilenameFilter filter = new FilenameFilter() {
public boolean accept(File dir, String name) {
return versionedLibPattern.matcher(name).matches();
}
};
Map matches = new LinkedHashMap();
for (String path : libraryPaths) {
if (exclude.matcher(path).matches()) {
continue;
}
File libraryPath = new File(path);
File[] files = libraryPath.listFiles(filter);
if (files == null) {
continue;
}
for (File file : files) {
Matcher matcher = versionedLibPattern.matcher(file.getName());
String versionString = matcher.matches() ? matcher.group(1) : "";
int[] version;
if (versionString == null || versionString.isEmpty()) {
version = new int[0];
} else {
String[] parts = versionString.split("\\.");
version = new int[parts.length - 1];
for (int i = 1; i < parts.length; i++) {
version[i - 1] = Integer.parseInt(parts[i]);
}
}
matches.put(file.getAbsolutePath(), version);
}
}
//
// Search through the results and return the highest numbered version
// i.e. libc.so.6 is preferred over libc.so.5
//
int[] bestVersion = null;
String bestMatch = null;
for (Map.Entry entry : matches.entrySet()) {
String file = entry.getKey();
int[] fileVersion = entry.getValue();
if (compareVersions(fileVersion, bestVersion) > 0) {
bestMatch = file;
bestVersion = fileVersion;
}
}
return bestMatch != null ? bestMatch : mapLibraryName(libName);
}
private static int compareVersions(int[] version1, int[] version2) {
// Null is always smallest
if (version1 == null) {
return version2 == null ? 0 : -1;
}
if (version2 == null) {
return 1;
}
// Compare component by component
int commonLength = Math.min(version1.length, version2.length);
for (int i = 0; i < commonLength; i++) {
if (version1[i] < version2[i]) {
return -1;
} else if (version1[i] > version2[i]) {
return 1;
}
}
// If all components are equal, version with fewest components is smallest
if (version1.length < version2.length) {
return -1;
} else if (version1.length > version2.length) {
return 1;
} else {
return 0;
}
}
@Override
public String mapLibraryName(String libName) {
// Older JDK on linux map 'c' to 'libc.so' which doesn't work
return "c".equals(libName) || "libc.so".equals(libName)
? "libc.so.6" : super.mapLibraryName(libName);
}
}
/**
* A {@link Platform} subclass representing the Windows system.
*/
private static class Windows extends Supported {
public Windows() {
super(OS.WINDOWS);
}
}
private static boolean startsWithIgnoreCase(String s1, String s2) {
return s1.startsWith(s2)
|| s1.toUpperCase(LOCALE).startsWith(s2.toUpperCase(LOCALE))
|| s1.toLowerCase(LOCALE).startsWith(s2.toLowerCase(LOCALE));
}
private static boolean equalsIgnoreCase(String s1, String s2) {
return s1.equalsIgnoreCase(s2)
|| s1.toUpperCase(LOCALE).equals(s2.toUpperCase(LOCALE))
|| s1.toLowerCase(LOCALE).equals(s2.toLowerCase(LOCALE));
}
}