001: /*
002: * Copyright Aduna (http://www.aduna-software.com/) (c) 2007.
003: *
004: * Licensed under the Aduna BSD-style license.
005: */
006: package org.openrdf.http.server.repository;
007:
008: import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
009: import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
010: import static javax.servlet.http.HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE;
011: import static org.openrdf.http.protocol.Protocol.BINDING_PREFIX;
012: import static org.openrdf.http.protocol.Protocol.DEFAULT_GRAPH_PARAM_NAME;
013: import static org.openrdf.http.protocol.Protocol.INCLUDE_INFERRED_PARAM_NAME;
014: import static org.openrdf.http.protocol.Protocol.NAMED_GRAPH_PARAM_NAME;
015: import static org.openrdf.http.protocol.Protocol.QUERY_LANGUAGE_PARAM_NAME;
016: import static org.openrdf.http.protocol.Protocol.QUERY_PARAM_NAME;
017:
018: import java.io.IOException;
019: import java.util.Enumeration;
020: import java.util.HashMap;
021: import java.util.Map;
022:
023: import javax.servlet.http.HttpServletRequest;
024: import javax.servlet.http.HttpServletResponse;
025:
026: import org.slf4j.Logger;
027: import org.slf4j.LoggerFactory;
028: import org.springframework.context.ApplicationContextException;
029: import org.springframework.web.servlet.ModelAndView;
030: import org.springframework.web.servlet.View;
031: import org.springframework.web.servlet.mvc.AbstractController;
032:
033: import info.aduna.lang.FileFormat;
034: import info.aduna.lang.service.FileFormatServiceRegistry;
035: import info.aduna.webapp.util.HttpServerUtil;
036:
037: import org.openrdf.http.protocol.Protocol;
038: import org.openrdf.http.protocol.error.ErrorInfo;
039: import org.openrdf.http.protocol.error.ErrorType;
040: import org.openrdf.http.server.ClientHTTPException;
041: import org.openrdf.http.server.ProtocolUtil;
042: import org.openrdf.model.URI;
043: import org.openrdf.model.Value;
044: import org.openrdf.query.BooleanQuery;
045: import org.openrdf.query.GraphQuery;
046: import org.openrdf.query.MalformedQueryException;
047: import org.openrdf.query.Query;
048: import org.openrdf.query.QueryLanguage;
049: import org.openrdf.query.TupleQuery;
050: import org.openrdf.query.UnsupportedQueryLanguageException;
051: import org.openrdf.query.impl.DatasetImpl;
052: import org.openrdf.query.resultio.BooleanQueryResultWriterRegistry;
053: import org.openrdf.query.resultio.TupleQueryResultWriterRegistry;
054: import org.openrdf.repository.Repository;
055: import org.openrdf.repository.RepositoryConnection;
056: import org.openrdf.repository.RepositoryException;
057: import org.openrdf.rio.RDFWriterRegistry;
058:
059: /**
060: * Handles queries on a repository and renders the results in a format suitable
061: * to the type of query.
062: *
063: * @author Herko ter Horst
064: */
065: public class RepositoryController extends AbstractController {
066:
067: private Logger logger = LoggerFactory.getLogger(this .getClass());
068:
069: public RepositoryController() throws ApplicationContextException {
070: setSupportedMethods(new String[] { METHOD_GET, METHOD_POST });
071: }
072:
073: @Override
074: protected ModelAndView handleRequestInternal(
075: HttpServletRequest request, HttpServletResponse response)
076: throws Exception {
077: Repository repository = RepositoryInterceptor
078: .getRepository(request);
079: RepositoryConnection repositoryCon = RepositoryInterceptor
080: .getRepositoryConnection(request);
081:
082: String reqMethod = request.getMethod();
083: if (METHOD_GET.equals(reqMethod)) {
084: logger.info("GET query");
085: } else if (METHOD_POST.equals(reqMethod)) {
086: logger.info("POST query");
087:
088: String mimeType = HttpServerUtil.getMIMEType(request
089: .getContentType());
090: if (!Protocol.FORM_MIME_TYPE.equals(mimeType)) {
091: throw new ClientHTTPException(
092: SC_UNSUPPORTED_MEDIA_TYPE,
093: "Unsupported MIME type: " + mimeType);
094: }
095: }
096:
097: String queryStr = request.getParameter(QUERY_PARAM_NAME);
098: logger.debug("query = {}", queryStr);
099:
100: if (queryStr != null) {
101: Query query = getQuery(repository, repositoryCon, queryStr,
102: request, response);
103:
104: View view;
105: Object queryResult;
106: FileFormatServiceRegistry<? extends FileFormat, ?> registry;
107:
108: if (query instanceof TupleQuery) {
109: TupleQuery tQuery = (TupleQuery) query;
110:
111: queryResult = tQuery.evaluate();
112: registry = TupleQueryResultWriterRegistry.getInstance();
113: view = TupleQueryResultView.getInstance();
114: } else if (query instanceof GraphQuery) {
115: GraphQuery gQuery = (GraphQuery) query;
116:
117: queryResult = gQuery.evaluate();
118: registry = RDFWriterRegistry.getInstance();
119: view = GraphQueryResultView.getInstance();
120: } else if (query instanceof BooleanQuery) {
121: BooleanQuery bQuery = (BooleanQuery) query;
122:
123: queryResult = bQuery.evaluate();
124: registry = BooleanQueryResultWriterRegistry
125: .getInstance();
126: view = BooleanQueryResultView.getInstance();
127: } else {
128: throw new ClientHTTPException(SC_BAD_REQUEST,
129: "Unsupported query type: "
130: + query.getClass().getName());
131: }
132:
133: Object factory = ProtocolUtil.getAcceptableService(request,
134: response, registry);
135:
136: Map<String, Object> model = new HashMap<String, Object>();
137: model
138: .put(QueryResultView.FILENAME_HINT_KEY,
139: "query-result");
140: model.put(QueryResultView.QUERY_RESULT_KEY, queryResult);
141: model.put(QueryResultView.FACTORY_KEY, factory);
142:
143: return new ModelAndView(view, model);
144: } else {
145: throw new ClientHTTPException(SC_BAD_REQUEST,
146: "Missing parameter: " + QUERY_PARAM_NAME);
147: }
148: }
149:
150: private Query getQuery(Repository repository,
151: RepositoryConnection repositoryCon, String queryStr,
152: HttpServletRequest request, HttpServletResponse response)
153: throws IOException, ClientHTTPException {
154: Query result = null;
155:
156: // default query language is SPARQL
157: QueryLanguage queryLn = QueryLanguage.SPARQL;
158:
159: String queryLnStr = request
160: .getParameter(QUERY_LANGUAGE_PARAM_NAME);
161: logger.debug("query language param = {}", queryLnStr);
162:
163: if (queryLnStr != null) {
164: queryLn = QueryLanguage.valueOf(queryLnStr);
165:
166: if (queryLn == null) {
167: throw new ClientHTTPException(SC_BAD_REQUEST,
168: "Unknown query language: " + queryLnStr);
169: }
170: }
171:
172: // determine if inferred triples should be included in query evaluation
173: boolean includeInferred = ProtocolUtil.parseBooleanParam(
174: request, INCLUDE_INFERRED_PARAM_NAME, true);
175:
176: // build a dataset, if specified
177: String[] defaultGraphURIs = request
178: .getParameterValues(DEFAULT_GRAPH_PARAM_NAME);
179: String[] namedGraphURIs = request
180: .getParameterValues(NAMED_GRAPH_PARAM_NAME);
181:
182: DatasetImpl dataset = null;
183: if (defaultGraphURIs != null || namedGraphURIs != null) {
184: dataset = new DatasetImpl();
185:
186: if (defaultGraphURIs != null) {
187: for (String defaultGraphURI : defaultGraphURIs) {
188: try {
189: URI uri = repository.getValueFactory()
190: .createURI(defaultGraphURI);
191: dataset.addDefaultGraph(uri);
192: } catch (IllegalArgumentException e) {
193: throw new ClientHTTPException(SC_BAD_REQUEST,
194: "Illegal URI for default graph: "
195: + defaultGraphURI);
196: }
197: }
198: }
199:
200: if (namedGraphURIs != null) {
201: for (String namedGraphURI : namedGraphURIs) {
202: try {
203: URI uri = repository.getValueFactory()
204: .createURI(namedGraphURI);
205: dataset.addNamedGraph(uri);
206: } catch (IllegalArgumentException e) {
207: throw new ClientHTTPException(SC_BAD_REQUEST,
208: "Illegal URI for named graph: "
209: + namedGraphURI);
210: }
211: }
212: }
213: }
214:
215: try {
216: result = repositoryCon.prepareQuery(queryLn, queryStr);
217: result.setIncludeInferred(includeInferred);
218:
219: if (dataset != null) {
220: result.setDataset(dataset);
221: }
222:
223: // determine if any variable bindings have been set on this query.
224: @SuppressWarnings("unchecked")
225: Enumeration<String> parameterNames = request
226: .getParameterNames();
227:
228: while (parameterNames.hasMoreElements()) {
229: String parameterName = parameterNames.nextElement();
230:
231: if (parameterName.startsWith(BINDING_PREFIX)
232: && parameterName.length() > BINDING_PREFIX
233: .length()) {
234: String bindingName = parameterName
235: .substring(BINDING_PREFIX.length());
236: Value bindingValue = ProtocolUtil.parseValueParam(
237: request, parameterName, repository
238: .getValueFactory());
239: result.setBinding(bindingName, bindingValue);
240: }
241: }
242: } catch (UnsupportedQueryLanguageException e) {
243: ErrorInfo errInfo = new ErrorInfo(
244: ErrorType.UNSUPPORTED_QUERY_LANGUAGE, queryLn
245: .getName());
246: throw new ClientHTTPException(SC_BAD_REQUEST, errInfo
247: .toString());
248: } catch (MalformedQueryException e) {
249: ErrorInfo errInfo = new ErrorInfo(
250: ErrorType.MALFORMED_QUERY, e.getMessage());
251: throw new ClientHTTPException(SC_BAD_REQUEST, errInfo
252: .toString());
253: } catch (RepositoryException e) {
254: logger.error("Repository error", e);
255: response.sendError(SC_INTERNAL_SERVER_ERROR);
256: }
257:
258: return result;
259: }
260: }
|