adaptation 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +1 -0
- data/README +90 -0
- data/bin/about +5 -0
- data/bin/adaptation +19 -0
- data/bin/destroy +5 -0
- data/bin/generate +5 -0
- data/bin/mom +8 -0
- data/bin/subscribe +8 -0
- data/configs/boot.rb +10 -0
- data/configs/databases/mysql.yml +48 -0
- data/configs/empty.log +0 -0
- data/configs/mom.yml +8 -0
- data/dispatches/dispatch.rb +8 -0
- data/dispatches/publish.rb +11 -0
- data/doc/README_FOR_APP +2 -0
- data/fresh_rakefile +10 -0
- data/helpers/publish.rb +24 -0
- data/helpers/test_helper.rb +6 -0
- data/lib/adaptation/adaptor.rb +32 -0
- data/lib/adaptation/base.rb +70 -0
- data/lib/adaptation/message.rb +328 -0
- data/lib/adaptation/mom.rb +70 -0
- data/lib/adaptation/oapdaemon.rb +38 -0
- data/lib/adaptation/test/test_help.rb +282 -0
- data/lib/adaptation/version.rb +9 -0
- data/lib/adaptation.rb +5 -0
- data/lib/commands/about.rb +3 -0
- data/lib/commands/destroy.rb +6 -0
- data/lib/commands/generate.rb +6 -0
- data/lib/commands/mom.rb +8 -0
- data/lib/commands/subscribe.rb +11 -0
- data/lib/commands.rb +17 -0
- data/lib/rails_generator/base.rb +262 -0
- data/lib/rails_generator/commands.rb +582 -0
- data/lib/rails_generator/generated_attribute.rb +42 -0
- data/lib/rails_generator/generators/applications/app/USAGE +13 -0
- data/lib/rails_generator/generators/applications/app/app_generator.rb +133 -0
- data/lib/rails_generator/generators/components/adaptor/USAGE +25 -0
- data/lib/rails_generator/generators/components/adaptor/adaptor_generator.rb +21 -0
- data/lib/rails_generator/generators/components/adaptor/templates/adaptor.rb +6 -0
- data/lib/rails_generator/generators/components/adaptor/templates/functional_test.rb +16 -0
- data/lib/rails_generator/generators/components/message/USAGE +16 -0
- data/lib/rails_generator/generators/components/message/message_generator.rb +28 -0
- data/lib/rails_generator/generators/components/message/templates/fixtures.xml +3 -0
- data/lib/rails_generator/generators/components/message/templates/message.rb +2 -0
- data/lib/rails_generator/generators/components/message/templates/unit_test.rb +25 -0
- data/lib/rails_generator/generators/components/model/USAGE +26 -0
- data/lib/rails_generator/generators/components/model/model_generator.rb +38 -0
- data/lib/rails_generator/generators/components/model/templates/fixtures.yml +11 -0
- data/lib/rails_generator/generators/components/model/templates/migration.rb +13 -0
- data/lib/rails_generator/generators/components/model/templates/model.rb +2 -0
- data/lib/rails_generator/generators/components/model/templates/unit_test.rb +10 -0
- data/lib/rails_generator/lookup.rb +209 -0
- data/lib/rails_generator/manifest.rb +53 -0
- data/lib/rails_generator/options.rb +143 -0
- data/lib/rails_generator/scripts/destroy.rb +7 -0
- data/lib/rails_generator/scripts/generate.rb +7 -0
- data/lib/rails_generator/scripts/update.rb +12 -0
- data/lib/rails_generator/scripts.rb +85 -0
- data/lib/rails_generator/simple_logger.rb +46 -0
- data/lib/rails_generator/spec.rb +44 -0
- data/lib/rails_generator.rb +43 -0
- data/lib/ruby_version_check.rb +17 -0
- metadata +142 -0
data/CHANGELOG
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
* 0.0.1 (18 June 2007)
|
data/README
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
== Welcome to Adaptation
|
2
|
+
|
3
|
+
Adaptation is a framework that tries to facilitate data interchange
|
4
|
+
between applications. Applications send and receive xml messages through
|
5
|
+
a message oriented middleware using a publish/subscribe pattern:
|
6
|
+
|
7
|
+
Application A publishes messages on topic A, and all applications interested
|
8
|
+
on reading messages from A subscribe to its topic.
|
9
|
+
|
10
|
+
Adaptation focuses on facilitate building _adaptors_. _adaptors_ are programs
|
11
|
+
that are executed for an application subscribed to a topic, when a message is
|
12
|
+
received on that topic.
|
13
|
+
|
14
|
+
_adaptors_ are built in a similar way that web apps are built using
|
15
|
+
the Ruby on Rails framework. This way adaptation uses a nice pattern
|
16
|
+
of separation between data input/output and logic. When building an
|
17
|
+
_adaptor_, logic will be stored under __Adaptors__ (in Rails these would
|
18
|
+
be Controllers) , and xml data interaction with the middleware will be
|
19
|
+
performed by a __Message__. __adaptors__ also can use ActiveRecord based
|
20
|
+
models for data interaction with applications database, like Rails does, if
|
21
|
+
adapting a database-backed application.
|
22
|
+
|
23
|
+
|
24
|
+
== Getting started
|
25
|
+
|
26
|
+
1. At the command prompt, start a new adaptation adaptor using the adaptation command
|
27
|
+
and your adaptor name. Ex: adaptation myadaptor
|
28
|
+
This will generate a an adaptor file tree.
|
29
|
+
2. If no message oriented middleware has been alreay set, change directory into myadaptor
|
30
|
+
and start the mom (message oriented middleware):
|
31
|
+
<tt>script/mom</tt>
|
32
|
+
This will start a mom in localhost (default), listening on port 8080 (default).
|
33
|
+
3. Subscribe your adaptor to the mom, so it will be executed when a message is received on
|
34
|
+
a topic your adaaptor is interested in:
|
35
|
+
<tt>script/subscribe</tt>
|
36
|
+
By default this will try to subscribe to a mom listening on localhost:8080, using port
|
37
|
+
8081 to subscribe. These values can be changed editing <tt>config/mom.yml</tt>. In mom.yml
|
38
|
+
you can also specify wich topics your adaptor is interested in.
|
39
|
+
4. Start developing your adaptor, probably generating __Adaptors__, __Messages__ and __Models__.
|
40
|
+
|
41
|
+
|
42
|
+
== Moms
|
43
|
+
|
44
|
+
By default, Adaptation will try to use druby to execute the built-in Ruby mom. This
|
45
|
+
mom is suitable for development, but not for production. For a production environment
|
46
|
+
a more stable solution like Xmlblaster should be chosen.
|
47
|
+
|
48
|
+
|
49
|
+
== Description of contents
|
50
|
+
|
51
|
+
app
|
52
|
+
Holds all the code that's specific to this particular adaptor.
|
53
|
+
|
54
|
+
app/adaptors
|
55
|
+
Holds adaptors that should be named like messagename_adaptor.rb for
|
56
|
+
automated mapping. All adaptors should descend from Adaptation::Adaptor.
|
57
|
+
|
58
|
+
app/messages
|
59
|
+
Holds messages that should be named like messagename.rb.
|
60
|
+
Messages descend from Adaptation::Message.
|
61
|
+
|
62
|
+
app/models
|
63
|
+
Holds models that should be named like post.rb.
|
64
|
+
Most models will descend from ActiveRecord::Base.
|
65
|
+
|
66
|
+
config
|
67
|
+
Configuration files for the Adaptation environment, the mom, the adapted application,
|
68
|
+
the database, and other dependencies.
|
69
|
+
|
70
|
+
db
|
71
|
+
Contains database related scripts.
|
72
|
+
|
73
|
+
doc
|
74
|
+
This directory is where your adaptor documentation will be stored.
|
75
|
+
|
76
|
+
lib
|
77
|
+
Application specific libraries. Basically, any kind of custom code that doesn't
|
78
|
+
belong under adaptors, models, or messages.
|
79
|
+
|
80
|
+
public
|
81
|
+
The directory available for the calling the adaptor and for utilities the adaptaed
|
82
|
+
application must be aware of, like a tool for publishing messages to the mom.
|
83
|
+
|
84
|
+
script
|
85
|
+
Helper scripts for automation and generation.
|
86
|
+
|
87
|
+
test
|
88
|
+
Unit and functional tests along with fixtures. When using the script/generate scripts, template
|
89
|
+
test files will be generated for you and placed in this directory.
|
90
|
+
|
data/bin/about
ADDED
data/bin/adaptation
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../lib/ruby_version_check'
|
2
|
+
Signal.trap("INT") { puts; exit }
|
3
|
+
|
4
|
+
require File.dirname(__FILE__) + '/../lib/adaptation/version'
|
5
|
+
if %w(--version -v).include? ARGV.first
|
6
|
+
puts "Adaptation #{Adaptation::VERSION::STRING}"
|
7
|
+
exit(0)
|
8
|
+
end
|
9
|
+
|
10
|
+
# freeze = ARGV.any? { |option| %w(--freeze -f).include?(option) }
|
11
|
+
app_path = ARGV.first
|
12
|
+
|
13
|
+
require File.dirname(__FILE__) + '/../lib/rails_generator'
|
14
|
+
|
15
|
+
require 'rails_generator/scripts/generate'
|
16
|
+
Rails::Generator::Base.use_application_sources!
|
17
|
+
Rails::Generator::Scripts::Generate.new.run(ARGV, :generator => 'app')
|
18
|
+
|
19
|
+
# Dir.chdir(app_path) { `rake rails:freeze:gems`; puts "froze" } if freeze
|
data/bin/destroy
ADDED
data/bin/generate
ADDED
data/bin/mom
ADDED
data/bin/subscribe
ADDED
data/configs/boot.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# Don't change this file. Configuration is done in config/environment.rb and config/environments/*.rb
|
2
|
+
|
3
|
+
unless defined?(RAILS_ROOT)
|
4
|
+
root_path = File.join(File.dirname(__FILE__), '..')
|
5
|
+
unless RUBY_PLATFORM =~ /mswin32/
|
6
|
+
require 'pathname'
|
7
|
+
root_path = Pathname.new(root_path).cleanpath(true).to_s
|
8
|
+
end
|
9
|
+
RAILS_ROOT = root_path
|
10
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# MySQL (default setup). Versions 4.1 and 5.0 are recommended.
|
2
|
+
#
|
3
|
+
# Install the MySQL driver:
|
4
|
+
# gem install mysql
|
5
|
+
# On MacOS X:
|
6
|
+
# gem install mysql -- --include=/usr/local/lib
|
7
|
+
# On Windows:
|
8
|
+
# gem install mysql
|
9
|
+
# Choose the win32 build.
|
10
|
+
# Install MySQL and put its /bin directory on your path.
|
11
|
+
#
|
12
|
+
# And be sure to use new-style password hashing:
|
13
|
+
# http://dev.mysql.com/doc/refman/5.0/en/old-client.html
|
14
|
+
development:
|
15
|
+
adapter: mysql
|
16
|
+
database: <%= app_name %>_development
|
17
|
+
username: root
|
18
|
+
password:
|
19
|
+
<% if socket -%>
|
20
|
+
socket: <%= socket %>
|
21
|
+
<% else -%>
|
22
|
+
host: localhost
|
23
|
+
<% end -%>
|
24
|
+
|
25
|
+
# Warning: The database defined as 'test' will be erased and
|
26
|
+
# re-generated from your development database when you run 'rake'.
|
27
|
+
# Do not set this db to the same as development or production.
|
28
|
+
test:
|
29
|
+
adapter: mysql
|
30
|
+
database: <%= app_name %>_test
|
31
|
+
username: root
|
32
|
+
password:
|
33
|
+
<% if socket -%>
|
34
|
+
socket: <%= socket %>
|
35
|
+
<% else -%>
|
36
|
+
host: localhost
|
37
|
+
<% end -%>
|
38
|
+
|
39
|
+
production:
|
40
|
+
adapter: mysql
|
41
|
+
database: <%= app_name %>_production
|
42
|
+
username: root
|
43
|
+
password:
|
44
|
+
<% if socket -%>
|
45
|
+
socket: <%= socket %>
|
46
|
+
<% else -%>
|
47
|
+
host: localhost
|
48
|
+
<% end -%>
|
data/configs/empty.log
ADDED
File without changes
|
data/configs/mom.yml
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
unless defined? ADAPTOR_ROOT
|
2
|
+
ADAPTOR_ROOT = File.expand_path(File.dirname(__FILE__) + '/..')
|
3
|
+
end
|
4
|
+
require 'drb'
|
5
|
+
require 'yaml'
|
6
|
+
|
7
|
+
config = YAML::load(File.open("#{ADAPTOR_ROOT}/config/mom.yml"))
|
8
|
+
mom_uri = "druby://#{config["mom"]["host"]}:#{config["mom"]["port"]}"
|
9
|
+
|
10
|
+
mom = DRbObject.new(nil, mom_uri)
|
11
|
+
mom.publish ARGV[1], ARGV[0]
|
data/doc/README_FOR_APP
ADDED
data/fresh_rakefile
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
2
|
+
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
3
|
+
|
4
|
+
require(File.join(File.dirname(__FILE__), 'config', 'boot'))
|
5
|
+
|
6
|
+
require 'rake'
|
7
|
+
require 'rake/testtask'
|
8
|
+
require 'rake/rdoctask'
|
9
|
+
|
10
|
+
require 'tasks/rails'
|
data/helpers/publish.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
class Adaptation::Adaptor
|
2
|
+
|
3
|
+
def publish *options
|
4
|
+
|
5
|
+
message_object = nil
|
6
|
+
if options.first.is_a?(Adaptation::Message)
|
7
|
+
message_object = options.first
|
8
|
+
elsif options.first.is_a?(String)
|
9
|
+
xml_message = options.first
|
10
|
+
message_type = xml_message[1..(xml_message.index(/(>| )/) - 1)]
|
11
|
+
message_class = get_class_object(message_type.capitalize)
|
12
|
+
message_object = message_class.to_object(xml_message)
|
13
|
+
end
|
14
|
+
|
15
|
+
mom = File.new(File.dirname(__FILE__) + '/mom.txt', "a")
|
16
|
+
mom.write("#{message_object.to_xml.to_s}\n")
|
17
|
+
mom.close
|
18
|
+
|
19
|
+
# configuration = {}
|
20
|
+
# configuration.update(options.pop) if options.last.is_a?(Hash)
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Adaptation
|
2
|
+
#= Adaptation::Adaptor -- The message processor
|
3
|
+
#
|
4
|
+
#Adaptation::Adaptor is the base class for those classes containing the logic to be executed when a message is read through the mom.
|
5
|
+
#
|
6
|
+
#Each class extending Adaptation::Adaptor must implement the _process_ function, using it as the main entry point for the logic to be executed when a message arrives. The name of the class extending Adaptation::Message associates the class with the one to be executed when a message arrives. Ie. if a message is received with a root element named _<hello>_, adaptation will search for a class extending Adaptation::Adaptor named _HelloAdaptor_.
|
7
|
+
#
|
8
|
+
#<i>Adaptation::Adaptors</i> (classes extending Adaptation::Adaptor) must be stored under <i>app/adaptors_name</i> in the adaptation file tree. This is done automatically when an adaptor is generated using adaptation built-in generator:
|
9
|
+
# script/generate adaptor hello
|
10
|
+
#
|
11
|
+
class Adaptor
|
12
|
+
|
13
|
+
def publish *options
|
14
|
+
message_object = nil
|
15
|
+
if options.first.is_a?(Message)
|
16
|
+
message_object = options.first
|
17
|
+
elsif options.first.is_a?(String)
|
18
|
+
xml_message = options.first
|
19
|
+
message_type = xml_message[1..(xml_message.index(/(>| )/) - 1)]
|
20
|
+
message_class = get_class_object(message_type.capitalize)
|
21
|
+
message_object = message_class.to_object(xml_message)
|
22
|
+
end
|
23
|
+
|
24
|
+
xml = message_object.to_xml
|
25
|
+
unless system("oappublish '#{$config["application"]}' '#{xml}'")
|
26
|
+
puts "Problem publishing: #{xml}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Adaptation
|
2
|
+
|
3
|
+
class Base
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
$environment = "development"
|
7
|
+
$config = YAML::load(File.open("config/settings.yml"))[$environment]
|
8
|
+
|
9
|
+
# require all adaptors
|
10
|
+
Dir["#{ADAPTOR_ROOT}/app/adaptors/*.rb"].each do |f|
|
11
|
+
require f
|
12
|
+
end
|
13
|
+
|
14
|
+
# require all messages
|
15
|
+
Dir["#{ADAPTOR_ROOT}/app/messages/*.rb"].reject{|f| f =~ /\/_/}.each do |f|
|
16
|
+
require f
|
17
|
+
end
|
18
|
+
|
19
|
+
# require all models
|
20
|
+
Dir["#{ADAPTOR_ROOT}/app/models/*.rb"].each do |f|
|
21
|
+
require f
|
22
|
+
end
|
23
|
+
|
24
|
+
# connect with database -> this could also be avoided?
|
25
|
+
if File.exists?("config/database.yml")
|
26
|
+
development_configurations = YAML::load(File.open("config/database.yml"))[$environment]
|
27
|
+
ActiveRecord::Base.configurations.update("development" => development_configurations)
|
28
|
+
ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations[$environment])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def process(xml_message)
|
33
|
+
# dirty method to discover the message type
|
34
|
+
message_type = xml_message[1..(xml_message.index(/(>| )/) - 1)]
|
35
|
+
|
36
|
+
begin
|
37
|
+
message_class = get_class_object(message_type.capitalize)
|
38
|
+
message = message_class.to_object(xml_message)
|
39
|
+
|
40
|
+
adaptor_class = get_class_object("#{message_type.capitalize}Adaptor")
|
41
|
+
adaptor = adaptor_class.new
|
42
|
+
rescue Exception => e
|
43
|
+
# message no implemented in this adaptor
|
44
|
+
return
|
45
|
+
end
|
46
|
+
|
47
|
+
unless message.check
|
48
|
+
puts "WARNING:Message doesn't validate!"
|
49
|
+
return
|
50
|
+
end
|
51
|
+
|
52
|
+
adaptor.process message
|
53
|
+
end
|
54
|
+
|
55
|
+
def get_class_object(searched_class)
|
56
|
+
class_object = nil
|
57
|
+
ObjectSpace.each_object(Class){|aClass|
|
58
|
+
class_object = aClass if aClass.to_s == searched_class
|
59
|
+
}
|
60
|
+
if class_object.nil?
|
61
|
+
#puts "Unknown class #{searched_class}."
|
62
|
+
raise Exception.new("Unknown class #{searched_class}.")
|
63
|
+
else
|
64
|
+
return class_object
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|