summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrautenberg <rautenberg@in-silico.ch>2012-05-10 09:36:01 +0200
committerrautenberg <rautenberg@in-silico.ch>2012-05-10 09:36:01 +0200
commitca0ac867535d38c0f6e59332b85c8da6f23f372d (patch)
tree01021be1437190889b61507c2b66adc0b5fe5d2a
parente523a4bda0507d3e0b17e50e39e873b0c92d3239 (diff)
parentc7822fc4c461ab6d10649a5964ecb10f7f4c54d7 (diff)
Merge branch 'development' of github.com:opentox/opentox-server into development
-rw-r--r--.gitignore2
-rw-r--r--VERSION2
-rw-r--r--lib/4store.rb76
-rw-r--r--lib/authorization-helper.rb5
-rw-r--r--lib/opentox.rb44
-rw-r--r--opentox-server.gemspec3
6 files changed, 76 insertions, 56 deletions
diff --git a/.gitignore b/.gitignore
index 5a5fa8c..c9daf01 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,5 @@
+Gemfile.lock
*.gem
.bundle
pkg/*
-Gemfile.lock
*~
diff --git a/VERSION b/VERSION
index bcab45a..3eefcb9 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.0.3
+1.0.0
diff --git a/lib/4store.rb b/lib/4store.rb
index b20af00..f2e3fcd 100644
--- a/lib/4store.rb
+++ b/lib/4store.rb
@@ -2,8 +2,6 @@ module OpenTox
module Backend
class FourStore
- #TODO: catch 4store errors
-
@@mime_format = {
"application/rdf+xml" => :rdfxml,
"text/turtle" => :turtle,
@@ -14,8 +12,8 @@ module OpenTox
#"text/x-yaml" => :yaml,
#"text/yaml" => :yaml,
"text/html" => :html,
- # TODO: compression, forms
#/sparql/ => :sparql #removed to prevent sparql injections
+ 'application/sparql-results+xml' => :sparql
}
@@format_mime = {
@@ -26,19 +24,19 @@ module OpenTox
#:json => "application/json",
#:yaml => "text/yaml",
:html => "text/html",
+ :sparql => 'application/sparql-results+xml'
}
- @@accept_formats = [:rdfxml, :turtle, :ntriples, :uri_list, :html] #, :json, :yaml]
+ @@accept_formats = [:rdfxml, :turtle, :ntriples, :uri_list, :html, :sparql] #, :json, :yaml]
@@content_type_formats = [:rdfxml, :turtle, :ntriples]#, :json, :yaml]
- @@rdf_formats = [:rdfxml, :turtle, :ntriples]
def self.list mime_type
mime_type = "text/html" if mime_type.match(%r{\*/\*})
bad_request_error "'#{mime_type}' is not a supported mime type. Please specify one of #{@@accept_formats.collect{|f| @@format_mime[f]}.join(", ")} in the Accept Header." unless @@accept_formats.include? @@mime_format[mime_type]
if mime_type =~ /json|yaml|uri-list/
- sparql = "SELECT ?s WHERE {?s <#{RDF.type}> <#{@@class}>. }"
+ sparql = "SELECT DISTINCT ?g WHERE {GRAPH ?g {?s ?p ?o} }"
elsif mime_type =~ /turtle|html|rdf|plain/
- sparql = "CONSTRUCT {?s ?p ?o.} WHERE {?s <#{RDF.type}> <#{@@class}>; ?p ?o. }"
+ sparql = "CONSTRUCT {?s ?p ?o.} WHERE {?s <#{RDF.type}> <#{klass}>; ?p ?o. }"
end
query sparql, mime_type
end
@@ -46,19 +44,22 @@ module OpenTox
def self.get uri, mime_type
mime_type = "text/html" if mime_type.match(%r{\*/\*})
bad_request_error "'#{mime_type}' is not a supported mime type. Please specify one of #{@@accept_formats.collect{|f| @@format_mime[f]}.join(", ")} in the Accept Header." unless @@accept_formats.include? @@mime_format[mime_type]
- not_found_error "#{uri} not found." unless list("text/uri-list").split("\n").include?(uri)
+ not_found_error "#{uri} not found." unless available? uri
sparql = "CONSTRUCT {?s ?p ?o.} FROM <#{uri}> WHERE { ?s ?p ?o. }"
query sparql, mime_type
end
def self.post uri, rdf, mime_type
- bad_request_error "'#{mime_type}' is not a supported content type. Please use one of #{@@content_type_formats.collect{|f| @@format_mime[f]}.join(", ")}." unless @@content_type_formats.include? @@mime_format[mime_type]
- rdf = convert rdf, @@mime_format[mime_type], :ntriples#, uri unless mime_type == 'text/plain'
+ bad_request_error "'#{mime_type}' is not a supported content type. Please use one of #{@@content_type_formats.collect{|f| @@format_mime[f]}.join(", ")}." unless @@content_type_formats.include? @@mime_format[mime_type] or mime_type == "multipart/form-data"
+ rdf = convert rdf, @@mime_format[mime_type], :ntriples
+ rdf = "<#{uri}> <#{RDF.type}> <#{klass}>." unless rdf # create empty resource
+ rdf += "\n<#{uri}> <#{RDF::DC.date}> \"#{DateTime.now}\"." unless rdf.match(%r{#{RDF::DC.date}})
RestClient.post File.join(four_store_uri,"data")+"/", :data => rdf, :graph => uri, "mime-type" => "application/x-turtle" # not very consistent in 4store
end
def self.put uri, rdf, mime_type, skip_rewrite=false
bad_request_error "'#{mime_type}' is not a supported content type. Please use one of #{@@content_type_formats.collect{|f| @@format_mime[f]}.join(", ")}." unless @@content_type_formats.include? @@mime_format[mime_type]
+ bad_request_error "Reqest body empty." unless rdf # create empty resource
uuid = uri.sub(/\/$/,'').split('/').last
bad_request_error "'#{uri}' is not a valid URI." unless uuid =~ /[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/
if !skip_rewrite
@@ -66,19 +67,23 @@ module OpenTox
elsif mime_type != "text/plain" # ntriples are not converted
rdf = convert rdf, @@mime_format[mime_type], :ntriples
end
- rdf = "<#{uri}> <#{RDF.type}> <#{@@class}>." unless rdf # create empty resource
RestClient.put File.join(four_store_uri,"data",uri), rdf, :content_type => "application/x-turtle" # content-type not very consistent in 4store
end
def self.delete uri
- RestClientWrapper.delete data_uri uri
+ RestClientWrapper.delete data_uri(uri)
+ end
+
+ def self.update sparql
+ RestClient.post(update_uri, :update => sparql )
end
def self.query sparql, mime_type
if sparql =~ /SELECT/i
- xml = RestClient.post File.join(four_store_uri,"sparql")+"/", :query => sparql
- #TODO request tab delimited format to speed up parsing
- list = parse_sparql_xml_results(xml).collect{|hash| hash["s"]}
+ return RestClient.get(sparql_uri, :params => { :query => sparql }, :accept => mime_type).body.gsub(/<|>/,'').split("\n") if mime_type == 'application/sparql-results+xml'
+ list = RestClient.get(sparql_uri, :params => { :query => sparql }, :accept => "text/plain").body.gsub(/<|>/,'').split("\n")
+ list.shift
+ return list unless mime_type
case mime_type
when /json/
return list.to_json
@@ -98,7 +103,7 @@ module OpenTox
when /html/
# TODO: fix and improve
html = "<html><body>"
- html += convert(nt,:ntriples, :turtle).gsub(%r{<(.*)>},'&lt;<a href="\1">\1</a>&gt;').gsub(/\n/,'<br/>')#.gsub(/ /,'&nbsp;')
+ html += convert(nt,:ntriples, :turtle).gsub(%r{<(.*)>},'&lt;<a href="\1">\1</a>&gt;').gsub(/\n/,'<br/>')
html += "</body></html>"
return html
when "application/rdf+xml"
@@ -112,6 +117,17 @@ module OpenTox
private
+ def self.klass
+ RDF::OT[SERVICE.capitalize]
+ end
+
+ def self.available? uri
+ #sparql = "SELECT DISTINCT ?s WHERE {GRAPH <#{uri}> {?s ?p ?o} }"
+ sparql = "SELECT DISTINCT ?s WHERE {GRAPH <#{uri}> {?s <#{RDF.type}> <#{klass}>} }"
+ r = query(sparql, nil)
+ r.size == 1 and r.first == uri
+ end
+
def self.convert rdf_string, input_format, output_format, rewrite_uri=nil
rewrite_uri ? serialize(parse_and_rewrite_uri(rdf_string,input_format, rewrite_uri), output_format) : serialize(parse(rdf_string,input_format), output_format)
end
@@ -122,7 +138,7 @@ module OpenTox
statements = [] # use array instead of graph for performance reasons
RDF::Reader.for(format).new(string) do |reader|
reader.each_statement do |statement|
- subject = statement.subject if statement.predicate == RDF.type and statement.object == @@class
+ subject = statement.subject if statement.predicate == RDF.type and statement.object == klass
statements << statement
end
end
@@ -144,8 +160,9 @@ module OpenTox
def self.serialize rdf, format
if format == :turtle # prefixes seen to need RDF::N3
- # TODO add prefixes
- string = RDF::N3::Writer.for(format).buffer(:prefixes => {:ot => "http://www.opentox.org/api/1.2#"}) do |writer|
+ prefixes = {:rdf => "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"}
+ ['OT', 'DC', 'XSD'].each{|p| prefixes[p.downcase.to_sym] = eval("RDF::#{p}.to_s") }
+ string = RDF::N3::Writer.for(format).buffer(:prefixes => prefixes) do |writer|
rdf.each{|statement| writer << statement}
end
else
@@ -157,6 +174,7 @@ module OpenTox
end
def self.four_store_uri
+ # TODO remove credentials from URI 9security risk in tasks)
$four_store[:uri].sub(%r{//},"//#{$four_store[:user]}:#{$four_store[:password]}@")
end
@@ -164,24 +182,12 @@ module OpenTox
File.join(four_store_uri, "sparql") + '/'
end
- def self.data_uri uri
- File.join(four_store_uri, "data","?graph=#{uri}")
+ def self.update_uri
+ File.join(four_store_uri, "update") + '/'
end
- def self.parse_sparql_xml_results(xml)
- results = []
- doc = REXML::Document.new(REXML::Source.new(xml))
- doc.elements.each("*/results/result") do |result|
- result_hash = {}
- result.elements.each do |binding|
- key = binding.attributes["name"]
- value = binding.elements[1].text
- type = binding.elements[1].name
- result_hash[key] = value
- end
- results.push result_hash
- end
- results
+ def self.data_uri uri
+ File.join(four_store_uri, "data","?graph=#{uri}")
end
end
diff --git a/lib/authorization-helper.rb b/lib/authorization-helper.rb
index 4b534a5..46834c6 100644
--- a/lib/authorization-helper.rb
+++ b/lib/authorization-helper.rb
@@ -78,7 +78,8 @@ module OpenTox
uri = uri.sub(" ", "%20") #dirty hacks => to fix
uri = uri[0,uri.index("InChI=")] if uri.index("InChI=")
out = URI.parse(uri)
- out.path = out.path[0, out.path.length - (out.path.reverse.rindex(/\/{1}\d+\/{1}/))] if out.path.index(/\/{1}\d+\/{1}/) #cuts after /id/ for a&a
+ out.path = out.path[0, out.path.length - (out.path.reverse.rindex(/\/{1}\d+\/{1}/))] if out.path.index(/\/{1}\d+\/{1}/) #cuts after numeric /id/ for a&a
+ out.path.sub! /(\/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}).*/, '\1' # cut after uuid
out.path = out.path.split('.').first #cut extension
port = (out.scheme=="http" && out.port==80)||(out.scheme=="https" && out.port==443) ? "" : ":#{out.port.to_s}"
"#{out.scheme}://#{out.host}#{port}#{out.path.chomp("/")}" #"
@@ -128,4 +129,4 @@ module OpenTox
end
end
end
-end \ No newline at end of file
+end
diff --git a/lib/opentox.rb b/lib/opentox.rb
index 7a73d66..31a6e82 100644
--- a/lib/opentox.rb
+++ b/lib/opentox.rb
@@ -1,7 +1,8 @@
require 'sinatra/base'
-require "sinatra/reloader"
-
ENV["RACK_ENV"] ||= "production"
+require "sinatra/reloader" if ENV["RACK_ENV"] == "development"
+require File.join(ENV["HOME"],".opentox","config","#{SERVICE}.rb")
+
logfile = File.join(ENV['HOME'], ".opentox","log","#{ENV["RACK_ENV"]}.log")
$logger = OTLogger.new(logfile)
@@ -23,6 +24,19 @@ module OpenTox
before do
request.content_type ? response['Content-Type'] = request.content_type : response['Content-Type'] = request.env['HTTP_ACCEPT']
+ parse_input if request.request_method =~ /POST|PUT/
+ end
+
+ helpers do
+ def parse_input
+ if request.content_type == "multipart/form-data"
+ @body = File.read(params[:file][:tempfile])
+ @content_type = params[:file][:type]
+ else
+ @body = request.body.read
+ @content_type = request.content_type
+ end
+ end
end
# Attention: Error within tasks are catched by Task.create
@@ -43,38 +57,36 @@ module OpenTox
# see http://jcalcote.wordpress.com/2008/10/16/put-or-post-the-rest-of-the-story/
# Get a list of objects at the server
- get '/?' do
+ get "/#{SERVICE}/?" do
FourStore.list request.env['HTTP_ACCEPT']
end
# Create a new resource
- # TODO: handle multipart uploads
- post '/?' do
- rdf = request.body.read
- uri = uri(SecureRandom.uuid)
- FourStore.put(uri, rdf, request.content_type) unless rdf == ''
+ post "/#{SERVICE}/?" do
+ uri = uri("/#{SERVICE}/#{SecureRandom.uuid}")
+ FourStore.put(uri, @body, @content_type)
response['Content-Type'] = "text/uri-list"
uri
end
# Get resource representation
- get '/:id/?' do
- FourStore.get(uri("/#{params[:id]}"), request.env['HTTP_ACCEPT'])
+ get "/#{SERVICE}/:id/?" do
+ FourStore.get(uri("/#{SERVICE}/#{params[:id]}"), request.env['HTTP_ACCEPT'])
end
# Modify (i.e. add rdf statments to) a resource
- post '/:id/?' do
- FourStore.post uri("/#{params[:id]}"), request.body.read, request.content_type
+ post "/#{SERVICE}/:id/?" do
+ FourStore.post uri("/#{SERVICE}/#{params[:id]}"), @body, @content_type
end
# Create or updata a resource
- put '/:id/?' do
- FourStore.put uri("/#{params[:id]}"), request.body.read, request.content_type
+ put "/#{SERVICE}/:id/?" do
+ FourStore.put uri("/#{SERVICE}/#{params[:id]}"), @body, @content_type
end
# Delete a resource
- delete '/:id/?' do
- FourStore.delete uri("/#{params[:id]}")
+ delete "/#{SERVICE}/:id/?" do
+ FourStore.delete uri("/#{SERVICE}/#{params[:id]}")
end
end
diff --git a/opentox-server.gemspec b/opentox-server.gemspec
index 1074fbf..199a67a 100644
--- a/opentox-server.gemspec
+++ b/opentox-server.gemspec
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
Gem::Specification.new do |s|
s.name = "opentox-server"
- s.version = "0.0.3"
+ s.version = File.read("./VERSION")
s.authors = ["Christoph Helma, Martin Guetlein, Andreas Maunz, Micha Rautenberg, David Vorgrimmler"]
s.email = ["helma@in-silico.ch"]
s.homepage = "http://github.com/opentox/opentox-server"
@@ -25,6 +25,7 @@ Gem::Specification.new do |s|
s.add_runtime_dependency 'sinatra'
s.add_runtime_dependency 'sinatra-contrib'
s.add_runtime_dependency 'roo'
+ s.add_runtime_dependency 'spreadsheet', "= 0.6.8" # cannot load 0.7.0
s.add_runtime_dependency 'unicorn'
s.add_runtime_dependency 'rdf-n3'
end