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 @SuppressWarnings("deprecation") 103 ResourceResolver tmp = new ResourceResolver(resolver.resolverSpi.getClass().newInstance()); 104 resolverTmp = tmp; 105 ; 106 } catch (InstantiationException e) { 107 throw new ResourceResolverException("", e, context.attr, context.baseUri); 108 } catch (IllegalAccessException e) { 109 throw new ResourceResolverException("", e, context.attr, context.baseUri); 110 } 111 } 112 113 if (log.isLoggable(java.util.logging.Level.FINE)) { 114 log.log(java.util.logging.Level.FINE, 115 "check resolvability by class " + resolverTmp.getClass().getName() 116 ); 117 } 118 119 if ((resolverTmp != null) && resolverTmp.canResolve(context)) { 120 // Check to see whether the Resolver is allowed 121 if (context.secureValidation 122 && (resolverTmp.resolverSpi instanceof ResolverLocalFilesystem 123 || resolverTmp.resolverSpi instanceof ResolverDirectHTTP)) { 124 Object exArgs[] = { resolverTmp.resolverSpi.getClass().getName() }; 125 throw new ResourceResolverException( 126 "signature.Reference.ForbiddenResolver", exArgs, context.attr, context.baseUri 127 ); 128 } 129 return resolverTmp; 130 } 131 } 132 } 133 134 Object exArgs[] = { ((context.uriToResolve != null) 135 ? context.uriToResolve : "null"), context.baseUri }; 136 137 throw new ResourceResolverException("utils.resolver.noClass", exArgs, context.attr, context.baseUri); 138 } 139 140 /** 141 * Method getInstance 142 * 143 * @param uri 144 * @param baseURI 145 * @param individualResolvers 146 * @return the instance 147 * 148 * @throws ResourceResolverException 149 */ 150 public static ResourceResolver getInstance( 151 Attr uri, String baseURI, List<ResourceResolver> individualResolvers 152 ) throws ResourceResolverException { 153 return getInstance(uri, baseURI, individualResolvers, false); 154 } 155 156 /** 157 * Method getInstance 158 * 159 * @param uri 160 * @param baseURI 161 * @param individualResolvers 162 * @param secureValidation 163 * @return the instance 164 * 165 * @throws ResourceResolverException 166 */ 167 public static ResourceResolver getInstance( 168 Attr uri, String baseURI, List<ResourceResolver> individualResolvers, boolean secureValidation 169 ) throws ResourceResolverException { 170 if (log.isLoggable(java.util.logging.Level.FINE)) { 171 log.log(java.util.logging.Level.FINE, 172 "I was asked to create a ResourceResolver and got " 173 + (individualResolvers == null ? 0 : individualResolvers.size()) 174 ); 175 } 176 177 ResourceResolverContext context = new ResourceResolverContext(uri, baseURI, secureValidation); 178 179 // first check the individual Resolvers 180 if (individualResolvers != null) { 181 for (int i = 0; i < individualResolvers.size(); i++) { 182 ResourceResolver resolver = individualResolvers.get(i); 183 184 if (resolver != null) { 185 if (log.isLoggable(java.util.logging.Level.FINE)) { 186 String currentClass = resolver.resolverSpi.getClass().getName(); 187 log.log(java.util.logging.Level.FINE, "check resolvability by class " + currentClass); 188 } 189 190 if (resolver.canResolve(context)) { 191 return resolver; 192 } 193 } 194 } 195 } 196 197 return internalGetInstance(context); 198 } 199 200 /** 201 * Registers a ResourceResolverSpi class. This method logs a warning if 202 * the class cannot be registered. 203 * 204 * @param className the name of the ResourceResolverSpi class to be registered 205 * @throws SecurityException if a security manager is installed and the 206 * caller does not have permission to register a resource resolver 207 */ 208 @SuppressWarnings("unchecked") 209 public static void register(String className) { 210 JavaUtils.checkRegisterPermission(); 211 try { 212 Class<ResourceResolverSpi> resourceResolverClass = 213 (Class<ResourceResolverSpi>) Class.forName(className); 214 register(resourceResolverClass, false); 215 } catch (ClassNotFoundException e) { 216 log.log(java.util.logging.Level.WARNING, "Error loading resolver " + className + " disabling it"); 217 } 218 } 219 220 /** 221 * Registers a ResourceResolverSpi class at the beginning of the provider 222 * list. This method logs a warning if the class cannot be registered. 223 * 224 * @param className the name of the ResourceResolverSpi class to be registered 225 * @throws SecurityException if a security manager is installed and the 226 * caller does not have permission to register a resource resolver 227 */ 228 @SuppressWarnings("unchecked") 229 public static void registerAtStart(String className) { 230 JavaUtils.checkRegisterPermission(); 231 try { 232 Class<ResourceResolverSpi> resourceResolverClass = 233 (Class<ResourceResolverSpi>) Class.forName(className); 234 register(resourceResolverClass, true); 235 } catch (ClassNotFoundException e) { 236 log.log(java.util.logging.Level.WARNING, "Error loading resolver " + className + " disabling it"); 237 } 238 } 239 240 /** 241 * Registers a ResourceResolverSpi class. This method logs a warning if the class 242 * cannot be registered. 243 * @param className 244 * @param start 245 * @throws SecurityException if a security manager is installed and the 246 * caller does not have permission to register a resource resolver 247 */ 248 public static void register(Class<? extends ResourceResolverSpi> className, boolean start) { 249 JavaUtils.checkRegisterPermission(); 250 try { 251 @SuppressWarnings("deprecation") 252 ResourceResolverSpi resourceResolverSpi = className.newInstance(); 253 register(resourceResolverSpi, start); 254 } catch (IllegalAccessException e) { 255 log.log(java.util.logging.Level.WARNING, "Error loading resolver " + className + " disabling it"); 256 } catch (InstantiationException e) { 257 log.log(java.util.logging.Level.WARNING, "Error loading resolver " + className + " disabling it"); 258 } 259 } 260 261 /** 262 * Registers a ResourceResolverSpi instance. This method logs a warning if the class 263 * cannot be registered. 264 * @param resourceResolverSpi 265 * @param start 266 * @throws SecurityException if a security manager is installed and the 267 * caller does not have permission to register a resource resolver 268 */ 269 public static void register(ResourceResolverSpi resourceResolverSpi, boolean start) { 270 JavaUtils.checkRegisterPermission(); 271 synchronized(resolverList) { 272 if (start) { 273 resolverList.add(0, new ResourceResolver(resourceResolverSpi)); 274 } else { 275 resolverList.add(new ResourceResolver(resourceResolverSpi)); 276 } 277 } 278 if (log.isLoggable(java.util.logging.Level.FINE)) { 279 log.log(java.util.logging.Level.FINE, "Registered resolver: " + resourceResolverSpi.toString()); 280 } 281 } 282 283 /** 284 * This method registers the default resolvers. 285 */ 286 public static void registerDefaultResolvers() { 287 synchronized(resolverList) { 288 resolverList.add(new ResourceResolver(new ResolverFragment())); 289 resolverList.add(new ResourceResolver(new ResolverLocalFilesystem())); 290 resolverList.add(new ResourceResolver(new ResolverXPointer())); 291 resolverList.add(new ResourceResolver(new ResolverDirectHTTP())); 292 } 293 } 294 295 /** 296 * @deprecated New clients should use {@link #resolve(Attr, String, boolean)} 297 */ 298 @Deprecated 299 public XMLSignatureInput resolve(Attr uri, String baseURI) 300 throws ResourceResolverException { 301 return resolve(uri, baseURI, true); 302 } 303 304 /** 305 * Method resolve 306 * 307 * @param uri 308 * @param baseURI 309 * @return the resource 310 * 311 * @throws ResourceResolverException 312 */ 313 public XMLSignatureInput resolve(Attr uri, String baseURI, boolean secureValidation) 314 throws ResourceResolverException { 315 ResourceResolverContext context = new ResourceResolverContext(uri, baseURI, secureValidation); 316 return resolverSpi.engineResolveURI(context); 317 } 318 319 /** 320 * Method setProperty 321 * 322 * @param key 323 * @param value 324 */ 325 public void setProperty(String key, String value) { 326 resolverSpi.engineSetProperty(key, value); 327 } 328 329 /** 330 * Method getProperty 331 * 332 * @param key 333 * @return the value of the property 334 */ 335 public String getProperty(String key) { 336 return resolverSpi.engineGetProperty(key); 337 } 338 339 /** 340 * Method addProperties 341 * 342 * @param properties 343 */ 344 public void addProperties(Map<String, String> properties) { 345 resolverSpi.engineAddProperies(properties); 346 } 347 348 /** 349 * Method getPropertyKeys 350 * 351 * @return all property keys. 352 */ 353 public String[] getPropertyKeys() { 354 return resolverSpi.engineGetPropertyKeys(); 355 } 356 357 /** 358 * Method understandsProperty 359 * 360 * @param propertyToTest 361 * @return true if the resolver understands the property 362 */ 363 public boolean understandsProperty(String propertyToTest) { 364 return resolverSpi.understandsProperty(propertyToTest); 365 } 366 367 /** 368 * Method canResolve 369 * 370 * @param uri 371 * @param baseURI 372 * @return true if it can resolve the uri 373 */ 374 private boolean canResolve(ResourceResolverContext context) { 375 return this.resolverSpi.engineCanResolveURI(context); 376 } 377 }