buildr 1.3.2-java → 1.3.3-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. data/CHANGELOG +66 -4
  2. data/{README → README.rdoc} +29 -16
  3. data/Rakefile +16 -20
  4. data/_buildr +38 -0
  5. data/addon/buildr/cobertura.rb +49 -45
  6. data/addon/buildr/emma.rb +238 -0
  7. data/addon/buildr/jetty.rb +1 -1
  8. data/addon/buildr/nailgun.rb +585 -661
  9. data/{lib/buildr/java → addon/buildr}/org/apache/buildr/BuildrNail$Main.class +0 -0
  10. data/{lib/buildr/java → addon/buildr}/org/apache/buildr/BuildrNail.class +0 -0
  11. data/{lib/buildr/java → addon/buildr}/org/apache/buildr/BuildrNail.java +0 -0
  12. data/bin/buildr +9 -2
  13. data/buildr.buildfile +53 -0
  14. data/buildr.gemspec +21 -14
  15. data/doc/css/default.css +51 -48
  16. data/doc/css/print.css +60 -55
  17. data/doc/images/favicon.png +0 -0
  18. data/doc/images/growl-icon.tiff +0 -0
  19. data/doc/images/project-structure.png +0 -0
  20. data/doc/pages/artifacts.textile +46 -156
  21. data/doc/pages/building.textile +63 -323
  22. data/doc/pages/contributing.textile +112 -102
  23. data/doc/pages/download.textile +19 -27
  24. data/doc/pages/extending.textile +27 -81
  25. data/doc/pages/getting_started.textile +44 -119
  26. data/doc/pages/index.textile +26 -47
  27. data/doc/pages/languages.textile +407 -0
  28. data/doc/pages/more_stuff.textile +92 -173
  29. data/doc/pages/packaging.textile +71 -239
  30. data/doc/pages/projects.textile +58 -233
  31. data/doc/pages/recipes.textile +19 -43
  32. data/doc/pages/settings_profiles.textile +39 -104
  33. data/doc/pages/testing.textile +41 -304
  34. data/doc/pages/troubleshooting.textile +29 -47
  35. data/doc/pages/whats_new.textile +69 -167
  36. data/doc/print.haml +0 -1
  37. data/doc/print.toc.yaml +1 -0
  38. data/doc/scripts/buildr-git.rb +1 -1
  39. data/doc/site.haml +1 -0
  40. data/doc/site.toc.yaml +8 -5
  41. data/{KEYS → etc/KEYS} +0 -0
  42. data/etc/git-svn-authors +16 -0
  43. data/lib/buildr.rb +2 -5
  44. data/lib/buildr/core/application.rb +192 -98
  45. data/lib/buildr/core/build.rb +140 -91
  46. data/lib/buildr/core/checks.rb +5 -5
  47. data/lib/buildr/core/common.rb +1 -1
  48. data/lib/buildr/core/compile.rb +12 -10
  49. data/lib/buildr/core/filter.rb +151 -46
  50. data/lib/buildr/core/generate.rb +9 -9
  51. data/lib/buildr/core/progressbar.rb +1 -1
  52. data/lib/buildr/core/project.rb +8 -7
  53. data/lib/buildr/core/test.rb +51 -26
  54. data/lib/buildr/core/transports.rb +22 -38
  55. data/lib/buildr/core/util.rb +78 -26
  56. data/lib/buildr/groovy.rb +18 -0
  57. data/lib/buildr/groovy/bdd.rb +105 -0
  58. data/lib/buildr/groovy/compiler.rb +138 -0
  59. data/lib/buildr/ide/eclipse.rb +102 -71
  60. data/lib/buildr/ide/idea.rb +7 -12
  61. data/lib/buildr/ide/idea7x.rb +7 -8
  62. data/lib/buildr/java.rb +4 -7
  63. data/lib/buildr/java/ant.rb +26 -5
  64. data/lib/buildr/java/bdd.rb +449 -0
  65. data/lib/buildr/java/commands.rb +9 -9
  66. data/lib/buildr/java/{compilers.rb → compiler.rb} +8 -90
  67. data/lib/buildr/java/jruby.rb +29 -11
  68. data/lib/buildr/java/jtestr_runner.rb.erb +116 -0
  69. data/lib/buildr/java/packaging.rb +23 -16
  70. data/lib/buildr/java/pom.rb +1 -1
  71. data/lib/buildr/java/rjb.rb +21 -8
  72. data/lib/buildr/java/test_result.rb +308 -0
  73. data/lib/buildr/java/tests.rb +324 -0
  74. data/lib/buildr/packaging/artifact.rb +12 -11
  75. data/lib/buildr/packaging/artifact_namespace.rb +7 -4
  76. data/lib/buildr/packaging/gems.rb +3 -3
  77. data/lib/buildr/packaging/zip.rb +13 -10
  78. data/lib/buildr/resources/buildr.icns +0 -0
  79. data/lib/buildr/scala.rb +19 -0
  80. data/lib/buildr/scala/compiler.rb +109 -0
  81. data/lib/buildr/scala/tests.rb +203 -0
  82. data/rakelib/apache.rake +71 -45
  83. data/rakelib/doc.rake +2 -2
  84. data/rakelib/package.rake +3 -2
  85. data/rakelib/rspec.rake +23 -21
  86. data/rakelib/setup.rake +34 -9
  87. data/rakelib/stage.rake +4 -1
  88. data/spec/addon/cobertura_spec.rb +77 -0
  89. data/spec/addon/emma_spec.rb +120 -0
  90. data/spec/addon/test_coverage_spec.rb +255 -0
  91. data/spec/{application_spec.rb → core/application_spec.rb} +82 -4
  92. data/spec/{artifact_namespace_spec.rb → core/artifact_namespace_spec.rb} +12 -1
  93. data/spec/core/build_spec.rb +415 -0
  94. data/spec/{checks_spec.rb → core/checks_spec.rb} +2 -2
  95. data/spec/{common_spec.rb → core/common_spec.rb} +119 -30
  96. data/spec/{compile_spec.rb → core/compile_spec.rb} +17 -13
  97. data/spec/core/generate_spec.rb +33 -0
  98. data/spec/{project_spec.rb → core/project_spec.rb} +9 -6
  99. data/spec/{test_spec.rb → core/test_spec.rb} +222 -28
  100. data/spec/{transport_spec.rb → core/transport_spec.rb} +5 -9
  101. data/spec/groovy/bdd_spec.rb +80 -0
  102. data/spec/{groovy_compilers_spec.rb → groovy/compiler_spec.rb} +1 -1
  103. data/spec/ide/eclipse_spec.rb +243 -0
  104. data/spec/{java_spec.rb → java/ant.rb} +7 -17
  105. data/spec/java/bdd_spec.rb +358 -0
  106. data/spec/{java_compilers_spec.rb → java/compiler_spec.rb} +1 -1
  107. data/spec/java/java_spec.rb +88 -0
  108. data/spec/{java_packaging_spec.rb → java/packaging_spec.rb} +65 -4
  109. data/spec/{java_test_frameworks_spec.rb → java/tests_spec.rb} +31 -10
  110. data/spec/{archive_spec.rb → packaging/archive_spec.rb} +12 -2
  111. data/spec/{artifact_spec.rb → packaging/artifact_spec.rb} +12 -5
  112. data/spec/{packaging_helper.rb → packaging/packaging_helper.rb} +0 -0
  113. data/spec/{packaging_spec.rb → packaging/packaging_spec.rb} +1 -1
  114. data/spec/sandbox.rb +22 -5
  115. data/spec/{scala_compilers_spec.rb → scala/compiler_spec.rb} +1 -1
  116. data/spec/{scala_test_frameworks_spec.rb → scala/tests_spec.rb} +11 -12
  117. data/spec/spec_helpers.rb +38 -17
  118. metadata +93 -70
  119. data/lib/buildr/java/bdd_frameworks.rb +0 -265
  120. data/lib/buildr/java/groovyc.rb +0 -137
  121. data/lib/buildr/java/test_frameworks.rb +0 -450
  122. data/spec/build_spec.rb +0 -193
  123. data/spec/java_bdd_frameworks_spec.rb +0 -238
  124. data/spec/spec.opts +0 -6
