1 /* 2 * Copyright (c) 2017, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package java.lang.invoke; 25 26 import java.lang.reflect.Method; 27 import java.util.ArrayList; 28 import java.util.Arrays; 29 import java.util.List; 30 31 /** 32 * Helper class, injected into java.lang.invoke, 33 * that bridges to the private ClassSpecializer mechanism. 34 */ 35 36 public interface ClassSpecializerHelper { 37 interface Frob { 38 Kind kind(); 39 int label(); 40 List<Object> asList(); 41 } 42 abstract class FrobImpl implements Frob { 43 private final int label; 44 public FrobImpl(int label) { 45 this.label = label; 46 } 47 public int label() { return label; } 48 @Override public abstract Kind kind(); 49 50 public String toString() { 51 final StringBuilder buf = new StringBuilder(); 52 buf.append("Frob[label=").append(label); 53 final Kind k = kind(); 54 if (k != null) { 55 for (MethodHandle mh : k.getters()) { 56 Object x = "?"; 57 try { 58 x = mh.invoke(this); 59 } catch (Throwable ex) { 60 x = "<<"+ex.getMessage()+">>"; 61 } 62 buf.append(", ").append(x); 63 } 64 } 65 buf.append("]"); 66 return buf.toString(); 67 } 68 69 public List<Object> asList() { 70 final List<MethodHandle> getters = kind().getters(); 71 ArrayList<Object> res = new ArrayList<>(getters.size()); 72 for (MethodHandle getter : getters) { 73 try { 74 res.add(getter.invoke(this)); 75 } catch (Throwable ex) { 76 throw new AssertionError(ex); 77 } 78 } 79 return res; 80 } 81 } 82 83 public static class Kind extends ClassSpecializer<Frob, Byte, Kind>.SpeciesData<Frob, Byte> { 84 public Kind(SpecTest outer, Byte key) { 85 outer.super(key); 86 } 87 88 public MethodHandle factory() { 89 return super.factory(); 90 } 91 92 public List<MethodHandle> getters() { 93 return super.getters(); 94 } 95 96 private static final List<Class<?>> FIELD_TYPES 97 = Arrays.asList(String.class, float.class, Double.class, boolean.class, Object[].class, Object.class); 98 99 public static int MAX_KEY = FIELD_TYPES.size(); 100 101 @Override 102 protected List<Class<?>> deriveFieldTypes(Byte key) { 103 return FIELD_TYPES.subList(0, key); 104 } 105 106 @Override 107 protected Class<? extends Frob> deriveSuperClass() { 108 return FrobImpl.class; 109 } 110 111 @Override 112 protected MethodHandle deriveTransformHelper(Method transform, int whichtm) { 113 throw new AssertionError(); 114 } 115 116 @Override 117 protected <X> List<X> deriveTransformHelperArguments(Method transform, int whichtm, List<X> args, List<X> fields) { 118 throw new AssertionError(); 119 } 120 } 121 122 class SpecTest extends ClassSpecializer<Frob, Byte, Kind> { 123 124 public SpecTest() { 125 super(Frob.class, Byte.class, Kind.class, 126 MethodType.methodType(void.class, int.class), 127 reflectMethod(FrobImpl.class, "kind"), "KIND", Arrays.asList()); 128 } 129 130 @Override 131 protected Kind newSpeciesData(Byte key) { 132 return new Kind(this, key); 133 } 134 135 @Override 136 protected Byte addFieldTypeToKey(Byte key, Class<?> type) { 137 throw new AssertionError("NYI addFieldTypeToKey"); 138 } 139 140 public static Kind kind(int key) { 141 return (Kind) SPEC_TEST.findSpecies((byte)key); 142 } 143 } 144 145 static final SpecTest SPEC_TEST = new SpecTest(); 146 147 } 148