assaf-buildr 1.3.3

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 (163) hide show
  1. data/CHANGELOG +887 -0
  2. data/DISCLAIMER +7 -0
  3. data/LICENSE +176 -0
  4. data/NOTICE +26 -0
  5. data/README.rdoc +146 -0
  6. data/Rakefile +62 -0
  7. data/_buildr +38 -0
  8. data/addon/buildr/antlr.rb +65 -0
  9. data/addon/buildr/cobertura.rb +236 -0
  10. data/addon/buildr/emma.rb +238 -0
  11. data/addon/buildr/hibernate.rb +142 -0
  12. data/addon/buildr/javacc.rb +85 -0
  13. data/addon/buildr/jdepend.rb +60 -0
  14. data/addon/buildr/jetty.rb +248 -0
  15. data/addon/buildr/jibx.rb +86 -0
  16. data/addon/buildr/nailgun.rb +817 -0
  17. data/addon/buildr/openjpa.rb +90 -0
  18. data/addon/buildr/org/apache/buildr/BuildrNail$Main.class +0 -0
  19. data/addon/buildr/org/apache/buildr/BuildrNail.class +0 -0
  20. data/addon/buildr/org/apache/buildr/BuildrNail.java +41 -0
  21. data/addon/buildr/org/apache/buildr/JettyWrapper$1.class +0 -0
  22. data/addon/buildr/org/apache/buildr/JettyWrapper$BuildrHandler.class +0 -0
  23. data/addon/buildr/org/apache/buildr/JettyWrapper.class +0 -0
  24. data/addon/buildr/org/apache/buildr/JettyWrapper.java +144 -0
  25. data/addon/buildr/xmlbeans.rb +93 -0
  26. data/bin/buildr +28 -0
  27. data/buildr.buildfile +53 -0
  28. data/buildr.gemspec +58 -0
  29. data/doc/css/default.css +228 -0
  30. data/doc/css/print.css +100 -0
  31. data/doc/css/syntax.css +52 -0
  32. data/doc/images/apache-incubator-logo.png +0 -0
  33. data/doc/images/buildr-hires.png +0 -0
  34. data/doc/images/buildr.png +0 -0
  35. data/doc/images/favicon.png +0 -0
  36. data/doc/images/growl-icon.tiff +0 -0
  37. data/doc/images/note.png +0 -0
  38. data/doc/images/project-structure.png +0 -0
  39. data/doc/images/tip.png +0 -0
  40. data/doc/images/zbuildr.tif +0 -0
  41. data/doc/pages/artifacts.textile +207 -0
  42. data/doc/pages/building.textile +240 -0
  43. data/doc/pages/contributing.textile +208 -0
  44. data/doc/pages/download.textile +62 -0
  45. data/doc/pages/extending.textile +175 -0
  46. data/doc/pages/getting_started.textile +273 -0
  47. data/doc/pages/index.textile +42 -0
  48. data/doc/pages/languages.textile +407 -0
  49. data/doc/pages/mailing_lists.textile +17 -0
  50. data/doc/pages/more_stuff.textile +286 -0
  51. data/doc/pages/packaging.textile +427 -0
  52. data/doc/pages/projects.textile +274 -0
  53. data/doc/pages/recipes.textile +103 -0
  54. data/doc/pages/settings_profiles.textile +274 -0
  55. data/doc/pages/testing.textile +212 -0
  56. data/doc/pages/troubleshooting.textile +103 -0
  57. data/doc/pages/whats_new.textile +323 -0
  58. data/doc/print.haml +51 -0
  59. data/doc/print.toc.yaml +29 -0
  60. data/doc/scripts/buildr-git.rb +412 -0
  61. data/doc/scripts/install-jruby.sh +44 -0
  62. data/doc/scripts/install-linux.sh +64 -0
  63. data/doc/scripts/install-osx.sh +52 -0
  64. data/doc/site.haml +56 -0
  65. data/doc/site.toc.yaml +47 -0
  66. data/etc/KEYS +151 -0
  67. data/etc/git-svn-authors +16 -0
  68. data/lib/buildr.rb +35 -0
  69. data/lib/buildr/core.rb +27 -0
  70. data/lib/buildr/core/application.rb +489 -0
  71. data/lib/buildr/core/application_cli.rb +139 -0
  72. data/lib/buildr/core/build.rb +311 -0
  73. data/lib/buildr/core/checks.rb +382 -0
  74. data/lib/buildr/core/common.rb +154 -0
  75. data/lib/buildr/core/compile.rb +596 -0
  76. data/lib/buildr/core/environment.rb +120 -0
  77. data/lib/buildr/core/filter.rb +362 -0
  78. data/lib/buildr/core/generate.rb +195 -0
  79. data/lib/buildr/core/help.rb +118 -0
  80. data/lib/buildr/core/progressbar.rb +156 -0
  81. data/lib/buildr/core/project.rb +892 -0
  82. data/lib/buildr/core/test.rb +715 -0
  83. data/lib/buildr/core/transports.rb +558 -0
  84. data/lib/buildr/core/util.rb +289 -0
  85. data/lib/buildr/groovy.rb +18 -0
  86. data/lib/buildr/groovy/bdd.rb +105 -0
  87. data/lib/buildr/groovy/compiler.rb +138 -0
  88. data/lib/buildr/ide.rb +19 -0
  89. data/lib/buildr/ide/eclipse.rb +212 -0
  90. data/lib/buildr/ide/idea.ipr.template +300 -0
  91. data/lib/buildr/ide/idea.rb +189 -0
  92. data/lib/buildr/ide/idea7x.ipr.template +290 -0
  93. data/lib/buildr/ide/idea7x.rb +210 -0
  94. data/lib/buildr/java.rb +23 -0
  95. data/lib/buildr/java/ant.rb +92 -0
  96. data/lib/buildr/java/bdd.rb +449 -0
  97. data/lib/buildr/java/commands.rb +211 -0
  98. data/lib/buildr/java/compiler.rb +348 -0
  99. data/lib/buildr/java/deprecated.rb +141 -0
  100. data/lib/buildr/java/jruby.rb +117 -0
  101. data/lib/buildr/java/jtestr_runner.rb.erb +116 -0
  102. data/lib/buildr/java/org/apache/buildr/JavaTestFilter.class +0 -0
  103. data/lib/buildr/java/org/apache/buildr/JavaTestFilter.java +119 -0
  104. data/lib/buildr/java/packaging.rb +713 -0
  105. data/lib/buildr/java/pom.rb +178 -0
  106. data/lib/buildr/java/rjb.rb +155 -0
  107. data/lib/buildr/java/test_result.rb +308 -0
  108. data/lib/buildr/java/tests.rb +324 -0
  109. data/lib/buildr/java/version_requirement.rb +172 -0
  110. data/lib/buildr/packaging.rb +21 -0
  111. data/lib/buildr/packaging/artifact.rb +730 -0
  112. data/lib/buildr/packaging/artifact_namespace.rb +972 -0
  113. data/lib/buildr/packaging/artifact_search.rb +140 -0
  114. data/lib/buildr/packaging/gems.rb +102 -0
  115. data/lib/buildr/packaging/package.rb +233 -0
  116. data/lib/buildr/packaging/tar.rb +104 -0
  117. data/lib/buildr/packaging/zip.rb +722 -0
  118. data/lib/buildr/resources/buildr.icns +0 -0
  119. data/lib/buildr/scala.rb +19 -0
  120. data/lib/buildr/scala/compiler.rb +109 -0
  121. data/lib/buildr/scala/tests.rb +203 -0
  122. data/rakelib/apache.rake +191 -0
  123. data/rakelib/changelog.rake +57 -0
  124. data/rakelib/doc.rake +103 -0
  125. data/rakelib/package.rake +73 -0
  126. data/rakelib/release.rake +65 -0
  127. data/rakelib/rspec.rake +83 -0
  128. data/rakelib/rubyforge.rake +53 -0
  129. data/rakelib/scm.rake +49 -0
  130. data/rakelib/setup.rake +86 -0
  131. data/rakelib/stage.rake +48 -0
  132. data/spec/addon/cobertura_spec.rb +77 -0
  133. data/spec/addon/emma_spec.rb +120 -0
  134. data/spec/addon/test_coverage_spec.rb +255 -0
  135. data/spec/core/application_spec.rb +412 -0
  136. data/spec/core/artifact_namespace_spec.rb +646 -0
  137. data/spec/core/build_spec.rb +415 -0
  138. data/spec/core/checks_spec.rb +537 -0
  139. data/spec/core/common_spec.rb +664 -0
  140. data/spec/core/compile_spec.rb +566 -0
  141. data/spec/core/generate_spec.rb +33 -0
  142. data/spec/core/project_spec.rb +754 -0
  143. data/spec/core/test_spec.rb +1091 -0
  144. data/spec/core/transport_spec.rb +500 -0
  145. data/spec/groovy/bdd_spec.rb +80 -0
  146. data/spec/groovy/compiler_spec.rb +239 -0
  147. data/spec/ide/eclipse_spec.rb +243 -0
  148. data/spec/java/ant.rb +28 -0
  149. data/spec/java/bdd_spec.rb +358 -0
  150. data/spec/java/compiler_spec.rb +446 -0
  151. data/spec/java/java_spec.rb +88 -0
  152. data/spec/java/packaging_spec.rb +1103 -0
  153. data/spec/java/tests_spec.rb +466 -0
  154. data/spec/packaging/archive_spec.rb +503 -0
  155. data/spec/packaging/artifact_spec.rb +754 -0
  156. data/spec/packaging/packaging_helper.rb +63 -0
  157. data/spec/packaging/packaging_spec.rb +589 -0
  158. data/spec/sandbox.rb +137 -0
  159. data/spec/scala/compiler_spec.rb +228 -0
  160. data/spec/scala/tests_spec.rb +215 -0
  161. data/spec/spec_helpers.rb +304 -0
  162. data/spec/version_requirement_spec.rb +123 -0
  163. metadata +369 -0
