c3s 0.2.7 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
data/Manifest CHANGED
@@ -1,7 +1,7 @@
1
1
  Manifest
2
2
  README.rdoc
3
3
  Rakefile
4
- c3s.gemspec
4
+ c3s
5
5
  lib/c3s.rb
6
6
  lib/c3s_logger.rb
7
7
  lib/component.rb
@@ -9,5 +9,25 @@ lib/component_connection.rb
9
9
  lib/configreader.rb
10
10
  lib/databaseadapter.rb
11
11
  lib/model.rb
12
- lib/nodetracker.rb
13
- lib/publisher.rb
12
+ lib/pubsub/node.rb
13
+ lib/pubsub/nodetracker.rb
14
+ lib/pubsub/publisher.rb
15
+ lib/pubsub/subscriber.rb
16
+ pkg/c3s-0.3.2.gem
17
+ pkg/c3s-0.3.2.tar.gz
18
+ pkg/c3s-0.3.2/Manifest
19
+ pkg/c3s-0.3.2/README.rdoc
20
+ pkg/c3s-0.3.2/Rakefile
21
+ pkg/c3s-0.3.2/c3s
22
+ pkg/c3s-0.3.2/c3s.gemspec
23
+ pkg/c3s-0.3.2/lib/c3s.rb
24
+ pkg/c3s-0.3.2/lib/c3s_logger.rb
25
+ pkg/c3s-0.3.2/lib/component.rb
26
+ pkg/c3s-0.3.2/lib/component_connection.rb
27
+ pkg/c3s-0.3.2/lib/configreader.rb
28
+ pkg/c3s-0.3.2/lib/databaseadapter.rb
29
+ pkg/c3s-0.3.2/lib/model.rb
30
+ pkg/c3s-0.3.2/lib/pubsub/node.rb
31
+ pkg/c3s-0.3.2/lib/pubsub/nodetracker.rb
32
+ pkg/c3s-0.3.2/lib/pubsub/publisher.rb
33
+ pkg/c3s-0.3.2/lib/pubsub/subscriber.rb
data/Rakefile CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
2
2
  require 'rake'
3
3
  require 'echoe'
4
4
 
5
- Echoe.new('c3s', '0.2.7') do |p|
5
+ Echoe.new('c3s', '0.3.2') do |p|
6
6
  p.description = "C3s library gem."
7
7
  p.url = "http://github.com/rikas/c3s"
8
8
  p.author = "Ricardo Otero"
data/c3s ADDED
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This is the command used to run the component
4
+
5
+ require 'rubygems'
6
+
7
+ # Check for gem versions
8
+ gem 'c3s', '>=0.3.2'
9
+ gem 'xmpp4r', '>=0.5'
10
+
11
+ require 'c3s'
12
+ require 'pathname'
13
+
14
+ PROVIDERS_DIR = File.join(ENV['HOME'], "ptcb", "code", "providers")
15
+
16
+ def usage
17
+ puts "Usage: provider [provider_dir]"
18
+ puts ""
19
+ puts "Available providers: #{available_providers}"
20
+ puts ""
21
+ exit
22
+ end
23
+
24
+ def available_providers
25
+ available_providers = []
26
+ Dir.glob(File.join(PROVIDERS_DIR, "*")) do |dir|
27
+ next unless File.directory?(dir)
28
+ conf = File.join(dir, "component.yml")
29
+ path = Pathname.new(dir)
30
+ available_providers << path.basename if File.exist?(conf)
31
+ end
32
+ available_providers.join(", ")
33
+ end
34
+
35
+ args = ARGV
36
+ if (args.size!=1)
37
+ usage
38
+ else
39
+ provider = File.join(PROVIDERS_DIR, args.last)
40
+ if (!File.directory?(provider))
41
+ puts "Couldn't find '#{args.last}' provider"
42
+ exit
43
+ end
44
+ end
45
+
46
+ # Set process name to provider
47
+ $0 = args.last
48
+
49
+ # Set the dir variables
50
+ C3S_COMPONENT_DIR = File.join(PROVIDERS_DIR, args.last)
51
+ C3S_LIB_DIR = File.join(C3S_COMPONENT_DIR, 'lib')
52
+ C3S_LOG_DIR = File.join(C3S_COMPONENT_DIR, 'logs')
53
+
54
+ # Power to the requires
55
+ $:.unshift C3S_COMPONENT_DIR
56
+ $:.unshift C3S_LIB_DIR
57
+ $:.unshift File.join(C3S_LIB_DIR, args.last)
58
+
59
+ require 'lib/runner'
data/c3s.gemspec CHANGED
@@ -2,15 +2,15 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{c3s}
5
- s.version = "0.2.7"
5
+ s.version = "0.3.2"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Ricardo Otero"]
9
- s.date = %q{2009-12-16}
9
+ s.date = %q{2010-02-11}
10
10
  s.description = %q{C3s library gem.}
11
11
  s.email = %q{oterosantos@gmail.com}
12
- s.extra_rdoc_files = ["README.rdoc", "lib/c3s.rb", "lib/c3s_logger.rb", "lib/component.rb", "lib/component_connection.rb", "lib/configreader.rb", "lib/databaseadapter.rb", "lib/model.rb", "lib/nodetracker.rb", "lib/publisher.rb"]
13
- s.files = ["Manifest", "README.rdoc", "Rakefile", "c3s.gemspec", "lib/c3s.rb", "lib/c3s_logger.rb", "lib/component.rb", "lib/component_connection.rb", "lib/configreader.rb", "lib/databaseadapter.rb", "lib/model.rb", "lib/nodetracker.rb", "lib/publisher.rb"]
12
+ s.extra_rdoc_files = ["README.rdoc", "lib/c3s.rb", "lib/c3s_logger.rb", "lib/component.rb", "lib/component_connection.rb", "lib/configreader.rb", "lib/databaseadapter.rb", "lib/model.rb", "lib/pubsub/node.rb", "lib/pubsub/nodetracker.rb", "lib/pubsub/publisher.rb", "lib/pubsub/subscriber.rb"]
13
+ s.files = ["Manifest", "README.rdoc", "Rakefile", "c3s", "lib/c3s.rb", "lib/c3s_logger.rb", "lib/component.rb", "lib/component_connection.rb", "lib/configreader.rb", "lib/databaseadapter.rb", "lib/model.rb", "lib/pubsub/node.rb", "lib/pubsub/nodetracker.rb", "lib/pubsub/publisher.rb", "lib/pubsub/subscriber.rb", "c3s.gemspec"]
14
14
  s.homepage = %q{http://github.com/rikas/c3s}
15
15
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "C3s", "--main", "README.rdoc"]
16
16
  s.require_paths = ["lib"]
data/lib/c3s.rb CHANGED
@@ -19,7 +19,7 @@ require 'databaseadapter'
19
19
  require 'c3s_logger'
20
20
 
21
21
  module C3s
22
- VERSION = "0.2.7"
22
+ VERSION = "0.2.9"
23
23
 
24
24
  def self.included(base)
25
25
  base.extend ClassMethods
data/lib/c3s_logger.rb CHANGED
@@ -5,7 +5,8 @@ module C3s
5
5
  class C3sLogger
6
6
  attr_accessor :logger
7
7
 
8
- def initialize(log_file)
8
+ def initialize
9
+ log_file = File.join(C3S_LOG_DIR, 'component.log')
9
10
  logger = Logger.new(log_file, "weekly")
10
11
  logger.formatter = C3sLogFormatter.new
11
12
  self.logger = logger
data/lib/component.rb CHANGED
@@ -8,7 +8,9 @@ rescue Exception => e
8
8
  end
9
9
  require 'xmpp4r/discovery'
10
10
  require 'xmpp4r/pubsub/helper/nodebrowser'
11
- require 'publisher'
11
+ require 'pubsub/publisher'
12
+ require 'pubsub/subscriber'
13
+ require 'pubsub/node'
12
14
 
13
15
  module C3s
14
16
  class Component < Jabber::Component
@@ -16,15 +18,21 @@ module C3s
16
18
  # Component configuration hash
17
19
  attr_accessor :config
18
20
 
21
+ ##
22
+ # Active record main class associated with component
23
+ attr_accessor :model
24
+
19
25
  ##
