Skip to content

Commit

Permalink
initial commit from rubyamf/current
Browse files Browse the repository at this point in the history
  • Loading branch information
jdtornow committed Feb 6, 2009
0 parents commit 7be5cca
Show file tree
Hide file tree
Showing 32 changed files with 3,240 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.DS_Store
285 changes: 285 additions & 0 deletions CHANGELOG

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
Copyright (c) 2007 Aaron Smith ([email protected])

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:

There is one exception to the above MIT license. WebORB may not use this code
base in any of their releases of WebORB for RoR.

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.
3 changes: 3 additions & 0 deletions README
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
(c) aaron smith, [email protected]
http://www.rubyamf.org
http://code.google.com/p/rubyamf
166 changes: 166 additions & 0 deletions app/actions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
require 'app/configuration'
module RubyAMF
module Actions
module Utils
include RubyAMF::VoHelper

def generate_acknowledge_object(message_id = nil, client_id = nil)
res = VoHash.new
res._explicitType = "flex.messaging.messages.AcknowledgeMessage"
res["messageId"] = rand_uuid
res["clientId"] = client_id||rand_uuid
res["destination"] = nil
res["body"] = nil
res["timeToLive"] = 0
res["timestamp"] = (String(Time.new) + '00')
res["headers"] = {}
res["correlationId"] = message_id
res
end

#going for speed with these UUID's not neccessarily unique in space and time continue - um, word
def rand_uuid
[8,4,4,4,12].map {|n| rand_hex_3(n)}.join('-').to_s
end

def rand_hex_3(l)
"%0#{l}x" % rand(1 << l*4)
end
end
#This sets up each body for processing
class PrepareAction
include RubyAMF::App
include RubyAMF::Actions::Utils
include RubyAMF::Configuration

def run(amfbody)
if RequestStore.amf_encoding == 'amf3' && #AMF3
(raw_body = amfbody.value[0]).is_a?(VoHash) &&
['flex.messaging.messages.RemotingMessage','flex.messaging.messages.CommandMessage'].include?(raw_body._explicitType)
case raw_body._explicitType
when 'flex.messaging.messages.RemotingMessage' #Flex Messaging setup
RequestStore.flex_messaging = true # only set RequestStore and ClassMappings when its a remoting message, not command message
ClassMappings.use_array_collection = !(ClassMappings.use_array_collection==false) # it will only set it to false if the user specifically sets use_array_collection to false
amfbody.special_handling = 'RemotingMessage'
amfbody.value = raw_body['body']
amfbody.set_meta('clientId', raw_body['clientId'])
amfbody.set_meta('messageId', raw_body['messageId'])
amfbody.target_uri = raw_body['source']
amfbody.service_method_name = raw_body['operation']
amfbody._explicitType = raw_body._explicitType
when 'flex.messaging.messages.CommandMessage' #it's a ping, don't process this body, and hence, dont set service uri information
if raw_body['operation'] == 5
amfbody.exec = false
amfbody.special_handling = 'Ping'
amfbody.set_meta('clientId', raw_body['clientId'])
amfbody.set_meta('messageId', raw_body['messageId'])
end
return # we don't want it to run set_service_uri_information
end
else
RequestStore.flex_messaging = false # ensure that array_collection is disabled
ClassMappings.use_array_collection = false
end

amfbody.set_service_uri_information!
end
end

#Invoke ActionController's process on the target controller action
class RailsInvokeAction
include RubyAMF::App
include RubyAMF::Exceptions
include RubyAMF::Configuration
include RubyAMF::Actions::Utils
include RubyAMF::VoHelper

def run(amfbody)
if amfbody.exec == false
if amfbody.special_handling == 'Ping'
amfbody.results = generate_acknowledge_object(amfbody.get_meta('messageId'), amfbody.get_meta('clientId')) #generate an empty acknowledge message here, no body needed for a ping
amfbody.success! #flag the success response
end
return
end
@amfbody = amfbody #store amfbody in member var
invoke
end

#invoke the service call
def invoke
begin
# RequestStore.available_services[@amfbody.service_class_name] ||=
@service = @amfbody.service_class_name.constantize.new #handle on service
rescue Exception => e
puts e.message
puts e.backtrace
raise RUBYAMFException.new(RUBYAMFException.UNDEFINED_OBJECT_REFERENCE_ERROR, "There was an error loading the service class #{@amfbody.service_class_name}")
end

if @service.private_methods.include?(@amfbody.service_method_name)
raise RUBYAMFException.new(RUBYAMFException.METHOD_ACCESS_ERROR, "The method {#{@amfbody.service_method_name}} in class {#{@amfbody.service_class_file_path}} is declared as private, it must be defined as public to access it.")
elsif !@service.public_methods.include?(@amfbody.service_method_name)
raise RUBYAMFException.new(RUBYAMFException.METHOD_UNDEFINED_METHOD_ERROR, "The method {#{@amfbody.service_method_name}} in class {#{@amfbody.service_class_file_path}} is not declared.")
end

#clone the request and response and alter it for the target controller/method
req = RequestStore.rails_request.clone
res = RequestStore.rails_response.clone

#change the request controller/action targets and tell the service to process. THIS IS THE VOODOO. SWEET!
controller = @amfbody.service_class_name.gsub("Controller","").underscore
action = @amfbody.service_method_name
req.parameters['controller'] = req.request_parameters['controller'] = req.path_parameters['controller'] = controller
req.parameters['action'] = req.request_parameters['action'] = req.path_parameters['action'] = action
req.env['PATH_INFO'] = req.env['REQUEST_PATH'] = req.env['REQUEST_URI'] = "#{controller}/#{action}"
req.env['HTTP_ACCEPT'] = 'application/x-amf,' + req.env['HTTP_ACCEPT'].to_s

#set conditional helper
@service.is_amf = true
@service.is_rubyamf = true

#process the request
rubyamf_params = @service.rubyamf_params = {}
if @amfbody.value && !@amfbody.value.empty?
@amfbody.value.each_with_index do |item,i|
rubyamf_params[i] = item
end
end

# put them by default into the parameter hash if they opt for it
rubyamf_params.each{|k,v| req.parameters[k] = v} if ParameterMappings.always_add_to_params

begin
#One last update of the parameters hash, this will map custom mappings to the hash, and will override any conflicting from above
ParameterMappings.update_request_parameters(@amfbody.service_class_name, @amfbody.service_method_name, req.parameters, rubyamf_params, @amfbody.value)
rescue Exception => e
raise RUBYAMFException.new(RUBYAMFException.PARAMETER_MAPPING_ERROR, "There was an error with your parameter mappings: {#{e.message}}")
end
@service.process(req, res)

#unset conditional helper
@service.is_amf = false
@service.is_rubyamf = false
@service.rubyamf_params = rubyamf_params # add the rubyamf_args into the controller to be accessed

result = RequestStore.render_amf_results

#handle FaultObjects
if result.class.to_s == 'FaultObject' #catch returned FaultObjects - use this check so we don't have to include the fault object module
e = RUBYAMFException.new(result['code'], result['message'])
e.payload = result['payload']
raise e
end

#amf3
@amfbody.results = result
if @amfbody.special_handling == 'RemotingMessage'
@wrapper = generate_acknowledge_object(@amfbody.get_meta('messageId'), @amfbody.get_meta('clientId'))
@wrapper["body"] = result
@amfbody.results = @wrapper
end
@amfbody.success! #set the success response uri flag (/onResult)
end
end
end
end
Loading

0 comments on commit 7be5cca

Please sign in to comment.