@@ -0,0 +1,86 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with this
3
+ # work for additional information regarding copyright ownership. The ASF
4
+ # licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations under
14
+ # the License.
15
+
16
+
17
+ require 'java/java'
18
+
19
+
20
+ module Buildr
21
+
22
+ # Provides JiBX bytecode enhancement. Require explicitly using <code>require 'buildr/jibx'</code>.
23
+ module JiBX
24
+
25
+ JIBX_VERSION = '1.1.5'
26
+ BCEL_VERSION = '5.2'
27
+ STAX_VERSION = '1.0-2'
28
+ XPP3_VERSION = '1.1.4c'
29
+
30
+ REQUIRES = [ "org.jibx:jibx-bind:jar:#{JIBX_VERSION}",
31
+ "org.jibx:jibx-run:jar:#{JIBX_VERSION}",
32
+ "org.apache.bcel:bcel:jar:#{BCEL_VERSION}",
33
+ "javax.xml.stream:stax-api:jar:#{STAX_VERSION}",
34
+ "xpp3:xpp3:jar:#{XPP3_VERSION}" ]
35
+
36
+ Java.classpath << REQUIRES
37
+
38
+ class << self
39
+
40
+ def bind(options)
41
+ rake_check_options options, :classpath, :output, :binding, :target, :verbose, :load
42
+ artifacts = Buildr.artifacts(options[:classpath]).each { |a| a.invoke }.map(&:to_s) + [options[:output].to_s]
43
+ binding = file(options[:binding]).tap { |task| task.invoke }.to_s
44
+
45
+ Buildr.ant 'jibx' do |ant|
46
+ ant.taskdef :name=>'bind', :classname=>'org.jibx.binding.ant.CompileTask',
47
+ :classpath => requires.join(File::PATH_SEPARATOR)
48
+ ant.bind :verbose => options[:verbose].to_s, :load => options[:load].to_s, :binding=>options[:binding].to_s do
49
+ ant.classpath :path => artifacts.join(File::PATH_SEPARATOR)
50
+ end
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def requires()
57
+ @requires ||= Buildr.artifacts(REQUIRES).each { |artifact| artifact.invoke }.map(&:to_s)
58
+ end
59
+
60
+ end
61
+
62
+ def jibx_bind(options = nil)
63
+
64
+ # FIXME - add support for :bindingfileset and :classpathset
65
+ # Note: either :binding or :bindingfileset should be set, and either
66
+ # :classpath or :classpathset should be set, and options passed to
67
+ # ant.bind should be adjusted accordingly. At present, only :binding
68
+ # and :classpath are supported (which should be fine for most!)
69
+ jibx_options = { :output => compile.target,
70
+ :classpath => compile.classpath,
71
+ :binding => path_to(:source, :main, :resources, 'META-INF/binding.xml'),
72
+ :target => compile.target,
73
+ :load => false,
74
+ :verbose => false
75
+ }
76
+
77
+ JiBX.bind jibx_options.merge(options || {})
78
+ end
79
+
80
+ end
81
+
82
+ class Project
83
+ include JiBX
84
+ end
85
+ end
86
+
@@ -0,0 +1,817 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with this
3
+ # work for additional information regarding copyright ownership. The ASF
4
+ # licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations under
14
+ # the License.
15
+
16
+ require 'benchmark'
17
+ require 'jruby'
18
+ require 'monitor'
19
+ require 'ostruct'
20
+ require 'rbconfig'
21
+ require 'thread'
22
+ require 'buildr/core/application_cli'
23
+
24
+ module Buildr #:nodoc:
25
+
26
+ module Nailgun
27
+
28
+ extend self
29
+
30
+ attr_reader :ng
31
+ @ng ||= OpenStruct.new
32
+
33
+ VERSION = '0.7.1'
34
+ NAME = "nailgun-#{VERSION}"
35
+ URL = "http://downloads.sourceforge.net/nailgun/#{NAME}.zip"
36
+ ARTIFACT_SPEC = "com.martiansoftware:nailgun:jar:#{VERSION}"
37
+
38
+ # Paths used to initialize a buildr runtime
39
+ BUILDR_PATHS = [File.expand_path('../', File.dirname(__FILE__)),
40
+ File.expand_path('../../lib', File.dirname(__FILE__))]
41
+
42
+ HELP = <<-HELP.strip.gsub(/ *\n +/, "\n ")
43
+ NailGun is a client, protocol, and server for running Java
44
+ programs from the command line without incurring the JVM
45
+ startup overhead. Nailgun integration is currently available
46
+ only when running Buildr with JRuby.
47
+
48
+ Buildr provides a custom nailgun server, allowing you to
49
+ start a single JVM and let buildr create a queue of runtimes.
50
+ These JRuby runtimes can be cached (indexed by buildfile path)
51
+ and are automatically reloaded when the buildfile has been modified.
52
+ Runtime caching allows you to execute tasks without
53
+ spending time creating the buildr environment. Some nailgun
54
+ tasks have been provided to manage the cached runtimes.
55
+
56
+ To start the buildr server execute the following task:
57
+
58
+ nailgun:start
59
+
60
+ Server output will display a message when it becomes ready, you
61
+ will also see messages when the JRuby runtimes are being created,
62
+ or when a new buildr environment is being loaded on them.
63
+ After the runtime queues have been populated, you can start calling
64
+ buildr as you normally do, by invoking the $NAILGUN_HOME/ng binary:
65
+
66
+ # on another terminal, change directory to a project.
67
+ # if this project is the same nailgun:start was invoked on, it's
68
+ # runtime has been cached, so no loading is performed unless
69
+ # the buildfile has been modified. otherwise the buildfile
70
+ # will be loaded on a previously loaded fresh-buildr runtime
71
+ # and it will be cached.
72
+ cd /some/buildr/project
73
+ ng nailgun:help # display nailgun help
74
+ ng nailgun:tasks # display overview of ng tasks
75
+ ng clean compile # just invoke those two tasks
76
+
77
+ Configuration and Environment Variables.
78
+
79
+ Before starting the server, buildr will check if you have
80
+ nailgun already installed by seeking the nailgun jar under
81
+
82
+ $NAILGUN_HOME
83
+
84
+ You can override this environment variable to tell buildr where
85
+ to find or where to install nailgun. If missing, NAILGUN_HOME
86
+ defaults to the $JRUBY_HOME/tool/nailgun directory.
87
+
88
+ Buildr will also check that the nailgun client binary (ng.exe for
89
+ Windows systems, ng otherwise) is installed on NAILGUN_HOME.
90
+ If no binary is found, buildr will download nailgun and
91
+ compile+install it.
92
+
93
+ The buildr server binds itself to localhost, port 2113. You can
94
+ override this when starting the nailgun server:
95
+
96
+ buildr nailgun:start[4444,127.0.0.1]
97
+
98
+ If you provided custom host/port settings you need
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.
108
+
109
+ Execute nailgun:tasks get an overview of available nailgun tasks.
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]
137
+ end
138
+
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
146
+ end
147
+ end
148
+
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
152
+ end
153
+
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}'
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
181
+ end
182
+
183
+ desc 'Show nailgun help'
184
+ task('help') do
185
+ info HELP
186
+ exit(0)
187
+ end
188
+
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
202
+
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)
210
+ end
211
+ else
212
+ info "Not running on nailgun server"
213
+ end
214
+ exit(0)
215
+ end
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"
224
+ else
225
+ info "Not running on nailgun server"
226
+ end
227
+ exit(0)
228
+ end
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"
244
+ end
245
+ exit(0)
246
+ end
247
+
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
255
+ end
256
+
257
+ Util.add_to_sysloader ng.artifact.to_s
258
+ Util.add_to_sysloader File.dirname(__FILE__)
259
+
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
267
+ end
268
+
269
+ end # server_setup
270
+
271
+ module Util
272
+ extend self
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
+
282
+ def benchmark(action = ['Completed'], verbose = true)
283
+ result = nil
284
+ times = Benchmark.measure do
285
+ result = yield(action)
286
+ end
287
+ if verbose
288
+ real = []
289
+ real << ("%ih" % (times.real / 3600)) if times.real >= 3600
290
+ real << ("%im" % ((times.real / 60) % 60)) if times.real >= 60
291
+ real << ("%.3fs" % (times.real % 60))
292
+ trace "#{[action].flatten.join(' ')} in #{real.join}"
293
+ end
294
+ result
295
+ end
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
+
344
+ def on_runtime(runtime, *args, &block)
345
+ raise_error = lambda do |cls, msg, trace|
346
+ raise RuntimeError.new(cls + ": "+ msg.to_s).tap { |e| e.set_backtrace(trace.map(&:to_s)) }
347
+ end
348
+ executor = runtime.object.const_get(:Module).new do
349
+ extend self
350
+ def runtime_exec(*args, &prc)
351
+ define_method(:runtime_exec, &prc)
352
+ runtime_exec(*args)
353
+ rescue => e
354
+ [:error, e.class.name, e.message, e.backtrace]
355
+ end
356
+ end
357
+ result = executor.runtime_exec(*args, &block)
358
+ raise_error.call(*result[1..-1]) if result.kind_of?(Array) && result.first == :error
359
+ result
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
+
383
+ end # module Util
384
+
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
397
+
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]
409
+ end
410
+ end
411
+ end
412
+
413
+ module NailMethods
414
+
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
420
+ end
421
+ end
422
+
423
+ def argv
424
+ [command] + args
425
+ end
426
+
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
437
+ end
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)
448
+ end
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
462
+
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
486
+ end
487
+
488
+ def rakefiles
489
+ Nailgun.ng.nail.options.rakefiles
490
+ end
491
+
492
+ def requires
493
+ Nailgun.ng.nail.options.requires
494
+ end
495
+
496
+ def help
497
+ super
498
+ puts
499
+ puts 'To get a summary of Nailgun features use'
500
+ puts ' nailgun:help'
501
+ end
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
515
+ else
516
+ super
517
+ end
518
+ end
519
+
520
+ def sBuildr
521
+ Nailgun.ng.nail.server.runtime.object.const_get(:Buildr)
522
+ end
523
+
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 = []
533
+ end
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)
541
+ end
542
+ end
543
+
544
+ def main(nail)
545
+ nail.extend NailMethods
546
+ info "Got connection from #{nail.pwd}"
547
+
548
+ Client.client(nail.jruby, nail) do
549
+
550
+ parse_options
551
+ if options.exit
552
+ send(options.exit)
553
+ nail.exit(0)
554
+ end
555
+
556
+ if options.project && File.directory?(options.project)
557
+ Dir.chdir(options.project)
558
+ end
559
+
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)
564
+ end
565
+
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
569
+
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
588
+ end
589
+ end
590
+
591
+ app.instance_eval do
592
+ @original_dir = nail.pwd
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)
608
+ end
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
635
+
636
+ def runtime
637
+ JRuby.runtime.extend RuntimeMixin
638
+ end
639
+
640
+ def start
641
+ self.allow_nails_by_class_name = false
642
+
643
+ NGClient::Main.nail = NGClient.new
644
+ self.default_nail_class = NGClient::Main
645
+ runtime_factory.start
646
+
647
+ @thread = java.lang.Thread.new(self)
648
+ @thread.setName(to_s)
649
+ @thread.start
650
+
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
659
+
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)
679
+
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
690
+
691
+ def new_jruby(&block)
692
+ # get(:jruby)
693
+ create_jruby(0, &block)
694
+ end
695
+
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
703
+
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"
718
+ needs.broadcast
719
+ trace "should be creating #{thing}"
720
+ ready.wait_while { collection.empty? }
721
+ 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
732
+
733
+ def create(thing, *args, &block)
734
+ Util.exception_handling do
735
+ creator = needed(thing)
736
+ collection = instance_variable_get("@#{thing}s")
737
+ ready = instance_variable_get("@#{thing}s_ready")
738
+ needs = instance_variable_get("@#{thing}s_needed")
739
+ unless creator
740
+ collection.synchronize do
741
+ trace "awake those wanting a #{thing}"
742
+ ready.broadcast
743
+ Thread.pass
744
+ trace "wait until more #{thing}s are needed"
745
+ # needs.wait(1); return
746
+ needs.wait_until { creator = needed(thing) }
747
+ end
748
+ end
749
+ trace "About to create #{thing} # #{creator}"
750
+ method = "create_#{thing}"
751
+ creators = instance_variable_get("@#{thing}s_creators")
752
+ trace "registering creator for #{thing} #{creator}"
753
+ creators.synchronize { creators << creator }
754
+ result = send(method, creator, *args, &block)
755
+ trace "created #{thing}[#{creator}] => #{result.inspect}"
756
+ creators.synchronize do
757
+ trace "unregistering creator for #{thing} #{creator}"
758
+ creators.delete(creator)
759
+ collection.synchronize do
760
+ trace "adding object on queue for #{thing} #{creator}"
761
+ collection << result
762
+ end
763
+ end
764
+ end
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 }
775
+ end
776
+ count if count < size
777
+ end
778
+ end
779
+
780
+ def create_jruby(creator, &block)
781
+ Util.exception_handling do
782
+ trace "Creating jruby[#{creator}]"
783
+ Util.benchmark do |header|
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
790
+ end
791
+ end
792
+ end
793
+
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
801
+ load_service.require 'rubygems'
802
+ load_service.require 'buildr'
803
+ end
804
+ jruby
805
+ end
806
+ end
807
+
808
+ end # RuntimeFactory
809
+
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
814
+
815
+ end # module Nailgun
816
+
817
+ end