1 /*
  2  * Copyright (c) 2002, 2021, 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 jdk.internal.access;
 27 
 28 import javax.crypto.SealedObject;
 29 import javax.crypto.spec.SecretKeySpec;
 30 import java.io.ObjectInputFilter;
 31 import java.lang.invoke.MethodHandles;
 32 import java.lang.module.ModuleDescriptor;
 33 import java.security.spec.EncodedKeySpec;
 34 import java.util.ResourceBundle;
 35 import java.util.jar.JarFile;
 36 import java.io.Console;
 37 import java.io.FileDescriptor;
 38 import java.io.FilePermission;
 39 import java.io.ObjectInputStream;
 40 import java.io.RandomAccessFile;
 41 import java.security.ProtectionDomain;
 42 import java.security.Signature;
 43 
 44 /** A repository of "shared secrets", which are a mechanism for
 45     calling implementation-private methods in another package without
 46     using reflection. A package-private class implements a public
 47     interface and provides the ability to call package-private methods
 48     within that package; the object implementing that interface is
 49     provided through a third package to which access is restricted.
 50     This framework avoids the primary disadvantage of using reflection
 51     for this purpose, namely the loss of compile-time checking. */
 52 
 53 public class SharedSecrets {
 54     private static final MethodHandles.Lookup lookup = MethodHandles.lookup();
 55     private static JavaAWTAccess javaAWTAccess;
 56     private static JavaAWTFontAccess javaAWTFontAccess;
 57     private static JavaBeansAccess javaBeansAccess;
 58     private static JavaLangAccess javaLangAccess;
 59     private static JavaLangInvokeAccess javaLangInvokeAccess;
 60     private static JavaLangModuleAccess javaLangModuleAccess;
 61     private static JavaLangRefAccess javaLangRefAccess;
 62     private static JavaLangReflectAccess javaLangReflectAccess;
 63     private static JavaIOAccess javaIOAccess;
 64     private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess;
 65     private static JavaIOFilePermissionAccess javaIOFilePermissionAccess;
 66     private static JavaIORandomAccessFileAccess javaIORandomAccessFileAccess;
 67     private static JavaObjectInputStreamReadString javaObjectInputStreamReadString;
 68     private static JavaObjectInputStreamAccess javaObjectInputStreamAccess;
 69     private static JavaObjectInputFilterAccess javaObjectInputFilterAccess;
 70     private static JavaNetInetAddressAccess javaNetInetAddressAccess;
 71     private static JavaNetHttpCookieAccess javaNetHttpCookieAccess;
 72     private static JavaNetUriAccess javaNetUriAccess;
 73     private static JavaNetURLAccess javaNetURLAccess;
 74     private static JavaNioAccess javaNioAccess;
 75     private static JavaUtilCollectionAccess javaUtilCollectionAccess;
 76     private static JavaUtilJarAccess javaUtilJarAccess;
 77     private static JavaUtilZipFileAccess javaUtilZipFileAccess;
 78     private static JavaUtilResourceBundleAccess javaUtilResourceBundleAccess;
 79     private static JavaSecurityAccess javaSecurityAccess;
 80     private static JavaSecuritySignatureAccess javaSecuritySignatureAccess;
 81     private static JavaSecuritySpecAccess javaSecuritySpecAccess;
 82     private static JavaxCryptoSealedObjectAccess javaxCryptoSealedObjectAccess;
 83     private static JavaxCryptoSpecAccess javaxCryptoSpecAccess;
 84 
 85     public static void setJavaUtilCollectionAccess(JavaUtilCollectionAccess juca) {
 86         javaUtilCollectionAccess = juca;
 87     }
 88 
 89     public static JavaUtilCollectionAccess getJavaUtilCollectionAccess() {
 90         var access = javaUtilCollectionAccess;
 91         if (access == null) {
 92             try {
 93                 Class.forName("java.util.ImmutableCollections$Access", true, null);
 94                 access = javaUtilCollectionAccess;
 95             } catch (ClassNotFoundException e) {}
 96         }
 97         return access;
 98     }
 99 
100     public static JavaUtilJarAccess javaUtilJarAccess() {
101         var access = javaUtilJarAccess;
102         if (access == null) {
103             // Ensure JarFile is initialized; we know that this class
104             // provides the shared secret
105             ensureClassInitialized(JarFile.class);
106             access = javaUtilJarAccess;
107         }
108         return access;
109     }
110 
111     public static void setJavaUtilJarAccess(JavaUtilJarAccess access) {
112         javaUtilJarAccess = access;
113     }
114 
115     public static void setJavaLangAccess(JavaLangAccess jla) {
116         javaLangAccess = jla;
117     }
118 
119     public static JavaLangAccess getJavaLangAccess() {
120         return javaLangAccess;
121     }
122 
123     public static void setJavaLangInvokeAccess(JavaLangInvokeAccess jlia) {
124         javaLangInvokeAccess = jlia;
125     }
126 
127     public static JavaLangInvokeAccess getJavaLangInvokeAccess() {
128         var access = javaLangInvokeAccess;
129         if (access == null) {
130             try {
131                 Class.forName("java.lang.invoke.MethodHandleImpl", true, null);
132                 access = javaLangInvokeAccess;
133             } catch (ClassNotFoundException e) {}
134         }
135         return access;
136     }
137 
138     public static void setJavaLangModuleAccess(JavaLangModuleAccess jlrma) {
139         javaLangModuleAccess = jlrma;
140     }
141 
142     public static JavaLangModuleAccess getJavaLangModuleAccess() {
143         var access = javaLangModuleAccess;
144         if (access == null) {
145             ensureClassInitialized(ModuleDescriptor.class);
146             access = javaLangModuleAccess;
147         }
148         return access;
149     }
150 
151     public static void setJavaLangRefAccess(JavaLangRefAccess jlra) {
152         javaLangRefAccess = jlra;
153     }
154 
155     public static JavaLangRefAccess getJavaLangRefAccess() {
156         return javaLangRefAccess;
157     }
158 
159     public static void setJavaLangReflectAccess(JavaLangReflectAccess jlra) {
160         javaLangReflectAccess = jlra;
161     }
162 
163     public static JavaLangReflectAccess getJavaLangReflectAccess() {
164         return javaLangReflectAccess;
165     }
166 
167     public static void setJavaNetUriAccess(JavaNetUriAccess jnua) {
168         javaNetUriAccess = jnua;
169     }
170 
171     public static JavaNetUriAccess getJavaNetUriAccess() {
172         var access = javaNetUriAccess;
173         if (access == null) {
174             ensureClassInitialized(java.net.URI.class);
175             access = javaNetUriAccess;
176         }
177         return access;
178     }
179 
180     public static void setJavaNetURLAccess(JavaNetURLAccess jnua) {
181         javaNetURLAccess = jnua;
182     }
183 
184     public static JavaNetURLAccess getJavaNetURLAccess() {
185         var access = javaNetURLAccess;
186         if (access == null) {
187             ensureClassInitialized(java.net.URL.class);
188             access = javaNetURLAccess;
189         }
190         return access;
191     }
192 
193     public static void setJavaNetInetAddressAccess(JavaNetInetAddressAccess jna) {
194         javaNetInetAddressAccess = jna;
195     }
196 
197     public static JavaNetInetAddressAccess getJavaNetInetAddressAccess() {
198         var access = javaNetInetAddressAccess;
199         if (access == null) {
200             ensureClassInitialized(java.net.InetAddress.class);
201             access = javaNetInetAddressAccess;
202         }
203         return access;
204     }
205 
206     public static void setJavaNetHttpCookieAccess(JavaNetHttpCookieAccess a) {
207         javaNetHttpCookieAccess = a;
208     }
209 
210     public static JavaNetHttpCookieAccess getJavaNetHttpCookieAccess() {
211         var access = javaNetHttpCookieAccess;
212         if (access == null) {
213             ensureClassInitialized(java.net.HttpCookie.class);
214             access = javaNetHttpCookieAccess;
215         }
216         return access;
217     }
218 
219     public static void setJavaNioAccess(JavaNioAccess jna) {
220         javaNioAccess = jna;
221     }
222 
223     public static JavaNioAccess getJavaNioAccess() {
224         var access = javaNioAccess;
225         if (access == null) {
226             // Ensure java.nio.Buffer is initialized, which provides the
227             // shared secret.
228             ensureClassInitialized(java.nio.Buffer.class);
229             access = javaNioAccess;
230         }
231         return access;
232     }
233 
234     public static void setJavaIOAccess(JavaIOAccess jia) {
235         javaIOAccess = jia;
236     }
237 
238     public static JavaIOAccess getJavaIOAccess() {
239         var access = javaIOAccess;
240         if (access == null) {
241             ensureClassInitialized(Console.class);
242             access = javaIOAccess;
243         }
244         return access;
245     }
246 
247     public static void setJavaIOFileDescriptorAccess(JavaIOFileDescriptorAccess jiofda) {
248         javaIOFileDescriptorAccess = jiofda;
249     }
250 
251     public static JavaIOFilePermissionAccess getJavaIOFilePermissionAccess() {
252         var access = javaIOFilePermissionAccess;
253         if (access == null) {
254             ensureClassInitialized(FilePermission.class);
255             access = javaIOFilePermissionAccess;
256         }
257         return access;
258     }
259 
260     public static void setJavaIOFilePermissionAccess(JavaIOFilePermissionAccess jiofpa) {
261         javaIOFilePermissionAccess = jiofpa;
262     }
263 
264     public static JavaIOFileDescriptorAccess getJavaIOFileDescriptorAccess() {
265         var access = javaIOFileDescriptorAccess;
266         if (access == null) {
267             ensureClassInitialized(FileDescriptor.class);
268             access = javaIOFileDescriptorAccess;
269         }
270         return access;
271     }
272 
273     public static void setJavaSecurityAccess(JavaSecurityAccess jsa) {
274         javaSecurityAccess = jsa;
275     }
276 
277     public static JavaSecurityAccess getJavaSecurityAccess() {
278         var access = javaSecurityAccess;
279         if (access == null) {
280             ensureClassInitialized(ProtectionDomain.class);
281             access = javaSecurityAccess;
282         }
283         return access;
284     }
285 
286     public static JavaUtilZipFileAccess getJavaUtilZipFileAccess() {
287         var access = javaUtilZipFileAccess;
288         if (access == null) {
289             ensureClassInitialized(java.util.zip.ZipFile.class);
290             access = javaUtilZipFileAccess;
291         }
292         return access;
293     }
294 
295     public static void setJavaUtilZipFileAccess(JavaUtilZipFileAccess access) {
296         javaUtilZipFileAccess = access;
297     }
298 
299     public static void setJavaAWTAccess(JavaAWTAccess jaa) {
300         javaAWTAccess = jaa;
301     }
302 
303     public static JavaAWTAccess getJavaAWTAccess() {
304         // this may return null in which case calling code needs to
305         // provision for.
306         return javaAWTAccess;
307     }
308 
309     public static void setJavaAWTFontAccess(JavaAWTFontAccess jafa) {
310         javaAWTFontAccess = jafa;
311     }
312 
313     public static JavaAWTFontAccess getJavaAWTFontAccess() {
314         // this may return null in which case calling code needs to
315         // provision for.
316         return javaAWTFontAccess;
317     }
318 
319     public static JavaBeansAccess getJavaBeansAccess() {
320         return javaBeansAccess;
321     }
322 
323     public static void setJavaBeansAccess(JavaBeansAccess access) {
324         javaBeansAccess = access;
325     }
326 
327     public static JavaUtilResourceBundleAccess getJavaUtilResourceBundleAccess() {
328         var access = javaUtilResourceBundleAccess;
329         if (access == null) {
330             ensureClassInitialized(ResourceBundle.class);
331             access = javaUtilResourceBundleAccess;
332         }
333         return access;
334     }
335 
336     public static void setJavaUtilResourceBundleAccess(JavaUtilResourceBundleAccess access) {
337         javaUtilResourceBundleAccess = access;
338     }
339 
340     public static JavaObjectInputStreamReadString getJavaObjectInputStreamReadString() {
341         var access = javaObjectInputStreamReadString;
342         if (access == null) {
343             ensureClassInitialized(ObjectInputStream.class);
344             access = javaObjectInputStreamReadString;
345         }
346         return access;
347     }
348 
349     public static void setJavaObjectInputStreamReadString(JavaObjectInputStreamReadString access) {
350         javaObjectInputStreamReadString = access;
351     }
352 
353     public static JavaObjectInputStreamAccess getJavaObjectInputStreamAccess() {
354         var access = javaObjectInputStreamAccess;
355         if (access == null) {
356             ensureClassInitialized(ObjectInputStream.class);
357             access = javaObjectInputStreamAccess;
358         }
359         return access;
360     }
361 
362     public static void setJavaObjectInputStreamAccess(JavaObjectInputStreamAccess access) {
363         javaObjectInputStreamAccess = access;
364     }
365 
366     public static JavaObjectInputFilterAccess getJavaObjectInputFilterAccess() {
367         var access = javaObjectInputFilterAccess;
368         if (access == null) {
369             ensureClassInitialized(ObjectInputFilter.Config.class);
370             access = javaObjectInputFilterAccess;
371         }
372         return access;
373     }
374 
375     public static void setJavaObjectInputFilterAccess(JavaObjectInputFilterAccess access) {
376         javaObjectInputFilterAccess = access;
377     }
378 
379     public static void setJavaIORandomAccessFileAccess(JavaIORandomAccessFileAccess jirafa) {
380         javaIORandomAccessFileAccess = jirafa;
381     }
382 
383     public static JavaIORandomAccessFileAccess getJavaIORandomAccessFileAccess() {
384         var access = javaIORandomAccessFileAccess;
385         if (access == null) {
386             ensureClassInitialized(RandomAccessFile.class);
387             access = javaIORandomAccessFileAccess;
388         }
389         return access;
390     }
391 
392     public static void setJavaSecuritySignatureAccess(JavaSecuritySignatureAccess jssa) {
393         javaSecuritySignatureAccess = jssa;
394     }
395 
396     public static JavaSecuritySignatureAccess getJavaSecuritySignatureAccess() {
397         var access = javaSecuritySignatureAccess;
398         if (access == null) {
399             ensureClassInitialized(Signature.class);
400             access = javaSecuritySignatureAccess;
401         }
402         return access;
403     }
404 
405     public static void setJavaSecuritySpecAccess(JavaSecuritySpecAccess jssa) {
406         javaSecuritySpecAccess = jssa;
407     }
408 
409     public static JavaSecuritySpecAccess getJavaSecuritySpecAccess() {
410         if (javaSecuritySpecAccess == null) {
411             ensureClassInitialized(EncodedKeySpec.class);
412         }
413         return javaSecuritySpecAccess;
414     }
415 
416     public static void setJavaxCryptoSpecAccess(JavaxCryptoSpecAccess jcsa) {
417         javaxCryptoSpecAccess = jcsa;
418     }
419 
420     public static JavaxCryptoSpecAccess getJavaxCryptoSpecAccess() {
421         if (javaxCryptoSpecAccess == null) {
422             ensureClassInitialized(SecretKeySpec.class);
423         }
424         return javaxCryptoSpecAccess;
425     }
426 
427     public static void setJavaxCryptoSealedObjectAccess(JavaxCryptoSealedObjectAccess jcsoa) {
428         javaxCryptoSealedObjectAccess = jcsoa;
429     }
430 
431     public static JavaxCryptoSealedObjectAccess getJavaxCryptoSealedObjectAccess() {
432         var access = javaxCryptoSealedObjectAccess;
433         if (access == null) {
434             ensureClassInitialized(SealedObject.class);
435             access = javaxCryptoSealedObjectAccess;
436         }
437         return access;
438     }
439 
440     private static void ensureClassInitialized(Class<?> c) {
441         try {
442             MethodHandles.lookup().ensureInitialized(c);
443         } catch (IllegalAccessException e) {}
444     }
445 }