• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 The gRPC Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.grpc.internal;
18 
19 import java.lang.reflect.InvocationTargetException;
20 import java.lang.reflect.Method;
21 import java.security.Provider;
22 
23 /**
24  * Utility to load dynamically Conscrypt when it is available.
25  */
26 public final class ConscryptLoader {
27   private static final Method NEW_PROVIDER_METHOD;
28   private static final Method IS_CONSCRYPT_METHOD;
29 
30   static {
31     Method newProvider;
32     Method isConscrypt;
33     try {
34       Class<?> conscryptClass = Class.forName("org.conscrypt.Conscrypt");
35       newProvider = conscryptClass.getMethod("newProvider");
36       isConscrypt = conscryptClass.getMethod("isConscrypt", Provider.class);
37     } catch (ClassNotFoundException ex) {
38       newProvider = null;
39       isConscrypt = null;
40     } catch (NoSuchMethodException ex) {
41       throw new AssertionError(ex);
42     }
43     NEW_PROVIDER_METHOD = newProvider;
44     IS_CONSCRYPT_METHOD = isConscrypt;
45   }
46 
47   /**
48    * Returns {@code true} when the Conscrypt Java classes are available. Does not imply it actually
49    * works on this platform.
50    */
isPresent()51   public static boolean isPresent() {
52     return NEW_PROVIDER_METHOD != null;
53   }
54 
55   /** Same as {@code Conscrypt.isConscrypt(Provider)}. */
isConscrypt(Provider provider)56   public static boolean isConscrypt(Provider provider) {
57     if (!isPresent()) {
58       return false;
59     }
60     try {
61       return (Boolean) IS_CONSCRYPT_METHOD.invoke(null, provider);
62     } catch (IllegalAccessException ex) {
63       throw new AssertionError(ex);
64     } catch (InvocationTargetException ex) {
65       throw new AssertionError(ex);
66     }
67   }
68 
69   /** Same as {@code Conscrypt.newProvider()}. */
newProvider()70   public static Provider newProvider() throws Throwable {
71     if (!isPresent()) {
72       Class.forName("org.conscrypt.Conscrypt");
73       throw new AssertionError("Unexpected failure referencing Conscrypt class");
74     }
75     // Exceptions here probably mean something's wrong with the JNI loading. Maybe the platform is
76     // not supported. It's an error, but it may occur in some environments as part of normal
77     // operation. It's too hard to distinguish "normal" from "abnormal" failures here.
78     return (Provider) NEW_PROVIDER_METHOD.invoke(null);
79   }
80 }
81