All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.datanucleus.util.ClassUtils Maven / Gradle / Ivy

Go to download

DataNucleus Core provides the primary components of a heterogenous Java persistence solution. It supports persistence API's being layered on top of the core functionality.

There is a newer version: 6.0.8
Show newest version
/**********************************************************************
Copyright (c) 2004 Andy Jefferson and others. 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. 


Contributors:
    ...
**********************************************************************/
package org.datanucleus.util;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import org.datanucleus.ClassLoaderResolver;
import org.datanucleus.ClassNameConstants;
import org.datanucleus.ObjectManagerFactoryImpl;
import org.datanucleus.exceptions.ClassNotResolvedException;
import org.datanucleus.exceptions.NucleusException;
import org.datanucleus.exceptions.NucleusUserException;

/**
 * Utilities for handling classes.
 * These are to supplement the methods provided by the Class object.
 */
public class ClassUtils
{
    /** Localisation utility for output messages */
    protected static final Localiser LOCALISER = Localiser.getInstance("org.datanucleus.Localisation",
        ObjectManagerFactoryImpl.class.getClassLoader());

    /** caching for constructors - using caching, the perf is at least doubled **/
    protected static Map constructorsCache = new SoftValueMap();

    /**
     * Accessor for a new instance of an object.
     * Uses reflection to generate the instance using the passed constructor parameter arguments.
     * @param type Type of object (the class).
     * @param parameterTypes Classes of params for the constructor
     * @param parameters The parameters for the constructor
     * @return The object
     * @throws NucleusException If an error occurs creating the instance
     */
    public static Object newInstance(Class type, Class[] parameterTypes, Object[] parameters)
    {
        Object obj;
        try
        {
            String name = ""+type.hashCode();
            if (parameterTypes != null)
            {
                for (int i=0;i 0)
                    {
                        classes.addAll(child_classes);
                    }
                }
            }
        }