20
26
  # Initializes the jabber component with
21
27
  # a configuration hash read with ConfigReader
22
28
  #
23
29
  # config:: [Hash] configuration hash
24
- def initialize(config)
30
+ def initialize(config, model)
25
31
  super(config['jid'])
26
32
  self.config = config
33
+ self.model = model
27
34
  Jabber::debug = config['debug'].to_s.eql?"true"
35
+ config['pubsub'] = "pubsub.#{config['url']}"
28
36
  end
29
37
 
30
38
  ##
@@ -33,6 +41,7 @@ module C3s
33
41
  # Throws ClientAuthenticationFailure
34
42
  def connect
35
43
  super(config['url'], config['port'])
44
+
36
45
  if is_connected?
37
46
  auth(config['password'])
38
47
  else
@@ -45,7 +54,7 @@ module C3s
45
54
  # provides a callback named *handle_iq* for especific components
46
55
  # to use.
47
56
  def start
48
- super()
57
+ super
49
58
 
50
59
  Thread.abort_on_exception = true
51
60
 
@@ -55,6 +64,84 @@ module C3s
55
64
  end
56
65
  t.join
57
66
  end
67
+
68
+ add_message_callback do |msg|
69
+ t = Thread.new do
70
+ handle_msg(msg)
71
+ end
72
+ t.join
73
+ end
74
+ end
75
+
76
+ ##
77
+ # Tries to send the message. It will repeat the process if
78
+ # sending the stanza fails, reconnecting the client. This should be used
79
+ # instead of the default send method.
80
+ # msg:: the stanza to send
81
+ def send!(msg)
82
+ attempts = 0
83
+ begin
84
+ attempts += 1
85
+ send(msg)
86
+ rescue Errno::EPIPE, IOError => e
87
+ sleep 1
88
+ disconnect
89
+ reconnect
90
+ retry unless attempts > 3
91
+ raise e
92
+ rescue Errno::ECONNRESET => e
93
+ sleep (attempts^2) * 60 + 60
94
+ disconnect
95
+ reconnect
96
+ retry unless attempts > 3
97
+ raise e
98
+ end
99
+ end
100
+
101
+ ##
102
+ # Handles discovery, sets and gets
103
+ # iq:: [Jabber::IQ] the received IQ packet
104
+ def handle_iq(iq)
105
+ if iq.query.kind_of?(Jabber::Discovery::IqQueryDiscoInfo)
106
+ handle_disco_info(iq)
107
+ elsif iq.query.first_element(config['name']) # TODO assuming that pubsubnode = xml root
108
+ handle_set(iq) if iq.type == :set
109
+ handle_get(iq) if iq.type == :get
110
+ end
111
+ rescue Exception => e
112
+ $LOG.error("#{e.inspect} #{e.backtrace.join("\n")}")
113
+ send_error(iq, ['bad-request', nil])
114
+ end
115
+
116
+ def handle_msg(msg)
117
+ end
118
+
119
+ ##
120
+ # Handles set of information
121
+ # iq:: [Jabber::IQ] the received IQ packet
122
+ def handle_set(iq)
123
+ stanza = iq.query.first_element(config['name']) # TODO assuming that pubsubnode = xml root
124
+
125
+ # Build data for activerecord object. The jid is taken from
126
+ # the 'jid' attribute on the main tag under the <query>
127
+ data = {:jid => iq.from.to_s}
128
+ self.model.new.nodes.each do |node|
129
+ data.merge!(node => stanza.first_element_text(node))
130
+ end
131
+
132
+ changed = true
133
+ @object = self.model.find_by_jid(data[:jid]) || self.model.new
134
+
135
+ $LOG.info "Saving #{config['name']} context for #{data[:jid]} #{data.inspect}"
136
+ @object.update_attributes(data)
137
+ changed = @object.changed?
138
+ @object.save!
139
+
140
+ publish(iq, stanza, changed) if @object.errors.count == 0
141
+
142
+ rescue Exception => e
143
+ $LOG.error("#{e.inspect} #{e.backtrace.join("\n")}")
144
+ send_error(iq, ['bad-request', @object.errors.full_messages.first])
58
145
  end
59
146
 
60
147
  ##
@@ -67,13 +154,13 @@ module C3s
67
154
  send_error(iq, ['bad-request', nil])
68
155
  return
69
156
  end
70
-
157
+
71
158
  reply.type = :result
72
159
  reply.query.add(Jabber::Discovery::Identity.new(config['category'], config['description'], config['type']))
73
160
  reply.query.add(Jabber::Discovery::Feature.new(Jabber::Discovery::IqQueryDiscoInfo.new.namespace))
74
161
  reply.query.add(Jabber::Discovery::Feature.new(Jabber::Discovery::IqQueryDiscoItems.new.namespace))
75
162
 
76
- send(reply)
163
+ send!(reply)
77
164
  end
78
165
 
79
166
  ##
@@ -89,7 +176,7 @@ module C3s
89
176
  error = Jabber::ErrorResponse.new(err.first, err.last)
90
177
  reply.add error
91
178
 
92
- send(reply) if iq.type != :error
179
+ send!(reply) if iq.type != :error
93
180
  end
94
181
 
95
182
  ##
@@ -98,27 +185,41 @@ module C3s
98
185
  # data:: what to publish
99
186
  # changed:: the data is different from last set operation?
100
187
  def publish(iq, data, changed)
101
- jid = (iq.is_a?(Jabber::Iq)) ? iq.from.bare.to_s : iq
188
+ jid = (iq.is_a?(Jabber::Iq)) ? iq.from.to_s : iq
102
189
  if changed
103
- pub = Publisher.new(self, "pubsub."+config['url'])
104
- pub.create_nodes("/#{config['name']}/#{jid}")
190
+ pub = Publisher.new(self, config['pubsub'])
191
+ pub.create_nodes("#{config['name']}:#{jid}")
105
192
  pub.publish(jid, data)
106
193
  end
107
194
 
108
195
  send_ok(iq) if iq.is_a?(Jabber::Iq)
109
196
  end
110
197
 
198
+ def get_subscriptions
199
+ @pubsub = Jabber::PubSub::ServiceHelper.new(self, config['pubsub'])
200
+ subs = @pubsub.get_subscriptions_from_all_nodes
201
+ puts "SUBSCRIPTIONS: #{subs.inspect}"
202
+ subs
203
+ end
204
+
205
+ def unsubscribe_all
206
+ subscriptions = get_subscriptions
207
+ return if !@pubsub
208
+ subscriptions.each do |sub|
209
+ @pubsub.unsubscribe_from(sub.node, sub.subid)
210
+ end
211
+ end
212
+
111
213
  ##
112
214
  # Sends an OK response to a given iq
113
215
  # iq:: the iq to respond to
114
216
  def send_ok(iq)
115
- reply = Jabber::Iq.new()
217
+ reply = iq.answer
116
218
  reply.id = iq.id
117
219
  reply.to = iq.from
118
220
  reply.type = :result
119
- reply.add(Jabber::IqQuery::new)
120
221
 
121
- send(reply) if iq.type != :error
222
+ send!(reply) if iq.type != :error
122
223
  end
123
224
  end
124
225
 
@@ -1,9 +1,5 @@
1
1
  module C3s
2
- class ComponentConnection
3
- ##
4
- # The configuration file
5
- CONFIG_FILE = "component.yml"
6
-
2
+ class ComponentConnection
7
3
  def initialize(componentclass, options={})
8
4
  @no_db = options[:no_db]
9
5
  if !componentclass.superclass.eql?(C3s::Component)
@@ -11,8 +7,8 @@ module C3s
11
7
  exit
12
8
  end
13
9
 
14
- reader = C3s::ConfigReader.new(CONFIG_FILE, options)
15
- puts "Reading configurations from '#{CONFIG_FILE}'..."
10
+ reader = C3s::ConfigReader.new(options)
11
+ puts "Reading configurations from yaml file..."
16
12
  @server_config = reader.section('server')
17
13
  @client_config = reader.section('client')
18
14
 
@@ -37,12 +33,12 @@ module C3s
37
33
  exit
38
34
  end
39
35
  end
40
- connect()
36
+ connect
41
37
  end
42
38
 
43
39
  def connect
44
40
  puts "Connecting to #{@server_config['url']} (port #{@server_config['port']})..."
45
-
41
+
46
42
  begin
47
43
  @component.connect
48
44
  rescue Jabber::ComponentAuthenticationFailure => e
@@ -52,20 +48,22 @@ module C3s
52
48
  puts "Connection refused on #{@server_config['url']} (port #{@server_config['port']})"
53
49
  exit
54
50
  rescue Exception => e
55
- puts "Error do fim do mundo!"
56
- puts e.message
51
+ puts "ERROR: Couldn't connect to server!"
52
+ $LOG.error "Couldn't connect to server!"
57
53
  exit
58
54
  end
59
55
  puts "External component #{@client_config['jid']} connected successfully."
60
56
 
57
+ # TODO - never used?!
61
58
  @component.on_exception do |e, component, where|
62
- $LOG.error "FATAL ERROR"
59
+ $LOG.error "**************FATAL ERROR"
63
60
  $LOG.error e.message
64
61
  $LOG.error e.backtrace.join("\n")
62
+ exit
65
63
  end
66
64
 
67
65
  puts "Starting messaging loop..."
68
- @component.start()
66
+ @component.start
69
67
  end
70
68
 
71
69
  def self.stop
data/lib/configreader.rb CHANGED
@@ -6,11 +6,12 @@ module C3s
6
6
  SECTIONS = ['client', 'server', 'db']
7
7
 
8
8
  class ConfigReader
9
+
9
10
  ##
10
11
  # Reads the configuration file
11
- # file::[String] the configuration file
12
- def initialize(file, options={})
13
- @config = YAML::load_file(File.join(file))
12
+ def initialize(options={})
13
+ config_file = File.join(C3S_COMPONENT_DIR, 'component.yml')
14
+ @config = YAML::load_file(config_file)
14
15
 
15
16
  SECTIONS.delete('db') if options[:no_db]
16
17
  check_config
@@ -3,15 +3,18 @@ require 'active_record'
3
3
  module C3s
4
4
  class DatabaseAdapter
5
5
  def initialize(config)
6
+ log_file = File.join(C3S_LOG_DIR, "database.log")
7
+ db_file = File.join(C3S_COMPONENT_DIR, config['database'])
8
+
6
9
  ActiveRecord::Base.colorize_logging = false
7
- ActiveRecord::Base.logger = Logger.new(File.open('logs/database.log', 'a'))
10
+ ActiveRecord::Base.logger = Logger.new(File.open(log_file, 'a'))
8
11
 
9
12
  ActiveRecord::Base.establish_connection(
10
13
  :adapter => config['adapter'],
11
14
  :host => config['host'],
12
15
  :username => config['username'],
13
16
  :password => config['password'],
14
- :database => config['database'],
17
+ :database => db_file, # TODO works only for sqlite3 dbs!
15
18
  :encoding => config['encoding']
16
19
  )
17
20
  end
@@ -0,0 +1,47 @@
1
+ module C3s
2
+ class Node
3
+ PATTERN = /^(?:([^@\/:]*):?)?(?:([^@]*)@)??([^@\/]*)(?:\/(.*?))?$/
4
+
5
+ attr_reader :jid
6
+ attr_accessor :provider
7
+
8
+ ##
9
+ # Create a new c3s pubsub node. If called as new('provider:jid') or
10
+ # new('provider:jid/resource') parse the string and split (provider, jid, resource)
11
+ def initialize(provider = "", jid = nil)
12
+ @jid = jid
13
+ @provider = provider
14
+
15
+ if @jid.nil? and @provider
16
+ @provider, @node, @domain, @resource = @provider.to_s.scan(PATTERN).first
17
+ @jid = Jabber::JID.new(@node, @domain, @resource)
18
+ end
19
+
20
+ @provider.downcase! if @provider
21
+ end
22
+
23
+ ##
24
+ # Returns a string representation of the node
25
+ # * ""
26
+ # * "provider"
27
+ # * "provider:user@domain"
28
+ # * "provider:user@domain/resource"
29
+ def to_s
30
+ s = @provider
31
+ s = "#{s}:#{@jid.to_s}" if @jid
32
+ end
33
+
34
+ ##
35
+ # Returns the resource for this node
36
+ def resource
37
+ return nil unless @jid
38
+ @jid.resource
39
+ end
40
+
41
+ ##
42
+ # Checks if a node is a leaf node on c3s pubsub
43
+ def leaf?
44
+ resource ? true : false
45
+ end
46
+ end
47
+ end
File without changes
@@ -0,0 +1,118 @@
1
+ require 'xmpp4r/pubsub'
2
+ require 'pubsub/nodetracker'
3
+
4
+ module C3s
5
+ class Publisher
6
+ ##
7
+ # Initializes the publisher
8
+ # client:: [Jabber::Client] the client publishing
9
+ # service:: [String] pubsub service name (eg: pubsub.jabber)
10
+ def initialize(client, service_name)
11
+ @client = client
12
+ @service = service_name
13
+ @pubsub = Jabber::PubSub::ServiceHelper.new(@client, @service)
14
+ end
15
+
16
+ ##
17
+ # Creates the collection node(s) and leaf node if needed
18
+ # nodetree:: [String] node tree (eg: location:user@jabber.com/resource)
19
+ def create_nodes(nodetree)
20
+ nodes = nodetree.split(":")
21
+
22
+ # build array like this one:
23
+ # ['location', 'user@jabber.com', 'user@jabber.com/resource']
24
+ nodes.insert(1, nodes.last.split("/").first)
25
+
26
+ collection = nodes.shift # collection (eg: location)
27
+ subcollection = "#{collection}:#{nodes.shift}" # subcollection (eg: location:user@jabber.com)
28
+ leaf = "#{collection}:#{nodes.shift}" # leaf node name (eg: location:user@jabber.com/resource)
29
+ leaf << "/default" unless leaf.match(/.*\/.*/)
30
+
31
+ # create nodes
32
+ create_node(collection, {:collection => true})
33
+ create_node(subcollection, {:father => collection, :collection => true})
34
+ create_node(leaf, {:father => subcollection, :collection => false})
35
+ end
36
+
37
+ ##
38
+ # Creates a pubsub node
39
+ # nodename:: [String] the node name
40
+ # options:: [Hash] hash with options. These can be:
41
+ # * :collection => true or false
42
+ # * :father => the father node or nil if its root
43
+ def create_node(nodename, options={})
44
+ return if node_exists?(nodename)
45
+ config = Jabber::PubSub::NodeConfig.new
46
+
47
+ if options[:father]
48
+ config.options = config.options.merge({'pubsub#collection' => options[:father]})
49
+ end
50
+
51
+ if options[:collection]
52
+ node = create_collection_node(nodename, config)
53
+ else
54
+ node = create_leaf_node(nodename, config)
55
+ end
56
+
57
+ # grant owner to admin user (eg: admin@jabber.com)
58
+ grant_owner_to_admin(node)
59
+ end
60
+
61
+ ##
62
+ # Creates the collection node if needed
63
+ # name:: [String] collection node name
64
+ # config:: [PubSub::NodeConfig] node configuration
65
+ def create_collection_node(name, config)
66
+ $LOG.debug("Creating collection node #{name}...")
67
+ $LOG.debug("Node config: #{config.options.inspect}")
68
+ return if node_exists?(name)
69
+ node = @pubsub.create_collection_node(name, config)
70
+ end
71
+
72
+ ##
73
+ # Creates a leaf node to publish if needed
74
+ # This node must be associated with the collection node
75
+ # name:: [String] the name of the leaf node
76
+ # config:: [PubSub::NodeConfig] node configuration
77
+ def create_leaf_node(name, config)
78
+ $LOG.debug("Creating leaf node #{name}")
79
+ $LOG.debug("Node config: #{config.options.inspect}")
80
+ return if node_exists?(name)
81
+ node = @pubsub.create_node(name, config)
82
+ end
83
+
84
+ def grant_owner_to_admin(node)
85
+ return unless node
86
+ @pubsub.set_affiliations(node, "admin@#{@client.config['url']}", 'owner')
87
+ end
88
+
89
+ ##
90
+ # Publishes content to the leaf node
91
+ # node:: [String] the node to plublish to
92
+ # content:: [REXML::Element] content xml to publish into node
93
+ def publish(node, content)
94
+ item = Jabber::PubSub::Item.new
95
+ item.add(content)
96
+
97
+ node << "/default" unless node.match(/.*\/.*/)
98
+ node = [@client.config['name'], node].join(":")
99
+ @pubsub.publish_item_to(node, item)
100
+ end
101
+
102
+ ##
103
+ # Checks for existance of a node with a given name. This
104
+ # node can be a leaf or a collection
105
+ # name:: [String] the node name
106
+ def node_exists?(name)
107
+ return true if NodeTracker.include?(name)
108
+ nodebrowser = Jabber::PubSub::NodeBrowser.new(@client)
109
+ nodebrowser.get_info(@service, name)
110
+ # TODO this could be used instead
111
+ # nodebrowser.nodes(@client.jid).include?(name)
112
+ NodeTracker.add_node(name)
113
+ true
114
+ rescue Jabber::ServerError => error
115
+ return false if error.to_s.include?("item-not-found")
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,52 @@
1
+ require 'xmpp4r/pubsub'
2
+ require 'pubsub/nodetracker'
3
+
4
+ module C3s
5
+ class Subscriber
6
+ ##
7
+ # Initializes the publisher
8
+ # client:: [Jabber::Client] the client publishing
9
+ # service:: [String] pubsub service name (eg: pubsub.jabber)
10
+ def initialize(client, service_name)
11
+ @client = client
12
+ @service = service_name
13
+ @pubsub = Jabber::PubSub::ServiceHelper.new(@client, @service)
14
+ @browser = Jabber::PubSub::NodeBrowser.new(@client)
15
+ end
16
+
17
+ ##
18
+ # Subscribes to collection node.
19
+ # nodename:: [String] the node name
20
+ def subscribe_collection(nodename)
21
+ return if !is_collection?(nodename)
22
+ subscription = @pubsub.subscribe_to(nodename)
23
+ options = {
24
+ 'pubsub#subscription_type' => 'items',
25
+ 'pubsub#subscription_depth' => 'all'
26
+ }
27
+ @pubsub.set_options_for(nodename, @client.jid, options, subscription.subid)
28
+ end
29
+
30
+ ##
31
+ # Unsubscribe node
32
+ # nodename:: [String] the node name
33
+ def unsubscribe_from(nodename)
34
+ @pubsub.unsubscribe_from(nodename)
35
+ end
36
+
37
+ ##
38
+ # Checks if a node is a collection node
39
+ # nodename:: [String] the node name
40
+ def is_collection?(nodename)
41
+ info = @browser.get_info(@service, nodename)
42
+ info['type'].eql?('collection')
43
+ end
44
+
45
+ ##
46
+ # Returns the last item from a node. This node must be a leaf node.
47
+ # nodename:: [String] the node name
48
+ def get_last_item(nodename)
49
+ @pubsub.get_items_from(nodename, 1)
50
+ end
51
+ end
52
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: c3s
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.7
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ricardo Otero
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-12-16 00:00:00 +00:00
12
+ date: 2010-02-11 00:00:00 +00:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -28,13 +28,15 @@ extra_rdoc_files:
28
28
  - lib/configreader.rb
29
29
  - lib/databaseadapter.rb
30
30
  - lib/model.rb
31
- - lib/nodetracker.rb
32
- - lib/publisher.rb
31
+ - lib/pubsub/node.rb
32
+ - lib/pubsub/nodetracker.rb
33
+ - lib/pubsub/publisher.rb
34
+ - lib/pubsub/subscriber.rb
33
35
  files:
34
36
  - Manifest
35
37
  - README.rdoc
36
38
  - Rakefile
37
- - c3s.gemspec
39
+ - c3s
38
40
  - lib/c3s.rb
39
41
  - lib/c3s_logger.rb
40
42
  - lib/component.rb
@@ -42,8 +44,11 @@ files:
42
44
  - lib/configreader.rb
43
45
  - lib/databaseadapter.rb
44
46
  - lib/model.rb
45
- - lib/nodetracker.rb
46
- - lib/publisher.rb
47
+ - lib/pubsub/node.rb
48
+ - lib/pubsub/nodetracker.rb
49
+ - lib/pubsub/publisher.rb
50
+ - lib/pubsub/subscriber.rb
51
+ - c3s.gemspec
47
52
  has_rdoc: true
48
53
  homepage: http://github.com/rikas/c3s
49
54
  licenses: []
data/lib/publisher.rb DELETED
@@ -1,95 +0,0 @@
1
- require 'xmpp4r/pubsub'
2
- require 'nodetracker'
3
-
4
- module C3s
5
- class Publisher
6
- ##
7
- # Initializes the publisher
8
- # client:: [Jabber::Client] the client publishing
9
- # service:: [String] pubsub service name (eg: pubsub.jabber)
10
- def initialize(client, service_name)
11
- @client = client
12
- @service = service_name
13
- @pubsub = Jabber::PubSub::ServiceHelper.new(@client, @service)
14
- end
15
-
16
- ##
17
- # Creates the collection node(s) and leaf node if needed
18
- # nodetree:: [String] node tree (eg: /location/user@jabber.com)
19
- def create_nodes(nodetree)
20
- nodes = nodetree.split("/")
21
- nodes.delete("")
22
-
23
- # all nodes except the last are assumed as collection nodes
24
- last_collection = nil
25
- nodes[0..nodes.size-2].each do |name|
26
- create_collection_node(name) if !node_exists?(name)
27
- last_collection = name
28
- end
29
-
30
- # last node is assumed as a leaf node
31
- leaf = nodetree[1..nodetree.size-1] if nodetree[0..0].eql?"/"
32
- leaf.gsub!("/", ":")
33
- create_leaf_node(leaf, last_collection) if !node_exists?(leaf)
34
- end
35
-
36
- ##
37
- # Creates the collection node if needed
38
- # name:: [String] collection node name
39
- def create_collection_node(name)
40
- config = Jabber::PubSub::NodeConfig.new
41
- node = @pubsub.create_collection_node(name, config)
42
- grant_owner_to_admin(node)
43
- end
44
-
45
- ##
46
- # Creates a leaf node to publish if needed
47
- # This node must be associated with the collection node
48
- # name:: [String] the name of the leaf node
49
- # collection:: [String] the collection node that contains the node
50
- def create_leaf_node(name, collection)
51
- config = Jabber::PubSub::NodeConfig.new
52
- config.options = config.options.merge({'pubsub#collection' => collection})
53
- node = @pubsub.create_node(name, config)
54
- grant_owner_to_admin(node)
55
- end
56
-
57
- def grant_owner_to_admin(node)
58
- return unless node
59
- @pubsub.set_affiliations(node, "admin@#{@client.config['url']}", 'owner')
60
- end
61
-
62
- ##
63
- # Publishes content to the leaf node
64
- # node:: [String] the node to plublish to
65
- # content:: [REXML::Element] content xml to publish into node
66
- def publish(node, content)
67
- item = Jabber::PubSub::Item.new
68
- item.add(content)
69
- node = [@client.config['name'], node].join(":")
70
- @pubsub.publish_item_to(node, item)
71
- end
72
-
73
- def fix_permissions
74
- nodebrowser = Jabber::PubSub::NodeBrowser.new(@client)
75
- nodes = nodebrowser.nodes_names(@service)
76
- nodes.each do |node|
77
- grant_owner_to_admin(node['node'])
78
- end
79
- end
80
-
81
- ##
82
- # Checks for existance of a node with a given name. This
83
- # node can be a leaf or a collection
84
- # name:: [String] the node name
85
- def node_exists?(name)
86
- return true if NodeTracker.include?(name)
87
- nodebrowser = Jabber::PubSub::NodeBrowser.new(@client)
88
- nodebrowser.get_info(@service, name)
89
- NodeTracker.add_node(name)
90
- true
91
- rescue Jabber::ServerError => error
92
- return false if error.to_s.include?("item-not-found")
93
- end
94
- end
95
- end