/*
* 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.jena.fuseki.servlets;
import java.util.Enumeration ;
import javax.servlet.http.HttpServletRequest ;
import org.apache.jena.fuseki.Fuseki ;
import org.apache.jena.graph.Graph ;
import org.apache.jena.graph.Node ;
import org.apache.jena.graph.NodeFactory ;
import org.apache.jena.riot.web.HttpNames ;
import org.apache.jena.riot.RiotException ;
import org.apache.jena.riot.system.IRIResolver ;
import org.apache.jena.sparql.core.DatasetGraph ;
public abstract class SPARQL_GSP extends ActionREST
{
private static final long serialVersionUID = 5807509103047946413L;
protected final static Target determineTarget(HttpAction action) {
// Delayed until inside a transaction.
if ( action.getActiveDSG() == null )
ServletOps.errorOccurred("Internal error : No action graph (not in a transaction?)") ;
boolean dftGraph = getOneOnly(action.request, HttpNames.paramGraphDefault) != null ;
String uri = getOneOnly(action.request, HttpNames.paramGraph) ;
if ( !dftGraph && uri == null ) {
// No params - direct naming.
if ( ! Fuseki.GSP_DIRECT_NAMING )
ServletOps.errorBadRequest("Neither default graph nor named graph specified") ;
// Direct naming.
String directName = action.request.getRequestURL().toString() ;
if ( action.request.getRequestURI().equals(action.getDatasetName()) )
// No name (should have been a quads operations).
ServletOps.errorBadRequest("Neither default graph nor named graph specified and no direct name") ;
Node gn = NodeFactory.createURI(directName) ;
return namedTarget(action, directName) ;
}
if ( dftGraph )
return Target.createDefault(action.getActiveDSG()) ;
// Named graph
if ( uri.equals(HttpNames.valueDefault ) )
// But "named" default
return Target.createDefault(action.getActiveDSG()) ;
// Strictly, a bit naughty on the URI resolution. But more sensible.
// Base is dataset.
// XXX Remove any service.
String base = action.request.getRequestURL().toString() ; //wholeRequestURL(request) ;
// Make sure it ends in "/", ie. dataset as container.
if ( action.request.getQueryString() != null && ! base.endsWith("/") )
base = base + "/" ;
String absUri = null ;
try { absUri = IRIResolver.resolveString(uri, base) ; }
catch (RiotException ex) {
// Bad IRI
ServletOps.errorBadRequest("Bad IRI: "+ex.getMessage()) ;
}
return namedTarget(action, absUri) ;
}
private static Target namedTarget(HttpAction action, String graphName) {
Node gn = NodeFactory.createURI(graphName) ;
return Target.createNamed(action.getActiveDSG(), graphName, gn) ;
}
// struct for target
protected static final class Target
{
final boolean isDefault ;
final DatasetGraph dsg ;
private Graph _graph ;
final String name ;
final Node graphName ;
static Target createNamed(DatasetGraph dsg, String name, Node graphName) {
return new Target(false, dsg, name, graphName) ;
}
static Target createDefault(DatasetGraph dsg) {
return new Target(true, dsg, null, null) ;
}
/** Create a new Target which is like the original but aimed at a different DatasetGraph */
static Target retarget(Target target, DatasetGraph dsg) {
Target target2 = new Target(target, dsg) ;
target2._graph = null ;
return target2 ;
}
private Target(boolean isDefault, DatasetGraph dsg, String name, Node graphName) {
this.isDefault = isDefault ;
this.dsg = dsg ;
this._graph = null ;
this.name = name ;
this.graphName = graphName ;
if ( isDefault )
{
if ( name != null || graphName != null )
throw new IllegalArgumentException("Inconsistent: default and a graph name/node") ;
}
else
{
if ( name == null || graphName == null )
throw new IllegalArgumentException("Inconsistent: not default and/or no graph name/node") ;
}
}
private Target(Target other, DatasetGraph dsg) {
this.isDefault = other.isDefault ;
this.dsg = dsg ; //other.dsg ;
this._graph = other._graph ;
this.name = other.name ;
this.graphName = other.graphName ;
}
/** Get a graph for the action - this may create a graph in the dataset - this is not a test for graph existence */
public Graph graph() {
if ( ! isGraphSet() )
{
if ( isDefault )
_graph = dsg.getDefaultGraph() ;
else
_graph = dsg.getGraph(graphName) ;
}
return _graph ;
}
public boolean exists()
{
if ( isDefault ) return true ;
return dsg.containsGraph(graphName) ;
}
public boolean isGraphSet()
{
return _graph != null ;
}
@Override
// protected static ErrorHandler errorHandler = ErrorHandlerFactory.errorHandlerStd(log) ;
public String toString()
{
if ( isDefault ) return "default" ;
return name ;
}
}
public SPARQL_GSP()
{ super() ; }
@Override
protected void validate(HttpAction action)
{
HttpServletRequest request = action.request ;
if ( request.getQueryString() == null ) {
//errorBadRequest("No query string") ;
return ;
}
String g = request.getParameter(HttpNames.paramGraph) ;
String d = request.getParameter(HttpNames.paramGraphDefault) ;
if ( g != null && d !=null )
ServletOps.errorBadRequest("Both ?default and ?graph in the query string of the request") ;
if ( g == null && d == null )
ServletOps.errorBadRequest("Neither ?default nor ?graph in the query string of the request") ;
int x1 = SPARQL_Protocol.countParamOccurences(request, HttpNames.paramGraph) ;
int x2 = SPARQL_Protocol.countParamOccurences(request, HttpNames.paramGraphDefault) ;
if ( x1 > 1 )
ServletOps.errorBadRequest("Multiple ?default in the query string of the request") ;
if ( x2 > 1 )
ServletOps.errorBadRequest("Multiple ?graph in the query string of the request") ;
Enumeration<String> en = request.getParameterNames() ;
for ( ; en.hasMoreElements() ; )
{
String h = en.nextElement() ;
if ( ! HttpNames.paramGraph.equals(h) && ! HttpNames.paramGraphDefault.equals(h) )
ServletOps.errorBadRequest("Unknown parameter '"+h+"'") ;
// one of ?default and &graph
if ( request.getParameterValues(h).length != 1 )
ServletOps.errorBadRequest("Multiple parameters '"+h+"'") ;
}
}
protected static String getOneOnly(HttpServletRequest request, String name)
{
String[] values = request.getParameterValues(name) ;
if ( values == null )
return null ;
if ( values.length == 0 )
return null ;
if ( values.length > 1 )
ServletOps.errorBadRequest("Multiple occurrences of '"+name+"'") ;
return values[0] ;
}
}