        return classes;
    }

    /**
     * Convenience accessor for the names of all class files in the jar file with the specified name.
     * The returned class names are of the form "org.datanucleus.MyClass".
     * @param jarFileName Name of the jar file
     * @return The class names
     */
    public static String[] getClassNamesForJarFile(String jarFileName)
    {
        try
        {
            JarFile jar = new JarFile(jarFileName);
            return getClassNamesForJarFile(jar);
        }
        catch (IOException ioe)
        {
            NucleusLogger.GENERAL.warn("Error opening the jar file " + jarFileName + " : " + ioe.getMessage());
        }
        return null;
    }

    /**
     * Convenience accessor for the names of all class files in the jar file with the specified URL.
     * The returned class names are of the form "org.datanucleus.MyClass".
     * @param jarFileURL URL for the jar file
     * @return The class names
     */
    public static String[] getClassNamesForJarFile(URL jarFileURL)
    {
        File jarFile = new File(jarFileURL.getFile()); // TODO Check for errors
        try
        {
            JarFile jar = new JarFile(jarFile);
            return getClassNamesForJarFile(jar);
        }
        catch (IOException ioe)
        {
            NucleusLogger.GENERAL.warn("Error opening the jar file " + jarFileURL.getFile() + " : " + ioe.getMessage());
        }
        return null;
    }

    /**
     * Convenience method to return the names of classes specified in the jar file.
     * All inner classes are ignored.
     * @param jar Jar file
     * @return The class names
     */
    private static String[] getClassNamesForJarFile(JarFile jar)
    {
        Enumeration jarEntries = jar.entries();
        HashSet classes = new HashSet();
        String file_separator = System.getProperty("file.separator");
        while (jarEntries.hasMoreElements())
        {
            String entry = ((JarEntry)jarEntries.nextElement()).getName();
            if (entry.endsWith(".class") && !ClassUtils.isInnerClass(entry))
            {
                String className = entry.substring(0, entry.length()-6); // Omit ".class"
                className = StringUtils.replaceAll(className, file_separator, ".");
                classes.add(className);
            }
        }
        return (String[])classes.toArray(new String[classes.size()]);
    }

    /**
     * Convenience accessor for the names of all "package.jdo" files in the jar file with the specified name.
     * @param jarFileName Name of the jar file
     * @return The "package.jdo" file names
     */
    public static String[] getPackageJdoFilesForJarFile(String jarFileName)
    {
        try
        {
            JarFile jar = new JarFile(jarFileName);
            return getFileNamesWithSuffixForJarFile(jar, "package.jdo");
        }
        catch (IOException ioe)
        {
            NucleusLogger.GENERAL.warn("Error opening the jar file " + jarFileName + " : " + ioe.getMessage());
        }
        return null;
    }

    /**
     * Convenience accessor for the names of all "package.jdo" files in the jar file with the specified URL.
     * @param jarFileURL URL for the jar file
     * @return The "package.jdo" file names
     */
    public static String[] getPackageJdoFilesForJarFile(URL jarFileURL)
    {
        File jarFile = new File(jarFileURL.getFile()); // TODO Check for errors
        try
        {
            JarFile jar = new JarFile(jarFile);
            return getFileNamesWithSuffixForJarFile(jar, "package.jdo");
        }
        catch (IOException ioe)
        {
            NucleusLogger.GENERAL.warn("Error opening the jar file " + jarFileURL.getFile() + " : " + ioe.getMessage());
        }
        return null;
    }

    /**
     * Convenience method to return the names of files specified in the jar file that end with
     * the specified suffix.
     * @param jar Jar file
     * @param suffix Suffix for the file (can be the filename without the path)
     * @return The fully-qualified names of the files with this suffix in the jar file
     */
    private static String[] getFileNamesWithSuffixForJarFile(JarFile jar, String suffix)
    {
        Enumeration jarEntries = jar.entries();
        HashSet files = new HashSet();
        while (jarEntries.hasMoreElements())
        {
            String entry = ((JarEntry)jarEntries.nextElement()).getName();
            if (entry.endsWith(suffix))
            {
                files.add(entry);
            }
        }
        return (String[])files.toArray(new String[files.size()]);
    }

    /**
     * Method to check whether a classname is for an inner class.
     * Currently checks for the presence of $ in the name.
     * @param class_name The class name
     * @return Whether it is an inner class
     */
    public static boolean isInnerClass(String class_name)
    {
        if (class_name == null)
        {
            return false;
        }
        else if (class_name.indexOf('$') >= 0)
        {
            return true;
        }
        return false;
    }

    /**
     * Method to check for a default constructor on a class.
     * Particular relevance for JDO is the requirement for a default
     * constructor on all Persistence-Capable classes. Doesn't check
     * superclasses for the default constructor.
     * @param the_class The class
     * @return Whether it has a default constructor
     **/
    public static boolean hasDefaultConstructor(Class the_class)
    {
        if (the_class == null)
        {
            return false;
        }
        try
        {
            the_class.getDeclaredConstructor();
        }
        catch (Exception e)
        {
            return false;
        }

        return true;
    }

    /**
     * Method to return the superclasses for a class.
     * The superclasses will be ordered.
     * @param the_class The class
     * @return The superclass of this class.
     */
    public static Collection getSuperclasses(Class the_class)
    {
        List superclasses = new ArrayList();

        Class c = the_class;
        boolean more_superclasses = true;
        while (more_superclasses)
        {
            Class superclass = c.getSuperclass();
            if (superclass != null)
            {
                superclasses.add(superclass);
                c = superclass;
            }
            else
            {
                more_superclasses = false;
            }
        }
        return superclasses;
    }

    /**
     * Method to return the superinterfaces for a class.
     * The superinterfaces will be ordered.
     * @param the_class The class
     * @return The superinterfaces of this class.
     */
    public static Collection getSuperinterfaces(Class the_class)
    {
        List superintfs = new ArrayList();

        Class c = the_class;
        Class[] superinterfaces = c.getInterfaces();
        if (superinterfaces != null)
        {
            for (int i=0; i
     * packageName=test className=Test, returns result=test.Test
     * packageName=test className=test1.Test, returns result=test1.Test
     * packageName=<null> className=Test, returns result=Test
     * packageName=<null> className=test1.Test, returns result=test1.Test
     * 
* @param pkg_name package name. * @param cls_name class name. * @return generated full class name. */ public static String createFullClassName(String pkg_name, String cls_name) { if (StringUtils.isWhitespace(cls_name)) { throw new IllegalArgumentException("Class name not specified"); } else if (StringUtils.isWhitespace(pkg_name)) { return cls_name; } else if (cls_name.indexOf('.') >= 0) { return cls_name; } return pkg_name + "." + cls_name; } /** * Convenience method to return the passed type as a java.lang type wherever possible. * The passed type will be stripped of any package name and will be checked if it is * a known java.lang class. This is used where the user has specified a class name * for a collection or map element/key/value type and meant a java.lang class but didn't * fully qualify it. * @param type The type name * @return The java.lang equivalent (or the input type if not possible) */ public static String getJavaLangClassForType(String type) { // Strip off any package name String baseType = null; if (type.lastIndexOf('.') < 0) { baseType = type; } else { baseType = type.substring(type.lastIndexOf('.')+1); } // Check against our known (supported) java.lang classes if (baseType.equals("String") || baseType.equals("Object") || baseType.equals("Boolean") || baseType.equals("Byte") || baseType.equals("Character") || baseType.equals("Double") || baseType.equals("Float") || baseType.equals("Integer") || baseType.equals("Long") || baseType.equals("Short") || baseType.equals("Number") || baseType.equals("StringBuffer")) { return "java.lang." + baseType; } return type; } /** * Method to check if 2 classes are direct descendents. So one of them is a * superclass of the other. * @param clr ClassLoaderResolver for loading the classes * @param class_name_1 Name of first class * @param class_name_2 Name of second class * @return Whether they are direct descendents. */ public static boolean classesAreDescendents(ClassLoaderResolver clr, String class_name_1, String class_name_2) { Class class_1=clr.classForName(class_name_1); Class class_2=clr.classForName(class_name_2); if (class_1 == null || class_2 == null) { return false; } // Check for direct descendents if (class_1.isAssignableFrom(class_2) || class_2.isAssignableFrom(class_1)) { return true; } return false; } /** * Utility to use Reflection to dump out the details of a class. * Will list all superclasses, interfaces, methods and fields. * Can be used, for example, in checking the methods adding by the * enhancement process. The information is dumped out the JPOX GENERAL log. * @param cls The class to dump out to the log */ public static void dumpClassInformation(Class cls) { NucleusLogger.GENERAL.info("----------------------------------------"); NucleusLogger.GENERAL.info("Class Information for class " + cls.getName()); // Superclasses Collection superclasses=ClassUtils.getSuperclasses(cls); Iterator superclass_iter=superclasses.iterator(); while (superclass_iter.hasNext()) { Class superclass=(Class)superclass_iter.next(); NucleusLogger.GENERAL.info(" Superclass : " + superclass.getName()); } // Interfaces Class[] interfaces=cls.getInterfaces(); if (interfaces != null) { for (int i=0;i



© 2015 - 2024 Weber Informatics LLC | Privacy Policy