Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/jca/ProviderConfig.java
38831 views
/*1* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.jca;2627import java.io.File;28import java.lang.reflect.*;2930import java.security.*;3132import sun.security.util.PropertyExpander;3334/**35* Class representing a configured provider. Encapsulates configuration36* (className plus optional argument), the provider loading logic, and37* the loaded Provider object itself.38*39* @author Andreas Sterbenz40* @since 1.541*/42final class ProviderConfig {4344private final static sun.security.util.Debug debug =45sun.security.util.Debug.getInstance("jca", "ProviderConfig");4647// classname of the SunPKCS11-Solaris provider48private static final String P11_SOL_NAME =49"sun.security.pkcs11.SunPKCS11";5051// config file argument of the SunPKCS11-Solaris provider52private static final String P11_SOL_ARG =53"${java.home}/lib/security/sunpkcs11-solaris.cfg";5455// maximum number of times to try loading a provider before giving up56private final static int MAX_LOAD_TRIES = 30;5758// parameters for the Provider(String) constructor,59// use by doLoadProvider()60private final static Class[] CL_STRING = { String.class };6162// name of the provider class63private final String className;6465// argument to the provider constructor,66// empty string indicates no-arg constructor67private final String argument;6869// number of times we have already tried to load this provider70private int tries;7172// Provider object, if loaded73private volatile Provider provider;7475// flag indicating if we are currently trying to load the provider76// used to detect recursion77private boolean isLoading;7879ProviderConfig(String className, String argument) {80if (className.equals(P11_SOL_NAME) && argument.equals(P11_SOL_ARG)) {81checkSunPKCS11Solaris();82}83this.className = className;84this.argument = expand(argument);85}8687ProviderConfig(String className) {88this(className, "");89}9091ProviderConfig(Provider provider) {92this.className = provider.getClass().getName();93this.argument = "";94this.provider = provider;95}9697// check if we should try to load the SunPKCS11-Solaris provider98// avoid if not available (pre Solaris 10) to reduce startup time99// or if disabled via system property100private void checkSunPKCS11Solaris() {101Boolean o = AccessController.doPrivileged(102new PrivilegedAction<Boolean>() {103public Boolean run() {104File file = new File("/usr/lib/libpkcs11.so");105if (file.exists() == false) {106return Boolean.FALSE;107}108if ("false".equalsIgnoreCase(System.getProperty109("sun.security.pkcs11.enable-solaris"))) {110return Boolean.FALSE;111}112return Boolean.TRUE;113}114});115if (o == Boolean.FALSE) {116tries = MAX_LOAD_TRIES;117}118}119120private boolean hasArgument() {121return argument.length() != 0;122}123124// should we try to load this provider?125private boolean shouldLoad() {126return (tries < MAX_LOAD_TRIES);127}128129// do not try to load this provider again130private void disableLoad() {131tries = MAX_LOAD_TRIES;132}133134boolean isLoaded() {135return (provider != null);136}137138public boolean equals(Object obj) {139if (this == obj) {140return true;141}142if (obj instanceof ProviderConfig == false) {143return false;144}145ProviderConfig other = (ProviderConfig)obj;146return this.className.equals(other.className)147&& this.argument.equals(other.argument);148}149150public int hashCode() {151return className.hashCode() + argument.hashCode();152}153154public String toString() {155if (hasArgument()) {156return className + "('" + argument + "')";157} else {158return className;159}160}161162/**163* Get the provider object. Loads the provider if it is not already loaded.164*/165synchronized Provider getProvider() {166// volatile variable load167Provider p = provider;168if (p != null) {169return p;170}171if (shouldLoad() == false) {172return null;173}174if (isLoading) {175// because this method is synchronized, this can only176// happen if there is recursion.177if (debug != null) {178debug.println("Recursion loading provider: " + this);179new Exception("Call trace").printStackTrace();180}181return null;182}183try {184isLoading = true;185tries++;186p = doLoadProvider();187} finally {188isLoading = false;189}190provider = p;191return p;192}193194/**195* Load and instantiate the Provider described by this class.196*197* NOTE use of doPrivileged().198*199* @return null if the Provider could not be loaded200*201* @throws ProviderException if executing the Provider's constructor202* throws a ProviderException. All other Exceptions are ignored.203*/204private Provider doLoadProvider() {205return AccessController.doPrivileged(new PrivilegedAction<Provider>() {206public Provider run() {207if (debug != null) {208debug.println("Loading provider: " + ProviderConfig.this);209}210try {211ClassLoader cl = ClassLoader.getSystemClassLoader();212Class<?> provClass;213if (cl != null) {214provClass = cl.loadClass(className);215} else {216provClass = Class.forName(className);217}218Object obj;219if (hasArgument() == false) {220obj = provClass.newInstance();221} else {222Constructor<?> cons = provClass.getConstructor(CL_STRING);223obj = cons.newInstance(argument);224}225if (obj instanceof Provider) {226if (debug != null) {227debug.println("Loaded provider " + obj);228}229return (Provider)obj;230} else {231if (debug != null) {232debug.println(className + " is not a provider");233}234disableLoad();235return null;236}237} catch (Exception e) {238Throwable t;239if (e instanceof InvocationTargetException) {240t = ((InvocationTargetException)e).getCause();241} else {242t = e;243}244if (debug != null) {245debug.println("Error loading provider " + ProviderConfig.this);246t.printStackTrace();247}248// provider indicates fatal error, pass through exception249if (t instanceof ProviderException) {250throw (ProviderException)t;251}252// provider indicates that loading should not be retried253if (t instanceof UnsupportedOperationException) {254disableLoad();255}256return null;257} catch (ExceptionInInitializerError err) {258// unexpected exception thrown from static initialization block in provider259// (ex: insufficient permission to initialize provider class)260if (debug != null) {261debug.println("Error loading provider " + ProviderConfig.this);262err.printStackTrace();263}264disableLoad();265return null;266}267}268});269}270271/**272* Perform property expansion of the provider value.273*274* NOTE use of doPrivileged().275*/276private static String expand(final String value) {277// shortcut if value does not contain any properties278if (value.contains("${") == false) {279return value;280}281return AccessController.doPrivileged(new PrivilegedAction<String>() {282public String run() {283try {284return PropertyExpander.expand(value);285} catch (GeneralSecurityException e) {286throw new ProviderException(e);287}288}289});290}291292}293294295