assaf-buildr 1.3.3

Sign up to get free protection for your applications and to get access to all the features.
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