buildr 0.16.0 → 0.18.0

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.
@@ -1,7 +1,10 @@
1
+ require 'stringio'
2
+
1
3
  module Buildr
2
4
  module Java
3
5
 
4
6
  JAVA_OPTIONS = [ :verbose, :noop, :cp, :classpath, :name, :java_args ]
7
+ JUNIT_REQUIRES = [ "junit:junit:jar:3.8.1", "jmock:jmock:jar:1.1.0" ]
5
8
 
6
9
  def self.java(*args)
7
10
  options = Hash === args.last ? args.pop : {}
@@ -44,6 +47,19 @@ module Buildr
44
47
  end
45
48
  end
46
49
 
50
+ # Gets the version of the java VM
51
+ def self.version()
52
+ @version ||= `java -version 2>&1`.scan(/java version "(.*)"/)[0][0]
53
+ end
54
+
55
+ def self.tools()
56
+ unless @tools
57
+ tools = File.join(ENV['JAVA_HOME'], "lib", "tools.jar")
58
+ @tools = File.exist?(tools) ? tools : []
59
+ end
60
+ @tools
61
+ end
62
+
47
63
  class AptTask < Rake::FileTask
48
64
 
49
65
  def initialize(*args)
@@ -94,9 +110,27 @@ module Buildr
94
110
  end
95
111
  end
96
112
 
113
+ def self.junit(*args)
114
+ options = Hash === args.last ? args.pop : {}
115
+ options[:verbose] ||= Rake.application.options.trace || false
116
+ fu_check_options options, :verbose, :noop, :cp, :classpath, :sourcepath, :output, :javac_args, :name
117
+
118
+ classpath = classpath_from(options) + junit_artifacts
119
+ tests = args.flatten
120
+ failed = tests.inject([]) do |failed, test|
121
+ begin
122
+ java "junit.textui.TestRunner", test, :classpath=>classpath, :name=>"tests in #{test}"
123
+ failed
124
+ rescue
125
+ failed << test
126
+ end
127
+ end
128
+ [ tests - failed, failed ]
129
+ end
130
+
97
131
  protected
98
132
 
99
- def self.path_to_bin(name)
133
+ def self.path_to_bin(name = "java")
100
134
  ENV["JAVA_HOME"] ? File.join(ENV["JAVA_HOME"], "bin", name) : name
101
135
  end
102
136
 
@@ -105,6 +139,10 @@ module Buildr
105
139
  artifacts(classpath).each { |t| t.invoke if t.respond_to?(:invoke) }.map(&:to_s)
106
140
  end
107
141
 
142
+ def self.junit_artifacts()
143
+ @junit_artifacts ||= artifacts(JUNIT_REQUIRES).each { |task| task.invoke }
144
+ end
145
+
108
146
  end
109
147
 
110
148
  def java(*args)
