blob: 5a36e0aacc93d1a4da0c9e7af8da7230330d7b2b [file] [log] [blame]
/*
* 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.apache.zest.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.apache.zest.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 );
}
}
}