You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2016/05/14 14:03:35 UTC
[36/42] jena git commit: Merge commit 'refs/pull/143/head' of
github.com:apache/jena
http://git-wip-us.apache.org/repos/asf/jena/blob/4b5cd267/jena-arq/src/main/java/org/apache/jena/query/ParameterizedSparqlString.java
----------------------------------------------------------------------
diff --cc jena-arq/src/main/java/org/apache/jena/query/ParameterizedSparqlString.java
index e096688,e096688..b6d7460
--- a/jena-arq/src/main/java/org/apache/jena/query/ParameterizedSparqlString.java
+++ b/jena-arq/src/main/java/org/apache/jena/query/ParameterizedSparqlString.java
@@@ -1,1710 -1,1710 +1,1710 @@@
--/**
-- * 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.query;
--
--import java.net.URL;
--import java.util.ArrayList;
--import java.util.Calendar;
--import java.util.Collections;
--import java.util.HashMap;
--import java.util.Iterator;
--import java.util.List;
--import java.util.Map;
--import java.util.Map.Entry;
--import java.util.regex.MatchResult;
--import java.util.regex.Matcher;
--import java.util.regex.Pattern;
--
--import org.apache.jena.atlas.lib.Pair;
--import org.apache.jena.datatypes.RDFDatatype ;
--import org.apache.jena.graph.Node ;
--import org.apache.jena.graph.NodeFactory ;
--import org.apache.jena.iri.IRI;
--import org.apache.jena.rdf.model.Literal ;
--import org.apache.jena.rdf.model.Model ;
--import org.apache.jena.rdf.model.ModelFactory ;
--import org.apache.jena.rdf.model.RDFNode ;
--import org.apache.jena.shared.PrefixMapping ;
--import org.apache.jena.shared.impl.PrefixMappingImpl ;
--import org.apache.jena.sparql.ARQException ;
--import org.apache.jena.sparql.serializer.SerializationContext ;
--import org.apache.jena.sparql.util.FmtUtils ;
--import org.apache.jena.sparql.util.NodeFactoryExtra ;
--import org.apache.jena.update.UpdateFactory ;
--import org.apache.jena.update.UpdateRequest ;
--
--/**
-- * <p>
-- * A Parameterized SPARQL String is a SPARQL query/update into which values may
-- * be injected.
-- * </p>
-- * <h3>Injecting Values</h3>
-- * <p>
-- * Values may be injected in several ways:
-- * </p>
-- * <ul>
-- * <li>By treating a variable in the SPARQL string as a parameter</li>
-- * <li>Using JDBC style positional parameters</li>
-- * <li>Appending values directly to the command text being built</li>
-- * </ul>
-- * <h4>Variable Parameters</h3>
-- * <p>
-- * Any variable in the command may have a value injected to it, injecting a
-- * value replaces all usages of that variable in the command i.e. substitutes
-- * the variable for a constant, injection is done by textual substitution.
-- * </p> <h4>Positional Parameters</h4>
-- * <p>
-- * You can use JDBC style positional parameters if you prefer, a JDBC style
-- * parameter is a single {@code ?} followed by whitespace or certain punctuation
-- * characters (currently {@code ; , .}). Positional parameters have a unique
-- * index which reflects the order in which they appear in the string. Positional
-- * parameters use a zero based index.
-- * </p>
-- * <h4>Buffer Usage</h3> </p> Additionally you may use this purely as a
-- * {@link StringBuffer} replacement for creating queries since it provides a
-- * large variety of convenience methods for appending things either as-is or as
-- * nodes (which causes appropriate formatting to be applied). </p>
-- * <h3>Intended Usage</h3>
-- * <p>
-- * The intended usage of this is where using a {@link QuerySolutionMap} as
-- * initial bindings is either inappropriate or not possible e.g.
-- * </p>
-- * <ul>
-- * <li>Generating query/update strings in code without lots of error prone and
-- * messy string concatenation</li>
-- * <li>Preparing a query/update for remote execution</li>
-- * <li>Where you do not want to simply say some variable should have a certain
-- * value but rather wish to insert constants into the query/update in place of
-- * variables</li>
-- * <li>Defending against SPARQL injection when creating a query/update using
-- * some external input, see SPARQL Injection notes for limitations.</li>
-- * <li>Provide a more convenient way to prepend common prefixes to your query</li>
-- * </ul>
-- * <p>
-- * This class is useful for preparing both queries and updates hence the generic
-- * name as it provides programmatic ways to replace variables in the query with
-- * constants and to add prefix and base declarations. A {@link Query} or
-- * {@link UpdateRequest} can be created using the {@link #asQuery()} and
-- * {@link #asUpdate()} methods assuming the command an instance represents is
-- * actually valid as a query/update.
-- * </p>
-- * <h3>Warnings</h3>
-- * <ol>
-- * <li>Note that this class does not in any way check that your command is
-- * syntactically correct until such time as you try and parse it as a
-- * {@link Query} or {@link UpdateRequest}.</li>
-- * <li>Also note that injection is done purely based on textual replacement, it
-- * does not understand or respect variable scope in any way. For example if your
-- * command text contains sub queries you should ensure that variables within the
-- * sub query which you don't want replaced have distinct names from those in the
-- * outer query you do want replaced (or vice versa)</li>
-- * </ol>
-- * <h3>SPARQL Injection Notes</h3>
-- * <p>
-- * While this class was in part designed to prevent SPARQL injection it is by no
-- * means foolproof because it works purely at the textual level. The current
-- * version of the code addresses some possible attack vectors that the
-- * developers have identified but we do not claim to be sufficiently devious to
-- * have thought of and prevented every possible attack vector.
-- * </p>
-- * <p>
-- * Therefore we <strong>strongly</strong> recommend that users concerned about
-- * SPARQL Injection attacks perform their own validation on provided parameters
-- * and test their use of this class themselves prior to its use in any security
-- * conscious deployment. We also recommend that users do not use easily
-- * guess-able variable names for their parameters as these can allow a chained
-- * injection attack though generally speaking the code should prevent these.
-- * </p>
-- */
--public class ParameterizedSparqlString implements PrefixMapping {
--
-- private Model model = ModelFactory.createDefaultModel();
--
-- private StringBuilder cmd = new StringBuilder();
-- private String baseUri;
-- private Map<String, Node> params = new HashMap<>();
-- private Map<Integer, Node> positionalParams = new HashMap<>();
-- private PrefixMapping prefixes;
--
-- /**
-- * Creates a new parameterized string
-- *
-- * @param command
-- * Raw Command Text
-- * @param map
-- * Initial Parameters to inject
-- * @param base
-- * Base URI
-- * @param prefixes
-- * Prefix Mapping
-- */
-- public ParameterizedSparqlString(String command, QuerySolutionMap map, String base, PrefixMapping prefixes) {
-- if (command != null)
-- this.cmd.append(command);
-- this.setParams(map);
-- this.baseUri = (base != null && !base.equals("") ? base : null);
-- this.prefixes = new PrefixMappingImpl();
-- if (prefixes != null)
-- this.prefixes.setNsPrefixes(prefixes);
-- }
--
-- /**
-- * Creates a new parameterized string
-- *
-- * @param command
-- * Raw Command Text
-- * @param map
-- * Initial Parameters to inject
-- * @param base
-- * Base URI
-- */
-- public ParameterizedSparqlString(String command, QuerySolutionMap map, String base) {
-- this(command, map, base, null);
-- }
--
-- /**
-- * Creates a new parameterized string
-- *
-- * @param command
-- * Raw Command Text
-- * @param map
-- * Initial Parameters to inject
-- * @param prefixes
-- * Prefix Mapping
-- */
-- public ParameterizedSparqlString(String command, QuerySolutionMap map, PrefixMapping prefixes) {
-- this(command, map, null, prefixes);
-- }
--
-- /**
-- * Creates a new parameterized string
-- *
-- * @param command
-- * Raw Command Text
-- * @param map
-- * Initial Parameters to inject
-- */
-- public ParameterizedSparqlString(String command, QuerySolutionMap map) {
-- this(command, map, null, null);
-- }
--
-- /**
-- * Creates a new parameterized string
-- *
-- * @param command
-- * Raw Command Text
-- * @param base
-- * Base URI
-- * @param prefixes
-- * Prefix Mapping
-- */
-- public ParameterizedSparqlString(String command, String base, PrefixMapping prefixes) {
-- this(command, null, base, prefixes);
-- }
--
-- /**
-- * Creates a new parameterized string
-- *
-- * @param command
-- * Raw Command Text
-- * @param prefixes
-- * Prefix Mapping
-- */
-- public ParameterizedSparqlString(String command, PrefixMapping prefixes) {
-- this(command, null, null, prefixes);
-- }
--
-- /**
-- * Creates a new parameterized string
-- *
-- * @param command
-- * Raw Command Text
-- * @param base
-- * Base URI
-- */
-- public ParameterizedSparqlString(String command, String base) {
-- this(command, null, base, null);
-- }
--
-- /**
-- * Creates a new parameterized string
-- *
-- * @param command
-- * Raw Command Text
-- */
-- public ParameterizedSparqlString(String command) {
-- this(command, null, null, null);
-- }
--
-- /**
-- * Creates a new parameterized string
-- *
-- * @param map
-- * Initial Parameters to inject
-- * @param prefixes
-- * Prefix Mapping
-- */
-- public ParameterizedSparqlString(QuerySolutionMap map, PrefixMapping prefixes) {
-- this(null, map, null, prefixes);
-- }
--
-- /**
-- * Creates a new parameterized string
-- *
-- * @param map
-- * Initial Parameters to inject
-- */
-- public ParameterizedSparqlString(QuerySolutionMap map) {
-- this(null, map, null, null);
-- }
--
-- /**
-- * Creates a new parameterized string
-- *
-- * @param prefixes
-- * Prefix Mapping
-- */
-- public ParameterizedSparqlString(PrefixMapping prefixes) {
-- this(null, null, null, prefixes);
-- }
--
-- /**
-- * Creates a new parameterized string with an empty command text
-- */
-- public ParameterizedSparqlString() {
-- this("", null, null, null);
-- }
--
-- /**
-- * Sets the command text, overwriting any existing command text. If you want
-- * to append to the command text use one of the {@link #append(String)},
-- * {@link #appendIri(String)}, {@link #appendLiteral(String)} or
-- * {@link #appendNode(Node)} methods instead
-- *
-- * @param command
-- * Command Text
-- */
-- public void setCommandText(String command) {
-- this.cmd = new StringBuilder();
-- this.cmd.append(command);
-- }
--
-- /**
-- * Appends some text as-is to the existing command text, to ensure correct
-- * formatting when used as a constant consider using the
-- * {@link #appendLiteral(String)} or {@link #appendIri(String)} method as
-- * appropriate
-- *
-- * @param text
-- * Text to append
-- */
-- public void append(String text) {
-- this.cmd.append(text);
-- }
--
-- /**
-- * Appends a character as-is to the existing command text, to ensure correct
-- * formatting when used as a constant consider using one of the
-- * {@code appendLiteral()} methods
-- *
-- * @param c
-- * Character to append
-- */
-- public void append(char c) {
-- this.cmd.append(c);
-- }
--
-- /**
-- * Appends a boolean as-is to the existing command text, to ensure correct
-- * formatting when used as a constant consider using the
-- * {@link #appendLiteral(boolean)} method
-- *
-- * @param b
-- * Boolean to append
-- */
-- public void append(boolean b) {
-- this.cmd.append(b);
-- }
--
-- /**
-- * Appends a double as-is to the existing command text, to ensure correct
-- * formatting when used as a constant consider using the
-- * {@link #appendLiteral(double)} method
-- *
-- * @param d
-- * Double to append
-- */
-- public void append(double d) {
-- this.cmd.append(d);
-- }
--
-- /**
-- * Appends a float as-is to the existing command text, to ensure correct
-- * formatting when used as a constant consider using the
-- * {@link #appendLiteral(float)} method
-- *
-- * @param f
-- * Float to append
-- */
-- public void append(float f) {
-- this.cmd.append(f);
-- }
--
-- /**
-- * Appends an integer as-is to the existing command text, to ensure correct
-- * formatting when used as a constant consider using the
-- * {@link #appendLiteral(int)} method
-- *
-- * @param i
-- * Integer to append
-- */
-- public void append(int i) {
-- this.cmd.append(i);
-- }
--
-- /**
-- * Appends a long as-is to the existing command text, to ensure correct
-- * formatting when used as a constant consider using the
-- * {@link #appendLiteral(long)} method
-- *
-- * @param l
-- * Long to append
-- */
-- public void append(long l) {
-- this.cmd.append(l);
-- }
--
-- /**
-- * Appends an object as-is to the existing command text, to ensure correct
-- * formatting when used as a constant consider converting into a more
-- * specific type and using the appropriate {@code appendLiteral()},
-- * {@code appendIri()} or {@code appendNode} methods
-- *
-- * @param obj
-- * Object to append
-- */
-- public void append(Object obj) {
-- this.cmd.append(obj);
-- }
--
-- /**
-- * Appends a Node to the command text as a constant using appropriate
-- * formatting
-- *
-- * @param n
-- * Node to append
-- */
-- public void appendNode(Node n) {
-- SerializationContext context = new SerializationContext(this.prefixes);
-- context.setBaseIRI(this.baseUri);
-- this.cmd.append(this.stringForNode(n, context));
-- }
--
-- /**
-- * Appends a Node to the command text as a constant using appropriate
-- * formatting
-- *
-- * @param n
-- * Node to append
-- */
-- public void appendNode(RDFNode n) {
-- this.appendNode(n.asNode());
-- }
--
-- /**
-- * Appends a URI to the command text as a constant using appropriate
-- * formatting
-- *
-- * @param uri
-- * URI to append
-- */
-- public void appendIri(String uri) {
-- this.appendNode(NodeFactory.createURI(uri));
-- }
--
-- /**
-- * Appends an IRI to the command text as a constant using appropriate
-- * formatting
-- *
-- * @param iri
-- * IRI to append
-- */
-- public void appendIri(IRI iri) {
-- this.appendNode(NodeFactory.createURI(iri.toString()));
-- }
--
-- /**
-- * Appends a simple literal as a constant using appropriate formatting
-- *
-- * @param value
-- * Lexical Value
-- */
-- public void appendLiteral(String value) {
-- this.appendNode(NodeFactoryExtra.createLiteralNode(value, null, null));
-- }
--
-- /**
-- * Appends a literal with a lexical value and language to the command text
-- * as a constant using appropriate formatting
-- *
-- * @param value
-- * Lexical Value
-- * @param lang
-- * Language
-- */
-- public void appendLiteral(String value, String lang) {
-- this.appendNode(NodeFactoryExtra.createLiteralNode(value, lang, null));
-- }
--
-- /**
-- * Appends a Typed Literal to the command text as a constant using
-- * appropriate formatting
-- *
-- * @param value
-- * Lexical Value
-- * @param datatype
-- * Datatype
-- */
-- public void appendLiteral(String value, RDFDatatype datatype) {
-- this.appendNode(NodeFactoryExtra.createLiteralNode(value, null, datatype.getURI()));
-- }
--
-- /**
-- * Appends a boolean to the command text as a constant using appropriate
-- * formatting
-- *
-- * @param b
-- * Boolean to append
-- */
-- public void appendLiteral(boolean b) {
-- this.appendNode(this.model.createTypedLiteral(b));
-- }
--
-- /**
-- * Appends an integer to the command text as a constant using appropriate
-- * formatting
-- *
-- * @param i
-- * Integer to append
-- */
-- public void appendLiteral(int i) {
-- this.appendNode(NodeFactoryExtra.intToNode(i));
-- }
--
-- /**
-- * Appends a long to the command text as a constant using appropriate
-- * formatting
-- *
-- * @param l
-- * Long to append
-- */
-- public void appendLiteral(long l) {
-- this.appendNode(NodeFactoryExtra.intToNode(l));
-- }
--
-- /**
-- * Appends a float to the command text as a constant using appropriate
-- * formatting
-- *
-- * @param f
-- * Float to append
-- */
-- public void appendLiteral(float f) {
-- this.appendNode(this.model.createTypedLiteral(f));
-- }
--
-- /**
-- * Appends a double to the command text as a constant using appropriate
-- * formatting
-- *
-- * @param d
-- * Double to append
-- */
-- public void appendLiteral(double d) {
-- this.appendNode(this.model.createTypedLiteral(d));
-- }
--
-- /**
-- * Appends a date time to the command text as a constant using appropriate
-- * formatting
-- *
-- * @param dt
-- * Date Time to append
-- */
-- public void appendLiteral(Calendar dt) {
-- this.appendNode(this.model.createTypedLiteral(dt));
-- }
--
-- /**
-- * Gets the basic Command Text
-- * <p>
-- * <strong>Note:</strong> This will not reflect any injected parameters, to
-- * see the command with injected parameters invoke the {@link #toString()}
-- * method
-- * </p>
-- *
-- * @return Command Text
-- */
-- public String getCommandText() {
-- return this.cmd.toString();
-- }
--
-- /**
-- * Sets the Base URI which will be prepended to the query/update
-- *
-- * @param base
-- * Base URI
-- */
-- public void setBaseUri(String base) {
-- this.baseUri = base;
-- }
--
-- /**
-- * Gets the Base URI which will be prepended to a query
-- *
-- * @return Base URI
-- */
-- public String getBaseUri() {
-- return this.baseUri;
-- }
--
-- /**
-- * Helper method which does the validation of the parameters
-- *
-- * @param n
-- * Node
-- */
-- protected void validateParameterValue(Node n) {
-- if (n.isURI()) {
-- if (n.getURI().contains(">"))
-- throw new ARQException("Value for the parameter contains a SPARQL injection risk");
-- }
-- }
--
-- /**
-- * Sets the Parameters
-- *
-- * @param map
-- * Parameters
-- */
-- public void setParams(QuerySolutionMap map) {
-- if (map != null) {
-- Iterator<String> iter = map.varNames();
-- while (iter.hasNext()) {
-- String var = iter.next();
-- this.setParam(var, map.get(var).asNode());
-- }
-- }
-- }
--
-- /**
-- * Sets a Positional Parameter
-- * <p>
-- * Setting a parameter to null is equivalent to calling
-- * {@link #clearParam(int)} for the given variable
-- * </p>
-- *
-- * @param index
-- * Positional Index
-- * @param n
-- * Node
-- */
-- public void setParam(int index, Node n) {
-- if (index < 0)
-- throw new IndexOutOfBoundsException();
-- if (n != null) {
-- this.validateParameterValue(n);
-- this.positionalParams.put(index, n);
-- } else {
-- this.positionalParams.remove(index);
-- }
-- }
--
-- /**
-- * Sets a variable parameter
-- * <p>
-- * Setting a parameter to null is equivalent to calling
-- * {@link #clearParam(String)} for the given variable
-- * </p>
-- *
-- * @param var
-- * Variable
-- * @param n
-- * Value
-- *
-- */
-- public void setParam(String var, Node n) {
-- if (var == null)
-- throw new IllegalArgumentException("var cannot be null");
-- if (var.startsWith("?") || var.startsWith("$"))
-- var = var.substring(1);
-- if (n != null) {
-- this.validateParameterValue(n);
-- this.params.put(var, n);
-- } else {
-- this.params.remove(var);
-- }
-- }
--
-- /**
-- * Sets a positional parameter
-- * <p>
-- * Setting a parameter to null is equivalent to calling
-- * {@link #clearParam(String)} for the given variable
-- * </p>
-- *
-- * @param index
-- * Positional Index
-- * @param n
-- * Node
-- */
-- public void setParam(int index, RDFNode n) {
-- this.setParam(index, n.asNode());
-- }
--
-- /**
-- * Sets a variable parameter
-- * <p>
-- * Setting a parameter to null is equivalent to calling
-- * {@link #clearParam(String)} for the given variable
-- * </p>
-- *
-- * @param var
-- * Variable
-- * @param n
-- * Value
-- */
-- public void setParam(String var, RDFNode n) {
-- this.setParam(var, n.asNode());
-- }
--
-- /**
-- * Sets a positional parameter to an IRI
-- * <p>
-- * Setting a parameter to null is equivalent to calling
-- * {@link #clearParam(int)} for the given index
-- * </p>
-- *
-- * @param index
-- * Positional Index
-- * @param iri
-- * IRI
-- */
-- public void setIri(int index, String iri) {
-- this.setParam(index, NodeFactory.createURI(iri));
-- }
--
-- /**
-- * Sets a variable parameter to an IRI
-- * <p>
-- * Setting a parameter to null is equivalent to calling
-- * {@link #clearParam(String)} for the given variable
-- * </p>
-- *
-- * @param var
-- * Variable
-- * @param iri
-- * IRI
-- */
-- public void setIri(String var, String iri) {
-- this.setParam(var, NodeFactory.createURI(iri));
-- }
--
-- /**
-- * Sets a positional parameter to an IRI
-- * <p>
-- * Setting a parameter to null is equivalent to calling
-- * {@link #clearParam(int)} for the given index
-- * </p>
-- *
-- * @param index
-- * Positional Index
-- * @param iri
-- * IRI
-- */
-- public void setIri(int index, IRI iri) {
-- this.setIri(index, iri.toString());
-- }
--
-- /**
-- * Sets a variable parameter to an IRI
-- * <p>
-- * Setting a parameter to null is equivalent to calling
-- * {@link #clearParam(String)} for the given variable
-- * </p>
-- *
-- * @param var
-- * Variable
-- * @param iri
-- * IRI
-- */
-- public void setIri(String var, IRI iri) {
-- this.setIri(var, iri.toString());
-- }
--
-- /**
-- * Sets a positional parameter to an IRI
-- * <p>
-- * Setting a parameter to null is equivalent to calling
-- * {@link #clearParam(int)} for the given index
-- * </p>
-- *
-- * @param index
-- * Positional Index
-- * @param url
-- * URL
-- */
-- public void setIri(int index, URL url) {
-- this.setIri(index, url.toString());
-- }
--
-- /**
-- * Sets a variable parameter to an IRI
-- * <p>
-- * Setting a parameter to null is equivalent to calling
-- * {@link #clearParam(String)} for the given variable
-- * </p>
-- *
-- * @param var
-- * Variable
-- * @param url
-- * URL used as IRI
-- *
-- */
-- public void setIri(String var, URL url) {
-- this.setIri(var, url.toString());
-- }
--
-- /**
-- * Sets a positional parameter to a Literal
-- * <p>
-- * Setting a parameter to null is equivalent to calling
-- * {@link #clearParam(int)} for the given index
-- * </p>
-- *
-- * @param index
-- * Positional Index
-- * @param lit
-- * Value
-- *
-- */
-- public void setLiteral(int index, Literal lit) {
-- this.setParam(index, lit.asNode());
-- }
--
-- /**
-- * Sets a variable parameter to a Literal
-- * <p>
-- * Setting a parameter to null is equivalent to calling
-- * {@link #clearParam(String)} for the given variable
-- * </p>
-- *
-- * @param var
-- * Variable
-- * @param lit
-- * Value
-- *
-- */
-- public void setLiteral(String var, Literal lit) {
-- this.setParam(var, lit.asNode());
-- }
--
-- /**
-- * Sets a positional parameter to a literal
-- * <p>
-- * Setting a parameter to null is equivalent to calling
-- * {@link #clearParam(int)} for the given index
-- * </p>
-- *
-- * @param index
-- * Positional Index
-- * @param value
-- * Lexical Value
-- *
-- */
-- public void setLiteral(int index, String value) {
-- this.setParam(index, NodeFactoryExtra.createLiteralNode(value, null, null));
-- }
--
-- /**
-- * Sets a variable parameter to a literal
-- * <p>
-- * Setting a parameter to null is equivalent to calling
-- * {@link #clearParam(String)} for the given variable
-- * </p>
-- *
-- * @param var
-- * Variable
-- * @param value
-- * Lexical Value
-- *
-- */
-- public void setLiteral(String var, String value) {
-- this.setParam(var, NodeFactoryExtra.createLiteralNode(value, null, null));
-- }
--
-- /**
-- * Sets a positional parameter to a literal with a language
-- * <p>
-- * Setting a parameter to null is equivalent to calling
-- * {@link #clearParam(int)} for the given index
-- * </p>
-- *
-- * @param index
-- * Positional index
-- * @param value
-- * Lexical Value
-- * @param lang
-- * Language
-- *
-- */
-- public void setLiteral(int index, String value, String lang) {
-- this.setParam(index, NodeFactoryExtra.createLiteralNode(value, lang, null));
-- }
--
-- /**
-- * Sets a variable parameter to a literal with a language
-- * <p>
-- * Setting a parameter to null is equivalent to calling
-- * {@link #clearParam(String)} for the given variable
-- * </p>
-- *
-- * @param var
-- * Variable
-- * @param value
-- * Lexical Value
-- * @param lang
-- * Language
-- *
-- */
-- public void setLiteral(String var, String value, String lang) {
-- this.setParam(var, NodeFactoryExtra.createLiteralNode(value, lang, null));
-- }
--
-- /**
-- * Sets a positional arameter to a typed literal
-- * <p>
-- * Setting a parameter to null is equivalent to calling
-- * {@link #clearParam(int)} for the given index
-- * </p>
-- *
-- * @param index
-- * Positional Index
-- * @param value
-- * Lexical Value
-- * @param datatype
-- * Datatype
-- *
-- */
-- public void setLiteral(int index, String value, RDFDatatype datatype) {
-- this.setParam(index, this.model.createTypedLiteral(value, datatype));
-- }
--
-- /**
-- * Sets a variable parameter to a typed literal
-- * <p>
-- * Setting a parameter to null is equivalent to calling
-- * {@link #clearParam(String)} for the given variable
-- * </p>
-- *
-- * @param var
-- * Variable
-- * @param value
-- * Lexical Value
-- * @param datatype
-- * Datatype
-- *
-- */
-- public void setLiteral(String var, String value, RDFDatatype datatype) {
-- this.setParam(var, this.model.createTypedLiteral(value, datatype));
-- }
--
-- /**
-- * Sets a positional parameter to a boolean literal
-- *
-- * @param index
-- * Positional Index
-- * @param value
-- * boolean
-- */
-- public void setLiteral(int index, boolean value) {
-- this.setParam(index, this.model.createTypedLiteral(value));
-- }
--
-- /**
-- * Sets a variable parameter to a boolean literal
-- *
-- * @param var
-- * Variable
-- * @param value
-- * boolean
-- */
-- public void setLiteral(String var, boolean value) {
-- this.setParam(var, this.model.createTypedLiteral(value));
-- }
--
-- /**
-- * Sets a positional parameter to an integer literal
-- *
-- * @param index
-- * Positional Index
-- * @param i
-- * Integer Value
-- */
-- public void setLiteral(int index, int i) {
-- this.setParam(index, NodeFactoryExtra.intToNode(i));
-- }
--
-- /**
-- * Sets a variable parameter to an integer literal
-- *
-- * @param var
-- * Variable
-- * @param i
-- * Integer Value
-- */
-- public void setLiteral(String var, int i) {
-- this.setParam(var, NodeFactoryExtra.intToNode(i));
-- }
--
-- /**
-- * Sets a positional parameter to an integer literal
-- *
-- * @param index
-- * Positional Index
-- * @param l
-- * Integer Value
-- */
-- public void setLiteral(int index, long l) {
-- this.setParam(index, NodeFactoryExtra.intToNode(l));
-- }
--
-- /**
-- * Sets a variable parameter to an integer literal
-- *
-- * @param var
-- * Variable
-- * @param l
-- * Integer Value
-- */
-- public void setLiteral(String var, long l) {
-- this.setParam(var, NodeFactoryExtra.intToNode(l));
-- }
--
-- /**
-- * Sets a positional parameter to a float literal
-- *
-- * @param index
-- * Positional Index
-- * @param f
-- * Float value
-- */
-- public void setLiteral(int index, float f) {
-- this.setParam(index, NodeFactoryExtra.floatToNode(f));
-- }
--
-- /**
-- * Sets a variable parameter to a float literal
-- *
-- * @param var
-- * Variable
-- * @param f
-- * Float value
-- */
-- public void setLiteral(String var, float f) {
-- this.setParam(var, NodeFactoryExtra.floatToNode(f));
-- }
--
-- /**
-- * Sets a positional parameter to a double literal
-- *
-- * @param index
-- * Positional Index
-- * @param d
-- * Double value
-- */
-- public void setLiteral(int index, double d) {
-- this.setParam(index, this.model.createTypedLiteral(d));
-- }
--
-- /**
-- * Sets a variable parameter to a double literal
-- *
-- * @param var
-- * Variable
-- * @param d
-- * Double value
-- */
-- public void setLiteral(String var, double d) {
-- this.setParam(var, this.model.createTypedLiteral(d));
-- }
--
-- /**
-- * Sets a positional parameter to a date time literal
-- *
-- * @param index
-- * Positional Index
-- * @param dt
-- * Date Time value
-- */
-- public void setLiteral(int index, Calendar dt) {
-- this.setParam(index, this.model.createTypedLiteral(dt));
-- }
--
-- /**
-- * Sets a variable parameter to a date time literal
-- *
-- * @param var
-- * Variable
-- * @param dt
-- * Date Time value
-- */
-- public void setLiteral(String var, Calendar dt) {
-- this.setParam(var, this.model.createTypedLiteral(dt));
-- }
--
-- /**
-- * Gets the current value for a variable parameter
-- *
-- * @param var
-- * Variable
-- * @return Current value or null if not set
-- */
-- public Node getParam(String var) {
-- return this.params.get(var);
-- }
--
-- /**
-- * Gets the current value for a positional parameter
-- *
-- * @param index
-- * Positional Index
-- * @return Current value or null if not set
-- */
-- public Node getParam(int index) {
-- return this.positionalParams.get(index);
-- }
--
-- /**
-- * Gets the variable names which are currently treated as variable
-- * parameters (i.e. have values set for them)
-- *
-- * @return Iterator of variable names
-- */
-- @Deprecated
-- public Iterator<String> getVars() {
-- return this.params.keySet().iterator();
-- }
--
-- /**
-- * Gets the map of currently set variable parameters, this will be an
-- * unmodifiable map
-- *
-- * @return Map of variable names and values
-- */
-- public Map<String, Node> getVariableParameters() {
-- return Collections.unmodifiableMap(this.params);
-- }
--
-- /**
-- * Gets the map of currently set positional parameters, this will be an
-- * unmodifiable map
-- *
-- * @return Map of positional indexes and values
-- */
-- public Map<Integer, Node> getPositionalParameters() {
-- return Collections.unmodifiableMap(this.positionalParams);
-- }
--
-- // TODO: Detecting eligible variable parameters
-- // public Iterator<String> getEligibleVariableParameters() {
-- //
-- // }
--
-- /**
-- * Gets the eligible positional parameters i.e. detected positional
-- * parameters that may be set in the command string as it currently stands
-- *
-- * @return Iterator of eligible positional parameters
-- */
-- public Iterator<Integer> getEligiblePositionalParameters() {
-- Pattern p = Pattern.compile("(\\?)[\\s;,.]");
-- List<Integer> positions = new ArrayList<>();
-- int index = 0;
-- Matcher matcher = p.matcher(this.cmd.toString());
-- while (matcher.find()) {
-- positions.add(index);
-- index++;
-- }
-- return positions.iterator();
-- }
--
-- /**
-- * Clears the value for a variable parameter so the given variable will not
-- * have a value injected
-- *
-- * @param var
-- * Variable
-- */
-- public void clearParam(String var) {
-- this.params.remove(var);
-- }
--
-- /**
-- * Clears the value for a positional parameter
-- *
-- * @param index
-- * Positional Index
-- */
-- public void clearParam(int index) {
-- this.positionalParams.remove(index);
-- }
--
-- /**
-- * Clears all values for both variable and positional parameters
-- */
-- public void clearParams() {
-- this.params.clear();
-- this.positionalParams.clear();
-- }
--
-- /**
-- * Helper method which checks whether it is safe to inject to a variable
-- * parameter the given value
-- *
-- * @param command
-- * Current command string
-- * @param var
-- * Variable
-- * @param n
-- * Value to inject
-- * @throws ARQException
-- * Thrown if not safe to inject, error message will describe why
-- * it is unsafe to inject
-- */
-- protected void validateSafeToInject(String command, String var, Node n) throws ARQException {
-- // Looks for the known injection attack vectors and throws an error if
-- // any are encountered
--
-- // A ?var surrounded by " or ' where the variable is a literal is an
-- // attack vector
-- Pattern p = Pattern.compile("\"[?$]" + var + "\"|'[?$]" + var + "'");
--
-- if (p.matcher(command).find() && n.isLiteral()) {
-- throw new ARQException(
-- "Command string is vunerable to injection attack, variable ?"
-- + var
-- + " appears surrounded directly by quotes and is bound to a literal which provides a SPARQL injection attack vector");
-- }
--
-- // Parse out delimiter info
-- DelimiterInfo delims = this.findDelimiters(command);
--
-- // Check each occurrence of the variable for safety
-- p = Pattern.compile("([?$]" + var + ")([^\\w]|$)");
-- Matcher matcher = p.matcher(command);
-- while (matcher.find()) {
-- MatchResult posMatch = matcher.toMatchResult();
--
-- if (n.isLiteral()) {
-- if (delims.isInsideLiteral(posMatch.start(1), posMatch.end(1))) {
-- throw new ARQException(
-- "Command string is vunerable to injection attack, variable ?"
-- + var
-- + " appears inside of a literal and is bound to a literal which provides a SPARQL injection attack vector");
-- }
-- }
-- }
-- }
--
-- /**
-- * Helper method which checks whether it is safe to inject to a positional
-- * parameter the given value
-- *
-- * @param command
-- * Current command string
-- * @param index
-- * Positional parameter index
-- * @param position
-- * Position within the command string at which the positional
-- * parameter occurs
-- * @param n
-- * Value to inject
-- * @throws ARQException
-- * Thrown if not safe to inject, error message will describe why
-- * it is unsafe to inject
-- */
-- protected void validateSafeToInject(String command, int index, int position, Node n) throws ARQException {
-- // Parse out delimiter info
-- DelimiterInfo delims = this.findDelimiters(command);
--
-- // Check each occurrence of the variable for safety
-- if (n.isLiteral()) {
-- if (delims.isInsideLiteral(position, position)) {
-- throw new ARQException(
-- "Command string is vunerable to injection attack, a positional paramter (index "
-- + index
-- + ") appears inside of a literal and is bound to a literal which provides a SPARQL injection attack vector");
-- }
-- }
-- }
--
-- /**
-- * Helper method which does light parsing on the command string to find the
-- * position of all relevant delimiters
-- *
-- * @param command
-- * Command String
-- * @return DelimiterInfo
-- */
-- protected final DelimiterInfo findDelimiters(String command) {
-- DelimiterInfo delims = new DelimiterInfo();
-- delims.parseFrom(command);
-- return delims;
-- }
--
-- protected final String stringForNode(Node n, SerializationContext context) {
-- String str = FmtUtils.stringForNode(n, context);
-- if (n.isLiteral() && str.contains("'")) {
-- // Should escape ' to avoid a possible injection vulnerability
-- str = str.replace("'", "\\'");
-- }
-- return str;
-- }
--
-- /**
-- * <p>
-- * This method is where the actual work happens, the original command text
-- * is always preserved and we just generated a temporary command string by
-- * prepending the defined Base URI and namespace prefixes at the start of
-- * the command and injecting the set parameters into a copy of that base
-- * command string and return the resulting command.
-- * </p>
-- * <p>
-- * This class makes no guarantees about the validity of the returned string
-- * for use as a SPARQL Query or Update, for example if a variable parameter
-- * was injected which was mentioned in the SELECT variables list you'd have
-- * a syntax error when you try to parse the query. If you run into issues
-- * like this try using a mixture of variable and positional parameters.
-- * </p>
-- *
-- * @throws ARQException
-- * May be thrown if the code detects a SPARQL Injection
-- * vulnerability because of the interaction of the command
-- * string and the injected variables
-- */
-- @Override
-- public String toString() {
-- String command = this.cmd.toString();
-- Pattern p;
--
-- // Go ahead and inject Variable Parameters
-- SerializationContext context = new SerializationContext(this.prefixes);
-- context.setBaseIRI(this.baseUri);
-- for (String var : this.params.keySet()) {
-- Node n = this.params.get(var);
-- if (n == null) {
-- continue;
-- }
-- this.validateSafeToInject(command, var, n);
--
-- p = Pattern.compile("([?$]" + var + ")([^\\w]|$)");
-- command = p.matcher(command).replaceAll(Matcher.quoteReplacement(this.stringForNode(n, context)) + "$2");
-- }
--
-- // Then inject Positional Parameters
-- // To do this we need to find the ? we will replace
-- p = Pattern.compile("(\\?)[\\s;,.]");
-- int index = -1;
-- int adj = 0;
-- Matcher matcher = p.matcher(command);
-- while (matcher.find()) {
-- index++;
-- MatchResult posMatch = matcher.toMatchResult();
--
-- Node n = this.positionalParams.get(index);
-- if (n == null)
-- continue;
-- this.validateSafeToInject(command, index, posMatch.start(1) + adj, n);
--
-- String nodeStr = this.stringForNode(n, context);
-- command = command.substring(0, posMatch.start() + adj) + nodeStr
-- + command.substring(posMatch.start() + adj + 1);
-- // Because we are using a matcher over the string state prior to
-- // starting replacements we need to
-- // track the offset adjustments to make
-- adj += nodeStr.length() - 1;
-- }
--
-- // Build the final command string
-- StringBuilder finalCmd = new StringBuilder();
--
-- // Add BASE declaration
-- if (this.baseUri != null) {
-- finalCmd.append("BASE ");
-- finalCmd.append(FmtUtils.stringForURI(this.baseUri, null, null));
-- finalCmd.append('\n');
-- }
--
-- // Then pre-pend prefixes
--
-- for (String prefix : this.prefixes.getNsPrefixMap().keySet()) {
-- finalCmd.append("PREFIX ");
-- finalCmd.append(prefix);
-- finalCmd.append(": ");
-- finalCmd.append(FmtUtils.stringForURI(this.prefixes.getNsPrefixURI(prefix), null, null));
-- finalCmd.append('\n');
-- }
--
-- finalCmd.append(command);
-- return finalCmd.toString();
-- }
--
-- /**
-- * Attempts to take the command text with parameters injected from the
-- * {@link #toString()} method and parse it as a {@link Query}
-- *
-- * @return Query if the command text is a valid SPARQL query
-- * @exception QueryException
-- * Thrown if the command text does not parse
-- */
-- public Query asQuery() throws QueryException {
-- return QueryFactory.create(this.toString());
-- }
--
-- /**
-- * Attempts to take the command text with parameters injected from the
-- * {@link #toString()} method and parse it as a {@link UpdateRequest}
-- *
-- * @return Update if the command text is a valid SPARQL Update request
-- * (one/more update commands)
-- */
-- public UpdateRequest asUpdate() {
-- return UpdateFactory.create(this.toString());
-- }
--
-- /**
-- * Makes a full copy of this parameterized string
-- *
-- * @return Copy of the string
-- */
-- public ParameterizedSparqlString copy() {
-- return this.copy(true, true, true);
-- }
--
-- /**
-- * Makes a copy of the command text, base URI and prefix mapping and
-- * optionally copies parameter values
-- *
-- * @param copyParams
-- * Whether to copy parameters
-- * @return Copy of the string
-- */
-- public ParameterizedSparqlString copy(boolean copyParams) {
-- return this.copy(copyParams, true, true);
-- }
--
-- /**
-- * Makes a copy of the command text and optionally copies other aspects
-- *
-- * @param copyParams
-- * Whether to copy parameters
-- * @param copyBase
-- * Whether to copy the Base URI
-- * @param copyPrefixes
-- * Whether to copy the prefix mappings
-- * @return Copy of the string
-- */
-- public ParameterizedSparqlString copy(boolean copyParams, boolean copyBase, boolean copyPrefixes) {
-- ParameterizedSparqlString copy = new ParameterizedSparqlString(this.cmd.toString(), null,
-- (copyBase ? this.baseUri : null), (copyPrefixes ? this.prefixes : null));
-- if (copyParams) {
-- Iterator<String> vars = this.getVars();
-- while (vars.hasNext()) {
-- String var = vars.next();
-- copy.setParam(var, this.getParam(var));
-- }
-- for (Entry<Integer, Node> entry : this.positionalParams.entrySet()) {
-- copy.setParam(entry.getKey(), entry.getValue());
-- }
-- }
-- return copy;
-- }
--
-- @Override
-- public PrefixMapping setNsPrefix(String prefix, String uri) {
-- return this.prefixes.setNsPrefix(prefix, uri);
-- }
--
-- @Override
-- public PrefixMapping removeNsPrefix(String prefix) {
-- return this.prefixes.removeNsPrefix(prefix);
-- }
--
-- @Override
-- public PrefixMapping setNsPrefixes(PrefixMapping other) {
-- return this.prefixes.setNsPrefixes(other);
-- }
--
-- @Override
-- public PrefixMapping setNsPrefixes(Map<String, String> map) {
-- return this.prefixes.setNsPrefixes(map);
-- }
--
-- @Override
-- public PrefixMapping withDefaultMappings(PrefixMapping map) {
-- return this.prefixes.withDefaultMappings(map);
-- }
--
-- @Override
-- public String getNsPrefixURI(String prefix) {
-- return this.prefixes.getNsPrefixURI(prefix);
-- }
--
-- @Override
-- public String getNsURIPrefix(String uri) {
-- return this.prefixes.getNsURIPrefix(uri);
-- }
--
-- @Override
-- public Map<String, String> getNsPrefixMap() {
-- return this.prefixes.getNsPrefixMap();
-- }
--
-- @Override
-- public String expandPrefix(String prefixed) {
-- return this.prefixes.expandPrefix(prefixed);
-- }
--
-- @Override
-- public String shortForm(String uri) {
-- return this.prefixes.shortForm(uri);
-- }
--
-- @Override
-- public String qnameFor(String uri) {
-- return this.prefixes.qnameFor(uri);
-- }
--
-- @Override
-- public PrefixMapping lock() {
-- return this.prefixes.lock();
-- }
--
-- @Override
-- public boolean samePrefixMappingAs(PrefixMapping other) {
-- return this.prefixes.samePrefixMappingAs(other);
-- }
--
-- /**
-- * Represents information about delimiters in a string
-- *
-- */
-- private class DelimiterInfo {
-- private List<Pair<Integer, String>> starts = new ArrayList<>();
-- private Map<Integer, Integer> stops = new HashMap<>();
--
-- /**
-- * Parse delimiters from a string, discards any previously parsed
-- * information
-- *
-- * @param command
-- * Command string
-- */
-- public void parseFrom(String command) {
-- this.starts.clear();
-- this.stops.clear();
--
-- char[] cs = command.toCharArray();
-- for (int i = 0; i < cs.length; i++) {
-- switch (cs[i]) {
-- case '"':
-- // Start of a Literal
-- // Is it a long literal?
-- if (i < cs.length - 2 && cs[i + 1] == '"' && cs[i + 2] == '"') {
-- this.addStart(i, "\"\"\"");
-- for (int j = i + 3; j < cs.length - 2; j++) {
-- if (cs[j] == '"' && cs[j + 1] == '"' && cs[j + 2] == '"') {
-- this.addStop(i, j + 2);
-- i = j + 2;
-- }
-- }
-- // Was unterminated
-- } else {
-- // Normal literal, scan till we see a " which is not
-- // preceded by a \
-- this.addStart(i, "\"");
-- for (int j = i + 1; j < cs.length; j++) {
-- if (cs[j] == '"' && cs[j - 1] != '\\') {
-- this.addStop(i, j);
-- i = j;
-- continue;
-- }
-- }
-- // Was unterminated
-- }
-- break;
-- case '<':
-- // Start of a URI
-- this.addStart(i, "<");
-- for (int j = i + 1; j < cs.length; j++) {
-- if (cs[j] == '>' && cs[j - 1] != '\\') {
-- this.addStop(i, j);
-- i = j;
-- continue;
-- }
-- }
-- // Was unterminated
-- break;
-- case '\'':
-- // Start of alternative literal form
-- // Start of a Literal
-- // Is it a long literal?
-- if (i < cs.length - 2 && cs[i + 1] == '\'' && cs[i + 2] == '\'') {
-- this.addStart(i, "'''");
-- for (int j = i + 3; j < cs.length - 2; j++) {
-- if (cs[j] == '\'' && cs[j + 1] == '\'' && cs[j + 2] == '\'') {
-- this.addStop(i, j + 2);
-- i = j + 2;
-- }
-- }
-- // Was unterminated
-- } else {
-- // Normal literal, scan till we see a ' which is not
-- // preceded by a \
-- this.addStart(i, "'");
-- for (int j = i + 1; j < cs.length; j++) {
-- if (cs[j] == '\'' && cs[j - 1] != '\\') {
-- this.addStop(i, j);
-- i = j;
-- continue;
-- }
-- }
-- // Was unterminated
-- }
-- break;
-- case '#':
-- // Start of a comment
-- // Scan to next newline
-- this.addStart(i, "#");
-- for (int j = i + 1; j < cs.length; j++) {
-- if (cs[j] == '\n' || cs[j] == '\r') {
-- this.addStop(i, j);
-- i = j;
-- continue;
-- }
-- }
-- this.addStop(i, cs.length - 1);
-- break;
-- case '\n':
-- case '\r':
-- case '.':
-- case ',':
-- case ';':
-- case '(':
-- case ')':
-- case '{':
-- case '}':
-- case '[':
-- case ']':
-- // Treat various punctuation as delimiters
-- this.addStart(i, new String(new char[] { cs[i] }));
-- this.addStop(i, i);
-- break;
-- }
-- }
-- }
--
-- public void addStart(int index, String delim) {
-- this.starts.add(new Pair<>(index, delim));
-- }
--
-- public void addStop(int start, int stop) {
-- this.stops.put(start, stop);
-- }
--
-- public Pair<Integer, String> findBefore(int index) {
-- Pair<Integer, String> found = null;
-- for (Pair<Integer, String> pair : this.starts) {
-- if (pair.getLeft() < index)
-- found = pair;
-- if (pair.getLeft() >= index)
-- break;
-- }
-- return found;
-- }
--
-- public Pair<Integer, String> findAfter(int index) {
-- for (Pair<Integer, String> pair : this.starts) {
-- if (pair.getLeft() > index)
-- return pair;
-- }
-- return null;
-- }
--
-- public boolean isInsideLiteral(int start, int stop) {
-- Pair<Integer, String> pair = this.findBefore(start);
-- if (pair == null)
-- return false;
-- if (pair.getRight().equals("\"")) {
-- Integer nearestStop = this.stops.get(pair.getLeft());
-- if (nearestStop == null)
-- return true; // Inside unterminated literal
-- return (nearestStop > stop); // May be inside a literal
-- } else {
-- // Not inside a literal
-- return false;
-- }
-- }
--
-- public boolean isInsideAltLiteral(int start, int stop) {
-- Pair<Integer, String> pair = this.findBefore(start);
-- if (pair == null)
-- return false;
-- if (pair.getRight().equals("'")) {
-- Integer nearestStop = this.stops.get(pair.getLeft());
-- if (nearestStop == null)
-- return true; // Inside unterminated literal
-- return (nearestStop > stop); // May be inside a literal
-- } else {
-- // Not inside a literal
-- return false;
-- }
-- }
--
-- public boolean isBetweenLiterals(int start, int stop) {
-- Pair<Integer, String> pairBefore = this.findBefore(start);
-- if (pairBefore == null)
-- return false;
-- if (pairBefore.getRight().equals("\"")) {
-- Integer stopBefore = this.stops.get(pairBefore.getLeft());
-- if (stopBefore == null)
-- return false; // Inside unterminated literal
--
-- // We occur after a literal, is there a subsequent literal?
-- Pair<Integer, String> pairAfter = this.findAfter(stop);
-- return pairAfter != null && pairAfter.getRight().equals("\"");
-- } else {
-- // Previous deliminator is not that of a literal
-- return false;
-- }
-- }
--
-- }
--}
++/**
++ * 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.query;
++
++import java.net.URL;
++import java.util.ArrayList;
++import java.util.Calendar;
++import java.util.Collections;
++import java.util.HashMap;
++import java.util.Iterator;
++import java.util.List;
++import java.util.Map;
++import java.util.Map.Entry;
++import java.util.regex.MatchResult;
++import java.util.regex.Matcher;
++import java.util.regex.Pattern;
++
++import org.apache.jena.atlas.lib.Pair;
++import org.apache.jena.datatypes.RDFDatatype ;
++import org.apache.jena.graph.Node ;
++import org.apache.jena.graph.NodeFactory ;
++import org.apache.jena.iri.IRI;
++import org.apache.jena.rdf.model.Literal ;
++import org.apache.jena.rdf.model.Model ;
++import org.apache.jena.rdf.model.ModelFactory ;
++import org.apache.jena.rdf.model.RDFNode ;
++import org.apache.jena.shared.PrefixMapping ;
++import org.apache.jena.shared.impl.PrefixMappingImpl ;
++import org.apache.jena.sparql.ARQException ;
++import org.apache.jena.sparql.serializer.SerializationContext ;
++import org.apache.jena.sparql.util.FmtUtils ;
++import org.apache.jena.sparql.util.NodeFactoryExtra ;
++import org.apache.jena.update.UpdateFactory ;
++import org.apache.jena.update.UpdateRequest ;
++
++/**
++ * <p>
++ * A Parameterized SPARQL String is a SPARQL query/update into which values may
++ * be injected.
++ * </p>
++ * <h3>Injecting Values</h3>
++ * <p>
++ * Values may be injected in several ways:
++ * </p>
++ * <ul>
++ * <li>By treating a variable in the SPARQL string as a parameter</li>
++ * <li>Using JDBC style positional parameters</li>
++ * <li>Appending values directly to the command text being built</li>
++ * </ul>
++ * <h4>Variable Parameters</h3>
++ * <p>
++ * Any variable in the command may have a value injected to it, injecting a
++ * value replaces all usages of that variable in the command i.e. substitutes
++ * the variable for a constant, injection is done by textual substitution.
++ * </p> <h4>Positional Parameters</h4>
++ * <p>
++ * You can use JDBC style positional parameters if you prefer, a JDBC style
++ * parameter is a single {@code ?} followed by whitespace or certain punctuation
++ * characters (currently {@code ; , .}). Positional parameters have a unique
++ * index which reflects the order in which they appear in the string. Positional
++ * parameters use a zero based index.
++ * </p>
++ * <h4>Buffer Usage</h3> </p> Additionally you may use this purely as a
++ * {@link StringBuffer} replacement for creating queries since it provides a
++ * large variety of convenience methods for appending things either as-is or as
++ * nodes (which causes appropriate formatting to be applied). </p>
++ * <h3>Intended Usage</h3>
++ * <p>
++ * The intended usage of this is where using a {@link QuerySolutionMap} as
++ * initial bindings is either inappropriate or not possible e.g.
++ * </p>
++ * <ul>
++ * <li>Generating query/update strings in code without lots of error prone and
++ * messy string concatenation</li>
++ * <li>Preparing a query/update for remote execution</li>
++ * <li>Where you do not want to simply say some variable should have a certain
++ * value but rather wish to insert constants into the query/update in place of
++ * variables</li>
++ * <li>Defending against SPARQL injection when creating a query/update using
++ * some external input, see SPARQL Injection notes for limitations.</li>
++ * <li>Provide a more convenient way to prepend common prefixes to your query</li>
++ * </ul>
++ * <p>
++ * This class is useful for preparing both queries and updates hence the generic
++ * name as it provides programmatic ways to replace variables in the query with
++ * constants and to add prefix and base declarations. A {@link Query} or
++ * {@link UpdateRequest} can be created using the {@link #asQuery()} and
++ * {@link #asUpdate()} methods assuming the command an instance represents is
++ * actually valid as a query/update.
++ * </p>
++ * <h3>Warnings</h3>
++ * <ol>
++ * <li>Note that this class does not in any way check that your command is
++ * syntactically correct until such time as you try and parse it as a
++ * {@link Query} or {@link UpdateRequest}.</li>
++ * <li>Also note that injection is done purely based on textual replacement, it
++ * does not understand or respect variable scope in any way. For example if your
++ * command text contains sub queries you should ensure that variables within the
++ * sub query which you don't want replaced have distinct names from those in the
++ * outer query you do want replaced (or vice versa)</li>
++ * </ol>
++ * <h3>SPARQL Injection Notes</h3>
++ * <p>
++ * While this class was in part designed to prevent SPARQL injection it is by no
++ * means foolproof because it works purely at the textual level. The current
++ * version of the code addresses some possible attack vectors that the
++ * developers have identified but we do not claim to be sufficiently devious to
++ * have thought of and prevented every possible attack vector.
++ * </p>
++ * <p>
++ * Therefore we <strong>strongly</strong> recommend that users concerned about
++ * SPARQL Injection attacks perform their own validation on provided parameters
++ * and test their use of this class themselves prior to its use in any security
++ * conscious deployment. We also recommend that users do not use easily
++ * guess-able variable names for their parameters as these can allow a chained
++ * injection attack though generally speaking the code should prevent these.
++ * </p>
++ */
++public class ParameterizedSparqlString implements PrefixMapping {
++
++ private Model model = ModelFactory.createDefaultModel();
++
++ private StringBuilder cmd = new StringBuilder();
++ private String baseUri;
++ private Map<String, Node> params = new HashMap<>();
++ private Map<Integer, Node> positionalParams = new HashMap<>();
++ private PrefixMapping prefixes;
++
++ /**
++ * Creates a new parameterized string
++ *
++ * @param command
++ * Raw Command Text
++ * @param map
++ * Initial Parameters to inject
++ * @param base
++ * Base URI
++ * @param prefixes
++ * Prefix Mapping
++ */
++ public ParameterizedSparqlString(String command, QuerySolutionMap map, String base, PrefixMapping prefixes) {
++ if (command != null)
++ this.cmd.append(command);
++ this.setParams(map);
++ this.baseUri = (base != null && !base.equals("") ? base : null);
++ this.prefixes = new PrefixMappingImpl();
++ if (prefixes != null)
++ this.prefixes.setNsPrefixes(prefixes);
++ }
++
++ /**
++ * Creates a new parameterized string
++ *
++ * @param command
++ * Raw Command Text
++ * @param map
++ * Initial Parameters to inject
++ * @param base
++ * Base URI
++ */
++ public ParameterizedSparqlString(String command, QuerySolutionMap map, String base) {
++ this(command, map, base, null);
++ }
++
++ /**
++ * Creates a new parameterized string
++ *
++ * @param command
++ * Raw Command Text
++ * @param map
++ * Initial Parameters to inject
++ * @param prefixes
++ * Prefix Mapping
++ */
++ public ParameterizedSparqlString(String command, QuerySolutionMap map, PrefixMapping prefixes) {
++ this(command, map, null, prefixes);
++ }
++
++ /**
++ * Creates a new parameterized string
++ *
++ * @param command
++ * Raw Command Text
++ * @param map
++ * Initial Parameters to inject
++ */
++ public ParameterizedSparqlString(String command, QuerySolutionMap map) {
++ this(command, map, null, null);
++ }
++
++ /**
++ * Creates a new parameterized string
++ *
++ * @param command
++ * Raw Command Text
++ * @param base
++ * Base URI
++ * @param prefixes
++ * Prefix Mapping
++ */
++ public ParameterizedSparqlString(String command, String base, PrefixMapping prefixes) {
++ this(command, null, base, prefixes);
++ }
++
++ /**
++ * Creates a new parameterized string
++ *
++ * @param command
++ * Raw Command Text
++ * @param prefixes
++ * Prefix Mapping
++ */
++ public ParameterizedSparqlString(String command, PrefixMapping prefixes) {
++ this(command, null, null, prefixes);
++ }
++
++ /**
++ * Creates a new parameterized string
++ *
++ * @param command
++ * Raw Command Text
++ * @param base
++ * Base URI
++ */
++ public ParameterizedSparqlString(String command, String base) {
++ this(command, null, base, null);
++ }
++
++ /**
++ * Creates a new parameterized string
++ *
++ * @param command
++ * Raw Command Text
++ */
++ public ParameterizedSparqlString(String command) {
++ this(command, null, null, null);
++ }
++
++ /**
++ * Creates a new parameterized string
++ *
++ * @param map
++ * Initial Parameters to inject
++ * @param prefixes
++ * Prefix Mapping
++ */
++ public ParameterizedSparqlString(QuerySolutionMap map, PrefixMapping prefixes) {
++ this(null, map, null, prefixes);
++ }
++
++ /**
++ * Creates a new parameterized string
++ *
++ * @param map
++ * Initial Parameters to inject
++ */
++ public ParameterizedSparqlString(QuerySolutionMap map) {
++ this(null, map, null, null);
++ }
++
++ /**
++ * Creates a new parameterized string
++ *
++ * @param prefixes
++ * Prefix Mapping
++ */
++ public ParameterizedSparqlString(PrefixMapping prefixes) {
++ this(null, null, null, prefixes);
++ }
++
++ /**
++ * Creates a new parameterized string with an empty command text
++ */
++ public ParameterizedSparqlString() {
++ this("", null, null, null);
++ }
++
++ /**
++ * Sets the command text, overwriting any existing command text. If you want
++ * to append to the command text use one of the {@link #append(String)},
++ * {@link #appendIri(String)}, {@link #appendLiteral(String)} or
++ * {@link #appendNode(Node)} methods instead
++ *
++ * @param command
++ * Command Text
++ */
++ public void setCommandText(String command) {
++ this.cmd = new StringBuilder();
++ this.cmd.append(command);
++ }
++
++ /**
++ * Appends some text as-is to the existing command text, to ensure correct
++ * formatting when used as a constant consider using the
++ * {@link #appendLiteral(String)} or {@link #appendIri(String)} method as
++ * appropriate
++ *
++ * @param text
++ * Text to append
++ */
++ public void append(String text) {
++ this.cmd.append(text);
++ }
++
++ /**
++ * Appends a character as-is to the existing command text, to ensure correct
++ * formatting when used as a constant consider using one of the
++ * {@code appendLiteral()} methods
++ *
++ * @param c
++ * Character to append
++ */
++ public void append(char c) {
++ this.cmd.append(c);
++ }
++
++ /**
++ * Appends a boolean as-is to the existing command text, to ensure correct
++ * formatting when used as a constant consider using the
++ * {@link #appendLiteral(boolean)} method
++ *
++ * @param b
++ * Boolean to append
++ */
++ public void append(boolean b) {
++ this.cmd.append(b);
++ }
++
++ /**
++ * Appends a double as-is to the existing command text, to ensure correct
++ * formatting when used as a constant consider using the
++ * {@link #appendLiteral(double)} method
++ *
++ * @param d
++ * Double to append
++ */
++ public void append(double d) {
++ this.cmd.append(d);
++ }
++
++ /**
++ * Appends a float as-is to the existing command text, to ensure correct
++ * formatting when used as a constant consider using the
++ * {@link #appendLiteral(float)} method
++ *
++ * @param f
++ * Float to append
++ */
++ public void append(float f) {
++ this.cmd.append(f);
++ }
++
++ /**
++ * Appends an integer as-is to the existing command text, to ensure correct
++ * formatting when used as a constant consider using the
++ * {@link #appendLiteral(int)} method
++ *
++ * @param i
++ * Integer to append
++ */
++ public void append(int i) {
++ this.cmd.append(i);
++ }
++
++ /**
++ * Appends a long as-is to the existing command text, to ensure correct
++ * formatting when used as a constant consider using the
++ * {@link #appendLiteral(long)} method
++ *
++ * @param l
++ * Long to append
++ */
++ public void append(long l) {
++ this.cmd.append(l);
++ }
++
++ /**
++ * Appends an object as-is to the existing command text, to ensure correct
++ * formatting when used as a constant consider converting into a more
++ * specific type and using the appropriate {@code appendLiteral()},
++ * {@code appendIri()} or {@code appendNode} methods
++ *
++ * @param obj
++ * Object to append
++ */
++ public void append(Object obj) {
++ this.cmd.append(obj);
++ }
++
++ /**
++ * Appends a Node to the command text as a constant using appropriate
++ * formatting
++ *
++ * @param n
++ * Node to append
++ */
++ public void appendNode(Node n) {
++ SerializationContext context = new SerializationContext(this.prefixes);
++ context.setBaseIRI(this.baseUri);
++ this.cmd.append(this.stringForNode(n, context));
++ }
++
++ /**
++ * Appends a Node to the command text as a constant using appropriate
++ * formatting
++ *
++ * @param n
++ * Node to append
++ */
++ public void appendNode(RDFNode n) {
++ this.appendNode(n.asNode());
++ }
++
++ /**
++ * Appends a URI to the command text as a constant using appropriate
++ * formatting
++ *
++ * @param uri
++ * URI to append
++ */
++ public void appendIri(String uri) {
++ this.appendNode(NodeFactory.createURI(uri));
++ }
++
++ /**
++ * Appends an IRI to the command text as a constant using appropriate
++ * formatting
++ *
++ * @param iri
++ * IRI to append
++ */
++ public void appendIri(IRI iri) {
++ this.appendNode(NodeFactory.createURI(iri.toString()));
++ }
++
++ /**
++ * Appends a simple literal as a constant using appropriate formatting
++ *
++ * @param value
++ * Lexical Value
++ */
++ public void appendLiteral(String value) {
++ this.appendNode(NodeFactoryExtra.createLiteralNode(value, null, null));
++ }
++
++ /**
++ * Appends a literal with a lexical value and language to the command text
++ * as a constant using appropriate formatting
++ *
++ * @param value
++ * Lexical Value
++ * @param lang
++ * Language
++ */
++ public void appendLiteral(String value, String lang) {
++ this.appendNode(NodeFactoryExtra.createLiteralNode(value, lang, null));
++ }
++
++ /**
++ * Appends a Typed Literal to the command text as a constant using
++ * appropriate formatting
++ *
++ * @param value
++ * Lexical Value
++ * @param datatype
++ * Datatype
++ */
++ public void appendLiteral(String value, RDFDatatype datatype) {
++ this.appendNode(NodeFactoryExtra.createLiteralNode(value, null, datatype.getURI()));
++ }
++
++ /**
++ * Appends a boolean to the command text as a constant using appropriate
++ * formatting
++ *
++ * @param b
++ * Boolean to append
++ */
++ public void appendLiteral(boolean b) {
++ this.appendNode(this.model.createTypedLiteral(b));
++ }
++
++ /**
++ * Appends an integer to the command text as a constant using appropriate
++ * formatting
++ *
++ * @param i
++ * Integer to append
++ */
++ public void appendLiteral(int i) {
++ this.appendNode(NodeFactoryExtra.intToNode(i));
++ }
++
++ /**
++ * Appends a long to the command text as a constant using appropriate
++ * formatting
++ *
++ * @param l
++ * Long to append
++ */
++ public void appendLiteral(long l) {
++ this.appendNode(NodeFactoryExtra.intToNode(l));
++ }
++
++ /**
++ * Appends a float to the command text as a constant using appropriate
++ * formatting
++ *
++ * @param f
++ * Float to append
++ */
++ public void appendLiteral(float f) {
++ this.appendNode(this.model.createTypedLiteral(f));
++ }
++
++ /**
++ * Appends a double to the command text as a constant using appropriate
++ * formatting
++ *
++ * @param d
++ * Double to append
++ */
++ public void appendLiteral(double d) {
++ this.appendNode(this.model.createTypedLiteral(d));
++ }
++
++ /**
++ * Appends a date time to the command text as a constant using appropriate
++ * formatting
++ *
++ * @param dt
++ * Date Time to append
++ */
++ public void appendLiteral(Calendar dt) {
++ this.appendNode(this.model.createTypedLiteral(dt));
++ }
++
++ /**
++ * Gets the basic Command Text
++ * <p>
++ * <strong>Note:</strong> This will not reflect any injected parameters, to
++ * see the command with injected parameters invoke the {@link #toString()}
++ * method
++ * </p>
++ *
++ * @return Command Text
++ */
++ public String getCommandText() {
++ return this.cmd.toString();
++ }
++
++ /**
++ * Sets the Base URI which will be prepended to the query/update
++ *
++ * @param base
++ * Base URI
++ */
++ public void setBaseUri(String base) {
++ this.baseUri = base;
++ }
++
++ /**
++ * Gets the Base URI which will be prepended to a query
++ *
++ * @return Base URI
++ */
++ public String getBaseUri() {
++ return this.baseUri;
++ }
++
++ /**
++ * Helper method which does the validation of the parameters
++ *
++ * @param n
++ * Node
++ */
++ protected void validateParameterValue(Node n) {
++ if (n.isURI()) {
++ if (n.getURI().contains(">"))
++ throw new ARQException("Value for the parameter contains a SPARQL injection risk");
++ }
++ }
++
++ /**
++ * Sets the Parameters
++ *
++ * @param map
++ * Parameters
++ */
++ public void setParams(QuerySolutionMap map) {
++ if (map != null) {
++ Iterator<String> iter = map.varNames();
++ while (iter.hasNext()) {
++ String var = iter.next();
++ this.setParam(var, map.get(var).asNode());
++ }
++ }
++ }
++
++ /**
++ * Sets a Positional Parameter
++ * <p>
++ * Setting a parameter to null is equivalent to calling
++ * {@link #clearParam(int)} for the given variable
++ * </p>
++ *
++ * @param index
++ * Positional Index
++ * @param n
++ * Node
++ */
++ public void setParam(int index, Node n) {
++ if (index < 0)
++ throw new IndexOutOfBoundsException();
++ if (n != null) {
++ this.validateParameterValue(n);
++ this.positionalParams.put(index, n);
++ } else {
++ this.positionalParams.remove(index);
++ }
++ }
++
++ /**
++ * Sets a variable parameter
++ * <p>
++ * Setting a parameter to null is equivalent to calling
++ * {@link #clearParam(String)} for the given variable
++ * </p>
++ *
++ * @param var
++ * Variable
++ * @param n
++ * Value
++ *
++ */
++ public void setParam(String var, Node n) {
++ if (var == null)
++ throw new IllegalArgumentException("var cannot be null");
++ if (var.startsWith("?") || var.startsWith("$"))
++ var = var.substring(1);
++ if (n != null) {
++ this.validateParameterValue(n);
++ this.params.put(var, n);
++ } else {
++ this.params.remove(var);
++ }
++ }
++
++ /**
++ * Sets a positional parameter
++ * <p>
++ * Setting a parameter to null is equivalent to calling
++ * {@link #clearParam(String)} for the given variable
++ * </p>
++ *
++ * @param index
++ * Positional Index
++ * @param n
++ * Node
++ */
++ public void setParam(int index, RDFNode n) {
++ this.setParam(index, n.asNode());
++ }
++
++ /**
++ * Sets a variable parameter
++ * <p>
++ * Setting a parameter to null is equivalent to calling
++ * {@link #clearParam(String)} for the given variable
++ * </p>
++ *
++ * @param var
++ * Variable
++ * @param n
++ * Value
++ */
++ public void setParam(String var, RDFNode n) {
++ this.setParam(var, n.asNode());
++ }
++
++ /**
++ * Sets a positional parameter to an IRI
++ * <p>
++ * Setting a parameter to null is equivalent to calling
++ * {@link #clearParam(int)} for the given index
++ * </p>
++ *
++ * @param index
++ * Positional Index
++ * @param iri
++ * IRI
++ */
++ public void setIri(int index, String iri) {
++ this.setParam(index, NodeFactory.createURI(iri));
++ }
++
++ /**
++ * Sets a variable parameter to an IRI
++ * <p>
++ * Setting a parameter to null is equivalent to calling
++ * {@link #clearParam(String)} for the given variable
++ * </p>
++ *
++ * @param var
++ * Variable
++ * @param iri
++ * IRI
++ */
++ public void setIri(String var, String iri) {
++ this.setParam(var, NodeFactory.createURI(iri));
++ }
++
++ /**
++ * Sets a positional parameter to an IRI
++ * <p>
++ * Setting a parameter to null is equivalent to calling
++ * {@link #clearParam(int)} for the given index
++ * </p>
++ *
++ * @param index
++ * Positional Index
++ * @param iri
++ * IRI
++ */
++ public void setIri(int index, IRI iri) {
++ this.setIri(index, iri.toString());
++ }
++
++ /**
++ * Sets a variable parameter to an IRI
++ * <p>
++ * Setting a parameter to null is equivalent to calling
++ * {@link #clearParam(String)} for the given variable
++ * </p>
++ *
++ * @param var
++ * Variable
++ * @param iri
++ * IRI
++ */
++ public void setIri(String var, IRI iri) {
++ this.setIri(var, iri.toString());
++ }
++
++ /**
++ * Sets a positional parameter to an IRI
++ * <p>
++ * Setting a parameter to null is equivalent to calling
++ * {@link #clearParam(int)} for the given index
++ * </p>
++ *
++ * @param index
++ * Positional Index
++ * @param url
++ * URL
++ */
++ public void setIri(int index, URL url) {
++ this.setIri(index, url.toString());
++ }
++
++ /**
++ * Sets a variable parameter to an IRI
++ * <p>
++ * Setting a parameter to null is equivalent to calling
++ * {@link #clearParam(String)} for the given variable
++ * </p>
++ *
++ * @param var
++ * Variable
++ * @param url
++ * URL used as IRI
++ *
++ */
++ public void setIri(String var, URL url) {
++ this.setIri(var, url.toString());
++ }
++
++ /**
++ * Sets a positional parameter to a Literal
++ * <p>
++ * Setting a parameter to null is equivalent to calling
++ * {@link #clearParam(int)} for the given index
++ * </p>
++ *
++ * @param index
++ * Positional Index
++ * @param lit
++ * Value
++ *
++ */
++ public void setLiteral(int index, Literal lit) {
++ this.setParam(index, lit.asNode());
++ }
++
++ /**
++ * Sets a variable parameter to a Literal
++ * <p>
++ * Setting a parameter to null is equivalent to calling
++ * {@link #clearParam(String)} for the given variable
++ * </p>
++ *
++ * @param var
++ * Variable
++ * @param lit
++ * Value
++ *
++ */
++ public void setLiteral(String var, Literal lit) {
++ this.setParam(var, lit.asNode());
++ }
++
++ /**
++ * Sets a positional parameter to a literal
++ * <p>
++ * Setting a parameter to null is equivalent to calling
++ * {@link #clearParam(int)} for the given index
++ * </p>
++ *
++ * @param index
++ * Positional Index
++ * @param value
++ * Lexical Value
++ *
++ */
++ public void setLiteral(int index, String value) {
++ this.setParam(index, NodeFactoryExtra.createLiteralNode(value, null, null));
++ }
++
++ /**
++ * Sets a variable parameter to a literal
++ * <p>
++ * Setting a parameter to null is equivalent to calling
++ * {@link #clearParam(String)} for the given variable
++ * </p>
++ *
++ * @param var
++ * Variable
++ * @param value
++ * Lexical Value
++ *
++ */
++ public void setLiteral(String var, String value) {
++ this.setParam(var, NodeFactoryExtra.createLiteralNode(value, null, null));
++ }
++
++ /**
++ * Sets a positional parameter to a literal with a language
++ * <p>
++ * Setting a parameter to null is equivalent to calling
++ * {@link #clearParam(int)} for the given index
++ * </p>
++ *
++ * @param index
++ * Positional index
++ * @param value
++ * Lexical Value
++ * @param lang
++ * Language
++ *
++ */
++ public void setLiteral(int index, String value, String lang) {
++ this.setParam(index, NodeFactoryExtra.createLiteralNode(value, lang, null));
++ }
++
++ /**
++ * Sets a variable parameter to a literal with a language
++ * <p>
++ * Setting a parameter to null is equivalent to calling
++ * {@link #clearParam(String)} for the given variable
++ * </p>
++ *
++ * @param var
++ * Variable
++ * @param value
++ * Lexical Value
++ * @param lang
++ * Language
++ *
++ */
++ public void setLiteral(String var, String value, String lang) {
++ this.setParam(var, NodeFactoryExtra.createLiteralNode(value, lang, null));
++ }
++
++ /**
++ * Sets a positional arameter to a typed literal
++ * <p>
++ * Setting a parameter to null is equivalent to calling
++ * {@link #clearParam(int)} for the given index
++ * </p>
++ *
++ * @param index
++ * Positional Index
++ * @param value
++ * Lexical Value
++ * @param datatype
++ * Datatype
++ *
++ */
++ public void setLiteral(int index, String value, RDFDatatype datatype) {
++ this.setParam(index, this.model.createTypedLiteral(value, datatype));
++ }
++
++ /**
++ * Sets a variable parameter to a typed literal
++ * <p>
++ * Setting a parameter to null is equivalent to calling
++ * {@link #clearParam(String)} for the given variable
++ * </p>
++ *
++ * @param var
++ * Variable
++ * @param value
++ * Lexical Value
++ * @param datatype
++ * Datatype
++ *
++ */
++ public void setLiteral(String var, String value, RDFDatatype datatype) {
++ this.setParam(var, this.model.createTypedLiteral(value, datatype));
++ }
++
++ /**
++ * Sets a positional parameter to a boolean literal
++ *
++ * @param index
++ * Positional Index
++ * @param value
++ * boolean
++ */
++ public void setLiteral(int index, boolean value) {
++ this.setParam(index, this.model.createTypedLiteral(value));
++ }
++
++ /**
++ * Sets a variable parameter to a boolean literal
++ *
++ * @param var
++ * Variable
++ * @param value
++ * boolean
++ */
++ public void setLiteral(String var, boolean value) {
++ this.setParam(var, this.model.createTypedLiteral(value));
++ }
++
++ /**
++ * Sets a positional parameter to an integer literal
++ *
++ * @param index
++ * Positional Index
++ * @param i
++ * Integer Value
++ */
++ public void setLiteral(int index, int i) {
++ this.setParam(index, NodeFactoryExtra.intToNode(i));
++ }
++
++ /**
++ * Sets a variable parameter to an integer literal
++ *
++ * @param var
++ * Variable
++ * @param i
++ * Integer Value
++ */
++ public void setLiteral(String var, int i) {
++ this.setParam(var, NodeFactoryExtra.intToNode(i));
++ }
++
++ /
<TRUNCATED>