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

org.modelcc.io.java.Reflection Maven / Gradle / Ivy

Go to download

ModelCC is a model-based parser generator (a.k.a. compiler compiler) that decouples language specification from language processing, avoiding some of the problems caused by grammar-driven parser generators. ModelCC receives a conceptual model as input, along with constraints that annotate it. It is then able to create a parser for the desired textual language and the generated parser fully automates the instantiation of the language conceptual model. ModelCC also includes a built-in reference resolution mechanism that results in abstract syntax graphs, rather than mere abstract syntax trees.

The newest version!
/*
 * ModelCC, distributed under ModelCC Shared Software License, www.modelcc.org
 */

package org.modelcc.io.java;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.modelcc.language.metamodel.MemberCollectionType;

/**
 * Reflection utilities
 * 
 * @author Luis Quesada ([email protected]) & Fernando Berzal
 *         ([email protected]), with contributions by Evan Klinger
 */
public class Reflection 
{
	
    public static Field findField(Class c, String fieldName) 
    {
        try {
            return c.getDeclaredField(fieldName);
        } catch (Exception e) {
            if (c.getSuperclass() != null)
                return findField(c.getSuperclass(), fieldName);
            return null;
        }
    }

    public static Field[] getAllFields(Class type) 
    {
        List list = new ArrayList();
        getAllFields(list, type);
        Field[] fl = new Field[list.size()];
        for (int i = 0; i < list.size(); i++)
            fl[i] = list.get(i);
        return fl;
    }

    private static List getAllFields(List fields, Class type) 
    {
        for (Field field : type.getDeclaredFields()) {
            fields.add(field);
        }

        if (type.getSuperclass() != null) {
            fields = getAllFields(fields, type.getSuperclass());
        }

        return fields;
    }

    // Class cache

    private static Map> cache = new HashMap>();

    /**
     * Detect all the classes within a specified package or its subpackages.
     * 
     * @param packageName
     *            the package name
     * @return a set of classes
     * @throws ClassNotFoundException
     */
    public static Set findClasses(String packageName, Class type) 
    	throws ClassNotFoundException 
    {
        // Cache lookup

        Set classes = cache.get(packageName);

        if (classes == null) {

            // Cache miss: Look for classes

            List urls = null;
            try {
                urls = getResourceURL(packageName);
            } catch (IOException e) {
            	Logger.getLogger(Reflection.class.getName()).log(Level.INFO,"Unable to get class resource URLs",e);
            }

            if (urls != null) {
                for (URL url : urls) {
                    classes = new HashSet();

                    File directory = new File(url.getFile());

                    if (directory.exists()) { // class within the file system

                        String[] files = directory.list();

                        for (int i = 0; i < files.length; i++) {
                            if (files[i].endsWith(".class") && !files[i].contains("")) {
                                String classname = files[i].substring(0, files[i].length() - 6);
                                Class newClass = Reflection.getClass(packageName + "." + classname);
                                if (newClass != null)
                                    classes.add(newClass);
                            } else {
                                classes.addAll(findClasses(packageName + "." + files[i], type));
                            }
                        }

                    } else { // class within a jar file

                        classes = findJarClasses(type);
                    }
                }
            }

            // Cache update

            cache.put(packageName, classes);
        }

        return classes;
    }

    /**
     * Find classes in the same JAR file than the specified class.
     * 
     * @param type
     *            the class
     * @return classes in the JAR file
     * @throws ClassNotFoundException
     */
    private static Set findJarClasses(Class type) 
    	throws ClassNotFoundException 
    {
        Set classes = new HashSet();

        JarInputStream jarFile;

        try {

            jarFile = new JarInputStream(
                    new FileInputStream(type.getProtectionDomain().getCodeSource().getLocation().toString().substring(5)));

            try {
                JarEntry e = jarFile.getNextJarEntry();

                while (e != null) {
                    String entryname = e.getName();
                    if (entryname.endsWith(".class") && !entryname.contains("")) {
                        String classname = entryname.substring(0, entryname.length() - 6);
                        if (classname.startsWith("/")) {
                            classname = classname.substring(1);
                        }
                        classname = classname.replace('/', '.');
                        Class newClass = Reflection.getClass(classname);
                        if (newClass != null)
                            classes.add(newClass);
                    }
                    e = jarFile.getNextJarEntry();
                }

            } catch (IOException error) {
            	Logger.getLogger(Reflection.class.getName()).log(Level.INFO,"Unable to process class JAR entry",error);
            }

            jarFile.close();

        } catch (IOException error) {
        	Logger.getLogger(Reflection.class.getName()).log(Level.INFO,"Unable to process JAR file",error);
        }

        return classes;
    }

