2014-05-17 19:26:01 +02:00
|
|
|
/*
|
|
|
|
* Copyright 2014 The Netty Project
|
|
|
|
*
|
|
|
|
* The Netty Project licenses this file to you 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 io.netty.handler.ssl;
|
|
|
|
|
2016-02-03 20:50:57 +01:00
|
|
|
import io.netty.buffer.ByteBuf;
|
2016-06-20 14:07:53 +02:00
|
|
|
import io.netty.handler.ssl.util.SelfSignedCertificate;
|
2016-08-09 18:14:22 +02:00
|
|
|
import io.netty.util.ReferenceCountUtil;
|
|
|
|
import io.netty.util.ReferenceCounted;
|
2014-05-17 19:26:01 +02:00
|
|
|
import io.netty.util.internal.NativeLibraryLoader;
|
2016-02-19 18:20:35 +01:00
|
|
|
import io.netty.util.internal.SystemPropertyUtil;
|
2014-05-17 19:26:01 +02:00
|
|
|
import io.netty.util.internal.logging.InternalLogger;
|
|
|
|
import io.netty.util.internal.logging.InternalLoggerFactory;
|
2017-02-10 16:25:47 +01:00
|
|
|
import io.netty.internal.tcnative.Buffer;
|
|
|
|
import io.netty.internal.tcnative.Library;
|
|
|
|
import io.netty.internal.tcnative.SSL;
|
|
|
|
import io.netty.internal.tcnative.SSLContext;
|
2016-08-10 08:55:30 +02:00
|
|
|
|
2016-08-01 22:17:30 +02:00
|
|
|
import java.security.AccessController;
|
|
|
|
import java.security.PrivilegedAction;
|
2014-12-30 10:59:30 +01:00
|
|
|
import java.util.Collections;
|
2014-12-30 11:20:43 +01:00
|
|
|
import java.util.LinkedHashSet;
|
2016-02-19 18:20:35 +01:00
|
|
|
import java.util.Locale;
|
2014-12-30 11:20:43 +01:00
|
|
|
import java.util.Set;
|
2014-05-17 19:26:01 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Tells if <a href="http://netty.io/wiki/forked-tomcat-native.html">{@code netty-tcnative}</a> and its OpenSSL support
|
|
|
|
* are available.
|
|
|
|
*/
|
|
|
|
public final class OpenSsl {
|
|
|
|
|
|
|
|
private static final InternalLogger logger = InternalLoggerFactory.getInstance(OpenSsl.class);
|
2016-03-02 20:18:45 +01:00
|
|
|
private static final String LINUX = "linux";
|
2016-02-19 18:20:35 +01:00
|
|
|
private static final String UNKNOWN = "unknown";
|
2014-05-17 19:26:01 +02:00
|
|
|
private static final Throwable UNAVAILABILITY_CAUSE;
|
|
|
|
|
2016-06-22 15:46:45 +02:00
|
|
|
static final Set<String> AVAILABLE_CIPHER_SUITES;
|
|
|
|
private static final Set<String> AVAILABLE_OPENSSL_CIPHER_SUITES;
|
|
|
|
private static final Set<String> AVAILABLE_JAVA_CIPHER_SUITES;
|
2016-06-20 14:07:53 +02:00
|
|
|
private static final boolean SUPPORTS_KEYMANAGER_FACTORY;
|
2016-08-01 22:17:30 +02:00
|
|
|
private static final boolean USE_KEYMANAGER_FACTORY;
|
2016-06-22 15:46:45 +02:00
|
|
|
|
|
|
|
// Protocols
|
|
|
|
static final String PROTOCOL_SSL_V2_HELLO = "SSLv2Hello";
|
|
|
|
static final String PROTOCOL_SSL_V2 = "SSLv2";
|
|
|
|
static final String PROTOCOL_SSL_V3 = "SSLv3";
|
|
|
|
static final String PROTOCOL_TLS_V1 = "TLSv1";
|
|
|
|
static final String PROTOCOL_TLS_V1_1 = "TLSv1.1";
|
|
|
|
static final String PROTOCOL_TLS_V1_2 = "TLSv1.2";
|
|
|
|
|
2017-01-27 11:54:11 +01:00
|
|
|
static final Set<String> SUPPORTED_PROTOCOLS_SET;
|
2014-12-30 10:59:30 +01:00
|
|
|
|
2014-05-17 19:26:01 +02:00
|
|
|
static {
|
|
|
|
Throwable cause = null;
|
2015-01-08 04:23:14 +01:00
|
|
|
|
|
|
|
// Test if netty-tcnative is in the classpath first.
|
2014-05-17 19:26:01 +02:00
|
|
|
try {
|
2017-02-10 16:25:47 +01:00
|
|
|
Class.forName("io.netty.internal.tcnative.SSL", false, OpenSsl.class.getClassLoader());
|
2015-01-08 04:23:14 +01:00
|
|
|
} catch (ClassNotFoundException t) {
|
2014-05-17 19:26:01 +02:00
|
|
|
cause = t;
|
|
|
|
logger.debug(
|
2015-01-08 04:23:14 +01:00
|
|
|
"netty-tcnative not in the classpath; " +
|
|
|
|
OpenSslEngine.class.getSimpleName() + " will be unavailable.");
|
|
|
|
}
|
|
|
|
|
|
|
|
// If in the classpath, try to load the native library and initialize netty-tcnative.
|
|
|
|
if (cause == null) {
|
|
|
|
try {
|
2016-04-11 18:06:48 +02:00
|
|
|
// The JNI library was not already loaded. Load it now.
|
|
|
|
loadTcNative();
|
|
|
|
} catch (Throwable t) {
|
|
|
|
cause = t;
|
|
|
|
logger.debug(
|
|
|
|
"Failed to load netty-tcnative; " +
|
|
|
|
OpenSslEngine.class.getSimpleName() + " will be unavailable, unless the " +
|
|
|
|
"application has already loaded the symbols by some other means. " +
|
|
|
|
"See http://netty.io/wiki/forked-tomcat-native.html for more information.", t);
|
|
|
|
}
|
2016-03-02 20:18:45 +01:00
|
|
|
|
2016-04-11 18:06:48 +02:00
|
|
|
try {
|
|
|
|
initializeTcNative();
|
2016-02-19 18:20:35 +01:00
|
|
|
|
2016-04-11 18:06:48 +02:00
|
|
|
// The library was initialized successfully. If loading the library failed above,
|
|
|
|
// reset the cause now since it appears that the library was loaded by some other
|
|
|
|
// means.
|
|
|
|
cause = null;
|
2015-01-08 04:23:14 +01:00
|
|
|
} catch (Throwable t) {
|
2016-04-11 18:06:48 +02:00
|
|
|
if (cause == null) {
|
|
|
|
cause = t;
|
|
|
|
}
|
2015-01-08 04:23:14 +01:00
|
|
|
logger.debug(
|
2016-04-11 18:06:48 +02:00
|
|
|
"Failed to initialize netty-tcnative; " +
|
2015-01-08 04:43:03 +01:00
|
|
|
OpenSslEngine.class.getSimpleName() + " will be unavailable. " +
|
|
|
|
"See http://netty.io/wiki/forked-tomcat-native.html for more information.", t);
|
2015-01-08 04:23:14 +01:00
|
|
|
}
|
2014-05-17 19:26:01 +02:00
|
|
|
}
|
2015-01-08 04:23:14 +01:00
|
|
|
|
2014-05-17 19:26:01 +02:00
|
|
|
UNAVAILABILITY_CAUSE = cause;
|
2014-12-30 10:59:30 +01:00
|
|
|
|
|
|
|
if (cause == null) {
|
2016-06-22 15:46:45 +02:00
|
|
|
final Set<String> availableOpenSslCipherSuites = new LinkedHashSet<String>(128);
|
2016-06-20 14:07:53 +02:00
|
|
|
boolean supportsKeyManagerFactory = false;
|
2016-08-01 22:17:30 +02:00
|
|
|
boolean useKeyManagerFactory = false;
|
2014-12-30 10:59:30 +01:00
|
|
|
try {
|
2016-08-10 08:55:30 +02:00
|
|
|
final long sslCtx = SSLContext.make(SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_SERVER);
|
2016-06-20 14:07:53 +02:00
|
|
|
long privateKeyBio = 0;
|
|
|
|
long certBio = 0;
|
2014-12-30 10:59:30 +01:00
|
|
|
try {
|
|
|
|
SSLContext.setCipherSuite(sslCtx, "ALL");
|
|
|
|
final long ssl = SSL.newSSL(sslCtx, true);
|
|
|
|
try {
|
|
|
|
for (String c: SSL.getCiphers(ssl)) {
|
|
|
|
// Filter out bad input.
|
2017-02-10 15:03:00 +01:00
|
|
|
if (c == null || c.isEmpty() || availableOpenSslCipherSuites.contains(c)) {
|
2014-12-30 10:59:30 +01:00
|
|
|
continue;
|
|
|
|
}
|
2016-06-22 15:46:45 +02:00
|
|
|
availableOpenSslCipherSuites.add(c);
|
2014-12-30 10:59:30 +01:00
|
|
|
}
|
2016-06-20 14:07:53 +02:00
|
|
|
try {
|
|
|
|
SelfSignedCertificate cert = new SelfSignedCertificate();
|
2017-02-10 15:03:00 +01:00
|
|
|
certBio = ReferenceCountedOpenSslContext.toBIO(cert.cert());
|
2016-06-20 14:07:53 +02:00
|
|
|
SSL.setCertificateChainBio(ssl, certBio, false);
|
|
|
|
supportsKeyManagerFactory = true;
|
2016-08-01 22:17:30 +02:00
|
|
|
useKeyManagerFactory = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
|
|
|
|
@Override
|
|
|
|
public Boolean run() {
|
|
|
|
return SystemPropertyUtil.getBoolean(
|
|
|
|
"io.netty.handler.ssl.openssl.useKeyManagerFactory", true);
|
|
|
|
}
|
|
|
|
});
|
2016-06-20 14:07:53 +02:00
|
|
|
} catch (Throwable ignore) {
|
|
|
|
logger.debug("KeyManagerFactory not supported.");
|
|
|
|
}
|
2014-12-30 10:59:30 +01:00
|
|
|
} finally {
|
|
|
|
SSL.freeSSL(ssl);
|
2016-06-20 14:07:53 +02:00
|
|
|
if (privateKeyBio != 0) {
|
|
|
|
SSL.freeBIO(privateKeyBio);
|
|
|
|
}
|
|
|
|
if (certBio != 0) {
|
|
|
|
SSL.freeBIO(certBio);
|
|
|
|
}
|
2014-12-30 10:59:30 +01:00
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
SSLContext.free(sslCtx);
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
logger.warn("Failed to get the list of available OpenSSL cipher suites.", e);
|
|
|
|
}
|
2016-06-22 15:46:45 +02:00
|
|
|
AVAILABLE_OPENSSL_CIPHER_SUITES = Collections.unmodifiableSet(availableOpenSslCipherSuites);
|
2014-12-30 10:59:30 +01:00
|
|
|
|
2016-06-22 15:46:45 +02:00
|
|
|
final Set<String> availableJavaCipherSuites = new LinkedHashSet<String>(
|
|
|
|
AVAILABLE_OPENSSL_CIPHER_SUITES.size() * 2);
|
|
|
|
for (String cipher: AVAILABLE_OPENSSL_CIPHER_SUITES) {
|
|
|
|
// Included converted but also openssl cipher name
|
|
|
|
availableJavaCipherSuites.add(CipherSuiteConverter.toJava(cipher, "TLS"));
|
|
|
|
availableJavaCipherSuites.add(CipherSuiteConverter.toJava(cipher, "SSL"));
|
|
|
|
}
|
|
|
|
AVAILABLE_JAVA_CIPHER_SUITES = Collections.unmodifiableSet(availableJavaCipherSuites);
|
|
|
|
|
|
|
|
final Set<String> availableCipherSuites = new LinkedHashSet<String>(
|
|
|
|
AVAILABLE_OPENSSL_CIPHER_SUITES.size() + AVAILABLE_JAVA_CIPHER_SUITES.size());
|
|
|
|
for (String cipher: AVAILABLE_OPENSSL_CIPHER_SUITES) {
|
|
|
|
availableCipherSuites.add(cipher);
|
|
|
|
}
|
|
|
|
for (String cipher: AVAILABLE_JAVA_CIPHER_SUITES) {
|
|
|
|
availableCipherSuites.add(cipher);
|
|
|
|
}
|
|
|
|
AVAILABLE_CIPHER_SUITES = availableCipherSuites;
|
2016-06-20 14:07:53 +02:00
|
|
|
SUPPORTS_KEYMANAGER_FACTORY = supportsKeyManagerFactory;
|
2016-08-01 22:17:30 +02:00
|
|
|
USE_KEYMANAGER_FACTORY = useKeyManagerFactory;
|
2017-01-27 11:54:11 +01:00
|
|
|
|
|
|
|
Set<String> protocols = new LinkedHashSet<String>(6);
|
|
|
|
// Seems like there is no way to explicitly disable SSLv2Hello in openssl so it is always enabled
|
|
|
|
protocols.add(PROTOCOL_SSL_V2_HELLO);
|
2016-08-10 08:55:30 +02:00
|
|
|
if (doesSupportProtocol(SSL.SSL_PROTOCOL_SSLV2)) {
|
|
|
|
protocols.add(PROTOCOL_SSL_V2);
|
|
|
|
}
|
|
|
|
if (doesSupportProtocol(SSL.SSL_PROTOCOL_SSLV3)) {
|
|
|
|
protocols.add(PROTOCOL_SSL_V3);
|
|
|
|
}
|
|
|
|
if (doesSupportProtocol(SSL.SSL_PROTOCOL_TLSV1)) {
|
|
|
|
protocols.add(PROTOCOL_TLS_V1);
|
2017-01-27 11:54:11 +01:00
|
|
|
}
|
2016-08-10 08:55:30 +02:00
|
|
|
if (doesSupportProtocol(SSL.SSL_PROTOCOL_TLSV1_1)) {
|
|
|
|
protocols.add(PROTOCOL_TLS_V1_1);
|
|
|
|
}
|
|
|
|
if (doesSupportProtocol(SSL.SSL_PROTOCOL_TLSV1_2)) {
|
|
|
|
protocols.add(PROTOCOL_TLS_V1_2);
|
|
|
|
}
|
|
|
|
|
2017-01-27 11:54:11 +01:00
|
|
|
SUPPORTED_PROTOCOLS_SET = Collections.unmodifiableSet(protocols);
|
2014-12-30 10:59:30 +01:00
|
|
|
} else {
|
2016-06-22 15:46:45 +02:00
|
|
|
AVAILABLE_OPENSSL_CIPHER_SUITES = Collections.emptySet();
|
|
|
|
AVAILABLE_JAVA_CIPHER_SUITES = Collections.emptySet();
|
2014-12-30 11:20:43 +01:00
|
|
|
AVAILABLE_CIPHER_SUITES = Collections.emptySet();
|
2016-06-20 14:07:53 +02:00
|
|
|
SUPPORTS_KEYMANAGER_FACTORY = false;
|
2016-08-01 22:17:30 +02:00
|
|
|
USE_KEYMANAGER_FACTORY = false;
|
2017-01-27 11:54:11 +01:00
|
|
|
SUPPORTED_PROTOCOLS_SET = Collections.emptySet();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-10 08:55:30 +02:00
|
|
|
private static boolean doesSupportProtocol(int protocol) {
|
2017-01-27 11:54:11 +01:00
|
|
|
long sslCtx = -1;
|
|
|
|
try {
|
2016-08-10 08:55:30 +02:00
|
|
|
sslCtx = SSLContext.make(protocol, SSL.SSL_MODE_COMBINED);
|
2017-01-27 11:54:11 +01:00
|
|
|
return true;
|
|
|
|
} catch (Exception ignore) {
|
|
|
|
return false;
|
|
|
|
} finally {
|
|
|
|
if (sslCtx != -1) {
|
|
|
|
SSLContext.free(sslCtx);
|
|
|
|
}
|
2014-12-30 10:59:30 +01:00
|
|
|
}
|
2014-05-17 19:26:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns {@code true} if and only if
|
|
|
|
* <a href="http://netty.io/wiki/forked-tomcat-native.html">{@code netty-tcnative}</a> and its OpenSSL support
|
|
|
|
* are available.
|
|
|
|
*/
|
|
|
|
public static boolean isAvailable() {
|
|
|
|
return UNAVAILABILITY_CAUSE == null;
|
|
|
|
}
|
|
|
|
|
2015-03-05 14:19:13 +01:00
|
|
|
/**
|
|
|
|
* Returns {@code true} if the used version of openssl supports
|
|
|
|
* <a href="https://tools.ietf.org/html/rfc7301">ALPN</a>.
|
|
|
|
*/
|
|
|
|
public static boolean isAlpnSupported() {
|
2015-04-15 23:05:10 +02:00
|
|
|
return version() >= 0x10002000L;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the version of the used available OpenSSL library or {@code -1} if {@link #isAvailable()}
|
|
|
|
* returns {@code false}.
|
|
|
|
*/
|
|
|
|
public static int version() {
|
|
|
|
if (isAvailable()) {
|
|
|
|
return SSL.version();
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the version string of the used available OpenSSL library or {@code null} if {@link #isAvailable()}
|
|
|
|
* returns {@code false}.
|
|
|
|
*/
|
|
|
|
public static String versionString() {
|
|
|
|
if (isAvailable()) {
|
|
|
|
return SSL.versionString();
|
|
|
|
}
|
|
|
|
return null;
|
2015-03-05 14:19:13 +01:00
|
|
|
}
|
|
|
|
|
2014-05-17 19:26:01 +02:00
|
|
|
/**
|
|
|
|
* Ensure that <a href="http://netty.io/wiki/forked-tomcat-native.html">{@code netty-tcnative}</a> and
|
|
|
|
* its OpenSSL support are available.
|
|
|
|
*
|
|
|
|
* @throws UnsatisfiedLinkError if unavailable
|
|
|
|
*/
|
|
|
|
public static void ensureAvailability() {
|
|
|
|
if (UNAVAILABILITY_CAUSE != null) {
|
|
|
|
throw (Error) new UnsatisfiedLinkError(
|
|
|
|
"failed to load the required native library").initCause(UNAVAILABILITY_CAUSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the cause of unavailability of
|
|
|
|
* <a href="http://netty.io/wiki/forked-tomcat-native.html">{@code netty-tcnative}</a> and its OpenSSL support.
|
|
|
|
*
|
|
|
|
* @return the cause if unavailable. {@code null} if available.
|
|
|
|
*/
|
|
|
|
public static Throwable unavailabilityCause() {
|
|
|
|
return UNAVAILABILITY_CAUSE;
|
|
|
|
}
|
|
|
|
|
2016-06-22 15:46:45 +02:00
|
|
|
/**
|
|
|
|
* @deprecated use {@link #availableOpenSslCipherSuites()}
|
|
|
|
*/
|
|
|
|
@Deprecated
|
|
|
|
public static Set<String> availableCipherSuites() {
|
|
|
|
return availableOpenSslCipherSuites();
|
|
|
|
}
|
|
|
|
|
2014-12-30 10:59:30 +01:00
|
|
|
/**
|
|
|
|
* Returns all the available OpenSSL cipher suites.
|
|
|
|
* Please note that the returned array may include the cipher suites that are insecure or non-functional.
|
|
|
|
*/
|
2016-06-22 15:46:45 +02:00
|
|
|
public static Set<String> availableOpenSslCipherSuites() {
|
|
|
|
return AVAILABLE_OPENSSL_CIPHER_SUITES;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns all the available cipher suites (Java-style).
|
|
|
|
* Please note that the returned array may include the cipher suites that are insecure or non-functional.
|
|
|
|
*/
|
|
|
|
public static Set<String> availableJavaCipherSuites() {
|
|
|
|
return AVAILABLE_JAVA_CIPHER_SUITES;
|
2014-12-30 11:20:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns {@code true} if and only if the specified cipher suite is available in OpenSSL.
|
|
|
|
* Both Java-style cipher suite and OpenSSL-style cipher suite are accepted.
|
|
|
|
*/
|
|
|
|
public static boolean isCipherSuiteAvailable(String cipherSuite) {
|
|
|
|
String converted = CipherSuiteConverter.toOpenSsl(cipherSuite);
|
|
|
|
if (converted != null) {
|
|
|
|
cipherSuite = converted;
|
|
|
|
}
|
2016-06-22 15:46:45 +02:00
|
|
|
return AVAILABLE_OPENSSL_CIPHER_SUITES.contains(cipherSuite);
|
2014-12-30 10:59:30 +01:00
|
|
|
}
|
|
|
|
|
2016-06-20 14:07:53 +02:00
|
|
|
/**
|
|
|
|
* Returns {@code true} if {@link javax.net.ssl.KeyManagerFactory} is supported when using OpenSSL.
|
|
|
|
*/
|
|
|
|
public static boolean supportsKeyManagerFactory() {
|
|
|
|
return SUPPORTS_KEYMANAGER_FACTORY;
|
|
|
|
}
|
|
|
|
|
2016-08-01 22:17:30 +02:00
|
|
|
static boolean useKeyManagerFactory() {
|
|
|
|
return USE_KEYMANAGER_FACTORY;
|
|
|
|
}
|
|
|
|
|
2016-02-03 20:50:57 +01:00
|
|
|
static long memoryAddress(ByteBuf buf) {
|
|
|
|
assert buf.isDirect();
|
|
|
|
return buf.hasMemoryAddress() ? buf.memoryAddress() : Buffer.address(buf.nioBuffer());
|
|
|
|
}
|
|
|
|
|
2014-05-17 19:26:01 +02:00
|
|
|
private OpenSsl() { }
|
2016-02-19 18:20:35 +01:00
|
|
|
|
2016-04-11 18:06:48 +02:00
|
|
|
private static void loadTcNative() throws Exception {
|
|
|
|
String os = normalizeOs(SystemPropertyUtil.get("os.name", ""));
|
|
|
|
String arch = normalizeArch(SystemPropertyUtil.get("os.arch", ""));
|
|
|
|
|
|
|
|
Set<String> libNames = new LinkedHashSet<String>(3);
|
|
|
|
// First, try loading the platform-specific library. Platform-specific
|
|
|
|
// libraries will be available if using a tcnative uber jar.
|
|
|
|
libNames.add("netty-tcnative-" + os + '-' + arch);
|
|
|
|
if (LINUX.equalsIgnoreCase(os)) {
|
|
|
|
// Fedora SSL lib so naming (libssl.so.10 vs libssl.so.1.0.0)..
|
|
|
|
libNames.add("netty-tcnative-" + os + '-' + arch + "-fedora");
|
|
|
|
}
|
|
|
|
// finally the default library.
|
|
|
|
libNames.add("netty-tcnative");
|
|
|
|
|
|
|
|
NativeLibraryLoader.loadFirstAvailable(SSL.class.getClassLoader(),
|
|
|
|
libNames.toArray(new String[libNames.size()]));
|
|
|
|
}
|
|
|
|
|
2016-08-10 08:55:30 +02:00
|
|
|
private static boolean initializeTcNative() throws Exception {
|
|
|
|
return Library.initialize();
|
2016-04-11 18:06:48 +02:00
|
|
|
}
|
|
|
|
|
2016-02-19 18:20:35 +01:00
|
|
|
private static String normalizeOs(String value) {
|
|
|
|
value = normalize(value);
|
|
|
|
if (value.startsWith("aix")) {
|
|
|
|
return "aix";
|
|
|
|
}
|
|
|
|
if (value.startsWith("hpux")) {
|
|
|
|
return "hpux";
|
|
|
|
}
|
|
|
|
if (value.startsWith("os400")) {
|
|
|
|
// Avoid the names such as os4000
|
|
|
|
if (value.length() <= 5 || !Character.isDigit(value.charAt(5))) {
|
|
|
|
return "os400";
|
|
|
|
}
|
|
|
|
}
|
2016-03-02 20:18:45 +01:00
|
|
|
if (value.startsWith(LINUX)) {
|
|
|
|
return LINUX;
|
2016-02-19 18:20:35 +01:00
|
|
|
}
|
|
|
|
if (value.startsWith("macosx") || value.startsWith("osx")) {
|
|
|
|
return "osx";
|
|
|
|
}
|
|
|
|
if (value.startsWith("freebsd")) {
|
|
|
|
return "freebsd";
|
|
|
|
}
|
|
|
|
if (value.startsWith("openbsd")) {
|
|
|
|
return "openbsd";
|
|
|
|
}
|
|
|
|
if (value.startsWith("netbsd")) {
|
|
|
|
return "netbsd";
|
|
|
|
}
|
|
|
|
if (value.startsWith("solaris") || value.startsWith("sunos")) {
|
|
|
|
return "sunos";
|
|
|
|
}
|
|
|
|
if (value.startsWith("windows")) {
|
|
|
|
return "windows";
|
|
|
|
}
|
|
|
|
|
|
|
|
return UNKNOWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static String normalizeArch(String value) {
|
|
|
|
value = normalize(value);
|
|
|
|
if (value.matches("^(x8664|amd64|ia32e|em64t|x64)$")) {
|
|
|
|
return "x86_64";
|
|
|
|
}
|
|
|
|
if (value.matches("^(x8632|x86|i[3-6]86|ia32|x32)$")) {
|
|
|
|
return "x86_32";
|
|
|
|
}
|
|
|
|
if (value.matches("^(ia64|itanium64)$")) {
|
|
|
|
return "itanium_64";
|
|
|
|
}
|
|
|
|
if (value.matches("^(sparc|sparc32)$")) {
|
|
|
|
return "sparc_32";
|
|
|
|
}
|
|
|
|
if (value.matches("^(sparcv9|sparc64)$")) {
|
|
|
|
return "sparc_64";
|
|
|
|
}
|
|
|
|
if (value.matches("^(arm|arm32)$")) {
|
|
|
|
return "arm_32";
|
|
|
|
}
|
|
|
|
if ("aarch64".equals(value)) {
|
|
|
|
return "aarch_64";
|
|
|
|
}
|
|
|
|
if (value.matches("^(ppc|ppc32)$")) {
|
|
|
|
return "ppc_32";
|
|
|
|
}
|
|
|
|
if ("ppc64".equals(value)) {
|
|
|
|
return "ppc_64";
|
|
|
|
}
|
|
|
|
if ("ppc64le".equals(value)) {
|
|
|
|
return "ppcle_64";
|
|
|
|
}
|
|
|
|
if ("s390".equals(value)) {
|
|
|
|
return "s390_32";
|
|
|
|
}
|
|
|
|
if ("s390x".equals(value)) {
|
|
|
|
return "s390_64";
|
|
|
|
}
|
|
|
|
|
|
|
|
return UNKNOWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static String normalize(String value) {
|
|
|
|
return value.toLowerCase(Locale.US).replaceAll("[^a-z0-9]+", "");
|
|
|
|
}
|
2016-08-09 18:14:22 +02:00
|
|
|
|
|
|
|
static void releaseIfNeeded(ReferenceCounted counted) {
|
|
|
|
if (counted.refCnt() > 0) {
|
|
|
|
ReferenceCountUtil.safeRelease(counted);
|
|
|
|
}
|
|
|
|
}
|
2014-05-17 19:26:01 +02:00
|
|
|
}
|