1
2
3
4
5
6 package org.openrdf.repository.loader;
7
8 import java.io.IOException;
9 import java.net.URL;
10 import java.net.URLConnection;
11 import java.util.Enumeration;
12 import java.util.Map;
13 import java.util.Properties;
14 import java.util.concurrent.ConcurrentHashMap;
15
16 import org.openrdf.model.URI;
17 import org.openrdf.model.ValueFactory;
18 import org.openrdf.repository.Repository;
19 import org.openrdf.repository.RepositoryConnection;
20 import org.openrdf.repository.RepositoryException;
21 import org.openrdf.repository.base.RepositoryWrapper;
22 import org.openrdf.rio.RDFFormat;
23 import org.openrdf.rio.RDFParseException;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26
27
28
29
30
31
32
33 public class LoaderRepository extends RepositoryWrapper {
34 private final Logger logger = LoggerFactory
35 .getLogger(LoaderRepository.class);
36 private Map<URL, Map<URL, URI>> index = new ConcurrentHashMap<URL, Map<URL, URI>>();
37 private ClassLoader cl = Thread.currentThread().getContextClassLoader();
38 private long lastModified;
39
40 public LoaderRepository() {
41 super();
42 }
43
44 public LoaderRepository(Repository delegate) {
45 super(delegate);
46 }
47
48 public synchronized void loadResources(String path) throws IOException,
49 RepositoryException, RDFParseException {
50 refresh();
51 Enumeration<URL> resources = cl.getResources(path);
52 if (!resources.hasMoreElements()) {
53 ClassLoader classLoader = LoaderRepository.class.getClassLoader();
54 resources = classLoader.getResources(path);
55 }
56 if (!resources.hasMoreElements())
57 throw new IllegalArgumentException(path + " not found");
58 while (resources.hasMoreElements()) {
59 URL resource = resources.nextElement();
60 Map<URL, URI> map = new ConcurrentHashMap<URL, URI>();
61 loadIndex(resource, resource.openConnection(), map);
62 index.put(resource, map);
63 for (Map.Entry<URL, URI> e : map.entrySet()) {
64 reload(e.getKey(), e.getKey().openConnection(), e.getValue());
65 }
66 }
67 lastModified = System.currentTimeMillis();
68 }
69
70 public synchronized void loadContext(URL dataset, URI context)
71 throws IOException, RepositoryException, RDFParseException {
72 Map<URL, URI> map = new ConcurrentHashMap<URL, URI>();
73 map.put(dataset, context);
74 index.put(dataset, map);
75 reload(dataset, dataset.openConnection(), context);
76 }
77
78 @Override
79 public RepositoryConnection getConnection() throws RepositoryException {
80 try {
81 refresh();
82 } catch (IOException e) {
83 throw new RepositoryException(e);
84 } catch (RDFParseException e) {
85 throw new RepositoryException(e);
86 }
87 return super.getConnection();
88 }
89
90 @Override
91 public void shutDown() throws RepositoryException {
92 clearLoadedContexts();
93 super.shutDown();
94 }
95
96 public void clearLoadedContexts() throws RepositoryException {
97 RepositoryConnection conn = super.getConnection();
98 try {
99 conn.setAutoCommit(false);
100 for (Map.Entry<URL, Map<URL, URI>> e : index.entrySet()) {
101 for (Map.Entry<URL, URI> f : e.getValue().entrySet()) {
102 conn.clear(f.getValue());
103 }
104 }
105 conn.commit();
106 } finally {
107 conn.close();
108 }
109 }
110
111 private void refresh() throws IOException, RepositoryException,
112 RDFParseException {
113 URLConnection open;
114 long modified = lastModified;
115 for (Map.Entry<URL, Map<URL, URI>> e : index.entrySet()) {
116 open = getUrlIfNeeded(e);
117 if (open != null) {
118 long m = loadIndex(e.getKey(), open, e.getValue());
119 if (m > modified) {
120 modified = m;
121 }
122 }
123 for (Map.Entry<URL, URI> f : e.getValue().entrySet()) {
124 open = getUrlIfNeeded(f.getKey());
125 if (open != null) {
126 long m = reload(f.getKey(), open, f.getValue());
127 if (m > modified) {
128 modified = m;
129 }
130 }
131 }
132 }
133 lastModified = modified;
134 }
135
136 private URI createURI(String context, URL dataset) {
137 ValueFactory vf = getValueFactory();
138 if (context == null || context.length() == 0)
139 return vf.createURI(dataset.toExternalForm());
140 return vf.createURI(context);
141 }
142
143 private URLConnection getUrlIfNeeded(Map.Entry<URL, ?> e)
144 throws IOException, RepositoryException {
145 if (e.getValue() == null)
146 return e.getKey().openConnection();
147 return getUrlIfNeeded(e.getKey());
148 }
149
150 private URLConnection getUrlIfNeeded(URL url) throws IOException,
151 RepositoryException {
152 URLConnection open = url.openConnection();
153 if (lastModified == 0)
154 return open;
155 open.setIfModifiedSince(lastModified);
156 if (open.getLastModified() > lastModified)
157 return open;
158 return null;
159 }
160
161 private synchronized long loadIndex(URL url, URLConnection conn,
162 Map<URL, URI> map) throws IOException {
163 long modified = conn.getLastModified();
164 RDFFormat format = findRdfFormat(url, conn, null);
165 if (format == null) {
166 Properties p = new Properties();
167 p.load(conn.getInputStream());
168 map.clear();
169 for (Map.Entry e : p.entrySet()) {
170 String path = e.getKey().toString();
171 String context = e.getValue().toString();
172 Enumeration<URL> resources = cl.getResources(path);
173 while (resources.hasMoreElements()) {
174 URL dataset = resources.nextElement();
175 map.put(dataset, createURI(context, dataset));
176 }
177 }
178 } else if (!map.containsKey(url)) {
179 map.put(url, createURI(null, url));
180 }
181 return modified;
182 }
183
184 private synchronized long reload(URL dataset, URLConnection url, URI context)
185 throws RepositoryException, IOException, RDFParseException {
186 RDFFormat format = findRdfFormat(dataset, url, RDFFormat.RDFXML);
187 logger.info("Loading {}", dataset);
188 long modified = url.getLastModified();
189 RepositoryConnection conn = super.getConnection();
190 try {
191 conn.setAutoCommit(false);
192 conn.clear(context);
193 conn.add(url.getInputStream(), dataset.toExternalForm(), format,
194 context);
195 conn.commit();
196 } finally {
197 conn.close();
198 }
199 return modified;
200 }
201
202 private RDFFormat findRdfFormat(URL url, URLConnection conn,
203 RDFFormat defaultFormat) {
204 RDFFormat format = RDFFormat.forMIMEType(conn.getContentType());
205 if (format == null) {
206 format = RDFFormat.forFileName(url.getFile(), defaultFormat);
207 }
208 return format;
209 }
210 }