JDK9Method.java revision 12748:fbb9c8026495
1169695Skan/* 2169695Skan * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3169695Skan * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4169695Skan * 5169695Skan * This code is free software; you can redistribute it and/or modify it 6169695Skan * under the terms of the GNU General Public License version 2 only, as 7169695Skan * published by the Free Software Foundation. 8169695Skan * 9169695Skan * This code is distributed in the hope that it will be useful, but WITHOUT 10169695Skan * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11169695Skan * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12169695Skan * version 2 for more details (a copy is included in the LICENSE file that 13169695Skan * accompanied this code). 14169695Skan * 15169695Skan * You should have received a copy of the GNU General Public License version 16169695Skan * 2 along with this work; if not, write to the Free Software Foundation, 17169695Skan * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18169695Skan * 19169695Skan * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20169695Skan * or visit www.oracle.com if you need additional information or have any 21169695Skan * questions. 22169695Skan */ 23169695Skanpackage org.graalvm.compiler.serviceprovider; 24169695Skan 25169695Skanimport java.lang.reflect.InvocationTargetException; 26169695Skanimport java.lang.reflect.Method; 27169695Skanimport java.lang.reflect.Modifier; 28169695Skan 29169695Skan/** 30169695Skan * Reflection based access to API introduced by JDK 9. This allows the API to be used in code that 31169695Skan * must be compiled on a JDK prior to 9. 32169695Skan */ 33169695Skanpublic final class JDK9Method { 34169695Skan 35169695Skan private static int getJavaSpecificationVersion() { 36169695Skan String value = System.getProperty("java.specification.version"); 37169695Skan if (value.startsWith("1.")) { 38169695Skan value = value.substring(2); 39169695Skan } 40169695Skan return Integer.parseInt(value); 41169695Skan } 42169695Skan 43169695Skan /** 44169695Skan * The integer value corresponding to the value of the {@code java.specification.version} system 45169695Skan * property after any leading {@code "1."} has been stripped. 46169695Skan */ 47169695Skan public static final int JAVA_SPECIFICATION_VERSION = getJavaSpecificationVersion(); 48169695Skan 49169695Skan public JDK9Method(Class<?> declaringClass, String name, Class<?>... parameterTypes) { 50169695Skan try { 51169695Skan this.method = declaringClass.getMethod(name, parameterTypes); 52169695Skan } catch (Exception e) { 53169695Skan throw new InternalError(e); 54169695Skan } 55169695Skan } 56169695Skan 57169695Skan /** 58169695Skan * Determines if the Java runtime is version 8 or earlier. 59169695Skan */ 60169695Skan public static final boolean Java8OrEarlier = JAVA_SPECIFICATION_VERSION <= 8; 61169695Skan 62169695Skan public final Method method; 63169695Skan 64169695Skan public Class<?> getReturnType() { 65169695Skan return method.getReturnType(); 66169695Skan } 67169695Skan 68169695Skan /** 69 * {@code Class.getModule()}. 70 */ 71 public static final JDK9Method getModule; 72 73 /** 74 * {@code java.lang.Module.getPackages()}. 75 */ 76 public static final JDK9Method getPackages; 77 78 /** 79 * {@code java.lang.Module.getResourceAsStream(String)}. 80 */ 81 public static final JDK9Method getResourceAsStream; 82 83 /** 84 * {@code java.lang.Module.addOpens(String, Module)}. 85 */ 86 public static final JDK9Method addOpens; 87 88 /** 89 * {@code java.lang.Module.isOpen(String, Module)}. 90 */ 91 public static final JDK9Method isOpenTo; 92 93 /** 94 * Invokes the static Module API method represented by this object. 95 */ 96 @SuppressWarnings("unchecked") 97 public <T> T invokeStatic(Object... args) { 98 checkAvailability(); 99 assert Modifier.isStatic(method.getModifiers()); 100 try { 101 return (T) method.invoke(null, args); 102 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { 103 throw new InternalError(e); 104 } 105 } 106 107 /** 108 * Invokes the non-static Module API method represented by this object. 109 */ 110 @SuppressWarnings("unchecked") 111 public <T> T invoke(Object receiver, Object... args) { 112 checkAvailability(); 113 assert !Modifier.isStatic(method.getModifiers()); 114 try { 115 return (T) method.invoke(receiver, args); 116 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { 117 throw new InternalError(e); 118 } 119 } 120 121 private void checkAvailability() throws InternalError { 122 if (method == null) { 123 throw new InternalError("Cannot use Module API on JDK " + JAVA_SPECIFICATION_VERSION); 124 } 125 } 126 127 static { 128 if (JAVA_SPECIFICATION_VERSION >= 9) { 129 getModule = new JDK9Method(Class.class, "getModule"); 130 Class<?> moduleClass = getModule.getReturnType(); 131 getPackages = new JDK9Method(moduleClass, "getPackages"); 132 addOpens = new JDK9Method(moduleClass, "addOpens", String.class, moduleClass); 133 getResourceAsStream = new JDK9Method(moduleClass, "getResourceAsStream", String.class); 134 isOpenTo = new JDK9Method(moduleClass, "isOpen", String.class, moduleClass); 135 } else { 136 JDK9Method unavailable = new JDK9Method(); 137 getModule = unavailable; 138 getPackages = unavailable; 139 addOpens = unavailable; 140 getResourceAsStream = unavailable; 141 isOpenTo = unavailable; 142 } 143 } 144 145 private JDK9Method() { 146 method = null; 147 } 148} 149