@@ -44,7 +44,7 @@ module Buildr
44
44
  class Jetty
45
45
 
46
46
  # Which version of Jetty we're using by default (change with options.jetty.version).
47
- VERSION = "6.1.3" unless const_defined?('VERSION')
47
+ VERSION = "6.1.3"
48
48
  SLF4J_VERSION = "1.4.3"
49
49
 
50
50
  # Libraries used by Jetty.
@@ -13,7 +13,6 @@
13
13
  # License for the specific language governing permissions and limitations under
14
14
  # the License.
15
15
 
16
-
17
16
  require 'benchmark'
18
17
  require 'jruby'
19
18
  require 'monitor'
@@ -22,52 +21,25 @@ require 'rbconfig'
22
21
  require 'thread'
23
22
  require 'buildr/core/application_cli'
24
23
 
25
- module Buildr
24
+ module Buildr #:nodoc:
25
+
26
+ module Nailgun
26
27
 
27
- # See the nailgun_help method for documentation.
28
- module Nailgun # :nodoc:
29
28
  extend self
30
29
 
30
+ attr_reader :ng
31
+ @ng ||= OpenStruct.new
32
+
31
33
  VERSION = '0.7.1'
32
34
  NAME = "nailgun-#{VERSION}"
33
35
  URL = "http://downloads.sourceforge.net/nailgun/#{NAME}.zip"
34
36
  ARTIFACT_SPEC = "com.martiansoftware:nailgun:jar:#{VERSION}"
37
+
38
+ # Paths used to initialize a buildr runtime
35
39
  BUILDR_PATHS = [File.expand_path('../', File.dirname(__FILE__)),
36
40
  File.expand_path('../../lib', File.dirname(__FILE__))]
37
-
38
- attr_accessor :artifact
39
- attr_accessor :server, :port, :jruby_queue_size, :buildr_queue_size
40
- attr_accessor :jruby_home, :home
41
-
42
- self.jruby_home = if PLATFORM =~ /java/
43
- Config::CONFIG['prefix']
44
- else
45
- ENV['JRUBY_HOME'] || File.join(ENV['HOME'], '.jruby')
46
- end
47
-
48
- self.home = ENV['NAILGUN_HOME'] || File.join(jruby_home, 'tool', 'nailgun')
49
- self.server = 'localhost'
50
- self.port = 2113
51
- self.jruby_queue_size = 3
52
- self.buildr_queue_size = 3
53
-
54
- def namespace(&block)
55
- if Object.const_defined?(:Rake)
56
- Rake.application.in_namespace(:nailgun, &block)
57
- end
58
- end
59
41
 
60
- def boot(&block)
61
- if block
62
- @boot = block
63
- else
64
- @boot.call
65
- end
66
- end
67
-
68
- module Application
69
- def nailgun_help
70
- " " + <<-DESC.strip.gsub(/ *\n +/, "\n ")
42
+ HELP = <<-HELP.strip.gsub(/ *\n +/, "\n ")
71
43
  NailGun is a client, protocol, and server for running Java
72
44
  programs from the command line without incurring the JVM
73
45
  startup overhead. Nailgun integration is currently available
@@ -98,8 +70,8 @@ module Buildr
98
70
  # will be loaded on a previously loaded fresh-buildr runtime
99
71
  # and it will be cached.
100
72
  cd /some/buildr/project
101
- ng nailgun:help # display nailgun help
102
- ng nailgun:tasks # display overview of ng tasks
73
+ ng nailgun:help # display nailgun help
74
+ ng nailgun:tasks # display overview of ng tasks
103
75
  ng clean compile # just invoke those two tasks
104
76
 
105
77
  Configuration and Environment Variables.
@@ -111,223 +83,202 @@ module Buildr
111
83
 
112
84
  You can override this environment variable to tell buildr where
113
85
  to find or where to install nailgun. If missing, NAILGUN_HOME
114
- defaults to the $JRUBY_HOME/tool/nailgun directory. You can
115
- also specify the nailgun_home on your buildfile with the following
116
- code:
117
-
118
- require 'buildr/nailgun'
119
- Buildr::Nailgun.home = File.expand_path('~/.jruby/tool/nailgun')
86
+ defaults to the $JRUBY_HOME/tool/nailgun directory.
120
87
 
121
88
  Buildr will also check that the nailgun client binary (ng.exe for
122
89
  Windows systems, ng otherwise) is installed on NAILGUN_HOME.
123
90
  If no binary is found, buildr will download nailgun and
124
- compile+install it.
125
-
91
+ compile+install it.
126
92
 
127
93
  The buildr server binds itself to localhost, port 2113. You can
128
- override this on your buildfile, by placing the following code:
94
+ override this when starting the nailgun server:
129
95
 
130
- require 'buildr/nailgun'
131
- Buildr::Nailgun.server = '127.0.0.1'
132
- Buildr::Nailgun.port = 2233
96
+ buildr nailgun:start[4444,127.0.0.1]
133
97
 
134
98
  If you provided custom host/port settings you need
135
- to tell the nailgun client where to connect to:
136
-
137
- ng --nailgun-server 127.0.0.1 --nailgun-port 2233 nailgun:tasks
138
-
139
- The buildr server starts a BuildrFactory responsible for providing
140
- a pool of JRuby runtimes configured and ready for task execution.
141
- This BuildrFactory consists of two queues: One of pure JRuby runtimes
142
- with almost nothing loaded, and another of Buildr runtimes (consumed
143
- from the first queue) with the Buildr runtime preloaded but without
144
- any project definition. The jruby queue is used for sandboxing code
145
- like running GetoptLong, but most importantly its the place where
146
- buildr runtimes begin life, to be later added on the buildr queue.
147
- By default both queues are of size 3, you can customize this with:
148
-
149
- require 'buildr/nailgun'
150
- Buildr::Nailgun.jruby_queue_size = 4 # JRuby creation is fast!
151
- Buildr::Nailgun.buildr_queue_size = 5 # loading buildr takes longer
152
-
153
- The buildr_queue_size is of particular importance if you expect to
154
- reload lots of buildfiles.
99
+ to tell the nailgun client where to connect:
100
+
101
+ ng --nailgun-server 127.0.0.1 --nailgun-port 4444 nailgun:tasks
102
+
103
+ The buildr server starts a RuntimeFactory responsible for providing
104
+ a pool of preloaded Buildr runtimes ready for task execution.
105
+ You can provide a third argument to the nailgun:start task, to set
106
+ the buildr queue size. You may want to increase this value if you
107
+ need to load many buildfiles on the same server.
155
108
 
156
109
  Execute nailgun:tasks get an overview of available nailgun tasks.
157
-
158
- DESC
110
+ HELP
111
+
112
+ private
113
+
114
+ # Returns the path to JRUBY_HOME.
115
+ def jruby_home
116
+ ENV['JRUBY_HOME'] || Config::CONFIG['prefix']
117
+ end
118
+
119
+ # Returns the path to NAILGUN_HOME.
120
+ def nailgun_home
121
+ ENV['NAILGUN_HOME'] || File.expand_path('tool/nailgun', jruby_home)
122
+ end
123
+
124
+ def tmp_path(*paths)
125
+ File.join(Dir.tmpdir, 'nailgun', *paths)
126
+ end
127
+
128
+ file_tasks = lambda do
129
+
130
+ dist_zip = Buildr.download(tmp_path(NAME + '.zip') => URL)
131
+ dist_dir = Buildr.unzip(tmp_path(NAME) => dist_zip)
132
+
133
+ nailgun_jar = file(tmp_path(NAME, NAME, NAME + '.jar'))
134
+ ng.artifact = Buildr.artifact(ARTIFACT_SPEC).from(nailgun_jar)
135
+ unless File.exist?(nailgun_jar.to_s)
136
+ nailgun_jar.enhance [dist_dir]
159
137
  end
160
138
 
161
- def nailgun_tasks
162
- tasks = {}
163
- tasks['nailgun:help'] = 'Display nailgun help'
164
- tasks['nailgun:start'] = 'Start the Nailgun server.'
165
- tasks['nailgun:stop'] = 'Stop the Nailgun server.'
166
- tasks['nailgun:tasks'] = 'Display this message'
167
- tasks['nailgun:list'] = <<-DESC
168
- Display a list of builfile paths having an associated
169
- buildr runtime. Having a cached runtime reduces buidlr
170
- execution time.
171
-
172
- If buildr finds the current buildfile on this list,
173
- no file loading will be performed, only execution of
174
- specified tasks on the previously loaded environment.
175
- However if the cached runtime is out of date (buildfile
176
- has been modified) the runtime will be reloaded.
177
-
178
- This feature becomes handy when performing development
179
- cycle: edit -> compile -> test -> report.
180
-
181
- This task exits inmediatly after printing the file list.
182
- DESC
183
- tasks['nailgun:clear'] = <<-DESC
184
- Remove all cached buildr runtimes and exit
185
- DESC
186
- tasks['nailgun:load'] = <<-DESC
187
- Add or update a cached runtime.
188
-
189
- Use this task to create a cached buildr runtime for a
190
- buildfile.
191
- DESC
192
- tasks['nailgun:delete'] = <<-DESC
193
- Delete cached runtime for a buildfile and exit.
194
- DESC
195
- tasks['nailgun:once [tasks]'] = <<-DESC
196
- Ignore cached runtime and perform tasks on a newly
197
- created environment. This new runtime is dropped right
198
- after buildr completion.
199
- DESC
200
-
201
- out = ""
202
- out << "\nNailgun tasks:\n"
203
- tasks.each_pair do |task, desc|
204
- out << "\n"
205
- out << sprintf(" %20-s\n", [task].flatten.join(' | '))
206
- out << sprintf(" %s\n", desc.strip.gsub(/ *\n +/, "\n "))
139
+ compiled_bin = file(tmp_path(NAME, NAME, 'ng' + Config::CONFIG['EXEEXT']) => dist_dir.target) do |task|
140
+ unless task.to_s.pathmap('%x') == '.exe'
141
+ Dir.chdir(task.to_s.pathmap('%d')) do
142
+ info "Compiling #{task.to_s}"
143
+ system('make', task.to_s.pathmap('%f')) or
144
+ fail "Nailgun binary compilation failed."
145
+ end
207
146
  end
208
- out
209
147
  end
210
148
 
211
- def buildfile(dir = nil, candidates = nil)
212
- dir ||= Dir.pwd
213
- candidates ||= @rakefiles.dup
214
- Util.find_buildfile(dir, candidates, options.nosearch)
149
+ ng.installed_bin = file(File.expand_path(compiled_bin.to_s.pathmap('%f'), nailgun_home) => compiled_bin) do |task|
150
+ mkpath task.to_s.pathmap('%d'), :verbose => false
151
+ cp compiled_bin.to_s, task.to_s, :verbose => false
215
152
  end
216
153
 
217
- def clear_invoked
218
- tasks.each do |task|
219
- is_project = Project.instance_variable_get(:@projects).key?(task.name)
220
- task.instance_variable_set(:@already_invoked, false) unless is_project
154
+ end # file_tasks
155
+
156
+ server_tasks = lambda do
157
+
158
+ desc 'Start the nailgun server'
159
+ task('start', :port, :iface, :queue_size) do |task, args|
160
+
161
+ [ng.installed_bin, ng.artifact].map(&:invoke)
162
+
163
+ iface = args[:iface].to_s.empty? ? '127.0.0.1' : args[:iface]
164
+ port = args[:port].to_s.empty? ? 2113 : args[:port].to_i
165
+ queue_size = args[:queue_size].to_s.empty? ? 3 : args[:queue_size].to_i
166
+
167
+ fail "Already running on Nailgun server: #{ng.server || ng.nail}" if ng.server || ng.client
168
+
169
+ info 'Booting Buildr nailgun server...'
170
+ top_level = Buildr.application.instance_eval { @top_level_tasks.dup }
171
+ top_level.delete_if { |t| t[/nailgun/] }
172
+ unless top_level.empty?
173
+ raise 'Don\'t specify more targets when starting Nailgun server: #{top_level}'
221
174
  end
175
+ ng.server_setup.call
176
+
177
+ factory = RuntimeFactory.new(queue_size, queue_size)
178
+ ng.server = NGServer.new(iface, port, factory)
179
+
180
+ ng.server.start
222
181
  end
223
182
 
224
- if Buildr.const_defined?(:Application)
225
- class Buildr::Application
226
- include Nailgun::Application
227
- public :requires
228
- end
183
+ desc 'Show nailgun help'
184
+ task('help') do
185
+ info HELP
186
+ exit(0)
229
187
  end
230
- end
231
-
232
- module ContextRunner
233
- extend self
234
188
 
235
- def parse_options(ctx, opts)
236
- opts.requires = []
237
- Buildr.const_set(:VERSION, ctx.server.runtime.object.const_get(:Buildr)::VERSION)
238
-
239
- obj = OpenStruct.new(:ctx => ctx, :opts => opts)
240
- class << obj
241
- include Buildr::CommandLineInterface
242
-
243
- def help
244
- super
245
- puts
246
- puts 'To get a summary of Nailgun features use'
247
- puts ' nailgun:help'
248
- end
189
+ desc 'List nailgun tasks'
190
+ task('tasks') do
191
+ task_hash = Buildr.application.instance_variable_get(:@tasks)
192
+ tasks = task_hash.keys.select { |k| k =~ /^nailgun:/ }
193
+ width = [tasks.map { |t| task_hash[t].name_with_args.size }, 20].flatten.max
194
+ tasks.each do |name|
195
+ task = task_hash[name]
196
+ title = task.name_with_args
197
+ comment = task.full_comment
198
+ info comment.empty? ? title : (" %-#{width}s # %s" % [title, comment])
199
+ end
200
+ exit(0)
201
+ end
249
202
 
250
- def do_option(opt, value)
251
- case opt
252
- when '--help'
253
- help
254
- opts.exit = true
255
- when '--version'
256
- puts version
257
- opts.exit = true
258
- when '--environment'
259
- ctx.env['BUILDR_ENV'] = value
260
- when '--buildfile'
261
- opts.buildfile = value
262
- when '--require'
263
- opts.requires << value
264
- when '--nosearch'
265
- opts.nosearch = true
266
- end
203
+ desc 'List currently cached runtimes'
204
+ task('list') do
205
+ if Nailgun.ng.server
206
+ Nailgun.ng.server.cached_stamps.each_pair do |bf, time|
207
+ loaded = Nailgun.ng.server.loaded_times[bf]
208
+ ary = [bf, "Load Timestamp", loaded, "Modification Timestamp", time]
209
+ info("* %s\n %-25s %s\n %-25s %s\n\n" % ary)
267
210
  end
211
+ else
212
+ info "Not running on nailgun server"
268
213
  end
269
-
270
- ARGV.replace(ctx.argv)
271
- obj.parse_options
214
+ exit(0)
272
215
  end
273
-
274
- def run(ctx)
275
- ARGV.replace(ctx.argv)
276
- Dir.chdir(ctx.pwd)
277
- ctx.env.each { |k, v| ENV[k.to_s] = v.to_s }
278
- Buildr::Application.module_eval do
279
- include Nailgun::Application
280
- end
281
- task 'nailgun:load' do
282
- puts "Buildfile #{Rake.application.buildfile} loaded"
283
- end
284
- if ctx.fresh
285
- run_fresh(ctx)
216
+
217
+ desc 'Remove all cached runtimes'
218
+ task('clear') do
219
+ if Nailgun.ng.server
220
+ Nailgun.ng.server.cached_runtimes.clear
221
+ Nailgun.ng.server.cached_stamps.clear
222
+ Nailgun.ng.server.loaded_times.clear
223
+ info "Cleared all cached runtimes"
286
224
  else