@@ -0,0 +1,123 @@
1
+ require 'net/http'
2
+
3
+ # Monkeypatching: forcing FileUtils to ignore .svn files when
4
+ # copying files around. We may want to implement our own deep
5
+ # copy instead of hacking FileUtils in the future, but the cases
6
+ # where you effectively want to copy .svn files are very, very
7
+ # rare.
8
+ module FileUtils
9
+ class Entry_
10
+ alias original_cp copy
11
+ def copy(dest)
12
+ unless path['.svn']
13
+ original_cp(dest)
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ module Buildr
20
+
21
+ module Jetty
22
+
23
+ VERSION = "6.1.1"
24
+
25
+ REQUIRES = [ "org.mortbay.jetty:jetty:jar:#{VERSION}",
26
+ "org.mortbay.jetty:jetty-util:jar:#{VERSION}",
27
+ "org.mortbay.jetty:servlet-api-2.5:jar:#{VERSION}",
28
+ "log4j:log4j:jar:1.2.13",
29
+ "commons-logging:commons-logging:jar:1.1"
30
+ ]
31
+
32
+ OPTIONS = [ :classpath, :war_path, :context_path, :noop, :base_url, :process_alias ]
33
+
34
+ # Bouncing a webapp deployed in the Jetty web server. Just does a post
35
+ # to a buildr specific handler. If there's nothing on the other side,
36
+ # a new Jetty instance is spawned.
37
+ def self.bounce(options)
38
+ fu_check_options options, *OPTIONS
39
+ options[:classpath] ||= []
40
+
41
+ begin
42
+ puts "Bouncing webapp #{options[:war_path]}" if verbose
43
+ res = jetty_call('/bounce', :post, options)
44
+ puts "done." if verbose
45
+ rescue Errno::ECONNREFUSED => e
46
+ puts "Web server not found, spawning it."
47
+ runtool options.merge(:class=>"JettyWrapper",
48
+ :args=>[ options[:war_path], options[:context_path] ],
49
+ :classpath=>options[:classpath] + ['../buildr/lib/java/jetty'])
50
+ end
51
+
52
+ case res
53
+ when Net::HTTPNotFound
54
+ fail "A web server seems to be already running without Buildr deployment hooks."
55
+ when Net::HTTPInternalServerError
56
+ fail "Server error occured when redeploying the WAR, see the web server logs."
57
+ end
58
+ end
59
+
60
+ # Sends an http request to the buildr handler deployed in Jetty.
61
+ def self.jetty_call(rel_url, get_post, options)
62
+ base_url = URI.parse((options[:base_url] || 'http://localhost:8080/buildr') + rel_url)
63
+ req = get_post == :post ? Net::HTTP::Post.new(base_url.path) : Net::HTTP::Get.new(base_url.path)
64
+ res = Net::HTTP.start(base_url.host, base_url.port) {|http| http.request(req) }
65
+ end
66
+
67
+ protected
68
+
69
+ def self.runtool(options)
70
+ classpath = REQUIRES + (options[:classpath] || []).collect | (options[:cp] || []).collect
71
+ classpath = artifacts(classpath).each { |t| t.invoke if t.respond_to?(:invoke) }.map(&:to_s)
72
+ cmd_args = ["-cp", classpath.join(File::PATH_SEPARATOR)]
73
+ cmd_args << options[:class]
74
+ cmd_args += options[:args]
75
+ unless options[:noop]
76
+ if fork.nil?
77
+ STDOUT.reopen File.new("stdout.log", "w")
78
+ STDERR.reopen File.new("stderr.log", "w")
79
+ exec ([Java.path_to_bin("java")] + cmd_args).join(' ')
80
+ end
81
+ end
82
+ end
83
+
84
+ class JettyTask < Rake::Task
85
+ def initialize(*args)
86
+ super
87
+ enhance do |task|
88
+ Jetty.bounce task.options
89
+ end
90
+ end
91
+
92
+ def options()
93
+ @options ||= {}
94
+ end
95
+
96
+ def using(options)
97
+ self.options.merge!(options)
98
+ self
99
+ end
100
+ end
101
+ end
102
+
103
+ class Project
104
+ def webserve(&block)
105
+ task "jetty:shutdown" do
106
+ begin
107
+ res = Jetty.jetty_call('/stop', :put, @webserve_task.options)
108
+ puts "Response #{res}" if verbose
109
+ rescue Errno::ECONNREFUSED
110
+ puts "Jetty server couldn't be contacted, nothing done."
111
+ rescue EOFError
112
+ puts "Shutdown successful."
113
+ rescue Exception => e
114
+ puts "Unexpected error: #{e.class}"
115
+ end
116
+ end
117
+ returning(@webserve_task ||= Jetty::JettyTask.define_task("jetty:bounce"=>package(:war))) do |task|
118
+ task.enhance &block if block
119
+ end
120
+ end
121
+ end
122
+
123
+ end
@@ -0,0 +1,107 @@
1
+ import org.mortbay.jetty.Server;
2
+ import org.mortbay.jetty.Request;
3
+ import org.mortbay.jetty.Handler;
4
+ import org.mortbay.jetty.handler.AbstractHandler;
5
+ import org.mortbay.jetty.handler.ContextHandler;
6
+ import org.mortbay.jetty.handler.ContextHandlerCollection;
7
+ import org.mortbay.jetty.webapp.WebAppContext;
8
+
9
+ import javax.servlet.http.HttpServletRequest;
10
+ import javax.servlet.http.HttpServletResponse;
11
+ import javax.servlet.ServletException;
12
+ import java.io.IOException;
13
+
14
+ /**
15
+ * @author Matthieu Riou <mriou at apache dot org>
16
+ */
17
+ public class JettyWrapper {
18
+
19
+ private Server _server;
20
+ private WebAppContext _webAppHandler;
21
+ private ContextHandlerCollection _handlerColl;
22
+ private String _webAppDir;
23
+ private String _contextPath;
24
+
25
+ public JettyWrapper(String webAppDir, String contextPath) {
26
+ _server = new Server(8080);
27
+ _webAppDir = webAppDir;
28
+ _contextPath = contextPath;
29
+
30
+ // Adding handler for the war to deploy
31
+ _webAppHandler = new WebAppContext(_webAppDir, _contextPath);
32
+ _webAppHandler.setConfigurationClasses(new String[] {
33
+ "org.mortbay.jetty.webapp.WebInfConfiguration",
34
+ "org.mortbay.jetty.webapp.WebXmlConfiguration"});
35
+
36
+ // Adding the buildr handler to control our server lifecycle
37
+ ContextHandler context = new ContextHandler();
38
+ context.setContextPath("/buildr");
39
+ Handler handler = new BuildrHandler();
40
+ context.setHandler(handler);
41
+
42
+ _handlerColl = new ContextHandlerCollection();
43
+ _handlerColl.setHandlers(new Handler[] {_webAppHandler, context});
44
+
45
+ _server.addHandler(_handlerColl);
46
+ }
47
+
48
+ public void start() {
49
+ try {
50
+ _server.start();
51
+ _server.join();
52
+ } catch (Exception e) {
53
+ e.printStackTrace();
54
+ }
55
+ }
56
+
57
+ public static void main(String[] args) {
58
+ if (args.length != 2) {
59
+ System.out.println("Please provide the webapp directory and the context path.");
60
+ }
61
+ String webAppDir = args[0];
62
+ String contextPath = args[1];
63
+ JettyWrapper jetwrap = new JettyWrapper(webAppDir, contextPath);
64
+ jetwrap.start();
65
+ }
66
+
67
+ private class BuildrHandler extends AbstractHandler {
68
+
69
+ public void handle(String string, HttpServletRequest request,
70
+ HttpServletResponse response, int i) throws IOException, ServletException {
71
+ response.setContentType("text/html");
72
+ if (request.getPathInfo().equals("/bounce")) {
73
+ try {
74
+ _webAppHandler.stop();
75
+ _handlerColl.removeHandler(_webAppHandler);
76
+ _webAppHandler = new WebAppContext(_webAppDir, _contextPath);
77
+ _webAppHandler.setConfigurationClasses(new String[] {
78
+ "org.mortbay.jetty.webapp.WebInfConfiguration",
79
+ "org.mortbay.jetty.webapp.WebXmlConfiguration"});
80
+ _handlerColl.addHandler(_webAppHandler);
81
+ _webAppHandler.start();
82
+ } catch (Throwable e) {
83
+ e.printStackTrace();
84
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
85
+ ((Request)request).setHandled(true);
86
+ return;
87
+ }
88
+ } else if (request.getPathInfo().equals("/stop")) {
89
+ try {
90
+ _server.stop();
91
+ _server.destroy();
92
+ // Brute force
93
+ System.exit(0);
94
+ } catch (Exception e) {
95
+ e.printStackTrace();
96
+ }
97
+ } else if (request.getPathInfo().equals("/war")) {
98
+ response.getWriter().println(_webAppHandler.getTempDirectory());
99
+ ((Request)request).setHandled(true);
100
+ return;
101
+ }
102
+ response.getWriter().println("OK " + request.getPathInfo());
103
+ ((Request)request).setHandled(true);
104
+ }
105
+
106
+ }
107
+ }
@@ -36,16 +36,14 @@ module Buildr
36
36
  protected
