de.alpharogroup.lang.ClassExtensions Maven / Gradle / Ivy
/**
* The MIT License
*
* Copyright (C) 2015 Asterios Raptis
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package de.alpharogroup.lang;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import de.alpharogroup.file.FileExtension;
import de.alpharogroup.file.FilenameExtensions;
import de.alpharogroup.file.filter.ClassFileFilter;
import de.alpharogroup.string.StringExtensions;
import lombok.experimental.ExtensionMethod;
/**
* The class ClassExtensions provides extension methods for the class {@link Class}.
*/
@ExtensionMethod(StringExtensions.class)
public final class ClassExtensions
{
/** The Constant LOGGER. */
protected static final Logger LOGGER = Logger.getLogger(ClassExtensions.class);
/**
* Equal the given class objects by they qualified class names.
*
* @param oneClass
* one class for equation by the qualified class name.
* @param otherClass
* the other class for equation by the qualified class name.
* @return s true if the qualified class names are equal otherwise false.
*/
public static boolean equalsByClassName(final Class> oneClass, final Class> otherClass)
{
final String oneNormalizedClassName = ClassExtensions
.normalizeQualifiedClassName(oneClass.getName());
final String otherNormalizedClassName = ClassExtensions
.normalizeQualifiedClassName(otherClass.getName());
if (otherNormalizedClassName.equals(oneNormalizedClassName))
{
return true;
}
return false;
}
/**
* Look up the class in the "current" ClassLoader.
*
* @param className
* The class name to load
* @return the class
* @throws ClassNotFoundException
* is thrown if the Class was not found or could not be located.
*/
public static Class> forName(final String className) throws ClassNotFoundException
{
Class> clazz = null;
try
{
clazz = Class.forName(className);
}
catch (final Throwable throwable)
{
clazz = Class.forName(className, true, getClassLoader());
if (clazz == null)
{
throw throwable;
}
}
return clazz;
}
/**
* Gets the parent base class from the given child class.
*
* @param childClass
* the child class
* @return the parent base class from the given child class.
*/
public static Class> getBaseClass(final Class> childClass)
{
if (childClass == null)
{
return childClass;
}
Class> superClass = childClass.getSuperclass();
while ((superClass != null) && !superClass.getSuperclass().equals(Object.class))
{
superClass = superClass.getSuperclass();
}
if (superClass == null)
{
return childClass;
}
return superClass;
}
/**
* Gets the current class loader.
*
* @return 's the current class loader
*/
public static ClassLoader getClassLoader()
{
return ClassExtensions.getClassLoader(null);
}
/**
* Gets the ClassLoader from the given object.
*
* @param obj
* The object.
* @return the ClassLoader from the given object.
*/
public static ClassLoader getClassLoader(final Object obj)
{
ClassLoader classLoader = null;
if (null != obj)
{
if (isDerivate(Thread.currentThread().getContextClassLoader(),
obj.getClass().getClassLoader()))
{
classLoader = obj.getClass().getClassLoader();
}
else
{
classLoader = Thread.currentThread().getContextClassLoader();
}
if (isDerivate(classLoader, ClassLoader.getSystemClassLoader()))
{
classLoader = ClassLoader.getSystemClassLoader();
}
}
else
{
if (isDerivate(Thread.currentThread().getContextClassLoader(),
ClassLoader.getSystemClassLoader()))
{
classLoader = ClassLoader.getSystemClassLoader();
}
else
{
classLoader = Thread.currentThread().getContextClassLoader();
}
}
return classLoader;
}
/**
* Gets the classname and concats the suffix ".class" from the class.
*
* @param clazz
* The class.
* @return The classname and concats the suffix ".class".
*/
public static String getClassnameWithSuffix(final Class> clazz)
{
String className = clazz.getName();
className = className.substring(className.lastIndexOf('.') + 1)
+ FileExtension.CLASS.getExtension();
return className;
}
/**
* Gets the classname and concats the suffix ".class" from the object.
*
* @param obj
* The object.
* @return The classname and concats the suffix ".class".
*/
public static String getClassnameWithSuffix(final Object obj)
{
return getClassnameWithSuffix(obj.getClass());
}
/**
* Gets the {@link ClassType} from the given class.
*
* @param clazz
* The class.
* @return the {@link ClassType} from the given class.
*/
public static ClassType getClassType(final Class> clazz)
{
if (clazz.isArray())
{
return ClassType.ARRAY;
}
if (isCollection(clazz))
{
return ClassType.COLLECTION;
}
if (isMap(clazz))
{
return ClassType.MAP;
}
if (clazz.isLocalClass())
{
return ClassType.LOCAL;
}
if (clazz.isMemberClass())
{
return ClassType.MEMBER;
}
if (clazz.isPrimitive())
{
return ClassType.PRIMITIVE;
}
if (clazz.isAnnotation())
{
return ClassType.ANNOTATION;
}
if (clazz.isEnum())
{
return ClassType.ENUM;
}
if (clazz.isInterface())
{
return ClassType.INTERFACE;
}
if (clazz.isSynthetic())
{
return ClassType.SYNTHETIC;
}
if (clazz.isAnonymousClass())
{
return ClassType.ANONYMOUS;
}
return ClassType.DEFAULT;
}
/**
* Gets the directories from the given path.
*
* @param path
* the path
* @param isPackage
* If the Flag is true than the given path is a package.
* @return the directories from resources
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static List getDirectoriesFromResources(String path, final boolean isPackage)
throws IOException
{
if (isPackage)
{
path = path.replace('.', '/');
}
final List resources = ClassExtensions.getResources(path);
final List dirs = new ArrayList<>();
for (final URL resource : resources)
{
dirs.add(new File(URLDecoder.decode(resource.getFile(), "UTF-8")));
}
return dirs;
}
/**
* If the given class is in a JAR, WAR or EAR file than the manifest url as String is returned.
*
* @param clazz
* The class.
* @return the manifest url as String if the given class is in a JAR, WAR or EAR file.
*/
public static String getManifestUrl(final Class> clazz)
{
String manifestUrl = null;
final String path = ClassExtensions.getPath(clazz);
final URL classUrl = ClassExtensions.getResource(path);
if (classUrl != null)
{
final String classUrlString = classUrl.toString();
if ((classUrlString.startsWith("jar:") && (classUrlString.indexOf(path) > 0))
|| (classUrlString.startsWith("war:") && (classUrlString.indexOf(path) > 0))
|| (classUrlString.startsWith("ear:") && (classUrlString.indexOf(path) > 0))
|| (classUrlString.startsWith("file:") && (classUrlString.indexOf(path) > 0)))
{
manifestUrl = classUrlString.replace(path, "/META-INF/MANIFEST.MF");
}
}
return manifestUrl;
}
/**
* If the given class is in a JAR file than the jar path as String will be returned.
*
* @param clazz
* The class.
* @return the jar path as String if the given class is in a JAR file.
*/
public static String getJarPath(final Class> clazz)
{
String jarPath = null;
final String jarPathPrefix = "jar:";
final String jarPathFilePrefix = jarPathPrefix + "file:";
final String path = ClassExtensions.getPath(clazz);
final URL classUrl = ClassExtensions.getResource(path);
if (classUrl != null)
{
final String classUrlString = classUrl.toString();
if ((classUrlString.startsWith(jarPathPrefix) && (classUrlString.indexOf(path) > 0)))
{
jarPath = classUrlString.replace("!" + path, "");
if (jarPath.startsWith(jarPathFilePrefix))
{
final int beginIndex = jarPathFilePrefix.length();
jarPath = jarPath.substring(beginIndex, jarPath.length());
}
}
}
return jarPath;
}
/**
* Returns the name of the given class or null if the given class is null.
*
* @param clazz
* The class.
*
* @return The name of the given class.
*/
public static String getName(final Class> clazz)
{
return getName(clazz, false);
}
/**
* Returns the name of the given class or null if the given class is null. If the given flag
* 'simple' is true the simple name (without the package) will be returned.
*
* @param clazz
* The class
* @param simple
* The flag if the simple name should be returned.
*
* @return The name of the given class or if the given flag 'simple' is true the simple name
* (without the package) will be returned.
*/
public static String getName(Class> clazz, final boolean simple)
{
String name = null;
if (clazz != null)
{
while (clazz.isAnonymousClass())
{
clazz = clazz.getSuperclass();
}
if (simple)
{
name = clazz.getSimpleName();
}
else
{
name = clazz.getName();
}
}
return name;
}
/**
* Gets the path from the given class. For instance /java/lang/Object.class if the given class
* is from {@code Object}
*
* @param clazz
* The class.
* @return the path from the given class.
*/
public static String getPath(final Class> clazz)
{
final String packagePath = PackageExtensions.getPackagePath(clazz);
final String className = ClassExtensions.getSimpleName(clazz);
final StringBuilder sb = new StringBuilder().append("/").append(packagePath)
.append(className).append(FileExtension.CLASS.getExtension());
final String path = sb.toString();
return path;
}
/**
* Finds the absolute path from the object.
*
* @param obj
* The object.
* @return The absolute path from the object.
*/
public static String getPathFromObject(final Object obj)
{
if (obj == null)
{
return null;
}
final String pathFromObject = obj.getClass()
.getResource(ClassExtensions.getClassnameWithSuffix(obj)).getPath();
return pathFromObject;
}
/**
* Gives the url from the path back.
*
* @param clazz
* The class-object.
* @param path
* The path.
* @return 's the url from the path.
*/
public static URL getResource(final Class> clazz, final String path)
{
URL url = clazz.getResource(path);
if (url == null)
{
url = ClassExtensions.getClassLoader().getResource(path);
}
return url;
}
/**
* Gives the url from the path back.
*
* @param clazz
* The class-object.
* @return 's the url from the path.
*/
public static URL getResource(final Class> clazz)
{
final String path = ClassExtensions.getPath(clazz);
URL url = clazz.getResource(path);
if (url == null)
{
url = ClassExtensions.getClassLoader().getResource(path);
}
return url;
}
/**
* Gives the URL from the resource. Wrapes the Class.getResource(String)-method.
*
* @param name
* The name from the resource.
* @return The resource or null if the resource does not exists.
*/
public static URL getResource(final String name)
{
String path = name;
if (name.startsWith("/"))
{
path = name.substring(1, name.length());
}
final URL url = ClassExtensions.getClassLoader().getResource(path);
return url;
}
/**
* Gives the URL from the resource. Wrapes the Class.getResource(String)-method.
*
* @param
* the generic type
* @param name
* The name from the resource.
* @param obj
* The Object.
* @return The resource or null if the resource does not exists.
*/
public static URL getResource(final String name, final T obj)
{
final Class> clazz = obj.getClass();
URL url = clazz.getResource(name);
if (url == null)
{
url = getResource(clazz, name);
}
return url;
}
/**
* Gives the resource as a file Object.
*
* @param name
* The name from the file.
* @return The file or null if the file does not exists.
* @throws URISyntaxException
* occurs by creation of the file with an uri.
*/
public static File getResourceAsFile(final String name) throws URISyntaxException
{
File file = null;
URL url = getResource(name);
if (null == url)
{
url = ClassExtensions.getClassLoader().getResource(name);
if (null != url)
{
file = new File(url.toURI());
}
}
else
{
file = new File(url.toURI());
}
return file;
}
/**
* Gives the resource as a file Object.
*
* @param name
* The name from the file.
* @param obj
* The Object.
* @return The file or null if the file does not exists.
* @throws URISyntaxException
* occurs by creation of the file with an uri.
*/
public static File getResourceAsFile(final String name, final Object obj)
throws URISyntaxException
{
File file = null;
URL url = getResource(name, obj);
if (null == url)
{
url = ClassExtensions.getClassLoader(obj).getResource(name);
if (null != url)
{
file = new File(url.toURI());
}
}
else
{
file = new File(url.toURI());
}
return file;
}
/**
* This method call the getResourceAsStream from the ClassLoader. You can use this method to
* read files from jar-files.
*
* @param clazz
* the clazz
* @param uri
* The uri as String.
* @return The InputStream from the uri.
*/
public static InputStream getResourceAsStream(final Class> clazz, final String uri)
{
InputStream is = clazz.getResourceAsStream(uri);
if (null == is)
{
is = ClassExtensions.getClassLoader().getResourceAsStream(uri);
}
return is;
}
/**
* Gives the Inputstream from the resource. Wrapes the Class.getResourceAsStream(String)-method.
*
* @param name
* The name from the resource.
* @return The resource or null if the resource does not exists.
*/
public static InputStream getResourceAsStream(final String name)
{
final ClassLoader loader = ClassExtensions.getClassLoader();
final InputStream inputStream = loader.getResourceAsStream(name);
return inputStream;
}
/**
* Gives the Inputstream from the resource. Wrapes the Class.getResourceAsStream(String)-method.
*
* @param name
* The name from the resource.
* @param obj
* The Object.
* @return The resource or null if the resource does not exists.
*/
public static InputStream getResourceAsStream(final String name, final Object obj)
{
InputStream inputStream = obj.getClass().getResourceAsStream(name);
if (null == inputStream)
{
final ClassLoader loader = ClassExtensions.getClassLoader(obj);
inputStream = loader.getResourceAsStream(name);
}
return inputStream;
}
/**
* Gets a list with urls from the given path for all resources.
*
* @param path
* The base path.
* @return The resources.
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static List getResources(final String path) throws IOException
{
final ClassLoader classLoader = ClassExtensions.getClassLoader();
final List list = Collections.list(classLoader.getResources(path));
return list;
}
/**
* Returns the simple name of the given class or null if the given class is null.
*
* @param clazz
* The class.
*
* @return The simple name of the given class.
*/
public static String getSimpleName(final Class> clazz)
{
return getName(clazz, true);
}
/**
* Returns the URL from the given class.
*
* @param clazz
* The class.
* @return the URL from the given class.
*/
public static URL getURL(final Class> clazz)
{
return ClassExtensions.getResource(ClassExtensions.getPath(clazz));
}
/**
* Checks if the given class is assignable from {@link Collection}.
*
* @param clazz
* The class.
* @return true, if the given class is assignable from {@link Collection} otherwise false.
*/
public static boolean isCollection(final Class> clazz)
{
return Collection.class.isAssignableFrom(clazz);
}
/**
* Compares the two given ClassLoader objects and returns true if compare is a derivate of
* source.
*
* @param source
* the source
* @param compare
* the compare
* @return true, if compare is a derivate of source.
*/
public static boolean isDerivate(final ClassLoader source, ClassLoader compare)
{
if (source == compare)
{
return true;
}
if (compare == null)
{
return false;
}
if (source == null)
{
return true;
}
while (null != compare)
{
compare = compare.getParent();
if (source == compare)
{
return true;
}
}
return false;
}
/**
* Checks if the given class is assignable from {@link Map}.
*
* @param clazz
* The class.
* @return true, if the given class is assignable from {@link Map} otherwise false.
*/
public static boolean isMap(final Class> clazz)
{
return Map.class.isAssignableFrom(clazz);
}
/**
* Normalizes the given full qualified class name. This can be an entry from a jar file for
* instance.
*
* @param qualifiedClassname
* the full qualified class name to normalize.
* @return The normalized class name.
*/
public static String normalizeQualifiedClassName(final String qualifiedClassname)
{
return normalizeSimpleClassName(qualifiedClassname).replaceAll("/", ".");
}
/**
* Normalizes the given simple class name.
*
* @param className
* the class name to normalize.
* @return The normalized class name.
*/
public static String normalizeSimpleClassName(final String className)
{
String result = className;
if (className.endsWith(FileExtension.CLASS.getExtension()))
{
result = className.replaceLast(FileExtension.CLASS.getExtension(), "");
}
final int lastIndexOf$ = result.lastIndexOf("$");
if (lastIndexOf$ != -1)
{
final String prefix = result.substring(0, lastIndexOf$);
final String compilerClassName = result.substring(lastIndexOf$ + 1, result.length());
if (StringUtils.isNumeric(compilerClassName))
{
return prefix;
}
}
return result;
}
/**
* Scan for classes in the given directory.
*
* @param directory
* the directory
* @param packagePath
* the package path
* @return the list
* @throws ClassNotFoundException
* the class not found exception
*/
public static Set> scanClassesFromPackage(final File directory,
final String packagePath) throws ClassNotFoundException
{
return scanClassesFromPackage(directory, packagePath, false);
}
/**
* Scan recursive for classes in the given directory.
*
* @param directory
* the directory
* @param packagePath
* the package path
* @param recursive
* the recursive
* @return the list
* @throws ClassNotFoundException
* is thrown if a class in the given path cannot be located.
*/
public static Set> scanClassesFromPackage(final File directory,
final String packagePath, final boolean recursive) throws ClassNotFoundException
{
final Set> foundClasses = new LinkedHashSet<>();
if (!directory.exists())
{
return foundClasses;
}
// define the include filefilter for class files...
final FileFilter includeFileFilter = new ClassFileFilter();
final File[] files = directory.listFiles(includeFileFilter);
for (final File file : files)
{
String qualifiedClassname = null;
if (file.isDirectory() && recursive)
{
qualifiedClassname = packagePath + "." + file.getName();
foundClasses.addAll(scanClassesFromPackage(file, qualifiedClassname, recursive));
}
else
{
if (!file.isDirectory())
{
final String filename = FilenameExtensions.getFilenameWithoutExtension(file);
qualifiedClassname = packagePath + '.' + filename;
foundClasses.add(forName(qualifiedClassname));
}
}
}
return foundClasses;
}
/**
* Scan class names from the given package name.
*
* @param packageName
* the package name
* @return the Set with all class found in the given package name.
* @throws IOException
* Signals that an I/O exception has occurred.
* @throws ClassNotFoundException
* is thrown if a class in the given path cannot be located.
*/
public static Set> scanClassNames(final String packageName)
throws IOException, ClassNotFoundException
{
return scanClassNames(packageName, false);
}
/**
* Scan class names from the given package name.
*
* @param packageName
* the package name
* @param recursive
* the recursive flag
* @return the Set with all class found in the given package name.
* @throws IOException
* Signals that an I/O exception has occurred.
* @throws ClassNotFoundException
* is thrown if a class in the given path cannot be located.
*/
public static Set> scanClassNames(final String packageName, final boolean recursive)
throws IOException, ClassNotFoundException
{
final Set> foundClasses = new LinkedHashSet<>();
final Set qualifiedClassnames = PackageExtensions.scanClassNames(packageName,
recursive, true);
for (final String qualifiedClassname : qualifiedClassnames)
{
foundClasses.add(forName(qualifiedClassname));
}
return foundClasses;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy