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