001: /*
002: * Copyright Aduna (http://www.aduna-software.com/) (c) 2006-2007.
003: *
004: * Licensed under the Aduna BSD-style license.
005: */
006: package org.openrdf.repository.http;
007:
008: import java.io.IOException;
009: import java.io.InputStream;
010: import java.io.Reader;
011: import java.util.ArrayList;
012: import java.util.Collections;
013: import java.util.List;
014:
015: import info.aduna.iteration.CloseableIteratorIteration;
016:
017: import org.openrdf.http.client.HTTPClient;
018: import org.openrdf.http.protocol.transaction.operations.AddStatementOperation;
019: import org.openrdf.http.protocol.transaction.operations.ClearNamespacesOperation;
020: import org.openrdf.http.protocol.transaction.operations.ClearOperation;
021: import org.openrdf.http.protocol.transaction.operations.RemoveNamespaceOperation;
022: import org.openrdf.http.protocol.transaction.operations.RemoveStatementsOperation;
023: import org.openrdf.http.protocol.transaction.operations.SetNamespaceOperation;
024: import org.openrdf.http.protocol.transaction.operations.TransactionOperation;
025: import org.openrdf.model.Literal;
026: import org.openrdf.model.Namespace;
027: import org.openrdf.model.Resource;
028: import org.openrdf.model.Statement;
029: import org.openrdf.model.URI;
030: import org.openrdf.model.Value;
031: import org.openrdf.model.impl.NamespaceImpl;
032: import org.openrdf.query.BindingSet;
033: import org.openrdf.query.BooleanQuery;
034: import org.openrdf.query.GraphQuery;
035: import org.openrdf.query.Query;
036: import org.openrdf.query.QueryEvaluationException;
037: import org.openrdf.query.QueryLanguage;
038: import org.openrdf.query.TupleQuery;
039: import org.openrdf.query.TupleQueryResult;
040: import org.openrdf.repository.RepositoryException;
041: import org.openrdf.repository.RepositoryResult;
042: import org.openrdf.repository.base.RepositoryConnectionBase;
043: import org.openrdf.rio.RDFFormat;
044: import org.openrdf.rio.RDFHandler;
045: import org.openrdf.rio.RDFHandlerException;
046: import org.openrdf.rio.RDFParseException;
047: import org.openrdf.rio.helpers.StatementCollector;
048:
049: /**
050: * RepositoryConnection that communicates with a server using the HTTP protocol.
051: * Methods in this class may throw the specific RepositoryException subclasses
052: * UnautorizedException and NotAllowedException, the semantics of which are
053: * defined by the HTTP protocol.
054: *
055: * @see org.openrdf.http.protocol.UnauthorizedException
056: * @see org.openrdf.http.protocol.NotAllowedException
057: * @author Arjohn Kampman
058: * @author Herko ter Horst
059: */
060: class HTTPRepositoryConnection extends RepositoryConnectionBase {
061:
062: /*-----------*
063: * Variables *
064: *-----------*/
065:
066: private List<TransactionOperation> txn = Collections
067: .synchronizedList(new ArrayList<TransactionOperation>());
068:
069: /*--------------*
070: * Constructors *
071: *--------------*/
072:
073: public HTTPRepositoryConnection(HTTPRepository repository) {
074: super (repository);
075: }
076:
077: /*---------*
078: * Methods *
079: *---------*/
080:
081: @Override
082: public HTTPRepository getRepository() {
083: return (HTTPRepository) super .getRepository();
084: }
085:
086: /**
087: * Unsupported method, throws an {@link UnsupportedOperationException}.
088: */
089: public Query prepareQuery(QueryLanguage ql, String queryString,
090: String baseURI) {
091: throw new UnsupportedOperationException();
092: }
093:
094: public TupleQuery prepareTupleQuery(QueryLanguage ql,
095: String queryString, String baseURI) {
096: return new HTTPTupleQuery(this , ql, queryString, baseURI);
097: }
098:
099: public GraphQuery prepareGraphQuery(QueryLanguage ql,
100: String queryString, String baseURI) {
101: return new HTTPGraphQuery(this , ql, queryString, baseURI);
102: }
103:
104: public BooleanQuery prepareBooleanQuery(QueryLanguage ql,
105: String queryString, String baseURI) {
106: return new HTTPBooleanQuery(this , ql, queryString, baseURI);
107: }
108:
109: public RepositoryResult<Resource> getContextIDs()
110: throws RepositoryException {
111: try {
112: List<Resource> contextList = new ArrayList<Resource>();
113:
114: TupleQueryResult contextIDs = getRepository()
115: .getHTTPClient().getContextIDs();
116: try {
117: while (contextIDs.hasNext()) {
118: BindingSet bindingSet = contextIDs.next();
119: Value context = bindingSet.getValue("contextID");
120:
121: if (context instanceof Resource) {
122: contextList.add((Resource) context);
123: }
124: }
125: } finally {
126: contextIDs.close();
127: }
128:
129: return createRepositoryResult(contextList);
130: } catch (QueryEvaluationException e) {
131: throw new RepositoryException(e);
132: } catch (IOException e) {
133: throw new RepositoryException(e);
134: }
135: }
136:
137: public RepositoryResult<Statement> getStatements(Resource subj,
138: URI pred, Value obj, boolean includeInferred,
139: Resource... contexts) throws RepositoryException {
140: try {
141: StatementCollector collector = new StatementCollector();
142: exportStatements(subj, pred, obj, includeInferred,
143: collector, contexts);
144: return createRepositoryResult(collector.getStatements());
145: } catch (RDFHandlerException e) {
146: // found a bug in StatementCollector?
147: throw new RuntimeException(e);
148: }
149: }
150:
151: public void exportStatements(Resource subj, URI pred, Value obj,
152: boolean includeInferred, RDFHandler handler,
153: Resource... contexts) throws RDFHandlerException,
154: RepositoryException {
155: try {
156: getRepository().getHTTPClient().getStatements(subj, pred,
157: obj, includeInferred, handler, contexts);
158: } catch (IOException e) {
159: throw new RepositoryException(e);
160: }
161: }
162:
163: public long size(Resource... contexts) throws RepositoryException {
164: try {
165: return getRepository().getHTTPClient().size(contexts);
166: } catch (IOException e) {
167: throw new RepositoryException(e);
168: }
169: }
170:
171: public void commit() throws RepositoryException {
172: synchronized (txn) {
173: if (txn.size() > 0) {
174: try {
175: getRepository().getHTTPClient()
176: .sendTransaction(txn);
177: txn.clear();
178: } catch (IOException e) {
179: throw new RepositoryException(e);
180: }
181: }
182: }
183: }
184:
185: public void rollback() {
186: txn.clear();
187: }
188:
189: @Override
190: public void close() throws RepositoryException {
191: if (txn.size() > 0) {
192: logger.warn(
193: "Rolling back transaction due to connection close",
194: new Throwable());
195: rollback();
196: }
197:
198: super .close();
199: }
200:
201: @Override
202: protected void addInputStreamOrReader(Object inputStreamOrReader,
203: String baseURI, RDFFormat dataFormat, Resource... contexts)
204: throws IOException, RDFParseException, RepositoryException {
205: if (isAutoCommit()) {
206: // Send bytes directly to the server
207: HTTPClient httpClient = getRepository().getHTTPClient();
208: if (inputStreamOrReader instanceof InputStream) {
209: httpClient.upload(((InputStream) inputStreamOrReader),
210: baseURI, dataFormat, false, contexts);
211: } else if (inputStreamOrReader instanceof Reader) {
212: httpClient.upload(((Reader) inputStreamOrReader),
213: baseURI, dataFormat, false, contexts);
214: } else {
215: throw new IllegalArgumentException(
216: "inputStreamOrReader must be an InputStream or a Reader, is a: "
217: + inputStreamOrReader.getClass());
218: }
219: } else {
220: // Parse files locally
221: super .addInputStreamOrReader(inputStreamOrReader, baseURI,
222: dataFormat, contexts);
223: }
224: }
225:
226: @Override
227: protected void addWithoutCommit(Resource subject, URI predicate,
228: Value object, Resource... contexts)
229: throws RepositoryException {
230: txn.add(new AddStatementOperation(subject, predicate, object,
231: contexts));
232: }
233:
234: @Override
235: protected void removeWithoutCommit(Resource subject, URI predicate,
236: Value object, Resource... contexts)
237: throws RepositoryException {
238: txn.add(new RemoveStatementsOperation(subject, predicate,
239: object, contexts));
240: }
241:
242: @Override
243: public void clear(Resource... contexts) throws RepositoryException {
244: txn.add(new ClearOperation(contexts));
245: autoCommit();
246: }
247:
248: public void removeNamespace(String prefix)
249: throws RepositoryException {
250: txn.add(new RemoveNamespaceOperation(prefix));
251: autoCommit();
252: }
253:
254: public void clearNamespaces() throws RepositoryException {
255: txn.add(new ClearNamespacesOperation());
256: autoCommit();
257: }
258:
259: public void setNamespace(String prefix, String name)
260: throws RepositoryException {
261: txn.add(new SetNamespaceOperation(prefix, name));
262: autoCommit();
263: }
264:
265: public RepositoryResult<Namespace> getNamespaces()
266: throws RepositoryException {
267: try {
268: List<Namespace> namespaceList = new ArrayList<Namespace>();
269:
270: TupleQueryResult namespaces = getRepository()
271: .getHTTPClient().getNamespaces();
272: try {
273: while (namespaces.hasNext()) {
274: BindingSet bindingSet = namespaces.next();
275: Value prefix = bindingSet.getValue("prefix");
276: Value namespace = bindingSet.getValue("namespace");
277:
278: if (prefix instanceof Literal
279: && namespace instanceof Literal) {
280: String prefixStr = ((Literal) prefix)
281: .getLabel();
282: String namespaceStr = ((Literal) namespace)
283: .getLabel();
284: namespaceList.add(new NamespaceImpl(prefixStr,
285: namespaceStr));
286: }
287: }
288: } finally {
289: namespaces.close();
290: }
291:
292: return createRepositoryResult(namespaceList);
293: } catch (QueryEvaluationException e) {
294: throw new RepositoryException(e);
295: } catch (IOException e) {
296: throw new RepositoryException(e);
297: }
298: }
299:
300: public String getNamespace(String prefix)
301: throws RepositoryException {
302: try {
303: return getRepository().getHTTPClient().getNamespace(prefix);
304: } catch (IOException e) {
305: throw new RepositoryException(e);
306: }
307: }
308:
309: /**
310: * Creates a RepositoryResult for the supplied element set.
311: */
312: protected <E> RepositoryResult<E> createRepositoryResult(
313: Iterable<? extends E> elements) {
314: return new RepositoryResult<E>(
315: new CloseableIteratorIteration<E, RepositoryException>(
316: elements.iterator()));
317: }
318: }
|