Skip to content

Commit

Permalink
Read many and read one
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul Sadauskas committed Jul 31, 2008
0 parents commit a7bef5b
Show file tree
Hide file tree
Showing 7 changed files with 339 additions and 0 deletions.
21 changes: 21 additions & 0 deletions MIT-LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Copyright (c) 2008 Absolute-Performance, Inc
Copyright (c) 2008 Peter Williams

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 changes: 7 additions & 0 deletions README.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# DataMapper: Abstract ReST Adapter

Copyright
---------

Copyright (c) 2008 Absolute Performance, Inc, Paul Sadauskas; released under the MIT License.

81 changes: 81 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
require 'rubygems'
require 'rake'
require 'rake/gempackagetask'
require 'rake/rdoctask'
require 'spec/rake/spectask'

desc 'Default: run unit tests.'
task :default => :spec

desc "Run all tests"
task :test => :spec

desc "Verify Resourceful against it's specs"
Spec::Rake::SpecTask.new(:spec) do |t|
t.libs << 'lib'
t.pattern = 'spec/**/*_spec.rb'
end

begin
gem 'yard', '>=0.2.3'
require 'yard'
desc 'Generate documentation for dm-abstract_rest_adapter.'
YARD::Rake::YardocTask.new do |t|
t.files = ['lib/**/*.rb', 'README']
end
rescue Exception
# install YARD to generate documentation
end

desc 'Removes all temporary files'
task :clean

##############################################################################
# Packaging & Installation
##############################################################################

DM_ABSTRACT_REST_ADAPTER_VERSION = "0.0.1"

windows = (PLATFORM =~ /win32|cygwin/) rescue nil

SUDO = windows ? "" : "sudo"

task :'dm-abstract_rest_adapter' => [:clean, :rdoc, :package]

spec = Gem::Specification.new do |s|
s.name = "dm-abstract_rest_adapter"
s.version = DM_ABSTRACT_REST_ADAPTER_VERSION
s.platform = Gem::Platform::RUBY
s.author = "Paul Sadauskas"
s.email = "psadauskas@gmail.com"
s.homepage = "https://github.com/paul/dm-abstract_rest_adapter/tree/master"
s.summary = "A generic DataMapper adapter for talking to ReST-based web servers."
s.description = s.summary
s.rubyforge_project = 'dm-abstract_rest_adapter'
s.require_path = "lib"
s.files = %w( MIT-LICENSE README.markdown Rakefile ) + Dir["{spec,lib}/**/*"]

# rdoc
s.has_rdoc = false

# Dependencies
s.add_dependency "dm-abstract_rest_adapter"
s.add_dependency "rspec"

s.required_ruby_version = ">= 1.8.6"
end

Rake::GemPackageTask.new(spec) do |package|
package.gem_spec = spec
end

desc "Run :package and install the resulting .gem"
task :install => :package do
sh %{#{SUDO} gem install --local pkg/dm-abstract_rest_adapter-#{DM_ABSTRACT_REST_ADAPTER_VERSION}.gem --no-rdoc --no-ri}
end

desc "Run :clean and uninstall the .gem"
task :uninstall => :clean do
sh %{#{SUDO} gem uninstall dm-abstract_rest_adapter}
end

25 changes: 25 additions & 0 deletions lib/dm-types/uuid.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
require 'rubygems'
require 'uuidtools'

module DataMapper
module Types
class UUID < DataMapper::Type
primitive String

def self.load(value, property)
::UUID.parse(value)
end

def self.dump(value, property)
return nil if value.nil?
value.to_s
end

def self.typecast(value, property)
value.kind_of?(::UUID) ? value : load(value.to_s, property)
end
end
end
end


50 changes: 50 additions & 0 deletions lib/resourceful/ssbe_authenticator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
module Resourceful

class SSBEAuthenticator
require 'httpauth'
require 'addressable/uri'


attr_reader :username, :password, :realm, :domain, :challenge

def initialize(username, password)
@username, @password = username, password
@realm = 'SystemShepherd'
@domain = nil
end

def update_credentials(challenge_response)
@domain = Addressable::URI.parse(challenge_response.uri).host
@challenge = HTTPAuth::Digest::Challenge.from_header(challenge_response.header['WWW-Authenticate'].first)
end

def valid_for?(challenge_response)
return false unless challenge_header = challenge_response.header['WWW-Authenticate']
begin
challenge = HTTPAuth::Digest::Challenge.from_header(challenge_header.first)
rescue HTTPAuth::UnwellformedHeader
return false
end
challenge.realm == @realm
end

def can_handle?(request)
Addressable::URI.parse(request.uri).host == @domain
end

def add_credentials_to(request)
request.header['Authorization'] = credentials_for(request)
end

def credentials_for(request)
HTTPAuth::Digest::Credentials.from_challenge(@challenge,
:username => @username,
:password => @password,
:method => request.method.to_s.upcase,
:uri => Addressable::URI.parse(request.uri).path).to_header
end

end

end

126 changes: 126 additions & 0 deletions lib/ssbe_adapter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
require 'rubygems'
require 'resourceful'
require 'json'
gem 'dm-core', '>=0.9.3'

require 'pathname'
require Pathname(__FILE__).dirname + 'resourceful/ssbe_authenticator'
require Pathname(__FILE__).dirname + 'dm-types/uuid'

module DataMapper
module Adapters

class HttpAdapter < AbstractAdapter
attr_reader :http

def initialize(name, uri_or_options)
super

@http = Resourceful::HttpAccessor.new
end
end

class SsbeAdapter < HttpAdapter

def initialize(name, uri_or_options)
super

http.cache_manager = Resourceful::InMemoryCacheManager.new
http.logger = Resourceful::StdOutLogger.new
http.auth_manager.add_auth_handler Resourceful::SSBEAuthenticator.new('dev', 'dev')

service_descriptor_uri = uri_or_options[:service_descriptor_uri]
@service_descriptor = @http.resource(service_descriptor_uri).get.body
@service_descriptor = JSON.parse(@service_descriptor)
end

def read_many(query)
model = query.model
puts "Model:", query.inspect
service_type = model.service_type
resource_name = model.resource_name
parser = model.parser

unless model.resource
resource_descriptor_uri = @service_descriptor["items"].find { |i| i["service_type"] == service_type }["href"]
resource_descriptor = JSON.parse(@http.resource(resource_descriptor_uri).get.body)

resource_uri = resource_descriptor["resources"].find { |i| i["name"] == resource_name }["href"]
model.resource = @http.resource(resource_uri, :accept => parser.mime_type)
end

doc = parser.deserialize(model.resource.get.body)

Collection.new(query) do |collection|
doc['items'].each do |item|
collection.load(
query.fields.map { |prop| item[prop.field.to_s] }
)
end
end
end

def read_one(query)
uri = query.conditions.first[2]
parser = query.model.parser

resource = @http.resource(uri, :accept => parser.mime_type)

doc = parser.deserialize(resource.get.body)

query.model.load(query.fields.map { |prop| doc[prop.field.to_s] }, query)
end


class Parser

def self.mime_type(mime_type)
@@mime_type = mime_type
end

def mime_type
@@mime_type
end

end

class SSJParser < Parser
mime_type 'application/vnd.absolute-performance.sysshep+json'

def deserialize(body)
JSON.parse(body)
end

end

end


end

module Model
attr_reader :service_type, :resource_name, :parser
attr_accessor :resource

def set_service_type(uri_or_type)
@service_type = case uri_or_type
when String then uri_or_type
when :kernel
'http://systemshepherd.com/services/kernel'
else
raise "Unknown service type"
end
end

def set_resource_name(name)
@resource_name = name
end

def set_parser(parser)
@parser = parser
end

end

end

29 changes: 29 additions & 0 deletions test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
require 'rubygems'
require 'dm-core'
require 'dm-types'
require 'pathname'
require 'uuidtools'
require Pathname(__FILE__).dirname + 'lib/ssbe_adapter'

DataMapper.setup(:default, :adapter => :ssbe, :service_descriptor_uri => 'http://core.ssbe.localhost/service_descriptors')

class Client
include DataMapper::Resource
set_service_type :kernel
set_resource_name "AllClients"
set_parser DataMapper::Adapters::SsbeAdapter::SSJParser.new

property :name, String
property :href, URI, :key => true
property :id, UUID
property :longname, String
property :active, Boolean

end

clients = Client.all
puts clients.inspect

client = Client.get(clients.first.href)
puts client.inspect

0 comments on commit a7bef5b

Please sign in to comment.