8130302: jarsigner and keytool -providerClass needs be re-examined for modules
authorweijun
Tue, 12 Jul 2016 09:41:49 +0800
changeset 39633 9dc7586be5f0
parent 39570 f774415f91ad
child 39634 812020bcb9f1
8130302: jarsigner and keytool -providerClass needs be re-examined for modules Reviewed-by: valeriep, mchung, mullan
jdk/src/java.base/share/classes/sun/security/tools/KeyStoreUtil.java
jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java
jdk/src/java.base/share/classes/sun/security/tools/keytool/Resources.java
jdk/src/java.base/share/conf/security/java.policy
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java
jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java
jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java
jdk/test/sun/security/pkcs11/fips/ImportKeyStore.java
jdk/test/sun/security/tools/jarsigner/AltProvider.java
jdk/test/sun/security/tools/jarsigner/alt/test.dummy/module-info.java
jdk/test/sun/security/tools/jarsigner/alt/test.dummy/org/test/dummy/DummyProvider.java
jdk/test/sun/security/tools/keytool/AltProviderPath.sh
jdk/test/sun/security/tools/keytool/DummyProvider.java
jdk/test/sun/security/tools/keytool/KeyToolTest.java
jdk/test/sun/security/tools/keytool/i18n.html
--- a/jdk/src/java.base/share/classes/sun/security/tools/KeyStoreUtil.java	Mon Jul 11 17:18:59 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/tools/KeyStoreUtil.java	Tue Jul 12 09:41:49 2016 +0800
@@ -38,6 +38,8 @@
 
 import java.security.KeyStore;
 
+import java.security.Provider;
+import java.security.Security;
 import java.security.cert.X509Certificate;
 import java.text.Collator;
 
@@ -46,6 +48,7 @@
 import java.util.List;
 import java.util.Locale;
 import java.util.Properties;
+import java.util.ServiceLoader;
 
 import sun.security.util.PropertyExpander;
 
@@ -209,6 +212,7 @@
 
     /**
      * Prepends matched options from a pre-configured options file.
+     *
      * @param tool the name of the tool, can be "keytool" or "jarsigner"
      * @param file the pre-configured options file
      * @param c1 the name of the command, with the "-" prefix,
@@ -259,4 +263,68 @@
             return result.toArray(new String[result.size()]);
         }
     }
+
+    /**
+     * Loads a security provider as a service.
+     *
+     * @param provName the name
+     * @param arg optional arg
+     * @throws IllegalArgumentException if no provider matches the name
+     */
+    public static void loadProviderByName(String provName, String arg) {
+        Provider loaded = Security.getProvider(provName);
+        if (loaded != null) {
+            if (arg != null) {
+                loaded = loaded.configure(arg);
+                Security.addProvider(loaded);
+            }
+            return;
+        }
+        for (Provider p : ServiceLoader.load(Provider.class,
+                ClassLoader.getSystemClassLoader())) {
+            if (p.getName().equals(provName)) {
+                if (arg != null) {
+                    p = p.configure(arg);
+                }
+                Security.addProvider(p);
+                return;
+            }
+        }
+        throw new IllegalArgumentException("No provider found");
+    }
+
+    /**
+     * Loads a security provider by a fully-qualified class name.
+     *
+     * @param provClass the class name
+     * @param arg optional arg
+     * @param cl optional class loader
+     * @throws IllegalArgumentException if no provider matches the class name
+     * @throws ClassCastException if the class has not extended Provider
+     */
+    public static void loadProviderByClass(
+            String provClass, String arg, ClassLoader cl) {
+
+        // For compatibility, SunPKCS11 and OracleUcrypto can still be
+        // loadable with -providerClass.
+        if (provClass.equals("sun.security.pkcs11.SunPKCS11")) {
+            loadProviderByName("SunPKCS11", arg);
+            return;
+        } else if (provClass.equals("com.oracle.security.crypto.UcryptoProvider")) {
+            loadProviderByName("OracleUcrypto", arg);
+            return;
+        }
+
+        Provider prov;
+        try {
+            Class<?> clazz = Class.forName(provClass, false, cl);
+            prov = (Provider) clazz.getConstructor().newInstance();
+        } catch (ReflectiveOperationException e) {
+            throw new IllegalArgumentException(e);
+        }
+        if (arg != null) {
+            prov = prov.configure(arg);
+        }
+        Security.addProvider(prov);
+    }
 }
--- a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java	Mon Jul 11 17:18:59 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java	Tue Jul 12 09:41:49 2016 +0800
@@ -33,13 +33,11 @@
 import java.security.Key;
 import java.security.PublicKey;
 import java.security.PrivateKey;
-import java.security.Security;
 import java.security.Signature;
 import java.security.Timestamp;
 import java.security.UnrecoverableEntryException;
 import java.security.UnrecoverableKeyException;
 import java.security.Principal;
-import java.security.Provider;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateFactory;
 import java.security.cert.CertStoreException;
@@ -128,6 +126,7 @@
     // them through the command line.
 
     private Set<Pair <String, String>> providers = null;
+    private Set<Pair <String, String>> providerClasses = null;
     private String storetype = null;
     private boolean hasStoretypeOption = false;
     private String srcProviderName = null;
@@ -166,57 +165,57 @@
     enum Command {
         CERTREQ("Generates.a.certificate.request",
             ALIAS, SIGALG, FILEOUT, KEYPASS, KEYSTORE, DNAME,
-            STOREPASS, STORETYPE, PROVIDERNAME, PROVIDERCLASS,
-            PROVIDERARG, PROVIDERPATH, V, PROTECTED),
+            STOREPASS, STORETYPE, PROVIDERNAME, ADDPROVIDER,
+            PROVIDERCLASS, PROVIDERPATH, V, PROTECTED),
         CHANGEALIAS("Changes.an.entry.s.alias",
             ALIAS, DESTALIAS, KEYPASS, KEYSTORE, STOREPASS,
-            STORETYPE, PROVIDERNAME, PROVIDERCLASS, PROVIDERARG,
+            STORETYPE, PROVIDERNAME, ADDPROVIDER, PROVIDERCLASS,
             PROVIDERPATH, V, PROTECTED),
         DELETE("Deletes.an.entry",
             ALIAS, KEYSTORE, STOREPASS, STORETYPE,
-            PROVIDERNAME, PROVIDERCLASS, PROVIDERARG,
+            PROVIDERNAME, ADDPROVIDER, PROVIDERCLASS,
             PROVIDERPATH, V, PROTECTED),
         EXPORTCERT("Exports.certificate",
             RFC, ALIAS, FILEOUT, KEYSTORE, STOREPASS,
-            STORETYPE, PROVIDERNAME, PROVIDERCLASS, PROVIDERARG,
+            STORETYPE, PROVIDERNAME, ADDPROVIDER, PROVIDERCLASS,
             PROVIDERPATH, V, PROTECTED),
         GENKEYPAIR("Generates.a.key.pair",
             ALIAS, KEYALG, KEYSIZE, SIGALG, DESTALIAS, DNAME,
             STARTDATE, EXT, VALIDITY, KEYPASS, KEYSTORE,
-            STOREPASS, STORETYPE, PROVIDERNAME, PROVIDERCLASS,
-            PROVIDERARG, PROVIDERPATH, V, PROTECTED),
+            STOREPASS, STORETYPE, PROVIDERNAME, ADDPROVIDER,
+            PROVIDERCLASS, PROVIDERPATH, V, PROTECTED),
         GENSECKEY("Generates.a.secret.key",
             ALIAS, KEYPASS, KEYALG, KEYSIZE, KEYSTORE,
-            STOREPASS, STORETYPE, PROVIDERNAME, PROVIDERCLASS,
-            PROVIDERARG, PROVIDERPATH, V, PROTECTED),
+            STOREPASS, STORETYPE, PROVIDERNAME, ADDPROVIDER,
+            PROVIDERCLASS, PROVIDERPATH, V, PROTECTED),
         GENCERT("Generates.certificate.from.a.certificate.request",
             RFC, INFILE, OUTFILE, ALIAS, SIGALG, DNAME,
             STARTDATE, EXT, VALIDITY, KEYPASS, KEYSTORE,
-            STOREPASS, STORETYPE, PROVIDERNAME, PROVIDERCLASS,
-            PROVIDERARG, PROVIDERPATH, V, PROTECTED),
+            STOREPASS, STORETYPE, PROVIDERNAME, ADDPROVIDER,
+            PROVIDERCLASS, PROVIDERPATH, V, PROTECTED),
         IMPORTCERT("Imports.a.certificate.or.a.certificate.chain",
             NOPROMPT, TRUSTCACERTS, PROTECTED, ALIAS, FILEIN,
             KEYPASS, KEYSTORE, STOREPASS, STORETYPE,
-            PROVIDERNAME, PROVIDERCLASS, PROVIDERARG,
+            PROVIDERNAME, ADDPROVIDER, PROVIDERCLASS,
             PROVIDERPATH, V),
         IMPORTPASS("Imports.a.password",
             ALIAS, KEYPASS, KEYALG, KEYSIZE, KEYSTORE,
-            STOREPASS, STORETYPE, PROVIDERNAME, PROVIDERCLASS,
-            PROVIDERARG, PROVIDERPATH, V, PROTECTED),
+            STOREPASS, STORETYPE, PROVIDERNAME, ADDPROVIDER,
+            PROVIDERCLASS, PROVIDERPATH, V, PROTECTED),
         IMPORTKEYSTORE("Imports.one.or.all.entries.from.another.keystore",
             SRCKEYSTORE, DESTKEYSTORE, SRCSTORETYPE,
             DESTSTORETYPE, SRCSTOREPASS, DESTSTOREPASS,
             SRCPROTECTED, DESTPROTECTED, SRCPROVIDERNAME, DESTPROVIDERNAME,
             SRCALIAS, DESTALIAS, SRCKEYPASS, DESTKEYPASS,
-            NOPROMPT, PROVIDERCLASS, PROVIDERARG, PROVIDERPATH,
+            NOPROMPT, ADDPROVIDER, PROVIDERCLASS, PROVIDERPATH,
             V),
         KEYPASSWD("Changes.the.key.password.of.an.entry",
             ALIAS, KEYPASS, NEW, KEYSTORE, STOREPASS,
-            STORETYPE, PROVIDERNAME, PROVIDERCLASS, PROVIDERARG,
+            STORETYPE, PROVIDERNAME, ADDPROVIDER, PROVIDERCLASS,
             PROVIDERPATH, V),
         LIST("Lists.entries.in.a.keystore",
             RFC, ALIAS, KEYSTORE, STOREPASS, STORETYPE,
-            PROVIDERNAME, PROVIDERCLASS, PROVIDERARG,
+            PROVIDERNAME, ADDPROVIDER, PROVIDERCLASS,
             PROVIDERPATH, V, PROTECTED),
         PRINTCERT("Prints.the.content.of.a.certificate",
             RFC, FILEIN, SSLSERVER, JARFILE, V),
@@ -226,26 +225,26 @@
             FILEIN, V),
         STOREPASSWD("Changes.the.store.password.of.a.keystore",
             NEW, KEYSTORE, STOREPASS, STORETYPE, PROVIDERNAME,
-            PROVIDERCLASS, PROVIDERARG, PROVIDERPATH, V),
+            ADDPROVIDER, PROVIDERCLASS, PROVIDERPATH, V),
 
         // Undocumented start here, KEYCLONE is used a marker in -help;
 
         KEYCLONE("Clones.a.key.entry",
             ALIAS, DESTALIAS, KEYPASS, NEW, STORETYPE,
-            KEYSTORE, STOREPASS, PROVIDERNAME, PROVIDERCLASS,
-            PROVIDERARG, PROVIDERPATH, V),
+            KEYSTORE, STOREPASS, PROVIDERNAME, ADDPROVIDER,
+            PROVIDERCLASS, PROVIDERPATH, V),
         SELFCERT("Generates.a.self.signed.certificate",
             ALIAS, SIGALG, DNAME, STARTDATE, VALIDITY, KEYPASS,
             STORETYPE, KEYSTORE, STOREPASS, PROVIDERNAME,
-            PROVIDERCLASS, PROVIDERARG, PROVIDERPATH, V),
+            ADDPROVIDER, PROVIDERCLASS, PROVIDERPATH, V),
         GENCRL("Generates.CRL",
             RFC, FILEOUT, ID,
             ALIAS, SIGALG, EXT, KEYPASS, KEYSTORE,
-            STOREPASS, STORETYPE, PROVIDERNAME, PROVIDERCLASS,
-            PROVIDERARG, PROVIDERPATH, V, PROTECTED),
+            STOREPASS, STORETYPE, PROVIDERNAME, ADDPROVIDER,
+            PROVIDERCLASS, PROVIDERPATH, V, PROTECTED),
         IDENTITYDB("Imports.entries.from.a.JDK.1.1.x.style.identity.database",
             FILEIN, STORETYPE, KEYSTORE, STOREPASS, PROVIDERNAME,
-            PROVIDERCLASS, PROVIDERARG, PROVIDERPATH, V);
+            ADDPROVIDER, PROVIDERCLASS, PROVIDERPATH, V);
 
         final String description;
         final Option[] options;
@@ -289,48 +288,48 @@
 
     enum Option {
         ALIAS("alias", "<alias>", "alias.name.of.the.entry.to.process"),
-        DESTALIAS("destalias", "<destalias>", "destination.alias"),
+        DESTALIAS("destalias", "<alias>", "destination.alias"),
         DESTKEYPASS("destkeypass", "<arg>", "destination.key.password"),
-        DESTKEYSTORE("destkeystore", "<destkeystore>", "destination.keystore.name"),
+        DESTKEYSTORE("destkeystore", "<keystore>", "destination.keystore.name"),
         DESTPROTECTED("destprotected", null, "destination.keystore.password.protected"),
-        DESTPROVIDERNAME("destprovidername", "<destprovidername>", "destination.keystore.provider.name"),
+        DESTPROVIDERNAME("destprovidername", "<name>", "destination.keystore.provider.name"),
         DESTSTOREPASS("deststorepass", "<arg>", "destination.keystore.password"),
-        DESTSTORETYPE("deststoretype", "<deststoretype>", "destination.keystore.type"),
-        DNAME("dname", "<dname>", "distinguished.name"),
+        DESTSTORETYPE("deststoretype", "<type>", "destination.keystore.type"),
+        DNAME("dname", "<name>", "distinguished.name"),
         EXT("ext", "<value>", "X.509.extension"),
-        FILEOUT("file", "<filename>", "output.file.name"),
-        FILEIN("file", "<filename>", "input.file.name"),
+        FILEOUT("file", "<file>", "output.file.name"),
+        FILEIN("file", "<file>", "input.file.name"),
         ID("id", "<id:reason>", "Serial.ID.of.cert.to.revoke"),
-        INFILE("infile", "<filename>", "input.file.name"),
-        KEYALG("keyalg", "<keyalg>", "key.algorithm.name"),
+        INFILE("infile", "<file>", "input.file.name"),
+        KEYALG("keyalg", "<alg>", "key.algorithm.name"),
         KEYPASS("keypass", "<arg>", "key.password"),
-        KEYSIZE("keysize", "<keysize>", "key.bit.size"),
+        KEYSIZE("keysize", "<size>", "key.bit.size"),
         KEYSTORE("keystore", "<keystore>", "keystore.name"),
         NEW("new", "<arg>", "new.password"),
         NOPROMPT("noprompt", null, "do.not.prompt"),
-        OUTFILE("outfile", "<filename>", "output.file.name"),
+        OUTFILE("outfile", "<file>", "output.file.name"),
         PROTECTED("protected", null, "password.through.protected.mechanism"),
-        PROVIDERARG("providerarg", "<arg>", "provider.argument"),
-        PROVIDERCLASS("providerclass", "<providerclass>", "provider.class.name"),
-        PROVIDERNAME("providername", "<providername>", "provider.name"),
-        PROVIDERPATH("providerpath", "<pathlist>", "provider.classpath"),
+        PROVIDERCLASS("providerclass", "<class>\n[-providerarg <arg>]", "provider.class.option"),
+        ADDPROVIDER("addprovider", "<name>\n[-providerarg <arg>]", "addprovider.option"),
+        PROVIDERNAME("providername", "<name>", "provider.name"),
+        PROVIDERPATH("providerpath", "<list>", "provider.classpath"),
         RFC("rfc", null, "output.in.RFC.style"),
-        SIGALG("sigalg", "<sigalg>", "signature.algorithm.name"),
-        SRCALIAS("srcalias", "<srcalias>", "source.alias"),
+        SIGALG("sigalg", "<alg>", "signature.algorithm.name"),
+        SRCALIAS("srcalias", "<alias>", "source.alias"),
         SRCKEYPASS("srckeypass", "<arg>", "source.key.password"),
-        SRCKEYSTORE("srckeystore", "<srckeystore>", "source.keystore.name"),
+        SRCKEYSTORE("srckeystore", "<keystore>", "source.keystore.name"),
         SRCPROTECTED("srcprotected", null, "source.keystore.password.protected"),
-        SRCPROVIDERNAME("srcprovidername", "<srcprovidername>", "source.keystore.provider.name"),
+        SRCPROVIDERNAME("srcprovidername", "<name>", "source.keystore.provider.name"),
         SRCSTOREPASS("srcstorepass", "<arg>", "source.keystore.password"),
-        SRCSTORETYPE("srcstoretype", "<srcstoretype>", "source.keystore.type"),
+        SRCSTORETYPE("srcstoretype", "<type>", "source.keystore.type"),
         SSLSERVER("sslserver", "<server[:port]>", "SSL.server.host.and.port"),
-        JARFILE("jarfile", "<filename>", "signed.jar.file"),
-        STARTDATE("startdate", "<startdate>", "certificate.validity.start.date.time"),
+        JARFILE("jarfile", "<file>", "signed.jar.file"),
+        STARTDATE("startdate", "<date>", "certificate.validity.start.date.time"),
         STOREPASS("storepass", "<arg>", "keystore.password"),
-        STORETYPE("storetype", "<storetype>", "keystore.type"),
+        STORETYPE("storetype", "<type>", "keystore.type"),
         TRUSTCACERTS("trustcacerts", null, "trust.certificates.from.cacerts"),
         V("v", null, "verbose.output"),
-        VALIDITY("validity", "<valDays>", "validity.number.of.days");
+        VALIDITY("validity", "<days>", "validity.number.of.days");
 
         final String name, arg, description;
         Option(String name, String arg, String description) {
@@ -344,8 +343,6 @@
         }
     };
 
-    private static final Class<?>[] PARAM_STRING = { String.class };
-
     private static final String NONE = "NONE";
     private static final String P11KEYSTORE = "PKCS11";
     private static final String P12KEYSTORE = "PKCS12";
@@ -549,10 +546,10 @@
                 jarfile = args[++i];
             } else if (collator.compare(flags, "-srckeystore") == 0) {
                 srcksfname = args[++i];
-            } else if ((collator.compare(flags, "-provider") == 0) ||
-                        (collator.compare(flags, "-providerclass") == 0)) {
-                if (providers == null) {
-                    providers = new HashSet<Pair <String, String>> (3);
+            } else if (collator.compare(flags, "-provider") == 0 ||
+                        collator.compare(flags, "-providerclass") == 0) {
+                if (providerClasses == null) {
+                    providerClasses = new HashSet<Pair <String, String>> (3);
                 }
                 String providerClass = args[++i];
                 String providerArg = null;
@@ -565,8 +562,25 @@
                         i += 2;
                     }
                 }
+                providerClasses.add(
+                        Pair.of(providerClass, providerArg));
+            } else if (collator.compare(flags, "-addprovider") == 0) {
+                if (providers == null) {
+                    providers = new HashSet<Pair <String, String>> (3);
+                }
+                String provider = args[++i];
+                String providerArg = null;
+
+                if (args.length > (i+1)) {
+                    flags = args[i+1];
+                    if (collator.compare(flags, "-providerarg") == 0) {
+                        if (args.length == (i+2)) errorNeedArgument(flags);
+                        providerArg = args[i+2];
+                        i += 2;
+                    }
+                }
                 providers.add(
-                        Pair.of(providerClass, providerArg));
+                        Pair.of(provider, providerArg));
             }
 
             /*
@@ -617,7 +631,6 @@
         return cmd != PRINTCERT && cmd != PRINTCERTREQ;
     }
 
-
     /**
      * Execute the commands.
      */