37
37
 
38
38
  def self.runtool(options)
39
- classpath = REQUIRES + (options[:classpath] || []).collect | (options[:cp] || []).collect
40
- classpath = artifacts(classpath).each { |t| t.invoke if t.respond_to?(:invoke) }.map(&:to_s)
41
- cmd_args = ["-cp", classpath.join(File::PATH_SEPARATOR)]
42
- cmd_args << options[:class]
43
- cmd_args += options[:args].select { |n, v| v }.map { |n, v| [ n, v ] }.flatten
44
- cmd_args << { :verbose=>options[:verbose] }
45
- unless options[:noop]
46
- verbose { puts "Running OpenJPA #{options[:name]}" }
47
- sh(Java.path_to_bin("java"), *cmd_args) { |ok, res| fail "Failed to execute OpenJPA #{options[:name]}, see errors above" unless ok }
48
- end
39
+ args = [options[:class]] + options[:args].select { |n, v| v }.map { |n, v| [ n, v ] }.flatten
40
+ args << { :classpath=>requires + (options[:classpath] || []),
41
+ :name=>"OpenJPA #{options[:name]}", :verbose=>options[:verbose] }
42
+ java *args
43
+ end
44
+
45
+ def self.requires()
46
+ @required ||= artifacts(REQUIRES).each { |artifact| artifact.invoke }.map(&:to_s)
49
47
  end
