1 /* 2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.security.jca; 27 28 import java.util.*; 29 30 import java.security.*; 31 import java.security.Provider.Service; 32 33 /** 34 * Collection of utility methods to facilitate implementing getInstance() 35 * methods in the JCA/JCE/JSSE/... framework. 36 * 37 * @author Andreas Sterbenz 38 * @since 1.5 39 */ 40 public class GetInstance { 41 GetInstance()42 private GetInstance() { 43 // empty 44 } 45 46 /** 47 * Static inner class representing a newly created instance. 48 */ 49 public static final class Instance { 50 // public final fields, access directly without accessors 51 public final Provider provider; 52 public final Object impl; Instance(Provider provider, Object impl)53 private Instance(Provider provider, Object impl) { 54 this.provider = provider; 55 this.impl = impl; 56 } 57 // Return Provider and implementation as an array as used in the 58 // old Security.getImpl() methods. toArray()59 public Object[] toArray() { 60 return new Object[] {impl, provider}; 61 } 62 } 63 getService(String type, String algorithm)64 public static Service getService(String type, String algorithm) 65 throws NoSuchAlgorithmException { 66 ProviderList list = Providers.getProviderList(); 67 Service s = list.getService(type, algorithm); 68 if (s == null) { 69 throw new NoSuchAlgorithmException 70 (algorithm + " " + type + " not available"); 71 } 72 return s; 73 } 74 getService(String type, String algorithm, String provider)75 public static Service getService(String type, String algorithm, 76 String provider) throws NoSuchAlgorithmException, 77 NoSuchProviderException { 78 if ((provider == null) || (provider.length() == 0)) { 79 throw new IllegalArgumentException("missing provider"); 80 } 81 Provider p = Providers.getProviderList().getProvider(provider); 82 if (p == null) { 83 throw new NoSuchProviderException("no such provider: " + provider); 84 } 85 Service s = p.getService(type, algorithm); 86 if (s == null) { 87 throw new NoSuchAlgorithmException("no such algorithm: " 88 + algorithm + " for provider " + provider); 89 } 90 return s; 91 } 92 getService(String type, String algorithm, Provider provider)93 public static Service getService(String type, String algorithm, 94 Provider provider) throws NoSuchAlgorithmException { 95 if (provider == null) { 96 throw new IllegalArgumentException("missing provider"); 97 } 98 Service s = provider.getService(type, algorithm); 99 if (s == null) { 100 throw new NoSuchAlgorithmException("no such algorithm: " 101 + algorithm + " for provider " + provider.getName()); 102 } 103 return s; 104 } 105 106 /** 107 * Return a List of all the available Services that implement 108 * (type, algorithm). Note that the list is initialized lazily 109 * and Provider loading and lookup is only trigered when 110 * necessary. 111 */ getServices(String type, String algorithm)112 public static List<Service> getServices(String type, String algorithm) { 113 ProviderList list = Providers.getProviderList(); 114 return list.getServices(type, algorithm); 115 } 116 117 /** 118 * This method exists for compatibility with JCE only. It will be removed 119 * once JCE has been changed to use the replacement method. 120 * @deprecated use getServices(List<ServiceId>) instead 121 */ 122 @Deprecated getServices(String type, List<String> algorithms)123 public static List<Service> getServices(String type, 124 List<String> algorithms) { 125 ProviderList list = Providers.getProviderList(); 126 return list.getServices(type, algorithms); 127 } 128 129 /** 130 * Return a List of all the available Services that implement any of 131 * the specified algorithms. See getServices(String, String) for detals. 132 */ getServices(List<ServiceId> ids)133 public static List<Service> getServices(List<ServiceId> ids) { 134 ProviderList list = Providers.getProviderList(); 135 return list.getServices(ids); 136 } 137 138 /* 139 * For all the getInstance() methods below: 140 * @param type the type of engine (e.g. MessageDigest) 141 * @param clazz the Spi class that the implementation must subclass 142 * (e.g. MessageDigestSpi.class) or null if no superclass check 143 * is required 144 * @param algorithm the name of the algorithm (or alias), e.g. MD5 145 * @param provider the provider (String or Provider object) 146 * @param param the parameter to pass to the Spi constructor 147 * (for CertStores) 148 * 149 * There are overloaded methods for all the permutations. 150 */ 151 getInstance(String type, Class<?> clazz, String algorithm)152 public static Instance getInstance(String type, Class<?> clazz, 153 String algorithm) throws NoSuchAlgorithmException { 154 // in the almost all cases, the first service will work 155 // avoid taking long path if so 156 ProviderList list = Providers.getProviderList(); 157 Service firstService = list.getService(type, algorithm); 158 if (firstService == null) { 159 throw new NoSuchAlgorithmException 160 (algorithm + " " + type + " not available"); 161 } 162 NoSuchAlgorithmException failure; 163 try { 164 return getInstance(firstService, clazz); 165 } catch (NoSuchAlgorithmException e) { 166 failure = e; 167 } 168 // if we cannot get the service from the preferred provider, 169 // fail over to the next 170 for (Service s : list.getServices(type, algorithm)) { 171 if (s == firstService) { 172 // do not retry initial failed service 173 continue; 174 } 175 try { 176 return getInstance(s, clazz); 177 } catch (NoSuchAlgorithmException e) { 178 failure = e; 179 } 180 } 181 throw failure; 182 } 183 getInstance(String type, Class<?> clazz, String algorithm, Object param)184 public static Instance getInstance(String type, Class<?> clazz, 185 String algorithm, Object param) throws NoSuchAlgorithmException { 186 List<Service> services = getServices(type, algorithm); 187 NoSuchAlgorithmException failure = null; 188 for (Service s : services) { 189 try { 190 return getInstance(s, clazz, param); 191 } catch (NoSuchAlgorithmException e) { 192 failure = e; 193 } 194 } 195 if (failure != null) { 196 throw failure; 197 } else { 198 throw new NoSuchAlgorithmException 199 (algorithm + " " + type + " not available"); 200 } 201 } 202 getInstance(String type, Class<?> clazz, String algorithm, String provider)203 public static Instance getInstance(String type, Class<?> clazz, 204 String algorithm, String provider) throws NoSuchAlgorithmException, 205 NoSuchProviderException { 206 return getInstance(getService(type, algorithm, provider), clazz); 207 } 208 getInstance(String type, Class<?> clazz, String algorithm, Object param, String provider)209 public static Instance getInstance(String type, Class<?> clazz, 210 String algorithm, Object param, String provider) 211 throws NoSuchAlgorithmException, NoSuchProviderException { 212 return getInstance(getService(type, algorithm, provider), clazz, param); 213 } 214 getInstance(String type, Class<?> clazz, String algorithm, Provider provider)215 public static Instance getInstance(String type, Class<?> clazz, 216 String algorithm, Provider provider) 217 throws NoSuchAlgorithmException { 218 return getInstance(getService(type, algorithm, provider), clazz); 219 } 220 getInstance(String type, Class<?> clazz, String algorithm, Object param, Provider provider)221 public static Instance getInstance(String type, Class<?> clazz, 222 String algorithm, Object param, Provider provider) 223 throws NoSuchAlgorithmException { 224 return getInstance(getService(type, algorithm, provider), clazz, param); 225 } 226 227 /* 228 * The two getInstance() methods below take a service. They are 229 * intended for classes that cannot use the standard methods, e.g. 230 * because they implement delayed provider selection like the 231 * Signature class. 232 */ 233 getInstance(Service s, Class<?> clazz)234 public static Instance getInstance(Service s, Class<?> clazz) 235 throws NoSuchAlgorithmException { 236 Object instance = s.newInstance(null); 237 checkSuperClass(s, instance.getClass(), clazz); 238 return new Instance(s.getProvider(), instance); 239 } 240 getInstance(Service s, Class<?> clazz, Object param)241 public static Instance getInstance(Service s, Class<?> clazz, 242 Object param) throws NoSuchAlgorithmException { 243 Object instance = s.newInstance(param); 244 checkSuperClass(s, instance.getClass(), clazz); 245 return new Instance(s.getProvider(), instance); 246 } 247 248 /** 249 * Check is subClass is a subclass of superClass. If not, 250 * throw a NoSuchAlgorithmException. 251 */ checkSuperClass(Service s, Class<?> subClass, Class<?> superClass)252 public static void checkSuperClass(Service s, Class<?> subClass, 253 Class<?> superClass) throws NoSuchAlgorithmException { 254 if (superClass == null) { 255 return; 256 } 257 if (superClass.isAssignableFrom(subClass) == false) { 258 throw new NoSuchAlgorithmException 259 ("class configured for " + s.getType() + ": " 260 + s.getClassName() + " not a " + s.getType()); 261 } 262 } 263 264 } 265