287
- run_local(ctx)
225
+ info "Not running on nailgun server"
288
226
  end
227
+ exit(0)
289
228
  end
290
-
291
- private
292
-
293
- def run_fresh(ctx)
294
- Project.clear
295
- old_app = Rake.application
296
- Rake.application = Buildr::Application.new
297
- Rake.application.instance_eval do
298
- @tasks = old_app.instance_variable_get(:@tasks)
299
- @rules = old_app.instance_variable_get(:@rules)
300
- run
229
+
230
+ desc 'Remove runtime for this buildfile'
231
+ task('delete', :buildfile) do |task, args|
232
+ if Nailgun.ng.server
233
+ if args[:buildfile]
234
+ buildfile = File.expand_path(args[:buildfile])
235
+ else
236
+ buildfile = Buildr.application.buildfile.to_s
237
+ end
238
+ Nailgun.ng.server.cached_runtimes.delete(buildfile)
239
+ Nailgun.ng.server.cached_stamps.delete(buildfile)
240
+ Nailgun.ng.server.loaded_times.delete(buildfile)
241
+ info "Deleted #{buildfile} from runtime cache"
242
+ else
243
+ info "Not running on nailgun server"
301
244
  end
245
+ exit(0)
302
246
  end
303
247
 
304
- def run_local(ctx)
305
- Rake.application.instance_eval do
306
- verbose(nil)
307
- options.trace = false
308
- parse_options
309
- collect_tasks
310
- clear_invoked
311
- top_level_tasks.delete('buildr:initialize')
312
- Util.benchmark { top_level }
313
- end
248
+ end # server_tasks
249
+
250
+ # Load java classes on server side.
251
+ ng.server_setup = lambda do
252
+
253
+ module Util
254
+ include Buildr::Util
314
255
  end
315
- end
316
256
 
317
- module Util
318
- extend Buildr::Util
319
- extend self
257
+ Util.add_to_sysloader ng.artifact.to_s
258
+ Util.add_to_sysloader File.dirname(__FILE__)
320
259
 
321
- def find_buildfile(pwd, candidates, nosearch=false)
322
- candidates = [candidates].flatten
323
- buildfile = candidates.find { |c| File.file?(File.expand_path(c, pwd)) }
324
- return File.expand_path(buildfile, pwd) if buildfile
325
- return nil if nosearch
326
- updir = File.dirname(pwd)
327
- return nil if File.expand_path(updir) == File.expand_path(pwd)
328
- find_buildfile(updir, candidates)
260
+ class NGClient
261
+ include org.apache.buildr.BuildrNail
262
+ include Client
263
+ end
264
+
265
+ class NGServer < com.martiansoftware.nailgun.NGServer
266
+ include Server
329
267
  end
268
+
269
+ end # server_setup
270
+
271
+ module Util
272
+ extend self
330
273
 
274
+ def add_to_sysloader(path)
275
+ sysloader = java.lang.ClassLoader.getSystemClassLoader
276
+ add_url_method = java.lang.Class.forName('java.net.URLClassLoader').
277
+ getDeclaredMethod('addURL', [java.net.URL.java_class].to_java(java.lang.Class))
278
+ add_url_method.setAccessible(true)
279
+ add_url_method.invoke(sysloader, [java.io.File.new(path).toURI.toURL].to_java(java.net.URL))
280
+ end
281
+
331
282
  def benchmark(action = ['Completed'], verbose = true)
332
283
  result = nil
333
284
  times = Benchmark.measure do
@@ -338,11 +289,58 @@ module Buildr
338
289
  real << ("%ih" % (times.real / 3600)) if times.real >= 3600
339
290
  real << ("%im" % ((times.real / 60) % 60)) if times.real >= 60
340
291
  real << ("%.3fs" % (times.real % 60))
341
- puts "#{[action].flatten.join(' ')} in #{real.join}"
292
+ trace "#{[action].flatten.join(' ')} in #{real.join}"
342
293
  end
343
294
  result
344
295
  end
345
296
 
297
+ def find_file(pwd, candidates, nosearch=false)
298
+ candidates = [candidates].flatten
299
+ buildfile = candidates.find { |c| File.file?(File.expand_path(c, pwd)) }
300
+ return File.expand_path(buildfile, pwd) if buildfile
301
+ return nil if nosearch
302
+ updir = File.dirname(pwd)
303
+ return nil if File.expand_path(updir) == File.expand_path(pwd)
304
+ find_file(updir, candidates)
305
+ end
306
+
307
+ def exception_handling(raise_again = true, show_error = true)
308
+ begin
309
+ yield
310
+ rescue => e
311
+ if show_error
312
+ error "#{e.backtrace.shift}: #{e.message}"
313
+ e.backtrace.each { |i| error "\tfrom #{i}" }
314
+ end
315
+ raise if raise_again
316
+ end
317
+ end
318
+
319
+ # invoke a java constructor
320
+ def ctor(on_class, *args)
321
+ parameters = []
322
+ classes = []
323
+ args.each do |obj|
324
+ case obj
325
+ when nil
326
+ classes.push(nil)
327
+ parameters.push(nil)
328
+ when Hash
329
+ vclass = obj.keys.first
330
+ value = obj[vclass]
331
+ classes.push(vclass.java_class)
332
+ parameters.push(value)
333
+ else
334
+ parameters.push obj
335
+ classes.push obj.class.java_class
336
+ end
337
+ end
338
+ on_class = [on_class.java_class].to_java(java.lang.Class)[0]
339
+ ctor = on_class.getDeclaredConstructor(classes.to_java(java.lang.Class))
340
+ ctor.setAccessible(true)
341
+ ctor.newInstance(parameters.to_java(java.lang.Object))
342
+ end
343
+
346
344
  def on_runtime(runtime, *args, &block)
347
345
  raise_error = lambda do |cls, msg, trace|
348
346
  raise RuntimeError.new(cls + ": "+ msg.to_s).tap { |e| e.set_backtrace(trace.map(&:to_s)) }
@@ -360,534 +358,460 @@ module Buildr
360
358
  raise_error.call(*result[1..-1]) if result.kind_of?(Array) && result.first == :error
361
359
  result
362
360
  end
361
+
362
+ def set_stdio(runtime, dev)
363
+ set_global = lambda do |global, constant, stream|
364
+ runtime.global_variables.set(global, stream)
365
+ runtime.object.send(:remove_const, constant)
366
+ runtime.object.send(:const_set, constant, stream)
367
+ end
368
+ stdin = runtime.global_variables.get('$stdin')
369
+ stdout = runtime.global_variables.get('$stdout')
370
+ stderr = runtime.global_variables.get('$stderr')
371
+ #stdin.close; stdout.close; stderr.close;
372
+ output = Util.ctor(org.jruby.RubyIO, runtime, java.io.OutputStream => dev.out)
373
+ error = Util.ctor(org.jruby.RubyIO, runtime, java.io.OutputStream => dev.err)
374
+ input = Util.ctor(org.jruby.RubyIO, runtime, java.io.InputStream => dev.in)
375
+ #stdin.reopen(input, 'r') # not working on jruby, :(
376
+ #stdout.reopen(output, 'w')
377
+ #stderr.reopen(error, 'w')
378
+ set_global.call('$stdin', 'STDIN', input)
379
+ set_global.call('$stdout', 'STDOUT', output)
380
+ set_global.call('$stderr', 'STDERR', error)
381
+ end
382
+
363
383
  end # module Util
364
384
 
365
- boot do
385
+ class FieldAccessor
386
+ def initialize(obj, clazz = nil)
387
+ @obj = obj
388
+ clazz ||= obj.class
389
+ @cls = [clazz.java_class].to_java(java.lang.Class)[0]
390
+ end
391
+
392
+ def [](name)
393
+ field = @cls.getDeclaredField(name.to_s)
394
+ field.setAccessible(true)
395
+ field.get(@obj)
396
+ end
366
397
 
