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