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.utils.resolver; 24 25 import java.util.ArrayList; 26 import java.util.List; 27 import java.util.Map; 28 29 import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; 30 import com.sun.org.apache.xml.internal.security.utils.resolver.implementations.ResolverDirectHTTP; 31 import com.sun.org.apache.xml.internal.security.utils.resolver.implementations.ResolverFragment; 32 import com.sun.org.apache.xml.internal.security.utils.resolver.implementations.ResolverLocalFilesystem; 33 import com.sun.org.apache.xml.internal.security.utils.resolver.implementations.ResolverXPointer; 34 import org.w3c.dom.Attr; 35 36 /** 37 * During reference validation, we have to retrieve resources from somewhere. 38 * This is done by retrieving a Resolver. The resolver needs two arguments: The 39 * URI in which the link to the new resource is defined and the baseURI of the 40 * file/entity in which the URI occurs (the baseURI is the same as the SystemId). 41 */ 42 public class ResourceResolver { 43 44 /** {@link org.apache.commons.logging} logging facility */ 45 private static java.util.logging.Logger log = 46 java.util.logging.Logger.getLogger(ResourceResolver.class.getName()); 47 48 /** these are the system-wide resolvers */ 49 private static List<ResourceResolver> resolverList = new ArrayList<ResourceResolver>(); 50 51 /** Field resolverSpi */ 52 private final ResourceResolverSpi resolverSpi; 53 54 /** 55 * Constructor ResourceResolver 56 * 57 * @param resourceResolver 58 */ 59 public ResourceResolver(ResourceResolverSpi resourceResolver) { 60 this.resolverSpi = resourceResolver; 61 } 62 63 /** 64 * Method getInstance 65 * 66 * @param uri 67 * @param baseURI 68 * @return the instance 69 * 70 * @throws ResourceResolverException 71 */ 72 public static final ResourceResolver getInstance(Attr uri, String baseURI) 73 throws ResourceResolverException { 74 return getInstance(uri, baseURI, false); 75 } 76 77 /** 78 * Method getInstance 79 * 80 * @param uri 81 * @param baseURI 82 * @param secureValidation 83 * @return the instance 84 * 85 * @throws ResourceResolverException 86 */ 87 public static final ResourceResolver getInstance( 88 Attr uriAttr, String baseURI, boolean secureValidation 89 ) throws ResourceResolverException { 90 ResourceResolverContext context = new ResourceResolverContext(uriAttr, baseURI, secureValidation); 91 return internalGetInstance(context); 92 } 93 94 private static <N> ResourceResolver internalGetInstance(ResourceResolverContext context) 95 throws ResourceResolverException { 96 synchronized (resolverList) { 97 for (ResourceResolver resolver : resolverList) { 98 ResourceResolver resolverTmp = resolver; 99 if (!resolver.resolverSpi.engineIsThreadSafe()) { 100 try { 101 resolverTmp = 102 new ResourceResolver(resolver.resolverSpi.getClass().newInstance()); 103 } catch (InstantiationException e) { 104 throw new ResourceResolverException("", e, context.attr, context.baseUri); 105 } catch (IllegalAccessException e) { 106 throw new ResourceResolverException("", e, context.attr, context.baseUri); 107 } 108 } 109 110 if (log.isLoggable(java.util.logging.Level.FINE)) { 111 log.log(java.util.logging.Level.FINE, 112 "check resolvability by class " + resolverTmp.getClass().getName() 113 ); 114 } 115 116 if ((resolverTmp != null) && resolverTmp.canResolve(context)) { 117 // Check to see whether the Resolver is allowed 118 if (context.secureValidation 119 && (resolverTmp.resolverSpi instanceof ResolverLocalFilesystem 120 || resolverTmp.resolverSpi instanceof ResolverDirectHTTP)) { 121 Object exArgs[] = { resolverTmp.resolverSpi.getClass().getName() }; 122 throw new ResourceResolverException( 123 "signature.Reference.ForbiddenResolver", exArgs, context.attr, context.baseUri 124 ); 125 } 126 return resolverTmp; 127 } 128 } 129 } 130 131 Object exArgs[] = { ((context.uriToResolve != null) 132 ? context.uriToResolve : "null"), context.baseUri }; 133 134 throw new ResourceResolverException("utils.resolver.noClass", exArgs, context.attr, context.baseUri); 135 } 136 137 /** 138 * Method getInstance 139 * 140 * @param uri 141 * @param baseURI 142 * @param individualResolvers 143 * @return the instance 144 * 145 * @throws ResourceResolverException 146 */ 147 public static ResourceResolver getInstance( 148 Attr uri, String baseURI, List<ResourceResolver> individualResolvers 149 ) throws ResourceResolverException { 150 return getInstance(uri, baseURI, individualResolvers, false); 151 } 152 153 /** 154 * Method getInstance 155 * 156 * @param uri 157 * @param baseURI 158 * @param individualResolvers 159 * @param secureValidation 160 * @return the instance 161 * 162 * @throws ResourceResolverException 163 */ 164 public static ResourceResolver getInstance( 165 Attr uri, String baseURI, List<ResourceResolver> individualResolvers, boolean secureValidation 166 ) throws ResourceResolverException { 167 if (log.isLoggable(java.util.logging.Level.FINE)) { 168 log.log(java.util.logging.Level.FINE, 169 "I was asked to create a ResourceResolver and got " 170 + (individualResolvers == null ? 0 : individualResolvers.size()) 171 ); 172 } 173 174 ResourceResolverContext context = new ResourceResolverContext(uri, baseURI, secureValidation); 175 176 // first check the individual Resolvers 177 if (individualResolvers != null) { 178 for (int i = 0; i < individualResolvers.size(); i++) { 179 ResourceResolver resolver = individualResolvers.get(i); 180 181 if (resolver != null) { 182 if (log.isLoggable(java.util.logging.Level.FINE)) { 183 String currentClass = resolver.resolverSpi.getClass().getName(); 184 log.log(java.util.logging.Level.FINE, "check resolvability by class " + currentClass); 185 } 186 187 if (resolver.canResolve(context)) { 188 return resolver; 189 } 190 } 191 } 192 } 193 194 return internalGetInstance(context); 195 } 196 197 /** 198 * Registers a ResourceResolverSpi class. This method logs a warning if 199 * the class cannot be registered. 200 * 201 * @param className the name of the ResourceResolverSpi class to be registered 202 */ 203 @SuppressWarnings("unchecked") 204 public static void register(String className) { 205 try { 206 Class<ResourceResolverSpi> resourceResolverClass = 207 (Class<ResourceResolverSpi>) Class.forName(className); 208 register(resourceResolverClass, false); 209 } catch (ClassNotFoundException e) { 210 log.log(java.util.logging.Level.WARNING, "Error loading resolver " + className + " disabling it"); 211 } 212 } 213 214 /** 215 * Registers a ResourceResolverSpi class at the beginning of the provider 216 * list. This method logs a warning if the class cannot be registered. 217 * 218 * @param className the name of the ResourceResolverSpi class to be registered 219 */ 220 @SuppressWarnings("unchecked") 221 public static void registerAtStart(String className) { 222 try { 223 Class<ResourceResolverSpi> resourceResolverClass = 224 (Class<ResourceResolverSpi>) Class.forName(className); 225 register(resourceResolverClass, true); 226 } catch (ClassNotFoundException e) { 227 log.log(java.util.logging.Level.WARNING, "Error loading resolver " + className + " disabling it"); 228 } 229 } 230 231 /** 232 * Registers a ResourceResolverSpi class. This method logs a warning if the class 233 * cannot be registered. 234 * @param className 235 * @param start 236 */ 237 public static void register(Class<? extends ResourceResolverSpi> className, boolean start) { 238 try { 239 ResourceResolverSpi resourceResolverSpi = className.newInstance(); 240 register(resourceResolverSpi, start); 241 } catch (IllegalAccessException e) { 242 log.log(java.util.logging.Level.WARNING, "Error loading resolver " + className + " disabling it"); 243 } catch (InstantiationException e) { 244 log.log(java.util.logging.Level.WARNING, "Error loading resolver " + className + " disabling it"); 245 } 246 } 247 248 /** 249 * Registers a ResourceResolverSpi instance. This method logs a warning if the class 250 * cannot be registered. 251 * @param resourceResolverSpi 252 * @param start 253 */ 254 public static void register(ResourceResolverSpi resourceResolverSpi, boolean start) { 255 synchronized(resolverList) { 256 if (start) { 257 resolverList.add(0, new ResourceResolver(resourceResolverSpi)); 258 } else { 259 resolverList.add(new ResourceResolver(resourceResolverSpi)); 260 } 261 } 262 if (log.isLoggable(java.util.logging.Level.FINE)) { 263 log.log(java.util.logging.Level.FINE, "Registered resolver: " + resourceResolverSpi.toString()); 264 } 265 } 266 267 /** 268 * This method registers the default resolvers. 269 */ 270 public static void registerDefaultResolvers() { 271 synchronized(resolverList) { 272 resolverList.add(new ResourceResolver(new ResolverFragment())); 273 resolverList.add(new ResourceResolver(new ResolverLocalFilesystem())); 274 resolverList.add(new ResourceResolver(new ResolverXPointer())); 275 resolverList.add(new ResourceResolver(new ResolverDirectHTTP())); 276 } 277 } 278 279 /** 280 * @deprecated New clients should use {@link #resolve(Attr, String, boolean)} 281 */ 282 @Deprecated 283 public XMLSignatureInput resolve(Attr uri, String baseURI) 284 throws ResourceResolverException { 285 return resolve(uri, baseURI, true); 286 } 287 288 /** 289 * Method resolve 290 * 291 * @param uri 292 * @param baseURI 293 * @return the resource 294 * 295 * @throws ResourceResolverException 296 */ 297 public XMLSignatureInput resolve(Attr uri, String baseURI, boolean secureValidation) 298 throws ResourceResolverException { 299 ResourceResolverContext context = new ResourceResolverContext(uri, baseURI, secureValidation); 300 return resolverSpi.engineResolveURI(context); 301 } 302 303 /** 304 * Method setProperty 305 * 306 * @param key 307 * @param value 308 */ 309 public void setProperty(String key, String value) { 310 resolverSpi.engineSetProperty(key, value); 311 } 312 313 /** 314 * Method getProperty 315 * 316 * @param key 317 * @return the value of the property 318 */ 319 public String getProperty(String key) { 320 return resolverSpi.engineGetProperty(key); 321 } 322 323 /** 324 * Method addProperties 325 * 326 * @param properties 327 */ 328 public void addProperties(Map<String, String> properties) { 329 resolverSpi.engineAddProperies(properties); 330 } 331 332 /** 333 * Method getPropertyKeys 334 * 335 * @return all property keys. 336 */ 337 public String[] getPropertyKeys() { 338 return resolverSpi.engineGetPropertyKeys(); 339 } 340 341 /** 342 * Method understandsProperty 343 * 344 * @param propertyToTest 345 * @return true if the resolver understands the property 346 */ 347 public boolean understandsProperty(String propertyToTest) { 348 return resolverSpi.understandsProperty(propertyToTest); 349 } 350 351 /** 352 * Method canResolve 353 * 354 * @param uri 355 * @param baseURI 356 * @return true if it can resolve the uri 357 */ 358 private boolean canResolve(ResourceResolverContext context) { 359 return this.resolverSpi.engineCanResolveURI(context); 360 } 361 }