367
- class ::ConcreteJavaProxy
368
- def self.jclass(name = nil)
369
- name ||= self.java_class.name
370
- Nailgun::Util.class_for_name(name)
371
- end
372
-
373
- def self.jnew(*args)
374
- objs = []
375
- classes = args.map do |a|
376
- case a
377
- when nil
378
- obj << nil
379
- nil
380
- when Hash
381
- objs << a.keys.first
382
- cls = a.values.first
383
- cls = Nailgun::Util.proxy_class(cls) if String == cls
384
- cls
385
- else
386
- objs << a
387
- a.java_class
388
- end
389
- end
390
- classes = classes.to_java(java.lang.Class)
391
- ctor = jclass.getDeclaredConstructor(classes)
392
- ctor.setAccessible(true)
393
- ctor.newInstance(objs.to_java(java.lang.Object))
398
+ def []=(name, value)
399
+ field = @cls.getDeclaredField(name.to_s)
400
+ field.setAccessible(true)
401
+ field.set(@obj, value)
402
+ end
403
+
404
+ def method_missing(name, value =nil)
405
+ if name.to_s =~ /=$/
406
+ self[name.to_s.chomp('=')] = value
407
+ else
408
+ self[name]
394
409
  end
395
410
  end
411
+ end
396
412
 
397
- module Util
398
- def class_for_name(name)
399
- java.lang.Class.forName(name)
400
- end
401
-
402
- def add_to_sysloader(path)
403
- sysloader = java.lang.ClassLoader.system_class_loader
404
- add_url_method = class_for_name('java.net.URLClassLoader').
405
- getDeclaredMethod('addURL', [java.net.URL].to_java(java.lang.Class))
406
- add_url_method.accessible = true
407
- add_url_method.invoke(sysloader, [java.io.File.new(path.to_s).
408
- toURL].to_java(java.net.URL))
409
- end
410
- add_to_sysloader Nailgun.artifact
413
+ module NailMethods
411
414
 
412
- def proxy_class(name)
413
- JavaUtilities.get_proxy_class(name)
415
+ def self.extend_object(obj)
416
+ super
417
+ (class << obj; self; end).module_eval do
418
+ alias_method :pwd, :getWorkingDirectory
419
+ alias_method :server, :getNGServer
414
420
  end
421
+ end
422
+
423
+ def argv
424
+ [command] + args
425
+ end
415
426
 
416
- import org.jruby.RubyIO
417
- def set_stdio(runtime, dev)
418
- set_global = lambda do |global, constant, stream|
419
- runtime.global_variables.set(global, stream)
420
- runtime.object.send(:remove_const, constant)
421
- runtime.object.send(:const_set, constant, stream)
422
- end
423
- stdin = runtime.global_variables.get('$stdin')
424
- stdout = runtime.global_variables.get('$stdout')
425
- stderr = runtime.global_variables.get('$stderr')
426
- input = RubyIO.jnew(runtime, dev.in => java.io.InputStream)
427
- output = RubyIO.jnew(runtime, dev.out => java.io.OutputStream)
428
- error = RubyIO.jnew(runtime, dev.err => java.io.OutputStream)
429
- # stdin.reopen(input, 'r') # not working on jruby, :(
430
- set_global.call('$stdin', 'STDIN', input)
431
- stdout.reopen(output, 'w')
432
- stderr.reopen(error, 'w')
433
- end
434
-
435
- def redirect_stdio(runtime, nail)
436
- result = nil
437
- begin
438
- set_stdio(runtime, nail)
439
- result = yield
440
- ensure
441
- set_stdio(runtime, java.lang.System)
427
+ def attach_runtime(runtime)
428
+ runtime.extend RuntimeMixin
429
+ runtime.evalScriptlet %q{
430
+ require 'ostruct'
431
+ module Buildr
432
+ module Nailgun
433
+ extend self
434
+ attr_reader :ng
435
+ @ng = OpenStruct.new
436
+ end
442
437
  end
443
- result
438
+ }
439
+ runtime.Buildr::Nailgun.ng.nail = self
440
+ runtime.load_service.require __FILE__
441
+ runtime
442
+ end
443
+ private :attach_runtime
444
+
445
+ def jruby
446
+ @jruby ||= server.runtime_factory.new_jruby.tap do |runtime|
447
+ attach_runtime(runtime)
444
448
  end
445
449
  end
450
+
451
+ def buildr
452
+ @buildr ||= server.runtime_factory.new_buildr.tap do |runtime|
453
+ attach_runtime(runtime)
454
+ end
455
+ end
456
+
457
+ def options
458
+ @options ||= OpenStruct.new
459
+ end
460
+
461
+ end # NailMethods
446
462
 
447
- class Buildfile
448
- attr_reader :path, :requires, :loaded_time
449
- attr_accessor :runtime
450
-
451
- def initialize(path, *requires)
452
- @path = File.expand_path(path)
453
- @requires = requires.dup
463
+ module RuntimeMixin
464
+ def Buildr
465
+ object.const_get(:Buildr)
466
+ end
467
+ end
468
+
469
+ module AppMixin
470
+ def load_tasks
471
+ trace "Not loading tasks again"
472
+ end
473
+
474
+ def load_buildfile
475
+ trace "Not loading buildfile again"
476
+ end
477
+ end
478
+
479
+ module Client
480
+
481
+ class << self
482
+ include Buildr::CommandLineInterface
483
+
484
+ def options
485
+ Nailgun.ng.nail.options
454
486
  end
455
487
 
456
- def loaded!
457
- @loaded_time = Time.now
488
+ def rakefiles
489
+ Nailgun.ng.nail.options.rakefiles
458
490
  end
459
491
 
460
- def last_modification
461
- Util.timestamp(path)
492
+ def requires
493
+ Nailgun.ng.nail.options.requires
462
494
  end
463
495
 
464
- def should_be_loaded?
465
- (loaded_time || Rake::EARLY) < last_modification
496
+ def help
497
+ super
498
+ puts
499
+ puts 'To get a summary of Nailgun features use'
500
+ puts ' nailgun:help'
466
501
  end
467
-
468
- def to_s
469
- buff = path.dup
470
- buff << sprintf("\n %-25s %s", "Last Modified:", last_modification)
471
- unless requires.empty?
472
- buff << sprintf("\n %-25s %s", "Requires:", requires.join(" "))
473
- end
474
- if should_be_loaded?
475
- buff << sprintf("\n %-25s %s", "Needs reload, last was:", loaded_time)
502
+
503
+ def version
504
+ puts super
505
+ end
506
+
507
+ def do_option(opt, value)
508
+ case opt
509
+ when '--help'
510
+ options.exit = :help
511
+ when '--version'
512
+ options.exit = :version
513
+ when '--nosearch'
514
+ options.nosearch = true
476
515
  else
477
- buff << sprintf("\n %-25s %s", "Loaded at:", loaded_time)
516
+ super
478
517
  end
479
- buff << sprintf("\n %-25s %s", "Runtime:", runtime)
480
- buff
481
- end
482
- end
483
-
484
- class BuildrNail
485
- include org.apache.buildr.BuildrNail
486
- Main = Util.proxy_class 'org.apache.buildr.BuildrNail$Main'
518
+ end
487
519
 
488
- attr_reader :buildfile
520
+ def sBuildr
521
+ Nailgun.ng.nail.server.runtime.object.const_get(:Buildr)
522
+ end
489
523
 
490
- def initialize
491
- buildfile = Buildfile.new(Rake.application.buildfile,
492
- *Rake.application.requires)
493
- buildfile.loaded!
494
- buildfile.runtime = JRuby.runtime
495
- @buildfiles = { buildfile.path => buildfile }
524
+ def attach_runtime
525
+ nail = Nailgun.ng.nail
526
+ ARGV.replace nail.argv
527
+ Dir.chdir nail.pwd
528
+ nail.env.each { |k, v| ENV[k.to_s] = v.to_s }
529
+
530
+ Buildr.const_set(:VERSION, sBuildr::VERSION) unless Buildr.const_defined?(:VERSION)
531
+ nail.options.rakefiles = sBuildr::Application::DEFAULT_BUILDFILES.dup
532
+ nail.options.requires = []
496
533
  end
