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