    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one
    003 * or more contributor license agreements.  See the NOTICE file
    004 * distributed with this work for additional information
    005 * regarding copyright ownership.  The ASF licenses this file
    006 * to you under the Apache License, Version 2.0 (the
    007 * "License"); you may not use this file except in compliance
    008 * with the License.  You may obtain a copy of the License at
    009 *
    010 *   https://www.apache.org/licenses/LICENSE-2.0
    011 *
    012 * Unless required by applicable law or agreed to in writing,
    013 * software distributed under the License is distributed on an
    014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    015 * KIND, either express or implied.  See the License for the
    016 * specific language governing permissions and limitations
    017 * under the License.
    018 */
    019package org.apache.commons.compress.harmony.unpack200.bytecode;
    020
    021import java.io.DataOutputStream;
    022import java.io.IOException;
    023import java.util.Objects;
    024
    025/**
    026 * Abstract superclass for reference constant pool entries, such as a method or field reference.
    027 */
    028public abstract class CPRef extends ConstantPoolEntry {
    029
    030    CPClass className;
    031    transient int classNameIndex;
    032
    033    protected CPNameAndType nameAndType;
    034    transient int nameAndTypeIndex;
    035
    036    protected String cachedToString;
    037
    038    /**
    039     * Constructs a new CPRef.
    040     *
    041     * @param type        TODO
    042     * @param className   TODO
    043     * @param descriptor  TODO
    044     * @param globalIndex index in CpBands
    045     * @throws NullPointerException if descriptor or className is null
    046     */
    047    public CPRef(final byte type, final CPClass className, final CPNameAndType descriptor, final int globalIndex) {
    048        super(type, globalIndex);
    049        this.className = Objects.requireNonNull(className, "className");
    050        this.nameAndType = Objects.requireNonNull(descriptor, "descriptor");
    051    }
    052
    053    @Override
    054    public boolean equals(final Object obj) {
    055        if (this == obj) {
    056            return true;
    057        }
    058        if (obj == null || getClass() != obj.getClass() || hashCode() != obj.hashCode()) {
    059            return false;
    060        }
    061        final CPRef other = (CPRef) obj;
    062        return Objects.equals(className, other.className)
    063                && Objects.equals(nameAndType, other.nameAndType);
    064    }
    065
    066    @Override
    067    protected ClassFileEntry[] getNestedClassFileEntries() {
    068        final ClassFileEntry[] entries = new ClassFileEntry[2];
    069        entries[0] = className;
    070        entries[1] = nameAndType;
    071        return entries;
    072    }
    073
    074    @Override
    075    protected void resolve(final ClassConstantPool pool) {
    076        super.resolve(pool);
    077        nameAndTypeIndex = pool.indexOf(nameAndType);
    078        classNameIndex = pool.indexOf(className);
    079    }
    080
    081    @Override
    082    public String toString() {
    083        if (cachedToString == null) {
    084            final String type;
    085            if (getTag() == CP_Fieldref) {
    086                type = "FieldRef"; //$NON-NLS-1$
    087            } else if (getTag() == CP_Methodref) {
    088                type = "MethoddRef"; //$NON-NLS-1$
    089            } else if (getTag() == CP_InterfaceMethodref) {
    090                type = "InterfaceMethodRef"; //$NON-NLS-1$
    091            } else {
    092                type = "unknown"; //$NON-NLS-1$
    093            }
    094            cachedToString = type + ": " + className + "#" + nameAndType; //$NON-NLS-1$ //$NON-NLS-2$
    095        }
    096        return cachedToString;
    097    }
    098
    099    @Override
    100    protected void writeBody(final DataOutputStream dos) throws IOException {
    101        dos.writeShort(classNameIndex);
    102        dos.writeShort(nameAndTypeIndex);
    103    }
    104
    105}