    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 *  Unless required by applicable law or agreed to in writing, software
    012 *  distributed under the License is distributed on an "AS IS" BASIS,
    013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 *  See the License for the specific language governing permissions and
    015 *  limitations under the License.
    016 *
    017 */
    018package org.apache.bcel.generic;
    019
    020import org.apache.bcel.Const;
    021import org.apache.bcel.Repository;
    022import org.apache.bcel.classfile.JavaClass;
    023
    024/**
    025 * Denotes reference such as java.lang.String.
    026 *
    027 * @version $Id: ObjectType.java 1806200 2017-08-25 16:33:06Z ggregory $
    028 */
    029public class ObjectType extends ReferenceType {
    030
    031    private final String class_name; // Class name of type
    032
    033    /**
    034     * @since 6.0
    035     */
    036    public static ObjectType getInstance(final String class_name) {
    037        return new ObjectType(class_name);
    038    }
    039
    040    /**
    041     * @param class_name fully qualified class name, e.g. java.lang.String
    042     */
    043    public ObjectType(final String class_name) {
    044        super(Const.T_REFERENCE, "L" + class_name.replace('.', '/') + ";");
    045        this.class_name = class_name.replace('/', '.');
    046    }
    047
    048
    049    /** @return name of referenced class
    050     */
    051    public String getClassName() {
    052        return class_name;
    053    }
    054
    055
    056    /** @return a hash code value for the object.
    057     */
    058    @Override
    059    public int hashCode() {
    060        return class_name.hashCode();
    061    }
    062
    063
    064    /** @return true if both type objects refer to the same class.
    065     */
    066    @Override
    067    public boolean equals( final Object type ) {
    068        return (type instanceof ObjectType)
    069                ? ((ObjectType) type).class_name.equals(class_name)
    070                : false;
    071    }
    072
    073
    074    /**
    075     * If "this" doesn't reference a class, it references an interface
    076     * or a non-existant entity.
    077     * @deprecated (since 6.0) this method returns an inaccurate result
    078     *   if the class or interface referenced cannot
    079     *   be found: use referencesClassExact() instead
    080     */
    081    @Deprecated
    082    public boolean referencesClass() {
    083        try {
    084            final JavaClass jc = Repository.lookupClass(class_name);
    085            return jc.isClass();
    086        } catch (final ClassNotFoundException e) {
    087            return false;
    088        }
    089    }
    090
    091
    092    /**
    093     * If "this" doesn't reference an interface, it references a class
    094     * or a non-existant entity.
    095     * @deprecated (since 6.0) this method returns an inaccurate result
    096     *   if the class or interface referenced cannot
    097     *   be found: use referencesInterfaceExact() instead
    098     */
    099    @Deprecated
    100    public boolean referencesInterface() {
    101        try {
    102            final JavaClass jc = Repository.lookupClass(class_name);
    103            return !jc.isClass();
    104        } catch (final ClassNotFoundException e) {
    105            return false;
    106        }
    107    }
    108
    109
    110    /**
    111     * Return true if this type references a class,
    112     * false if it references an interface.
    113     * @return true if the type references a class, false if
    114     *   it references an interface
    115     * @throws ClassNotFoundException if the class or interface
    116     *   referenced by this type can't be found
    117     */
    118    public boolean referencesClassExact() throws ClassNotFoundException {
    119        final JavaClass jc = Repository.lookupClass(class_name);
    120        return jc.isClass();
    121    }
    122
    123
    124    /**
    125     * Return true if this type references an interface,
    126     * false if it references a class.
    127     * @return true if the type references an interface, false if
    128     *   it references a class
    129     * @throws ClassNotFoundException if the class or interface
    130     *   referenced by this type can't be found
    131     */
    132    public boolean referencesInterfaceExact() throws ClassNotFoundException {
    133        final JavaClass jc = Repository.lookupClass(class_name);
    134        return !jc.isClass();
    135    }
    136
    137
    138    /**
    139     * Return true if this type is a subclass of given ObjectType.
    140     * @throws ClassNotFoundException if any of this class's superclasses
    141     *  can't be found
    142     */
    143    public boolean subclassOf( final ObjectType superclass ) throws ClassNotFoundException {
    144        if (this.referencesInterfaceExact() || superclass.referencesInterfaceExact()) {
    145            return false;
    146        }
    147        return Repository.instanceOf(this.class_name, superclass.class_name);
    148    }
    149
    150
    151    /**
    152     * Java Virtual Machine Specification edition 2, � 5.4.4 Access Control
    153     * @throws ClassNotFoundException if the class referenced by this type
    154     *   can't be found
    155     */
    156    public boolean accessibleTo( final ObjectType accessor ) throws ClassNotFoundException {
    157        final JavaClass jc = Repository.lookupClass(class_name);
    158        if (jc.isPublic()) {
    159            return true;
    160        }
    161        final JavaClass acc = Repository.lookupClass(accessor.class_name);
    162        return acc.getPackageName().equals(jc.getPackageName());
    163    }
    164}