/* * Copyright (c) 2008, Rickard Öberg. All Rights Reserved. * * Licensed 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.qi4j.library.rest.admin; import info.aduna.xml.XMLWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; import org.openrdf.http.protocol.Protocol; import org.openrdf.model.URI; import org.openrdf.model.Value; import org.openrdf.query.*; import org.openrdf.query.impl.DatasetImpl; import org.openrdf.query.resultio.TupleQueryResultWriter; import org.openrdf.query.resultio.sparqljson.SPARQLResultsJSONWriterFactory; import org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLWriter; import org.openrdf.repository.Repository; import org.openrdf.repository.RepositoryConnection; import org.openrdf.repository.RepositoryException; import org.qi4j.api.injection.scope.Service; import org.restlet.data.Form; import org.restlet.data.MediaType; import org.restlet.data.Method; import org.restlet.data.Status; import org.restlet.representation.InputRepresentation; import org.restlet.representation.OutputRepresentation; import org.restlet.representation.Representation; import org.restlet.representation.Variant; import org.restlet.resource.ResourceException; import org.restlet.resource.ServerResource; import static org.openrdf.http.protocol.Protocol.*; /** * JAVADOC */ public class SPARQLResource extends ServerResource { @Service Repository repository; public SPARQLResource() { getVariants().addAll( Arrays.asList( new Variant( MediaType.TEXT_HTML ), new Variant( MediaType.APPLICATION_RDF_XML ), new Variant( RestApplication.APPLICATION_SPARQL_JSON ) ) ); setNegotiated( true ); } @Override protected void doInit() throws ResourceException { super.doInit(); } @Override public Representation get( final Variant variant ) throws ResourceException { try { // TODO There's probably a helper somewhere that can do this more nicely if( getRequest().getOriginalRef().getLastSegment().equals( "sparqlhtml.xsl" ) ) { InputStream resourceAsStream = getClass().getResourceAsStream( "sparqlhtml.xsl" ); return new InputRepresentation( resourceAsStream, MediaType.TEXT_XML ); } Form form; if( getRequest().getMethod().equals( Method.POST ) ) { form = new Form(getRequest().getEntity()); } else { form = getRequest().getResourceRef().getQueryAsForm(); } final RepositoryConnection conn = repository.getConnection(); String queryStr = form.getFirstValue( "query" ); if( queryStr == null ) { InputStream resourceAsStream = getClass().getResourceAsStream( "sparqlform.html" ); return new InputRepresentation( resourceAsStream, MediaType.TEXT_HTML ); } Query query = getQuery( repository, conn, queryStr ); if( query instanceof TupleQuery ) { TupleQuery tQuery = (TupleQuery) query; final TupleQueryResult queryResult = tQuery.evaluate(); if( variant.getMediaType().equals( MediaType.TEXT_HTML ) ) { return new OutputRepresentation( MediaType.TEXT_XML ) { @Override public void write( OutputStream outputStream ) throws IOException { try { PrintWriter out = new PrintWriter( outputStream ); out.println( "<?xml version='1.0' encoding='UTF-8'?>" ); out.println( "<?xml-stylesheet type=\"text/xsl\" href=\"query/sparqlhtml.xsl\"?>" ); out.flush(); TupleQueryResultWriter qrWriter = new SPARQLResultsXMLWriter( new XMLWriter( outputStream ) { @Override public void startDocument() throws IOException { // Ignore } } ); QueryResultUtil.report( queryResult, qrWriter ); } catch( Exception e ) { throw new IOException( e ); } finally { try { conn.close(); } catch( RepositoryException e ) { // Ignore } } } }; } else if( variant.getMediaType().equals( MediaType.APPLICATION_RDF_XML ) ) { return new OutputRepresentation( MediaType.APPLICATION_XML ) { @Override public void write( OutputStream outputStream ) throws IOException { try { TupleQueryResultWriter qrWriter = new SPARQLResultsXMLWriter( new XMLWriter( outputStream ) ); QueryResultUtil.report( queryResult, qrWriter ); } catch( Exception e ) { throw new IOException( e ); } finally { try { conn.close(); } catch( RepositoryException e ) { // Ignore } } } }; } else if( variant.getMediaType().equals( RestApplication.APPLICATION_SPARQL_JSON ) ) { return new OutputRepresentation( RestApplication.APPLICATION_SPARQL_JSON ) { @Override public void write( OutputStream outputStream ) throws IOException { try { TupleQueryResultWriter qrWriter = new SPARQLResultsJSONWriterFactory().getWriter( outputStream ); QueryResultUtil.report( queryResult, qrWriter ); } catch( Exception e ) { throw new IOException( e ); } finally { try { conn.close(); } catch( RepositoryException e ) { // Ignore } } } }; } } else if( query instanceof GraphQuery ) { GraphQuery gQuery = (GraphQuery) query; /* queryResult = gQuery.evaluate(); registry = RDFWriterRegistry.getInstance(); view = GraphQueryResultView.getInstance(); */ conn.close(); } else if( query instanceof BooleanQuery ) { BooleanQuery bQuery = (BooleanQuery) query; /* queryResult = bQuery.evaluate(); registry = BooleanQueryResultWriterRegistry.getInstance(); view = BooleanQueryResultView.getInstance(); */ conn.close(); } else { conn.close(); throw new ResourceException( Status.CLIENT_ERROR_BAD_REQUEST, "Unsupported query type: " + query.getClass().getName() ); } } catch( RepositoryException e ) { throw new ResourceException( Status.SERVER_ERROR_INTERNAL, e ); } catch( QueryEvaluationException e ) { throw new ResourceException( Status.SERVER_ERROR_INTERNAL, e ); } return null; } private Query getQuery( Repository repository, RepositoryConnection repositoryCon, String queryStr ) throws ResourceException { Form form = getRequest().getResourceRef().getQueryAsForm(); Query result; // default query language is SPARQL QueryLanguage queryLn = QueryLanguage.SPARQL; // determine if inferred triples should be included in query evaluation boolean includeInferred = true; // build a dataset, if specified String[] defaultGraphURIs = form.getValuesArray( DEFAULT_GRAPH_PARAM_NAME ); String[] namedGraphURIs = form.getValuesArray( NAMED_GRAPH_PARAM_NAME ); DatasetImpl dataset = null; if( defaultGraphURIs.length > 0 || namedGraphURIs.length > 0 ) { dataset = new DatasetImpl(); if( defaultGraphURIs.length > 0 ) { for( String defaultGraphURI : defaultGraphURIs ) { try { URI uri = repository.getValueFactory().createURI( defaultGraphURI ); dataset.addDefaultGraph( uri ); } catch( IllegalArgumentException e ) { throw new ResourceException( Status.CLIENT_ERROR_BAD_REQUEST, "Illegal URI for default graph: " + defaultGraphURI ); } } } if( namedGraphURIs.length > 0 ) { for( String namedGraphURI : namedGraphURIs ) { try { URI uri = repository.getValueFactory().createURI( namedGraphURI ); dataset.addNamedGraph( uri ); } catch( IllegalArgumentException e ) { throw new ResourceException( Status.CLIENT_ERROR_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 = Collections.enumeration( form.getValuesMap().keySet() ); 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 = parseValueParam( repository, form, parameterName ); result.setBinding( bindingName, bindingValue ); } } } catch( UnsupportedQueryLanguageException e ) { throw new ResourceException( Status.CLIENT_ERROR_BAD_REQUEST, e.getMessage() ); } catch( MalformedQueryException e ) { throw new ResourceException( Status.CLIENT_ERROR_BAD_REQUEST, e.getMessage() ); } catch( RepositoryException e ) { throw new ResourceException( Status.SERVER_ERROR_INTERNAL, e.getMessage() ); } return result; } private Value parseValueParam( Repository repository, Form form, String parameterName ) throws ResourceException { String paramValue = form.getFirstValue( parameterName ); try { return Protocol.decodeValue( paramValue, repository.getValueFactory() ); } catch( IllegalArgumentException e ) { throw new ResourceException( Status.CLIENT_ERROR_BAD_REQUEST, "Invalid value for parameter '" + parameterName + "': " + paramValue ); } } }