julien51-babylon 0.0.12 → 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -85,7 +85,7 @@ Babylon's edge versions are located at Github : http://github.com/julien51/babyl
85
85
 
86
86
  == REQUIREMENTS :
87
87
 
88
- Gems : Eventmachine, nokogiri, YAML, log4r, sax-machine
88
+ Gems : Eventmachine, nokogiri, YAML, log4r, sax-machine, templater, daemons
89
89
 
90
90
  == LICENSE:
91
91
 
data/Rakefile CHANGED
@@ -9,7 +9,7 @@ begin
9
9
  gem.email = "julien.genestoux@gmail.com"
10
10
  gem.homepage = "http://github.com/julien51/babylon"
11
11
  gem.authors = ["julien Genestoux"]
12
- gem.requirements = ["eventmachine", "yaml", "fileutils", "log4r", "nokogiri", "sax-machine"]
12
+ gem.requirements = ["eventmachine", "yaml", "fileutils", "log4r", "nokogiri", "sax-machine", "templater", "daemons"]
13
13
  gem.executables = "babylon"
14
14
  gem.files = [ "bin/babylon",
15
15
  "lib/babylon.rb",
@@ -35,7 +35,11 @@ begin
35
35
  "templates/babylon/config/config.yaml",
36
36
  "templates/babylon/config/dependencies.rb",
37
37
  "templates/babylon/config/routes.rb",
38
- "templates/babylon/script/component"
38
+ "templates/babylon/script/component",
39
+ "templates/babylon/tmp/log/test.log",
40
+ "templates/babylon/tmp/log/development.log",
41
+ "templates/babylon/tmp/log/production.log",
42
+ "templates/babylon/tmp/pid/README"
39
43
  ]
40
44
  gem.rubyforge_project = 'babylon'
41
45
  end
data/lib/babylon.rb CHANGED
@@ -60,7 +60,7 @@ module Babylon
60
60
  def self.logger
61
61
  unless self.class_variable_defined?("@@logger")
62
62
  @@logger = Log4r::Logger.new("BABYLON")
63
- @@logger.add(Log4r::Outputter.stderr)
63
+ @@logger.add(Log4r::Outputter.stdout) if Babylon.environment == "development"
64
64
  end
65
65
  @@logger
66
66
  end
@@ -9,10 +9,8 @@ module Babylon
9
9
 
10
10
  ##
11
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(params = {})
13
- params.each do |key, value|
14
- instance_variable_set("@#{key}", value)
15
- end
12
+ def initialize(stanza = nil)
13
+ @stanza = stanza
16
14
  @rendered = false
17
15
  end
18
16
 
@@ -29,8 +27,24 @@ module Babylon
29
27
  self.render
30
28
  end
31
29
 
30
+ ##
31
+ # Returns the list of variables assigned during the action.
32
+ def assigns
33
+ vars = Hash.new
34
+ instance_variables.each do |var|
35
+ if !["@rendered", "@action_name", "@block"].include? var
36
+ vars[var[1..-1]] = instance_variable_get(var)
37
+ end
38
+ end
39
+ return vars
40
+ end
41
+
32
42
  ##
33
43
  # Called by default after each action to "build" a XMPP stanza. By default, it will use the /controller_name/action.xml.builder
44
+ # You can use the following options :
45
+ # - :file : render a specific file (can be in a different controller)
46
+ # - :action : render another action of the current controller
47
+ # - :nothing : doesn't render anything
34
48
  def render(options = nil)
35
49
  return if @rendered # Avoid double rendering
36
50
 
@@ -45,6 +59,8 @@ module Babylon
45
59
  end
46
60
  elsif action_name = options[:action]
47
61
  render(:file => default_template_name(action_name.to_s))
62
+ elsif options[:nothing]
63
+ # Then we don't do anything.
48
64
  end
49
65
 
50
66
  # And finally, we set up rendered to be true
@@ -52,15 +68,6 @@ module Babylon
52
68
  end
53
69
 
54
70
  protected
55
-
56
- # Used to transfer the assigned variables from the controller to the views
57
- def hashed_variables
58
- vars = Hash.new
59
- instance_variables.each do |var|
60
- vars[var[1..-1]] = instance_variable_get(var)
61
- end
62
- return vars
63
- end
64
71
 
65
72
  def view_path(file_name)
66
73
  File.join("app/views", "#{self.class.name.gsub("Controller","").downcase}", file_name)
@@ -73,7 +80,7 @@ module Babylon
73
80
 
74
81
  # Creates the view and "evaluates" it to build the XML for the stanza
75
82
  def render_for_file(file)
76
- @block.call(Babylon::Base::View.new(file, hashed_variables).evaluate) if @block
83
+ @block.call(Babylon::Base::View.new(file, assigns).evaluate) if @block
77
84
  Babylon.logger.info("RENDERED : #{file}")
