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. 028package org.springframework.asm; 029 030import java.util.Arrays; 031 032/** 033 * A constant whose value is computed at runtime, with a bootstrap method. 034 * 035 * @author Remi Forax 036 */ 037public final class ConstantDynamic { 038 039 /** The constant name (can be arbitrary). */ 040 private final String name; 041 042 /** The constant type (must be a field descriptor). */ 043 private final String descriptor; 044 045 /** The bootstrap method to use to compute the constant value at runtime. */ 046 private final Handle bootstrapMethod; 047 048 /** 049 * The arguments to pass to the bootstrap method, in order to compute the constant value at 050 * runtime. 051 */ 052 private final Object[] bootstrapMethodArguments; 053 054 /** 055 * Constructs a new {@link ConstantDynamic}. 056 * 057 * @param name the constant name (can be arbitrary). 058 * @param descriptor the constant type (must be a field descriptor). 059 * @param bootstrapMethod the bootstrap method to use to compute the constant value at runtime. 060 * @param bootstrapMethodArguments the arguments to pass to the bootstrap method, in order to 061 * compute the constant value at runtime. 062 */ 063 public ConstantDynamic( 064 final String name, 065 final String descriptor, 066 final Handle bootstrapMethod, 067 final Object... bootstrapMethodArguments) { 068 this.name = name; 069 this.descriptor = descriptor; 070 this.bootstrapMethod = bootstrapMethod; 071 this.bootstrapMethodArguments = bootstrapMethodArguments; 072 } 073 074 /** 075 * Returns the name of this constant. 076 * 077 * @return the name of this constant. 078 */ 079 public String getName() { 080 return name; 081 } 082 083 /** 084 * Returns the type of this constant. 085 * 086 * @return the type of this constant, as a field descriptor. 087 */ 088 public String getDescriptor() { 089 return descriptor; 090 } 091 092 /** 093 * Returns the bootstrap method used to compute the value of this constant. 094 * 095 * @return the bootstrap method used to compute the value of this constant. 096 */ 097 public Handle getBootstrapMethod() { 098 return bootstrapMethod; 099 } 100 101 /** 102 * Returns the number of arguments passed to the bootstrap method, in order to compute the value 103 * of this constant. 104 * 105 * @return the number of arguments passed to the bootstrap method, in order to compute the value 106 * of this constant. 107 */ 108 public int getBootstrapMethodArgumentCount() { 109 return bootstrapMethodArguments.length; 110 } 111 112 /** 113 * Returns an argument passed to the bootstrap method, in order to compute the value of this 114 * constant. 115 * 116 * @param index an argument index, between 0 and {@link #getBootstrapMethodArgumentCount()} 117 * (exclusive). 118 * @return the argument passed to the bootstrap method, with the given index. 119 */ 120 public Object getBootstrapMethodArgument(final int index) { 121 return bootstrapMethodArguments[index]; 122 } 123 124 /** 125 * Returns the arguments to pass to the bootstrap method, in order to compute the value of this 126 * constant. WARNING: this array must not be modified, and must not be returned to the user. 127 * 128 * @return the arguments to pass to the bootstrap method, in order to compute the value of this 129 * constant. 130 */ 131 Object[] getBootstrapMethodArgumentsUnsafe() { 132 return bootstrapMethodArguments; 133 } 134 135 /** 136 * Returns the size of this constant. 137 * 138 * @return the size of this constant, i.e., 2 for {@code long} and {@code double}, 1 otherwise. 139 */ 140 public int getSize() { 141 char firstCharOfDescriptor = descriptor.charAt(0); 142 return (firstCharOfDescriptor == 'J' || firstCharOfDescriptor == 'D') ? 2 : 1; 143 } 144 145 @Override 146 public boolean equals(final Object object) { 147 if (object == this) { 148 return true; 149 } 150 if (!(object instanceof ConstantDynamic)) { 151 return false; 152 } 153 ConstantDynamic constantDynamic = (ConstantDynamic) object; 154 return name.equals(constantDynamic.name) 155 && descriptor.equals(constantDynamic.descriptor) 156 && bootstrapMethod.equals(constantDynamic.bootstrapMethod) 157 && Arrays.equals(bootstrapMethodArguments, constantDynamic.bootstrapMethodArguments); 158 } 159 160 @Override 161 public int hashCode() { 162 return name.hashCode() 163 ^ Integer.rotateLeft(descriptor.hashCode(), 8) 164 ^ Integer.rotateLeft(bootstrapMethod.hashCode(), 16) 165 ^ Integer.rotateLeft(Arrays.hashCode(bootstrapMethodArguments), 24); 166 } 167 168 @Override 169 public String toString() { 170 return name 171 + " : " 172 + descriptor 173 + ' ' 174 + bootstrapMethod 175 + ' ' 176 + Arrays.toString(bootstrapMethodArguments); 177 } 178}