497
-
498
- def main(nail)
499
- Thread.exclusive { Thread.current.priority = 100; run(nail) }
534
+
535
+ def client(runtime, nail, &block)
536
+ Util.set_stdio(runtime, nail)
537
+ nailgun_module = runtime.Buildr::Nailgun
538
+ nailgun_module.ng.nail = nail
539
+ nailgun_module::Client.attach_runtime
540
+ nailgun_module::Client.instance_eval(&block)
500
541
  end
542
+ end
543
+
544
+ def main(nail)
545
+ nail.extend NailMethods
546
+ info "Got connection from #{nail.pwd}"
501
547
 
502
- private
503
- def run(nail)
504
- nail.assert_loopback_client
505
- nail.out.println "Using #{nail.getNGServer}"
506
- ctx = context_from_nail(nail)
548
+ Client.client(nail.jruby, nail) do
507
549
 
508
- case ctx.action
509
- when :start
510
- nail.out.println "Cannot start nailgun when running as client"
511
- return nail.exit(0)
512
- when :stop
513
- puts "Stopping #{nail.getNGServer}"
514
- nail.out.println "Stopping #{nail.getNGServer}"
515
- return nail.getNGServer.shutdown(true)
516
- when :list
517
- if @buildfiles.empty?
518
- nail.out.println "No defined runtimes"
519
- else
520
- nail.out.println "Defined runtimes:"
521
- @buildfiles.each_value { |f| nail.out.println "- #{f}" }
522
- end
523
- return nail.exit(0)
524
- when :clear
525
- @buildfiles.clear
526
- nail.out.println "Cleared all runtimes"
527
- return nail.exit(0)
528
- when :tasks
529
- nail.out.println ""
530
- nail.out.println Rake.application.nailgun_tasks
531
- return nail.exit(0)
532
- when :help
533
- nail.out.println ""
534
- nail.out.println Rake.application.nailgun_help
535
- return nail.exit(0)
550
+ parse_options
551
+ if options.exit
552
+ send(options.exit)
553
+ nail.exit(0)
536
554
  end
537
-
538
- opts = OpenStruct.new
539
-
540
- runtime = ctx.runtime
541
- #Util.set_stdio(runtime, nail)
542
- runtime.object.const_get(:Buildr)::Nailgun::ContextRunner.parse_options(ctx, opts)
543
- return nail.exit(0) if opts.exit
544
555
 
545
- candidates = Buildr::Application::DEFAULT_BUILDFILES
546
- candidates = [opts.buildfile] if opts.buildfile
547
-
548
- path = Util.find_buildfile(ctx.pwd, candidates, opts.nosearch) ||
549
- File.expand_path(candidates.first, ctx.pwd)
556
+ if options.project && File.directory?(options.project)
557
+ Dir.chdir(options.project)
558
+ end
550
559
 
551
- if ctx.action == :delete
552
- nail.out.println "Deleting runtime for #{path}"
553
- @buildfiles.delete(path)
554
- return nail.exit(0)
560
+ bf = Util.find_file(Dir.pwd, options.rakefiles, options.nosearch)
561
+ unless bf
562
+ nail.out.println "No buildfile found at #{Dir.pwd}"
563
+ nail.exit(0)
555
564
  end
556
-
557
- puts "Getting buildr runtime for #{path}"
558
- buildfile = @buildfiles[path] || Buildfile.new(path, *opts.requires)
559
565
 
560
- save = buildfile.should_be_loaded? || ctx.action == :load
566
+ rt = nail.server.cached_runtimes[bf]
567
+ old_stamp = nail.server.cached_stamps[bf] || Rake::EARLY
568
+ new_stamp = rt ? rt.Buildr.application.buildfile.timestamp : Rake::EARLY
561
569
 
562
- runtime = buildfile.runtime
563
-
564
- if save || ctx.action == :once
565
- ctx.argv.unshift 'nailgun:load'
566
- ctx.fresh = true
567
- runtime = ctx.buildr
568
- if save
569
- buildfile.runtime = runtime
570
- buildfile.loaded!
571
- @buildfiles[buildfile.path] = buildfile
570
+ if rt.nil? || new_stamp > old_stamp
571
+ rt = nail.buildr
572
+ app = rt.Buildr.application
573
+ app.instance_variable_set(:@rakefile, bf)
574
+ nail.out.println "Currently nailgun has issues reloading buildfiles, will get fixed in next release."
575
+ nail.out.println "Restart your nailgun server."
576
+ return nail.exit(1)
577
+ else
578
+ app = rt.Buildr.application.extend AppMixin
579
+ app.lookup('buildr:initialize').instance_eval do
580
+ @already_invoked = false
581
+ @actions = []
582
+ end
583
+ app.instance_eval do
584
+ @tasks.values.each do |task|
585
+ is_project = rt.Buildr::Project.instance_variable_get(:@projects).key?(task.name)
586
+ task.instance_variable_set(:@already_invoked, false) unless is_project
587
+ end
572
588
  end
573
589
  end
574
590
 
575
- Util.redirect_stdio(runtime, nail) do
576
- runtime.object.send :puts
577
- runtime.object.const_get(:Buildr)::Nailgun::ContextRunner.run(ctx)
591
+ app.instance_eval do
592
+ @original_dir = nail.pwd
578
593
  end
594
+
595
+ Client.client(rt, nail) do
596
+ Util.exception_handling do
597
+ begin
598
+ app.parse_options
599
+ app.collect_tasks
600
+ app.run
601
+ rescue SystemExit => e
602
+ nail.exit(1)
603
+ end
604
+ end
605
+ end
606
+
607
+ nail.server.cache(rt, app.buildfile)
579
608
  end
580
-
581
- def context_from_nail(nail)
582
- ctx = OpenStruct.new
583
- ctx.pwd = nail.getWorkingDirectory
584
- ctx.env = nail.env
585
- ctx.argv = [nail.command] + nail.args.map(&:to_s)
586
- ctx.server = nail.getNGServer
587
- def ctx.runtime; @runtime ||= server.buildr_factory.runtime; end
588
- def ctx.buildr; @buildr ||= server.buildr_factory.obtain; end
589
- actions = {
590
- :load => %w{ nailgun:load },
591
- :delete => %w{ nailgun:delete },
592
- :clear => %w{ nailgun:clear },
593
- :list => %w{ nailgun:list },
594
- :start => %w{ nailgun:boot nailgun:start },
595
- :stop => %w{ nailgun:stop },
596
- :once => %w{ nailgun:once },
597
- :tasks => %w{ nailgun:tasks },
598
- :help => %w{ nailgun:help help:nailgun },
599
- }
600
- action = actions.find { |k,v| k if v.any? { |t| ctx.argv.delete(t) } }
601
- ctx.action = action.first if action
602
- ctx
603
- end
604
-
605
- end # class BuildrNail
609
+ end
610
+
611
+ end # class Client
612
+
613
+ module Server
614
+
615
+ attr_reader :runtime_factory
616
+ attr_reader :cached_runtimes
617
+ attr_reader :cached_stamps
618
+ attr_reader :loaded_times
619
+
620
+ def initialize(host = 'localhost', port = 2113, buildr_factory = nil)
621
+ super(java.net.InetAddress.get_by_name(host), port)
622
+ @cached_runtimes = {}
623
+ @cached_stamps = {}
624
+ @loaded_times = {}
625
+ cache(runtime, Buildr.application.buildfile)
626
+ @runtime_factory = buildr_factory
627
+ @host, @port = host, port
628
+ end
629
+
630
+ def cache(runtime, buildfile)
631
+ cached_runtimes[buildfile.to_s] = runtime
632
+ cached_stamps[buildfile.to_s] = buildfile.timestamp
633
+ loaded_times[buildfile.to_s] = Time.now
634
+ end
606
635
 
607
- class BuildrFactory
636
+ def runtime
637
+ JRuby.runtime.extend RuntimeMixin
638
+ end
639
+
640
+ def start
641
+ self.allow_nails_by_class_name = false
608
642
 
