/* * Copyright Aduna (http://www.aduna-software.com/) (c) 2007. * * Licensed under the Aduna BSD-style license. */ package org.openrdf.http.server.repository; import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; import static javax.servlet.http.HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE; import static org.openrdf.http.protocol.Protocol.BINDING_PREFIX; import static org.openrdf.http.protocol.Protocol.DEFAULT_GRAPH_PARAM_NAME; import static org.openrdf.http.protocol.Protocol.INCLUDE_INFERRED_PARAM_NAME; import static org.openrdf.http.protocol.Protocol.NAMED_GRAPH_PARAM_NAME; import static org.openrdf.http.protocol.Protocol.QUERY_LANGUAGE_PARAM_NAME; import static org.openrdf.http.protocol.Protocol.QUERY_PARAM_NAME; import java.io.IOException; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContextException; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.View; import org.springframework.web.servlet.mvc.AbstractController; import info.aduna.lang.FileFormat; import info.aduna.lang.service.FileFormatServiceRegistry; import info.aduna.webapp.util.HttpServerUtil; import org.openrdf.http.protocol.Protocol; import org.openrdf.http.protocol.error.ErrorInfo; import org.openrdf.http.protocol.error.ErrorType; import org.openrdf.http.server.ClientHTTPException; import org.openrdf.http.server.ProtocolUtil; import org.openrdf.model.URI; import org.openrdf.model.Value; import org.openrdf.query.BooleanQuery; import org.openrdf.query.GraphQuery; import org.openrdf.query.MalformedQueryException; import org.openrdf.query.Query; import org.openrdf.query.QueryLanguage; import org.openrdf.query.TupleQuery; import org.openrdf.query.UnsupportedQueryLanguageException; import org.openrdf.query.impl.DatasetImpl; import org.openrdf.query.resultio.BooleanQueryResultWriterRegistry; import org.openrdf.query.resultio.TupleQueryResultWriterRegistry; import org.openrdf.repository.Repository; import org.openrdf.repository.RepositoryConnection; import org.openrdf.repository.RepositoryException; import org.openrdf.rio.RDFWriterRegistry; /** * Handles queries on a repository and renders the results in a format suitable * to the type of query. * * @author Herko ter Horst */ public class RepositoryController extends AbstractController { private Logger logger = LoggerFactory.getLogger(this.getClass()); public RepositoryController() throws ApplicationContextException { setSupportedMethods(new String[] { METHOD_GET, METHOD_POST }); } @Override protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { Repository repository = RepositoryInterceptor.getRepository(request); RepositoryConnection repositoryCon = RepositoryInterceptor.getRepositoryConnection(request); String reqMethod = request.getMethod(); if (METHOD_GET.equals(reqMethod)) { logger.info("GET query"); } else if (METHOD_POST.equals(reqMethod)) { logger.info("POST query"); String mimeType = HttpServerUtil.getMIMEType(request.getContentType()); if (!Protocol.FORM_MIME_TYPE.equals(mimeType)) { throw new ClientHTTPException(SC_UNSUPPORTED_MEDIA_TYPE, "Unsupported MIME type: " + mimeType); } } String queryStr = request.getParameter(QUERY_PARAM_NAME); logger.debug("query = {}", queryStr); if (queryStr != null) { Query query = getQuery(repository, repositoryCon, queryStr, request, response); View view; Object queryResult; FileFormatServiceRegistry<? extends FileFormat, ?> registry; if (query instanceof TupleQuery) { TupleQuery tQuery = (TupleQuery)query; queryResult = tQuery.evaluate(); registry = TupleQueryResultWriterRegistry.getInstance(); view = TupleQueryResultView.getInstance(); } else if (query instanceof GraphQuery) { GraphQuery gQuery = (GraphQuery)query; queryResult = gQuery.evaluate(); registry = RDFWriterRegistry.getInstance(); view = GraphQueryResultView.getInstance(); } else if (query instanceof BooleanQuery) { BooleanQuery bQuery = (BooleanQuery)query; queryResult = bQuery.evaluate(); registry = BooleanQueryResultWriterRegistry.getInstance(); view = BooleanQueryResultView.getInstance(); } else { throw new ClientHTTPException(SC_BAD_REQUEST, "Unsupported query type: " + query.getClass().getName()); } Object factory = ProtocolUtil.getAcceptableService(request, response, registry); Map<String, Object> model = new HashMap<String, Object>(); model.put(QueryResultView.FILENAME_HINT_KEY, "query-result"); model.put(QueryResultView.QUERY_RESULT_KEY, queryResult); model.put(QueryResultView.FACTORY_KEY, factory); return new ModelAndView(view, model); } else { throw new ClientHTTPException(SC_BAD_REQUEST, "Missing parameter: " + QUERY_PARAM_NAME); } } private Query getQuery(Repository repository, RepositoryConnection repositoryCon, String queryStr, HttpServletRequest request, HttpServletResponse response) throws IOException, ClientHTTPException { Query result = null; // default query language is SPARQL QueryLanguage queryLn = QueryLanguage.SPARQL; String queryLnStr = request.getParameter(QUERY_LANGUAGE_PARAM_NAME); logger.debug("query language param = {}", queryLnStr); if (queryLnStr != null) { queryLn = QueryLanguage.valueOf(queryLnStr); if (queryLn == null) { throw new ClientHTTPException(SC_BAD_REQUEST, "Unknown query language: " + queryLnStr); } } // determine if inferred triples should be included in query evaluation boolean includeInferred = ProtocolUtil.parseBooleanParam(request, INCLUDE_INFERRED_PARAM_NAME, true); // build a dataset, if specified String[] defaultGraphURIs = request.getParameterValues(DEFAULT_GRAPH_PARAM_NAME); String[] namedGraphURIs = request.getParameterValues(NAMED_GRAPH_PARAM_NAME); DatasetImpl dataset = null; if (defaultGraphURIs != null || namedGraphURIs != null) { dataset = new DatasetImpl(); if (defaultGraphURIs != null) { for (String defaultGraphURI : defaultGraphURIs) { try { URI uri = repository.getValueFactory().createURI(defaultGraphURI); dataset.addDefaultGraph(uri); } catch (IllegalArgumentException e) { throw new ClientHTTPException(SC_BAD_REQUEST, "Illegal URI for default graph: " + defaultGraphURI); } } } if (namedGraphURIs != null) { for (String namedGraphURI : namedGraphURIs) { try { URI uri = repository.getValueFactory().createURI(namedGraphURI); dataset.addNamedGraph(uri); } catch (IllegalArgumentException e) { throw new ClientHTTPException(SC_BAD_REQUEST, "Illegal URI for named graph: " + namedGraphURI); } } } } try { result = repositoryCon.prepareQuery(queryLn, queryStr); result.setIncludeInferred(includeInferred); if (dataset != null) { result.setDataset(dataset); } // determine if any variable bindings have been set on this query. @SuppressWarnings("unchecked") Enumeration<String> parameterNames = request.getParameterNames(); while (parameterNames.hasMoreElements()) { String parameterName = parameterNames.nextElement(); if (parameterName.startsWith(BINDING_PREFIX) && parameterName.length() > BINDING_PREFIX.length()) { String bindingName = parameterName.substring(BINDING_PREFIX.length()); Value bindingValue = ProtocolUtil.parseValueParam(request, parameterName, repository.getValueFactory()); result.setBinding(bindingName, bindingValue); } } } catch (UnsupportedQueryLanguageException e) { ErrorInfo errInfo = new ErrorInfo(ErrorType.UNSUPPORTED_QUERY_LANGUAGE, queryLn.getName()); throw new ClientHTTPException(SC_BAD_REQUEST, errInfo.toString()); } catch (MalformedQueryException e) { ErrorInfo errInfo = new ErrorInfo(ErrorType.MALFORMED_QUERY, e.getMessage()); throw new ClientHTTPException(SC_BAD_REQUEST, errInfo.toString()); } catch (RepositoryException e) { logger.error("Repository error", e); response.sendError(SC_INTERNAL_SERVER_ERROR); } return result; } }