78
85
  end
79
86
  end
@@ -68,7 +68,7 @@ module Babylon
68
68
  end
69
69
  @outstream = builder.doc
70
70
  start_stream, stop_stream = builder.to_xml.split('<paste_content_here/>')
71
- send(start_stream)
71
+ send_xml(start_stream)
72
72
  end
73
73
 
74
74
  ##
@@ -91,7 +91,7 @@ module Babylon
91
91
  if stanza.at("starttls") # we shall start tls
92
92
  starttls = Nokogiri::XML::Node.new("starttls", @outstream)
93
93
  starttls["xmlns"] = "urn:ietf:params:xml:ns:xmpp-tls"
94
- send(starttls)
94
+ send_xml(starttls)
95
95
  @state = :wait_for_proceed
96
96
  elsif stanza.at("mechanisms") # tls is ok
97
97
  if stanza.at("mechanisms/[contains(mechanism,'PLAIN')]")
@@ -100,7 +100,7 @@ module Babylon
100
100
  auth['mechanism'] = "PLAIN"
101
101
  auth['xmlns'] = "urn:ietf:params:xml:ns:xmpp-sasl"
102
102
  auth.content = Base64::encode64([jid, jid.split("@").first, @password].join("\000")).gsub(/\s/, '')
103
- send(auth)
103
+ send_xml(auth)
104
104
  @state = :wait_for_success
105
105
  end
106
106
  end
@@ -111,7 +111,7 @@ module Babylon
111
111
  @success = true
112
112
  @state = :wait_for_stream
113
113
  @parser.reset
114
- send @outstream.root.to_xml.split('<paste_content_here/>').first
114
+ send_xml @outstream.root.to_xml.split('<paste_content_here/>').first
115
115
  elsif stanza.name == "failure"
116
116
  if stanza.at("bad-auth") || stanza.at("not-authorized")
117
117
  raise AuthenticationError
@@ -138,7 +138,7 @@ module Babylon
138
138
  end
139
139
  end
140
140
  iq = @outstream.add_child(builder.doc.root)
141
- send(iq)
141
+ send_xml(iq)
142
142
  @state = :wait_for_confirmed_binding
143
143
  end
144
144
  end
@@ -157,14 +157,14 @@ module Babylon
157
157
  end
158
158
  end
159
159
  iq = @outstream.add_child(builder.doc.root)
160
- send(iq)
160
+ send_xml(iq)
161
161
  @state = :wait_for_confirmed_session
162
162
 
163
163
  when :wait_for_confirmed_session
164
164
  if stanza.name == "iq" && stanza["type"] == "result" && Integer(stanza["id"]) == @session_iq_id && stanza.at("session")
165
165
  # And now, send a presence!
166
166
  presence = Nokogiri::XML::Node.new("presence", @outstream)
167
- send(presence)
167
+ send_xml(presence)
168
168
  begin
169
169
  @handler.on_connected(self) if @handler and @handler.respond_to?("on_connected")
170
170
  rescue
@@ -177,7 +177,7 @@ module Babylon
177
177
  start_tls() # starting TLS
178
178
  @state = :wait_for_stream
179
179
  @parser.reset
180
- send @outstream.root.to_xml.split('<paste_content_here/>').first
180
+ send_xml @outstream.root.to_xml.split('<paste_content_here/>').first
181
181
  end
182
182
  rescue
183
183
  Babylon.logger.error("#{$!}:\n#{$!.backtrace.join("\n")}")
@@ -24,7 +24,7 @@ module Babylon
24
24
  end
25
25
  end
26
26
  start, stop = builder.to_xml.split('<paste_content_here/>')
27
- send(start)
27
+ send_xml(start)
28
28
  end
29
29
 
30
30
  ##
@@ -39,7 +39,7 @@ module Babylon
39
39
  if stanza.name == "stream:stream" && stanza.attributes['id']
40
40
  # This means the XMPP session started!
41
41
  # We must send the handshake now.
42
- send(handshake(stanza))
42
+ send_xml(handshake(stanza))
43
43
  @state = :wait_for_handshake
44
44
  else
45
45
  raise
@@ -40,7 +40,16 @@ module Babylon
40
40
  empty_directory :initializers_directory do |d|
41
41
  d.destination = "#{application_name}/config/initializers"
42
42
  end
43
-
43
+ empty_directory :tmp_directory do |d|
44
+ d.destination = "#{application_name}/tmp"
45
+ end
46
+ empty_directory :log_directory do |d|
47
+ d.destination = "#{application_name}/tmp/log"
48
+ end
49
+ empty_directory :pid_directory do |d|
50
+ d.destination = "#{application_name}/tmp/pid"
51
+ end
52
+
44
53
  # And now add the critical files
