/* * 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; import java.util.Iterator ; import javax.servlet.http.HttpServletRequest ; import org.apache.jena.atlas.web.ContentType ; import org.apache.jena.ext.com.google.common.collect.ArrayListMultimap; import org.apache.jena.ext.com.google.common.collect.Multimap; import org.apache.jena.fuseki.server.SystemState ; import org.apache.jena.fuseki.servlets.HttpAction ; import org.apache.jena.graph.Graph ; import org.apache.jena.graph.Node ; import org.apache.jena.graph.Triple ; import org.apache.jena.query.* ; import org.apache.jena.rdf.model.Literal ; import org.apache.jena.rdf.model.Model ; import org.apache.jena.rdf.model.RDFNode ; import org.apache.jena.rdf.model.Resource ; import org.apache.jena.riot.Lang ; import org.apache.jena.riot.RDFLanguages ; import org.apache.jena.shared.PrefixMapping ; import org.apache.jena.sparql.core.DatasetGraph ; import org.apache.jena.sparql.core.Quad ; import org.apache.jena.sparql.util.Convert ; import org.apache.jena.vocabulary.RDFS ; public class FusekiLib { // ==> ActionLib /** Get the content type of an action or return the default. * @param action * @return ContentType */ public static ContentType getContentType(HttpAction action) { return getContentType(action.request) ; } /** Get the content type of an action or return the default. * @param request * @return ContentType */ public static ContentType getContentType(HttpServletRequest request) { String contentTypeHeader = request.getContentType() ; if ( contentTypeHeader == null ) return null ; return ContentType.create(contentTypeHeader) ; } /** Get the incoming Lang based on Content-Type of an action. * @param action * @param dft Default if no "Content-Type:" found. * @return ContentType */ public static Lang getLangFromAction(HttpAction action, Lang dft) { String contentTypeHeader = action.request.getContentType() ; if ( contentTypeHeader == null ) return dft ; return RDFLanguages.contentTypeToLang(contentTypeHeader) ; } static String fmtRequest(HttpServletRequest request) { StringBuffer sbuff = new StringBuffer() ; sbuff.append(request.getMethod()) ; sbuff.append(" ") ; sbuff.append(Convert.decWWWForm(request.getRequestURL())) ; String qs = request.getQueryString() ; if ( qs != null ) { String tmp = request.getQueryString() ; tmp = Convert.decWWWForm(tmp) ; tmp = tmp.replace('\n', ' ') ; tmp = tmp.replace('\r', ' ') ; sbuff.append("?").append(tmp) ; } return sbuff.toString() ; } /** Parse the query string - do not process the body even for a form */ public static Multimap<String, String> parseQueryString(HttpServletRequest req) { Multimap<String, String> map = ArrayListMultimap.create() ; // Don't use ServletRequest.getParameter or getParamterNames // as that reads form data. This code parses just the query string. if ( req.getQueryString() != null ) { String[] params = req.getQueryString().split("&") ; for (int i = 0; i < params.length; i++) { String p = params[i] ; String[] x = p.split("=", 2) ; String name = null ; String value = null ; if ( x.length == 0 ) { // No "=" name = p ; value = "" ; } else if ( x.length == 1 ) { // param= name = x[0] ; value = "" ; } else { // param=value name = x[0] ; value = x[1] ; } map.put(name, value) ; } } return map ; } public static String safeParameter(HttpServletRequest request, String pName) { String value = request.getParameter(pName) ; value = value.replace("\r", "") ; value = value.replace("\n", "") ; return value ; } // Do the addition directly on the dataset public static void addDataInto(Graph data, DatasetGraph dsg, Node graphName) { // Prefixes? if ( graphName == null ) graphName = Quad.defaultGraphNodeGenerated ; Iterator<Triple> iter = data.find(Node.ANY, Node.ANY, Node.ANY) ; for (; iter.hasNext();) { Triple t = iter.next() ; dsg.add(graphName, t.getSubject(), t.getPredicate(), t.getObject()) ; } PrefixMapping pmapSrc = data.getPrefixMapping() ; PrefixMapping pmapDest = dsg.getDefaultGraph().getPrefixMapping() ; pmapDest.setNsPrefixes(pmapSrc) ; } public static void addDataInto(DatasetGraph src, DatasetGraph dest) { Iterator<Quad> iter = src.find(Node.ANY, Node.ANY, Node.ANY, Node.ANY) ; for (; iter.hasNext();) { Quad q = iter.next() ; dest.add(q) ; } PrefixMapping pmapSrc = src.getDefaultGraph().getPrefixMapping() ; PrefixMapping pmapDest = dest.getDefaultGraph().getPrefixMapping() ; pmapDest.withDefaultMappings(pmapSrc) ; } // ---- Helper code public static ResultSet query(String string, Model m) { return query(string, m, null, null) ; } public static ResultSet query(String string, Dataset ds) { return query(string, ds, null, null) ; } public static ResultSet query(String string, Model m, String varName, RDFNode value) { Query query = QueryFactory.create(SystemState.PREFIXES + string) ; QuerySolutionMap initValues = null ; if ( varName != null ) initValues = querySolution(varName, value) ; try ( QueryExecution qExec = QueryExecutionFactory.create(query, m, initValues) ) { return ResultSetFactory.copyResults(qExec.execSelect()) ; } } public static ResultSet query(String string, Dataset ds, String varName, RDFNode value) { Query query = QueryFactory.create(SystemState.PREFIXES + string) ; QuerySolutionMap initValues = null ; if ( varName != null ) initValues = querySolution(varName, value) ; try ( QueryExecution qExec = QueryExecutionFactory.create(query, ds, initValues) ) { return ResultSetFactory.copyResults(qExec.execSelect()) ; } } private static QuerySolutionMap querySolution(String varName, RDFNode value) { QuerySolutionMap qsm = new QuerySolutionMap() ; querySolution(qsm, varName, value) ; return qsm ; } public static QuerySolutionMap querySolution(QuerySolutionMap qsm, String varName, RDFNode value) { qsm.add(varName, value) ; return qsm ; } public static RDFNode getOne(Resource svc, String property) { ResultSet rs = FusekiLib.query("SELECT * { ?svc " + property + " ?x}", svc.getModel(), "svc", svc) ; if ( !rs.hasNext() ) throw new FusekiConfigException("No property '" + property + "' for service " + FusekiLib.nodeLabel(svc)) ; RDFNode x = rs.next().get("x") ; if ( rs.hasNext() ) throw new FusekiConfigException("Multiple properties '" + property + "' for service " + FusekiLib.nodeLabel(svc)) ; return x ; } // Node presentation public static String nodeLabel(RDFNode n) { if ( n == null ) return "<null>" ; if ( n instanceof Resource ) return strForResource((Resource)n) ; Literal lit = (Literal)n ; return lit.getLexicalForm() ; } // XXX Lib public static String strForResource(Resource r) { return strForResource(r, r.getModel()) ; } // XXX Lib public static String strForResource(Resource r, PrefixMapping pm) { if ( r == null ) return "NULL " ; if ( r.hasProperty(RDFS.label) ) { RDFNode n = r.getProperty(RDFS.label).getObject() ; if ( n instanceof Literal ) return ((Literal)n).getString() ; } if ( r.isAnon() ) return "<<blank node>>" ; if ( pm == null ) pm = r.getModel() ; return strForURI(r.getURI(), pm) ; } public static String strForURI(String uri, PrefixMapping pm) { if ( pm != null ) { String x = pm.shortForm(uri) ; if ( !x.equals(uri) ) return x ; } return "<" + uri + ">" ; } }