28
28
import org .apache .jena .rdf .model .Statement ;
29
29
import org .apache .jena .rdf .model .StmtIterator ;
30
30
import org .apache .jena .riot .RDFDataMgr ;
31
- import org .apache .jena .riot .RiotNotFoundException ;
32
31
import org .apache .jena .shared .PropertyNotFoundException ;
33
32
import org .slf4j .Logger ;
34
33
import org .slf4j .LoggerFactory ;
35
34
35
+ import java .io .IOException ;
36
+ import java .net .HttpURLConnection ;
37
+ import java .net .URL ;
38
+ import java .net .URLConnection ;
36
39
import java .util .ArrayList ;
37
40
import java .util .Collections ;
38
41
import java .util .HashMap ;
39
42
import java .util .Map ;
40
43
import java .util .NoSuchElementException ;
41
- import java .util .Set ;
42
44
43
45
/**
44
46
* Provides a dynamically build {@link Map} based on an RDF resource. Can be one file or a comma separated list of RDF
45
- * files or an HTTP(S) URI.
47
+ * files or an HTTP(S) URI. Redirections of HTTP(S) URIs are followed.
46
48
* The resources are supposed to be UTF-8 encoded.
47
49
* <p>
48
50
*
@@ -57,6 +59,10 @@ public final class RdfMap extends AbstractReadOnlyMap<String, String> {
57
59
private static String targetLanguage = "" ;
58
60
private static String target ;
59
61
private static final Logger LOG = LoggerFactory .getLogger (RdfMap .class );
62
+ private static final int MAX_REDIRECTIONS = 10 ;
63
+ private static final int MIN_HTTP_STATUS_CODE = 299 ;
64
+ private static final int MAX_HTTP_STATUS_CODE = 400 ;
65
+
60
66
private Model model ;
61
67
private boolean isUninitialized = true ;
62
68
private final ArrayList <String > filenames = new ArrayList <>();
@@ -104,15 +110,19 @@ private void loadFiles() {
104
110
}
105
111
106
112
private void loadFile (final String file ) {
113
+ String f = file ;
107
114
try {
115
+ if (file .toLowerCase ().startsWith ("http" )) {
116
+ f = read (file );
117
+ }
108
118
if (model == null ) {
109
- model = RDFDataMgr .loadModel (file );
119
+ model = RDFDataMgr .loadModel (f );
110
120
}
111
121
else {
112
- RDFDataMgr .read (model , file );
122
+ RDFDataMgr .read (model , f );
113
123
}
114
124
}
115
- catch (final RiotNotFoundException e ) {
125
+ catch (final IOException e ) {
116
126
throw new FixExecutionException ("rdf file: cannot read file" , e );
117
127
}
118
128
}
@@ -140,7 +150,7 @@ public String get(final Object key) {
140
150
if (isUninitialized ) {
141
151
init ();
142
152
}
143
- String ret = Maps . DEFAULT_MAP_KEY ;
153
+ String ret ;
144
154
if (map .containsKey (key .toString ())) {
145
155
ret = map .get (key .toString ());
146
156
}
@@ -160,7 +170,7 @@ public String get(final Object key) {
160
170
//second try to get SUBJECT using PROPERTY and LITERAL
161
171
ret = getSubjectUsingPropertyAndLiteral (key , targetProperty );
162
172
//third try: get LITERAL of PREDICATE A using PREDICATE B
163
- if (ret == Maps .DEFAULT_MAP_KEY ) {
173
+ if (ret . equals ( Maps .DEFAULT_MAP_KEY ) ) {
164
174
ret = getLiteralOfPredicateUsingOtherPredicate (key , targetProperty );
165
175
}
166
176
else {
@@ -180,7 +190,7 @@ private String getLiteralOfPredicateUsingOtherPredicate(final Object key, final
180
190
while (iter .hasNext ()) {
181
191
resource = iter .nextResource ();
182
192
if (resource .getProperty (targetProperty ).getString ().equals (key .toString ())) {
183
- Statement stmt = resource . getProperty ( targetProperty ) ;
193
+ Statement stmt ;
184
194
final StmtIterator iterProp = resource .listProperties (targetProperty );
185
195
while (iterProp .hasNext ()) {
186
196
stmt = iterProp .nextStatement ();
@@ -213,14 +223,6 @@ private String getSubjectUsingPropertyAndLiteral(final Object key, final Propert
213
223
return ret ;
214
224
}
215
225
216
- @ Override
217
- public Set <String > keySet () {
218
- if (isUninitialized ) {
219
- init ();
220
- }
221
- return Collections .unmodifiableSet (map .keySet ());
222
- }
223
-
224
226
/**
225
227
* Sets the language of the target Property which is queried in the RDF. Valid values are defined by BCP47.
226
228
* <br>
@@ -253,4 +255,48 @@ public void setTarget(final String target) {
253
255
public void setDefault (final String defaultValue ) {
254
256
map .put (Maps .DEFAULT_MAP_KEY , defaultValue );
255
257
}
258
+
259
+ /**
260
+ * Gets a redirected URL, if any redirection takes place. Adapted predated code from org.apache.jena.rdfxml.xmlinput.JenaReader.
261
+ *
262
+ * @Deprecated Using newer jena version (needs java 11) this method would be obsolete.
263
+ * @param url the URL to resolve
264
+ * @return the (redirected) URL
265
+ * @throws IOException if any IO error occurs
266
+ */
267
+ private String read (final String url ) throws IOException {
268
+ String connectionURL = url ;
269
+ try {
270
+ int count = 0 ;
271
+ URLConnection conn ;
272
+ while (true ) {
273
+ final URLConnection conn2 = new URL (connectionURL ).openConnection ();
274
+ if (!(conn2 instanceof HttpURLConnection )) {
275
+ conn = conn2 ;
276
+ break ;
277
+ }
278
+ count += 1 ;
279
+ if (count > MAX_REDIRECTIONS ) {
280
+ throw new IOException ("Too many redirects followed for " + url );
281
+ }
282
+ final HttpURLConnection httpURLConnection = (HttpURLConnection ) conn2 ;
283
+ conn2 .setRequestProperty ("accept" , "*/*" );
284
+ final int statusCode = httpURLConnection .getResponseCode ();
285
+ if (statusCode <= MIN_HTTP_STATUS_CODE || statusCode >= MAX_HTTP_STATUS_CODE ) {
286
+ conn = conn2 ;
287
+ break ;
288
+ }
289
+ // Redirect
290
+ connectionURL = conn2 .getHeaderField ("Location" );
291
+ if (connectionURL == null || url .equals (connectionURL )) {
292
+ throw new IOException ("Failed to follow redirects for " + url );
293
+ }
294
+ }
295
+ connectionURL = conn .getURL ().toString ();
296
+ }
297
+ catch (final IOException e ) {
298
+ throw new IOException (e );
299
+ }
300
+ return connectionURL ;
301
+ }
256
302
}
0 commit comments