45
54
  file :boot_file do |f|
46
55
  f.source = "#{source_root}/config/boot.rb"
@@ -58,7 +67,7 @@ module Babylon
58
67
  f.source = "#{source_root}/config/routes.rb"
59
68
  f.destination = "#{application_name}/config/routes.rb"
60
69
  end
61
- file :component_file do |f|
70
+ template :component_file do |f|
62
71
  f.source = "#{source_root}/script/component"
63
72
  f.destination = "#{application_name}/script/component"
64
73
  end
@@ -53,13 +53,13 @@ module Babylon
53
53
  Babylon.logger.info("ROUTING TO #{route.controller}::#{route.action}")
54
54
  # Parsing the stanza
55
55
  begin
56
- controller = route.controller.new({:stanza => Kernel.const_get(route.action.capitalize).new(stanza)})
56
+ controller = route.controller.new(Kernel.const_get(route.action.capitalize).new(stanza))
57
57
  rescue NameError
58
58
  raise UndefinedStanza
59
59
  end
60
60
  controller.perform(route.action) do |response|
61
61
  # Response should be a Nokogiri::Nodeset
62
- @@connection.send(response)
62
+ @@connection.send_xml(response)
63
63
  end
64
64
  return true
65
65
  end
@@ -17,6 +17,9 @@ module Babylon
17
17
  EventMachine.epoll
18
18
  EventMachine.run do
19
19
 
20
+ # Add an outputter to the logger
21
+ Babylon.logger.add(Log4r::FileOutputter.new("#{Babylon.environment}", :filename => "tmp/log/#{Babylon.environment}.log", :trunc => false))
22
+
20
23
  # Requiring all models
21
24
  Dir.glob('app/models/*.rb').each { |f| require f }
22
25
 
@@ -26,7 +29,7 @@ module Babylon
26
29
  # Load the controllers
27
30
  Dir.glob('app/controllers/*_controller.rb').each {|f| require f }
28
31
 
29
- # Evaluate routes defined with the new DSL router.
32
+ # Evaluate routes defined with the new DSL router.
30
33
  CentralRouter.draw do
31
34
  eval File.read("config/routes.rb")
32
35
  end
@@ -41,27 +44,48 @@ module Babylon
41
44
  Babylon.config = YAML.load(config_file)[Babylon.environment]
42
45
 
43
46
  case Babylon.config["application_type"]
44
- when "client"
45
- Babylon::ClientConnection.connect(Babylon.config, self)
46
- else # By default, we assume it's a component
47
- Babylon::ComponentConnection.connect(Babylon.config, self)
47
+ when "client"
48
+ Babylon::ClientConnection.connect(Babylon.config, self)
49
+ else # By default, we assume it's a component
50
+ Babylon::ComponentConnection.connect(Babylon.config, self)
48
51
  end
49
52
 
50
53
  # And finally, let's allow the application to do all it wants to do after we started the EventMachine!
51
- yield if block_given?
54
+ yield(self) if block_given?
52
55
  end
53
56
  end
54
57
 
58
+ ##
59
+ # Returns the list of connection observers
60
+ def self.connection_observers()
61
+ @@observers ||= Array.new
62
+ end
63
+
64
+ ##
65
+ # Adding a connection observer. These observer will receive on_connected and on_disconnected events.
66
+ def self.add_connection_observer(object)
67
+ @@observers ||= Array.new
68
+ @@observers.push(object)
69
+ end
70
+
55
71
  ##
56
72
  # Will be called by the connection class once it is connected to the server.
73
+ # It "plugs" the router and then calls on_connected on the various observers.
57
74
  def self.on_connected(connection)
58
75
  Babylon::CentralRouter.connected(connection)
76
+ connection_observers.each do |conn_obs|
77
+ conn_obs.on_connected(connection) if conn_obs.respond_to?("on_connected")
78
+ end
59
79
  end
60
80
 
61
81
  ##
62
82
  # Will be called by the connection class upon disconnection.
83
+ # It stops the event loop and then calls on_disconnected on the various observers.
63
84
  def self.on_disconnected()
64
85
  EventMachine.stop_event_loop
86
+ connection_observers.each do |conn_obs|
87
+ conn_obs.on_disconnected if conn_obs.respond_to?("on_disconnected")
88
+ end
65
89
  end
66
90
 
67
91
  ##
@@ -8,6 +8,10 @@ module Babylon
8
8
  # xml-not-well-formed Exception
9
9
  class XmlNotWellFormed < Exception; end
10
10
 
11
+ ##
12
+ # Error when there is no connection to the host and port.
13
+ class NoConnection < Exception; end
14
+
11
15
  ##
