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 /** This class provides wrappers for classes and methods that are new in JDK 9, and which are not 35 * available on older versions of the platform on which javac may be compiled and run. 36 * In future releases, when javac is always compiled on JDK 9 or later, the use of these wrappers 37 * can be replaced by use of the real underlying classes. 38 */ 39 public class ModuleWrappers { 40 public static final class ServiceLoaderHelper { 41 @SuppressWarnings("unchecked") 42 public static <S> ServiceLoader<S> load(Layer layer, Class<S> service) { 43 try { 44 Class<?> layerClass = LayerHelper.getLayerClass(); 45 Method loadMethod = ServiceLoader.class 46 .getDeclaredMethod("load", layerClass, Class.class); 47 Object result = loadMethod.invoke(ServiceLoader.class, layer.theRealLayer, service); 48 return (ServiceLoader<S>)result; 49 } catch (NoSuchMethodException | 50 SecurityException | 51 IllegalArgumentException | 52 IllegalAccessException | 53 InvocationTargetException ex) { 54 throw new Abort(ex); 55 } 56 } 57 } 58 59 public static class ModuleFinder { 60 Object theRealModuleFinder; 61 62 private ModuleFinder(Object moduleFinder) { 63 this.theRealModuleFinder = moduleFinder; 64 } 65 66 public static ModuleFinder of(Path... dirs) { 67 try { 68 Object result = ModuleFinderHelper.getOfMethod() 69 .invoke(ModuleFinderHelper.moduleFinderInterface, (Object)dirs); 70 ModuleFinder mFinder = new ModuleFinder(result); 71 return mFinder; 72 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { 73 throw new Abort(ex); 74 } 75 } 76 77 public static ModuleFinder empty() { 78 try { 79 Object result = ModuleFinderHelper.getEmptyMethod() 80 .invoke(ModuleFinderHelper.moduleFinderInterface); 81 ModuleFinder mFinder = new ModuleFinder(result); 82 return mFinder; 83 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { 84 throw new Abort(ex); 85 } 86 } 87 } 88 89 private static class ModuleFinderHelper { 90 static Method ofMethod = null; 91 static Method emptyMethod = null; 92 static Class<?> moduleFinderInterface; 93 94 static Method getOfMethod() { 95 if (ModuleFinderHelper.ofMethod == null) { 96 try { 97 getModuleFinderInterface(); 98 ofMethod = moduleFinderInterface.getDeclaredMethod("of", Path[].class); 99 } catch (NoSuchMethodException | SecurityException ex) { 100 throw new Abort(ex); 101 } 102 } 103 return ofMethod; 104 } 105 106 static Method getEmptyMethod() { 107 if (emptyMethod == null) { 108 try { 109 getModuleFinderInterface(); 110 emptyMethod = moduleFinderInterface.getDeclaredMethod("empty"); 111 } catch (NoSuchMethodException | SecurityException ex) { 112 throw new Abort(ex); 113 } 114 } 115 return emptyMethod; 116 } 117 118 static Class<?> getModuleFinderInterface() { 119 if (moduleFinderInterface == null) { 120 try { 121 moduleFinderInterface = Class.forName("java.lang.module.ModuleFinder", false, ClassLoader.getSystemClassLoader()); 122 } catch (ClassNotFoundException ex) { 123 throw new Abort(ex); 124 } 125 } 126 return moduleFinderInterface; 127 } 128 } 129 130 public static final class Configuration { 131 Object theRealConfiguration; 132 133 private Configuration(Object configuration) { 134 this.theRealConfiguration = configuration; 135 } 136 137 public Configuration resolveRequiresAndUses( 138 ModuleFinder beforeFinder, 139 ModuleFinder afterFinder, 140 Collection<String> roots) { 141 try { 142 Object result = ConfigurationHelper.getResolveRequiresAndUses() 143 .invoke(theRealConfiguration, 144 beforeFinder.theRealModuleFinder, 145 afterFinder.theRealModuleFinder, 146 roots 147 ); 148 Configuration configuration = new Configuration(result); 149 return configuration; 150 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { 151 throw new Abort(ex); 152 } 153 } 154 } 155 156 private static class ConfigurationHelper { 157 static Method resolveRequiresAndUsesMethod; 158 static Class<?> configurationClass; 159 160 static Method getResolveRequiresAndUses() { 161 if (resolveRequiresAndUsesMethod == null) { 162 try { 163 getConfigurationClass(); 164 Class<?> moduleFinderInterface = ModuleFinderHelper.getModuleFinderInterface(); 165 Class<?> configurationClass = ConfigurationHelper.getConfigurationClass(); 166 resolveRequiresAndUsesMethod = configurationClass.getDeclaredMethod("resolveRequiresAndUses", 167 moduleFinderInterface, 168 moduleFinderInterface, 169 Collection.class 170 ); 171 } catch (NoSuchMethodException | SecurityException ex) { 172 throw new Abort(ex); 173 } 174 } 175 return resolveRequiresAndUsesMethod; 176 } 177 178 static Class<?> getConfigurationClass() { 179 if (configurationClass == null) { 180 try { 181 configurationClass = Class.forName("java.lang.module.Configuration", false, ClassLoader.getSystemClassLoader()); 182 } catch (ClassNotFoundException ex) { 183 throw new Abort(ex); 184 } 185 } 186 return configurationClass; 187 } 188 } 189 190 public static final class Layer { 191 Object theRealLayer; 192 193 private Layer(Object layer) { 194 this.theRealLayer = layer; 195 } 196 197 public static Layer boot() { 198 try { 199 Object result = LayerHelper.getBootMethod().invoke(LayerHelper.getLayerClass()); 200 Layer layer = new Layer(result); 201 return layer; 202 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { 203 throw new Abort(ex); 204 } 205 } 206 207 public Configuration configuration() { 208 try { 209 Object result = LayerHelper.getConfigurationMethod().invoke(theRealLayer); 210 Layer layer = new Layer(result); 211 return new Configuration(result); 212 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { 213 throw new Abort(ex); 214 } 215 } 216 217 public Layer defineModulesWithOneLoader(Configuration configuration, ClassLoader parentClassLoader) { 218 try { 219 Object result = LayerHelper.getDefineModulesWithOneLoaderMethod() 220 .invoke(theRealLayer, configuration.theRealConfiguration, parentClassLoader); 221 Layer layer = new Layer(result); 222 return layer; 223 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { 224 throw new Abort(ex); 225 } 226 } 227 228 } 229 230 private static class LayerHelper { 231 static Class<?> layerClass; 232 static Method bootMethod; 233 static Method defineModulesWithOneLoaderMethod = null; 234 static Method configurationMethod; 235 236 static Class<?> getLayerClass() { 237 if (layerClass == null) { 238 try { 239 layerClass = Class.forName("java.lang.reflect.Layer", false, ClassLoader.getSystemClassLoader()); 240 } catch (ClassNotFoundException ex) { 241 throw new Abort(ex); 242 } 243 } 244 return layerClass; 245 } 246 247 static Method getBootMethod() { 248 if (bootMethod == null) { 249 try { 250 bootMethod = getLayerClass().getDeclaredMethod("boot"); 251 } catch (NoSuchMethodException | SecurityException ex) { 252 throw new Abort(ex); 253 } 254 } 255 return bootMethod; 256 } 257 258 static Method getDefineModulesWithOneLoaderMethod() { 259 if (defineModulesWithOneLoaderMethod == null) { 260 try { 261 defineModulesWithOneLoaderMethod = getLayerClass().getDeclaredMethod("defineModulesWithOneLoader", 262 ConfigurationHelper.getConfigurationClass(), 263 ClassLoader.class 264 ); 265 } catch (NoSuchMethodException | SecurityException ex) { 266 throw new Abort(ex); 267 } 268 } 269 return defineModulesWithOneLoaderMethod; 270 } 271 272 static Method getConfigurationMethod() { 273 if (configurationMethod == null) { 274 try { 275 configurationMethod = getLayerClass().getDeclaredMethod("configuration"); 276 } catch (NoSuchMethodException | SecurityException ex) { 277 throw new Abort(ex); 278 } 279 } 280 return configurationMethod; 281 } 282 } 283 }