Java tutorial
/* * Copyright 2013 Lyor Goldstein * * 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 org.apache.commons.lang3; import java.io.File; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.security.CodeSource; import java.security.ProtectionDomain; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.apache.commons.io.ExtendedFileUtils; import org.apache.commons.net.util.URLUtils; /** * @author lgoldstein */ public class ExtendedClassUtils extends ClassUtils { public static final List<Class<?>> EXTRA_BASE_TYPES = Collections .unmodifiableList(Arrays.asList((Class<?>) Enum.class, (Class<?>) String.class)); public ExtendedClassUtils() { super(); } /** * Compares 2 {@link Class}-es using their <U>full</U> name * @see Class#getName() */ public static final Comparator<Class<?>> BY_FULL_NAME_COMPARATOR = new Comparator<Class<?>>() { @Override public int compare(Class<?> o1, Class<?> o2) { if (o1 == o2) { return 0; } String n1 = (o1 == null) ? null : o1.getName(); String n2 = (o2 == null) ? null : o2.getName(); return ExtendedStringUtils.safeCompare(n1, n2); } }; /** * @param type The type to check - ignored if <code>null</code> * @return <code>true</code> if the given type is either a primitive, * its wrapper or one of the types in the {@link #EXTRA_BASE_TYPES} * @see ClassUtils#isPrimitiveOrWrapper(Class) */ public static final boolean isBaseType(Class<?> type) { if (type == null) { return false; } if (isPrimitiveOrWrapper(type)) { return true; } for (Class<?> baseType : EXTRA_BASE_TYPES) { if (baseType.isAssignableFrom(type)) { return true; } } return false; } /** * @param clazz A {@link Class} object * @return A {@link File} of the location of the class bytes container * - e.g., the root folder, the containing JAR, etc.. Returns * <code>null</code> if location could not be resolved * @throws IllegalArgumentException If location is not a valid * {@link File} location * @see #getClassContainerLocationURI(Class) * @see ExtendedFileUtils#asFile(URI) */ public static final File getClassContainerLocationFile(Class<?> clazz) throws IllegalArgumentException { try { URI uri = getClassContainerLocationURI(clazz); return ExtendedFileUtils.asFile(uri); } catch (URISyntaxException e) { throw new IllegalArgumentException(e.getClass().getSimpleName() + ": " + e.getMessage(), e); } catch (MalformedURLException e) { throw new IllegalArgumentException(e.getClass().getSimpleName() + ": " + e.getMessage(), e); } } /** * @param clazz A {@link Class} object * @return A {@link URI} to the location of the class bytes container * - e.g., the root folder, the containing JAR, etc.. Returns * <code>null</code> if location could not be resolved * @throws URISyntaxException if location is not a valid URI * @see #getClassContainerLocationURL(Class) */ public static final URI getClassContainerLocationURI(Class<?> clazz) throws URISyntaxException { URL url = getClassContainerLocationURL(clazz); return (url == null) ? null : url.toURI(); } /** * @param clazz A {@link Class} object * @return A {@link URL} to the location of the class bytes container * - e.g., the root folder, the containing JAR, etc.. Returns * <code>null</code> if location could not be resolved */ public static final URL getClassContainerLocationURL(Class<?> clazz) { ProtectionDomain pd = clazz.getProtectionDomain(); CodeSource cs = (pd == null) ? null : pd.getCodeSource(); URL url = (cs == null) ? null : cs.getLocation(); if (url == null) { if ((url = getClassBytesURL(clazz)) == null) { return null; } String srcForm = URLUtils.getURLSource(url); if (StringUtils.isEmpty(srcForm)) { return null; } try { url = new URL(srcForm); } catch (MalformedURLException e) { throw new IllegalArgumentException( "getClassContainerLocationURL(" + clazz.getName() + ")" + "Failed to create URL=" + srcForm + " from " + url.toExternalForm() + ": " + e.getMessage()); } } return url; } /** * @param clazz The request {@link Class} * @return A {@link URL} to the location of the <code>.class</code> file * - <code>null</code> if location could not be resolved */ public static final URL getClassBytesURL(Class<?> clazz) { String className = clazz.getName(); int sepPos = className.indexOf('$'); // if this is an internal class, then need to use its parent as well if (sepPos > 0) { if ((sepPos = className.lastIndexOf('.')) > 0) { className = className.substring(sepPos + 1); } } else { className = clazz.getSimpleName(); } return clazz.getResource(className + ".class"); } /** * @return A {@link ClassLoader} to be used by the caller. The loader is * resolved in the following manner:</P></BR> * <UL> * <LI> * If a non-<code>null</code> loader is returned from the * {@link Thread#getContextClassLoader()} call then use it. * </LI> * * <LI> * Otherwise, use the same loader that was used to load this class. * </LI> * </UL> * @see #getDefaultClassLoader(Class) */ public static final ClassLoader getDefaultClassLoader() { return getDefaultClassLoader(ExtendedClassUtils.class); } /** * @param anchor An "anchor" {@link Class} to be used in case * no thread context loader is available * @return A {@link ClassLoader} to be used by the caller. The loader is * resolved in the following manner:</P></BR> * <UL> * <LI> * If a non-<code>null</code> loader is returned from the * {@link Thread#getContextClassLoader()} call then use it. * </LI> * * <LI> * Otherwise, use the same loader that was used to load the anchor class. * </LI> * </UL> * @throws IllegalArgumentException if no anchor class provided (regardless of * whether it is used or not) */ public static final ClassLoader getDefaultClassLoader(Class<?> anchor) { if (anchor == null) { throw new IllegalArgumentException("No anchor class provided"); } Thread t = Thread.currentThread(); ClassLoader cl = t.getContextClassLoader(); if (cl == null) { // No thread context class loader -> use class loader of this class. cl = anchor.getClassLoader(); } if (cl == null) { // no class loader - assume system cl = ClassLoader.getSystemClassLoader(); } return cl; } /** * Attempts to locate the <U>first</U> class in the hierarchy whose name * matches the specified one - in other words, answers the question * whether the specified class is a descendant of the named class. * @param clazz The "root" {@link Class} to start from - ignored * if <code>null</code> * @param className The class name to be located * @return The matching {@link Class} - <code>null</code> if not found * @see #findDescendantOf(Class, String, Class) * @throws IllegalArgumentException if <code>null</code>/empty class name */ public static Class<?> findDescendantOf(Class<?> clazz, String className) { return findDescendantOf(clazz, className, null); } /** * Attempts to locate the <U>first</U> class in the hierarchy whose name * matches the specified one - in other words, answers the question * whether the specified class is a descendant of the named class - up to * the specified "stop" class. * @param clazz The "root" {@link Class} to start from - ignored * if <code>null</code> * @param className The class name to be located * @param stopClass The class beyond which to stop looking (inclusive - * i.e., the stop class <U>is checked</U> for match). If <code>null</code> * then same as looking all the way through to {@link Object} (including) * @return The matching {@link Class} - <code>null</code> if not found * @throws IllegalArgumentException if <code>null</code>/empty class name */ public static Class<?> findDescendantOf(Class<?> clazz, String className, Class<?> stopClass) { if (StringUtils.isEmpty(className)) { throw new IllegalArgumentException("No instance class name specified"); } for (Class<?> match = clazz; match != null; match = match.getSuperclass()) { if (className.equals(match.getName())) { return match; } if (match == stopClass) { break; } } return null; } }