View Javadoc
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.HashMap;
26  import java.util.Map;
27  
28  import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput;
29  import org.w3c.dom.Attr;
30  
31  /**
32   * During reference validation, we have to retrieve resources from somewhere.
33   *
34   * @author $Author: coheigea $
35   */
36  public abstract class ResourceResolverSpi {
37  
38      /** {@link org.apache.commons.logging} logging facility */
39      private static java.util.logging.Logger log =
40          java.util.logging.Logger.getLogger(ResourceResolverSpi.class.getName());
41  
42      /** Field properties */
43      protected java.util.Map<String, String> properties = null;
44  
45      /**
46       * Deprecated - used to carry state about whether resolution was being done in a secure fashion,
47       * but was not thread safe, so the resolution information is now passed as parameters to methods.
48       *
49       * @deprecated Secure validation flag is now passed to methods.
50       */
51      @Deprecated
52      protected final boolean secureValidation = true;
53  
54      /**
55       * This is the workhorse method used to resolve resources.
56       *
57       * @param uri
58       * @param BaseURI
59       * @return the resource wrapped around a XMLSignatureInput
60       *
61       * @throws ResourceResolverException
62       *
63       * @deprecated New clients should override {@link #engineResolveURI(ResourceResolverContext)}
64       */
65      @Deprecated
66      public XMLSignatureInput engineResolve(Attr uri, String BaseURI)
67          throws ResourceResolverException {
68          throw new UnsupportedOperationException();
69      }
70  
71      /**
72       * This is the workhorse method used to resolve resources.
73       * @param context Context to use to resolve resources.
74       *
75       * @return the resource wrapped around a XMLSignatureInput
76       *
77       * @throws ResourceResolverException
78       */
79      public XMLSignatureInput engineResolveURI(ResourceResolverContext context)
80          throws ResourceResolverException {
81          // The default implementation, to preserve backwards compatibility in the
82          // test cases, calls the old resolver API.
83          return engineResolve(context.attr, context.baseUri);
84      }
85  
86      /**
87       * Method engineSetProperty
88       *
89       * @param key
90       * @param value
91       */
92      public void engineSetProperty(String key, String value) {
93          if (properties == null) {
94              properties = new HashMap<String, String>();
95          }
96          properties.put(key, value);
97      }
98  
99      /**
100      * Method engineGetProperty
101      *
102      * @param key
103      * @return the value of the property
104      */
105     public String engineGetProperty(String key) {
106         if (properties == null) {
107             return null;
108         }
109         return properties.get(key);
110     }
111 
112     /**
113      *
114      * @param newProperties
115      */
116     public void engineAddProperies(Map<String, String> newProperties) {
117         if (newProperties != null && !newProperties.isEmpty()) {
118             if (properties == null) {
119                 properties = new HashMap<String, String>();
120             }
121             properties.putAll(newProperties);
122         }
123     }
124 
125     /**
126      * Tells if the implementation does can be reused by several threads safely.
127      * It normally means that the implementation does not have any member, or there is
128      * member change between engineCanResolve & engineResolve invocations. Or it maintains all
129      * member info in ThreadLocal methods.
130      */
131     public boolean engineIsThreadSafe() {
132         return false;
133     }
134 
135     /**
136      * This method helps the {@link ResourceResolver} to decide whether a
137      * {@link ResourceResolverSpi} is able to perform the requested action.
138      *
139      * @param uri
140      * @param BaseURI
141      * @return true if the engine can resolve the uri
142      *
143      * @deprecated See {@link #engineCanResolveURI(ResourceResolverContext)}
144      */
145     @Deprecated
146     public boolean engineCanResolve(Attr uri, String BaseURI) {
147         // This method used to be abstract, so any calls to "super" are bogus.
148         throw new UnsupportedOperationException();
149     }
150 
151     /**
152      * This method helps the {@link ResourceResolver} to decide whether a
153      * {@link ResourceResolverSpi} is able to perform the requested action.
154      *
155      * <p>New clients should override this method, and not override {@link #engineCanResolve(Attr, String)}
156      * </p>
157      * @param context Context in which to do resolution.
158      * @return true if the engine can resolve the uri
159      */
160     public boolean engineCanResolveURI(ResourceResolverContext context) {
161         // To preserve backward compatibility with existing resolvers that might override the old method,
162         // call the old deprecated API.
163         return engineCanResolve( context.attr, context.baseUri );
164     }
165 
166     /**
167      * Method engineGetPropertyKeys
168      *
169      * @return the property keys
170      */
171     public String[] engineGetPropertyKeys() {
172         return new String[0];
173     }
174 
175     /**
176      * Method understandsProperty
177      *
178      * @param propertyToTest
179      * @return true if understands the property
180      */
181     public boolean understandsProperty(String propertyToTest) {
182         String[] understood = this.engineGetPropertyKeys();
183 
184         if (understood != null) {
185             for (int i = 0; i < understood.length; i++) {
186                 if (understood[i].equals(propertyToTest)) {
187                     return true;
188                 }
189             }
190         }
191 
192         return false;
193     }
194 
195 
196     /**
197      * Fixes a platform dependent filename to standard URI form.
198      *
199      * @param str The string to fix.
200      *
201      * @return Returns the fixed URI string.
202      */
203     public static String fixURI(String str) {
204 
205         // handle platform dependent strings
206         str = str.replace(java.io.File.separatorChar, '/');
207 
208         if (str.length() >= 4) {
209 
210             // str =~ /^\W:\/([^/])/ # to speak perl ;-))
211             char ch0 = Character.toUpperCase(str.charAt(0));
212             char ch1 = str.charAt(1);
213             char ch2 = str.charAt(2);
214             char ch3 = str.charAt(3);
215             boolean isDosFilename = ((('A' <= ch0) && (ch0 <= 'Z'))
216                 && (ch1 == ':') && (ch2 == '/')
217                 && (ch3 != '/'));
218 
219             if (isDosFilename && log.isLoggable(java.util.logging.Level.FINE)) {
220                 log.log(java.util.logging.Level.FINE, "Found DOS filename: " + str);
221             }
222         }
223 
224         // Windows fix
225         if (str.length() >= 2) {
226             char ch1 = str.charAt(1);
227 
228             if (ch1 == ':') {
229                 char ch0 = Character.toUpperCase(str.charAt(0));
230 
231                 if (('A' <= ch0) && (ch0 <= 'Z')) {
232                     str = "/" + str;
233                 }
234             }
235         }
236 
237         // done
238         return str;
239     }
240 }