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-2018, Hazelcast, Inc. All Rights Reserved.
*
* 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 com.hazelcast.nio;
import com.hazelcast.internal.usercodedeployment.impl.ClassSource;
import com.hazelcast.spi.annotation.PrivateApi;
import com.hazelcast.util.ConcurrentReferenceHashMap;
import com.hazelcast.util.ExceptionUtil;
import java.lang.ref.WeakReference;
import java.lang.reflect.Constructor;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import static com.hazelcast.util.Preconditions.isNotNull;
import static java.util.Collections.unmodifiableMap;
/**
* Utility class to deal with classloaders.
*/
@PrivateApi
public final class ClassLoaderUtil {
public static final String HAZELCAST_BASE_PACKAGE = "com.hazelcast.";
public static final String HAZELCAST_ARRAY = "[L" + HAZELCAST_BASE_PACKAGE;
private static final boolean CLASS_CACHE_DISABLED = Boolean.getBoolean("hazelcast.compat.classloading.cache.disabled");
private static final Map PRIMITIVE_CLASSES;
private static final int MAX_PRIM_CLASSNAME_LENGTH = 7;
private static final ClassLoaderWeakCache CONSTRUCTOR_CACHE = new ClassLoaderWeakCache();
private static final ClassLoaderWeakCache CLASS_CACHE = new ClassLoaderWeakCache();
static {
final Map primitives = new HashMap(10, 1.0f);
primitives.put("boolean", boolean.class);
primitives.put("byte", byte.class);
primitives.put("int", int.class);
primitives.put("long", long.class);
primitives.put("short", short.class);
primitives.put("float", float.class);
primitives.put("double", double.class);
primitives.put("char", char.class);
primitives.put("void", void.class);
PRIMITIVE_CLASSES = unmodifiableMap(primitives);
}
private ClassLoaderUtil() {
}
/**
* Returns the {@code instance} if not null, otherwise constructs a new instance of the class using
* {@link #newInstance(Class, ClassLoader, String)}.
*
* @param instance the instance of the class, can be null
* @param classLoader the classloader used for class instantiation
* @param className the name of the class being constructed
* @return either the provided {@code instance} or a newly constructed instance of {@code className}
*/
public static T getOrCreate(T instance, ClassLoader classLoader, String className) {
if (instance != null) {
return instance;
} else if (className != null) {
try {
return ClassLoaderUtil.newInstance(classLoader, className);
} catch (Exception e) {
throw ExceptionUtil.rethrow(e);
}
} else {
return null;
}
}
@SuppressWarnings("unchecked")
public static T newInstance(ClassLoader classLoader, final String className) throws Exception {
classLoader = classLoader == null ? ClassLoaderUtil.class.getClassLoader() : classLoader;
Constructor constructor = CONSTRUCTOR_CACHE.get(classLoader, className);
if (constructor != null) {
return constructor.newInstance();
}
Class klass = (Class) loadClass(classLoader, className);
return newInstance(klass, classLoader, className);
}
public static T newInstance(Class klass, ClassLoader classLoader, String className) throws Exception {
final Constructor constructor = klass.getDeclaredConstructor();
if (!constructor.isAccessible()) {
constructor.setAccessible(true);
}
if (!shouldBypassCache(klass)) {
CONSTRUCTOR_CACHE.put(classLoader, className, constructor);
}
return constructor.newInstance();
}
public static Class loadClass(final ClassLoader classLoader, final String className) throws ClassNotFoundException {
isNotNull(className, "className");
if (className.length() <= MAX_PRIM_CLASSNAME_LENGTH && Character.isLowerCase(className.charAt(0))) {
final Class primitiveClass = PRIMITIVE_CLASSES.get(className);
if (primitiveClass != null) {
return primitiveClass;
}
}
ClassLoader theClassLoader = classLoader;
if (theClassLoader == null) {
theClassLoader = Thread.currentThread().getContextClassLoader();
}
// first try to load it through the given classloader
if (theClassLoader != null) {
try {
return tryLoadClass(className, theClassLoader);
} catch (ClassNotFoundException ignore) {
// reset selected classloader and try with others
theClassLoader = null;
}
}
// if failed and this is a Hazelcast class try again with our classloader
if (className.startsWith(HAZELCAST_BASE_PACKAGE) || className.startsWith(HAZELCAST_ARRAY)) {
theClassLoader = ClassLoaderUtil.class.getClassLoader();
}
if (theClassLoader == null) {
theClassLoader = Thread.currentThread().getContextClassLoader();
}
if (theClassLoader != null) {
return tryLoadClass(className, theClassLoader);
}
return Class.forName(className);
}
public static boolean isClassAvailable(final ClassLoader classLoader, final String className) {
try {
Class clazz = loadClass(classLoader, className);
return clazz != null;
} catch (ClassNotFoundException e) {
return false;
}
}
private static Class tryLoadClass(String className, ClassLoader classLoader) throws ClassNotFoundException {
Class clazz;
if (!CLASS_CACHE_DISABLED) {
clazz = CLASS_CACHE.get(classLoader, className);
if (clazz != null) {
return clazz;
}
}
if (className.startsWith("[")) {
clazz = Class.forName(className, false, classLoader);
} else {
clazz = classLoader.loadClass(className);
}
if (!CLASS_CACHE_DISABLED) {
if (!shouldBypassCache(clazz)) {
CLASS_CACHE.put(classLoader, className, clazz);
}
}
return clazz;
}
public static boolean isInternalType(Class type) {
String name = type.getName();
ClassLoader classLoader = ClassLoaderUtil.class.getClassLoader();
return type.getClassLoader() == classLoader && name.startsWith(HAZELCAST_BASE_PACKAGE);
}
/**
* Tries to load the given class.
*
* @param className Name of the class to load
* @return Loaded class
* @throws ClassNotFoundException when the class is not found
*/
public static Class tryLoadClass(String className) throws ClassNotFoundException {
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
return contextClassLoader.loadClass(className);
}
}
/**
* Indicates whether or not the given class exists
*
* @param className Name of the class
* @return {@code true} if the class exists, {@code false} otherwise
*/
public static boolean isClassDefined(String className) {
try {
tryLoadClass(className);
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
/**
* Check whether given class implements an interface with the same name.
* It returns true even when the implemented interface is loaded by a different
* classloader and hence the class is not assignable into it.
*
* An interface is considered as implemented even when either:
*
*
The class directly implements the interface
*
The class implements an interface which extends the original interface
*
One of superclasses directly implements the interface
*
One of superclasses implements an interface which extends the original interface
*
*
* This is useful for logging purposes.
*
* @param clazz class to check whether implements the interface
* @param iface interface to be implemented
* @return true when the class implements the inteface with the same name
*/
public static boolean implementsInterfaceWithSameName(Class clazz, Class iface) {
Class[] interfaces = getAllInterfaces(clazz);
for (Class implementedInterface : interfaces) {
if (implementedInterface.getName().equals(iface.getName())) {
return true;
}
}
return false;
}
public static Class[] getAllInterfaces(Class clazz) {
Collection> interfaces = new HashSet>();
addOwnInterfaces(clazz, interfaces);
addInterfacesOfSuperclasses(clazz, interfaces);
return interfaces.toArray(new Class[0]);
}
private static void addOwnInterfaces(Class clazz, Collection> allInterfaces) {
Class[] interfaces = clazz.getInterfaces();
Collections.addAll(allInterfaces, interfaces);
for (Class cl : interfaces) {
addOwnInterfaces(cl, allInterfaces);
}
}
private static void addInterfacesOfSuperclasses(Class clazz, Collection> interfaces) {
Class superClass = clazz.getSuperclass();
while (superClass != null) {
addOwnInterfaces(superClass, interfaces);
superClass = superClass.getSuperclass();
}
}
private static final class ClassLoaderWeakCache {
private final ConcurrentMap>> cache;
private ClassLoaderWeakCache() {
// let's guess 16 classloaders to not waste too much memory (16 is default concurrency level)
cache = new ConcurrentReferenceHashMap>>(16);
}
private void put(ClassLoader classLoader, String className, V value) {
ClassLoader cl = classLoader == null ? ClassLoaderUtil.class.getClassLoader() : classLoader;
ConcurrentMap> innerCache = cache.get(cl);
if (innerCache == null) {
// let's guess a start of 100 classes per classloader
innerCache = new ConcurrentHashMap>(100);
ConcurrentMap> old = cache.putIfAbsent(cl, innerCache);
if (old != null) {
innerCache = old;
}
}
innerCache.put(className, new WeakReference(value));
}
public V get(ClassLoader classloader, String className) {
isNotNull(className, "className");
ConcurrentMap> innerCache = cache.get(classloader);
if (innerCache == null) {
return null;
}
WeakReference reference = innerCache.get(className);
V value = reference == null ? null : reference.get();
if (reference != null && value == null) {
innerCache.remove(className);
}
return value;
}
}
private static boolean shouldBypassCache(Class clazz) {
// dynamically loaded class should not be cached here, as they are already
// cached in the DistributedLoadingService (when cache is enabled)
return (clazz.getClassLoader() instanceof ClassSource);
}
}