1 /*
2 * Copyright (c) 2014, 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 jdk.vm.ci.services;
24
25 import java.lang.reflect.Module;
26 import java.util.Formatter;
27 import java.util.Iterator;
28 import java.util.ServiceConfigurationError;
29 import java.util.ServiceLoader;
30
31 /**
32 * A mechanism for accessing service providers via JVMCI.
33 */
34 public final class Services {
35
36 private Services() {
37 }
38
39 /**
40 * Performs any required security checks and dynamic reconfiguration to allow the module of a
41 * given class to access the classes in the JVMCI module.
42 *
43 * Note: This API uses {@link Class} instead of {@link Module} to provide backwards
44 * compatibility for JVMCI clients compiled against a JDK release earlier than 9.
45 *
46 * @param requestor a class requesting access to the JVMCI module for its module
47 * @throws SecurityException if a security manager is present and it denies
48 * {@link JVMCIPermission}
49 */
50 public static void exportJVMCITo(Class<?> requestor) {
51 SecurityManager sm = System.getSecurityManager();
52 if (sm != null) {
53 sm.checkPermission(new JVMCIPermission());
54 }
55 Module jvmci = Services.class.getModule();
56 Module requestorModule = requestor.getModule();
57 if (jvmci != requestorModule) {
58 for (String pkg : jvmci.getPackages()) {
59 // Export all JVMCI packages dynamically instead
60 // of requiring a long list of --add-exports
61 // options on the JVM command line.
62 if (!jvmci.isExported(pkg, requestorModule)) {
63 jvmci.addExports(pkg, requestorModule);
64 }
65 }
66 }
67 }
68
69 /**
70 * Gets an {@link Iterable} of the JVMCI providers available for a given service.
71 *
72 * @throws SecurityException if a security manager is present and it denies
73 * {@link JVMCIPermission}
74 */
75 public static <S> Iterable<S> load(Class<S> service) {
76 SecurityManager sm = System.getSecurityManager();
77 if (sm != null) {
78 sm.checkPermission(new JVMCIPermission());
79 }
80 Module jvmci = Services.class.getModule();
81 jvmci.addUses(service);
82
83 // Restrict JVMCI clients to be on the class path or module path
84 return ServiceLoader.load(service, ClassLoader.getSystemClassLoader());
85 }
86
87 /**
88 * Gets the JVMCI provider for a given service for which at most one provider must be available.
89 *
90 * @param service the service whose provider is being requested
91 * @param required specifies if an {@link InternalError} should be thrown if no provider of
92 * {@code service} is available
93 * @throws SecurityException if a security manager is present and it denies
94 * {@link JVMCIPermission}
95 */
96 public static <S> S loadSingle(Class<S> service, boolean required) {
97 SecurityManager sm = System.getSecurityManager();
98 if (sm != null) {
99 sm.checkPermission(new JVMCIPermission());
100 }
101 Module jvmci = Services.class.getModule();
102 jvmci.addUses(service);
103 // Restrict JVMCI clients to be on the class path or module path
104 Iterable<S> providers = ServiceLoader.load(service, ClassLoader.getSystemClassLoader());
105 S singleProvider = null;
106 try {
107 for (Iterator<S> it = providers.iterator(); it.hasNext();) {
108 singleProvider = it.next();
109 if (it.hasNext()) {
110 throw new InternalError(String.format("Multiple %s providers found", service.getName()));
111 }
112 }
113 } catch (ServiceConfigurationError e) {
114 // If the service is required we will bail out below.
115 }
116 if (singleProvider == null && required) {
117 String javaHome = System.getProperty("java.home");
118 String vmName = System.getProperty("java.vm.name");
119 Formatter errorMessage = new Formatter();
120 errorMessage.format("The VM does not expose required service %s.%n", service.getName());
121 errorMessage.format("Currently used Java home directory is %s.%n", javaHome);
122 errorMessage.format("Currently used VM configuration is: %s", vmName);
123 throw new UnsupportedOperationException(errorMessage.toString());
124 }
125 return singleProvider;
126 }
127 }
--- EOF ---