mohiam-babylon 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +111 -0
  3. data/Rakefile +145 -0
  4. data/bin/babylon +6 -0
  5. data/lib/babylon.rb +119 -0
  6. data/lib/babylon/base/controller.rb +116 -0
  7. data/lib/babylon/base/stanza.rb +23 -0
  8. data/lib/babylon/base/view.rb +49 -0
  9. data/lib/babylon/client_connection.rb +210 -0
  10. data/lib/babylon/component_connection.rb +87 -0
  11. data/lib/babylon/generator.rb +139 -0
  12. data/lib/babylon/router.rb +103 -0
  13. data/lib/babylon/router/dsl.rb +61 -0
  14. data/lib/babylon/runner.rb +148 -0
  15. data/lib/babylon/xmpp_connection.rb +172 -0
  16. data/lib/babylon/xmpp_parser.rb +111 -0
  17. data/lib/babylon/xpath_helper.rb +13 -0
  18. data/spec/bin/babylon_spec.rb +0 -0
  19. data/spec/em_mock.rb +42 -0
  20. data/spec/lib/babylon/base/controller_spec.rb +205 -0
  21. data/spec/lib/babylon/base/stanza_spec.rb +15 -0
  22. data/spec/lib/babylon/base/view_spec.rb +86 -0
  23. data/spec/lib/babylon/client_connection_spec.rb +304 -0
  24. data/spec/lib/babylon/component_connection_spec.rb +135 -0
  25. data/spec/lib/babylon/generator_spec.rb +10 -0
  26. data/spec/lib/babylon/router/dsl_spec.rb +72 -0
  27. data/spec/lib/babylon/router_spec.rb +189 -0
  28. data/spec/lib/babylon/runner_spec.rb +213 -0
  29. data/spec/lib/babylon/xmpp_connection_spec.rb +197 -0
  30. data/spec/lib/babylon/xmpp_parser_spec.rb +275 -0
  31. data/spec/lib/babylon/xpath_helper_spec.rb +25 -0
  32. data/spec/spec_helper.rb +34 -0
  33. data/templates/babylon/app/controllers/controller.rb +7 -0
  34. data/templates/babylon/app/stanzas/stanza.rb +6 -0
  35. data/templates/babylon/app/views/view.rb +6 -0
  36. data/templates/babylon/config/boot.rb +16 -0
  37. data/templates/babylon/config/config.yaml +24 -0
  38. data/templates/babylon/config/dependencies.rb +1 -0
  39. data/templates/babylon/config/routes.rb +22 -0
  40. data/templates/babylon/log/development.log +0 -0
  41. data/templates/babylon/log/production.log +0 -0
  42. data/templates/babylon/log/test.log +52 -0
  43. data/templates/babylon/script/component +46 -0
  44. data/templates/babylon/tmp/pids/README +2 -0
  45. data/test/babylon_test.rb +7 -0
  46. data/test/test_helper.rb +10 -0
  47. metadata +179 -0
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 julien
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,111 @@
1
+ = Babylon
2
+
3
+ == DESCRIPTION:
4
+
5
+ Babylon is a framework to build XMPP Applications in Ruby. The framework uses EventMachine to handle network connections.
6
+
7
+ This framework can use both an XMPP Component (XEP-0114) and an XMPP Client (and XMPP Servers should come soon). However, we strongly discourage any production application using a regular client.
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ Please link "report/request here.":http://github.com/julien51/babylon/issues
12
+
13
+ The current version is a good candidate for version 0.1. We will probably not add any important features before that release, but we need some help with the tests and documentation.
14
+
15
+ == ROADMAP :
16
+
17
+ - Implement the ServerConnection for S2S
18
+ - Implement templates for disco-info... and common XEPs
19
+ - Delete route priorities? And rely on the order only? (As Rails does)
20
+ - Review doc
21
+ - Write tests
22
+ - Evangelize!
23
+
24
+ You can help with at least one of these points, don't turn your back on Babylon!
25
+
26
+ == DOCUMENTATION :
27
+
28
+ You can find it on our "Rubyforge page":http://babylon.rubyforge.org/
29
+ Feel free to fork the "github":http://github.com/julien51/babylon/tree/master repo and add some documentation if you think anything is missing.
30
+
31
+ __You can't be a bad coder, a bad tester and a bad documenter at the same time ;)__
32
+
33
+ == SYNOPSIS :
34
+
35
+ You can build applications directly with Babylon, or you can use the Babylon::ClientConnection and Babylon::ComponentConnection to create simple apps, but you will then have to handle stanza routing and creation yourself. You can also use these classes in external gems.
36
+
37
+ === To create an Application with Babylon:
38
+
39
+ 1. Install the gem
40
+ 2. The app contains a generator that will "build" a scaffold for your application.
41
+
42
+ $> babylon application __myapp__
43
+
44
+ 3. Use the generator or write your own controllers :
45
+
46
+ $> babylon controller __messages__ __echo__:__10__:__//stream:message[@type='chat']/body__,__subscribed__:__0__:__//stream:presence[@type='subscribe']__
47
+
48
+ This will generate a __MessagesController__ class with 2 methods : __echo__ and __subscribed__.
49
+ - "echo" will be called when the component receives message stanzas of type 'chat',
50
+ - "subscribed" will be called for presence stanzas of type 'subscribe'.
51
+ 10 and 0 are the priority : useful when a stanza matches 2 XPath.
52
+
53
+ Each of these actions will be called with stanza objects. You have to define your own objects in __stanzas/echo.rb__ and __stanzas/subscribed.rb__
54
+ By implementing them, you can choose which elements and attributes you want to have access to. These attributes will be populated upon instantiation of the Stanza objects.
55
+
56
+ This will also generate 2 'views' used to build your responses stanzas.
57
+
58
+ And finally, this will write 2 routes in the config/routes.rb
59
+
60
+ 4. Customize your controllers, stanzas and views!
61
+
62
+ 5. Make sure that the XMPP settings are correct in config/config.yaml.
63
+
64
+ 6. And finally start the component :
65
+
66
+ script/component
67
+
68
+ === To use the Connection Classes only (Client or Component), you can just call the following :
69
+
70
+ Babylon::ClientConnection.connect(params, handler)
71
+ or,
72
+ Babylon::ComponentConnection.connect(params, handler)
73
+
74
+ where params is a hash for all the necessary information to connect, and handler is an object that will receive the callbacks. Right now 3 callbacks are supported:
75
+
76
+ on_connected(connection), on_disconnected and on_stanza(stanza)
77
+
78
+ == ADDITIONAL INFORMATION :
79
+
80
+ Feel free to pull, branch, improve and commit the {code|specs|tests|docs} : we will merge it if it's a step ahead!
81
+
82
+ Babylon's edge versions are located at Github : http://github.com/julien51/babylon/tree/master
83
+
84
+ == REQUIREMENTS :
85
+
86
+ Gems : Eventmachine, nokogiri (please, use build from the guthub repo, since 1.2.3 is not supported by Babylon), YAML, log4r, sax-machine, templater, daemons
87
+
88
+ == LICENSE:
89
+
90
+ (The MIT License)
91
+
92
+ Copyright (c) 2009 Julien Genestoux http://notifixio.us
93
+
94
+ Permission is hereby granted, free of charge, to any person obtaining
95
+ a copy of this software and associated documentation files (the
96
+ 'Software'), to deal in the Software without restriction, including
97
+ without limitation the rights to use, copy, modify, merge, publish,
98
+ distribute, sublicense, and/or sell copies of the Software, and to
99
+ permit persons to whom the Software is furnished to do so, subject to
100
+ the following conditions:
101
+
102
+ The above copyright notice and this permission notice shall be
103
+ included in all copies or substantial portions of the Software.
104
+
105
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
106
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
107
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
108
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
109
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
110
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
111
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,145 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "babylon"
8
+ gem.summary = %Q{Babylon is a framework to create EventMachine based XMPP External Components in Ruby.}
9
+ gem.email = "julien.genestoux@gmail.com"
10
+ gem.homepage = "http://github.com/julien51/babylon"
11
+ gem.authors = ["julien Genestoux"]
12
+
13
+ gem.add_dependency('eventmachine')
14
+ gem.add_dependency('log4r')
15
+ gem.add_dependency('nokogiri', ">= 1.3.0")
16
+ gem.add_dependency('eventmachine')
17
+ gem.add_dependency('julien51-sax-machine')
18
+ gem.add_dependency('templater')
19
+ gem.add_dependency('daemons')
20
+ gem.requirements = ["eventmachine", "yaml", "fileutils", "log4r", "nokogiri", "sax-machine", "templater", "daemons", "optparse", "digest/sha1", "base64", "resolv"]
21
+ gem.executables = "babylon"
22
+ gem.files = [ "bin/babylon",
23
+ "lib/babylon.rb",
24
+ "lib/babylon/base/controller.rb",
25
+ "lib/babylon/base/view.rb",
26
+ "lib/babylon/base/stanza.rb",
27
+ "lib/babylon/client_connection.rb",
28
+ "lib/babylon/component_connection.rb",
29
+ "lib/babylon/router/dsl.rb",
30
+ "lib/babylon/router.rb",
31
+ "lib/babylon/runner.rb",
32
+ "lib/babylon/generator.rb",
33
+ "lib/babylon/xmpp_connection.rb",
34
+ "lib/babylon/xmpp_parser.rb",
35
+ "lib/babylon/xpath_helper.rb",
36
+ "LICENSE",
37
+ "Rakefile",
38
+ "README.rdoc",
39
+ "templates/babylon/app/controllers/controller.rb",
40
+ "templates/babylon/app/views/view.rb",
41
+ "templates/babylon/app/stanzas/stanza.rb",
42
+ "templates/babylon/config/boot.rb",
43
+ "templates/babylon/config/config.yaml",
44
+ "templates/babylon/config/dependencies.rb",
45
+ "templates/babylon/config/routes.rb",
46
+ "templates/babylon/script/component",
47
+ "templates/babylon/log/test.log",
48
+ "templates/babylon/log/development.log",
49
+ "templates/babylon/log/production.log",
50
+ "templates/babylon/tmp/pids/README"
51
+ ]
52
+ gem.rubyforge_project = 'babylon'
53
+ end
54
+ rescue LoadError
55
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
56
+ end
57
+
58
+ require 'rake/rdoctask'
59
+ Rake::RDocTask.new do |rdoc|
60
+ rdoc.rdoc_dir = 'rdoc'
61
+ rdoc.title = 'Babylon : a framework to create EventMachine based XMPP External Components in Ruby.'
62
+ rdoc.rdoc_files.include('README*')
63
+ rdoc.rdoc_files.include('lib/**/*.rb')
64
+ rdoc.options << '--line-numbers'
65
+ end
66
+
67
+ require 'rake/testtask'
68
+ Rake::TestTask.new(:test) do |test|
69
+ test.libs << 'lib' << 'test'
70
+ test.pattern = 'test/**/*_test.rb'
71
+ test.verbose = false
72
+ end
73
+
74
+ begin
75
+ require 'rcov/rcovtask'
76
+ Rcov::RcovTask.new do |test|
77
+ test.libs << 'test'
78
+ test.pattern = 'test/**/*_test.rb'
79
+ test.verbose = true
80
+ end
81
+ rescue LoadError
82
+ task :rcov do
83
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
84
+ end
85
+ end
86
+
87
+ begin
88
+ require 'spec/rake/spectask'
89
+ desc "Run all Spec"
90
+ Spec::Rake::SpecTask.new('spec') do |spec|
91
+ spec.spec_files = FileList['spec/**/*.rb']
92
+ spec.verbose = true
93
+ spec.warning = false
94
+ spec.rcov = true
95
+ end
96
+ rescue LoadError
97
+ task :spec do
98
+ abort "Rspec is not available. In order to run rspec, you must: sudo gem install rspec"
99
+ end
100
+ end
101
+
102
+ begin
103
+ require 'spec/rake/verify_rcov'
104
+
105
+ RCov::VerifyTask.new(:verify_rcov => 'spec') do |t|
106
+ t.threshold = 100.0
107
+ t.index_html = 'coverage/index.html'
108
+ end
109
+ rescue LoadError
110
+ task :spec do
111
+ abort "Rcov is not available. In order to run rcov, you must: sudo gem install rcov"
112
+ end
113
+ end
114
+
115
+ # These are Rubyforge tasks
116
+ begin
117
+ require 'rake/contrib/sshpublisher'
118
+ namespace :rubyforge do
119
+
120
+ desc "Release gem and RDoc documentation to RubyForge"
121
+ task :release => ["rubyforge:release:gem", "rubyforge:release:docs"]
122
+
123
+ namespace :release do
124
+ desc "Publish RDoc to RubyForge."
125
+ task :docs => [:rdoc] do
126
+ config = YAML.load(
127
+ File.read(File.expand_path('~/.rubyforge/user-config.yml'))
128
+ )
129
+
130
+ host = "#{config['username']}@rubyforge.org"
131
+ remote_dir = "/var/www/gforge-projects/babylon"
132
+ local_dir = 'rdoc'
133
+
134
+ Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
135
+ end
136
+ end
137
+ end
138
+ rescue LoadError
139
+ puts "Rake SshDirPublisher is unavailable or your rubyforge environment is not configured."
140
+ end
141
+
142
+
143
+ task :install => :build
144
+
145
+ task :default => :test
data/bin/babylon ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'babylon'
5
+
6
+ Babylon::Generator.run_cli(Dir.pwd, 'babylon_app', "0.1", ARGV)
data/lib/babylon.rb ADDED
@@ -0,0 +1,119 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'eventmachine'
5
+ require 'log4r'
6
+ require 'nokogiri'
7
+ require 'yaml'
8
+ require 'fileutils'
9
+ require 'sax-machine'
10
+ require 'digest/sha1'
11
+ require 'base64'
12
+ require 'resolv'
13
+ require "templater"
14
+ require 'extlib'
15
+
16
+
17
+ require 'babylon/xmpp_connection'
18
+ require 'babylon/xmpp_parser'
19
+ require 'babylon/component_connection'
20
+ require 'babylon/client_connection'
21
+ require 'babylon/router'
22
+ require 'babylon/runner'
23
+ require 'babylon/generator'
24
+ require "babylon/xpath_helper"
25
+ require 'babylon/base/controller'
26
+ require 'babylon/base/view'
27
+ require 'babylon/base/stanza'
28
+
29
+ # Babylon is a XMPP Component Framework based on EventMachine. It uses the Nokogiri GEM, which is a Ruby wrapper for Libxml2.
30
+ # It implements the MVC paradigm.
31
+ # You can create your own application by running :
32
+ # $> babylon app_name
33
+ # This will generate some folders and files for your application. Please see README.rdoc for further instructions
34
+
35
+ module Babylon
36
+
37
+ def self.environment=(_env)
38
+ @@env = _env
39
+ end
40
+
41
+ def self.environment
42
+ unless self.class_variable_defined?("@@env")
43
+ @@env = "development"
44
+ end
45
+ @@env
46
+ end
47
+
48
+ ##
49
+ # Sets up the router
50
+ def self.router=(router)
51
+ @@router = router
52
+ end
53
+
54
+ ##
55
+ # Retruns the router
56
+ def self.router
57
+ unless self.class_variable_defined?("@@router")
58
+ @@router = nil
59
+ end
60
+ @@router
61
+ end
62
+
63
+ ##
64
+ # Caches the view files to improve performance.
65
+ def self.cache_views
66
+ @@views= {}
67
+ Dir.glob('app/views/**/*').each do |f|
68
+ Babylon.logger.debug("adding view #{f}")
69
+ @@views[f] = File.read(f) if File.file?(f)
70
+ end
71
+ end
72
+
73
+ def self.views
74
+ unless self.class_variable_defined?("@@views")
75
+ @@views= {}
76
+ end
77
+ @@views
78
+ end
79
+
80
+ ##
81
+ # Returns a shared logger for this component.
82
+ def self.logger
83
+ unless self.class_variable_defined?("@@logger")
84
+ @@logger = Log4r::Logger.new("BABYLON")
85
+ @@logger.add(Log4r::Outputter.stdout) if Babylon.environment == "development"
86
+ end
87
+ @@logger
88
+ end
89
+
90
+ ##
91
+ # Set the configuration for this component.
92
+ def self.config=(conf)
93
+ @@config = conf
94
+ end
95
+
96
+ ##
97
+ # Return the configuration for this component.
98
+ def self.config
99
+ @@config
100
+ end
101
+
102
+ ##
103
+ # Decodes XML special characters.
104
+ def self.decode_xml(str)
105
+ entities = {
106
+ 'lt' => '<',
107
+ 'gt' => '>',
108
+ '#38' => '&',
109
+ 'amp' => '&',
110
+ 'quot' => '"',
111
+ '#13' => "\r",
112
+ }
113
+ entities.keys.inject(str) { |string, key|
114
+ string.gsub(/&#{key};/, entities[key])
115
+ }
116
+ end
117
+
118
+ end
119
+
@@ -0,0 +1,116 @@
1
+ module Babylon
2
+ module Base
3
+
4
+ ##
5
+ # Your application's controller should be descendant of this class.
6
+ class Controller
7
+
8
+ attr_accessor :stanza, :rendered, :action_name # Stanza received by the controller (Nokogiri::XML::Node)
9
+
10
+ ##
11
+ # Creates a new controller (you should not override this class) and assigns the stanza as well as any other value of the hash to instances named after the keys of the hash.
12
+ def initialize(stanza = nil)
13
+ @stanza = stanza
14
+ @view = nil
15
+
16
+ # used to render basic strings
17
+ @content = nil
18
+ end
19
+
20
+ ##
21
+ # Performs the action and calls back the optional block argument : you should not override this function
22
+ def perform(action)
23
+ @action_name = action
24
+ begin
25
+ self.send(@action_name)
26
+ rescue
27
+ Babylon.logger.error {
28
+ "#{$!}:\n#{$!.backtrace.join("\n")}"
29
+ }
30
+ end
31
+ self.render
32
+ end
33
+
34
+ ##
35
+ # Returns the list of variables assigned during the action.
36
+ def assigns
37
+ vars = Hash.new
38
+ instance_variables.each do |var|
39
+ if !["@view", "@action_name", "@block"].include? var
40
+ vars[var[1..-1]] = instance_variable_get(var)
41
+ end
42
+ end
43
+ vars
44
+ end
45
+
46
+ ##
47
+ # Called by default after each action to "build" a XMPP stanza. By default, it will use the /controller_name/action.xml.builder
48
+ # You can use the following options :
49
+ # - :file : render a specific file (can be in a different controller)
50
+ # - :action : render another action of the current controller
51
+ # - :nothing : doesn't render anything
52
+ def render(options = {})
53
+ return if @view and !options[:force] # Avoid double rendering, if we have already attached a view
54
+
55
+ if options == :nothing
56
+ @view = Babylon::Base::View.new()
57
+ elsif options.kind_of? String
58
+ @content = options
59
+ elsif options == {} # default rendering
60
+ # Babylon.logger.debug("rendering default view #{default_template_name}")
61
+ result = render(:file => default_template_name)
62
+ elsif options[:file]
63
+ file = options[:file]
64
+ if file =~ /^\// # Render from view root
65
+ result = render_for_file(File.join("app", "views", "#{file}.xml.builder"))
66
+ else
67
+ Babylon.logger.debug("rendering from here #{file} #{view_path(file)}")
68
+ result = render_for_file(view_path(file))
69
+ end
70
+ elsif action_name = options[:action]
71
+ result = render(:file => default_template_name(action_name.to_s))
72
+ elsif options[:nothing]
73
+ @view = Babylon::Base::View.new()
74
+ end
75
+ end
76
+
77
+ ##
78
+ # Actually evaluates the view
79
+ def evaluate
80
+ return @view.evaluate if @view
81
+ return @content
82
+ end
83
+
84
+ protected
85
+
86
+ ##
87
+ # Builds the view path.
88
+ def view_path(file_name)
89
+ File.join("app", "views", "#{self.class.name.gsub("Controller","").downcase}", file_name)
90
+ end
91
+
92
+ ##
93
+ # Default template name used to build stanzas
94
+ def default_template_name(action_name = nil)
95
+ "#{action_name || @action_name}.xml.builder"
96
+ end
97
+
98
+ ##
99
+ # Creates the view and "evaluates" it to build the XML for the stanza
100
+ def render_for_file(file)
101
+
102
+ # if the view doesn't exist, then don't render it
103
+ return unless File.exists?(file)
104
+
105
+ Babylon.logger.info {
106
+ "RENDERING : #{file}"
107
+ }
108
+ @view = Babylon::Base::View.new(file, assigns)
109
+ Babylon.logger.info {
110
+ " "
111
+ }
112
+ end
113
+
114
+ end
115
+ end
116
+ end