1
+ /*
2
+ * eXist-db Open Source Native XML Database
3
+ * Copyright (C) 2001 The eXist-db Authors
4
+ *
5
+
6
+ * http://www.exist-db.org
7
+ *
8
+ * This library is free software; you can redistribute it and/or
9
+ * modify it under the terms of the GNU Lesser General Public
10
+ * License as published by the Free Software Foundation; either
11
+ * version 2.1 of the License, or (at your option) any later version.
12
+ *
13
+ * This library is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
+ * Lesser General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU Lesser General Public
19
+ * License along with this library; if not, write to the Free Software
20
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
+ */
22
+
23
+ package org .exist .xquery .functions .fn .transform ;
24
+
25
+ import org .exist .dom .persistent .NodeProxy ;
26
+ import org .exist .security .PermissionDeniedException ;
27
+ import org .exist .xmldb .XmldbURI ;
28
+ import org .exist .xquery .ErrorCodes ;
29
+ import org .exist .xquery .Expression ;
30
+ import org .exist .xquery .XPathException ;
31
+ import org .exist .xquery .XQueryContext ;
32
+ import org .exist .xquery .util .DocUtils ;
33
+ import org .exist .xquery .value .AnyURIValue ;
34
+ import org .exist .xquery .value .Sequence ;
35
+ import org .exist .xquery .value .Type ;
36
+ import org .w3c .dom .Node ;
37
+
38
+ import javax .xml .transform .Source ;
39
+ import javax .xml .transform .TransformerException ;
40
+ import javax .xml .transform .URIResolver ;
41
+ import javax .xml .transform .dom .DOMSource ;
42
+ import java .net .URI ;
43
+ import java .net .URISyntaxException ;
44
+
45
+ public class URIResolution {
46
+
47
+ /**
48
+ * URI resolution, the core should be the same as for fn:resolve-uri
49
+ * @param relative URI to resolve
50
+ * @param base to resolve against
51
+ * @return resolved URI
52
+ * @throws URISyntaxException if resolution is not possible
53
+ */
54
+ static AnyURIValue resolveURI (final AnyURIValue relative , final AnyURIValue base ) throws URISyntaxException {
55
+ var relativeURI = new URI (relative .getStringValue ());
56
+ if (relativeURI .isAbsolute ()) {
57
+ return relative ;
58
+ }
59
+ var baseURI = new URI (base .getStringValue () );
60
+ try {
61
+ var xBase = XmldbURI .xmldbUriFor (baseURI );
62
+ var resolved = xBase .getURI ().resolve (relativeURI );
63
+ return new AnyURIValue (XmldbURI .XMLDB_URI_PREFIX + resolved );
64
+ } catch (URISyntaxException e ) {
65
+ return new AnyURIValue (baseURI .resolve (relativeURI ));
66
+ } catch (XPathException e ) {
67
+ throw new RuntimeException (e );
68
+ }
69
+ }
70
+
71
+ static public class CompileTimeURIResolver implements URIResolver {
72
+
73
+ private final XQueryContext xQueryContext ;
74
+ private final Expression containingExpression ;
75
+
76
+ public CompileTimeURIResolver (XQueryContext xQueryContext , Expression containingExpression ) {
77
+ this .xQueryContext = xQueryContext ;
78
+ this .containingExpression = containingExpression ;
79
+ }
80
+
81
+ @ Override
82
+ public Source resolve (final String href , final String base ) throws TransformerException {
83
+
84
+ try {
85
+ final AnyURIValue baseURI = new AnyURIValue (base );
86
+ final AnyURIValue hrefURI = new AnyURIValue (href );
87
+ var resolved = resolveURI (hrefURI , baseURI );
88
+ return resolveDocument (resolved .getStringValue (), xQueryContext , containingExpression );
89
+ } catch (URISyntaxException e ) {
90
+ throw new TransformerException ("Failed to resolve " +
91
+ href +
92
+ " against " +
93
+ base , e );
94
+ } catch (org .exist .xquery .XPathException e ) {
95
+ throw new TransformerException ("Failed to find document as result of resolving " +
96
+ href +
97
+ " against " +
98
+ base , e );
99
+ }
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Resolve an absolute document location, stylesheet or included source
105
+ *
106
+ * @param location of the stylesheet
107
+ * @return the resolved stylesheet as a source
108
+ * @throws org.exist.xquery.XPathException if the item does not exist, or is not a document
109
+ */
110
+ static Source resolveDocument (final String location , final XQueryContext xQueryContext , Expression containingExpression ) throws org .exist .xquery .XPathException {
111
+
112
+ final Sequence document ;
113
+ try {
114
+ document = DocUtils .getDocument (xQueryContext , location );
115
+ } catch (final PermissionDeniedException e ) {
116
+ throw new org .exist .xquery .XPathException (containingExpression , ErrorCodes .FODC0002 ,
117
+ "Can not access '" + location + "'" + e .getMessage ());
118
+ }
119
+ if (document == null || document .isEmpty ()) {
120
+ throw new org .exist .xquery .XPathException (containingExpression , ErrorCodes .FODC0002 ,
121
+ "No document found at location '" + location );
122
+ }
123
+ if (document .hasOne () && Type .subTypeOf (document .getItemType (), Type .NODE )) {
124
+ if (document instanceof NodeProxy proxy ) {
125
+ return new DOMSource (proxy .getNode ());
126
+ }
127
+ else if (document .itemAt (0 ) instanceof Node node ) {
128
+ return new DOMSource (node );
129
+ }
130
+ }
131
+ throw new org .exist .xquery .XPathException (containingExpression , ErrorCodes .FODC0002 ,
132
+ "Location '" + location + "' returns an item which is not a document node" );
133
+ }
134
+ }
0 commit comments