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 io.ebean.enhance.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 (see {@link Type#getInternalName()}).
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 (see {@link Type#getInternalName()}).
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   *     (see {@link Type#getInternalName()}).
123   */
124  public String getOwner() {
125    return owner;
126  }
127
128  /**
129   * Returns the name of the field or method designated by this handle.
130   *
131   * @return the name of the field or method designated by this handle.
132   */
133  public String getName() {
134    return name;
135  }
136
137  /**
138   * Returns the descriptor of the field or method designated by this handle.
139   *
140   * @return the descriptor of the field or method designated by this handle.
141   */
142  public String getDesc() {
143    return descriptor;
144  }
145
146  /**
147   * Returns true if the owner of the field or method designated by this handle is an interface.
148   *
149   * @return true if the owner of the field or method designated by this handle is an interface.
150   */
151  public boolean isInterface() {
152    return isInterface;
153  }
154
155  @Override
156  public boolean equals(final Object object) {
157    if (object == this) {
158      return true;
159    }
160    if (!(object instanceof Handle)) {
161      return false;
162    }
163    Handle handle = (Handle) object;
164    return tag == handle.tag
165        && isInterface == handle.isInterface
166        && owner.equals(handle.owner)
167        && name.equals(handle.name)
168        && descriptor.equals(handle.descriptor);
169  }
170
171  @Override
172  public int hashCode() {
173    return tag
174        + (isInterface ? 64 : 0)
175        + owner.hashCode() * name.hashCode() * descriptor.hashCode();
176  }
177
178  /**
179   * Returns the textual representation of this handle. The textual representation is:
180   *
181   * <ul>
182   *   <li>for a reference to a class: owner "." name descriptor " (" tag ")",
183   *   <li>for a reference to an interface: owner "." name descriptor " (" tag " itf)".
184   * </ul>
185   */
186  @Override
187  public String toString() {
188    return owner + '.' + name + descriptor + " (" + tag + (isInterface ? " itf" : "") + ')';
189  }
190}