Project

Profile

Help

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

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

1
package net.sf.saxon;
2
import net.sf.saxon.event.IDFilter;
3
import net.sf.saxon.event.Stripper;
4
import net.sf.saxon.functions.URIQueryParameters;
5
import net.sf.saxon.om.AllElementStripper;
6
import net.sf.saxon.trans.DynamicError;
7
import net.sf.saxon.trans.XPathException;
8
import net.sf.saxon.value.Whitespace;
9
import org.xml.sax.InputSource;
10
import org.xml.sax.XMLReader;
11

    
12
import javax.xml.parsers.SAXParserFactory;
13
import javax.xml.transform.Source;
14
import javax.xml.transform.sax.SAXSource;
15
import java.io.File;
16
import java.io.Serializable;
17
import java.net.MalformedURLException;
18
import java.net.URI;
19
import java.net.URISyntaxException;
20
import java.net.URL;
21

    
22

    
23
/**
24
* This class provides the service of converting a URI into an InputSource.
25
* It is used to get stylesheet modules referenced by xsl:import and xsl:include,
26
* and source documents referenced by the document() function. The standard version
27
* handles anything that the java URL class will handle.
28
* You can write a subclass to handle other kinds of URI, e.g. references to things in
29
* a database.
30
* @author Michael H. Kay
31
*/
32

    
33
public class StandardURIResolver implements NonDelegatingURIResolver, Serializable {
34

    
35
    // TODO: support the data: URI scheme. (Requires unescaping of the URI, then parsing the content as XML)
36

    
37
    private Configuration config = null;
38
    protected boolean recognizeQueryParameters = false;
39

    
40
    /**
41
     * Create a StandardURIResolver, with no reference to a TransformerFactory
42
     */
43
    public StandardURIResolver() {
44
        this(null);
45
    }
46

    
47
    /**
48
     * Create a StandardURIResolver, with a reference to a TransformerFactory
49
     * @param config The Configuration object.
50
     * This is used to get a SAX Parser for a source XML document
51
     */
52

    
53
    public StandardURIResolver(Configuration config) {
54
        this.config = config;
55
    }
56

    
57
    /**
58
     * Indicate that query parameters (such as ?validation=strict) are to be recognized
59
     * @param recognize Set to true if query parameters in the URI are to be recognized and acted upon.
60
     * The default (for compatibility and interoperability reasons) is false.
61
     */
62

    
63
    public void setRecognizeQueryParameters(boolean recognize) {
64
        recognizeQueryParameters = recognize;
65
    }
66

    
67
    /**
68
     * Determine whether query parameters (such as ?validation=strict) are to be recognized
69
     * @return true if query parameters are recognized and interpreted by Saxon.
70
     */
71

    
72
    public boolean queryParametersAreRecognized() {
73
        return recognizeQueryParameters;
74
    }
75

    
76
    /**
77
    * Resolve a URI
78
    * @param href The relative or absolute URI. May be an empty string. May contain
79
    * a fragment identifier starting with "#", which must be the value of an ID attribute
80
    * in the referenced XML document.
81
    * @param base The base URI that should be used. May be null if uri is absolute.
82
    * @return a Source object representing an XML document
83
    */
84

    
85
    public Source resolve(String href, String base)
86
    throws XPathException {
87

    
88
        // System.err.println("StandardURIResolver, href=" + href + ", base=" + base);
89

    
90
        String relativeURI = href;
91
        String id = null;
92

    
93
        // Extract any fragment identifier. Note, this code is no longer used to
94
        // resolve fragment identifiers in URI references passed to the document()
95
        // function: the code of the document() function handles these itself.
96

    
97
        int hash = href.indexOf('#');
98
        if (hash>=0) {
99
            relativeURI = href.substring(0, hash);
100
            id = href.substring(hash+1);
101
            // System.err.println("StandardURIResolver, href=" + href + ", id=" + id);
102
        }
103

    
104
        URIQueryParameters params = null;
105
        URI url;
106
        URI relative;
107
        try {
108
            relativeURI = escapeSpaces(relativeURI);
109
            relative = new URI(relativeURI);
110
        } catch (URISyntaxException err) {
111
            throw new DynamicError("Invalid relative URI " + Err.wrap(relativeURI), err);
112
        }
113

    
114
        String query = relative.getQuery();
115
        if (query != null && recognizeQueryParameters) {
116
            params = new URIQueryParameters(query, config);
117
            int q = relativeURI.indexOf('?');
118
            relativeURI = relativeURI.substring(0, q);
119
        }
120

    
121
        Source source = null;
122
        if (recognizeQueryParameters && relativeURI.endsWith(".ptree")) {
123
            source = getPTreeSource(relativeURI, base);
124
        }
125

    
126
        if (source == null) {
127
            try {
128
                url = makeAbsolute(relativeURI, base);
129
            } catch (URISyntaxException err) {
130
                // System.err.println("Recovering from " + err);
131
                // last resort: if the base URI is null, or is itself a relative URI, we
132
                // try to expand it relative to the current working directory
133
                String expandedBase = tryToExpand(base);
134
                if (!expandedBase.equals(base)) { // prevent infinite recursion
135
                    return resolve(href, expandedBase);
136
                }
137
                //err.printStackTrace();
138
                throw new DynamicError("Invalid URI " + Err.wrap(relativeURI) + " - base " + Err.wrap(base), err);
139
            }
140

    
141
            source = new SAXSource();
142
            ((SAXSource)source).setInputSource(new InputSource(url.toString()));
143
            source.setSystemId(url.toString());
144

    
145
            if (params != null) {
146
                XMLReader parser = params.getXMLReader();
147
                if (parser != null) {
148
                    ((SAXSource)source).setXMLReader(parser);
149
                }
150
            }
151

    
152
            if (((SAXSource)source).getXMLReader() == null) {
153
                if (config==null) {
154
                    try {
155
                        ((SAXSource)source).setXMLReader(SAXParserFactory.newInstance().newSAXParser().getXMLReader());
156
                    } catch (Exception err) {
157
                        throw new DynamicError(err);
158
                    }
159
                } else {
160
                    //((SAXSource)source).setXMLReader(config.getSourceParser());
161
                    // Leave the Sender to allocate an XMLReader, so that it can be returned to the pool after use
162
                }
163
            }
164
        }
165

    
166
        if (params != null) {
167
            int stripSpace = params.getStripSpace();
168
            switch (stripSpace) {
169
                case Whitespace.ALL: {
170
                    Stripper stripper = AllElementStripper.getInstance();
171
                    stripper.setStripAll();
172
                    source = AugmentedSource.makeAugmentedSource(source);
173
                    ((AugmentedSource)source).addFilter(stripper);
174
                    break;
175
                }
176
                case Whitespace.IGNORABLE:
177
                case Whitespace.NONE:
178
                    source = AugmentedSource.makeAugmentedSource(source);
179
                    ((AugmentedSource)source).setStripSpace(stripSpace);
180
            }
181
        }
182

    
183
        if (id != null) {
184
            IDFilter filter = new IDFilter(id);
185
            source = AugmentedSource.makeAugmentedSource(source);
186
            ((AugmentedSource)source).addFilter(filter);
187
        }
188

    
189
        if (params != null) {
190
            Integer validation = params.getValidationMode();
191
            if (validation != null) {
192
                source = AugmentedSource.makeAugmentedSource(source);
193
                ((AugmentedSource)source).setSchemaValidationMode(validation.intValue());
194
            }
195
        }
196

    
197
        return source;
198
    }
199

    
200
    /**
201
     * Combine the relative URI and base URI
202
     */
203

    
204
    public static URI makeAbsolute(String relativeURI, String base) throws DynamicError, URISyntaxException {
205
        URI url;
206
        relativeURI = escapeSpaces(relativeURI);
207
        base = escapeSpaces(base);
208
        try {
209
            if (base==null) {
210
                url = new URI(relativeURI);
211
                if (!url.isAbsolute()) {
212
                    String expandedBase = tryToExpand(base);
213
                    if (!expandedBase.equals(base)) { // prevent infinite recursion
214
                        return makeAbsolute(relativeURI, expandedBase);
215
                    }
216
                }
217
                // System.err.println("Resolved " + relativeURI + " as " + url.toString());
218
            } else {
219
                // System.err.println("Resolving " + relativeURI + " against " + base);
220
                URI baseURL = new URI(base);
221
                // System.err.println("Base URI " + base);
222
                url = (relativeURI.length()==0 ?
223
                                 baseURL :
224
                                 baseURL.resolve(relativeURI)
225
                             );
226
                // Note: an older version of this method incorrectly double-escaped percent signs,
227
                // for example %20 was escaped to %2520. We removed them by hand, as follows. But
228
                // the problem seems to have gone away (test mdocs31)
229
//                String u = url.toString();
230
//                int pc = u.indexOf("%25");
231
//                if (pc >= 0) {
232
//                    while (pc>=0) {
233
//                        u = u.substring(0, pc+1) + u.substring(pc+3);
234
//                        pc = u.indexOf("%25");
235
//                    }
236
//                    url = new URI(u);
237
//                }
238
                // System.err.println("Resolved URI " + url);
239
            }
240
        } catch (IllegalArgumentException err0) {
241
            // can be thrown by resolve() when given a bad URI
242
            throw new DynamicError("Invalid URI " + Err.wrap(relativeURI) + " - base " + Err.wrap(base));
243
        }
244
        return url;
245
    }
246

    
247
    /**
248
     * Replace spaces by %20
249
     */
250

    
251
    public static String escapeSpaces(String s) {
252
        // It's not entirely clear why we have to escape spaces by hand, and not other special characters;
253
        // it's just that tests with a variety of filenames show that this approach seems to work.
254
        if (s == null) return s;
255
        int i = s.indexOf(' ');
256
        if (i < 0) {
257
            return s;
258
        }
259
        return (i == 0 ? "" : s.substring(0, i))
260
                + "%20"
261
                + (i == s.length()-1 ? "" : escapeSpaces(s.substring(i+1)));
262
    }
263
    /**
264
    * If a system ID can't be parsed as a URL, we'll try to expand it as a relative
265
    * URI using the current directory as the base URI: MHK addition.
266
    */
267

    
268
    public static String tryToExpand(String systemId) {
269
        if (systemId==null) {
270
            systemId = "";
271
        }
272
	    try {
273
	        new URL(systemId);
274
	        return systemId;   // all is well
275
	    } catch (MalformedURLException err) {
276
	        String dir;
277
	        try {
278
	            dir = System.getProperty("user.dir");
279
	        } catch (Exception geterr) {
280
	            // this doesn't work when running an applet
281
	            return systemId;
282
	        }
283
	        if (!(dir.endsWith("/") || systemId.startsWith("/"))) {
284
	            dir = dir + '/';
285
	        }
286

    
287
	        try {
288
	            URL currentDirectoryURL = new File(dir).toURL();
289
	            URL baseURL = new URL(currentDirectoryURL, systemId);
290
	            // System.err.println("SAX Driver: expanded " + systemId + " to " + baseURL);
291
	            return baseURL.toString();
292
	        } catch (MalformedURLException err2) {
293
	            // go with the original one
294
	            return systemId;
295
	        }
296
	    }
297
	}
298

    
299
    /**
300
     * Handle a PTree source file (Saxon-SA only)
301
     */
302

    
303
    protected Source getPTreeSource(String href, String base) throws XPathException {
304
        return null;
305
    }
306

    
307
}
308

    
309
//
310
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
311
// you may not use this file except in compliance with the License. You may obtain a copy of the
312
// License at http://www.mozilla.org/MPL/
313
//
314
// Software distributed under the License is distributed on an "AS IS" basis,
315
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
316
// See the License for the specific language governing rights and limitations under the License.
317
//
318
// The Original Code is: all this file.
319
//
320
// The Initial Developer of the Original Code is Michael H. Kay.
321
//
322
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
323
//
324
// Contributor(s): none.
325
//
(23-23/29)