    /**
     * Detect all the classes that extend a class or implement an interface.
     * 
     * @param type
     *            the class
     * @return a set of subclasses
     * @throws ClassNotFoundException
     */
    public static Set findSubclasses(Class type) 
    	throws ClassNotFoundException 
    {
        String packageName = "";

        if (type.getPackage() != null)
            packageName = type.getPackage().getName();

        return findSubclasses(packageName, type);
    }

    /**
     * Detect all the classes that extend a class or implement an interface
     * within a specified set of packages.
     * 
     * @param packages
     *            the set of package names
     * @param type
     *            the class
     * @return a set of subclasses
     * @throws ClassNotFoundException
     */
    public static Set findSubclasses(Set packages, Class type) 
    	throws ClassNotFoundException 
    {
        Set subclasses = new HashSet();

        for (String packageName : packages) {
            subclasses.addAll(findSubclasses(packageName, type));
        }

        return subclasses;
    }

    /**
     * Detect all the classes that extend a class or implement an interface
     * within a specified package or its subpackages.
     * 
     * @param packageName
     *            the package name
     * @param type
     *            the class
     * @return a set of subclasses
     * @throws ClassNotFoundException
     */
    public static Set findSubclasses(String packageName, Class type) 
    	throws ClassNotFoundException 
    {
        Set classes = findClasses(packageName, type);
        Set subclasses = new HashSet();

        for (Class candidate : classes) {
            if (type.isAssignableFrom(candidate) && !type.equals(candidate)) {
                subclasses.add(candidate);
            }
        }

        return subclasses;
    }

    private static List getResourceURL(String packageName) 
    	throws IOException 
    {
        String name = packageName;

        name = name.replace('.', '/');

        Enumeration resources = Thread.currentThread().getContextClassLoader().getResources(name);
        List results = new ArrayList<>();
        
        while (resources.hasMoreElements()) {
            results.add(resources.nextElement());
        }
        
        return results;
    }

    public static boolean hasConstructor(Class elementClass) 
    {
        try {
            if (elementClass.getConstructor() != null)
                return true;
        } catch (Exception e) {
        }
        
        return false;
    }

    /**
     * Checks whether a class (or one of its members) has a given annotation
     * 
     * @param type
     *            the class
     * @param annotation
     *            the annotation
     * @return true if it has a pattern or value annotation, false otherwise
     */
    public static boolean hasAnnotation(Class type, Class annotation) 
    {
        if (type.isAnnotationPresent(annotation))
            return true;
        else {
            Field fl[] = type.getDeclaredFields();
            int i;
            for (i = 0; i < fl.length; i++) {
                if (fl[i].isAnnotationPresent(annotation)) {
                    return true;
                }
            }
            return false;
        }
    }

    /**
     * Returns an element type
     * 
     * @param collection
     *            the collection type (null if no collection)
     * @param field
     *            the field
     * @return the component type
     */
    public static Class getType(MemberCollectionType collection, Field field) 
    {
        if (collection == null)
            return field.getType();

        switch (collection) {
        case ARRAY:
            return field.getType().getComponentType();
        case LIST:
        case SET:
            String name = field.getType().getName();
            String fname = field.getGenericType().toString();
            int ini = name.length() + 1;
            int fin = fname.length() - 1;
            if (ini < fin && fname.endsWith(">")) {
                try {
                    return Reflection.getClass(fname.substring(ini, fin));
                } catch (ClassNotFoundException ex) {
                    return null;
                }
            }
        }

        return null;
    }

    /**
     * Obtain the Class object corresponding to a primitive or non-primitive
     * type name.
     * 
     * @param className
     *            the class name
     * @return the Class object
     * @throws ClassNotFoundException
     */
    public static Class getClass(String className) 
    	throws ClassNotFoundException 
    {
        if (!className.contains(".")) {
            if ("int".equals(className))
                return int.class;
            if ("long".equals(className))
                return long.class;
            if ("byte".equals(className))
                return byte.class;
            if ("short".equals(className))
                return short.class;
            if ("float".equals(className))
                return float.class;
            if ("double".equals(className))
                return double.class;
            if ("boolean".equals(className))
                return boolean.class;
            if ("char".equals(className))
                return char.class;
        }
        return Class.forName(className);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy