lib/cmis/connection.rb in cmis-ruby-0.3.1 vs lib/cmis/connection.rb in cmis-ruby-0.3.4

- old
+ new

@@ -1,137 +1,195 @@ require 'active_support' +require 'json' require 'typhoeus' require 'net/http/post/multipart' module CMIS class Connection - def initialize(service_url, username, password, headers) @service_url = service_url @username = username @password = password @headers = headers @url_cache = {} end def execute!(params = {}, options = {}) - options.stringify_keys! - query = options['query'] || {} - headers = @headers.merge(options['headers'] || {}) + query, headers = parse_options(options) - url = get_url(params.delete(:repositoryId), params[:objectId]) + Request.new(service_url: @service_url, + url_cache: @url_cache, + params: params, + query: query, + headers: headers, + username: @username, + password: @password).run + end - params = transform_hash(params) + private - if params[:cmisaction] - method = params[:content] ? 'multipart_post' : 'post' - body = params - else - method = 'get' - body = nil - query.merge!(params) + def parse_options(options) + options.symbolize_keys! + query = options[:query] || {} + headers = @headers + headers.merge!(options[:headers]) if options[:headers] + [ query, headers ] + end + + class Request + def initialize(options) + @service_url = options[:service_url] + @url_cache = options[:url_cache] + @params = massage(options[:params]) + @repository_id = @params.delete(:repositoryId) + @query = options[:query] + @headers = options[:headers] + @username = options[:username] + @password = options[:password] end - response = perform_request(method: method, url: url, - body: body, query: query, headers: headers) - - content_type = if response.respond_to?(:content_type) - response.content_type - else - response.headers['Content-Type'] + def run + case method + when 'get' + typhoeus_request + when 'post' + typhoeus_request + when 'multipart_post' + multipart_post + end end - result = response.body - result = JSON.parse(result) if content_type =~ /application\/json/ - result = result.with_indifferent_access if result.is_a? Hash + private - check_for_exception!(response.code.to_i, result) + def typhoeus_request + options = { + method: method, + body: body, + params: query, + headers: @headers, + followlocation: true + } + options[:userpwd] = "#{@username}:#{@password}" if @username + response = Typhoeus::Request.new(url, options).run + Response.new(response.headers['Content-Type'], response.body).parse! + end - result - end + def multipart_post + uri = URI.parse(url) + req = Net::HTTP::Post::Multipart.new(uri.path, body) + @headers.each { |key, value| req[key] = value } + req.basic_auth @username, @password if @username + opts = if uri.scheme == 'https' + { use_ssl: true , verify_mode: OpenSSL::SSL::VERIFY_NONE } + else + {} + end + Net::HTTP.start(uri.host, uri.port, opts) do |http| + response = http.request(req) + Response.new(response['Content-Type'], response.body).parse! + end + end - private - - def check_for_exception!(code, result) - unless (200...300).include?(code) - if result.is_a?(Hash) && result['exception'] - exception_class = "CMIS::Exceptions::#{result['exception'].camelize}" - raise exception_class.constantize, "#{result['message']}" + def url + if @repository_id.nil? + @service_url + else + urls = repository_urls(@repository_id) + if @params[:objectId] + urls[:root_folder_url] + else + urls[:repository_url] + end end end - end - def get_url(repository_id, cmis_object_id) - if repository_id.nil? - @service_url - else - urls = repository_urls(repository_id) - if cmis_object_id - urls[:root_folder_url] + def method + if @params[:cmisaction] + if @params[:content] + 'multipart_post' + else + 'post' + end else - urls[:repository_url] + 'get' end end - end - def repository_urls(repository_id) - if @url_cache[repository_id].nil? - repository_infos = JSON.parse(perform_request(url: @service_url).body) - raise Exceptions::ObjectNotFound, "repositoryId: #{repository_id}" unless repository_infos.has_key?(repository_id) - repository_info = repository_infos[repository_id] - @url_cache[repository_id] = { repository_url: repository_info['repositoryUrl'], - root_folder_url: repository_info['rootFolderUrl'] } + def body + @params if @params[:cmisaction] end - @url_cache[repository_id] - end - def transform_hash(hash) - hash.reject! { |_, v| v.nil? } - - if content_hash = hash[:content] - hash[:content] = UploadIO.new(content_hash[:stream], content_hash[:mime_type], content_hash[:filename]) + def query + if @params[:cmisaction] + @query + else + @params.merge(@query) + end end - if props = hash.delete(:properties) - props.each_with_index do |(id, value), index| - value = value.to_time if value.is_a?(Date) or value.is_a?(DateTime) - value = (value.to_f * 1000).to_i if value.is_a?(Time) - if value.is_a?(Array) - hash.merge!("propertyId[#{index}]" => id) - value.each_with_index do |v, idx| - hash.merge!("propertyValue[#{index}][#{idx}]" => value[idx]) + # TODO: Extract functionality + def massage(hash) + hash.compact + + if content_hash = hash[:content] + hash[:content] = UploadIO.new(content_hash[:stream], + content_hash[:mime_type], + content_hash[:filename]) + end + + if props = hash.delete(:properties) + props.each_with_index do |(id, value), index| + value = value.to_time if value.is_a?(Date) or value.is_a?(DateTime) + value = (value.to_f * 1000).to_i if value.is_a?(Time) + if value.is_a?(Array) + hash.merge!("propertyId[#{index}]" => id) + value.each_with_index do |v, idx| + hash.merge!("propertyValue[#{index}][#{idx}]" => value[idx]) + end + else + hash.merge!("propertyId[#{index}]" => id, + "propertyValue[#{index}]" => value) end - else - hash.merge!("propertyId[#{index}]" => id, - "propertyValue[#{index}]" => value) end end + hash end - hash - end - def perform_request(options) - if options[:method] == 'multipart_post' - multipart_post(options) - else - typhoeus_request(options) + def repository_urls(repository_id) + if @url_cache[repository_id].nil? + + options = { method: 'get' } + options[:userpwd] = "#{@username}:#{@password}" if @username + response = Typhoeus::Request.new(@service_url, options).run + repository_infos = JSON.parse(response.body) + + unless repository_infos.has_key?(repository_id) + raise Exceptions::ObjectNotFound, "repositoryId: #{repository_id}" + end + + repository_info = repository_infos[repository_id] + @url_cache[repository_id] = { repository_url: repository_info['repositoryUrl'], + root_folder_url: repository_info['rootFolderUrl'] } + end + @url_cache[repository_id] end end - def typhoeus_request(options) - options[:params] = options.delete(:query) - options[:followlocation] = true - options[:userpwd] = "#{@username}:#{@password}" if @username - Typhoeus::Request.new(options.delete(:url), options).run - end + class Response + def initialize(content_type, body) + @content_type = content_type + @body = body + end - def multipart_post(options) - url = URI.parse(options[:url]) - req = Net::HTTP::Post::Multipart.new(url.path, options[:body]) - options[:headers].each { |key, value| req[key] = value } - req.basic_auth @username, @password if @username - opts = url.scheme == 'https' ? { use_ssl: true , verify_mode: OpenSSL::SSL::VERIFY_NONE } : {} - Net::HTTP.start(url.host, url.port, opts) { |http| http.request(req) } + def parse! + return @body unless @content_type =~ /application\/json/ + + result = JSON.parse(@body) + if result.is_a?(Hash) && ex = result['exception'] + raise "CMIS::Exceptions::#{ex.camelize}".constantize, result['message'] + end + result.with_indifferent_access + end end end end