001// ASM: a very small and fast Java bytecode manipulation framework
002// Copyright (c) 2000-2011 INRIA, France Telecom
003// All rights reserved.
004//
005// Redistribution and use in source and binary forms, with or without
006// modification, are permitted provided that the following conditions
007// are met:
008// 1. Redistributions of source code must retain the above copyright
009//    notice, this list of conditions and the following disclaimer.
010// 2. Redistributions in binary form must reproduce the above copyright
011//    notice, this list of conditions and the following disclaimer in the
012//    documentation and/or other materials provided with the distribution.
013// 3. Neither the name of the copyright holders nor the names of its
014//    contributors may be used to endorse or promote products derived from
015//    this software without specific prior written permission.
016//
017// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
018// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
019// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
020// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
021// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
022// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
023// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
024// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
025// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
026// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
027// THE POSSIBILITY OF SUCH DAMAGE.
028
029package org.springframework.asm;
030
031/**
032 * A reference to a field or a method.
033 *
034 * @author Remi Forax
035 * @author Eric Bruneton
036 */
037public final class Handle {
038
039  /**
040   * The kind of field or method designated by this Handle. Should be {@link Opcodes#H_GETFIELD},
041   * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, {@link
042   * Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
043   * {@link Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}.
044   */
045  private final int tag;
046
047  /** The internal name of the class that owns the field or method designated by this handle. */
048  private final String owner;
049
050  /** The name of the field or method designated by this handle. */
051  private final String name;
052
053  /** The descriptor of the field or method designated by this handle. */
054  private final String descriptor;
055
056  /** Whether the owner is an interface or not. */
057  private final boolean isInterface;
058
059  /**
060   * Constructs a new field or method handle.
061   *
062   * @param tag the kind of field or method designated by this Handle. Must be {@link
063   *     Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link
064   *     Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
065   *     {@link Opcodes#H_INVOKESPECIAL}, {@link Opcodes#H_NEWINVOKESPECIAL} or {@link
066   *     Opcodes#H_INVOKEINTERFACE}.
067   * @param owner the internal name of the class that owns the field or method designated by this
068   *     handle.
069   * @param name the name of the field or method designated by this handle.
070   * @param descriptor the descriptor of the field or method designated by this handle.
071   * @deprecated this constructor has been superseded by {@link #Handle(int, String, String, String,
072   *     boolean)}.
073   */
074  @Deprecated
075  public Handle(final int tag, final String owner, final String name, final String descriptor) {
076    this(tag, owner, name, descriptor, tag == Opcodes.H_INVOKEINTERFACE);
077  }
078
079  /**
080   * Constructs a new field or method handle.
081   *
082   * @param tag the kind of field or method designated by this Handle. Must be {@link
083   *     Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link
084   *     Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
085   *     {@link Opcodes#H_INVOKESPECIAL}, {@link Opcodes#H_NEWINVOKESPECIAL} or {@link
086   *     Opcodes#H_INVOKEINTERFACE}.
087   * @param owner the internal name of the class that owns the field or method designated by this
088   *     handle.
089   * @param name the name of the field or method designated by this handle.
090   * @param descriptor the descriptor of the field or method designated by this handle.
091   * @param isInterface whether the owner is an interface or not.
092   */
093  public Handle(
094      final int tag,
095      final String owner,
096      final String name,
097      final String descriptor,
098      final boolean isInterface) {
099    this.tag = tag;
100    this.owner = owner;
101    this.name = name;
102    this.descriptor = descriptor;
103    this.isInterface = isInterface;
104  }
105
106  /**
107   * Returns the kind of field or method designated by this handle.
108   *
109   * @return {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
110   *     {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, {@link
111   *     Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL}, {@link
112   *     Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}.
113   */
114  public int getTag() {
115    return tag;
116  }
117
118  /**
119   * Returns the internal name of the class that owns the field or method designated by this handle.
120   *
121   * @return the internal name of the class that owns the field or method designated by this handle.
122   */
123  public String getOwner() {
124    return owner;
125  }
126
127  /**
128   * Returns the name of the field or method designated by this handle.
129   *
130   * @return the name of the field or method designated by this handle.
131   */
132  public String getName() {
133    return name;
134  }
135
136  /**
137   * Returns the descriptor of the field or method designated by this handle.
138   *
139   * @return the descriptor of the field or method designated by this handle.
140   */
141  public String getDesc() {
142    return descriptor;
143  }
144
145  /**
146   * Returns true if the owner of the field or method designated by this handle is an interface.
147   *
148   * @return true if the owner of the field or method designated by this handle is an interface.
149   */
150  public boolean isInterface() {
151    return isInterface;
152  }
153
154  @Override
155  public boolean equals(final Object object) {
156    if (object == this) {
157      return true;
158    }
159    if (!(object instanceof Handle)) {
160      return false;
161    }
162    Handle handle = (Handle) object;
163    return tag == handle.tag
164        && isInterface == handle.isInterface
165        && owner.equals(handle.owner)
166        && name.equals(handle.name)
167        && descriptor.equals(handle.descriptor);
168  }
169
170  @Override
171  public int hashCode() {
172    return tag
173        + (isInterface ? 64 : 0)
174        + owner.hashCode() * name.hashCode() * descriptor.hashCode();
175  }
176
177  /**
178   * Returns the textual representation of this handle. The textual representation is:
179   *
180   * <ul>
181   *   <li>for a reference to a class: owner "." name descriptor " (" tag ")",
182   *   <li>for a reference to an interface: owner "." name descriptor " (" tag " itf)".
183   * </ul>
184   */
185  @Override
186  public String toString() {
187    return owner + '.' + name + descriptor + " (" + tag + (isInterface ? " itf" : "") + ')';
188  }
189}