12
16
  # Authentication Error (wrong password/jid combination). Used for Clients and Components
13
17
  class AuthenticationError < Exception; end
@@ -24,7 +28,11 @@ module Babylon
24
28
  # This can very well be overwritten by subclasses.
25
29
  def self.connect(params, handler)
26
30
  Babylon.logger.debug("CONNECTING TO #{params["host"]}:#{params["port"]}") # Very low level Logging
27
- EventMachine.connect(params["host"], params["port"], self, params.merge({"handler" => handler}))
31
+ begin
32
+ EventMachine.connect(params["host"], params["port"], self, params.merge({"handler" => handler}))
33
+ rescue
34
+ Babylon.logger.error("CONNECTION ERROR : #{$!}") # Very low level Logging
35
+ end
28
36
  end
29
37
 
30
38
  def connection_completed
@@ -83,7 +91,7 @@ module Babylon
83
91
  ##
84
92
  # Sends the Nokogiri::XML data (after converting to string) on the stream. It also appends the right "from" to be the component's JId if none has been mentionned. Eventually it displays this data for debugging purposes.
85
93
  # This method also adds a "from" attribute to all stanza if it was ommited (the full jid) only if a "to" attribute is present. if not, we assume that we're speaking to the server and the server doesn't need a "from" to identify where the message is coming from.
86
- def send(xml)
94
+ def send_xml(xml)
87
95
  raise NotConnected unless @connected
88
96
  if xml.is_a? Nokogiri::XML::NodeSet
89
97
  xml.each do |node|
@@ -1,9 +1,16 @@
1
+ ##
2
+ # This file is run by the dameons, in the apps directory
3
+
4
+ # Change directory to the app's directory.
5
+ Dir.chdir(File.dirname(__FILE__) + "/../")
6
+
1
7
  require "rubygems"
2
8
  require "babylon"
3
9
  require File.dirname(__FILE__) + "/dependencies"
4
10
 
11
+
5
12
  # Start the App
6
13
  Babylon::Runner::run(ARGV[0] || "development") do
7
- # And the initializers, too. This is done here since some initializers might need EventMachine to be started.
8
- Dir[File.join(File.dirname(__FILE__), '/initializers/*.rb')].each {|f| require f }
9
- end
14
+ # Run the initializers, too. This is done here since some initializers might need EventMachine to be started.
15
+ Dir.glob('initializers/*.rb').each { |f| require f }
16
+ end
@@ -1,2 +1,31 @@
1
1
  #!/usr/bin/env ruby
2
- require File.dirname(__FILE__) + '/../config/boot'
2
+
3
+ require 'rubygems'
4
+ require 'daemons'
5
+
6
+ if ["run", "start", "stop", "restart"].include? ARGV[0]
7
+ command = ARGV[0]
8
+ env = "development"
9
+ else
10
+ env = ARGV[0] || "development"
11
+ case env
12
+ when "development"
13
+ command = "run"
14
+ when "production"
15
+ command = "start"
16
+ else
17
+ # By default, we run in "on-top" mode
18
+ command = "run"
19
+ end
20
+ end
21
+
22
+ options = {
23
+ :ARGV => [command, '--', env],
24
+ :app_name => "#{Dir.pwd.split("/").last}",
25
+ :dir => "../tmp/pid/",
26
+ :multiple => true,
27
+ :backtrace => true
28
+ }
29
+
30
+ Daemons.run(File.dirname(__FILE__) + '/../config/boot.rb', options)
31
+
File without changes
File without changes
File without changes
@@ -0,0 +1,2 @@
1
+ # This is the pid directory. Please do not delete.
2
+ # Also, when your application fails, you will find a .log ile here that shows the last trace
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: julien51-babylon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.12
4
+ version: 0.0.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - julien Genestoux
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-03-31 00:00:00 -07:00
12
+ date: 2009-04-16 00:00:00 -07:00
13
13
  default_executable: babylon
14
14
  dependencies: []
15
15
 
@@ -48,6 +48,10 @@ files:
48
48
  - templates/babylon/config/dependencies.rb
49
49
  - templates/babylon/config/routes.rb
50
50
  - templates/babylon/script/component
51
+ - templates/babylon/tmp/log/test.log
52
+ - templates/babylon/tmp/log/development.log
53
+ - templates/babylon/tmp/log/production.log
54
+ - templates/babylon/tmp/pid/README
51
55
  has_rdoc: true
52
56
  homepage: http://github.com/julien51/babylon
53
57
  post_install_message:
@@ -75,6 +79,8 @@ requirements:
75
79
  - log4r
76
80
  - nokogiri
77
81
  - sax-machine
82
+ - templater
83
+ - daemons
78
84
  rubyforge_project: babylon
79
85
  rubygems_version: 1.2.0
80
86
  signing_key: