1 /* 2 * Copyright (c) 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. 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 package org.graalvm.compiler.serviceprovider; 24 25 import java.lang.reflect.InvocationTargetException; 26 import java.lang.reflect.Method; 27 import java.lang.reflect.Modifier; 28 29 /** 30 * Reflection based access to API introduced by JDK 9. This allows the API to be used in code that 31 * must be compiled on a JDK prior to 9. 32 */ 33 public final class JDK9Method { 34 35 private static int getJavaSpecificationVersion() { 36 String value = System.getProperty("java.specification.version"); 37 if (value.startsWith("1.")) { 38 value = value.substring(2); 39 } 40 return Integer.parseInt(value); 41 } 42 43 /** 44 * The integer value corresponding to the value of the {@code java.specification.version} system 45 * property after any leading {@code "1."} has been stripped. 46 */ 47 public static final int JAVA_SPECIFICATION_VERSION = getJavaSpecificationVersion(); 48 49 public JDK9Method(Class<?> declaringClass, String name, Class<?>... parameterTypes) { 50 try { 51 this.method = declaringClass.getMethod(name, parameterTypes); 52 } catch (Exception e) { 53 throw new InternalError(e); 54 } 55 } 56 57 /** 58 * Determines if the Java runtime is version 8 or earlier. 59 */ 60 public static final boolean Java8OrEarlier = JAVA_SPECIFICATION_VERSION <= 8; 61 62 public final Method method; 63 64 public Class<?> getReturnType() { 65 return method.getReturnType(); 66 } 67 68 /** 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 }