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, ClassLoader.getSystemClassLoader()); 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", 175 false, ClassLoader.getSystemClassLoader()); 176 Class<?> moduleFinderInterface = ModuleFinder.getModuleFinderClass(); 177 resolveRequiresAndUsesMethod = configurationClass.getDeclaredMethod("resolveRequiresAndUses", 178 moduleFinderInterface, 179 moduleFinderInterface, 180 Collection.class 181 ); 182 } catch (ClassNotFoundException | NoSuchMethodException | SecurityException ex) { 183 throw new Abort(ex); 184 } 185 } 186 } 187 } 188 189 /** 190 * Wrapper class for java.lang.module.Layer. 191 */ 192 public static final class Layer { 193 private final Object theRealLayer; 194 195 private Layer(Object layer) { 196 this.theRealLayer = layer; 197 } 198 199 public static Layer boot() { 200 try { 201 init(); 202 Object result = bootMethod.invoke(null); 203 Layer layer = new Layer(result); 204 return layer; 205 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException 206 | SecurityException ex) { 207 throw new Abort(ex); 208 } 209 } 210 211 public Configuration configuration() { 212 try { 213 Object result = configurationMethod.invoke(theRealLayer); 214 Configuration configuration = new Configuration(result); 215 return configuration; 216 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException 217 | SecurityException ex) { 218 throw new Abort(ex); 219 } 220 } 221 222 public Layer defineModulesWithOneLoader(Configuration configuration, ClassLoader parentClassLoader) { 223 try { 224 Object result = defineModulesWithOneLoaderMethod.invoke( 225 theRealLayer, configuration.theRealConfiguration, parentClassLoader); 226 Layer layer = new Layer(result); 227 return layer; 228 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException 229 | SecurityException ex) { 230 throw new Abort(ex); 231 } 232 } 233 234 // ----------------------------------------------------------------------------------------- 235 236 private static Class<?> layerClass = null; 237 private static Method bootMethod; 238 private static Method defineModulesWithOneLoaderMethod; 239 private static Method configurationMethod; 240 241 private static void init() { 242 if (layerClass == null) { 243 try { 244 layerClass = Class.forName("java.lang.reflect.Layer", false, ClassLoader.getSystemClassLoader()); 245 bootMethod = layerClass.getDeclaredMethod("boot"); 246 defineModulesWithOneLoaderMethod = layerClass.getDeclaredMethod("defineModulesWithOneLoader", 247 Configuration.getConfigurationClass(), 248 ClassLoader.class); 249 configurationMethod = layerClass.getDeclaredMethod("configuration"); 250 } catch (ClassNotFoundException | NoSuchMethodException | SecurityException ex) { 251 throw new Abort(ex); 252 } 253 } 254 } 255 } 256 }