609
- attr_accessor :buildrs_size, :runtimes_size
643
+ NGClient::Main.nail = NGClient.new
644
+ self.default_nail_class = NGClient::Main
645
+ runtime_factory.start
610
646
 
611
- def initialize(buildrs_size = 1, runtimes_size = nil)
612
- runtimes_size ||= buildrs_size
613
- @buildrs_size = buildrs_size < 1 ? 1 : buildrs_size
614
- @runtimes_size = runtimes_size < 1 ? 1 : runtimes_size
615
-
616
- @buildrs = [].extend(MonitorMixin)
617
- @buildrs_ready = @buildrs.new_cond
618
- @buildrs_needed = @buildrs.new_cond
619
-
620
- @buildrs_creators = [].extend(MonitorMixin)
621
-
622
- @runtimes = [].extend(MonitorMixin)
623
- @runtimes_ready = @runtimes.new_cond
624
- @runtimes_needed = @runtimes.new_cond
625
-
626
- @runtimes_creators = [].extend(MonitorMixin)
627
- end
647
+ @thread = java.lang.Thread.new(self)
648
+ @thread.setName(to_s)
649
+ @thread.start
628
650
 
629
- def obtain
630
- get(:buildr)
631
- end
651
+ sleep 1 while getPort == 0
652
+ info "#{self} Started."
653
+ end
654
+
655
+ def stop
656
+ runtime_factory.stop
657
+ @thread.kill
658
+ end
632
659
 
633
- def runtime
634
- get(:runtime)
635
- end
660
+ def to_s
661
+ self.class.name+'('+[Buildr.application.version, @host, @port].join(', ')+')'
662
+ end
663
+ end # module Server
664
+
665
+ class RuntimeFactory
666
+
667
+ attr_accessor :buildrs_size, :jrubys_size
668
+
669
+ def initialize(buildrs_size = 1, jrubys_size = nil)
670
+ # jrubys_size ||= buildrs_size
671
+ @buildrs_size = buildrs_size < 1 ? 1 : buildrs_size
672
+ # @jrubys_size = jrubys_size < 1 ? 1 : jrubys_size
673
+
674
+ @buildrs = [].extend(MonitorMixin)
675
+ @buildrs_ready = @buildrs.new_cond
676
+ @buildrs_needed = @buildrs.new_cond
677
+
678
+ @buildrs_creators = [].extend(MonitorMixin)
636
679
 
637
- def start
638
- debug "Starting Buildr runtime factory"
639
- @runtime_creator = Thread.new { loop { create :runtime } }
640
- @runtime_creator.priority = -2
641
- @buildr_creator = Thread.new { loop { create :buildr } }
642
- @buildr_creator.priority = 1
643
- end
680
+ # @jrubys = [].extend(MonitorMixin)
681
+ # @jrubys_ready = @jrubys.new_cond
682
+ # @jrubys_needed = @jrubys.new_cond
683
+
684
+ # @jrubys_creators = [].extend(MonitorMixin)
685
+ end
686
+
687
+ def new_buildr
688
+ get(:buildr)
689
+ end
644
690
 
645
- def stop
646
- @buildr_creator.kill if @buildr_creator
647
- @runtime_creator.kill if @runtime_creator
648
- end
691
+ def new_jruby(&block)
692
+ # get(:jruby)
693
+ create_jruby(0, &block)
694
+ end
649
695
 
650
- private
651
- def debug(*msg)
652
- puts *msg if Rake.application.options.trace
653
- end
696
+ def start
697
+ trace "Starting Buildr runtime factory"
698
+ # @jruby_creator = Thread.new { loop { create :jruby } }
699
+ # @jruby_creator.priority = -2
700
+ @buildr_creator = Thread.new { loop { create :buildr } }
701
+ @buildr_creator.priority = 1
702
+ end
654
703
 
655
- def get(thing)
656
- collection = instance_variable_get("@#{thing}s")
657
- needs = instance_variable_get("@#{thing}s_needed")
658
- ready = instance_variable_get("@#{thing}s_ready")
659
- result = nil
660
- collection.synchronize do
661
- if collection.empty?
662
- debug "no #{thing} available, ask to create more"
663
- needs.broadcast
664
- debug "should be creating #{thing}"
665
- ready.wait_while { collection.empty? }
666
- end
667
- debug "Getting my #{thing}"
668
- result = collection.shift
669
- debug "would need more #{thing}s"
704
+ def stop
705
+ @buildr_creator.kill if @buildr_creator
706
+ # @jruby_creator.kill if @jruby_creator
707
+ end
708
+
709
+ private
710
+ def get(thing)
711
+ collection = instance_variable_get("@#{thing}s")
712
+ needs = instance_variable_get("@#{thing}s_needed")
713
+ ready = instance_variable_get("@#{thing}s_ready")
714
+ result = nil
715
+ collection.synchronize do
716
+ if collection.empty?
717
+ trace "no #{thing} available, ask to create more"
670
718
  needs.broadcast
671
- debug "got my #{thing}: #{result.inspect}"
672
- Thread.pass
719
+ trace "should be creating #{thing}"
720
+ ready.wait_while { collection.empty? }
673
721
  end
674
- debug "returning #{result.inspect}"
675
- result
676
- end
722
+ trace "Getting my #{thing}"
723
+ result = collection.shift
724
+ trace "would need more #{thing}s"
725
+ needs.broadcast
726
+ trace "got my #{thing}: #{result.inspect}"
727
+ Thread.pass
728
+ end
729
+ trace "returning #{result.inspect}"
730
+ result
731
+ end
677
732
 
678
- def create(thing, *args, &prc)
733
+ def create(thing, *args, &block)
734
+ Util.exception_handling do
679
735
  creator = needed(thing)
680
736
  collection = instance_variable_get("@#{thing}s")
681
737
  ready = instance_variable_get("@#{thing}s_ready")
682
738
  needs = instance_variable_get("@#{thing}s_needed")
683
739
  unless creator
684
740
  collection.synchronize do
685
- debug "awake those wanting a #{thing}"
741
+ trace "awake those wanting a #{thing}"
686
742
  ready.broadcast
687
743
  Thread.pass
688
- debug "wait until more #{thing}s are needed"
744
+ trace "wait until more #{thing}s are needed"
689
745
  # needs.wait(1); return
690
746
  needs.wait_until { creator = needed(thing) }
691
747
  end
692
748
  end
693
- debug "About to create #{thing} # #{creator}"
749
+ trace "About to create #{thing} # #{creator}"
694
750
  method = "create_#{thing}"
695
751
  creators = instance_variable_get("@#{thing}s_creators")
696
- debug "registering creator for #{thing} #{creator}"
752
+ trace "registering creator for #{thing} #{creator}"
697
753
  creators.synchronize { creators << creator }
698
- result = send(method, creator, *args, &prc)
699
- debug "created #{thing}[#{creator}] => #{result.inspect}"
754
+ result = send(method, creator, *args, &block)
755
+ trace "created #{thing}[#{creator}] => #{result.inspect}"
700
756
  creators.synchronize do
701
- debug "unregistering creator for #{thing} #{creator}"
757
+ trace "unregistering creator for #{thing} #{creator}"
702
758
  creators.delete(creator)
703
759
  collection.synchronize do
704
- debug "adding object on queue for #{thing} #{creator}"
760
+ trace "adding object on queue for #{thing} #{creator}"
705
761
  collection << result
706
762
  end
707
763
  end
708
- rescue => e
709
- puts "#{e.backtrace.shift}: #{e.message}"
710
- e.backtrace.each { |i| puts "\tfrom #{i}" }
711
764
  end
