Updated Branches: refs/heads/master ed9268155 -> 468e810e0
refacotring SparqlWebService to distinct possible content types to return per query type Project: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/commit/1ceb90a5 Tree: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/tree/1ceb90a5 Diff: http://git-wip-us.apache.org/repos/asf/incubator-marmotta/diff/1ceb90a5 Branch: refs/heads/master Commit: 1ceb90a53fc4593a8e39e120abc9e85175dbf257 Parents: ed92681 Author: Sergio Fernández <[email protected]> Authored: Fri Apr 5 12:50:22 2013 +0200 Committer: Sergio Fernández <[email protected]> Committed: Fri Apr 5 12:50:22 2013 +0200 ---------------------------------------------------------------------- .../platform/sparql/api/sparql/SparqlService.java | 100 ++++++- .../sparql/services/sparql/SparqlServiceImpl.java | 107 +++++-- .../services/sparql/SparqlWritersHelper.java | 116 +++++++ .../sparql/webservices/SparqlWebService.java | 242 ++++++--------- 4 files changed, 393 insertions(+), 172 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/1ceb90a5/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/api/sparql/SparqlService.java ---------------------------------------------------------------------- diff --git a/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/api/sparql/SparqlService.java b/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/api/sparql/SparqlService.java index 373ab87..4fc372d 100644 --- a/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/api/sparql/SparqlService.java +++ b/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/api/sparql/SparqlService.java @@ -21,13 +21,19 @@ import org.apache.marmotta.platform.core.exception.MarmottaException; import org.apache.marmotta.platform.sparql.services.sparqlio.rdf.SPARQLGraphResultWriter; import org.apache.marmotta.platform.core.exception.InvalidArgumentException; 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.QueryEvaluationException; import org.openrdf.query.QueryLanguage; +import org.openrdf.query.TupleQuery; import org.openrdf.query.UpdateExecutionException; import org.openrdf.query.resultio.BooleanQueryResultWriter; import org.openrdf.query.resultio.TupleQueryResultWriter; +import org.openrdf.repository.RepositoryException; +import java.io.OutputStream; import java.util.List; import java.util.Map; @@ -37,10 +43,21 @@ import java.util.Map; * User: sschaffe */ public interface SparqlService { + + /** + * Parse query + * + * @param language language + * @param query query + * @return query parsed + * @throws RepositoryException + * @throws MalformedQueryException + */ + Query parseQuery(QueryLanguage language, String query) throws RepositoryException, MalformedQueryException ; /** * Evaluate a SPARQL query on the KiWi TripleStore. Writes the query results - * to the output stream passed as argument os in the output format specified + * to the output stream passed as argument on in the output format specified * as argument outputFormat. * * see http://www.w3.org/TR/sparql11-query/ @@ -54,8 +71,79 @@ public interface SparqlService { * @throws InvalidArgumentException if the output format or query language are undefined * @throws org.apache.marmotta.platform.core.exception.MarmottaException if the query evaluation fails */ - public void query(QueryLanguage queryLanguage, String query, TupleQueryResultWriter tupleWriter, BooleanQueryResultWriter booleanWriter, SPARQLGraphResultWriter graphWriter) throws InvalidArgumentException, MarmottaException, MalformedQueryException, QueryEvaluationException; + void query(QueryLanguage queryLanguage, String query, TupleQueryResultWriter tupleWriter, BooleanQueryResultWriter booleanWriter, SPARQLGraphResultWriter graphWriter) throws InvalidArgumentException, MarmottaException, MalformedQueryException, QueryEvaluationException; + /** + * Evaluate a SPARQL query on the KiWi TripleStore. Writes the query results + * to the stream passed in the format requested. + * + * @param query + * @param output + * @param format + * @throws QueryEvaluationException + */ + void query(Query query, OutputStream output, String format) throws QueryEvaluationException; + + /** + * Evaluate a SPARQL tuple query on the KiWi TripleStore. Writes the query results + * to the writer passed. + * + * @param tuple query + * @param writer the writer to use to write results + * @throws QueryEvaluationException + */ + void query(TupleQuery query, TupleQueryResultWriter writer) throws QueryEvaluationException; + + /** + * Evaluate a SPARQL tuple query on the KiWi TripleStore. Writes the query results + * to the stream passed in the format requested. + * + * @param query + * @param output + * @param format + */ + void query(TupleQuery query, OutputStream output, String format) throws QueryEvaluationException; + + /** + * Evaluate a SPARQL boolean query on the KiWi TripleStore. Writes the query results + * to the writer passed. + * + * @param query boolean query + * @param writer the writer to use to write results + * @throws QueryEvaluationException + */ + void query(BooleanQuery query, BooleanQueryResultWriter writer) throws QueryEvaluationException; + + /** + * Evaluate a SPARQL boolean query on the KiWi TripleStore. Writes the query results + * to the stream passed in the format requested. + * + * @param query + * @param output + * @param format + */ + void query(BooleanQuery query, OutputStream output, String format) throws QueryEvaluationException; + + /** + * Evaluate a SPARQL graph query on the KiWi TripleStore. Writes the query results + * to the writer passed. + * + * @param query graph query + * @param writer the writer to use to write results + * @throws QueryEvaluationException + */ + void query(GraphQuery query, SPARQLGraphResultWriter writer) throws QueryEvaluationException; + + /** + * Evaluate a SPARQL graph query on the KiWi TripleStore. Writes the query results + * to the stream passed in the format requested. + * + * @param query + * @param output + * @param format + */ + void query(GraphQuery query, OutputStream output, String format) throws QueryEvaluationException; + /** * Evaluate a SPARQL ASK query on the KiWi TripleStore * @@ -66,10 +154,10 @@ public interface SparqlService { * @param query the SPARQL query to evaluate in SPARQL 1.1 syntax * @throws org.apache.marmotta.platform.core.exception.MarmottaException if the query evaluation fails */ - public boolean ask(QueryLanguage queryLanguage, String query) throws MarmottaException; + boolean ask(QueryLanguage queryLanguage, String query) throws MarmottaException; /** - * Evaluate a SPARQL query on the LMF TripleStore. Returns the results as a list of result maps, each element + * Evaluate a SPARQL query on the KiWi TripleStore. Returns the results as a list of result maps, each element * a KiWiNode. * * see http://www.w3.org/TR/sparql11-query/ @@ -80,7 +168,7 @@ public interface SparqlService { public List<Map<String,Value>> query(QueryLanguage queryLanguage, String query) throws MarmottaException; /** - * Execute a SPARQL update on the LMF TripleStore. Throws a KiWiException in case the update execution fails. + * Execute a SPARQL update on the KiWi TripleStore. Throws a KiWiException in case the update execution fails. * * see http://www.w3.org/TR/sparql11-update/ * @@ -88,6 +176,6 @@ public interface SparqlService { * @param query a string representing the update query in SPARQL Update 1.1 syntax * @throws Exception */ - public void update(QueryLanguage queryLanguage, String query) throws InvalidArgumentException, MarmottaException, MalformedQueryException, UpdateExecutionException; + void update(QueryLanguage queryLanguage, String query) throws InvalidArgumentException, MarmottaException, MalformedQueryException, UpdateExecutionException; } http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/1ceb90a5/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/services/sparql/SparqlServiceImpl.java ---------------------------------------------------------------------- diff --git a/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/services/sparql/SparqlServiceImpl.java b/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/services/sparql/SparqlServiceImpl.java index c20d7f1..bfefd4d 100644 --- a/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/services/sparql/SparqlServiceImpl.java +++ b/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/services/sparql/SparqlServiceImpl.java @@ -18,6 +18,7 @@ package org.apache.marmotta.platform.sparql.services.sparql; import java.io.IOException; +import java.io.OutputStream; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -26,7 +27,6 @@ import java.util.Map; import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; -import org.apache.marmotta.kiwi.model.rdf.KiWiNode; import org.apache.marmotta.platform.core.api.config.ConfigurationService; import org.apache.marmotta.platform.core.api.triplestore.SesameService; import org.apache.marmotta.platform.core.exception.InvalidArgumentException; @@ -53,11 +53,11 @@ import org.openrdf.repository.RepositoryConnection; import org.openrdf.repository.RepositoryException; import org.slf4j.Logger; - /** * Sparql Service implementation * - * @author sschaffe + * @author Sebastian Schaffert + * @author Sergio Fernández */ @ApplicationScoped public class SparqlServiceImpl implements SparqlService { @@ -73,6 +73,20 @@ public class SparqlServiceImpl implements SparqlService { @Inject private SesameService sesameService; + + @Override + public Query parseQuery(QueryLanguage language, String query) throws RepositoryException, MalformedQueryException { + Query sparqlQuery = null; + RepositoryConnection connection = sesameService.getConnection(); + try { + connection.begin(); + sparqlQuery = connection.prepareQuery(language, query); + connection.commit(); + } finally { + connection.close(); + } + return sparqlQuery; + } @Override public void query(QueryLanguage queryLanguage, String query, TupleQueryResultWriter tupleWriter, BooleanQueryResultWriter booleanWriter, SPARQLGraphResultWriter graphWriter) throws MarmottaException, MalformedQueryException, QueryEvaluationException { @@ -87,14 +101,11 @@ public class SparqlServiceImpl implements SparqlService { Query sparqlQuery = connection.prepareQuery(queryLanguage, query); if (sparqlQuery instanceof TupleQuery) { - TupleQuery tupleQuery = (TupleQuery) sparqlQuery; - tupleQuery.evaluate(tupleWriter); + query((TupleQuery) sparqlQuery, tupleWriter); } else if (sparqlQuery instanceof BooleanQuery) { - BooleanQuery booleanQuery = (BooleanQuery) sparqlQuery; - booleanWriter.write(booleanQuery.evaluate()); + query((BooleanQuery) sparqlQuery, booleanWriter); } else if (sparqlQuery instanceof GraphQuery) { - GraphQuery graphQuery = (GraphQuery) sparqlQuery; - graphWriter.write(graphQuery.evaluate()); + query((GraphQuery) sparqlQuery, graphWriter); } else { connection.rollback(); throw new InvalidArgumentException("SPARQL query type " + sparqlQuery.getClass() + " not supported!"); @@ -104,26 +115,72 @@ public class SparqlServiceImpl implements SparqlService { } finally { connection.close(); } - } catch(RepositoryException ex) { - log.error("error while getting repository connection"); - throw new MarmottaException("error while getting repository connection",ex); - } catch (TupleQueryResultHandlerException e) { - throw new MarmottaException("error while writing query result in format ",e); - } catch (IOException e) { - throw new MarmottaException("error while writing query result in format ",e); + } catch(RepositoryException e) { + log.error("error while getting repository connection: {}", e); + throw new MarmottaException("error while getting repository connection", e); + } catch (QueryEvaluationException e) { + log.error("error while evaluating query: {}", e); + throw new MarmottaException("error while writing query result in format ", e); } - log.debug("SPARQL execution took {}ms",System.currentTimeMillis()-start); + log.debug("SPARQL execution took {}ms", System.currentTimeMillis()-start); + } + + @Override + public void query(Query query, OutputStream output, String format) throws QueryEvaluationException { + if (query instanceof TupleQuery) { + query((TupleQuery)query, output, format); + } else if (query instanceof BooleanQuery) { + query((BooleanQuery)query, output, format); + } else if (query instanceof GraphQuery) { + query((GraphQuery)query, output, format); + } else { + throw new InvalidArgumentException("SPARQL query type " + query.getClass() + " not supported!"); + } } -// private static Pattern subTypePattern = Pattern.compile("[a-z]+/([a-z0-9-._]+\\+)?([a-z0-9-._]+)(;.*)?"); -// private String parseSubType(String mimeType) { -// Matcher matcher = subTypePattern.matcher(mimeType); -// if(matcher.matches()) return matcher.group(2); -// else -// return mimeType; -// } - + @Override + public void query(TupleQuery query, TupleQueryResultWriter writer) throws QueryEvaluationException { + try { + query.evaluate(writer); + } catch (TupleQueryResultHandlerException e) { + throw new QueryEvaluationException("error while writing query tuple result: ",e); + } + } + + @Override + public void query(TupleQuery query, OutputStream output, String format) throws QueryEvaluationException { + query(query, SparqlWritersHelper.getTupleResultWriter(format, output)); + } + + @Override + public void query(BooleanQuery query, BooleanQueryResultWriter writer) throws QueryEvaluationException { + try { + writer.write(query.evaluate()); + } catch (IOException e) { + throw new QueryEvaluationException("error while writing query boolean result: ",e); + } + } + + @Override + public void query(BooleanQuery query, OutputStream output, String format) throws QueryEvaluationException { + query(query, SparqlWritersHelper.getBooleanResultWriter(format, output)); + } + + @Override + public void query(GraphQuery query, SPARQLGraphResultWriter writer) throws QueryEvaluationException { + try { + writer.write(query.evaluate()); + } catch (IOException e) { + throw new QueryEvaluationException("error while writing query graph result: ",e); + } + } + + @Override + public void query(GraphQuery query, OutputStream output, String format) throws QueryEvaluationException { + query(query, SparqlWritersHelper.getGraphResultWriter(format, output)); + } + /** * Evaluate a SPARQL query on the LMF TripleStore. Returns the results as a list of result maps, each element * a KiWiNode. http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/1ceb90a5/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/services/sparql/SparqlWritersHelper.java ---------------------------------------------------------------------- diff --git a/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/services/sparql/SparqlWritersHelper.java b/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/services/sparql/SparqlWritersHelper.java new file mode 100644 index 0000000..f827c57 --- /dev/null +++ b/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/services/sparql/SparqlWritersHelper.java @@ -0,0 +1,116 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.marmotta.platform.sparql.services.sparql; + +import java.io.OutputStream; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.lang.StringUtils; +import org.apache.marmotta.platform.core.exception.InvalidArgumentException; +import org.apache.marmotta.platform.sparql.services.sparqlio.rdf.SPARQLGraphResultWriter; +import org.apache.marmotta.platform.sparql.services.sparqlio.sparqlhtml.SPARQLBooleanHTMLWriter; +import org.apache.marmotta.platform.sparql.services.sparqlio.sparqlhtml.SPARQLResultsHTMLWriter; +import org.apache.marmotta.platform.sparql.services.sparqlio.sparqljson.SPARQLBooleanJSONWriter; +import org.apache.marmotta.platform.sparql.services.sparqlio.sparqljson.SPARQLResultsJSONWriter; +import org.openrdf.query.resultio.BooleanQueryResultWriter; +import org.openrdf.query.resultio.TupleQueryResultWriter; +import org.openrdf.query.resultio.sparqlxml.SPARQLBooleanXMLWriter; +import org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLWriter; +import org.openrdf.query.resultio.text.BooleanTextWriter; +import org.openrdf.query.resultio.text.csv.SPARQLResultsCSVWriter; + +/** + * Helper for working with SPARQL Writers + * + * @author Sergio Fernández + * + */ +public class SparqlWritersHelper { + + public static TupleQueryResultWriter getTupleResultWriter(String format, OutputStream os) { + //build outputwriter + final TupleQueryResultWriter out; + if(format == null) { + out = new SPARQLResultsXMLWriter(os); + } else if(parseSubType(format).equals("html")) { + out = new SPARQLResultsHTMLWriter(os); + } else if(parseSubType(format).equals("json")) { + out = new SPARQLResultsJSONWriter(os); + } else if(parseSubType(format).equals("xml")) { + out = new SPARQLResultsXMLWriter(os); + } else if(parseSubType(format).equals("csv")) { + out = new SPARQLResultsCSVWriter(os); + } else throw new InvalidArgumentException("could not produce format "+format); + return out; + } + + public static BooleanQueryResultWriter getBooleanResultWriter(String format, OutputStream os) { + //build outputwriter + final BooleanQueryResultWriter out; + if(format == null) { + out = new SPARQLBooleanXMLWriter(os); + } else if(parseSubType(format).equals("html")) { + out = new SPARQLBooleanHTMLWriter(os); + } else if(parseSubType(format).equals("json")) { + out = new SPARQLBooleanJSONWriter(os); + } else if(parseSubType(format).equals("xml")) { + out = new SPARQLBooleanXMLWriter(os); + } else if(parseSubType(format).equals("csv")) { + out = new BooleanTextWriter(os); + } else throw new InvalidArgumentException("could not produce format "+format); + return out; + } + + public static SPARQLGraphResultWriter getGraphResultWriter(String format, OutputStream os) { + return new SPARQLGraphResultWriter(os,format); + } + + //TODO: move this to another place + + public static Pattern subTypePattern = Pattern.compile("[a-z]+/([a-z0-9-._]+\\+)?([a-z0-9-._]+)(;.*)?"); + + public static String parseSubType(String mimeType) { + Matcher matcher = subTypePattern.matcher(mimeType); + if (matcher.matches()) + return matcher.group(2); + else + return mimeType; + } + + public static String buildSparqlContentType(String resultType) { + if(StringUtils.isBlank(resultType)) { + return "application/sparql-results+xml;charset=utf-8"; + } else if(parseSubType(resultType).equals("html") ) { + return "text/html;charset=utf-8"; + } else if(parseSubType(resultType).equals("json") ) { + return "application/sparql-results+json;charset=utf-8"; + } else if(parseSubType(resultType).equals("rdf+xml") ) { + return "application/rdf+xml;charset=utf-8"; + } else if(parseSubType(resultType).equals("rdf+n3") ) { + return "text/rdf+n3;charset=utf-8"; + } else if(parseSubType(resultType).equals("n3") ) { + return "text/rdf+n3;charset=utf-8"; + } else if(parseSubType(resultType).equals("csv") ) { + return "text/csv;charset=utf-8"; + } else { + return "application/sparql-results+xml;charset=utf-8"; + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/1ceb90a5/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/webservices/SparqlWebService.java ---------------------------------------------------------------------- diff --git a/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/webservices/SparqlWebService.java b/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/webservices/SparqlWebService.java index f15f6df..58a1ee7 100644 --- a/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/webservices/SparqlWebService.java +++ b/platform/marmotta-sparql/src/main/java/org/apache/marmotta/platform/sparql/webservices/SparqlWebService.java @@ -17,56 +17,60 @@ */ package org.apache.marmotta.platform.sparql.webservices; -import org.apache.marmotta.platform.core.exception.MarmottaException; -import org.apache.marmotta.platform.sparql.api.sparql.SparqlService; -import org.apache.marmotta.platform.sparql.services.sparqlio.rdf.SPARQLGraphResultWriter; -import org.apache.marmotta.platform.sparql.services.sparqlio.sparqlhtml.SPARQLBooleanHTMLWriter; -import org.apache.marmotta.platform.sparql.services.sparqlio.sparqlhtml.SPARQLResultsHTMLWriter; -import org.apache.marmotta.platform.sparql.services.sparqlio.sparqljson.SPARQLBooleanJSONWriter; -import org.apache.marmotta.platform.sparql.services.sparqlio.sparqljson.SPARQLResultsJSONWriter; -import com.google.common.collect.Lists; -import com.google.common.io.CharStreams; -import org.apache.marmotta.platform.core.api.config.ConfigurationService; -import org.apache.marmotta.platform.core.exception.InvalidArgumentException; -import org.apache.marmotta.platform.core.util.WebServiceUtil; -import org.apache.commons.lang.StringUtils; -import org.apache.marmotta.commons.http.ContentType; -import org.apache.marmotta.commons.http.LMFHttpUtils; -import org.openrdf.query.MalformedQueryException; -import org.openrdf.query.QueryEvaluationException; -import org.openrdf.query.QueryLanguage; -import org.openrdf.query.UpdateExecutionException; -import org.openrdf.query.resultio.BooleanQueryResultWriter; -import org.openrdf.query.resultio.TupleQueryResultWriter; -import org.openrdf.query.resultio.sparqlxml.SPARQLBooleanXMLWriter; -import org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLWriter; -import org.openrdf.query.resultio.text.BooleanTextWriter; -import org.openrdf.query.resultio.text.csv.SPARQLResultsCSVWriter; -import org.slf4j.Logger; - -import javax.enterprise.context.ApplicationScoped; -import javax.inject.Inject; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.*; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.StreamingOutput; -import javax.ws.rs.core.UriBuilder; - import java.io.IOException; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; import java.net.URLDecoder; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; + +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.Consumes; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.OPTIONS; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.QueryParam; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.StreamingOutput; +import javax.ws.rs.core.UriBuilder; + +import org.apache.commons.lang.StringUtils; +import org.apache.marmotta.commons.http.ContentType; +import org.apache.marmotta.commons.http.LMFHttpUtils; +import org.apache.marmotta.platform.core.api.config.ConfigurationService; +import org.apache.marmotta.platform.core.exception.InvalidArgumentException; +import org.apache.marmotta.platform.core.exception.MarmottaException; +import org.apache.marmotta.platform.core.util.WebServiceUtil; +import org.apache.marmotta.platform.sparql.api.sparql.SparqlService; +import org.apache.marmotta.platform.sparql.services.sparql.SparqlWritersHelper; +import org.openrdf.query.BooleanQuery; +import org.openrdf.query.GraphQuery; +import org.openrdf.query.MalformedQueryException; +import org.openrdf.query.Query; +import org.openrdf.query.QueryEvaluationException; +import org.openrdf.query.QueryLanguage; +import org.openrdf.query.TupleQuery; +import org.openrdf.query.UpdateExecutionException; +import org.openrdf.repository.RepositoryException; +import org.slf4j.Logger; + +import com.google.common.collect.Lists; +import com.google.common.io.CharStreams; /** - * Execute SPARQL query (both query and update) on the LMF triple store + * Execute SPARQL query (both query and update) on the kiwi triple store * according the SPARQL 1.1 Protocol * * @link http://www.w3.org/TR/sparql11-protocol/ @@ -82,7 +86,7 @@ public class SparqlWebService { public static final String SELECT = "/select"; public static final String UPDATE = "/update"; public static final String SNORQL = "/snorql"; - + @Inject private Logger log; @@ -147,36 +151,46 @@ public class SparqlWebService { @GET @Path(SELECT) public Response selectGet(@QueryParam("query") String query, @QueryParam("output") String resultType, @Context HttpServletRequest request) { - if(resultType == null) { - List<ContentType> acceptedTypes = LMFHttpUtils.parseAcceptHeader(request.getHeader("Accept")); - List<ContentType> offeredTypes = LMFHttpUtils.parseStringList(Lists.newArrayList("application/sparql-results+xml","application/sparql-results+json","text/html", "application/rdf+xml", "text/csv")); - - ContentType bestType = LMFHttpUtils.bestContentType(offeredTypes,acceptedTypes); - - if(bestType != null) { - resultType = bestType.getMime(); - } - } - - try { - if(resultType != null) { - if (StringUtils.isNotBlank(query)) - return buildQueryResponse(resultType, query); - else { - if (parseSubType(resultType).equals("html")) - return Response.seeOther(new URI(configurationService.getServerUri() + "sparql/admin/snorql/snorql.html")).build(); - else - return Response.status(Response.Status.BAD_REQUEST).entity("no SPARQL query specified").build(); - } - } else - return Response.status(Response.Status.BAD_REQUEST).entity("no result format specified or unsupported result format").build(); - } catch (InvalidArgumentException ex) { - return Response.status(Response.Status.BAD_REQUEST).entity(ex.getMessage()).build(); - } catch(Exception e) { - log.error("query execution threw an exception",e); - - return Response.serverError().entity("query not supported").build(); - } + if (StringUtils.isBlank(query)) { + try { + return Response.temporaryRedirect(new URI(configurationService.getServerUri() + "sparql/admin/snorql/snorql.html")).build(); + } catch (URISyntaxException e) { + return Response.status(Status.NOT_FOUND).build(); + } + } else { + try { + final Query sparqlQuery = sparqlService.parseQuery(QueryLanguage.SPARQL, query); + + final String format; + if(StringUtils.isBlank(resultType)) { + List<ContentType> offeredTypes = new ArrayList<ContentType>(); + if (sparqlQuery instanceof TupleQuery || sparqlQuery instanceof BooleanQuery) { + offeredTypes = LMFHttpUtils.parseStringList(Lists.newArrayList("application/sparql-results+xml", "application/sparql-results+json", "text/html", "text/csv")); + } else if (sparqlQuery instanceof GraphQuery) { + offeredTypes = LMFHttpUtils.parseStringList(Lists.newArrayList("application/rdf+xml", "text/rdf+n3", "text/turtle", "application/json")); + } + List<ContentType> acceptedTypes = LMFHttpUtils.parseAcceptHeader(request.getHeader("Accept")); + ContentType bestType = LMFHttpUtils.bestContentType(offeredTypes,acceptedTypes); + if(bestType != null) { + format = bestType.getMime(); + } else { + format = ""; + } + } else { + format = resultType; //FIXME: validate? + } + + return buildQueryResponse(format, sparqlQuery); + + } catch (RepositoryException e) { + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); + } catch (MalformedQueryException e) { + return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build(); + } catch (Exception e) { + log.error("query execution threw an exception",e); + return Response.serverError().entity("query not supported").build(); + } + } } /** @@ -343,7 +357,7 @@ public class SparqlWebService { resultType = bestType.getMime(); } } - if (parseSubType(resultType).equals("html")) + if (SparqlWritersHelper.parseSubType(resultType).equals("html")) return Response.seeOther(new URI(configurationService.getServerUri() + "sparql/admin/update.html")).build(); else return Response.status(Response.Status.BAD_REQUEST).entity("no SPARQL query specified").build(); @@ -481,7 +495,7 @@ public class SparqlWebService { @Override public void write(OutputStream output) throws IOException, WebApplicationException { try { - sparqlService.query(QueryLanguage.SPARQL,query,getTupleResultWriter(resultType,output),getBooleanResultWriter(resultType,output), getGraphResultWriter(resultType,output)); + sparqlService.query(QueryLanguage.SPARQL, query, SparqlWritersHelper.getTupleResultWriter(resultType, output), SparqlWritersHelper.getBooleanResultWriter(resultType, output), SparqlWritersHelper.getGraphResultWriter(resultType, output)); } catch (MarmottaException ex) { throw new WebApplicationException(ex.getCause(), Response.status(Response.Status.BAD_REQUEST).entity(WebServiceUtil.jsonErrorResponse(ex)).build()); } catch (QueryEvaluationException e) { @@ -492,76 +506,22 @@ public class SparqlWebService { } }; - //set returntype - String s = ""; - if(resultType ==null) { - s = "application/sparql-results+xml;charset=utf-8"; - } else if(parseSubType(resultType).equals("html") ) { - s = "text/html;charset=utf-8"; - } else if(parseSubType(resultType).equals("json") ) { - s = "application/sparql-results+json;charset=utf-8"; - } else if(parseSubType(resultType).equals("rdf+xml") ) { - s = "application/rdf+xml;charset=utf-8"; - } else if(parseSubType(resultType).equals("rdf+n3") ) { - s = "text/rdf+n3;charset=utf-8"; - } else if(parseSubType(resultType).equals("n3") ) { - s = "text/rdf+n3;charset=utf-8"; - } else if(parseSubType(resultType).equals("csv") ) { - s = "text/csv;charset=utf-8"; - } else { - s = "application/sparql-results+xml;charset=utf-8"; - } - - Response r = Response.ok().entity(entity).header("Content-Type", s).build(); - return r; - } - - private static Pattern subTypePattern = Pattern.compile("[a-z]+/([a-z0-9-._]+\\+)?([a-z0-9-._]+)(;.*)?"); - private String parseSubType(String mimeType) { - Matcher matcher = subTypePattern.matcher(mimeType); - if (matcher.matches()) - return matcher.group(2); - else - return mimeType; - } - - - private TupleQueryResultWriter getTupleResultWriter(String format, OutputStream os) { - //build outputwriter - final TupleQueryResultWriter out; - if(format == null) { - out = new SPARQLResultsXMLWriter(os); - } else if(parseSubType(format).equals("html")) { - out = new SPARQLResultsHTMLWriter(os); - } else if(parseSubType(format).equals("json")) { - out = new SPARQLResultsJSONWriter(os); - } else if(parseSubType(format).equals("xml")) { - out = new SPARQLResultsXMLWriter(os); - } else if(parseSubType(format).equals("csv")) { - out = new SPARQLResultsCSVWriter(os); - } else throw new InvalidArgumentException("could not produce format "+format); - return out; - } - - private BooleanQueryResultWriter getBooleanResultWriter(String format, OutputStream os) { - //build outputwriter - final BooleanQueryResultWriter out; - if(format == null) { - out = new SPARQLBooleanXMLWriter(os); - } else if(parseSubType(format).equals("html")) { - out = new SPARQLBooleanHTMLWriter(os); - } else if(parseSubType(format).equals("json")) { - out = new SPARQLBooleanJSONWriter(os); - } else if(parseSubType(format).equals("xml")) { - out = new SPARQLBooleanXMLWriter(os); - } else if(parseSubType(format).equals("csv")) { - out = new BooleanTextWriter(os); - } else throw new InvalidArgumentException("could not produce format "+format); - return out; + return Response.ok().entity(entity).header("Content-Type", SparqlWritersHelper.buildSparqlContentType(resultType)).build(); } - - protected SPARQLGraphResultWriter getGraphResultWriter(String format, OutputStream os) { - return new SPARQLGraphResultWriter(os,format); + + private Response buildQueryResponse(final String resultType, final Query query) throws Exception { + StreamingOutput entity = new StreamingOutput() { + @Override + public void write(OutputStream output) throws IOException, WebApplicationException { + try { + sparqlService.query(query, output, resultType); + } catch (QueryEvaluationException e) { + throw new WebApplicationException(e.getCause(), Response.status(Response.Status.BAD_REQUEST).entity(WebServiceUtil.jsonErrorResponse(e)).build()); + } + } + }; + + return Response.ok().entity(entity).header("Content-Type", SparqlWritersHelper.buildSparqlContentType(resultType)).build(); } }
