src/java.base/share/classes/sun/security/jca/ProviderConfig.java
Print this page
7191662: JCE providers should be located via ServiceLoader
*** 1,7 ****
/*
! * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
--- 1,7 ----
/*
! * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
*** 25,42 ****
package sun.security.jca;
import java.io.File;
import java.lang.reflect.*;
import java.security.*;
import sun.security.util.PropertyExpander;
/**
! * Class representing a configured provider. Encapsulates configuration
! * (className plus optional argument), the provider loading logic, and
* the loaded Provider object itself.
*
* @author Andreas Sterbenz
* @since 1.5
*/
--- 25,43 ----
package sun.security.jca;
import java.io.File;
import java.lang.reflect.*;
+ import java.util.*;
import java.security.*;
import sun.security.util.PropertyExpander;
/**
! * Class representing a configured provider which encapsulates configuration
! * (className + optional argument), the provider loading logic, and
* the loaded Provider object itself.
*
* @author Andreas Sterbenz
* @since 1.5
*/
*** 54,72 ****
"${java.home}/conf/security/sunpkcs11-solaris.cfg";
// maximum number of times to try loading a provider before giving up
private final static int MAX_LOAD_TRIES = 30;
- // parameters for the Provider(String) constructor,
- // use by doLoadProvider()
- private final static Class<?>[] CL_STRING = { String.class };
-
// name of the provider class
private final String className;
! // argument to the provider constructor,
! // empty string indicates no-arg constructor
private final String argument;
// number of times we have already tried to load this provider
private int tries;
--- 55,68 ----
"${java.home}/conf/security/sunpkcs11-solaris.cfg";
// maximum number of times to try loading a provider before giving up
private final static int MAX_LOAD_TRIES = 30;
// name of the provider class
private final String className;
! // argument to the Provider.configure() call, never null
private final String argument;
// number of times we have already tried to load this provider
private int tries;
*** 170,179 ****
--- 166,186 ----
return p;
}
if (shouldLoad() == false) {
return null;
}
+
+ // Create providers which are in java.base directly
+ if (className.equals("sun.security.provider.Sun")) {
+ p = new sun.security.provider.Sun();
+ } else if (className.equals("sun.security.rsa.SunRsaSign")) {
+ p = new sun.security.rsa.SunRsaSign();
+ } else if (className.equals("com.sun.crypto.provider.SunJCE")) {
+ p = new com.sun.crypto.provider.SunJCE();
+ } else if (className.equals("com.sun.net.ssl.internal.ssl.Provider")) {
+ p = new com.sun.net.ssl.internal.ssl.Provider();
+ } else {
if (isLoading) {
// because this method is synchronized, this can only
// happen if there is recursion.
if (debug != null) {
debug.println("Recursion loading provider: " + this);
*** 186,195 ****
--- 193,203 ----
tries++;
p = doLoadProvider();
} finally {
isLoading = false;
}
+ }
provider = p;
return p;
}
/**
*** 206,270 ****
return AccessController.doPrivileged(new PrivilegedAction<Provider>() {
public Provider run() {
if (debug != null) {
debug.println("Loading provider: " + ProviderConfig.this);
}
try {
! ClassLoader cl = ClassLoader.getSystemClassLoader();
! Class<?> provClass;
! if (cl != null) {
! provClass = cl.loadClass(className);
! } else {
! provClass = Class.forName(className);
}
- Object obj;
- if (hasArgument() == false) {
- obj = provClass.newInstance();
- } else {
- Constructor<?> cons = provClass.getConstructor(CL_STRING);
- obj = cons.newInstance(argument);
- }
- if (obj instanceof Provider) {
if (debug != null) {
! debug.println("Loaded provider " + obj);
}
- return (Provider)obj;
} else {
if (debug != null) {
! debug.println(className + " is not a provider");
}
disableLoad();
- return null;
}
} catch (Exception e) {
! Throwable t;
! if (e instanceof InvocationTargetException) {
! t = ((InvocationTargetException)e).getCause();
} else {
- t = e;
- }
if (debug != null) {
! debug.println("Error loading provider " + ProviderConfig.this);
! t.printStackTrace();
}
- // provider indicates fatal error, pass through exception
- if (t instanceof ProviderException) {
- throw (ProviderException)t;
- }
- // provider indicates that loading should not be retried
- if (t instanceof UnsupportedOperationException) {
disableLoad();
- }
return null;
- } catch (ExceptionInInitializerError err) {
- // no sufficient permission to initialize provider class
- if (debug != null) {
- debug.println("Error loading provider " + ProviderConfig.this);
- err.printStackTrace();
}
- disableLoad();
- return null;
}
}
});
}
--- 214,252 ----
return AccessController.doPrivileged(new PrivilegedAction<Provider>() {
public Provider run() {
if (debug != null) {
debug.println("Loading provider: " + ProviderConfig.this);
}
+ ProviderLoader pl = new ProviderLoader();
try {
! Provider p = pl.load(className);
! if (p != null) {
! if (hasArgument()) {
! p = p.configure(argument);
}
if (debug != null) {
! debug.println("Loaded provider " + p.getName());
}
} else {
if (debug != null) {
! debug.println("Error loading " + className);
}
disableLoad();
}
+ return p;
} catch (Exception e) {
! if (e instanceof ProviderException) {
! // pass up
! throw e;
} else {
if (debug != null) {
! debug.println("Error loading " + className);
! e.printStackTrace();
}
disableLoad();
return null;
}
}
}
});
}
*** 287,292 ****
--- 269,388 ----
}
}
});
}
+ // Inner class for loading security providers listed in java.security file
+ private static final class ProviderLoader {
+ ServiceLoader<Provider> services;
+
+ ProviderLoader() {
+ // VM should already been booted at this point, if not
+ // - Only providers in java.base should be loaded, don't use
+ // ServiceLoader
+ // - ClassLoader.getSystemClassLoader() will throw InternalError
+ services = ServiceLoader.load(java.security.Provider.class,
+ ClassLoader.getSystemClassLoader());
+ }
+
+ /**
+ * Loads the provider with the specified class name.
+ *
+ * @param name the name of the provider class
+ * @return the Provider, or null if it cannot be found or loaded
+ * @throws ProviderException all other exceptions are ignored
+ */
+ public Provider load(String classname) {
+ if (debug != null) {
+ debug.println("Attempt to load " + classname + " using SL");
+ }
+ Iterator<Provider> iter = services.iterator();
+ while (iter.hasNext()) {
+ try {
+ Provider p = iter.next();
+ if (debug != null) {
+ debug.println("Found SL Provider named " + p.getName());
+ }
+ if (p.getClass().getName().equals(classname)) {
+ return p;
+ }
+ } catch (SecurityException | ServiceConfigurationError |
+ InvalidParameterException ex) {
+ // if provider loading fail due to security permission,
+ // log it and move on to next provider
+ if (debug != null) {
+ debug.println("Encountered " + ex +
+ " while iterating through SL, ignore and move on");
+ ex.printStackTrace();
+ }
+ }
+ }
+ // No success with ServiceLoader. Try loading provider the legacy,
+ // i.e. pre-module, way via reflection
+ try {
+ return legacyLoad(classname);
+ } catch (ProviderException pe) {
+ // pass through
+ throw pe;
+ } catch (Exception ex) {
+ // logged and ignored
+ if (debug != null) {
+ debug.println("Encountered " + ex +
+ " during legacy load of " + classname);
+ ex.printStackTrace();
+ }
+ return null;
+ }
+ }
+
+ private Provider legacyLoad(String classname) {
+
+ if (debug != null) {
+ debug.println("Loading legacy provider: " + classname);
+ }
+
+ try {
+ Class<?> provClass =
+ ClassLoader.getSystemClassLoader().loadClass(classname);
+
+ // only continue if the specified class extends Provider
+ if (!Provider.class.isAssignableFrom(provClass)) {
+ if (debug != null) {
+ debug.println(classname + " is not a provider");
+ }
+ return null;
+ }
+
+ Provider p = AccessController.doPrivileged
+ (new PrivilegedExceptionAction<Provider>() {
+ public Provider run() throws Exception {
+ return (Provider) provClass.newInstance();
+ }
+ });
+ return p;
+ } catch (Exception e) {
+ Throwable t;
+ if (e instanceof InvocationTargetException) {
+ t = ((InvocationTargetException)e).getCause();
+ } else {
+ t = e;
+ }
+ if (debug != null) {
+ debug.println("Error loading legacy provider " + classname);
+ t.printStackTrace();
+ }
+ // provider indicates fatal error, pass through exception
+ if (t instanceof ProviderException) {
+ throw (ProviderException) t;
+ }
+ return null;
+ } catch (ExceptionInInitializerError | NoClassDefFoundError err) {
+ // no sufficient permission to access/initialize provider class
+ if (debug != null) {
+ debug.println("Error loading legacy provider " + classname);
+ err.printStackTrace();
+ }
+ return null;
+ }
+ }
+ }
}