torquebox-configure 2.0.0.beta1-java

Sign up to get free protection for your applications and to get access to all the features.
data/lib/gem_hook.rb ADDED
@@ -0,0 +1,19 @@
1
+ # Copyright 2008-2011 Red Hat, Inc, and individual contributors.
2
+ #
3
+ # This is free software; you can redistribute it and/or modify it
4
+ # under the terms of the GNU Lesser General Public License as
5
+ # published by the Free Software Foundation; either version 2.1 of
6
+ # the License, or (at your option) any later version.
7
+ #
8
+ # This software is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public
14
+ # License along with this software; if not, write to the Free
15
+ # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
16
+ # 02110-1301 USA, or see the FSF site: http://www.fsf.org.
17
+
18
+ require 'torquebox/configure'
19
+ require 'torquebox/configuration/global'
@@ -0,0 +1,209 @@
1
+ # Copyright 2008-2011 Red Hat, Inc, and individual contributors.
2
+ #
3
+ # This is free software; you can redistribute it and/or modify it
4
+ # under the terms of the GNU Lesser General Public License as
5
+ # published by the Free Software Foundation; either version 2.1 of
6
+ # the License, or (at your option) any later version.
7
+ #
8
+ # This software is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public
14
+ # License along with this software; if not, write to the Free
15
+ # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
16
+ # 02110-1301 USA, or see the FSF site: http://www.fsf.org.
17
+
18
+ require 'torquebox/configure'
19
+ require 'torquebox/configuration'
20
+
21
+ module TorqueBox
22
+ module Configuration
23
+ class GlobalConfiguration < TorqueBox::Configuration::Configuration
24
+ def self.load_configuration(file)
25
+ config = new
26
+ TorqueBox::Configuration.load_configuration( file, config, ENTRY_MAP )
27
+ config.to_metadata_hash
28
+ end
29
+
30
+ ENTRY_MAP = lambda do
31
+ destination_entry =
32
+ ThingWithOptionsEntry.with_settings(:validate => {
33
+ :optional => [
34
+ { :create => [true, false] },
35
+ { :durable => [true, false] },
36
+ :processor,
37
+ :remote_host
38
+ ]
39
+ })
40
+ {
41
+ :authentication => ThingWithOptionsEntry.with_settings( :validate => {
42
+ :required => [:domain],
43
+ :optional => [:credential]
44
+ }),
45
+ :credential => ThingsEntry.with_settings(:require_parent => [:authentication],
46
+ :discrete => true),
47
+ :environment => OptionsEntry,
48
+ :job => ThingWithOptionsEntry.with_settings(:discrete => true,
49
+ :validate => {
50
+ :required => [:cron],
51
+ :optional => [
52
+ :config,
53
+ :name,
54
+ { :singleton => [true, false] }
55
+ ]
56
+ }),
57
+ :options_for => ThingWithOptionsEntry.with_settings(:validate => {
58
+ :optional => [
59
+ :concurrency,
60
+ { :disabled => [true, false] },
61
+ :default_message_encoding
62
+ ]
63
+ }),
64
+ :pool => ThingWithOptionsEntry.with_settings(:validate => {
65
+ :required => [{ :type => [:bounded, :shared] }],
66
+ :optional => [:min, :max]
67
+ }),
68
+ :processor => ThingWithOptionsEntry.with_settings(:require_parent => [:queue, :topic],
69
+ :discrete => true,
70
+ :validate => {
71
+ :optional => [
72
+ :concurrency,
73
+ { :singleton => [true, false] },
74
+ :config,
75
+ :filter,
76
+ :name
77
+ ]
78
+ }),
79
+ :queue => destination_entry,
80
+ :ruby => OptionsEntry.with_settings(:validate => {
81
+ :optional => [{ :version => ['1.8', '1.9'] },
82
+ { :compile_mode => [:force, :jit, :off,
83
+ 'force', 'jit', 'off'] },
84
+ { :debug => [true, false] },
85
+ { :interactive => [true, false] }
86
+ ]
87
+ }),
88
+ :service => ThingWithOptionsEntry.with_settings(:discrete => true,
89
+ :validate => {
90
+ :optional => [
91
+ :config,
92
+ :name,
93
+ { :singleton => [true, false] }
94
+ ]
95
+ }),
96
+ :stomp => OptionsEntry.with_settings(:validate => { :required => [:host] } ),
97
+ :stomplet => ThingWithOptionsEntry.with_settings( :discrete => true,
98
+ :validate => {
99
+ :required => [ :route ],
100
+ :optional => [ :config, :name ] } ),
101
+
102
+ :topic => destination_entry,
103
+ :web => OptionsEntry.with_settings(:validate => {
104
+ :optional => [:context, :host, :rackup, :static, :'session-timeout' ]
105
+ })
106
+ }
107
+ end.call
108
+
109
+
110
+ def to_metadata_hash
111
+ metadata = Hash.new { |hash, key| hash[key] = Hash.new { |hash, key| hash[key] = { } } }
112
+
113
+ self[TorqueBox::CONFIGURATION_ROOT].each do |entry_name, entry_data|
114
+ case entry_name
115
+ when 'authentication' # => auth:
116
+ entry_data.each do |name, data|
117
+ (data.delete('credential') || []).each do |user, password|
118
+ data['credentials'] ||= {}
119
+ data['credentials'][user] = password
120
+ end
121
+ metadata['auth'][name] = data
122
+ end
123
+
124
+ when 'job' # => jobs:
125
+ entry_data.each do |klass, data|
126
+ name = data.delete( :name ) || unique_name( klass.to_s, metadata['jobs'].keys )
127
+ job = metadata['jobs'][name]
128
+ job['job'] = klass.to_s
129
+ job.merge!( data )
130
+ end
131
+
132
+ when 'options_for' # => tasks:, messaging:\n default_message_encoding:
133
+ if (messaging_opts = entry_data.delete( 'messaging' )) &&
134
+ (default_encoding = messaging_opts.delete( :default_message_encoding ))
135
+ metadata['messaging']['default_message_encoding'] = default_encoding.to_s
136
+ end
137
+
138
+ entry_data.each do |name, data|
139
+ data[:concurrency] = 0 if data.delete( :disabled )
140
+ data[:concurrency] &&= data[:concurrency].to_java(java.lang.Integer)
141
+ metadata['tasks'][name] = data
142
+ end
143
+
144
+ when 'pool' # => pooling:
145
+ entry_data.each do |name, data|
146
+ pool_type = data.delete( :type )
147
+ if pool_type.to_s == 'shared'
148
+ metadata['pooling'][name] = 'shared'
149
+ else
150
+ metadata['pooling'][name] = data
151
+ end
152
+ end
153
+
154
+ when 'queue', 'topic' # => queues:/topics: & messaging:
155
+ entry_data.each do |name, data|
156
+ metadata[entry_name + 's'][name] = data unless data.delete( :create ) === false
157
+ (data.delete( 'processor' ) || []).each do |processor|
158
+ processor_class, processor_options = processor
159
+ processor_options[:concurrency] &&= processor_options[:concurrency].to_java(java.lang.Integer)
160
+ metadata['messaging'][name][processor_class] = processor_options
161
+ end
162
+ end
163
+
164
+ when 'service' # => services:
165
+ entry_data.each do |klass, data|
166
+ name = data.delete( :name )
167
+ if name
168
+ data[:service] = klass.to_s
169
+ else
170
+ name = klass.to_s
171
+ end
172
+ metadata['services'][name] = data
173
+ end
174
+
175
+ when 'stomplet'
176
+ entry_data.each do |klass, data|
177
+ name = data.delete( :name ) || unique_name( klass.to_s, metadata['stomp']['stomplets'].keys )
178
+ stomplet = metadata['stomp']['stomplets'][name] = {}
179
+ stomplet['class'] = klass.to_s
180
+ stomplet.merge!( data )
181
+ end
182
+
183
+ else # => <entry_name>: (handles environment, ruby, stomp, web)
184
+ metadata[entry_name].merge!( entry_data )
185
+ end
186
+ end
187
+
188
+ hash_to_hashmap( metadata )
189
+ end
190
+
191
+ def hash_to_hashmap(hash)
192
+ hashmap = java.util.HashMap.new
193
+ hash.each do |key, value|
194
+ value = hash_to_hashmap( value ) if value.is_a?( Hash )
195
+ hashmap[key.to_s] = value
196
+ end
197
+ hashmap
198
+ end
199
+
200
+ protected
201
+ def unique_name(name, set, suffix = nil)
202
+ name = "#{name}-#{suffix}" if suffix
203
+ name = unique_name( name, set, suffix.to_i + 1 ) if set.include?( name )
204
+ name
205
+ end
206
+ end
207
+ end
208
+ end
209
+
@@ -0,0 +1,91 @@
1
+ # Copyright 2008-2011 Red Hat, Inc, and individual contributors.
2
+ #
3
+ # This is free software; you can redistribute it and/or modify it
4
+ # under the terms of the GNU Lesser General Public License as
5
+ # published by the Free Software Foundation; either version 2.1 of
6
+ # the License, or (at your option) any later version.
7
+ #
8
+ # This software is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public
14
+ # License along with this software; if not, write to the Free
15
+ # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
16
+ # 02110-1301 USA, or see the FSF site: http://www.fsf.org.
17
+
18
+ require 'torquebox/configuration'
19
+
20
+ module TorqueBox
21
+ module Configuration
22
+ class Validator
23
+
24
+ def initialize(ruleset, entry, options_to_validate)
25
+ @required = ruleset[:required] || []
26
+ @allowed = @required + (ruleset[:optional] || [])
27
+ @entry = entry
28
+ @options_to_validate = options_to_validate
29
+ validate
30
+ end
31
+
32
+
33
+ def valid?
34
+ !message
35
+ end
36
+
37
+ def message
38
+ case messages.size
39
+ when 0
40
+ nil
41
+ when 1
42
+ messages.first
43
+ else
44
+ result = "There are multiple messages for this entry:"
45
+ messages.each { |message| result << "\n " << message }
46
+ result
47
+ end
48
+ end
49
+
50
+ protected
51
+ def messages
52
+ @messages ||= []
53
+ end
54
+
55
+ def validate
56
+ validate_required
57
+ validate_allowed
58
+ validate_values
59
+ end
60
+
61
+ def validate_required
62
+ keys_for( @required ).each do |required|
63
+ messages << "Required option :#{required} is missing on '#{@entry}'" unless @options_to_validate.keys.map(&:to_s).include?( required )
64
+ end
65
+ end
66
+
67
+ def validate_allowed
68
+ @options_to_validate.keys.map(&:to_s).each do |option|
69
+ messages << "Option :#{option} is not allowed on '#{@entry}'" unless keys_for( @allowed ).include?( option )
70
+ end
71
+ end
72
+
73
+ def validate_values
74
+ @allowed.each do |allowed|
75
+ if allowed.is_a?( Hash )
76
+ key = allowed.keys.first
77
+ if @options_to_validate.has_key?( key ) && !allowed[key].include?( @options_to_validate[key] )
78
+ messages << "#{@options_to_validate[key].inspect} is not a valid value for #{key.inspect} on '#{@entry}'. Valid values are #{allowed[key].inspect}"
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ def keys_for(ary)
85
+ ary.collect do |value|
86
+ (value.is_a?( Hash ) ? value.keys.first : value).to_s
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,190 @@
1
+ # Copyright 2008-2011 Red Hat, Inc, and individual contributors.
2
+ #
3
+ # This is free software; you can redistribute it and/or modify it
4
+ # under the terms of the GNU Lesser General Public License as
5
+ # published by the Free Software Foundation; either version 2.1 of
6
+ # the License, or (at your option) any later version.
7
+ #
8
+ # This software is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public
14
+ # License along with this software; if not, write to the Free
15
+ # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
16
+ # 02110-1301 USA, or see the FSF site: http://www.fsf.org.
17
+
18
+ require 'blankslate'
19
+ require 'torquebox/configuration/validator'
20
+
21
+ module TorqueBox
22
+ module Configuration
23
+
24
+ def self.load_configuration(file, config, entry_map)
25
+ Thread.current[:torquebox_config] = config
26
+ Thread.current[:torquebox_config_entry_map] = entry_map
27
+ eval( File.read( file ) )
28
+ config
29
+ end
30
+
31
+ def self.const_missing(name)
32
+ FakeConstant.new( name )
33
+ end
34
+
35
+ class Entry < BlankSlate
36
+ def initialize(name, config, entry_map, options = { })
37
+ @name = name
38
+ @config = config
39
+ @entry_map = entry_map
40
+ @parents = options.delete( :parents ) || []
41
+ @options = options
42
+ @line_number = find_line_number
43
+ @entry_options = { }
44
+
45
+ if options[:require_parent] && ([options[:require_parent]].flatten & @parents).empty?
46
+ raise ConfigurationError.new( "#{@name} only allowed inside #{options[:require_parent]}", @line_number )
47
+ end
48
+ end
49
+
50
+ def find_line_number
51
+ caller.each do |line|
52
+ return $1 if line =~ /\(eval\):(\d+):/
53
+ end
54
+ nil
55
+ end
56
+
57
+ def process(*args, &block)
58
+ process_args( args )
59
+ eval_block( &block ) if block_given?
60
+ validate_options
61
+ finalize_options
62
+ local_config
63
+ end
64
+
65
+ def process_args(unused)
66
+ # no op
67
+ @config
68
+ end
69
+
70
+ def validate_options
71
+ if @options[:validate]
72
+ validator = Validator.new( @options[:validate], @name, @entry_options )
73
+ raise ConfigurationError.new( validator.message, @line_number ) unless validator.valid?
74
+ end
75
+ end
76
+
77
+ def eval_block(&block)
78
+ block.arity < 1 ? self.instance_eval( &block ) : block.call( self )
79
+ end
80
+
81
+ def self.const_missing(name)
82
+ FakeConstant.new( name )
83
+ end
84
+
85
+ def self.with_settings(options)
86
+ klass = self
87
+ proxy = Object.new
88
+ (class << proxy; self; end).__send__( :define_method, :new ) do |*args|
89
+ if args.last.is_a?( Hash )
90
+ args.last.merge!( options )
91
+ else
92
+ args << options
93
+ end
94
+ klass.new( *args )
95
+ end
96
+ proxy
97
+ end
98
+
99
+ alias_method :send, :__send__
100
+
101
+ def method_missing(method, *args, &block)
102
+ klass = @entry_map[method]
103
+ if klass
104
+ entry = klass.new( method, @entry_options, @entry_map, :parents => @parents + [@name] )
105
+ entry.process( *args, &block )
106
+ else
107
+ add_options( method.to_sym => args.first )
108
+ end
109
+ end
110
+
111
+ def add_options( option )
112
+ @entry_options.merge!( option )
113
+ end
114
+
115
+ def finalize_options
116
+ if @options[:discrete]
117
+ local_config << @entry_options
118
+ else
119
+ @entry_options = local_config.merge!( @entry_options )
120
+ end
121
+ local_config
122
+ end
123
+
124
+ def local_config
125
+ @config[@name.to_s] = [] if @options[:discrete] && !@config[@name.to_s].is_a?(Array)
126
+ @config[@name.to_s] ||= {}
127
+ end
128
+
129
+ def local_config=(value)
130
+ @config[@name.to_s] = value
131
+ end
132
+ end
133
+
134
+ class OptionsEntry < Entry
135
+ def process_args(args)
136
+ hash = args.first || { }
137
+ raise ConfigurationError.new( "'#{@name}' takes a hash (and only a hash)", @line_number ) if !hash.is_a?(Hash) || args.length > 1
138
+ add_options( hash )
139
+ end
140
+ end
141
+
142
+ class ThingWithOptionsEntry < Entry
143
+ def process_args(args)
144
+ @thing, hash = args
145
+ add_options( hash || {} )
146
+ end
147
+
148
+ def finalize_options
149
+ if @options[:discrete]
150
+ local_config << [@thing.to_s, @entry_options]
151
+ else
152
+ local_config[@thing.to_s] = { } unless local_config[@thing.to_s]
153
+ @entry_options = local_config[@thing.to_s].merge!( @entry_options )
154
+ end
155
+ end
156
+ end
157
+
158
+ class ThingsEntry < Entry
159
+ def process_args(args)
160
+ @entry_options = args.map(&:to_s)
161
+ local_config
162
+ end
163
+ end
164
+
165
+
166
+ class Configuration < Hash
167
+ def initialize
168
+ super { |hash, key| hash[key] = { } }
169
+ end
170
+ end
171
+
172
+ class FakeConstant
173
+ def initialize(name)
174
+ @name = name.to_s
175
+ end
176
+
177
+ def to_s
178
+ @name
179
+ end
180
+ end
181
+
182
+ class ConfigurationError < RuntimeError
183
+ def initialize(message, line_number = nil)
184
+ message += " (line #{line_number})" if line_number
185
+ super(message)
186
+ end
187
+ end
188
+
189
+ end
190
+ end
@@ -0,0 +1,31 @@
1
+ # Copyright 2008-2011 Red Hat, Inc, and individual contributors.
2
+ #
3
+ # This is free software; you can redistribute it and/or modify it
4
+ # under the terms of the GNU Lesser General Public License as
5
+ # published by the Free Software Foundation; either version 2.1 of
6
+ # the License, or (at your option) any later version.
7
+ #
8
+ # This software is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
+ # Lesser General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU Lesser General Public
14
+ # License along with this software; if not, write to the Free
15
+ # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
16
+ # 02110-1301 USA, or see the FSF site: http://www.fsf.org.
17
+
18
+ require 'torquebox/configuration'
19
+
20
+ module TorqueBox
21
+ CONFIGURATION_ROOT = '<root>'
22
+
23
+ def self.configure(&block)
24
+ config = Thread.current[:torquebox_config]
25
+ entry_map = Thread.current[:torquebox_config_entry_map]
26
+ Configuration::Entry.new( CONFIGURATION_ROOT, config, entry_map, :allow_block => true ).
27
+ process( nil, &block )
28
+ config
29
+ end
30
+
31
+ end
Binary file
@@ -0,0 +1,13 @@
1
+ module TorqueboxConfigure
2
+ VERSION = '2.0.0.beta1'
3
+ MAVEN_VERSION = '2.0.0.beta1'
4
+ end
5
+ begin
6
+ require 'java'
7
+ require File.dirname(__FILE__) + '/torquebox-configure.jar'
8
+ rescue LoadError
9
+ puts 'JAR-based gems require JRuby to load. Please visit www.jruby.org.'
10
+ raise
11
+ end
12
+
13
+ load File.dirname(__FILE__) + '/gem_hook.rb' if File.exists?( File.dirname(__FILE__) + '/gem_hook.rb')