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 jdk.vm.ci.services;
24 
25 import java.util.ArrayList;
26 import java.util.List;
27 import java.util.ServiceLoader;
28 
29 import jdk.vm.ci.services.internal.ReflectionAccessJDK;
30 
31 /**
32  * Service-provider class for the runtime to locate providers of JVMCI services where the latter are
33  * not in packages exported by the JVMCI module. As part of instantiating a
34  * {@link JVMCIServiceLocator}, all JVMCI packages will be opened to the module defining the class
35  * of the instantiated object.
36  *
37  * While the {@link #getProvider(Class)} method can be used directly, it's usually easier to use
38  * {@link #getProviders(Class)}.
39  */
40 public abstract class JVMCIServiceLocator {
41 
checkPermission()42     private static Void checkPermission() {
43         SecurityManager sm = System.getSecurityManager();
44         if (sm != null) {
45             sm.checkPermission(new JVMCIPermission());
46         }
47         return null;
48     }
49 
50     @SuppressWarnings("unused")
JVMCIServiceLocator(Void ignore)51     private JVMCIServiceLocator(Void ignore) {
52     }
53 
54     /**
55      * Creates a capability for accessing JVMCI. Once successfully instantiated, JVMCI opens all its
56      * packages to the module defining the type of this object.
57      *
58      * @throws SecurityException if a security manager has been installed and it denies
59      *             {@link JVMCIPermission}
60      */
JVMCIServiceLocator()61     protected JVMCIServiceLocator() {
62         this(checkPermission());
63         Services.checkJVMCIEnabled();
64         ReflectionAccessJDK.openJVMCITo(getClass());
65     }
66 
67     /**
68      * Gets the provider of the service defined by {@code service} or {@code null} if this object
69      * does not have a provider for {@code service}.
70      */
getProvider(Class<S> service)71     protected abstract <S> S getProvider(Class<S> service);
72 
73     /**
74      * Gets the providers of the service defined by {@code service} by querying the available
75      * {@link JVMCIServiceLocator} providers.
76      *
77      * @throws SecurityException if a security manager is present and it denies
78      *             {@link JVMCIPermission}
79      */
getProviders(Class<S> service)80     public static <S> List<S> getProviders(Class<S> service) {
81         Services.checkJVMCIEnabled();
82         SecurityManager sm = System.getSecurityManager();
83         if (sm != null) {
84             sm.checkPermission(new JVMCIPermission());
85         }
86         List<S> providers = new ArrayList<>();
87         for (JVMCIServiceLocator access : ServiceLoader.load(JVMCIServiceLocator.class, ClassLoader.getSystemClassLoader())) {
88             S provider = access.getProvider(service);
89             if (provider != null) {
90                 providers.add(provider);
91             }
92         }
93         return providers;
94     }
95 }
96