712
-
713
- def needed(thing)
714
- collection = instance_variable_get("@#{thing}s")
715
- creators = instance_variable_get("@#{thing}s_creators")
716
- size = instance_variable_get("@#{thing}s_size")
717
- collection.synchronize do
718
- count = collection.size
719
- if count < size
720
- count += creators.synchronize { creators.size }
721
- end
722
- count if count < size
765
+ end
766
+
767
+ def needed(thing)
768
+ collection = instance_variable_get("@#{thing}s")
769
+ creators = instance_variable_get("@#{thing}s_creators")
770
+ size = instance_variable_get("@#{thing}s_size")
771
+ collection.synchronize do
772
+ count = collection.size
773
+ if count < size
774
+ count += creators.synchronize { creators.size }
723
775
  end
776
+ count if count < size
724
777
  end
725
-
726
- def create_runtime(creator)
727
- debug "Creating runtime[#{creator}]"
778
+ end
779
+
780
+ def create_jruby(creator, &block)
781
+ Util.exception_handling do
782
+ trace "Creating jruby[#{creator}]"
728
783
  Util.benchmark do |header|
729
- runtime = org.jruby.Ruby.newInstance
730
- runtime.global_variables.set('$nailgun_server', JRuby.reference($nailgun_server))
731
- BUILDR_PATHS.each { |path| runtime.load_service.load_path.unshift path }
732
- runtime.load_service.require 'buildr/nailgun'
733
- header.replace ["Created runtime[#{creator}]", runtime]
734
- runtime
784
+ cfg = org.jruby.RubyInstanceConfig.new
785
+ yield cfg if block_given?
786
+ jruby = org.jruby.Ruby.newInstance(cfg)
787
+ jruby.load_service.load_path.unshift *BUILDR_PATHS
788
+ header.replace ["Created jruby[#{creator}]", jruby]
789
+ jruby
735
790
  end
736
791
  end
792
+ end
737
793
 
738
- def create_buildr(creator)
739
- debug "Obtaining runtime to load buildr[#{creator}] on it"
740
- runtime = get(:runtime)
741
- debug "Loading buildr[#{creator}] on #{runtime} ..."
742
- Util.benchmark ["Loaded buildr[#{creator}] on #{runtime}"] do
743
- load_service = runtime.load_service
794
+ def create_buildr(creator)
795
+ Util.exception_handling do
796
+ trace "Obtaining jruby to load buildr[#{creator}] on it"
797
+ jruby = new_jruby
798
+ trace "Loading buildr[#{creator}] on #{jruby} ..."
799
+ Util.benchmark ["Loaded buildr[#{creator}] on #{jruby}"] do
800
+ load_service = jruby.load_service
744
801
  load_service.require 'rubygems'
745
802
  load_service.require 'buildr'
746
803
  end
747
- runtime
748
- end
749
-
750
- end # BuildrFactory
751
-
752
- class BuildrServer < com.martiansoftware.nailgun.NGServer
753
-
754
- attr_reader :buildr_factory
755
-
756
- def initialize(host = 'localhost', port = 2113, buildr_factory = nil)
757
- super(java.net.InetAddress.get_by_name(host), port)
758
- @buildr_factory = buildr_factory
759
- @host, @port = host, port
760
- end
761
-
762
- def runtime
763
- JRuby.runtime
764
- end
765
-
766
- def start_server
767
- self.allow_nails_by_class_name = false
768
-
769
- BuildrNail::Main.nail = BuildrNail.new
770
- self.default_nail_class = BuildrNail::Main
771
- buildr_factory.start
772
-
773
- @thread = java.lang.Thread.new(self)
774
- @thread.setName(to_s)
775
- @thread.start
776
-
777
- sleep 1 while getPort == 0
778
- puts "#{self} Started."
779
- end
780
-
781
- def stop_server
782
- buildr_factory.stop
783
- @thread.kill
784
- end
785
-
786
- def to_s
787
- "BuildrServer(" <<
788
- [Rake.application.version, @host, @port].join(", ") <<
789
- ")"
790
- end
791
- end # class BuildrServer
792
-
793
- end # Nailgun boot
794
-
795
- namespace do
796
- tmp = lambda { |*files| File.join(Dir.tmpdir, "nailgun", *files) }
797
- dist_zip = Buildr.download(tmp[NAME + ".zip"] => URL)
798
- dist_dir = Buildr.unzip(tmp[NAME] => dist_zip)
799
-
800
- if File.exist?(File.join(home, NAME + ".jar"))
801
- ng_jar = file(File.join(home, NAME + ".jar"))
802
- else
803
- ng_jar = file(tmp[NAME, NAME, NAME+".jar"] => dist_dir)
804
- end
805
-
806
- self.artifact = Buildr.artifact(ARTIFACT_SPEC).from(ng_jar)
807
-
808
- compiled_bin = tmp[NAME, NAME, "ng"+Config::CONFIG['EXEEXT']]
809
- compiled_bin = file(compiled_bin => dist_dir.target) do |task|
810
- unless task.to_s.pathmap('%x') == '.exe'
811
- Dir.chdir(task.to_s.pathmap('%d')) do
812
- puts "Compiling #{task.to_s}"
813
- system('make', task.to_s.pathmap('%f')) or
814
- fail "Nailgun binary compilation failed."
815
- end
816
- end
817
- end
818
-
819
- installed_bin = file(File.join(home,
820
- compiled_bin.to_s.pathmap('%f')) => compiled_bin) do |task|
821
- mkpath task.to_s.pathmap('%d'), :verbose => false
822
- cp compiled_bin.to_s, task.to_s, :verbose => false
823
- end
824
-
825
- task :boot => artifact do |task|
826
- if $nailgun_server
827
- raise "Already nunning on Nailgun server: #{$nailgun_server}"
828
- end
829
- tasks = Rake.application.instance_eval { @top_level_tasks.dup }
830
- tasks.delete_if do |t|
831
- t =~ /^(buildr:initialize|(ng|nailgun):.+)$/
804
+ jruby
832
805
  end
833
- unless tasks.empty?
834
- raise "Don't specify more targets when starting Nailgun server"
835
- end
836
- boot
837
806
  end
838
807
 
839
- task :start => [installed_bin, :boot] do
840
- factory = BuildrFactory.new(buildr_queue_size, jruby_queue_size)
841
- $nailgun_server = BuildrServer.new(server, port, factory)
842
- puts "Starting #{$nailgun_server}"
843
- $nailgun_server.start_server
844
-
845
- is_win = Util.win_os?
846
- bin_path = File.expand_path(installed_bin.to_s.pathmap("%d"))
847
- bin_name = installed_bin.to_s.pathmap("%f")
808
+ end # RuntimeFactory
848
809
 
849
- puts <<-NOTICE
850
-
851
- Buildr server has been started, you may need to update your PATH
852
- variable in order to execute the #{bin_name} binary.
853
-
854
- #{ is_win ?
855
- "> set NAILGUN_HOME=#{bin_path}" :
856
- "$ export NAILGUN_HOME=#{bin_path}"
857
- }
858
- #{ is_win ?
859
- "> set PATH=%NAILGUN_HOME%;%PATH%" :
860
- "$ export PATH=${NAILGUN_HOME}:${PATH}"
861
- }
862
-
863
- Runtime for #{Rake.application.buildfile} has been cached, this
864
- means you can open a terminal inside
865
-
866
- #{Rake.application.buildfile.pathmap("%d")}
867
-
868
- Invoke tasks by executing the #{bin_name} program, it takes the
869
- same parameters you normally use for ``buildr''.
870
-
871
- To display Nailgun related help, execute the command:
872
- ``#{bin_name} nailgun:help''
873
-
874
- To get an overview of Nailgun tasks, execute the command:
875
- ``#{bin_name} nailgun:tasks''
876
-
877
- NOTICE
878
- end
879
-
880
- task :help do
881
- puts Rake.application.nailgun_help
882
- end
810
+ if Buildr.respond_to?(:application) && ng.nail.nil?
811
+ Buildr.application.in_namespace(:nailgun, &file_tasks)
812
+ Buildr.application.in_namespace(:nailgun, &server_tasks)
813
+ end
883
814
 
884
- task :tasks do
885
- puts Rake.application.nailgun_tasks
886
- end
887
-
888
- end # namespace :nailgun
889
-
890
815
  end # module Nailgun
891
-
816
+
892
817
  end
893
-