50
48
 
51
49
  end
@@ -3,10 +3,11 @@ module Buildr
3
3
 
4
4
  module Packaging
5
5
 
6
- MANIFEST_HEADER = "Manifest-Version: 1.0\nCreated-By: Ruby Build System"
6
+ MANIFEST_HEADER = "Manifest-Version: 1.0\nCreated-By: Buildr\n"
7
7
 
8
8
  class JarTask < ZipTask
9
9
  attr_accessor :manifest
10
+ attr_accessor :meta_inf
10
11
 
11
12
  def initialize(*args)
12
13
  super
@@ -16,6 +17,8 @@ module Buildr
16
17
  def []=(key, value)
17
18
  if key.to_sym == :manifest
18
19
  self.manifest = value
20
+ elsif key.to_sym == :meta_inf
21
+ self.meta_inf = value
19
22
  else
20
23
  super key, value
21
24
  end
@@ -25,23 +28,25 @@ module Buildr
25
28
  protected
26
29
 
27
30
  def create(zip)
28
- if manifest
29
- zip.mkdir "META-INF"
31
+ zip.mkdir "META-INF"
32
+ meta_inf.each { |file| zip.add "META-INF/#{File.basename(file)}", file } if meta_inf
33
+ unless manifest == false
30
34
  zip.file.open("META-INF/MANIFEST.MF", "w") do |output|
31
35
  output.write MANIFEST_HEADER
32
- case manifest
33
- when Hash
34
- output.write manifest.map { |pair| pair.join(": ") }.join("\n")
35
- when Array
36
- manifest.each do |section|
37
- output.write "\n"
38
- output.write section.map { |pair| pair.join(": ") }.join("\n")
36
+ if manifest
37
+ case manifest
38
+ when Hash
39
+ output.write manifest.map { |pair| pair.join(": ") }.sort.join("\n")
40
+ when Array
41
+ manifest.each do |section|
42
+ output.write "\n"
43
+ output.write section.map { |pair| pair.join(": ") }.sort.join("\n")
44
+ end
45
+ when Proc, Method
46
+ output.write manifest.call
47
+ when String
48
+ output.write File.read(manifest)
39
49
  end
40
- when Proc, Method
41
- output.write manifest.call
42
- when String
43
- output.write File.read(manifest)
44
- when true # Default behavior
45
50
  end
46
51
  output.write "\n"
47
52
  end
@@ -56,7 +61,7 @@ module Buildr
56
61
  def []=(key, value)
57
62
  case key.to_sym
58
63
  when :libs
59
- self.include value, :path=>"WEB-INF/lib"
64
+ self.include artifacts(value), :path=>"WEB-INF/lib"
60
65
  when :classes
61
66
  self.include value, :path=>"WEB-INF/classes"
62
67
  else
@@ -79,13 +84,22 @@ module Buildr
79
84
  Packaging::JarTask.define_task(file)
80
85
  end
81
86
 
82
-
83
87
  class Project
84
88
 
85
89
  # Group used for packaging. Inherited from parent project.
86
90
  inherited_attr :group
87
91
  # Version used for packaging. Inherited from parent project.
88
92
  inherited_attr :version
93
+ # Manifest used for packaging. Inherited from parent project.
94
+ inherited_attr :manifest do |project|
95
+ manifest = { "Build-By"=>ENV['USER'], "Build-Jdk"=>Java.version }
96
+ manifest["Implementation-Version"] = project.version if project.version
97
+ manifest
98
+ end
99
+ # Files to always include in the package META-INF directory.
100
+ inherited_attr :meta_inf do |project|
101
+ meta_inf = ["DISCLAIMER", "LICENSE", "NOTICE"].map { |f| path_to(f) if File.exist?(path_to(f)) }.compact
102
+ end
89
103
 
