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

javax.el.ImportHandler Maven / Gradle / Ivy

There is a newer version: 5.0.0-M1
Show newest version
/*
 * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package javax.el;

import java.util.Map;
import java.util.List;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.HashSet;
import java.lang.reflect.Modifier;

/**
 * Handles imports of class names and package names.  An imported package
 * name implicitly imports all the classes in the package.  A class that has
 * been imported can be used without its package name.
 * The name is resolved to its full (package and class) name
 * at evaluation time.
 */
public class ImportHandler {

    private Map classNameMap = new HashMap();
    private Map> classMap = new HashMap>();
    private Map staticNameMap = new HashMap();
    private HashSet notAClass = new HashSet();
    private List packages = new ArrayList();

    {
        importPackage("java.lang");
    }

    /**
     * Import a static field or method.
     * @param name The static member name, including the full class name,
     *     to be imported
     * @throws ELException if the name does not include a ".".
     */
    public void importStatic(String name) throws ELException {
        int i = name.lastIndexOf('.');
        if (i <= 0) {
            throw new ELException(
                "The name " + name + " is not a full static member name");
        }
        String memberName = name.substring(i+1);
        String className = name.substring(0, i);
        staticNameMap.put(memberName, className);
    }

    /**
     * Import a class.
     * @param name The full class name of the class to be imported
     * @throws ELException if the name does not include a ".".
     */
    public void importClass(String name) throws ELException {
        int i = name.lastIndexOf('.');
        if (i <= 0) {
            throw new ELException(
                "The name " + name + " is not a full class name");
        }
        String className = name.substring(i+1);
        classNameMap.put(className, name);
    }

    /**
     * Import all the classes in a package.
     * @param packageName The package name to be imported
     */
    public void importPackage(String packageName) {
        packages.add(packageName);
    }

    /**
     * Resolve a class name.
     *
     * @param name The name of the class (without package name) to be resolved.
     * @return  If the class has been imported previously, with
     *     {@link #importClass} or {@link #importPackage}, then its
     *     Class instance. Otherwise null.
     * @throws ELException if the class is abstract or is an interface, or
     *     not public.
     */
    public Class resolveClass(String name) {

        String className = classNameMap.get(name);
        if (className != null) {
            return resolveClassFor(className);
        }

        for (String packageName: packages) {
            String fullClassName = packageName + "." + name;
            Classc = resolveClassFor(fullClassName);
            if (c != null) {
                classNameMap.put(name, fullClassName);
                return c;
            }
        }
        return null;
    }

    /**
     * Resolve a static field or method name.
     *
     * @param name The name of the member(without package and class name)
     *    to be resolved.
     * @return  If the field or method  has been imported previously, with
     *     {@link #importStatic}, then the class object representing the class that
     *     declares the static field or method.
     *     Otherwise null.
     * @throws ELException if the class is not public, or is abstract or
     *     is an interface.
     */
    public Class resolveStatic(String name) {
        String className = staticNameMap.get(name);
        if (className != null) {
            Class c = resolveClassFor(className);
            if (c != null) {
                return c;
            }
        }
        return null;
    }

    private Class resolveClassFor(String className) {
        Class c = classMap.get(className);
        if (c != null) {
            return c;
        }
        c = getClassFor(className);
        if (c != null) {
            checkModifiers(c.getModifiers());
            classMap.put(className, c);
        }
        return c;
    }

    private Class getClassFor(String className) {
        if (!notAClass.contains(className)) {
            try {
                return Class.forName(className, false, Thread.currentThread().getContextClassLoader());
            } catch (ClassNotFoundException ex) {
                notAClass.add(className);
            }
        }
        return null;
    }

    private void checkModifiers(int modifiers) {
        if (Modifier.isAbstract(modifiers) || Modifier.isInterface(modifiers)
                || ! Modifier.isPublic((modifiers))) {
            throw new ELException("Imported class must be public, and cannot be abstract or an interface");
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy