src/java.security.sasl/share/classes/javax/security/sasl/Sasl.java

Print this page
7191662: JCE providers should be located via ServiceLoader

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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

@@ -31,11 +31,14 @@
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
 import java.util.HashSet;
 import java.util.Collections;
+import java.security.InvalidParameterException;
+import java.security.NoSuchAlgorithmException;
 import java.security.Provider;
+import java.security.Provider.Service;
 import java.security.Security;
 
 /**
  * A static class for creating SASL clients and servers.
  *<p>

@@ -358,30 +361,31 @@
         Map<String,?> props,
         CallbackHandler cbh) throws SaslException {
 
         SaslClient mech = null;
         SaslClientFactory fac;
-        String className;
+        Service service;
         String mechName;
 
         for (int i = 0; i < mechanisms.length; i++) {
             if ((mechName=mechanisms[i]) == null) {
                 throw new NullPointerException(
                     "Mechanism name cannot be null");
             } else if (mechName.length() == 0) {
                 continue;
             }
-            String mechFilter = "SaslClientFactory." + mechName;
-            Provider[] provs = Security.getProviders(mechFilter);
-            for (int j = 0; provs != null && j < provs.length; j++) {
-                className = provs[j].getProperty(mechFilter);
-                if (className == null) {
-                    // Case is ignored
+            String type = "SaslClientFactory";
+            Provider[] provs = Security.getProviders(type + "." + mechName);
+            if (provs != null) {
+                for (Provider p : provs) {
+                    service = p.getService(type, mechName);
+                    if (service == null) {
+                        // no such service exists
                     continue;
                 }
 
-                fac = (SaslClientFactory) loadFactory(provs[j], className);
+                    fac = (SaslClientFactory) loadFactory(service);
                 if (fac != null) {
                     mech = fac.createSaslClient(
                         new String[]{mechanisms[i]}, authorizationId,
                         protocol, serverName, props, cbh);
                     if (mech != null) {

@@ -388,15 +392,15 @@
                         return mech;
                     }
                 }
             }
         }
-
+        }
         return null;
     }
 
-    private static Object loadFactory(Provider p, String className)
+    private static Object loadFactory(Service service)
         throws SaslException {
         try {
             /*
              * Load the implementation class with the same class loader
              * that was used to load the provider.

@@ -404,22 +408,13 @@
              * caller's class loader must be the same as or an ancestor of
              * the class loader being returned. Otherwise, the caller must
              * have "getClassLoader" permission, or a SecurityException
              * will be thrown.
              */
-            ClassLoader cl = p.getClass().getClassLoader();
-            Class<?> implClass;
-            implClass = Class.forName(className, true, cl);
-            return implClass.newInstance();
-        } catch (ClassNotFoundException e) {
-            throw new SaslException("Cannot load class " + className, e);
-        } catch (InstantiationException e) {
-            throw new SaslException("Cannot instantiate class " + className, e);
-        } catch (IllegalAccessException e) {
-            throw new SaslException("Cannot access class " + className, e);
-        } catch (SecurityException e) {
-            throw new SaslException("Cannot access class " + className, e);
+            return service.newInstance(null);
+        } catch (InvalidParameterException | NoSuchAlgorithmException e) {
+            throw new SaslException("Cannot instantiate service " + service, e);
         }
     }
 
 
     /**

@@ -501,36 +496,37 @@
                     javax.security.auth.callback.CallbackHandler cbh)
         throws SaslException {
 
         SaslServer mech = null;
         SaslServerFactory fac;
-        String className;
+        Service service;
 
         if (mechanism == null) {
             throw new NullPointerException("Mechanism name cannot be null");
         } else if (mechanism.length() == 0) {
             return null;
         }
 
-        String mechFilter = "SaslServerFactory." + mechanism;
-        Provider[] provs = Security.getProviders(mechFilter);
-        for (int j = 0; provs != null && j < provs.length; j++) {
-            className = provs[j].getProperty(mechFilter);
-            if (className == null) {
+        String type = "SaslServerFactory";
+        Provider[] provs = Security.getProviders(type + "." + mechanism);
+        if (provs != null) {
+            for (Provider p : provs) {
+                service = p.getService(type, mechanism);
+                if (service == null) {
                 throw new SaslException("Provider does not support " +
-                    mechFilter);
+                        mechanism + " " + type);
             }
-            fac = (SaslServerFactory) loadFactory(provs[j], className);
+                fac = (SaslServerFactory) loadFactory(service);
             if (fac != null) {
                 mech = fac.createSaslServer(
                     mechanism, protocol, serverName, props, cbh);
                 if (mech != null) {
                     return mech;
                 }
             }
         }
-
+        }
         return null;
     }
 
     /**
      * Gets an enumeration of known factories for producing {@code SaslClient}.

@@ -580,42 +576,27 @@
         if ((serviceName == null) || (serviceName.length() == 0) ||
             (serviceName.endsWith("."))) {
             return result;
         }
 
-
-        Provider[] providers = Security.getProviders();
-        HashSet<String> classes = new HashSet<String>();
+        Provider[] provs = Security.getProviders();
         Object fac;
 
-        for (int i = 0; i < providers.length; i++) {
-            classes.clear();
+        for (Provider p : provs) {
 
-            // Check the keys for each provider.
-            for (Enumeration<Object> e = providers[i].keys(); e.hasMoreElements(); ) {
-                String currentKey = (String)e.nextElement();
-                if (currentKey.startsWith(serviceName)) {
-                    // We should skip the currentKey if it contains a
-                    // whitespace. The reason is: such an entry in the
-                    // provider property contains attributes for the
-                    // implementation of an algorithm. We are only interested
-                    // in entries which lead to the implementation
-                    // classes.
-                    if (currentKey.indexOf(' ') < 0) {
-                        String className = providers[i].getProperty(currentKey);
-                        if (!classes.contains(className)) {
-                            classes.add(className);
+            Iterator<Service> iter = p.getServices().iterator();
+            while (iter.hasNext()) {
+                Service s = iter.next();
+                if (s.getType().equals(serviceName)) {
                             try {
-                                fac = loadFactory(providers[i], className);
+                        fac = loadFactory(s);
                                 if (fac != null) {
                                     result.add(fac);
                                 }
-                            }catch (Exception ignore) {
+                    } catch (Exception ignore) {
                             }
                         }
-                    }
-                }
             }
         }
         return Collections.unmodifiableSet(result);
     }
 }