You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by rv...@apache.org on 2014/10/22 13:40:01 UTC
[46/68] [abbrv] [partial] reverting accidentally deleted files
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/soh
----------------------------------------------------------------------
diff --git a/jena-fuseki/soh b/jena-fuseki/soh
new file mode 100755
index 0000000..4f6590d
--- /dev/null
+++ b/jena-fuseki/soh
@@ -0,0 +1,713 @@
+#!/usr/bin/env ruby
+# -*- coding: utf-8 -*-
+
+# 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.
+
+# SPARQL HTTP Update, client.
+
+require 'optparse'
+require 'net/http'
+require 'uri'
+require 'cgi'
+require 'pp'
+require 'ostruct'
+
+# ToDo
+# Allow a choice of media type for GET
+# --accept "content-type" (and abbreviations)
+# --header "Add:this"
+# --user, --password
+# Basic authentication: request.basic_auth("username", "password")
+# Follow redirects => 301: puts response["location"] # All headers are lowercase?
+
+SOH_NAME="SOH"
+SOH_VERSION="0.0.0"
+
+$proxy = ENV['http_proxy'] ? URI.parse(ENV['http_proxy']) : OpenStruct.new
+
+# What about direct naming?
+
+# Names
+$mtTurtle = 'text/turtle;charset=utf-8'
+$mtRDF = 'application/rdf+xml'
+$mtText = 'text/plain'
+$mtNTriples = 'application/n-triples'
+$mtNQuads = 'application/n-quads'
+$mtJSONLD = 'application/ld+json'
+$mtTriG = 'application/trig'
+$mtSparqlResultsX = 'application/sparql-results+xml'
+$mtSparqlResultsJ = 'application/sparql-results+json'
+$mtAppJSON = 'application/json'
+$mtAppXML = 'application/xml'
+$mtSparqlResultsTSV = 'application/sparql-results+tsv'
+$mtSparqlResultsCSV = 'application/sparql-results+csv'
+$mtSparqlUpdate = 'application/sparql-update'
+$mtWWWForm = 'application/x-www-form-urlencoded'
+$mtSparqlQuery = "application/sparql-query" ;
+
+# Global media type table.
+$fileMediaTypes = {}
+$fileMediaTypes['ttl'] = $mtTurtle
+$fileMediaTypes['n3'] = 'text/n3; charset=utf-8'
+$fileMediaTypes['nt'] = $mtText
+$fileMediaTypes['rdf'] = $mtRDF
+$fileMediaTypes['owl'] = $mtRDF
+$fileMediaTypes['nq'] = $mtNQuads
+$fileMediaTypes['trig'] = $mtTriG
+$fileMediaTypes['json-ld'] = $mtJSONLD
+$fileMediaTypes['jsonld'] = $mtJSONLD
+
+# Global charset : no entry means "don't set"
+$charsetUTF8 = 'utf-8'
+$charset = {}
+$charset[$mtTurtle] = 'utf-8'
+$charset[$mtText] = 'ascii'
+$charset[$mtTriG] = 'utf-8'
+$charset[$mtNQuads] = 'utf-8'
+
+# Headers
+
+$hContentType = 'Content-Type'
+# $hContentEncoding = 'Content-Encoding'
+$hContentLength = 'Content-Length'
+# $hContentLocation = 'Content-Location'
+# $hContentRange = 'Content-Range'
+
+$hAccept = 'Accept'
+$hAcceptCharset = 'Accept-Charset'
+$hAcceptEncoding = 'Accept-Encoding'
+$hAcceptRanges = 'Accept-Ranges'
+
+$headers = { "User-Agent" => "#{SOH_NAME}/Fuseki #{SOH_VERSION}"}
+$print_http = false
+
+# Default for GET
+# At least allow anything (and hope!)
+$accept_rdf="#{$mtTurtle} , #{$mtNTriples};q=0.9 , #{$mtRDF};q=0.8 , #{$mtJSONLD};q=0.5"
+# Datasets
+$accept_ds="#{$mtTrig} , #{$mtNQuads};q=0.9 , #{$mtJSONLD};q=0.5"
+# For SPARQL query
+$accept_results="#{$mtSparqlResultsJ} , #{$mtSparqlResultsX};q=0.9 , #{$accept_rdf}"
+
+# Accept any in case of trouble.
+$accept_rdf="#{$accept_rdf} , */*;q=0.1"
+$accept_results="#{$accept_results} , */*;q=0.1"
+
+# The media type usually forces the charset.
+$accept_charset=nil
+
+## Who we are.
+## Two styles:
+## s-query .....
+## soh query .....
+
+$cmd = File.basename($0)
+if $cmd == 'soh'
+then
+ $cmd = (ARGV.size == 0) ? 'soh' : ARGV.shift
+end
+
+if ! $cmd.start_with?('s-') && $cmd != 'soh'
+ $cmd = 's-'+$cmd
+end
+
+## --------
+
+def GET(dataset, graph)
+ print "GET #{dataset} #{graph}\n" if $verbose
+ requestURI = target(dataset, graph)
+ headers = {}
+ headers.merge!($headers)
+ headers[$hAccept] = $accept_rdf
+ headers[$hAcceptCharset] = $accept_charset unless $accept_charset.nil?
+ get_worker(requestURI, headers)
+end
+
+def get_worker(requestURI, headers)
+ uri = URI.parse(requestURI)
+ request = Net::HTTP::Get.new(uri.request_uri)
+ request.initialize_http_header(headers)
+ print_http_request(uri, request)
+ response_print_body(uri, request)
+end
+
+def HEAD(dataset, graph)
+ print "HEAD #{dataset} #{graph}\n" if $verbose
+ requestURI = target(dataset, graph)
+ headers = {}
+ headers.merge!($headers)
+ headers[$hAccept] = $accept_rdf
+ headers[$hAcceptCharset] = $accept_charset unless $accept_charset.nil?
+ uri = URI.parse(requestURI)
+ request = Net::HTTP::Head.new(uri.request_uri)
+ request.initialize_http_header(headers)
+ print_http_request(uri, request)
+ response_no_body(uri, request)
+end
+
+def PUT(dataset, graph, file)
+ print "PUT #{dataset} #{graph} #{file}\n" if $verbose
+ send_body(dataset, graph, file, Net::HTTP::Put)
+end
+
+def POST(dataset, graph, file)
+ print "POST #{dataset} #{graph} #{file}\n" if $verbose
+ send_body(dataset, graph, file, Net::HTTP::Post)
+end
+
+def DELETE(dataset, graph)
+ print "DELETE #{dataset} #{graph}\n" if $verbose
+ requestURI = target(dataset, graph)
+ uri = URI.parse(requestURI)
+ request = Net::HTTP::Delete.new(uri.request_uri)
+ headers = {}
+ headers.merge!($headers)
+ request.initialize_http_header(headers)
+ print_http_request(uri, request)
+ response_no_body(uri, request)
+end
+
+def uri_escape(string)
+ CGI.escape(string)
+end
+
+def target(dataset, graph)
+ return dataset+"?default" if graph == "default"
+ return dataset+"?graph="+uri_escape(graph)
+end
+
+def send_body(dataset, graph, file, method)
+ mt = content_type(file)
+ headers = {}
+ headers.merge!($headers)
+ headers[$hContentType] = mt
+ headers[$hContentLength] = File.size(file).to_s
+ ## p headers
+
+ requestURI = target(dataset, graph)
+ uri = URI.parse(requestURI)
+
+ request = method.new(uri.request_uri)
+ request.initialize_http_header(headers)
+ print_http_request(uri, request)
+ request.body_stream = File.open(file)
+ response_no_body(uri, request)
+end
+
+def response_no_body(uri, request)
+ http = Net::HTTP::Proxy($proxy.host,$proxy.port).new(uri.host, uri.port)
+ http.read_timeout = nil
+ # check we can connect.
+ begin http.start
+ rescue Exception => e
+ # puts e.message
+ #puts e.backtrace.inspect
+ warn_exit "Failed to connect: #{uri.host}:#{uri.port}: #{e.message}", 3
+ end
+ response = http.request(request)
+ print_http_response(response)
+ case response
+ when Net::HTTPSuccess, Net::HTTPRedirection
+ # OK
+ when Net::HTTPNotFound
+ warn_exit "404 Not found: #{uri}", 9
+ #print response.body
+ else
+ warn_exit "#{response.code} #{response.message} #{uri}", 9
+ # Unreachable
+ response.error!
+ end
+ # NO BODY IN RESPONSE
+end
+
+def response_print_body(uri, request)
+ http = Net::HTTP::Proxy($proxy.host,$proxy.port).new(uri.host, uri.port)
+ http.read_timeout = nil
+ # check we can connect.
+ begin http.start
+ rescue => e
+ #puts e.backtrace.inspect
+ #print e.class
+ warn_exit "Failed to connect: #{uri.host}:#{uri.port}: #{e.message}", 3
+ end
+
+ # Add a blank line if headers were output.
+ print "\n" if $http_print ;
+
+ begin
+ response = http.request(request) { |res|
+ print_http_response(res)
+ #puts res.code
+ res.read_body do |segment|
+ print segment
+ end
+ }
+ case response
+ when Net::HTTPSuccess, Net::HTTPRedirection
+ # OK
+ when Net::HTTPNotFound
+ warn_exit "404 Not found: #{uri}", 9
+ #print response.body
+ else
+ warn_exit "#{response.code}: #{uri}", 9
+ # Unreachable
+ response.error!
+ end
+ rescue EOFError => e
+ warn_exit "IO Error: "+e.message, 3
+ end
+end
+
+def print_http_request(uri, request)
+ return unless $print_http
+ #print "Request\n"
+ print request.method," ",uri, "\n"
+ print_headers(" ",request)
+end
+
+def print_http_response(response)
+ return unless $print_http
+ #print "Response\n"
+ print response.code, " ", response.message, "\n"
+ print_headers(" ",response)
+end
+
+def print_headers(marker, headers)
+ headers.each do |k,v|
+ k = k.split('-').map{|w| w.capitalize}.join('-')+':'
+ printf "%s%-20s %s\n",marker,k,v
+ end
+end
+
+def content_type(file)
+ file =~ /\.([^.]*)$/
+ ext = $1
+ mt = $fileMediaTypes[ext]
+ cs = $charset[mt]
+ mt = mt+';charset='+cs if ! cs.nil?
+ return mt
+end
+
+def charset(content_type)
+ return $charset[content_type]
+end
+
+def warn_exit(msg, rc)
+ warn msg
+ exit rc ;
+end
+
+def parseURI(uri_string)
+ begin
+ return URI.parse(uri_string).to_s
+ rescue URI::InvalidURIError => err
+ warn_exit "Bad URI: <#{uri_string}>", 2
+ end
+end
+
+## ---- Command
+
+def cmd_soh(command=nil)
+ ## Command line
+ options = {}
+ optparse = OptionParser.new do |opts|
+ # Set a banner, displayed at the top
+ # of the help screen.
+ case $cmd
+ when "s-http", "sparql-http", "soh"
+ banner="$cmd [get|post|put|delete] datasetURI graph [file]"
+ when "s-get", "s-head", "s-delete"
+ banner="$cmd datasetURI graph"
+ end
+
+ opts.banner = $banner
+ # Define the options, and what they do
+
+ options[:verbose] = false
+ opts.on( '-v', '--verbose', 'Verbose' ) do
+ options[:verbose] = true
+ end
+
+ options[:version] = false
+ opts.on( '--version', 'Print version and exit' ) do
+ print "#{SOH_NAME} #{SOH_VERSION}\n"
+ exit
+ end
+
+ # This displays the help screen, all programs are
+ # assumed to have this option.
+ opts.on( '-h', '--help', 'Display this screen and exit' ) do
+ puts opts
+ exit
+ end
+ end
+
+ begin optparse.parse!
+ rescue OptionParser::InvalidArgument => e
+ warn e
+ exit
+ end
+
+ $verbose = options[:verbose]
+ $print_http = $verbose
+
+ if command.nil?
+ if ARGV.size == 0
+ warn "No command given: expected one of 'get', 'put', 'post', 'delete', 'query' or 'update'"
+ exit 1
+ end
+ cmdPrint=ARGV.shift
+ command=cmdPrint.upcase
+ else
+ cmdPrint=command
+ end
+
+ case command
+ when "HEAD", "GET", "DELETE"
+ requiredFile=false
+ when "PUT", "POST"
+ requiredFile=true
+ when "QUERY"
+ cmd_sparql_query
+ when "UPDATE"
+ cmd_sparql_update
+ else
+ warn_exit "Unknown command: #{command}", 2
+ end
+
+ if requiredFile
+ then
+ if ARGV.size != 3
+ warn_exit "Required: dataset URI, graph URI (or 'default') and file", 1
+ end
+ else
+ if ARGV.size != 2
+ warn_exit "Required: dataset URI and graph URI (or 'default')", 1
+ end
+ end
+
+ dataset=parseURI(ARGV.shift)
+ # Relative URI?
+ graph=parseURI(ARGV.shift)
+ file=""
+ if requiredFile
+ then
+ file = ARGV.shift if requiredFile
+ if ! File.exist?(file)
+ warn_exit "No such file: "+file, 3
+ end
+ if File.directory?(file)
+ warn_exit "File is a directory: "+file, 3
+ end
+ end
+
+ case command
+ when "GET"
+ GET(dataset, graph)
+ when "HEAD"
+ HEAD(dataset, graph)
+ when "PUT"
+ PUT(dataset, graph, file)
+ when "DELETE"
+ DELETE(dataset, graph)
+ when "POST"
+ POST(dataset, graph, file)
+ else
+ warn_exit "Internal error: Unknown command: #{cmd}", 2
+ end
+ exit 0
+end
+
+## --------
+def string_or_file(arg)
+ return arg if ! arg.match(/^@/)
+ a=(arg[1..-1])
+ open(a, 'rb'){|f| f.read}
+end
+
+## -------- SPARQL Query
+
+## Choose method
+def SPARQL_query(service, query, query_file, forcePOST=false, args2={})
+ if ! query_file.nil?
+ query = open(query_file, 'rb'){|f| f.read}
+ end
+ if forcePOST || query.length >= 2*1024
+ SPARQL_query_POST(service, query, args2)
+ else
+ SPARQL_query_GET(service, query, args2)
+ end
+end
+
+## By GET
+
+def SPARQL_query_GET(service, query, args2)
+ args = { "query" => query }
+ args.merge!(args2)
+ qs=args.collect { |k,v| "#{k}=#{uri_escape(v)}" }.join('&')
+ action="#{service}?#{qs}"
+ headers={}
+ headers.merge!($headers)
+ headers[$hAccept]=$accept_results
+ get_worker(action, headers)
+end
+
+## By POST
+
+def SPARQL_query_POST(service, query, args2)
+ # DRY - body/no body for each of request and response.
+ post_params={ "query" => query }
+ post_params.merge!(args2)
+ uri = URI.parse(service)
+ headers={}
+ headers.merge!($headers)
+ headers[$hAccept]=$accept_results
+ execute_post_form_body(uri, headers, post_params)
+end
+
+def execute_post_form_body(uri, headers, post_params)
+ request = Net::HTTP::Post.new(uri.request_uri)
+ qs=post_params.collect { |k,v| "#{k}=#{uri_escape(v)}" }.join('&')
+ headers[$hContentType] = $mtWWWForm
+ headers[$hContentLength] = qs.length.to_s
+ request.initialize_http_header(headers)
+ request.body = qs
+ print_http_request(uri, request)
+ response_print_body(uri, request)
+end
+
+# Usage: -v --help --file= --query=
+def cmd_sparql_query
+ options={}
+ optparse = OptionParser.new do |opts|
+ opts.banner = "Usage: #{$cmd} [--query QUERY] [--service URI] [--post] 'query' | @file"
+ opts.on('--service=URI', '--server=URI', 'SPARQL endpoint') do |uri|
+ options[:service]=uri
+ end
+ opts.on('--query=FILE','--file=FILE', 'Take query from a file') do |file|
+ options[:file]=file
+ end
+ opts.on('--output=TYPE', [:json,:xml,:text,:csv,:tsv],
+ 'Set the output argument') do |type|
+ options[:output]=type
+ end
+ opts.on('--accept=TYPE', [:json,:xml,:text,:csv,:tsv],
+ 'Set the accept header type') do |type|
+ options[:accept]=type
+ end
+ options[:verbose] = false
+ opts.on( '--post', 'Force use of POST' ) do
+ options[:post] = true
+ end
+ opts.on( '-v', '--verbose', 'Verbose' ) do
+ options[:verbose] = true
+ end
+ opts.on( '--version', 'Print version and exit' ) do
+ print "#{SOH_NAME} #{SOH_VERSION}\n"
+ exit
+ end
+ opts.on( '-h', '--help', 'Display this screen and exit' ) do
+ puts opts
+ exit
+ end
+ end
+
+ begin optparse.parse!
+ rescue OptionParser::InvalidArgument, OptionParser::InvalidOption => e
+ warn e
+ exit 1
+ end
+
+ $verbose = options[:verbose]
+ $print_http = $verbose
+ usePOST = options[:post]
+
+ service = options[:service]
+ warn_exit 'No service specified. Required --service=URI',1 if service.nil?
+
+ # Query
+ query=nil
+ query_file=options[:file]
+ if query_file.nil? && ARGV.size == 0
+ then
+ warn_exit 'No query specified.',1
+ end
+ if query_file.nil?
+ query = ARGV.shift
+ if query.match(/^@/)
+ query_file = query[1..-1]
+ query = nil
+ end
+ end
+
+ # --output ==> output= (non-standard)
+ args={}
+ case options[:output]
+ when nil
+ when "json","xml","text","csv","tsv"
+ args['output'] = options[:output]
+ when :json,:xml,:text,:csv,:tsv
+ args['output'] = options[:output].to_s
+ else
+ warn_exit "Unrecognized output type: "+options[:output],2
+ end
+
+ # --accept
+ # options[:accept]
+
+ print "SPARQL #{service}\n" if $verbose
+ #args={"output"=>"text"}
+ SPARQL_query(service, query, query_file, usePOST, args)
+ exit(0)
+end
+
+## -------- SPARQL Update
+
+# Update sent as a WWW form.
+def SPARQL_update_by_form(service, update, args2={})
+ args = {}
+ args.merge!(args2)
+ headers={}
+ headers.merge!($headers)
+ # args? encode?
+ body="update="+uri_escape(update)
+ headers[$hContentType] = $mtWWWForm
+ headers[$hContentLength] = body.length.to_s
+ uri = URI.parse(service)
+ execute_post_form(uri, headers, body)
+end
+
+# DRY - query form.
+def execute_post_form(uri, headers, body)
+ request = Net::HTTP::Post.new(uri.request_uri)
+ request.initialize_http_header(headers)
+ request.body = body
+ print_http_request(uri, request)
+ response_no_body(uri, request)
+end
+
+def SPARQL_update(service, update, args2={})
+ args = {}
+ args.merge!(args2)
+ headers={}
+ headers.merge!($headers)
+ headers[$hContentType] = $mtSparqlUpdate
+ uri = URI.parse(service)
+ request = Net::HTTP::Post.new(uri.request_uri)
+ request.initialize_http_header(headers)
+ request.body = update
+ print_http_request(uri, request)
+ response_no_body(uri, request)
+end
+
+def cmd_sparql_update(by_raw_post=true)
+ # Share with cmd_sparql_query
+ options={}
+ optparse = OptionParser.new do |opts|
+ opts.banner = "Usage: #{$cmd} [--file REQUEST] [--service URI] 'request' | @file"
+ opts.on('--service=URI', '--server=URI', 'SPARQL endpoint') do |uri|
+ options[:service]=uri
+ end
+ opts.on('--update=FILE', '--file=FILE', 'Take update from a file') do |file|
+ options[:file]=file
+ end
+ options[:verbose] = false
+ opts.on( '-v', '--verbose', 'Verbose' ) do
+ options[:verbose] = true
+ end
+ opts.on( '--version', 'Print version and exit' ) do
+ print "#{SOH_NAME} #{SOH_VERSION}\n"
+ exit
+ end
+ opts.on( '-h', '--help', 'Display this screen and exit' ) do
+ puts opts
+ exit
+ end
+ end
+
+ begin optparse.parse!
+ rescue OptionParser::InvalidArgument => e
+ warn e
+ exit
+ end
+
+ $verbose = options[:verbose]
+ $print_http = $verbose
+
+ service = options[:service]
+ warn_exit 'No service specified. Required --service=URI',1 if service.nil?
+
+ update=nil
+ update_file=options[:file]
+
+ if update_file.nil? && ARGV.size == 0
+ then
+ warn_exit 'No update specified.',1
+ end
+ if update_file.nil?
+ update = ARGV.shift
+ if update.match(/^@/)
+ update_file = update[1..-1]
+ update = nil
+ end
+ end
+
+ print "SPARQL-Update #{service}\n" if $verbose
+ args={}
+
+ # Reads in the file :-(
+ if update.nil?
+ then
+ update = open(update_file, 'rb'){|f| f.read}
+ else
+ update = string_or_file(update)
+ end
+
+ if by_raw_post
+ SPARQL_update(service, update, args)
+ else
+ SPARQL_update_by_form(service, update, args)
+ end
+ exit(0)
+end
+
+## -------
+
+case $cmd
+when "s-http", "sparql-http", "soh"
+ $banner="#{$cmd} [get|post|put|delete] datasetURI graph [file]"
+ cmd_soh
+when "s-get", "s-head", "s-put", "s-delete", "s-post"
+
+ case $cmd
+ when "s-get", "s-head", "s-delete"
+ $banner="#{$cmd} datasetURI graph"
+ when "s-put", "s-post"
+ $banner="#{$cmd} datasetURI graph file"
+ end
+ cmd2 = $cmd.sub(/^s-/, '').upcase
+ cmd_soh cmd2
+
+when "s-query", "sparql-query"
+ cmd_sparql_query
+when "s-update", "sparql-update"
+ cmd_sparql_update true
+when "s-update-form", "sparql-update-form"
+ cmd_sparql_update false
+else
+ warn_exit "Unknown: "+$cmd, 1
+end
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src-dev/dev/BackwardForwardDescribeFactory.java
----------------------------------------------------------------------
diff --git a/jena-fuseki/src-dev/dev/BackwardForwardDescribeFactory.java b/jena-fuseki/src-dev/dev/BackwardForwardDescribeFactory.java
new file mode 100644
index 0000000..2322929
--- /dev/null
+++ b/jena-fuseki/src-dev/dev/BackwardForwardDescribeFactory.java
@@ -0,0 +1,95 @@
+/*
+ * 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 dev;
+
+import com.hp.hpl.jena.query.Dataset;
+import com.hp.hpl.jena.rdf.model.Model;
+import com.hp.hpl.jena.rdf.model.ModelFactory;
+import com.hp.hpl.jena.rdf.model.RDFNode;
+import com.hp.hpl.jena.rdf.model.Resource;
+import com.hp.hpl.jena.sparql.ARQConstants;
+import com.hp.hpl.jena.sparql.core.Quad;
+import com.hp.hpl.jena.sparql.core.describe.DescribeHandler;
+import com.hp.hpl.jena.sparql.core.describe.DescribeHandlerFactory;
+import com.hp.hpl.jena.sparql.core.describe.DescribeHandlerRegistry;
+import com.hp.hpl.jena.sparql.util.Context;
+import com.hp.hpl.jena.tdb.TDB ;
+import com.hp.hpl.jena.util.iterator.ExtendedIterator;
+import com.hp.hpl.jena.vocabulary.RDFS;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BackwardForwardDescribeFactory implements DescribeHandlerFactory {
+
+ final static Logger log = LoggerFactory.getLogger(BackwardForwardDescribeFactory.class);
+
+ static {
+ TDB.init();
+ log.info("Attaching replacement describe handler");
+ DescribeHandlerRegistry reg = DescribeHandlerRegistry.get();
+ log.info("Clearing existing describe handlers");
+ reg.clear();
+ reg.add(new BackwardForwardDescribeFactory());
+ log.info("Attached");
+ }
+
+ @Override
+ public DescribeHandler create() {
+ return new BackwardForwardDescribe();
+ }
+
+ public static class BackwardForwardDescribe implements DescribeHandler {
+
+ private Dataset dataset;
+ private Model result;
+ private Model defaultModel;
+ private Model unionModel;
+
+ @Override
+ public void start(Model accumulateResultModel, Context qContext) {
+ this.result = accumulateResultModel;
+ this.dataset = (Dataset) qContext.get(ARQConstants.sysCurrentDataset);
+ this.defaultModel = dataset.getDefaultModel();
+ this.unionModel = dataset.getNamedModel(Quad.unionGraph.getURI());
+ }
+
+ @Override
+ public void describe(Resource resource) {
+ result.add(defaultModel.listStatements(resource, null, (RDFNode) null));
+ result.add(defaultModel.listStatements(null, null, resource));
+ result.add(unionModel.listStatements(resource, null, (RDFNode) null));
+ result.add(unionModel.listStatements(null, null, resource));
+
+ // Gather labels for dangling refs
+ Model labels = ModelFactory.createDefaultModel();
+ ExtendedIterator<RDFNode> it = result.listObjects().andThen(result.listSubjects());
+ while (it.hasNext()) {
+ RDFNode node = it.next();
+ if (node.isLiteral() || resource.equals(node)) continue;
+ labels.add(defaultModel.listStatements((Resource) node, RDFS.label, (RDFNode) null));
+ labels.add(unionModel.listStatements((Resource) node, RDFS.label, (RDFNode) null));
+ }
+ result.add(labels);
+ }
+
+ @Override
+ public void finish() {
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src-dev/dev/DevFuseki.java
----------------------------------------------------------------------
diff --git a/jena-fuseki/src-dev/dev/DevFuseki.java b/jena-fuseki/src-dev/dev/DevFuseki.java
new file mode 100644
index 0000000..70bbd7b
--- /dev/null
+++ b/jena-fuseki/src-dev/dev/DevFuseki.java
@@ -0,0 +1,149 @@
+/*
+ * 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 dev;
+
+public class DevFuseki
+{
+ // SPARQL_QueryDataset.vialidate query -- but FROM etc is important for TDB.
+ // DatasetDescription from protocol
+ // createDataset from the ARQ.
+ // SPARQL_QueryGeneral.datasetFromDescription
+
+ // Config:
+ // fuseki:name ==> fuseki:serviceName of fuseki:endpointBase
+ // rdfs:label for log files.
+
+ // sparql.jsp needs to switch on presence and name of service endpoints.
+ // --accept for to soh for construct queries (check can get CONSTRUCT in TTL).
+
+ // application/json for application/sparql-results+json.
+ // application/xml for application/sparql-results+xml.
+
+ // LimitingGraph, LimitingBulkUpdateHandler --> change to use a limiting Sink<>
+ // Finish: SPARQL_QueryGeneral
+ // Parse errors and etc need to be passed out.
+ // --jetty-config documentation
+
+ // Rework arguments.
+ // Explicit install pages.
+ // Pages for read-only.
+
+ // RDF/XML_ABBREV in ResponseModel
+ // Config Jetty from a file?
+ // Alternatibe way to run Fuseki
+
+ // Flint?
+ // Pages for publish mode.
+
+ // Multiple Accept headers
+ // WebContent and ContentType clean up.
+
+ // SOH default to not needing 'default'
+ // More error handling.
+
+ // Migrate ContentType to RIOT
+ // use in WebContent.
+
+ //soh : --accept application/turtle for CONSTRUCT queries.
+
+ // Direct naming.
+ // Use absence/presence of a query string to switch.
+
+ // sparql.jsp ==> if no dataset, go to choosing page or error page linking to.
+
+ // Better handling of bad URI name for a graph http:/example/X => stacktrace.
+
+ // FUSEKI_ROOT
+
+ // Documentation:
+ // Plan documentation.
+ // MIME types supported
+ // Include a data file in the distribution.
+ // curl as commandline
+
+ // Dataset servers - bulk loader.
+ // Access the bulk loader via web. [later]
+
+ // Structure pages, different static content servers
+ // /Main - index.html = fuseki.html
+ // /validate
+ // /admin
+
+ // Server-local graph naming
+
+ // Plain text error pages
+
+ // Deploy to sparql.org -- need query form for read-only mode.
+
+ // + LARQ
+
+ // Testing:
+ // No file -> error.
+
+ // Remove from package conneg - use code from ARQ/Atlas.
+ // TypedStream TypedInoputStrea, TypedOutputStream, MediaType, MediaRange
+
+ // Bundle tdb scripts with Fuseki.
+
+ // ParserFor - share between SPARQL_REST and SPARQL_Upload
+ // UploadTo dataset (TriG, N-Quads)
+
+ // populate forms with prefixes (later)
+
+ // Tests
+ // TestProtocol (HTTP update, query, update), inc status codes.
+ // SPARQL Query servlet / SPARQL Update servlet
+ // TestContentNegotiation - is coveage enough?
+
+ // ?? Slug header:
+ // http://bitworking.org/projects/atom/rfc5023.html#rfc.section.9.7
+
+ // ETags.
+
+ // Authentication
+
+ // SOH
+ // Refactor into body/no_body send & body/no_body receive
+ // All:
+ // -v --help --accept --user/--password ( or --auth user:pass)
+ // Drop --service.
+ // Local config file - read to get service settings.
+
+ // --accept line/shortname : s-get, s-query
+ // Basic authentication: --user --password
+
+ // Argument names: --service naming seems inconsistent.
+
+ // Plug-ins:
+ // Dataset (query, Update), HttpInternalIF?
+ // "Connection"
+ // Locking => transaction support (via default model?)
+ // HttpAction.beginRead() etc.
+
+ // Java clients:
+ // DatasetAccessor : don't serialise to byte[] and then send.
+ // DatasetAccessor : check existence of endpoint.
+
+ // Content-Length: SHOULD
+ // Transfer-Encoding: identity
+ // "chunked" encoding
+ // gzip
+
+ // Code examples
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src-dev/dev/RunFuseki.java
----------------------------------------------------------------------
diff --git a/jena-fuseki/src-dev/dev/RunFuseki.java b/jena-fuseki/src-dev/dev/RunFuseki.java
new file mode 100644
index 0000000..74f678c
--- /dev/null
+++ b/jena-fuseki/src-dev/dev/RunFuseki.java
@@ -0,0 +1,90 @@
+/*
+ * 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 dev;
+
+import org.apache.jena.fuseki.FusekiCmd ;
+
+public class RunFuseki
+{
+ public static void main(String[] args)
+ {
+ //demo() ;
+ //FusekiCmd.main("--config=config.ttl") ; System.exit(0) ;
+ main1() ;
+ }
+
+ public static void demo()
+ {
+ String DIR="DemoServer" ;
+ FusekiCmd.main("--config="+name(DIR,"config.ttl"), "--pages="+name(DIR, "demo-pages")) ;
+ System.exit(0) ;
+ }
+
+ public static String name(String DIR, String filename)
+ {
+ StringBuilder sb = new StringBuilder() ;
+ if ( ! filename.startsWith("/") )
+ {
+ sb.append(DIR) ;
+ if ( ! DIR.endsWith("/") )
+ sb.append("/") ;
+ }
+ sb.append(filename) ;
+ return sb.toString() ;
+ }
+
+ private static void main1()
+ {
+ String tmpdir = System.getenv("TMPDIR") ;
+ if ( tmpdir == null )
+ tmpdir = System.getenv("TMP") ;
+ if ( tmpdir == null )
+ tmpdir = System.getenv("HOME")+"/tmp" ;
+ if ( ! tmpdir.endsWith("/") )
+ tmpdir = tmpdir+"/" ;
+
+ FusekiCmd.main(
+ // "-v",
+ "--mem", "--update", "/ds"
+ //"--update", "--loc="+tmpdir+"DB", "--set=tdb:unionDefaultGraph=true", "/ds"
+ //"--update", "--mem", "/ds"
+
+ //"--update", "--memtdb", "--set=tdb:unionDefaultGraph=true", "/ds"
+
+ //"--debug",
+ //"--update",
+ //"--timeout=1000,5000",
+ //"--set=arq:queryTimeout=1000",
+ //"--port=3030",
+ //"--mgtPort=3031",
+ //"--mem",
+ //"--home=/home/afs/Projects/Fuseki",
+ //"--loc=DB",
+ //"--file=D.nt",
+ //"--gzip=no",
+ //"--desc=desc.ttl",
+ //--pages=
+ //"--jetty-config=jetty-fuseki.xml",
+ //"--config=config-tdb.ttl"
+ // "/ds"
+ ) ;
+ System.exit(0) ;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src/main/java/org/apache/jena/fuseki/DEF.java
----------------------------------------------------------------------
diff --git a/jena-fuseki/src/main/java/org/apache/jena/fuseki/DEF.java b/jena-fuseki/src/main/java/org/apache/jena/fuseki/DEF.java
new file mode 100644
index 0000000..c24f7e3
--- /dev/null
+++ b/jena-fuseki/src/main/java/org/apache/jena/fuseki/DEF.java
@@ -0,0 +1,66 @@
+/*
+ * 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 static org.apache.jena.riot.WebContent.* ;
+import org.apache.jena.atlas.web.AcceptList ;
+import org.apache.jena.atlas.web.MediaType ;
+
+public class DEF
+{
+ public static final MediaType acceptRDFXML = MediaType.create(contentTypeRDFXML) ;
+ public static final MediaType acceptNQuads = MediaType.create(contentTypeNQuads) ;
+ public static final MediaType acceptRSXML = MediaType.create(contentTypeResultsXML) ;
+
+ public static final AcceptList rdfOffer = AcceptList.create(contentTypeTurtle,
+ contentTypeTurtleAlt1,
+ contentTypeTurtleAlt2,
+ contentTypeNTriples,
+ contentTypeNTriplesAlt,
+ contentTypeRDFXML,
+ contentTypeJSONLD,
+ contentTypeRDFJSON,
+ contentTypeRDFThrift
+ ) ;
+
+ public static final AcceptList quadsOffer = AcceptList.create(contentTypeTriG,
+ contentTypeTriGAlt1,
+ contentTypeTriGAlt2,
+ contentTypeJSONLD,
+ contentTypeNQuads,
+ contentTypeNQuadsAlt1,
+ contentTypeNQuadsAlt2
+ ) ;
+
+ public static final AcceptList rsOfferTable = AcceptList.create(contentTypeResultsJSON,
+ contentTypeTextCSV,
+ contentTypeTextTSV,
+ contentTypeResultsXML,
+ contentTypeResultsThrift,
+ contentTypeTextPlain
+ ) ;
+
+ public static final AcceptList rsOfferBoolean = AcceptList.create(contentTypeResultsJSON,
+ contentTypeTextCSV,
+ contentTypeTextTSV,
+ contentTypeResultsXML,
+ contentTypeTextPlain
+ ) ;
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src/main/java/org/apache/jena/fuseki/EmbeddedFusekiServer.java
----------------------------------------------------------------------
diff --git a/jena-fuseki/src/main/java/org/apache/jena/fuseki/EmbeddedFusekiServer.java b/jena-fuseki/src/main/java/org/apache/jena/fuseki/EmbeddedFusekiServer.java
new file mode 100644
index 0000000..0261b67
--- /dev/null
+++ b/jena-fuseki/src/main/java/org/apache/jena/fuseki/EmbeddedFusekiServer.java
@@ -0,0 +1,86 @@
+/*
+ * 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 org.apache.jena.atlas.lib.FileOps ;
+import org.apache.jena.fuseki.server.FusekiConfig ;
+import org.apache.jena.fuseki.server.SPARQLServer ;
+import org.apache.jena.fuseki.server.ServerConfig ;
+
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.DatasetGraphFactory ;
+import com.hp.hpl.jena.tdb.TDBFactory ;
+
+/** Embedded (same JVM) server.
+ * <p>Example for one server per test suite:
+ * <pre>
+ private static EmbeddedFusekiServer server = null ;
+ \@BeforeClass public static void beforeClass() {
+ server = EmbeddedFusekiServer.createMemByPath(3030, "/test") ;
+ server.start() ;
+ \@AfterClass public static void afterClass() {
+ server.stop() ;
+ }
+ </pre>
+ */
+public class EmbeddedFusekiServer
+{
+
+ public static EmbeddedFusekiServer mem(int port, String datasetPath) {
+ DatasetGraph dsg = DatasetGraphFactory.createMem() ;
+ return EmbeddedFusekiServer.create(port, dsg, datasetPath) ;
+ }
+
+ public static EmbeddedFusekiServer memTDB(int port, String datasetPath) {
+ DatasetGraph dsg = TDBFactory.createDatasetGraph() ;
+ return EmbeddedFusekiServer.create(port, dsg, datasetPath) ;
+ }
+
+ public static EmbeddedFusekiServer create(int port, DatasetGraph dsg, String datasetPath) {
+ ServerConfig conf = FusekiConfig.defaultConfiguration(datasetPath, dsg, true, true) ;
+ conf.port = port ;
+ conf.pagesPort = port ;
+ if ( ! FileOps.exists(conf.pages) )
+ conf.pages = null ;
+ return new EmbeddedFusekiServer(conf) ;
+ }
+
+ public static EmbeddedFusekiServer configure(int port, String fileConfig) {
+ ServerConfig conf = FusekiConfig.configure(fileConfig) ;
+ conf.port = port ;
+ conf.pagesPort = port ;
+ if ( ! FileOps.exists(conf.pages) )
+ conf.pages = null ;
+ return new EmbeddedFusekiServer(conf) ;
+ }
+
+ private SPARQLServer server = null ;
+
+ public EmbeddedFusekiServer(ServerConfig conf) {
+ server = new SPARQLServer(conf) ;
+ }
+
+ public void start() {
+ server.start() ;
+ }
+
+ public void stop() {
+ server.stop() ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src/main/java/org/apache/jena/fuseki/Fuseki.java
----------------------------------------------------------------------
diff --git a/jena-fuseki/src/main/java/org/apache/jena/fuseki/Fuseki.java b/jena-fuseki/src/main/java/org/apache/jena/fuseki/Fuseki.java
new file mode 100644
index 0000000..c62ba1f
--- /dev/null
+++ b/jena-fuseki/src/main/java/org/apache/jena/fuseki/Fuseki.java
@@ -0,0 +1,174 @@
+/*
+ * 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 org.apache.jena.fuseki.server.SPARQLServer ;
+import org.apache.jena.riot.RIOT ;
+import org.apache.jena.riot.system.stream.LocatorFTP ;
+import org.apache.jena.riot.system.stream.LocatorHTTP ;
+import org.apache.jena.riot.system.stream.StreamManager ;
+import org.slf4j.Logger ;
+import org.slf4j.LoggerFactory ;
+
+import com.hp.hpl.jena.query.ARQ ;
+import com.hp.hpl.jena.sparql.SystemARQ ;
+import com.hp.hpl.jena.sparql.lib.Metadata ;
+import com.hp.hpl.jena.sparql.mgt.SystemInfo ;
+import com.hp.hpl.jena.sparql.util.Context ;
+import com.hp.hpl.jena.sparql.util.MappingRegistry ;
+import com.hp.hpl.jena.tdb.TDB ;
+import com.hp.hpl.jena.tdb.transaction.TransactionManager ;
+
+/**
+ * <p>The main class enabling us to:</p>
+ * <ol>
+ * <li>create instances of a Fuseki server e.g.
+ * the ARQ, RIOT and TDB server stack</li>
+ * <li>get server global {@link com.hp.hpl.jena.sparql.util.Context} e.g.
+ * named values used to pass implementation-specific parameters across
+ * general interfaces.</li>
+ * <li>get the {@link org.apache.jena.fuseki.server.SPARQLServer} instance.</li>
+ * <li>set the {@link org.apache.jena.fuseki.server.SPARQLServer} instance.</li>
+ *
+ */
+public class Fuseki
+{
+ /** Path to ???*/
+ static public String PATH = "org.apache.jena.fuseki" ;
+
+ /** a unique IRI for the Fuseki namespace*/
+ static public String FusekiIRI = "http://jena.apache.org/Fuseki" ;
+
+ /** Fuseki home environment, usually set to $FUSEKI_HOME */
+ static public String FusekiHomeEnv = "FUSEKI_HOME" ;
+
+ /** a unique IRI including the symbol notation for which properties should be appended */
+ static public String FusekiSymbolIRI = "http://jena.apache.org/fuseki#" ;
+
+ /** ??? */
+ static public String PagesStatic = "pages" ;
+
+ /**
+ * TEMPORARY - this enables POST of triples to the dataset URI causing a graph to be created.
+ * POSTing to /dataset?graph=uri is preferred
+ */
+ static public boolean graphStoreProtocolPostCreate = false ;
+
+ /** an relative path to the location of <code>fuseki-properties.xml</code> file */
+ static private String metadataLocation = "org/apache/jena/fuseki/fuseki-properties.xml" ;
+
+ /** Object which holds metadata specified within {@link Fuseki#metadataLocation} */
+ static private Metadata metadata = initMetadata() ;
+
+ private static Metadata initMetadata()
+ {
+ Metadata m = new Metadata() ;
+ //m.addMetadata(metadataDevLocation) ;
+ m.addMetadata(metadataLocation) ;
+ return m ;
+ }
+
+ /** The name of the Fuseki server. Set to the string <code>Fuseki</code> by default.*/
+ static public final String NAME = "Fuseki" ;
+
+ /** Version of this Fuseki instance */
+ static public final String VERSION = metadata.get(PATH+".version", "development");
+
+ /** Date when Fuseki was built */
+ static public final String BUILD_DATE = metadata.get(PATH+".build.datetime", "unknown") ; // call Date if unavailable.
+
+ /** An identifier for the HTTP Fuseki server instance*/
+ static public final String serverHttpName = NAME+" ("+VERSION+")" ;
+
+ /** Actual log file for operations */
+ public static final String requestLogName = PATH+".Fuseki" ;
+
+ /** Instance of log for operations */
+ public static final Logger requestLog = LoggerFactory.getLogger(requestLogName) ;
+
+ /** Actual log file for general server messages.*/
+ public static final String serverLogName = PATH+".Server" ;
+
+ /** Instance of log for general server messages */
+ public static final Logger serverLog = LoggerFactory.getLogger(serverLogName) ;
+
+ /** Actual log file for config server messages. */
+ public static final String configLogName = PATH+".Config" ;
+
+ /** Instance of log for config server message s*/
+ public static final Logger configLog = LoggerFactory.getLogger(configLogName) ;
+
+ /** Instance of log for config server message s*/
+ public static boolean verboseLogging = false ;
+
+ /** An instance of management for stream opening, including redirecting through a
+ * location mapper whereby a name (e.g. URL) is redirected to another name (e.g. local file).
+ * */
+ public static final StreamManager webStreamManager ;
+ static {
+ webStreamManager = new StreamManager() ;
+ // Only know how to handle http and ftp URLs - nothing local.
+ webStreamManager.addLocator(new LocatorHTTP()) ;
+ webStreamManager.addLocator(new LocatorFTP()) ;
+ }
+
+ private static boolean initialized = false ;
+
+ /**
+ * Initialize an instance of the Fuseki server stack.
+ */
+ public synchronized static void init()
+ {
+ if ( initialized )
+ return ;
+ initialized = true ;
+ ARQ.init() ;
+ SystemInfo sysInfo = new SystemInfo(FusekiIRI, PATH, VERSION, BUILD_DATE) ;
+ SystemARQ.registerSubSystem(sysInfo) ;
+ RIOT.init() ;
+ TDB.init() ;
+ MappingRegistry.addPrefixMapping("fuseki", FusekiSymbolIRI) ;
+
+ TDB.setOptimizerWarningFlag(false) ;
+ // Don't set TDB batch commits.
+ // This can be slower, but it less memory hungry and more predictable.
+ TransactionManager.QueueBatchSize = 0 ;
+ }
+
+ /**
+ * Get server global {@link com.hp.hpl.jena.sparql.util.Context}.
+ * @return {@link com.hp.hpl.jena.query.ARQ#getContext()}
+ */
+ public static Context getContext()
+ {
+ return ARQ.getContext() ;
+ }
+
+ // Temporary ...
+ private static SPARQLServer server ;
+
+ /** set/specify the {@link org.apache.jena.fuseki.server.SPARQLServer} instance.*/
+ public static void setServer(SPARQLServer _server) { server = _server ; }
+
+ /** get the {@link org.apache.jena.fuseki.server.SPARQLServer} instance. */
+ public static SPARQLServer getServer() { return server ; }
+
+ // Force a call to init.
+ static { init() ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiCmd.java
----------------------------------------------------------------------
diff --git a/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiCmd.java b/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiCmd.java
new file mode 100644
index 0000000..b076871
--- /dev/null
+++ b/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiCmd.java
@@ -0,0 +1,505 @@
+/*
+ * 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 static org.apache.jena.fuseki.Fuseki.serverLog ;
+
+import java.io.File ;
+import java.io.InputStream ;
+import java.util.List ;
+
+import org.apache.jena.atlas.io.IO ;
+import org.apache.jena.atlas.lib.FileOps ;
+import org.apache.jena.atlas.lib.Lib ;
+import org.apache.jena.atlas.lib.StrUtils ;
+import org.apache.jena.atlas.logging.LogCtl ;
+import org.apache.jena.fuseki.mgt.ManagementServer ;
+import org.apache.jena.fuseki.server.FusekiConfig ;
+import org.apache.jena.fuseki.server.SPARQLServer ;
+import org.apache.jena.fuseki.server.ServerConfig ;
+import org.apache.jena.riot.Lang ;
+import org.apache.jena.riot.RDFDataMgr ;
+import org.apache.jena.riot.RDFLanguages ;
+import org.apache.jena.riot.SysRIOT ;
+import org.eclipse.jetty.server.Server ;
+import org.slf4j.Logger ;
+import arq.cmd.CmdException ;
+import arq.cmdline.ArgDecl ;
+import arq.cmdline.CmdARQ ;
+import arq.cmdline.ModDatasetAssembler ;
+
+import com.hp.hpl.jena.query.ARQ ;
+import com.hp.hpl.jena.query.Dataset ;
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.DatasetGraphFactory ;
+import com.hp.hpl.jena.tdb.TDB ;
+import com.hp.hpl.jena.tdb.TDBFactory ;
+import com.hp.hpl.jena.tdb.sys.Names ;
+import com.hp.hpl.jena.tdb.transaction.TransactionManager ;
+
+public class FusekiCmd extends CmdARQ
+{
+ private static String log4Jsetup = StrUtils.strjoinNL(
+ "## Plain output to stdout"
+ , "log4j.appender.jena.plain=org.apache.log4j.ConsoleAppender"
+ , "log4j.appender.jena.plain.target=System.out"
+ , "log4j.appender.jena.plain.layout=org.apache.log4j.PatternLayout"
+ , "log4j.appender.jena.plain.layout.ConversionPattern=%d{HH:mm:ss} %-5p %m%n"
+
+ , "## Plain output with level, to stderr"
+ , "log4j.appender.jena.plainlevel=org.apache.log4j.ConsoleAppender"
+ , "log4j.appender.jena.plainlevel.target=System.err"
+ , "log4j.appender.jena.plainlevel.layout=org.apache.log4j.PatternLayout"
+ , "log4j.appender.jena.plainlevel.layout.ConversionPattern=%d{HH:mm:ss} %-5p %m%n"
+
+ , "## Everything"
+ , "log4j.rootLogger=INFO, jena.plain"
+ , "log4j.logger.com.hp.hpl.jena=WARN"
+ , "log4j.logger.org.openjena=WARN"
+ , "log4j.logger.org.apache.jena=WARN"
+
+ , "# Server log."
+ , "log4j.logger.org.apache.jena.fuseki.Server=INFO"
+ , "# Request log."
+ , "log4j.logger.org.apache.jena.fuseki.Fuseki=INFO"
+ , "log4j.logger.org.apache.jena.tdb.loader=INFO"
+ , "log4j.logger.org.eclipse.jetty=ERROR"
+
+ , "## Parser output"
+ , "log4j.additivity."+SysRIOT.riotLoggerName+"=false"
+ , "log4j.logger."+SysRIOT.riotLoggerName+"=INFO, jena.plainlevel "
+ ) ;
+
+
+ // Set logging.
+ // 1/ Use log4j.configuration is defined.
+ // 2/ Use file:log4j.properties
+ // 3/ Use Built in.
+
+ static void setLogging() {
+ // No loggers have been created but configuration may have been set up.
+ String x = System.getProperty("log4j.configuration", null) ;
+
+ if ( x != null && ! x.equals("set") ) {
+ // "set" indicates that CmdMain set logging.
+ // Use standard log4j initialization.
+ return ;
+ }
+
+ String fn = "log4j.properties" ;
+ File f = new File(fn) ;
+ if ( f.exists() ) {
+ System.out.println("File") ;
+ // Use file log4j.properties
+ System.setProperty("log4j.configuration", "file:"+fn) ;
+ return ;
+ }
+ // Use built-in for Fuseki.
+ LogCtl.resetLogging(log4Jsetup) ;
+ }
+
+ static { setLogging() ; }
+
+ // Arguments:
+ // --update
+
+ // Specific switches:
+
+ // --admin=on/off
+
+ // --http-update
+ // --http-get
+
+ // --sparql-query
+ // --sparql-update
+
+ // pages/validators/
+ // pages/control/
+ // pages/query/ or /pages/sparql/
+
+ private static ArgDecl argMgtPort = new ArgDecl(ArgDecl.HasValue, "mgtPort", "mgtport") ;
+ private static ArgDecl argMem = new ArgDecl(ArgDecl.NoValue, "mem") ;
+ private static ArgDecl argAllowUpdate = new ArgDecl(ArgDecl.NoValue, "update", "allowUpdate") ;
+ private static ArgDecl argFile = new ArgDecl(ArgDecl.HasValue, "file") ;
+ private static ArgDecl argMemTDB = new ArgDecl(ArgDecl.NoValue, "memtdb", "memTDB") ;
+ private static ArgDecl argTDB = new ArgDecl(ArgDecl.HasValue, "loc", "location") ;
+ private static ArgDecl argPort = new ArgDecl(ArgDecl.HasValue, "port") ;
+ private static ArgDecl argLocalhost = new ArgDecl(ArgDecl.NoValue, "localhost", "local") ;
+ private static ArgDecl argTimeout = new ArgDecl(ArgDecl.HasValue, "timeout") ;
+ private static ArgDecl argFusekiConfig = new ArgDecl(ArgDecl.HasValue, "config", "conf") ;
+ private static ArgDecl argJettyConfig = new ArgDecl(ArgDecl.HasValue, "jetty-config") ;
+ private static ArgDecl argGZip = new ArgDecl(ArgDecl.HasValue, "gzip") ;
+ private static ArgDecl argUber = new ArgDecl(ArgDecl.NoValue, "uber", "über") ; // Use the überservlet (experimental)
+ private static ArgDecl argBasicAuth = new ArgDecl(ArgDecl.HasValue, "basic-auth") ;
+
+ private static ArgDecl argGSP = new ArgDecl(ArgDecl.NoValue, "gsp") ; // GSP compliance mode
+
+ private static ArgDecl argHome = new ArgDecl(ArgDecl.HasValue, "home") ;
+ private static ArgDecl argPages = new ArgDecl(ArgDecl.HasValue, "pages") ;
+
+ //private static ModLocation modLocation = new ModLocation() ;
+ private static ModDatasetAssembler modDataset = new ModDatasetAssembler() ;
+
+ // fuseki [--mem|--desc assembler.ttl] [--port PORT] **** /datasetURI
+
+ static public void main(String...argv)
+ {
+ // Just to make sure ...
+ ARQ.init() ;
+ TDB.init() ;
+ Fuseki.init() ;
+ new FusekiCmd(argv).mainRun() ;
+ }
+
+ private int port = 3030 ;
+ private int mgtPort = -1 ;
+ private boolean listenLocal = false ;
+
+ private DatasetGraph dsg = null ;
+ private String datasetPath = null ;
+ private boolean allowUpdate = false ;
+
+ private String fusekiConfigFile = null ;
+ private boolean enableCompression = true ;
+ private String jettyConfigFile = null ;
+ private String authConfigFile = null ;
+ private String homeDir = null ;
+ private String pagesDir = null ;
+
+ public FusekiCmd(String...argv)
+ {
+ super(argv) ;
+
+ if ( false )
+ // Consider ...
+ TransactionManager.QueueBatchSize = TransactionManager.QueueBatchSize / 2 ;
+
+ getUsage().startCategory("Fuseki") ;
+ addModule(modDataset) ;
+ add(argMem, "--mem", "Create an in-memory, non-persistent dataset for the server") ;
+ add(argFile, "--file=FILE", "Create an in-memory, non-persistent dataset for the server, initialised with the contents of the file") ;
+ add(argTDB, "--loc=DIR", "Use an existing TDB database (or create if does not exist)") ;
+ add(argMemTDB, "--memTDB", "Create an in-memory, non-persistent dataset using TDB (testing only)") ;
+ add(argPort, "--port", "Listen on this port number") ;
+ add(argPages, "--pages=DIR", "Set of pages to serve as static content") ;
+ // Set via jetty config file.
+ add(argLocalhost, "--localhost", "Listen only on the localhost interface") ;
+ add(argTimeout, "--timeout=", "Global timeout applied to queries (value in ms) -- format is X[,Y] ") ;
+ add(argAllowUpdate, "--update", "Allow updates (via SPARQL Update and SPARQL HTTP Update)") ;
+ add(argFusekiConfig, "--config=", "Use a configuration file to determine the services") ;
+ add(argJettyConfig, "--jetty-config=FILE", "Set up the server (not services) with a Jetty XML file") ;
+ add(argBasicAuth, "--basic-auth=FILE", "Configure basic auth using provided Jetty realm file, ignored if --jetty-config is used") ;
+ add(argMgtPort, "--mgtPort=port", "Enable the management commands on the given port") ;
+ add(argHome, "--home=DIR", "Root of Fuseki installation (overrides environment variable FUSEKI_HOME)") ;
+ add(argGZip, "--gzip=on|off", "Enable GZip compression (HTTP Accept-Encoding) if request header set") ;
+
+ add(argUber) ;
+ //add(argGSP) ;
+
+ super.modVersion.addClass(TDB.class) ;
+ super.modVersion.addClass(Fuseki.class) ;
+ }
+
+ static String argUsage = "[--config=FILE] [--mem|--desc=AssemblerFile|--file=FILE] [--port PORT] /DatasetPathName" ;
+
+ @Override
+ protected String getSummary()
+ {
+ return getCommandName()+" "+argUsage ;
+ }
+
+ @Override
+ protected void processModulesAndArgs()
+ {
+ int x = 0 ;
+
+ Logger log = Fuseki.serverLog ;
+
+ if ( contains(argFusekiConfig) )
+ fusekiConfigFile = getValue(argFusekiConfig) ;
+
+ ArgDecl assemblerDescDecl = new ArgDecl(ArgDecl.HasValue, "desc", "dataset") ;
+ if ( contains(argMem) ) x++ ;
+ if ( contains(argFile) ) x++ ;
+ if ( contains(assemblerDescDecl) ) x++ ;
+ if ( contains(argTDB) ) x++ ;
+ if ( contains(argMemTDB) ) x++ ;
+
+ if ( fusekiConfigFile != null )
+ {
+ if ( x > 1 )
+ throw new CmdException("Dataset specificed on the command line and also a configuration file specificed.") ;
+ }
+ else
+ {
+ if ( x == 0 )
+ throw new CmdException("Required: either --config=FILE or one of --mem, --file, --loc or --desc") ;
+ }
+
+ if ( contains(argMem) )
+ {
+ log.info("Dataset: in-memory") ;
+ dsg = DatasetGraphFactory.createMem() ;
+ }
+ if ( contains(argFile) )
+ {
+ dsg = DatasetGraphFactory.createMem() ;
+ // replace by RiotLoader after ARQ refresh.
+ String filename = getValue(argFile) ;
+ log.info("Dataset: in-memory: load file: "+filename) ;
+ if ( ! FileOps.exists(filename) )
+ throw new CmdException("File not found: "+filename) ;
+
+ Lang language = RDFLanguages.filenameToLang(filename) ;
+ if ( language == null )
+ throw new CmdException("Can't guess language for file: "+filename) ;
+ InputStream input = IO.openFile(filename) ;
+
+ if ( RDFLanguages.isQuads(language) )
+ RDFDataMgr.read(dsg, filename) ;
+ else
+ RDFDataMgr.read(dsg.getDefaultGraph(), filename) ;
+ }
+
+ if ( contains(argMemTDB) )
+ {
+ log.info("TDB dataset: in-memory") ;
+ dsg = TDBFactory.createDatasetGraph() ;
+ }
+
+ if ( contains(argTDB) )
+ {
+ String dir = getValue(argTDB) ;
+
+ if ( Lib.equal(dir, Names.memName) ) {
+ log.info("TDB dataset: in-memory") ;
+ } else {
+ if ( ! FileOps.exists(dir) )
+ throw new CmdException("Directory not found: "+dir) ;
+ log.info("TDB dataset: directory="+dir) ;
+ }
+ dsg = TDBFactory.createDatasetGraph(dir) ;
+ }
+
+ // Otherwise
+ if ( contains(assemblerDescDecl) )
+ {
+ log.info("Dataset from assembler") ;
+ Dataset ds = modDataset.createDataset() ;
+ if ( ds != null )
+ dsg = ds.asDatasetGraph() ;
+ }
+
+ if ( contains(argFusekiConfig) )
+ {
+ if ( dsg != null )
+ throw new CmdException("Dataset specificed on the command line and also a configuration file specificed.") ;
+ fusekiConfigFile = getValue(argFusekiConfig) ;
+ }
+
+ if ( contains(argPort) )
+ {
+ String portStr = getValue(argPort) ;
+ try {
+ port = Integer.parseInt(portStr) ;
+ } catch (NumberFormatException ex)
+ {
+ throw new CmdException(argPort.getKeyName()+" : bad port number: "+portStr) ;
+ }
+ }
+
+ if ( contains(argMgtPort) )
+ {
+ String mgtPortStr = getValue(argMgtPort) ;
+ try {
+ mgtPort = Integer.parseInt(mgtPortStr) ;
+ } catch (NumberFormatException ex)
+ {
+ throw new CmdException(argMgtPort.getKeyName()+" : bad port number: "+mgtPortStr) ;
+ }
+ }
+
+ if ( contains(argLocalhost) )
+ listenLocal = true ;
+
+ if ( fusekiConfigFile == null && dsg == null )
+ throw new CmdException("No dataset defined and no configuration file: "+argUsage) ;
+
+ if ( dsg != null )
+ {
+ if ( getPositional().size() == 0 )
+ throw new CmdException("No dataset path name given") ;
+ if ( getPositional().size() > 1 )
+ throw new CmdException("Multiple dataset path names given") ;
+ datasetPath = getPositionalArg(0) ;
+ if ( datasetPath.length() > 0 && ! datasetPath.startsWith("/") )
+ throw new CmdException("Dataset path name must begin with a /: "+datasetPath) ;
+
+ allowUpdate = contains(argAllowUpdate) ;
+ }
+
+ if ( contains(argTimeout) )
+ {
+ String str = getValue(argTimeout) ;
+ ARQ.getContext().set(ARQ.queryTimeout, str) ;
+ }
+
+ if ( contains(argJettyConfig) )
+ {
+ jettyConfigFile = getValue(argJettyConfig) ;
+ if ( !FileOps.exists(jettyConfigFile) )
+ throw new CmdException("No such file: "+jettyConfigFile) ;
+ }
+
+ if ( contains(argBasicAuth) )
+ {
+ authConfigFile = getValue(argBasicAuth) ;
+ if ( !FileOps.exists(authConfigFile) )
+ throw new CmdException("No such file: " + authConfigFile) ;
+ }
+
+ if ( contains(argHome) )
+ {
+ List<String> args = super.getValues(argHome) ;
+ homeDir = args.get(args.size()-1) ;
+ }
+
+ if ( contains(argPages) )
+ {
+ List<String> args = super.getValues(argPages) ;
+ pagesDir = args.get(args.size()-1) ;
+ }
+
+ if ( contains(argGZip) )
+ {
+ if ( ! hasValueOfTrue(argGZip) && ! hasValueOfFalse(argGZip) )
+ throw new CmdException(argGZip.getNames().get(0)+": Not understood: "+getValue(argGZip)) ;
+ enableCompression = super.hasValueOfTrue(argGZip) ;
+ }
+
+ if ( contains(argUber) )
+ SPARQLServer.überServlet = true ;
+
+ if ( contains(argGSP) )
+ {
+ SPARQLServer.überServlet = true ;
+ Fuseki.graphStoreProtocolPostCreate = true ;
+ }
+
+ }
+
+ private static String sort_out_dir(String path)
+ {
+ path.replace('\\', '/') ;
+ if ( ! path.endsWith("/"))
+ path = path +"/" ;
+ return path ;
+ }
+
+ @Override
+ protected void exec()
+ {
+ if ( homeDir == null )
+ {
+ if ( System.getenv(Fuseki.FusekiHomeEnv) != null )
+ homeDir = System.getenv(Fuseki.FusekiHomeEnv) ;
+ else
+ homeDir = "." ;
+ }
+
+ homeDir = sort_out_dir(homeDir) ;
+ Fuseki.configLog.info("Home Directory: " + FileOps.fullDirectoryPath(homeDir));
+ if ( ! FileOps.exists(homeDir) )
+ Fuseki.configLog.warn("No such directory for Fuseki home: "+homeDir) ;
+
+ String staticContentDir = pagesDir ;
+ if ( staticContentDir == null )
+ staticContentDir = homeDir+Fuseki.PagesStatic ;
+
+ Fuseki.configLog.debug("Static Content Directory: "+ FileOps.fullDirectoryPath(staticContentDir)) ;
+
+ if ( ! FileOps.exists(staticContentDir) ) {
+ Fuseki.configLog.warn("No such directory for static content: " + FileOps.fullDirectoryPath(staticContentDir)) ;
+ Fuseki.configLog.warn("You may need to set the --pages or --home option to configure static content correctly");
+ }
+
+ if ( jettyConfigFile != null )
+ Fuseki.configLog.info("Jetty configuration: "+jettyConfigFile) ;
+
+ ServerConfig serverConfig ;
+
+ if ( fusekiConfigFile != null )
+ {
+ Fuseki.configLog.info("Configuration file: "+fusekiConfigFile) ;
+ serverConfig = FusekiConfig.configure(fusekiConfigFile) ;
+ }
+ else
+ {
+ serverConfig = FusekiConfig.defaultConfiguration(datasetPath, dsg, allowUpdate, listenLocal) ;
+ if ( ! allowUpdate )
+ Fuseki.serverLog.info("Running in read-only mode.");
+ }
+
+ // TODO Get from parsing config file.
+ serverConfig.port = port ;
+ serverConfig.pages = staticContentDir ;
+ serverConfig.mgtPort = mgtPort ;
+ serverConfig.pagesPort = port ;
+ serverConfig.loopback = listenLocal ;
+ serverConfig.enableCompression = enableCompression ;
+ serverConfig.jettyConfigFile = jettyConfigFile ;
+ serverConfig.authConfigFile = authConfigFile ;
+ serverConfig.verboseLogging = ( super.isVerbose() || super.isDebug() ) ;
+
+ SPARQLServer server = new SPARQLServer(serverConfig) ;
+
+ // Temporary
+ Fuseki.setServer(server) ;
+
+ Server mgtServer = null ;
+
+ if ( mgtPort > 0 )
+ {
+ Fuseki.configLog.info("Management services on port "+mgtPort) ;
+ mgtServer = ManagementServer.createManagementServer(mgtPort) ;
+ try { mgtServer.start() ; }
+ catch (java.net.BindException ex)
+ { serverLog.error("SPARQLServer: Failed to start management server: " + ex.getMessage()) ; System.exit(1) ; }
+ catch (Exception ex)
+ { serverLog.error("SPARQLServer: Failed to start management server: " + ex.getMessage(), ex) ; System.exit(1) ; }
+ }
+
+ server.start() ;
+ try { server.getServer().join() ; } catch (Exception ex) {}
+
+ if ( mgtServer != null )
+ {
+ try { mgtServer.stop() ; }
+ catch (Exception e) { serverLog.warn("Failed to cleanly stop the management server", e) ; }
+ }
+ System.exit(0) ;
+ }
+
+
+ @Override
+ protected String getCommandName()
+ {
+ return "fuseki" ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiConfigException.java
----------------------------------------------------------------------
diff --git a/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiConfigException.java b/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiConfigException.java
new file mode 100644
index 0000000..5e1b018
--- /dev/null
+++ b/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiConfigException.java
@@ -0,0 +1,28 @@
+/*
+ * 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;
+
+
+public class FusekiConfigException extends FusekiException
+{
+ public FusekiConfigException(String msg, Throwable cause) { super(msg, cause) ; }
+ public FusekiConfigException(String msg) { super(msg) ; }
+ public FusekiConfigException(Throwable cause) { super(cause) ; }
+ public FusekiConfigException() { super() ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiException.java
----------------------------------------------------------------------
diff --git a/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiException.java b/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiException.java
new file mode 100644
index 0000000..04953ce
--- /dev/null
+++ b/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiException.java
@@ -0,0 +1,29 @@
+/*
+ * 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 com.hp.hpl.jena.sparql.ARQException ;
+
+public class FusekiException extends ARQException
+{
+ public FusekiException(String msg, Throwable cause) { super(msg, cause) ; }
+ public FusekiException(String msg) { super(msg) ; }
+ public FusekiException(Throwable cause) { super(cause) ; }
+ public FusekiException() { super() ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiLib.java
----------------------------------------------------------------------
diff --git a/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiLib.java b/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiLib.java
new file mode 100644
index 0000000..5324793
--- /dev/null
+++ b/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiLib.java
@@ -0,0 +1,148 @@
+/*
+ * 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.commons.lang.StringUtils ;
+import org.apache.jena.atlas.lib.MultiMap ;
+import org.apache.jena.atlas.lib.MultiMapToList ;
+import org.apache.jena.atlas.web.ContentType ;
+import org.apache.jena.fuseki.servlets.HttpAction ;
+import org.apache.jena.riot.Lang ;
+import org.apache.jena.riot.RDFLanguages ;
+
+import com.hp.hpl.jena.graph.Graph ;
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.graph.Triple ;
+import com.hp.hpl.jena.shared.PrefixMapping ;
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.Quad ;
+import com.hp.hpl.jena.sparql.util.Convert ;
+
+public class FusekiLib {
+ /** 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) {
+ StringBuilder sbuff = new StringBuilder() ;
+ 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 = MultiMapToList.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 ( String p : params )
+ {
+ 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 = StringUtils.replaceChars(value, "\r", "") ;
+ value = StringUtils.replaceChars(value, "\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) ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiNotFoundException.java
----------------------------------------------------------------------
diff --git a/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiNotFoundException.java b/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiNotFoundException.java
new file mode 100644
index 0000000..be9be90
--- /dev/null
+++ b/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiNotFoundException.java
@@ -0,0 +1,26 @@
+/*
+ * 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 org.apache.jena.web.HttpSC ;
+
+public class FusekiNotFoundException extends FusekiRequestException
+{
+ public FusekiNotFoundException(String msg) { super(HttpSC.NOT_FOUND_404, msg) ; }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiRequestException.java
----------------------------------------------------------------------
diff --git a/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiRequestException.java b/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiRequestException.java
new file mode 100644
index 0000000..e197be2
--- /dev/null
+++ b/jena-fuseki/src/main/java/org/apache/jena/fuseki/FusekiRequestException.java
@@ -0,0 +1,57 @@
+/*
+ * 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 org.apache.jena.web.HttpSC ;
+
+
+public class FusekiRequestException extends FusekiException
+{
+ public static FusekiRequestException create(int code, String msg)
+ {
+ if ( code == HttpSC.NOT_FOUND_404 )
+ return new FusekiNotFoundException(msg) ;
+ return new FusekiRequestException(code, msg) ;
+ }
+
+ private final int statusCode ;
+ private final String responseMessage ;
+ protected FusekiRequestException(int code, String msg)
+ {
+ super(msg) ;
+ this.statusCode = code ;
+ responseMessage = msg ;
+ }
+
+ public int getStatusCode()
+ {
+ return statusCode ;
+ }
+
+ public String getResponseMessage()
+ {
+ return responseMessage ;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "HTTP: "+statusCode+" "+getMessage() ;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src/main/java/org/apache/jena/fuseki/HttpNames.java
----------------------------------------------------------------------
diff --git a/jena-fuseki/src/main/java/org/apache/jena/fuseki/HttpNames.java b/jena-fuseki/src/main/java/org/apache/jena/fuseki/HttpNames.java
new file mode 100644
index 0000000..f6cee56
--- /dev/null
+++ b/jena-fuseki/src/main/java/org/apache/jena/fuseki/HttpNames.java
@@ -0,0 +1,93 @@
+/*
+ * 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;
+
+public class HttpNames
+{
+ // Request
+ public static final String hAccept = "Accept" ;
+ public static final String hAcceptEncoding = "Accept-Encoding" ;
+ public static final String hAcceptCharset = "Accept-Charset" ;
+ //public static final String hAcceptLanguage = "Accept-Language" ;
+
+ // Response
+ public static final String xhAcceptRanges = "Accept-Ranges" ;
+ public static final String hAllow = "Allow" ;
+ public static final String hContentEncoding = "Content-Encoding" ;
+ public static final String hContentLengh = "Content-Length" ;
+ public static final String hContentLocation = "Content-Location" ;
+ public static final String hContentRange = "Content-Range" ;
+ public static final String hContentType = "Content-Type" ;
+ public static final String hRetryAfter = "Retry-After" ;
+ public static final String hServer = "Server" ;
+ public static final String hLocation = "Location" ;
+ public static final String hVary = "Vary" ;
+ public static final String charset = "charset" ;
+
+ // CORS:
+ // http://www.w3.org/TR/cors/ http://esw.w3.org/CORS_Enabled
+ public static final String hAccessControlAllowOrigin = "Access-Control-Allow-Origin" ;
+
+ // Fuseki parameter names
+ public static final String paramGraph = "graph" ;
+ public static final String paramGraphDefault = "default" ;
+
+ public static final String paramQuery = "query" ;
+ public static final String paramQueryRef = "query-ref" ;
+ public static final String paramDefaultGraphURI = "default-graph-uri" ;
+ public static final String paramNamedGraphURI = "named-graph-uri" ;
+
+ public static final String paramStyleSheet = "stylesheet" ;
+ public static final String paramAccept = "accept" ;
+ public static final String paramOutput1 = "output" ; // See Yahoo! developer: http://developer.yahoo.net/common/json.html
+ public static final String paramOutput2 = "format" ; // Alternative name
+ public static final String paramCallback = "callback" ;
+ public static final String paramForceAccept = "force-accept" ; // Force the accept header at the last moment
+ public static final String paramTimeout = "timeout" ;
+
+ public static final String paramUpdate = "update" ;
+ public static final String paramRequest = "request" ;
+ public static final String paramUsingGraphURI = "using-graph-uri" ;
+ public static final String paramUsingNamedGraphURI = "using-named-graph-uri" ;
+
+ public static final String METHOD_DELETE = "DELETE";
+ public static final String METHOD_HEAD = "HEAD";
+ public static final String METHOD_GET = "GET";
+ public static final String METHOD_OPTIONS = "OPTIONS";
+ public static final String METHOD_PATCH = "PATCH" ;
+ public static final String METHOD_POST = "POST";
+ public static final String METHOD_PUT = "PUT";
+ public static final String METHOD_TRACE = "TRACE";
+
+ public static final String HEADER_IFMODSINCE = "If-Modified-Since";
+ public static final String HEADER_LASTMOD = "Last-Modified";
+
+ // Names for services in the default configuration
+ public static final String ServiceQuery = "query" ;
+ public static final String ServiceQueryAlt = "sparql" ;
+ public static final String ServiceUpdate = "update" ;
+ public static final String ServiceData = "data" ;
+ public static final String ServiceUpload = "upload" ;
+ public static final String ServiceGeneralQuery = "/sparql" ;
+
+ // Posisble values of fields.
+ // TODO Pull in from results writer.
+ public static final String valueDefault = "default" ;
+
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/36855e1b/jena-fuseki/src/main/java/org/apache/jena/fuseki/Test.java
----------------------------------------------------------------------
diff --git a/jena-fuseki/src/main/java/org/apache/jena/fuseki/Test.java b/jena-fuseki/src/main/java/org/apache/jena/fuseki/Test.java
new file mode 100644
index 0000000..b4f5fed
--- /dev/null
+++ b/jena-fuseki/src/main/java/org/apache/jena/fuseki/Test.java
@@ -0,0 +1,25 @@
+/*
+ * 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;
+
+public class Test
+{
+ public static void init() { System.out.println("INIT called") ; }
+}
+