1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /** 6 * Licensed to the Apache Software Foundation (ASF) under one 7 * or more contributor license agreements. See the NOTICE file 8 * distributed with this work for additional information 9 * regarding copyright ownership. The ASF licenses this file 10 * to you under the Apache License, Version 2.0 (the 11 * "License"); you may not use this file except in compliance 12 * with the License. You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, 17 * software distributed under the License is distributed on an 18 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 19 * KIND, either express or implied. See the License for the 20 * specific language governing permissions and limitations 21 * under the License. 22 */ 23 package com.sun.org.apache.xml.internal.security.keys.keyresolver; 24 25 import java.security.PublicKey; 26 import java.security.cert.X509Certificate; 27 import java.util.ArrayList; 28 import java.util.Iterator; 29 import java.util.List; 30 import java.util.concurrent.CopyOnWriteArrayList; 31 32 import javax.crypto.SecretKey; 33 34 import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.DEREncodedKeyValueResolver; 35 import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.DSAKeyValueResolver; 36 import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.KeyInfoReferenceResolver; 37 import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.RSAKeyValueResolver; 38 import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.RetrievalMethodResolver; 39 import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.X509CertificateResolver; 40 import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.X509DigestResolver; 41 import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.X509IssuerSerialResolver; 42 import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.X509SKIResolver; 43 import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.X509SubjectNameResolver; 44 import com.sun.org.apache.xml.internal.security.keys.storage.StorageResolver; 45 import org.w3c.dom.Element; 46 import org.w3c.dom.Node; 47 48 /** 49 * KeyResolver is factory class for subclass of KeyResolverSpi that 50 * represent child element of KeyInfo. 51 */ 52 public class KeyResolver { 53 54 /** {@link org.apache.commons.logging} logging facility */ 55 private static java.util.logging.Logger log = 56 java.util.logging.Logger.getLogger(KeyResolver.class.getName()); 57 58 /** Field resolverVector */ 59 private static List<KeyResolver> resolverVector = new CopyOnWriteArrayList<KeyResolver>(); 60 61 /** Field resolverSpi */ 62 private final KeyResolverSpi resolverSpi; 63 64 /** 65 * Constructor. 66 * 67 * @param keyResolverSpi a KeyResolverSpi instance 68 */ 69 private KeyResolver(KeyResolverSpi keyResolverSpi) { 70 resolverSpi = keyResolverSpi; 71 } 72 73 /** 74 * Method length 75 * 76 * @return the length of resolvers registered 77 */ 78 public static int length() { 79 return resolverVector.size(); 80 } 81 82 /** 83 * Method getX509Certificate 84 * 85 * @param element 86 * @param baseURI 87 * @param storage 88 * @return The certificate represented by the element. 89 * 90 * @throws KeyResolverException 91 */ 92 public static final X509Certificate getX509Certificate( 93 Element element, String baseURI, StorageResolver storage 94 ) throws KeyResolverException { 95 for (KeyResolver resolver : resolverVector) { 96 if (resolver == null) { 97 Object exArgs[] = { 98 (((element != null) 99 && (element.getNodeType() == Node.ELEMENT_NODE)) 100 ? element.getTagName() : "null") 101 }; 102 103 throw new KeyResolverException("utils.resolver.noClass", exArgs); 104 } 105 if (log.isLoggable(java.util.logging.Level.FINE)) { 106 log.log(java.util.logging.Level.FINE, "check resolvability by class " + resolver.getClass()); 107 } 108 109 X509Certificate cert = resolver.resolveX509Certificate(element, baseURI, storage); 110 if (cert != null) { 111 return cert; 112 } 113 } 114 115 Object exArgs[] = { 116 (((element != null) && (element.getNodeType() == Node.ELEMENT_NODE)) 117 ? element.getTagName() : "null") 118 }; 119 120 throw new KeyResolverException("utils.resolver.noClass", exArgs); 121 } 122 123 /** 124 * Method getPublicKey 125 * 126 * @param element 127 * @param baseURI 128 * @param storage 129 * @return the public key contained in the element 130 * 131 * @throws KeyResolverException 132 */ 133 public static final PublicKey getPublicKey( 134 Element element, String baseURI, StorageResolver storage 135 ) throws KeyResolverException { 136 for (KeyResolver resolver : resolverVector) { 137 if (resolver == null) { 138 Object exArgs[] = { 139 (((element != null) 140 && (element.getNodeType() == Node.ELEMENT_NODE)) 141 ? element.getTagName() : "null") 142 }; 143 144 throw new KeyResolverException("utils.resolver.noClass", exArgs); 145 } 146 if (log.isLoggable(java.util.logging.Level.FINE)) { 147 log.log(java.util.logging.Level.FINE, "check resolvability by class " + resolver.getClass()); 148 } 149 150 PublicKey cert = resolver.resolvePublicKey(element, baseURI, storage); 151 if (cert != null) { 152 return cert; 153 } 154 } 155 156 Object exArgs[] = { 157 (((element != null) && (element.getNodeType() == Node.ELEMENT_NODE)) 158 ? element.getTagName() : "null") 159 }; 160 161 throw new KeyResolverException("utils.resolver.noClass", exArgs); 162 } 163 164 /** 165 * This method is used for registering {@link KeyResolverSpi}s which are 166 * available to <I>all</I> {@link com.sun.org.apache.xml.internal.security.keys.KeyInfo} objects. This means that 167 * personalized {@link KeyResolverSpi}s should only be registered directly 168 * to the {@link com.sun.org.apache.xml.internal.security.keys.KeyInfo} using 169 * {@link com.sun.org.apache.xml.internal.security.keys.KeyInfo#registerInternalKeyResolver}. 170 * Please note that this method will create a new copy of the underlying array, as the 171 * underlying collection is a CopyOnWriteArrayList. 172 * 173 * @param className 174 * @param globalResolver Whether the KeyResolverSpi is a global resolver or not 175 * @throws InstantiationException 176 * @throws IllegalAccessException 177 * @throws ClassNotFoundException 178 */ 179 public static void register(String className, boolean globalResolver) 180 throws ClassNotFoundException, IllegalAccessException, InstantiationException { 181 KeyResolverSpi keyResolverSpi = 182 (KeyResolverSpi) Class.forName(className).newInstance(); 183 keyResolverSpi.setGlobalResolver(globalResolver); 184 register(keyResolverSpi, false); 185 } 186 187 /** 188 * This method is used for registering {@link KeyResolverSpi}s which are 189 * available to <I>all</I> {@link com.sun.org.apache.xml.internal.security.keys.KeyInfo} objects. This means that 190 * personalized {@link KeyResolverSpi}s should only be registered directly 191 * to the {@link com.sun.org.apache.xml.internal.security.keys.KeyInfo} using 192 * {@link com.sun.org.apache.xml.internal.security.keys.KeyInfo#registerInternalKeyResolver}. 193 * Please note that this method will create a new copy of the underlying array, as the 194 * underlying collection is a CopyOnWriteArrayList. 195 * 196 * @param className 197 * @param globalResolver Whether the KeyResolverSpi is a global resolver or not 198 */ 199 public static void registerAtStart(String className, boolean globalResolver) { 200 KeyResolverSpi keyResolverSpi = null; 201 Exception ex = null; 202 try { 203 keyResolverSpi = (KeyResolverSpi) Class.forName(className).newInstance(); 204 } catch (ClassNotFoundException e) { 205 ex = e; 206 } catch (IllegalAccessException e) { 207 ex = e; 208 } catch (InstantiationException e) { 209 ex = e; 210 } 211 212 if (ex != null) { 213 throw (IllegalArgumentException) new 214 IllegalArgumentException("Invalid KeyResolver class name").initCause(ex); 215 } 216 keyResolverSpi.setGlobalResolver(globalResolver); 217 register(keyResolverSpi, true); 218 } 219 220 /** 221 * This method is used for registering {@link KeyResolverSpi}s which are 222 * available to <I>all</I> {@link com.sun.org.apache.xml.internal.security.keys.KeyInfo} objects. This means that 223 * personalized {@link KeyResolverSpi}s should only be registered directly 224 * to the {@link com.sun.org.apache.xml.internal.security.keys.KeyInfo} using 225 * {@link com.sun.org.apache.xml.internal.security.keys.KeyInfo#registerInternalKeyResolver}. 226 * Please note that this method will create a new copy of the underlying array, as the 227 * underlying collection is a CopyOnWriteArrayList. 228 * 229 * @param keyResolverSpi a KeyResolverSpi instance to register 230 * @param start whether to register the KeyResolverSpi at the start of the list or not 231 */ 232 public static void register( 233 KeyResolverSpi keyResolverSpi, 234 boolean start 235 ) { 236 KeyResolver resolver = new KeyResolver(keyResolverSpi); 237 if (start) { 238 resolverVector.add(0, resolver); 239 } else { 240 resolverVector.add(resolver); 241 } 242 } 243 244 /** 245 * This method is used for registering {@link KeyResolverSpi}s which are 246 * available to <I>all</I> {@link com.sun.org.apache.xml.internal.security.keys.KeyInfo} objects. This means that 247 * personalized {@link KeyResolverSpi}s should only be registered directly 248 * to the {@link com.sun.org.apache.xml.internal.security.keys.KeyInfo} using 249 * {@link com.sun.org.apache.xml.internal.security.keys.KeyInfo#registerInternalKeyResolver}. 250 * The KeyResolverSpi instances are not registered as a global resolver. 251 * 252 * 253 * @param classNames 254 * @throws InstantiationException 255 * @throws IllegalAccessException 256 * @throws ClassNotFoundException 257 */ 258 public static void registerClassNames(List<String> classNames) 259 throws ClassNotFoundException, IllegalAccessException, InstantiationException { 260 List<KeyResolver> keyResolverList = new ArrayList<KeyResolver>(classNames.size()); 261 for (String className : classNames) { 262 KeyResolverSpi keyResolverSpi = 263 (KeyResolverSpi) Class.forName(className).newInstance(); 264 keyResolverSpi.setGlobalResolver(false); 265 keyResolverList.add(new KeyResolver(keyResolverSpi)); 266 } 267 resolverVector.addAll(keyResolverList); 268 } 269 270 /** 271 * This method registers the default resolvers. 272 */ 273 public static void registerDefaultResolvers() { 274 275 List<KeyResolver> keyResolverList = new ArrayList<KeyResolver>(); 276 keyResolverList.add(new KeyResolver(new RSAKeyValueResolver())); 277 keyResolverList.add(new KeyResolver(new DSAKeyValueResolver())); 278 keyResolverList.add(new KeyResolver(new X509CertificateResolver())); 279 keyResolverList.add(new KeyResolver(new X509SKIResolver())); 280 keyResolverList.add(new KeyResolver(new RetrievalMethodResolver())); 281 keyResolverList.add(new KeyResolver(new X509SubjectNameResolver())); 282 keyResolverList.add(new KeyResolver(new X509IssuerSerialResolver())); 283 keyResolverList.add(new KeyResolver(new DEREncodedKeyValueResolver())); 284 keyResolverList.add(new KeyResolver(new KeyInfoReferenceResolver())); 285 keyResolverList.add(new KeyResolver(new X509DigestResolver())); 286 287 resolverVector.addAll(keyResolverList); 288 } 289 290 /** 291 * Method resolvePublicKey 292 * 293 * @param element 294 * @param baseURI 295 * @param storage 296 * @return resolved public key from the registered from the elements 297 * 298 * @throws KeyResolverException 299 */ 300 public PublicKey resolvePublicKey( 301 Element element, String baseURI, StorageResolver storage 302 ) throws KeyResolverException { 303 return resolverSpi.engineLookupAndResolvePublicKey(element, baseURI, storage); 304 } 305 306 /** 307 * Method resolveX509Certificate 308 * 309 * @param element 310 * @param baseURI 311 * @param storage 312 * @return resolved X509certificate key from the registered from the elements 313 * 314 * @throws KeyResolverException 315 */ 316 public X509Certificate resolveX509Certificate( 317 Element element, String baseURI, StorageResolver storage 318 ) throws KeyResolverException { 319 return resolverSpi.engineLookupResolveX509Certificate(element, baseURI, storage); 320 } 321 322 /** 323 * @param element 324 * @param baseURI 325 * @param storage 326 * @return resolved SecretKey key from the registered from the elements 327 * @throws KeyResolverException 328 */ 329 public SecretKey resolveSecretKey( 330 Element element, String baseURI, StorageResolver storage 331 ) throws KeyResolverException { 332 return resolverSpi.engineLookupAndResolveSecretKey(element, baseURI, storage); 333 } 334 335 /** 336 * Method setProperty 337 * 338 * @param key 339 * @param value 340 */ 341 public void setProperty(String key, String value) { 342 resolverSpi.engineSetProperty(key, value); 343 } 344 345 /** 346 * Method getProperty 347 * 348 * @param key 349 * @return the property set for this resolver 350 */ 351 public String getProperty(String key) { 352 return resolverSpi.engineGetProperty(key); 353 } 354 355 356 /** 357 * Method understandsProperty 358 * 359 * @param propertyToTest 360 * @return true if the resolver understands property propertyToTest 361 */ 362 public boolean understandsProperty(String propertyToTest) { 363 return resolverSpi.understandsProperty(propertyToTest); 364 } 365 366 367 /** 368 * Method resolverClassName 369 * 370 * @return the name of the resolver. 371 */ 372 public String resolverClassName() { 373 return resolverSpi.getClass().getName(); 374 } 375 376 /** 377 * Iterate over the KeyResolverSpi instances 378 */ 379 static class ResolverIterator implements Iterator<KeyResolverSpi> { 380 List<KeyResolver> res; 381 Iterator<KeyResolver> it; 382 383 public ResolverIterator(List<KeyResolver> list) { 384 res = list; 385 it = res.iterator(); 386 } 387 388 public boolean hasNext() { 389 return it.hasNext(); 390 } 391 392 public KeyResolverSpi next() { 393 KeyResolver resolver = it.next(); 394 if (resolver == null) { 395 throw new RuntimeException("utils.resolver.noClass"); 396 } 397 398 return resolver.resolverSpi; 399 } 400 401 public void remove() { 402 throw new UnsupportedOperationException("Can't remove resolvers using the iterator"); 403 } 404 }; 405 406 public static Iterator<KeyResolverSpi> iterator() { 407 return new ResolverIterator(resolverVector); 408 } 409 }