@@ -703,6 +716,20 @@
 
         // Try to load and install specified provider
         if (providers != null) {
+            for (Pair<String, String> provider : providers) {
+                try {
+                    KeyStoreUtil.loadProviderByName(
+                            provider.fst, provider.snd);
+                    if (debug) {
+                        System.out.println("loadProviderByName: " + provider.fst);
+                    }
+                } catch (IllegalArgumentException e) {
+                    throw new Exception(String.format(rb.getString(
+                            "provider.name.not.found"), provider.fst));
+                }
+            }
+        }
+        if (providerClasses != null) {
             ClassLoader cl = null;
             if (pathlist != null) {
                 String path = null;
@@ -717,30 +744,20 @@
             } else {
                 cl = ClassLoader.getSystemClassLoader();
             }
-
-            for (Pair <String, String> provider: providers) {
-                String provName = provider.fst;
-                Class<?> provClass;
-                if (cl != null) {
-                    provClass = cl.loadClass(provName);
-                } else {
-                    provClass = Class.forName(provName);
+            for (Pair<String, String> provider : providerClasses) {
+                try {
+                    KeyStoreUtil.loadProviderByClass(
+                            provider.fst, provider.snd, cl);
+                    if (debug) {
+                        System.out.println("loadProviderByClass: " + provider.fst);
+                    }
+                } catch (ClassCastException cce) {
+                    throw new Exception(String.format(rb.getString(
+                            "provclass.not.a.provider"), provider.fst));
+                } catch (IllegalArgumentException e) {
+                    throw new Exception(String.format(rb.getString(
+                            "provider.class.not.found"), provider.fst), e.getCause());
                 }
-
-                @SuppressWarnings("deprecation")
-                Object obj = provClass.newInstance();
-                if (!(obj instanceof Provider)) {
-                    MessageFormat form = new MessageFormat
-                        (rb.getString("provName.not.a.provider"));
-                    Object[] source = {provName};
-                    throw new Exception(form.format(source));
-                }
-                Provider p = (Provider) obj;
-                String provArg = provider.snd;
-                if (provArg != null) {
-                    p = p.configure(provArg);
-                }
-                Security.addProvider(p);
             }
         }
 
@@ -4132,27 +4149,40 @@
             System.err.println(rb.getString("Options."));
             System.err.println();
 
-            // Left and right sides of the options list
+            // Left and right sides of the options list. Both might
+            // contain "\n" and span multiple lines
             String[] left = new String[command.options.length];
             String[] right = new String[command.options.length];
 
-            // Check if there's an unknown option
-            boolean found = false;
-
             // Length of left side of options list
             int lenLeft = 0;
-            for (int j=0; j<left.length; j++) {
+
+            for (int j = 0; j < command.options.length; j++) {
                 Option opt = command.options[j];
                 left[j] = opt.toString();
-                if (opt.arg != null) left[j] += " " + opt.arg;
-                if (left[j].length() > lenLeft) {
-                    lenLeft = left[j].length();
+                if (opt.arg != null) {
+                    left[j] += " " + opt.arg;
+                }
+                String[] lefts = left[j].split("\n");
+                for (String s : lefts) {
+                    if (s.length() > lenLeft) {
+                        lenLeft = s.length();
+                    }
                 }
                 right[j] = rb.getString(opt.description);
             }
-            for (int j=0; j<left.length; j++) {
-                System.err.printf(" %-" + lenLeft + "s  %s\n",
-                        left[j], right[j]);
+            for (int j = 0; j < left.length; j++) {
+                String[] lefts = left[j].split("\n");
+                String[] rights = right[j].split("\n");
+                for (int i = 0; i < lefts.length && i < rights.length; i++) {
+                    String s1 = i < lefts.length ? lefts[i] : "";
+                    String s2 = i < rights.length ? rights[i] : "";
+                    if (i == 0) {
+                        System.err.printf(" %-" + lenLeft + "s  %s\n", s1, s2);
+                    } else {
+                        System.err.printf("   %-" + lenLeft + "s  %s\n", s1, s2);
+                    }
+                }
             }
             System.err.println();
             System.err.println(rb.getString(
--- a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Resources.java	Mon Jul 11 17:18:59 2016 -0700
+++ b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Resources.java	Tue Jul 12 09:41:49 2016 +0800
@@ -133,10 +133,16 @@
                 "do not prompt"}, //-noprompt
         {"password.through.protected.mechanism",
                 "password through protected mechanism"}, //-protected
-        {"provider.argument",
-                "provider argument"}, //-providerarg
-        {"provider.class.name",
-                "provider class name"}, //-providerclass
+
+        // The following 2 values should span 2 lines, the first for the
+        // option itself, the second for its -providerArg value.
+        {"addprovider.option",
+                "add security provider by name (e.g. SunPKCS11)\n" +
+                        "configure argument for -addprovider"}, //-addprovider
+        {"provider.class.option",
+                "add security provider by fully-qualified class name\n" +
+                        "configure argument for -providerclass"}, //-providerclass
+
         {"provider.name",
                 "provider name"}, //-providername
         {"provider.classpath",
@@ -209,7 +215,9 @@
         {"Illegal.startdate.value", "Illegal startdate value"},
         {"Validity.must.be.greater.than.zero",
                 "Validity must be greater than zero"},
-        {"provName.not.a.provider", "{0} not a provider"},
+        {"provclass.not.a.provider", "%s not a provider"},
+        {"provider.name.not.found", "Provider named \"%s\" not found"},
+        {"provider.class.not.found", "Provider \"%s\" not found"},
         {"Usage.error.no.command.provided", "Usage error: no command provided"},
         {"Source.keystore.file.exists.but.is.empty.", "Source keystore file exists, but is empty: "},
         {"Please.specify.srckeystore", "Please specify -srckeystore"},
--- a/jdk/src/java.base/share/conf/security/java.policy	Mon Jul 11 17:18:59 2016 -0700
+++ b/jdk/src/java.base/share/conf/security/java.policy	Tue Jul 12 09:41:49 2016 +0800
@@ -30,7 +30,8 @@
         permission java.security.SecurityPermission "putProviderProperty.OracleUcrypto";
         permission java.security.SecurityPermission "clearProviderProperties.OracleUcrypto";
         permission java.security.SecurityPermission "removeProviderProperty.OracleUcrypto";
-        permission java.io.FilePermission "${java.home}/conf/security/ucrypto-solaris.cfg", "read";
+        // Needed for reading Ucrypto config file
+        permission java.io.FilePermission "<<ALL FILES>>", "read";
 };
 
 grant codeBase "jrt:/java.sql" {
--- a/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java	Mon Jul 11 17:18:59 2016 -0700
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java	Tue Jul 12 09:41:49 2016 +0800
@@ -235,13 +235,14 @@
 
     @Override
     public Provider configure(String configArg) throws InvalidParameterException {
-        // default policy entry only grants read access to default config
-        if (!defConfigName.equals(configArg)) {
-            throw new InvalidParameterException("Ucrypto provider can only be " +
-                "configured with default configuration file");
+        try {
+            init(configArg);
+        } catch (UcryptoException ue) {
+            InvalidParameterException ipe =
+                    new InvalidParameterException("Error using " + configArg);
+            ipe.initCause(ue.getCause());
+            throw ipe;
         }
-        // re-read the config
-        init(defConfigName);
         return this;
     }
 
--- a/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java	Mon Jul 11 17:18:59 2016 -0700
+++ b/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java	Tue Jul 12 09:41:49 2016 +0800
@@ -118,7 +118,8 @@
     boolean protectedPath; // protected authentication path
     String storetype; // keystore type
     String providerName; // provider name
-    Vector<String> providers = null; // list of providers
+    List<String> providers = null; // list of provider names
+    List<String> providerClasses = null; // list of provider classes
     // arguments for provider constructors
     HashMap<String,String> providerArgs = new HashMap<>();
     char[] keypass; // private key password
@@ -174,30 +175,36 @@
 
             // Try to load and install the specified providers
             if (providers != null) {
-                ClassLoader cl = ClassLoader.getSystemClassLoader();
-                Enumeration<String> e = providers.elements();
-                while (e.hasMoreElements()) {
-                    String provName = e.nextElement();
-                    Class<?> provClass;
-                    if (cl != null) {
-                        provClass = cl.loadClass(provName);
-                    } else {
-                        provClass = Class.forName(provName);
+                for (String provName: providers) {
+                    try {
+                        KeyStoreUtil.loadProviderByName(provName,
+                                providerArgs.get(provName));
+                        if (debug) {
+                            System.out.println("loadProviderByName: " + provName);
+                        }
+                    } catch (IllegalArgumentException e) {
+                        throw new Exception(String.format(rb.getString(
+                                "provider.name.not.found"), provName));
                     }
+                }
+            }
 
-                    Object obj = provClass.newInstance();
-                    if (!(obj instanceof Provider)) {
-                        MessageFormat form = new MessageFormat(rb.getString
-                            ("provName.not.a.provider"));
-                        Object[] source = {provName};
-                        throw new Exception(form.format(source));
+            if (providerClasses != null) {
+                ClassLoader cl = ClassLoader.getSystemClassLoader();
+                for (String provClass: providerClasses) {
+                    try {
+                        KeyStoreUtil.loadProviderByClass(provClass,
+                                providerArgs.get(provClass), cl);
+                        if (debug) {
+                            System.out.println("loadProviderByClass: " + provClass);
+                        }
+                    } catch (ClassCastException cce) {
+                        throw new Exception(String.format(rb.getString(
+                                "provclass.not.a.provider"), provClass));
+                    } catch (IllegalArgumentException e) {
+                        throw new Exception(String.format(rb.getString(
+                                "provider.class.not.found"), provClass), e.getCause());
                     }
-                    Provider p = (Provider) obj;
-                    String provArg = providerArgs.get(provName);
-                    if (provArg != null) {
-                        p = p.configure(provArg);
-                    }
-                    Security.addProvider(p);
                 }
             }
 
@@ -335,11 +342,26 @@
             } else if (collator.compare(flags, "-providerName") ==0) {
                 if (++n == args.length) usageNoArg();
                 providerName = args[n];
-            } else if ((collator.compare(flags, "-provider") == 0) ||
-                        (collator.compare(flags, "-providerClass") == 0)) {
+            } else if (collator.compare(flags, "-provider") == 0 ||
+                        collator.compare(flags, "-providerClass") == 0) {
+                if (++n == args.length) usageNoArg();
+                if (providerClasses == null) {
+                    providerClasses = new ArrayList<>(3);
+                }
+                providerClasses.add(args[n]);
+
+                if (args.length > (n+1)) {
+                    flags = args[n+1];
+                    if (collator.compare(flags, "-providerArg") == 0) {
+                        if (args.length == (n+2)) usageNoArg();
+                        providerArgs.put(args[n], args[n+2]);
+                        n += 2;
+                    }
+                }
+            } else if (collator.compare(flags, "-addprovider") == 0) {
                 if (++n == args.length) usageNoArg();
                 if (providers == null) {
-                    providers = new Vector<String>(3);
+                    providers = new ArrayList<>(3);
                 }
                 providers.add(args[n]);
 
@@ -584,9 +606,14 @@
                 (".providerName.name.provider.name"));
         System.out.println();
         System.out.println(rb.getString
-                (".providerClass.class.name.of.cryptographic.service.provider.s"));
+                (".add.provider.option"));
         System.out.println(rb.getString
-                (".providerArg.arg.master.class.file.and.constructor.argument"));
+                (".providerArg.option.1"));
+        System.out.println();
+        System.out.println(rb.getString
+                (".providerClass.option"));
+        System.out.println(rb.getString
+                (".providerArg.option.2"));
         System.out.println();
         System.out.println(rb.getString
                 (".strict.treat.warnings.as.errors"));
--- a/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java	Mon Jul 11 17:18:59 2016 -0700
+++ b/jdk/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java	Tue Jul 12 09:41:49 2016 +0800
@@ -40,8 +40,9 @@
         {"6SPACE", "      "},
         {"COMMA", ", "},
 
-        {"provName.not.a.provider", "{0} not a provider"},
-        {"signerClass.is.not.a.signing.mechanism", "{0} is not a signing mechanism"},
+        {"provclass.not.a.provider", "%s not a provider"},
+        {"provider.name.not.found", "Provider named \"%s\" not found"},
+        {"provider.class.not.found", "Provider \"%s\" not found"},
         {"jarsigner.error.", "jarsigner error: "},
         {"Illegal.option.", "Illegal option: "},
         {"This.option.is.deprecated", "This option is deprecated: "},
@@ -105,10 +106,14 @@
                 "[-protected]                keystore has protected authentication path"},
         {".providerName.name.provider.name",
                 "[-providerName <name>]      provider name"},
-        {".providerClass.class.name.of.cryptographic.service.provider.s",
-                "[-providerClass <class>     name of cryptographic service provider's"},
-        {".providerArg.arg.master.class.file.and.constructor.argument",
-                "  [-providerArg <arg>]] ... master class file and constructor argument"},
+        {".add.provider.option",
+                "[-addprovider <name>        add security provider by name (e.g. SunPKCS11)"},
+        {".providerArg.option.1",
+                "  [-providerArg <arg>]] ... configure argument for -addprovider"},
+        {".providerClass.option",
+                "[-providerClass <class>     add security provider by fully-qualified class name"},
+        {".providerArg.option.2",
+                "  [-providerArg <arg>]] ... configure argument for -providerClass"},
         {".strict.treat.warnings.as.errors",
                 "[-strict]                   treat warnings as errors"},
         {".conf.url.specify.a.pre.configured.options.file",
--- a/jdk/test/sun/security/pkcs11/fips/ImportKeyStore.java	Mon Jul 11 17:18:59 2016 -0700
+++ b/jdk/test/sun/security/pkcs11/fips/ImportKeyStore.java	Tue Jul 12 09:41:49 2016 +0800
@@ -37,7 +37,7 @@
 modutil -create -dbdir .
 modutil -changepw "NSS Internal PKCS #11 Module" -dbdir .
 
-$JHOME/bin/keytool -list -storetype PKCS11 -providerclass sun.security.pkcs11.SunPKCS11 -providerarg "--name=NSS\nnssSecmodDirectory=." -v -storepass test12
+$JHOME/bin/keytool -list -storetype PKCS11 -addprovider SunPKCS11 -providerarg "--name=NSS\nnssSecmodDirectory=." -v -storepass test12
 
 modutil -fips true -dbdir .
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/AltProvider.java	Tue Jul 12 09:41:49 2016 +0800
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4906940 8130302
+ * @summary -providerPath, -providerClass, -addprovider, and -providerArg
+ * @library /lib/testlibrary /test/lib/share/classes
+ * @modules java.base/jdk.internal.misc
+ */
+
+import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+import jdk.testlibrary.JarUtils;
+
+import java.nio.file.*;
+
+public class AltProvider {
+
+    private static final String TEST_SRC =
+            Paths.get(System.getProperty("test.src")).toString();
+
+    private static final Path MOD_SRC_DIR = Paths.get(TEST_SRC, "alt");
+    private static final Path MOD_DEST_DIR = Paths.get("mods");
+
+    private static final String ktCommand = "-keystore x.jks " +
+            "-storepass changeit -storetype dummyks -list -debug";
+
+    private static final String jsCommand = "-keystore x.jks " +
+            "-storepass changeit -storetype dummyks -debug x.jar x";
+
+    public static void main(String[] args) throws Throwable {
+
+        // Compile the provider
+        CompilerUtils.compile(
+                MOD_SRC_DIR, MOD_DEST_DIR,
+                "-modulesourcepath",
+                MOD_SRC_DIR.toString());
+
+        // Create a keystore
+        tool("keytool", "-keystore x.jks -storetype jks -genkeypair" +
+                " -storepass changeit -keypass changeit -alias x -dname CN=X")
+                .shouldHaveExitValue(0);
+
+        // Create a jar file
+        JarUtils.createJar("x.jar", "x.jks");
+
+        // Test starts here
+
+        // Without new provider
+        testBoth("", 1, "DUMMYKS not found");
+
+        // legacy use (-providerPath only supported by keytool)
+        testKeytool("-providerPath mods/test.dummy " +
+                "-providerClass org.test.dummy.DummyProvider -providerArg full",
+                0, "loadProviderByClass: org.test.dummy.DummyProvider");
+
+        // legacy, on classpath
+        testBoth("-J-cp -Jmods/test.dummy " +
+                "-providerClass org.test.dummy.DummyProvider -providerArg full",
+                0, "loadProviderByClass: org.test.dummy.DummyProvider");
+
+        // Wrong name
+        testBoth("-J-cp -Jmods/test.dummy " +
+                "-providerClass org.test.dummy.Dummy -providerArg full",
+                1, "Provider \"org.test.dummy.Dummy\" not found");
+
+        // Not a provider name
+        testBoth("-J-cp -Jmods/test.dummy " +
+                "-providerClass java.lang.Object -providerArg full",
+                1, "java.lang.Object not a provider");
+
+        // without arg
+        testBoth("-J-cp -Jmods/test.dummy " +
+                "-providerClass org.test.dummy.DummyProvider",
+                1, "DUMMYKS not found");
+
+        // old -provider still works
+        testBoth("-J-cp -Jmods/test.dummy " +
+                "-provider org.test.dummy.DummyProvider -providerArg full",
+                0, "loadProviderByClass: org.test.dummy.DummyProvider");
+
+        // name in a module
+        testBoth("-J-mp -Jmods " +
+                "-addprovider Dummy -providerArg full",
+                0, "loadProviderByName: Dummy");
+
+        // -providerClass does not work
+        testBoth("-J-mp -Jmods " +
+                "-providerClass org.test.dummy.DummyProvider -providerArg full",
+                1, "Provider \"org.test.dummy.DummyProvider\" not found");
+
+        // -addprovider with class does not work
+        testBoth("-J-mp -Jmods " +
+                "-addprovider org.test.dummy.DummyProvider -providerArg full",
+                1, "Provider named \"org.test.dummy.DummyProvider\" not found");
+
+        // -addprovider without arg does not work
+        testBoth("-J-mp -Jmods " +
+                "-addprovider Dummy",
+                1, "DUMMYKS not found");
+    }
+
+    // Test both tools with the same extra options
+    private static void testBoth(String args, int exitValue, String contains)
+            throws Throwable {
+        testKeytool(args, exitValue, contains);
+        testJarsigner(args, exitValue, contains);
+    }
+
+    // Test keytool with extra options and check exitValue and output
+    private static void testKeytool(String args, int exitValue, String contains)
+            throws Throwable {
+        tool("keytool", ktCommand + " " + args)
+                .shouldHaveExitValue(exitValue)
+                .shouldContain(contains);
+    }
+
+    // Test jarsigner with extra options and check exitValue and output
+    private static void testJarsigner(String args, int exitValue, String contains)
+            throws Throwable {
+        tool("jarsigner", jsCommand + " " + args)
+                .shouldHaveExitValue(exitValue)
+                .shouldContain(contains);
+    }
+
+    // Launch a tool with args (space separated string)
+    private static OutputAnalyzer tool(String tool, String args)
+            throws Throwable {
+        JDKToolLauncher l = JDKToolLauncher.createUsingTestJDK(tool);
+        for (String a: args.split("\\s+")) {
+            if (a.startsWith("-J")) {
+                l.addVMArg(a.substring(2));
+            } else {
+                l.addToolArg(a);
+            }
+        }
+        return ProcessTools.executeCommand(l.getCommand());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/alt/test.dummy/module-info.java	Tue Jul 12 09:41:49 2016 +0800
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module test.dummy {
+    provides java.security.Provider with org.test.dummy.DummyProvider;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/alt/test.dummy/org/test/dummy/DummyProvider.java	Tue Jul 12 09:41:49 2016 +0800
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2004, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.test.dummy;
+
+import java.security.*;
+
+public class DummyProvider extends Provider {
+    public DummyProvider() {
+        super("Dummy", 0.1, "Dummy Provider with nothing");
+    }
+
+    @Override
+    public Provider configure(String configArg) {
+        return new DummyProvider(configArg);
+    }
+
+    private DummyProvider(String arg) {
+        super("Dummy", 0.2, "Dummy Provider with " + arg);
+        //
+        // KeyStore
+        //
+        put("KeyStore.DummyKS", "sun.security.provider.JavaKeyStore$JKS");
+
+        //
+        // Signature engines
+        //
+        put("Signature.SHA1withDSA",
+            "sun.security.provider.DSA$SHA1withDSA");
+        put("Alg.Alias.Signature.DSA", "SHA1withDSA");
+
+        //
+        // Key Pair Generator engines
+        //
+        put("KeyPairGenerator.DSA",
+            "sun.security.provider.DSAKeyPairGenerator");
+
+        //
+        // Digest engines
+        //
+        put("MessageDigest.SHA", "sun.security.provider.SHA");
+        put("Alg.Alias.MessageDigest.SHA1", "SHA");
+
+        //
+        // Algorithm Parameter Generator engines
+        //
+        put("AlgorithmParameterGenerator.DSA",
+            "sun.security.provider.DSAParameterGenerator");
+
+        //
+        // Algorithm Parameter engines
+        //
+        put("AlgorithmParameters.DSA",
+            "sun.security.provider.DSAParameters");
+
+        //
+        // Key factories
+        //
+        put("KeyFactory.DSA", "sun.security.provider.DSAKeyFactory");
+
+        //
+        // Certificate factories
+        //
+        put("CertificateFactory.X.509",
+            "sun.security.provider.X509Factory");
+        put("Alg.Alias.CertificateFactory.X509", "X.509");
+    }
+}
--- a/jdk/test/sun/security/tools/keytool/AltProviderPath.sh	Mon Jul 11 17:18:59 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-#
-# Copyright (c) 2004, 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.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-# @test
-# @bug 4906940
-# @summary Add -providerPath option for keytool allowing one to specify
-#          an additional classpath to search for providers.
-# @author Andrew Fan
-#
-# @run build DummyProvider
-# @run shell AltProviderPath.sh
-# set a few environment variables so that the shell-script can run stand-alone
-# in the source directory
-if [ "${TESTSRC}" = "" ] ; then
-  TESTSRC="."
-fi
-if [ "${TESTCLASSES}" = "" ] ; then
-  TESTCLASSES="."
-fi
-if [ "${TESTJAVA}" = "" ] ; then
-  echo "TESTJAVA not set.  Test cannot execute."
-  echo "FAILED!!!"
-  exit 1
-fi
-
-# set platform-dependent variables
-OS=`uname -s`
-case "$OS" in
-  SunOS | Linux | Darwin | AIX )
-    NULL=/dev/null
-    PS=":"
-    FS="/"
-    ;;
-  CYGWIN* )
-    NULL=/dev/null
-    PS=";"
-    FS="/"
-    ;;
-  Windows_* )
-    NULL=NUL
-    PS=";"
-    FS="\\"
-    ;;
-  * )
-    echo "Unrecognized operating system!"
-    exit 1;
-    ;;
-esac
-
-# the test code
-#genkey
-${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -genkey -v -alias dummyTestCA \
-    -keyalg "RSA" -keysize 1024 -sigalg "ShA1WithRSA" \
-    -dname "cn=Dummy Test CA, ou=JSN, o=JavaSoft, c=US" -validity 3650 \
-    -keypass storepass -keystore keystoreCA.dks -storepass storepass \
-    -storetype "dummyks" -provider "org.test.dummy.DummyProvider" \
-    -providerPath ${TESTCLASSES}
-
-if [ $? -ne 0 ]; then
-    exit 1
-fi
-
-#Change keystore password
-${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -storepasswd -new storepass2 \
-    -keystore keystoreCA.dks -storetype "dummyks" -storepass storepass \
-    -provider "org.test.dummy.DummyProvider" -providerPath ${TESTCLASSES}
-
-if [ $? -ne 0 ]; then
-    exit 1
-fi
-
-
-#Change keystore key password
-${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -keypasswd -alias "dummyTestCA" \
-    -keypass storepass -new keypass -keystore keystoreCA.dks \
-    -storetype "dummyks" -storepass storepass2 \
-    -provider "org.test.dummy.DummyProvider" -providerPath ${TESTCLASSES}
-
-if [ $? -ne 0 ]; then
-    exit 1
-fi
-
-#Export certificate
-${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -v -export -rfc -alias "dummyTestCA" \
-    -file "dummyTestCA.der" -keystore keystoreCA.dks -storetype "dummyks" \
-    -storepass storepass2 -provider "org.test.dummy.DummyProvider" \
-    -providerPath ${TESTCLASSES}
-
-if [ $? -ne 0 ]; then
-    exit 1
-fi
-
-#list keystore
-${TESTJAVA}${FS}bin${FS}keytool ${TESTTOOLVMOPTS} -v -list -keystore keystoreCA.dks \
-    -storetype "dummyks" -storepass storepass2 \
-    -provider "org.test.dummy.DummyProvider" -providerPath ${TESTCLASSES}
-
-if [ $? -ne 0 ]; then
-    exit 1
-fi
-
-exit 0
--- a/jdk/test/sun/security/tools/keytool/DummyProvider.java	Mon Jul 11 17:18:59 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2004, 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.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- *
- *
- * @bug 4906490
- * @summary Dummy security service provider.
- *          It is cited by the AltProviderPath.sh script.
- */
-package org.test.dummy;
-
-import java.util.*;
-import java.security.*;
-
-public class DummyProvider extends Provider {
-    public DummyProvider() {
-        super("Dummy", 0.1, "Dummy Provider");
-
-        //
-        // KeyStore
-        //
-        put("KeyStore.DummyKS", "sun.security.provider.JavaKeyStore$JKS");
-
-        //
-        // Signature engines
-        //
-        put("Signature.SHA1withDSA",
-            "sun.security.provider.DSA$SHA1withDSA");
-        put("Alg.Alias.Signature.DSA", "SHA1withDSA");
-
-        //
-        // Key Pair Generator engines
-        //
-        put("KeyPairGenerator.DSA",
-            "sun.security.provider.DSAKeyPairGenerator");
-
-        //
-        // Digest engines
-        //
-        put("MessageDigest.SHA", "sun.security.provider.SHA");
-        put("Alg.Alias.MessageDigest.SHA1", "SHA");
-
-        //
-        // Algorithm Parameter Generator engines
-        //
-        put("AlgorithmParameterGenerator.DSA",
-            "sun.security.provider.DSAParameterGenerator");
-
-        //
-        // Algorithm Parameter engines
-        //
-        put("AlgorithmParameters.DSA",
-            "sun.security.provider.DSAParameters");
-
-        //
-        // Key factories
-        //
-        put("KeyFactory.DSA", "sun.security.provider.DSAKeyFactory");
-
-        //
-        // Certificate factories
-        //
-        put("CertificateFactory.X.509",
-            "sun.security.provider.X509Factory");
-        put("Alg.Alias.CertificateFactory.X509", "X.509");
-    }
-}
--- a/jdk/test/sun/security/tools/keytool/KeyToolTest.java	Mon Jul 11 17:18:59 2016 -0700
+++ b/jdk/test/sun/security/tools/keytool/KeyToolTest.java	Tue Jul 12 09:41:49 2016 +0800
@@ -82,8 +82,9 @@
 
     static final String NSS_P11_ARG =
             "-keystore NONE -storetype PKCS11 -providerName SunPKCS11-nss " +
-            "-providerClass sun.security.pkcs11.SunPKCS11 " +
+            "-addprovider SunPKCS11 " +
             "-providerArg p11-nss.txt ";
+    // Use -providerClass here, to confirm it still works for SunPKCS11.
     static final String NSS_SRC_P11_ARG =
             "-srckeystore NONE -srcstoretype PKCS11 " +
             "-srcproviderName SunPKCS11-nss " +
@@ -91,12 +92,12 @@
             "-providerArg p11-nss.txt ";
     static final String NZZ_P11_ARG =
             "-keystore NONE -storetype PKCS11 -providerName SunPKCS11-nzz " +
-            "-providerClass sun.security.pkcs11.SunPKCS11 " +
+            "-addprovider SunPKCS11 " +
             "-providerArg p11-nzz.txt ";
     static final String NZZ_SRC_P11_ARG =
             "-srckeystore NONE -srcstoretype PKCS11 " +
             "-srcproviderName SunPKCS11-nzz " +
-            "-providerClass sun.security.pkcs11.SunPKCS11 " +
+            "-addprovider SunPKCS11 " +
             "-providerArg p11-nzz.txt ";
     static final String SUN_P11_ARG = "-keystore NONE -storetype PKCS11 ";
     static final String SUN_SRC_P11_ARG =
@@ -1715,9 +1716,9 @@
         //  14. keytool -printcert -file cert
         testOK("", "-printcert -file cert -keystore x.jks -storetype JKS");
         remove("cert");
-        //  15. keytool -list -storepass password -provider sun.security.provider.Sun
+        //  15. keytool -list -storepass password -addprovider SUN
         testOK("", "-list -storepass password" +
-                " -provider sun.security.provider.Sun" +
+                " -addprovider SUN" +
                 " -keystore x.jks -storetype JKS");
 
         //Error tests
--- a/jdk/test/sun/security/tools/keytool/i18n.html	Mon Jul 11 17:18:59 2016 -0700
+++ b/jdk/test/sun/security/tools/keytool/i18n.html	Tue Jul 12 09:41:49 2016 +0800
@@ -50,7 +50,7 @@
 <li>	keytool -import -v -file /tmp/cert -storepass password
 	Check error (Certificate reply and cert are the same)
 <li>	keytool -printcert -file /tmp/cert
-<li>	keytool -list -storepass password -provider sun.security.provider.Sun
+<li>	keytool -list -storepass password -addprovider SUN
 </ol>
 
 Error tests
@@ -93,19 +93,19 @@
 <ol>
 <li>	sccs edit cert8.db key3.db
 
-<li>	keytool -keystore NONE -storepass test12 -storetype PKCS11 -providerName SunPKCS11-nss -providerClass sun.security.pkcs11.SunPKCS11 -providerArg p11-nss.txt -genkey -alias genkey -dname cn=genkey -keysize 512 -keyalg rsa
-<li>	keytool -keystore NONE -storepass test12 -storetype PKCS11 -providerName SunPKCS11-nss -providerClass sun.security.pkcs11.SunPKCS11 -providerArg p11-nss.txt -list
-<li>	keytool -keystore NONE -storepass test12 -storetype PKCS11 -providerName SunPKCS11-nss -providerClass sun.security.pkcs11.SunPKCS11 -providerArg p11-nss.txt -list -alias genkey
-<li>	keytool -keystore NONE -storepass test12 -storetype PKCS11 -providerName SunPKCS11-nss -providerClass sun.security.pkcs11.SunPKCS11 -providerArg p11-nss.txt -certreq -alias genkey -file genkey.certreq
-<li>	keytool -keystore NONE -storepass test12 -storetype PKCS11 -providerName SunPKCS11-nss -providerClass sun.security.pkcs11.SunPKCS11 -providerArg p11-nss.txt -export -alias genkey -file genkey.cert
+<li>	keytool -keystore NONE -storepass test12 -storetype PKCS11 -providerName SunPKCS11-nss -addprovider SunPKCS11 -providerArg p11-nss.txt -genkey -alias genkey -dname cn=genkey -keysize 512 -keyalg rsa
+<li>	keytool -keystore NONE -storepass test12 -storetype PKCS11 -providerName SunPKCS11-nss -addprovider SunPKCS11 -providerArg p11-nss.txt -list
+<li>	keytool -keystore NONE -storepass test12 -storetype PKCS11 -providerName SunPKCS11-nss -addprovider SunPKCS11 -providerArg p11-nss.txt -list -alias genkey
+<li>	keytool -keystore NONE -storepass test12 -storetype PKCS11 -providerName SunPKCS11-nss -addprovider SunPKCS11 -providerArg p11-nss.txt -certreq -alias genkey -file genkey.certreq
+<li>	keytool -keystore NONE -storepass test12 -storetype PKCS11 -providerName SunPKCS11-nss -addprovider SunPKCS11 -providerArg p11-nss.txt -export -alias genkey -file genkey.cert
 <li>	keytool -printcert -file genkey.cert
-<li>	keytool -keystore NONE -storepass test12 -storetype PKCS11 -providerName SunPKCS11-nss -providerClass sun.security.pkcs11.SunPKCS11 -providerArg p11-nss.txt -selfcert -alias genkey -dname cn=selfCert
+<li>	keytool -keystore NONE -storepass test12 -storetype PKCS11 -providerName SunPKCS11-nss -addprovider SunPKCS11 -providerArg p11-nss.txt -selfcert -alias genkey -dname cn=selfCert
 
-<li>	keytool -keystore NONE -storepass test12 -storetype PKCS11 -providerName SunPKCS11-nss -providerClass sun.security.pkcs11.SunPKCS11 -providerArg p11-nss.txt -list -alias genkey -v
+<li>	keytool -keystore NONE -storepass test12 -storetype PKCS11 -providerName SunPKCS11-nss -addprovider SunPKCS11 -providerArg p11-nss.txt -list -alias genkey -v
 (check that cert subject DN is [cn=selfCert])
 
-<li>	keytool -keystore NONE -storepass test12 -storetype PKCS11 -providerName SunPKCS11-nss -providerClass sun.security.pkcs11.SunPKCS11 -providerArg p11-nss.txt -delete -alias genkey
-<li>	keytool -keystore NONE -storepass test12 -storetype PKCS11 -providerName SunPKCS11-nss -providerClass sun.security.pkcs11.SunPKCS11 -providerArg p11-nss.txt -list
+<li>	keytool -keystore NONE -storepass test12 -storetype PKCS11 -providerName SunPKCS11-nss -addprovider SunPKCS11 -providerArg p11-nss.txt -delete -alias genkey
+<li>	keytool -keystore NONE -storepass test12 -storetype PKCS11 -providerName SunPKCS11-nss -addprovider SunPKCS11 -providerArg p11-nss.txt -list
 (check for empty database listing)
 
 <li>	sccs unedit cert8.db key3.db