Project

Profile

Help

How to connect?
Download (11.2 KB) Statistics
| Branch: | Tag: | Revision:

he / latest8.8 / bj / net / sf / saxon / StandardURIResolver.java0 @ 8de369ca

1

    
2
/**
3
* This class provides the service of converting a URI into an InputSource.
4
* It is used to get stylesheet modules referenced by xsl:import and xsl:include,
5
* and source documents referenced by the document() function. The standard version
6
* handles anything that the java URL class will handle.
7
* You can write a subclass to handle other kinds of URI, e.g. references to things in
8
* a database.
9
* @author Michael H. Kay
10
*/
11

    
12
public class StandardURIResolver implements NonDelegatingURIResolver, Serializable {
13

    
14
    private Configuration config = null;
15
    protected boolean recognizeQueryParameters = false;
16

    
17
    /**
18
     * Create a StandardURIResolver, with no reference to a TransformerFactory
19
     */
20
    public StandardURIResolver() {
21
        this(null);
22
    }
23

    
24
    /**
25
     * Create a StandardURIResolver, with a reference to a TransformerFactory
26
     * @param config The Configuration object.
27
     * This is used to get a SAX Parser for a source XML document
28
     */
29

    
30
    public StandardURIResolver(Configuration config) {
31
        this.config = config;
32
    }
33

    
34
    /**
35
     * Indicate that query parameters (such as ?validation=strict) are to be recognized
36
     * @param recognize Set to true if query parameters in the URI are to be recognized and acted upon.
37
     * The default (for compatibility and interoperability reasons) is false.
38
     */
39

    
40
    public void setRecognizeQueryParameters(boolean recognize) {
41
        recognizeQueryParameters = recognize;
42
    }
43

    
44
    /**
45
     * Determine whether query parameters (such as ?validation=strict) are to be recognized
46
     * @return true if query parameters are recognized and interpreted by Saxon.
47
     */
48

    
49
    public boolean queryParametersAreRecognized() {
50
        return recognizeQueryParameters;
51
    }
52

    
53
    /**
54
    * Resolve a URI
55
    * @param href The relative or absolute URI. May be an empty string. May contain
56
    * a fragment identifier starting with "#", which must be the value of an ID attribute
57
    * in the referenced XML document.
58
    * @param base The base URI that should be used. May be null if uri is absolute.
59
    * @return a Source object representing an XML document
60
    */
61

    
62
    public Source resolve(String href, String base)
63
    throws XPathException {
64

    
65
        // System.err.println("StandardURIResolver, href=" + href + ", base=" + base);
66

    
67
        String relativeURI = href;
68
        String id = null;
69

    
70
        // Extract any fragment identifier. Note, this code is no longer used to
71
        // resolve fragment identifiers in URI references passed to the document()
72
        // function: the code of the document() function handles these itself.
73

    
74
        int hash = href.indexOf('#');
75
        if (hash>=0) {
76
            relativeURI = href.substring(0, hash);
77
            id = href.substring(hash+1);
78
            // System.err.println("StandardURIResolver, href=" + href + ", id=" + id);
79
        }
80

    
81
        URIQueryParameters params = null;
82
        URI url;
83
        URI relative;
84
        try {
85
            relativeURI = escapeSpaces(relativeURI);
86
            relative = new URI(relativeURI);
87
        } catch (URISyntaxException err) {
88
            throw new DynamicError("Invalid relative URI " + Err.wrap(relativeURI), err);
89
        }
90

    
91
        String query = relative.getQuery();
92
        if (query != null && recognizeQueryParameters) {
93
            params = new URIQueryParameters(query, config);
94
            int q = relativeURI.indexOf('?');
95
            relativeURI = relativeURI.substring(0, q);
96
        }
97

    
98
        Source source = null;
99
        if (recognizeQueryParameters && relativeURI.endsWith(".ptree")) {
100
            source = getPTreeSource(relativeURI, base);
101
        }
102

    
103
        if (source == null) {
104
            try {
105
                url = makeAbsolute(relativeURI, base);
106
            } catch (URISyntaxException err) {
107
                // System.err.println("Recovering from " + err);
108
                // last resort: if the base URI is null, or is itself a relative URI, we
109
                // try to expand it relative to the current working directory
110
                String expandedBase = tryToExpand(base);
111
                if (!expandedBase.equals(base)) { // prevent infinite recursion
112
                    return resolve(href, expandedBase);
113
                }
114
                //err.printStackTrace();
115
                throw new DynamicError("Invalid URI " + Err.wrap(relativeURI) + " - base " + Err.wrap(base), err);
116
            }
117

    
118
            source = new SAXSource();
119
            ((SAXSource)source).setInputSource(new InputSource(url.toString()));
120
            source.setSystemId(url.toString());
121

    
122
            if (params != null) {
123
                XMLReader parser = params.getXMLReader();
124
                if (parser != null) {
125
                    ((SAXSource)source).setXMLReader(parser);
126
                }
127
            }
128

    
129
            if (((SAXSource)source).getXMLReader() == null) {
130
                if (config==null) {
131
                    try {
132
                        ((SAXSource)source).setXMLReader(SAXParserFactory.newInstance().newSAXParser().getXMLReader());
133
                    } catch (Exception err) {
134
                        throw new DynamicError(err);
135
                    }
136
                } else {
137
                    //((SAXSource)source).setXMLReader(config.getSourceParser());
138
                    // Leave the Sender to allocate an XMLReader, so that it can be returned to the pool after use
139
                }
140
            }
141
        }
142

    
143
        if (params != null) {
144
            int stripSpace = params.getStripSpace();
145
            switch (stripSpace) {
146
                case Whitespace.ALL: {
147
                    Stripper stripper = AllElementStripper.getInstance();
148
                    stripper.setStripAll();
149
                    source = AugmentedSource.makeAugmentedSource(source);
150
                    ((AugmentedSource)source).addFilter(stripper);
151
                    break;
152
                }
153
                case Whitespace.IGNORABLE:
154
                case Whitespace.NONE:
155
                    source = AugmentedSource.makeAugmentedSource(source);
156
                    ((AugmentedSource)source).setStripSpace(stripSpace);
157
            }
158
        }
159

    
160
        if (id != null) {
161
            IDFilter filter = new IDFilter(id);
162
            source = AugmentedSource.makeAugmentedSource(source);
163
            ((AugmentedSource)source).addFilter(filter);
164
        }
165

    
166
        if (params != null) {
167
            Integer validation = params.getValidationMode();
168
            if (validation != null) {
169
                source = AugmentedSource.makeAugmentedSource(source);
170
                ((AugmentedSource)source).setSchemaValidationMode(validation.intValue());
171
            }
172
        }
173

    
174
        return source;
175
    }
176

    
177
    /**
178
     * Combine the relative URI and base URI
179
     */
180

    
181
    public static URI makeAbsolute(String relativeURI, String base) throws DynamicError, URISyntaxException {
182
        URI url;
183
        relativeURI = escapeSpaces(relativeURI);
184
        base = escapeSpaces(base);
185
        try {
186
            if (base==null) {
187
                url = new URI(relativeURI);
188
                if (!url.isAbsolute()) {
189
                    String expandedBase = tryToExpand(base);
190
                    if (!expandedBase.equals(base)) { // prevent infinite recursion
191
                        return makeAbsolute(relativeURI, expandedBase);
192
                    }
193
                }
194
                // System.err.println("Resolved " + relativeURI + " as " + url.toString());
195
            } else {
196
                // System.err.println("Resolving " + relativeURI + " against " + base);
197
                URI baseURL = new URI(base);
198
                // System.err.println("Base URI " + base);
199
                url = (relativeURI.length()==0 ?
200
                                 baseURL :
201
                                 baseURL.resolve(relativeURI)
202
                             );
203
                // Note: an older version of this method incorrectly double-escaped percent signs,
204
                // for example %20 was escaped to %2520. We removed them by hand, as follows. But
205
                // the problem seems to have gone away (test mdocs31)
206
//                String u = url.toString();
207
//                int pc = u.indexOf("%25");
208
//                if (pc >= 0) {
209
//                    while (pc>=0) {
210
//                        u = u.substring(0, pc+1) + u.substring(pc+3);
211
//                        pc = u.indexOf("%25");
212
//                    }
213
//                    url = new URI(u);
214
//                }
215
                // System.err.println("Resolved URI " + url);
216
            }
217
        } catch (IllegalArgumentException err0) {
218
            // can be thrown by resolve() when given a bad URI
219
            throw new DynamicError("Invalid URI " + Err.wrap(relativeURI) + " - base " + Err.wrap(base));
220
        }
221
        return url;
222
    }
223

    
224
    /**
225
     * Replace spaces by %20
226
     */
227

    
228
    public static String escapeSpaces(String s) {
229
        // It's not entirely clear why we have to escape spaces by hand, and not other special characters;
230
        // it's just that tests with a variety of filenames show that this approach seems to work.
231
        if (s == null) return s;
232
        int i = s.indexOf(' ');
233
        if (i < 0) {
234
            return s;
235
        }
236
        return (i == 0 ? "" : s.substring(0, i))
237
                + "%20"
238
                + (i == s.length()-1 ? "" : escapeSpaces(s.substring(i+1)));
239
    }
240
    /**
241
    * If a system ID can't be parsed as a URL, we'll try to expand it as a relative
242
    * URI using the current directory as the base URI: MHK addition.
243
    */
244

    
245
    public static String tryToExpand(String systemId) {
246
        if (systemId==null) {
247
            systemId = "";
248
        }
249
	    try {
250
	        new URL(systemId);
251
	        return systemId;   // all is well
252
	    } catch (MalformedURLException err) {
253
	        String dir;
254
	        try {
255
	            dir = System.getProperty("user.dir");
256
	        } catch (Exception geterr) {
257
	            // this doesn't work when running an applet
258
	            return systemId;
259
	        }
260
	        if (!(dir.endsWith("/") || systemId.startsWith("/"))) {
261
	            dir = dir + '/';
262
	        }
263

    
264
	        try {
265
	            URL currentDirectoryURL = new File(dir).toURL();
266
	            URL baseURL = new URL(currentDirectoryURL, systemId);
267
	            // System.err.println("SAX Driver: expanded " + systemId + " to " + baseURL);
268
	            return baseURL.toString();
269
	        } catch (MalformedURLException err2) {
270
	            // go with the original one
271
	            return systemId;
272
	        }
273
	    }
274
	}
275

    
276
    /**
277
     * Handle a PTree source file (Saxon-SA only)
278
     */
279

    
280
    protected Source getPTreeSource(String href, String base) throws XPathException {
281
        return null;
282
    }
283

    
284
}
285

    
286
//
287
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
288
// you may not use this file except in compliance with the License. You may obtain a copy of the
289
// License at http://www.mozilla.org/MPL/
290
//
291
// Software distributed under the License is distributed on an "AS IS" basis,
292
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
293
// See the License for the specific language governing rights and limitations under the License.
294
//
295
// The Original Code is: all this file.
296
//
297
// The Initial Developer of the Original Code is Michael H. Kay.
298
//
299
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
300
//
301
// Contributor(s): none.
302
//
(22-22/29)