90
104
  # The project ID is the project name, and for a sub-project the
91
105
  # parent project ID followed by the project name, separated with a
@@ -97,7 +111,7 @@ module Buildr
97
111
 
98
112
  def package(*args)
99
113
  if Hash === args.last
100
- options = args.pop.clone
114
+ options = args.pop.dup
101
115
  else
102
116
  options = {}
103
117
  end
@@ -117,14 +131,14 @@ module Buildr
117
131
  fail("Do not know how to create a package of type #{options[:type]}")
118
132
  package = packager.call(file, options) or fail("Do not know how to create a package of type #{options[:type]}")
119
133
 
120
- task("package").enhance [package]
121
- package.enhance [task("build")]
134
+ task "package"=>package
135
+ package.enhance [ task("build")]
122
136
 
123
- task "install"=>[
124
- file_create(File.dirname(repositories.locate(package))) { |task| mkpath task.name, :verbose=>false },
125
- file(repositories.locate(package)=>package) { |task| cp package.name, task.name },
126
- package.pom
127
- ]
137
+ task "install"=>(file(repositories.locate(package)=>package) { |task|
138
+ mkpath File.dirname(task.name), :verbose=>false
139
+ cp package.name, task.name
140
+ })
141
+ task "install"=>package.pom
128
142
 
129
143
  task "uninstall" do |task|
130
144
  verbose(Rake.application.options.trace) do
@@ -147,30 +161,49 @@ module Buildr
147
161
  protected
148
162
 
149
163
  def package_as_jar(file, options)
164
+ unless Rake::Task.task_defined?(file)
165
+ returning(Java::Packaging::JarTask.define_task(file)) do |task|
166
+ package_extend task, options
167
+ task.enhance [path_to(:java_target_dir)]
168
+ task.include path_to(:java_target_dir, "*")
169
+ task.manifest = manifest.merge("Implementation-Title"=>self.comment)
170
+ task.meta_inf = meta_inf
171
+ end
172
+ end
150
173
  returning(Java::Packaging::JarTask.define_task(file)) do |task|
151
- package_extend task, options
152
- task.include path_to(:java_target_dir, "*")
153
174
  task.include options[:include] if options[:include]
154
175
  task.manifest = options[:manifest] if options[:manifest]
155
176
  end
156
177
  end
157
178
 
158
179
  def package_as_war(file, options)
180
+ unless Rake::Task.task_defined?(file)
181
+ returning(Java::Packaging::WarTask.define_task(file)) do |task|
182
+ package_extend task, options
183
+ task.include path_to(:webapp_src_dir, "*")
184
+ task.with :classes=>path_to(:java_target_dir, "**")
185
+ task.manifest = manifest.merge("Implementation-Title"=>self.comment)
186
+ task.meta_inf = meta_inf
187
+ end
188
+ end
159
189
  # Add anything we find in webapp sources directory.
160
190
  returning(Java::Packaging::WarTask.define_task(file)) do |task|
161
- package_extend task, options
162
- task.include path_to(:webapp_src_dir, "*")
163
191
  task.include options[:include] if options[:include]
164
192
  # Add libraries in WEB-INF lib, and classes in WEB-INF classes
165
193
  task.with :libs=>options[:libs].collect if options[:libs]
166
- task.with :classes=>(options[:classes] || path_to(:java_target_dir, "**")) unless options[:classes] == false
194
+ task.with :classes=>options[:classes] if options[:classes]
195
+ task.manifest = options[:manifest] if options[:manifest]
167
196
  end
168
197
  end
169
198
 
170
199
  def package_as_zip(file, options)
200
+ unless Rake::Task.task_defined?(file)
201
+ returning(ZipTask.define_task(file)) do |task|
202
+ package_extend task, options
203
+ task.include path_to(:java_target_dir, "*")
204
+ end
205
+ end
171
206
  returning(ZipTask.define_task(file)) do |task|
172
- package_extend task, options
173
- task.include path_to(:java_target_dir, "*")
174
207
  task.include options[:include] if options[:include]
175
208
  end
176
209
  end