1 /* 2 * Copyright (c) 2015, 2016, 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 26 package com.sun.tools.javac.util; 27 28 import java.lang.reflect.InvocationTargetException; 29 import java.lang.reflect.Method; 30 import java.nio.file.Path; 31 import java.util.Collection; 32 import java.util.ServiceLoader; 33 34 /** 35 * This class provides wrappers for classes and methods that are new in JDK 9, and which are not 36 * available on older versions of the platform on which javac may be compiled and run. 37 * In future releases, when javac is always compiled on JDK 9 or later, the use of these wrappers 38 * can be replaced by use of the real underlying classes. 39 * 40 * <p>Wrapper classes provide a subset of the API of the wrapped classes, as needed for use 41 * in javac. Wrapper objects contain an {@code Object} reference to the underlying runtime object, 42 * and {@code Class} and {@code Method} objects for obtaining or using such instances via 43 * runtime reflection. The {@code Class} and {@code Method} objects are set up on a per-class 44 * basis, by an {@code init} method, which is called from static methods on the wrapper class, 45 * or in the constructor, when instances are created. 46 * <p> 47 * 48 * <p><b>This is NOT part of any supported API. 49 * If you write code that depends on this, you do so at your own risk. 50 * This code and its internal interfaces are subject to change or 51 * deletion without notice.</b> 52 */ 53 public class JDK9Wrappers { 54 55 /** 56 * Helper class for new method in java.util.ServiceLoader. 57 */ 58 public static final class ServiceLoaderHelper { 59 @SuppressWarnings("unchecked") 60 public static <S> ServiceLoader<S> load(Layer layer, Class<S> service) { 61 try { 62 init(); 63 Object result = loadMethod.invoke(null, layer.theRealLayer, service); 64 return (ServiceLoader<S>)result; 65 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException 66 | SecurityException ex) { 67 throw new Abort(ex); 68 } 69 } 70 71 // ----------------------------------------------------------------------------------------- 72 73 private static Method loadMethod = null; 74 75 private static void init() { 76 if (loadMethod == null) { 77 try { 78 Class<?> layerClass = Layer.layerClass; 79 loadMethod = ServiceLoader.class.getDeclaredMethod("load", layerClass, Class.class); 80 } catch (NoSuchMethodException | SecurityException ex) { 81 throw new Abort(ex); 82 } 83 } 84 } 85 } 86 87 /** 88 * Wrapper class for java.lang.module.ModuleFinder. 89 */ 90 public static class ModuleFinder { 91 private final Object theRealModuleFinder; 92 93 private ModuleFinder(Object moduleFinder) { 94 this.theRealModuleFinder = moduleFinder; 95 init(); 96 } 97 98 public static ModuleFinder of(Path... dirs) { 99 try { 100 init(); 101 Object result = ofMethod.invoke(null, (Object)dirs); 102 ModuleFinder mFinder = new ModuleFinder(result); 103 return mFinder; 104 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException 105 | SecurityException ex) { 106 throw new Abort(ex); 107 } 108 } 109 110 // ----------------------------------------------------------------------------------------- 111 112 private static Class<?> moduleFinderClass = null; 113 private static Method ofMethod; 114 115 static final Class<?> getModuleFinderClass() { 116 init(); 117 return moduleFinderClass; 118 } 119 120 private static void init() { 121 if (moduleFinderClass == null) { 122 try { 123 moduleFinderClass = Class.forName("java.lang.module.ModuleFinder", false, null); 124 ofMethod = moduleFinderClass.getDeclaredMethod("of", Path[].class); 125 } catch (ClassNotFoundException | NoSuchMethodException | SecurityException ex) { 126 throw new Abort(ex); 127 } 128 } 129 } 130 } 131 132 /** 133 * Wrapper class for java.lang.module.Configuration. 134 */ 135 public static final class Configuration { 136 private final Object theRealConfiguration; 137 138 private Configuration(Object configuration) { 139 this.theRealConfiguration = configuration; 140 init(); 141 } 142 143 public Configuration resolveRequiresAndUses( 144 ModuleFinder beforeFinder, 145 ModuleFinder afterFinder, 146 Collection<String> roots) { 147 try { 148 Object result = resolveRequiresAndUsesMethod.invoke(theRealConfiguration, 149 beforeFinder.theRealModuleFinder, 150 afterFinder.theRealModuleFinder, 151 roots 152 ); 153 Configuration configuration = new Configuration(result); 154 return configuration; 155 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException 156 | SecurityException ex) { 157 throw new Abort(ex); 158 } 159 } 160 161 // ----------------------------------------------------------------------------------------- 162 163 private static Class<?> configurationClass = null; 164 private static Method resolveRequiresAndUsesMethod; 165 166 static final Class<?> getConfigurationClass() { 167 init(); 168 return configurationClass; 169 } 170 171 private static void init() { 172 if (configurationClass == null) { 173 try { 174 configurationClass = Class.forName("java.lang.module.Configuration", false, null); 175 Class<?> moduleFinderInterface = ModuleFinder.getModuleFinderClass(); 176 resolveRequiresAndUsesMethod = configurationClass.getDeclaredMethod("resolveRequiresAndUses", 177 moduleFinderInterface, 178 moduleFinderInterface, 179 Collection.class 180 ); 181 } catch (ClassNotFoundException | NoSuchMethodException | SecurityException ex) { 182 throw new Abort(ex); 183 } 184 } 185 } 186 } 187 188 /** 189 * Wrapper class for java.lang.module.Layer. 190 */ 191 public static final class Layer { 192 private final Object theRealLayer; 193 194 private Layer(Object layer) { 195 this.theRealLayer = layer; 196 } 197 198 public static Layer boot() { 199 try { 200 init(); 201 Object result = bootMethod.invoke(null); 202 Layer layer = new Layer(result); 203 return layer; 204 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException 205 | SecurityException ex) { 206 throw new Abort(ex); 207 } 208 } 209 210 public Configuration configuration() { 211 try { 212 Object result = configurationMethod.invoke(theRealLayer); 213 Configuration configuration = new Configuration(result); 214 return configuration; 215 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException 216 | SecurityException ex) { 217 throw new Abort(ex); 218 } 219 } 220 221 public Layer defineModulesWithOneLoader(Configuration configuration, ClassLoader parentClassLoader) { 222 try { 223 Object result = defineModulesWithOneLoaderMethod.invoke( 224 theRealLayer, configuration.theRealConfiguration, parentClassLoader); 225 Layer layer = new Layer(result); 226 return layer; 227 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException 228 | SecurityException ex) { 229 throw new Abort(ex); 230 } 231 } 232 233 // ----------------------------------------------------------------------------------------- 234 235 private static Class<?> layerClass = null; 236 private static Method bootMethod; 237 private static Method defineModulesWithOneLoaderMethod; 238 private static Method configurationMethod; 239 240 private static void init() { 241 if (layerClass == null) { 242 try { 243 layerClass = Class.forName("java.lang.reflect.Layer", false, null); 244 bootMethod = layerClass.getDeclaredMethod("boot"); 245 defineModulesWithOneLoaderMethod = layerClass.getDeclaredMethod("defineModulesWithOneLoader", 246 Configuration.getConfigurationClass(), 247 ClassLoader.class); 248 configurationMethod = layerClass.getDeclaredMethod("configuration"); 249 } catch (ClassNotFoundException | NoSuchMethodException | SecurityException ex) { 250 throw new Abort(ex); 251 } 252 } 253 } 254 } 255 }