1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.lang.constant; 26 27 import java.lang.invoke.MethodHandles; 28 import java.util.Optional; 29 30 import static java.lang.constant.ConstantUtils.dropFirstAndLastChar; 31 import static java.lang.constant.ConstantUtils.internalToBinary; 32 import static java.util.Objects.requireNonNull; 33 34 /** 35 * A <a href="package-summary.html#nominal">nominal descriptor</a> for a class, 36 * interface, or array type. A {@linkplain ReferenceClassDescImpl} corresponds to a 37 * {@code Constant_Class_info} entry in the constant pool of a classfile. 38 */ 39 final class ReferenceClassDescImpl implements ClassDesc { 40 private final String descriptor; 41 42 /** 43 * Create a {@linkplain ClassDesc} from a descriptor string for a class or 44 * interface type 45 * 46 * @param descriptor a field descriptor string for a class or interface type, 47 * as per JVMS 4.3.2 48 * @throws IllegalArgumentException if the descriptor string is not a valid 49 * field descriptor string, or does not describe a class or interface type 50 * @jvms 4.3.2 Field Descriptors 51 */ 52 ReferenceClassDescImpl(String descriptor) { 53 requireNonNull(descriptor); 54 int len = ConstantUtils.matchSig(descriptor, 0, descriptor.length()); 55 if (len == 0 || len == 1 56 || len != descriptor.length()) 57 throw new IllegalArgumentException(String.format("not a valid reference type descriptor: %s", descriptor)); 58 this.descriptor = descriptor; 59 } 60 61 @Override 62 public String descriptorString() { 63 return descriptor; 64 } 65 66 @Override 67 public Class<?> resolveConstantDesc(MethodHandles.Lookup lookup) 68 throws ReflectiveOperationException { 69 ClassDesc c = this; 70 int depth = ConstantUtils.arrayDepth(descriptorString()); 71 for (int i=0; i<depth; i++) 72 c = c.componentType(); 73 74 if (c.isPrimitive()) 75 return lookup.findClass(descriptorString()); 76 else { 77 Class<?> clazz = lookup.findClass(internalToBinary(dropFirstAndLastChar(c.descriptorString()))); 78 for (int i = 0; i < depth; i++) 79 clazz = clazz.arrayType(); 80 return clazz; 81 } 82 } 83 84 @Override 85 public Optional<? extends ConstantDesc<ConstantDesc<Class<?>>>> describeConstable() { 86 return Optional.of(DynamicConstantDesc.ofSymbolic(this)); 87 } 88 89 @Override 90 public boolean equals(Object o) { 91 if (this == o) return true; 92 if (o == null || getClass() != o.getClass()) return false; 93 94 ClassDesc constant = (ClassDesc) o; 95 return descriptor.equals(constant.descriptorString()); 96 } 97 98 @Override 99 public int hashCode() { 100 return descriptor.hashCode(); 101 } 102 103 @Override 104 public String toString() { 105 return String.format("ClassDesc[%s]", displayName()); 106 } 107 }