[#2353] Use a privileged block to get ClassLoader and System property if needed
Motivation: When using System.getProperty(...) and various methods to get a ClassLoader it will fail when a SecurityManager is in place. Modifications: Use a priveled block if needed. This work is based in the PR #2353 done by @anilsaldhana . Result: Code works also when SecurityManager is present
This commit is contained in:
parent
69826637a8
commit
31a36e09ad
@ -90,12 +90,12 @@ public final class ClassResolvers {
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
final ClassLoader contextClassLoader = PlatformDependent.getContextClassLoader();
|
||||
if (contextClassLoader != null) {
|
||||
return contextClassLoader;
|
||||
}
|
||||
|
||||
return ClassResolvers.class.getClassLoader();
|
||||
return PlatformDependent.getClassLoader(ClassResolvers.class);
|
||||
}
|
||||
|
||||
private ClassResolvers() {
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
package io.netty.util;
|
||||
|
||||
import io.netty.util.internal.PlatformDependent;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.text.ParseException;
|
||||
@ -61,7 +63,7 @@ public final class Version {
|
||||
*/
|
||||
public static Map<String, Version> identify(ClassLoader classLoader) {
|
||||
if (classLoader == null) {
|
||||
classLoader = Thread.currentThread().getContextClassLoader();
|
||||
classLoader = PlatformDependent.getContextClassLoader();
|
||||
}
|
||||
|
||||
// Collect all properties.
|
||||
|
@ -51,9 +51,9 @@ public final class JavassistTypeParameterMatcherGenerator {
|
||||
}
|
||||
|
||||
public static TypeParameterMatcher generate(Class<?> type) {
|
||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
ClassLoader classLoader = PlatformDependent.getContextClassLoader();
|
||||
if (classLoader == null) {
|
||||
classLoader = ClassLoader.getSystemClassLoader();
|
||||
classLoader = PlatformDependent.getSystemClassLoader();
|
||||
}
|
||||
return generate(type, classLoader);
|
||||
}
|
||||
|
@ -387,10 +387,31 @@ public final class PlatformDependent {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link ClassLoader} for the given {@link Class}.
|
||||
*/
|
||||
public static ClassLoader getClassLoader(final Class<?> clazz) {
|
||||
return PlatformDependent0.getClassLoader(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the context {@link ClassLoader} for the current {@link Thread}.
|
||||
*/
|
||||
public static ClassLoader getContextClassLoader() {
|
||||
return PlatformDependent0.getContextClassLoader();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the system {@link ClassLoader}.
|
||||
*/
|
||||
public static ClassLoader getSystemClassLoader() {
|
||||
return PlatformDependent0.getSystemClassLoader();
|
||||
}
|
||||
|
||||
private static boolean isAndroid0() {
|
||||
boolean android;
|
||||
try {
|
||||
Class.forName("android.app.Application", false, ClassLoader.getSystemClassLoader());
|
||||
Class.forName("android.app.Application", false, getSystemClassLoader());
|
||||
android = true;
|
||||
} catch (Exception e) {
|
||||
// Failed to load the class uniquely available in Android.
|
||||
@ -517,7 +538,7 @@ public final class PlatformDependent {
|
||||
}
|
||||
|
||||
try {
|
||||
Class.forName("java.time.Clock", false, Object.class.getClassLoader());
|
||||
Class.forName("java.time.Clock", false, getClassLoader(Object.class));
|
||||
javaVersion = 8;
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
@ -525,7 +546,7 @@ public final class PlatformDependent {
|
||||
}
|
||||
|
||||
try {
|
||||
Class.forName("java.util.concurrent.LinkedTransferQueue", false, BlockingQueue.class.getClassLoader());
|
||||
Class.forName("java.util.concurrent.LinkedTransferQueue", false, getClassLoader(BlockingQueue.class));
|
||||
javaVersion = 7;
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
@ -591,7 +612,7 @@ public final class PlatformDependent {
|
||||
long maxDirectMemory = 0;
|
||||
try {
|
||||
// Try to get from sun.misc.VM.maxDirectMemory() which should be most accurate.
|
||||
Class<?> vmClass = Class.forName("sun.misc.VM", true, ClassLoader.getSystemClassLoader());
|
||||
Class<?> vmClass = Class.forName("sun.misc.VM", true, getSystemClassLoader());
|
||||
Method m = vmClass.getDeclaredMethod("maxDirectMemory");
|
||||
maxDirectMemory = ((Number) m.invoke(null)).longValue();
|
||||
} catch (Throwable t) {
|
||||
@ -606,9 +627,9 @@ public final class PlatformDependent {
|
||||
// Now try to get the JVM option (-XX:MaxDirectMemorySize) and parse it.
|
||||
// Note that we are using reflection because Android doesn't have these classes.
|
||||
Class<?> mgmtFactoryClass = Class.forName(
|
||||
"java.lang.management.ManagementFactory", true, ClassLoader.getSystemClassLoader());
|
||||
"java.lang.management.ManagementFactory", true, getSystemClassLoader());
|
||||
Class<?> runtimeClass = Class.forName(
|
||||
"java.lang.management.RuntimeMXBean", true, ClassLoader.getSystemClassLoader());
|
||||
"java.lang.management.RuntimeMXBean", true, getSystemClassLoader());
|
||||
|
||||
Object runtime = mgmtFactoryClass.getDeclaredMethod("getRuntimeMXBean").invoke(null);
|
||||
|
||||
@ -662,7 +683,7 @@ public final class PlatformDependent {
|
||||
}
|
||||
|
||||
try {
|
||||
JavassistTypeParameterMatcherGenerator.generate(Object.class, PlatformDependent.class.getClassLoader());
|
||||
JavassistTypeParameterMatcherGenerator.generate(Object.class, getClassLoader(PlatformDependent.class));
|
||||
logger.debug("Javassist: available");
|
||||
return true;
|
||||
} catch (Throwable t) {
|
||||
|
@ -26,6 +26,8 @@ import java.lang.reflect.Method;
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
|
||||
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
|
||||
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
|
||||
@ -50,7 +52,7 @@ final class PlatformDependent0 {
|
||||
static {
|
||||
boolean directBufferFreeable = false;
|
||||
try {
|
||||
Class<?> cls = Class.forName("sun.nio.ch.DirectBuffer", false, PlatformDependent0.class.getClassLoader());
|
||||
Class<?> cls = Class.forName("sun.nio.ch.DirectBuffer", false, getClassLoader(PlatformDependent0.class));
|
||||
Method method = cls.getMethod("cleaner");
|
||||
if ("sun.misc.Cleaner".equals(method.getReturnType().getName())) {
|
||||
directBufferFreeable = true;
|
||||
@ -328,6 +330,45 @@ final class PlatformDependent0 {
|
||||
return new UnsafeAtomicLongFieldUpdater<T>(UNSAFE, tclass, fieldName);
|
||||
}
|
||||
|
||||
static ClassLoader getClassLoader(final Class<?> clazz) {
|
||||
if (System.getSecurityManager() == null) {
|
||||
return clazz.getClassLoader();
|
||||
} else {
|
||||
return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
|
||||
@Override
|
||||
public ClassLoader run() {
|
||||
return clazz.getClassLoader();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static ClassLoader getContextClassLoader() {
|
||||
if (System.getSecurityManager() == null) {
|
||||
return Thread.currentThread().getContextClassLoader();
|
||||
} else {
|
||||
return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
|
||||
@Override
|
||||
public ClassLoader run() {
|
||||
return Thread.currentThread().getContextClassLoader();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static ClassLoader getSystemClassLoader() {
|
||||
if (System.getSecurityManager() == null) {
|
||||
return ClassLoader.getSystemClassLoader();
|
||||
} else {
|
||||
return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
|
||||
@Override
|
||||
public ClassLoader run() {
|
||||
return ClassLoader.getSystemClassLoader();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private PlatformDependent0() {
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,8 @@ package io.netty.util.internal;
|
||||
import io.netty.util.internal.logging.InternalLogger;
|
||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
@ -64,7 +66,7 @@ public final class SystemPropertyUtil {
|
||||
* {@code def} if there's no such property or if an access to the
|
||||
* specified property is not allowed.
|
||||
*/
|
||||
public static String get(String key, String def) {
|
||||
public static String get(final String key, String def) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException("key");
|
||||
}
|
||||
@ -74,7 +76,16 @@ public final class SystemPropertyUtil {
|
||||
|
||||
String value = null;
|
||||
try {
|
||||
value = System.getProperty(key);
|
||||
if (System.getSecurityManager() == null) {
|
||||
value = System.getProperty(key);
|
||||
} else {
|
||||
value = AccessController.doPrivileged(new PrivilegedAction<String>() {
|
||||
@Override
|
||||
public String run() {
|
||||
return System.getProperty(key);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (!loggedException) {
|
||||
log("Unable to retrieve a system property '" + key + "'; default values will be used.", e);
|
||||
|
@ -34,6 +34,7 @@ import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
import io.netty.handler.codec.http.LastHttpContent;
|
||||
import io.netty.handler.stream.ChunkedFile;
|
||||
import io.netty.util.CharsetUtil;
|
||||
import io.netty.util.internal.SystemPropertyUtil;
|
||||
|
||||
import javax.activation.MimetypesFileTypeMap;
|
||||
import java.io.File;
|
||||
@ -264,7 +265,7 @@ public class HttpStaticFileServerHandler extends SimpleChannelInboundHandler<Ful
|
||||
}
|
||||
|
||||
// Convert to absolute path.
|
||||
return System.getProperty("user.dir") + File.separator + uri;
|
||||
return SystemPropertyUtil.get("user.dir") + File.separator + uri;
|
||||
}
|
||||
|
||||
private static final Pattern ALLOWED_FILE_NAME = Pattern.compile("[A-Za-z0-9][-_A-Za-z0-9\\.]*");
|
||||
|
@ -20,6 +20,7 @@ import io.netty.channel.Channel;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import io.netty.util.internal.SystemPropertyUtil;
|
||||
|
||||
/**
|
||||
* A HTTP server which serves Web Socket requests at:
|
||||
@ -74,13 +75,13 @@ public class WebSocketSslServer {
|
||||
port = 8443;
|
||||
}
|
||||
|
||||
String keyStoreFilePath = System.getProperty("keystore.file.path");
|
||||
String keyStoreFilePath = SystemPropertyUtil.get("keystore.file.path");
|
||||
if (keyStoreFilePath == null || keyStoreFilePath.isEmpty()) {
|
||||
System.out.println("ERROR: System property keystore.file.path not set. Exiting now!");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
String keyStoreFilePassword = System.getProperty("keystore.file.password");
|
||||
String keyStoreFilePassword = SystemPropertyUtil.get("keystore.file.password");
|
||||
if (keyStoreFilePassword == null || keyStoreFilePassword.isEmpty()) {
|
||||
System.out.println("ERROR: System property keystore.file.password not set. Exiting now!");
|
||||
System.exit(1);
|
||||
|
@ -15,6 +15,8 @@
|
||||
*/
|
||||
package io.netty.example.http.websocketx.sslserver;
|
||||
|
||||
import io.netty.util.internal.SystemPropertyUtil;
|
||||
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.io.FileInputStream;
|
||||
@ -56,14 +58,14 @@ public final class WebSocketSslServerSslContext {
|
||||
SSLContext serverContext = null;
|
||||
try {
|
||||
// Key store (Server side certificate)
|
||||
String algorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm");
|
||||
String algorithm = SystemPropertyUtil.get("ssl.KeyManagerFactory.algorithm");
|
||||
if (algorithm == null) {
|
||||
algorithm = "SunX509";
|
||||
}
|
||||
|
||||
try {
|
||||
String keyStoreFilePath = System.getProperty("keystore.file.path");
|
||||
String keyStoreFilePassword = System.getProperty("keystore.file.password");
|
||||
String keyStoreFilePath = SystemPropertyUtil.get("keystore.file.path");
|
||||
String keyStoreFilePassword = SystemPropertyUtil.get("keystore.file.password");
|
||||
|
||||
KeyStore ks = KeyStore.getInstance("JKS");
|
||||
FileInputStream fin = new FileInputStream(keyStoreFilePath);
|
||||
|
@ -16,6 +16,7 @@
|
||||
package io.netty.example.securechat;
|
||||
|
||||
import io.netty.handler.ssl.SslHandler;
|
||||
import io.netty.util.internal.SystemPropertyUtil;
|
||||
|
||||
import java.security.KeyStore;
|
||||
import java.security.SecureRandom;
|
||||
@ -57,7 +58,7 @@ public final class SecureChatSslContextFactory {
|
||||
private static final SSLContext CLIENT_CONTEXT;
|
||||
|
||||
static {
|
||||
String algorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm");
|
||||
String algorithm = SystemPropertyUtil.get("ssl.KeyManagerFactory.algorithm");
|
||||
if (algorithm == null) {
|
||||
algorithm = "SunX509";
|
||||
}
|
||||
|
@ -625,7 +625,7 @@ public class SslHandler extends ByteToMessageDecoder {
|
||||
// No match by now.. Try to load the class via classloader and inspect it.
|
||||
// This is mainly done as other JDK implementations may differ in name of
|
||||
// the impl.
|
||||
Class<?> clazz = getClass().getClassLoader().loadClass(classname);
|
||||
Class<?> clazz = PlatformDependent.getClassLoader(getClass()).loadClass(classname);
|
||||
|
||||
if (SocketChannel.class.isAssignableFrom(clazz)
|
||||
|| DatagramChannel.class.isAssignableFrom(clazz)) {
|
||||
|
@ -19,6 +19,8 @@ package io.netty.channel.epoll;
|
||||
import io.netty.channel.DefaultFileRegion;
|
||||
import io.netty.channel.epoll.EpollChannelOutboundBuffer.AddressEntry;
|
||||
import io.netty.util.internal.NativeLibraryLoader;
|
||||
import io.netty.util.internal.PlatformDependent;
|
||||
import io.netty.util.internal.SystemPropertyUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Inet6Address;
|
||||
@ -37,11 +39,11 @@ final class Native {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0xff, (byte) 0xff };
|
||||
|
||||
static {
|
||||
String name = System.getProperty("os.name").toLowerCase(Locale.UK).trim();
|
||||
String name = SystemPropertyUtil.get("os.name").toLowerCase(Locale.UK).trim();
|
||||
if (!name.startsWith("linux")) {
|
||||
throw new IllegalStateException("Only supported on Linux");
|
||||
}
|
||||
NativeLibraryLoader.load("netty-transport-native-epoll", Native.class.getClassLoader());
|
||||
NativeLibraryLoader.load("netty-transport-native-epoll", PlatformDependent.getClassLoader(Native.class));
|
||||
}
|
||||
|
||||
// EventLoop operations and constants
|
||||
|
@ -302,7 +302,7 @@ final class DefaultChannelId implements ChannelId {
|
||||
}
|
||||
|
||||
private static int defaultProcessId() {
|
||||
final ClassLoader loader = ClassLoader.getSystemClassLoader();
|
||||
final ClassLoader loader = PlatformDependent.getSystemClassLoader();
|
||||
String value;
|
||||
try {
|
||||
// Invoke java.lang.management.ManagementFactory.getRuntimeMXBean().getName()
|
||||
|
@ -67,7 +67,7 @@ public final class NioEventLoop extends SingleThreadEventLoop {
|
||||
static {
|
||||
String key = "sun.nio.ch.bugLevel";
|
||||
try {
|
||||
String buglevel = System.getProperty(key);
|
||||
String buglevel = SystemPropertyUtil.get(key);
|
||||
if (buglevel == null) {
|
||||
System.setProperty(key, "");
|
||||
}
|
||||
@ -136,7 +136,7 @@ public final class NioEventLoop extends SingleThreadEventLoop {
|
||||
SelectedSelectionKeySet selectedKeySet = new SelectedSelectionKeySet();
|
||||
|
||||
Class<?> selectorImplClass =
|
||||
Class.forName("sun.nio.ch.SelectorImpl", false, ClassLoader.getSystemClassLoader());
|
||||
Class.forName("sun.nio.ch.SelectorImpl", false, PlatformDependent.getSystemClassLoader());
|
||||
|
||||
// Ensure the current selector implementation is what we can instrument.
|
||||
if (!selectorImplClass.isAssignableFrom(selector.getClass())) {
|
||||
|
@ -40,7 +40,7 @@ class NioDatagramChannelConfig extends DefaultDatagramChannelConfig {
|
||||
private static final Method SET_OPTION;
|
||||
|
||||
static {
|
||||
ClassLoader classLoader = DatagramChannel.class.getClassLoader();
|
||||
ClassLoader classLoader = PlatformDependent.getClassLoader(DatagramChannel.class);
|
||||
Class<?> socketOptionType = null;
|
||||
try {
|
||||
socketOptionType = Class.forName("java.net.SocketOption", true, classLoader);
|
||||
|
Loading…
Reference in New Issue
Block a user