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 , XPathException {
55
+ var relativeURI = new URI (relative .getStringValue ());
56
+ if (relativeURI .isAbsolute ()) {
57
+ return relative ;
58
+ }
59
+ var baseURI = new URI (base .getStringValue () );
60
+ if (!baseURI .isAbsolute ()) {
61
+ return relative ;
62
+ }
63
+ try {
64
+ var xBase = XmldbURI .xmldbUriFor (baseURI );
65
+ var resolved = xBase .getURI ().resolve (relativeURI );
66
+ return new AnyURIValue (XmldbURI .XMLDB_URI_PREFIX + resolved );
67
+ } catch (URISyntaxException e ) {
68
+ return new AnyURIValue (baseURI .resolve (relativeURI ));
69
+ }
70
+ }
71
+
72
+ public static class CompileTimeURIResolver implements URIResolver {
73
+
74
+ private final XQueryContext xQueryContext ;
75
+ private final Expression containingExpression ;
76
+
77
+ public CompileTimeURIResolver (XQueryContext xQueryContext , Expression containingExpression ) {
78
+ this .xQueryContext = xQueryContext ;
79
+ this .containingExpression = containingExpression ;
80
+ }
81
+
82
+ @ Override
83
+ public Source resolve (final String href , final String base ) throws TransformerException {
84
+
85
+ try {
86
+ final AnyURIValue baseURI = new AnyURIValue (base );
87
+ final AnyURIValue hrefURI = new AnyURIValue (href );
88
+ var resolved = resolveURI (hrefURI , baseURI );
89
+ return resolveDocument (resolved .getStringValue ());
90
+ } catch (URISyntaxException e ) {
91
+ throw new TransformerException (
92
+ "Failed to resolve " + href + " against " + base , e );
93
+ } catch (XPathException e ) {
94
+ throw new TransformerException (
95
+ "Failed to find document as result of resolving " + href + " against " + base , e );
96
+ }
97
+ }
98
+
99
+ protected Source resolveDocument (final String location ) throws XPathException {
100
+ return URIResolution .resolveDocument (location , xQueryContext , containingExpression );
101
+ }
102
+ }
103
+
104
+ /**
105
+ * Resolve an absolute document location, stylesheet or included source
106
+ *
107
+ * @param location of the stylesheet
108
+ * @return the resolved stylesheet as a source
109
+ * @throws org.exist.xquery.XPathException if the item does not exist, or is not a document
110
+ */
111
+ static Source resolveDocument (final String location , final XQueryContext xQueryContext , Expression containingExpression ) throws XPathException {
112
+
113
+ final Sequence document ;
114
+ try {
115
+ document = DocUtils .getDocument (xQueryContext , location );
116
+ } catch (final PermissionDeniedException e ) {
117
+ throw new XPathException (containingExpression , ErrorCodes .FODC0002 ,
118
+ "Can not access '" + location + "'" + e .getMessage ());
119
+ }
120
+ if (document == null || document .isEmpty ()) {
121
+ throw new XPathException (containingExpression , ErrorCodes .FODC0002 ,
122
+ "No document found at location '" + location );
123
+ }
124
+ if (document .hasOne () && Type .subTypeOf (document .getItemType (), Type .NODE )) {
125
+ if (document instanceof NodeProxy proxy ) {
126
+ return new DOMSource (proxy .getNode ());
127
+ }
128
+ else if (document .itemAt (0 ) instanceof Node node ) {
129
+ return new DOMSource (node );
130
+ }
131
+ }
132
+ throw new XPathException (containingExpression , ErrorCodes .FODC0002 ,
133
+ "Location '" + location + "' returns an item which is not a document node" );
134
+ }
135
+ }
0 commit comments