buildr-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From boisv...@apache.org
Subject svn commit: r1003400 - in /buildr/trunk: CHANGELOG doc/more_stuff.textile lib/buildr.rb lib/buildr/core.rb lib/buildr/core/run.rb lib/buildr/run.rb spec/core/run_spec.rb spec/java/run_spec.rb
Date Fri, 01 Oct 2010 06:18:11 GMT
Author: boisvert
Date: Fri Oct  1 06:18:10 2010
New Revision: 1003400

URL: http://svn.apache.org/viewvc?rev=1003400&view=rev
Log:
BUILDR-514 New 'run' local task.

Added:
    buildr/trunk/lib/buildr/core/run.rb
    buildr/trunk/lib/buildr/run.rb
    buildr/trunk/spec/core/run_spec.rb
    buildr/trunk/spec/java/run_spec.rb
Modified:
    buildr/trunk/CHANGELOG
    buildr/trunk/doc/more_stuff.textile
    buildr/trunk/lib/buildr.rb
    buildr/trunk/lib/buildr/core.rb

Modified: buildr/trunk/CHANGELOG
URL: http://svn.apache.org/viewvc/buildr/trunk/CHANGELOG?rev=1003400&r1=1003399&r2=1003400&view=diff
==============================================================================
--- buildr/trunk/CHANGELOG (original)
+++ buildr/trunk/CHANGELOG Fri Oct  1 06:18:10 2010
@@ -1,4 +1,5 @@
 1.4.3 (Pending)
+* Added:  BUILDR-514 New 'run' local task. http://buildr.apache.org/more_stuff.html#run
 * Added:  BUILDR-518 Load _buildr.rb or .buildr.rb from same directory as Buildfile if they
exist (Peter Donald)
 * Added:  BUILDR-519 Load repositories.release_to from build settings (Peter Donald)
 * Fixed:  BUILDR-520 Scaladoc 2.8 no longer support -windowtitle, use -doc-title instead.
@@ -6,7 +7,7 @@
 * Fixed:  BUILDR-513 --trace fails with NoMethodError : undefined method 
           `include?' for nil:NilClass
 * Fixed:  BUILDR-515 -update-snapshot doesn't work as expected
-* Fixed:  JavaRebel was previously not correctly detected
+* Fixed:  JavaRebel was previously not correctly detected.
 
 1.4.2 (2010-09-18)
 * Added:  BUILDR-415 Ability to exclude tests from command line

Modified: buildr/trunk/doc/more_stuff.textile
URL: http://svn.apache.org/viewvc/buildr/trunk/doc/more_stuff.textile?rev=1003400&r1=1003399&r2=1003400&view=diff
==============================================================================
--- buildr/trunk/doc/more_stuff.textile (original)
+++ buildr/trunk/doc/more_stuff.textile Fri Oct  1 06:18:10 2010
@@ -108,7 +108,7 @@ If you don't know which tracing category
 $ buildr --trace=all
 {% endhighlight %}
 
-h3. JavaRebel Integration
+h3(#javarebel). JavaRebel Integration
 
 "JavaRebel":http://www.zeroturnaround.com/javarebel is a live bytecode reloading solution
by Zero Turnaround.  It's a lot like the hot code reload feature found in many Java IDE debuggers
(like Eclipse and IntelliJ), but capable of handling things like member addition or removal
and new class definition.  The tool itself is commercial and works with any JVM language,
but they do offer a free license for use with Scala classes only.
 
@@ -146,6 +146,59 @@ scala> </pre>
 
 Note that Buildr does *not* check to make sure that you have a valid JavaRebel license, so
you may end up launching with JavaRebel configured but without the ability to use it (in which
case, JavaRebel will print a notification).
 
+h2(#run). Running Your Application
+
+The @run@ task lets you easily run programs from your buildfile, such as launching your own
application.
+
+In its simplest form, you simply define the main class of your Java application,
+
+{% highlight ruby %}
+define 'my-project' do
+  compile.with COMMONS_IO, HTTPCLIENT
+  run.using :main => "org.example.Main"
+end
+{% endhighlight %}
+
+And then run,
+
+{% highlight ruby %}
+~/my-project$ buildr run
+{% endhighlight %}
+
+which would launch your application using the project's compile classpath.
+
+It's also possible to pass arguments to the JVM using the @:java_args@ option:
+
+{% highlight ruby %}
+  run.using :main => "org.example.Main",
+            :java_args => ["-server"]
+{% endhighlight %}
+
+If your application requires arguments, you can pass in an array of values for the @:main@
option, or provide a set of system properties using @:properties@.
+
+{% highlight ruby %}
+  run.using :main => ["org.example.Main", "-t", "input.txt"],
+            :properties => { :debug => "true" }
+{% endhighlight %}
+
+The @run@ task is a local task, which means that Buildr will automatically pick the @run@
task matching the project in the current directory.  Executing the following command:
+
+{% highlight ruby %}
+~/my-project/subproject$ buildr run
+{% endhighlight %}
+
+will run the @my-project:subproject:run@ task, assuming @my-project@ is your top-level project.
+
+Here is a summary of @run.using@ options,
+
+|_. Option |_. Description ... |
+| @:main@   | The java main class, e.g. "com.example.Main". Can also be an array if the main
class requires arguments. |
+| @:properties@   | A hash of system properties to be passed to java. |
+| @:java_args@ | An array of additional parameters to pass to java |
+| @:classpath@   | An array of additional classpath elements (i.e. artifacts, files, etc.).
By default, the @run@ task automatically uses the @compile.dependencies@, @test.dependencies@
and @test.compile.target@ of your project. |
+
+p(note). The @run@ task also detects and uses JavaRebel if it's available.  See the "JavaRebel":#javarebel
section for details.
+
 h2(#gems).  Using Gems
 
 The purpose of the buildfile is to define your projects, and the various tasks and functions
used for building them.  Some of these are specific to your projects, others are more general
in nature, and you may want to share them across projects.

Modified: buildr/trunk/lib/buildr.rb
URL: http://svn.apache.org/viewvc/buildr/trunk/lib/buildr.rb?rev=1003400&r1=1003399&r2=1003400&view=diff
==============================================================================
--- buildr/trunk/lib/buildr.rb (original)
+++ buildr/trunk/lib/buildr.rb Fri Oct  1 06:18:10 2010
@@ -22,6 +22,7 @@ require 'buildr/packaging'
 require 'buildr/java'
 require 'buildr/ide'
 require 'buildr/shell'
+require 'buildr/run'
 
 # Methods defined in Buildr are both instance methods (e.g. when included in Project)
 # and class methods when invoked like Buildr.artifacts().

Modified: buildr/trunk/lib/buildr/core.rb
URL: http://svn.apache.org/viewvc/buildr/trunk/lib/buildr/core.rb?rev=1003400&r1=1003399&r2=1003400&view=diff
==============================================================================
--- buildr/trunk/lib/buildr/core.rb (original)
+++ buildr/trunk/lib/buildr/core.rb Fri Oct  1 06:18:10 2010
@@ -23,6 +23,7 @@ require 'buildr/core/filter'
 require 'buildr/core/compile'
 require 'buildr/core/test'
 require 'buildr/core/shell'
+require 'buildr/core/run'
 require 'buildr/core/checks'
 require 'buildr/core/transports'
 require 'buildr/core/generate'

Added: buildr/trunk/lib/buildr/core/run.rb
URL: http://svn.apache.org/viewvc/buildr/trunk/lib/buildr/core/run.rb?rev=1003400&view=auto
==============================================================================
--- buildr/trunk/lib/buildr/core/run.rb (added)
+++ buildr/trunk/lib/buildr/core/run.rb Fri Oct  1 06:18:10 2010
@@ -0,0 +1,43 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with this
+# work for additional information regarding copyright ownership.  The ASF
+# licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+require 'buildr/run'
+require 'buildr/java/commands'
+require 'buildr/core/util'
+
+module Buildr
+  module Run
+
+    class JavaRunner < Base
+      include Shell::JavaRebel
+
+      specify :name => :java, :languages => [:java, :scala, :groovy, :clojure]
+
+      def run(task)
+        fail "Missing :main option" unless task.options[:main]
+        cp = project.compile.dependencies + [project.path_to(:target, :classes)] + task.classpath
+        Java::Commands.java(task.options[:main], {
+          :properties => rebel_props(project).merge (task.options[:properties] || {}),
+          :classpath => cp,
+          :java_args => rebel_args + (task.options[:java_args] || [])
+        })
+      end
+    end # JavaRunnner
+
+  end
+end
+
+Buildr::Run.runners << Buildr::Run::JavaRunner
+

Added: buildr/trunk/lib/buildr/run.rb
URL: http://svn.apache.org/viewvc/buildr/trunk/lib/buildr/run.rb?rev=1003400&view=auto
==============================================================================
--- buildr/trunk/lib/buildr/run.rb (added)
+++ buildr/trunk/lib/buildr/run.rb Fri Oct  1 06:18:10 2010
@@ -0,0 +1,202 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with this
+# work for additional information regarding copyright ownership.  The ASF
+# licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+
+module Buildr
+  module Run
+    include Extension
+
+    class << self
+      def runners
+        @runners ||= []
+      end
+
+      def select_by_lang(lang)
+        fail 'Unable to define run task for nil language' if lang.nil?
+        runners.detect { |e| e.languages.nil? ? false : e.languages.include?(lang.to_sym)
}
+      end
+
+      alias_method :select, :select_by_lang
+
+      def select_by_name(name)
+        fail 'Unable to define run task for nil' if name.nil?
+        runners.detect { |e| e.to_sym == name.to_sym }
+      end
+
+    end
+
+    # Base class for any run provider.  Defines most
+    # common functionality (things like @lang@, @build?@ and friends).
+    class Base
+      attr_reader :project
+
+      class << self
+        attr_accessor :name, :languages
+
+        def specify(options)
+          @name ||= options[:name]
+          @languages ||= options[:languages]
+        end
+
+        def to_sym
+          @name ||= name.split('::').last.downcase.to_sym
+        end
+      end
+
+      def initialize(project)
+        @project = project
+      end
+
+      def build?
+        true
+      end
+
+      def launch
+        fail 'Not implemented'
+      end
+    end
+
+    class RunTask < Rake::Task
+      # Classpath dependencies.
+      attr_accessor :classpath
+
+      # Returns the run options.
+      attr_reader :options
+
+      # Returns file dependencies
+      attr_reader :files
+
+      attr_reader :project # :nodoc:
+
+      def initialize(*args) # :nodoc:
+        super
+        @options = {}
+        @classpath = []
+        @files = FileList[]
+      end
+
+      # :call-seq:
+      #   with(*artifacts) => self
+      #
+      # Adds files and artifacts as classpath dependencies, and returns self.
+      def with(*specs)
+        @classpath |= Buildr.artifacts(specs.flatten).uniq
+        self
+      end
+
+      # :call-seq:
+      #   using(options) => self
+      #
+      # Sets the run options from a hash and returns self.
+      #
+      # For example:
+      #   run.using :main=>'org.example.Main'
+      def using(*args)
+        args.pop.each { |key, value| @options[key.to_sym] = value } if Hash === args.last
+
+        until args.empty?
+          new_runner = Run.select_by_name(args.pop)
+          @runner = new_runner.new(project) unless new_runner.nil?
+        end
+
+        self
+      end
+
+      # :call-seq:
+      #   requires(*files) => self
+      #
+      # Adds additional files and directories as dependencies to the task and returns self.
+      # When specifying a directory, includes all files in that directory.
+      def requires(*files)
+        @files.include *files.flatten.compact
+        self
+      end
+
+      def runner
+        @runner ||= guess_runner
+      end
+
+      # :call-seq:
+      #   runner?(clazz) => boolean
+      #
+      # Check if the underlying runner is an instance of the given class.
+      # If no class is supplied, simply check if runner is defined.
+      def runner?(clazz = nil)
+        begin
+          @runner ||= guess_runner if project.compile.language
+        rescue
+          return false
+        end
+        return !@runner.nil? unless clazz
+        @runner.is_a?(clazz) if @runner
+      end
+
+      def run
+        runner.run(self) if runner?
+      end
+
+      def prerequisites #:nodoc:
+        super + @files + classpath
+      end
+
+    private
+
+      def guess_runner
+        runner = Run.select project.compile.language
+        fail 'Unable to guess runner for project.' unless runner
+        runner.new project
+      end
+
+      def associate_with(project)
+        @project ||= project
+      end
+    end
+
+    first_time do
+      Project.local_task 'run'
+    end
+
+    before_define(:run => :test) do |project|
+      RunTask.define_task('run').tap do |run|
+        run.send(:associate_with, project)
+        run.enhance([project.compile, project.test]) do |t|
+          # double-enhance to execute the runner last
+          run.enhance { |t| t.run }
+        end
+      end
+    end
+
+    after_define(:run => :test) do |project|
+      project.run.with project.test.compile.dependencies
+      project.run.with project.test.compile.target if project.test.compile.target
+    end
+
+    # :call-seq:
+    #   run(&block) => RunTask
+    #
+    # This method returns the project's run task. It also accepts a block to be executed
+    # when the run task is invoked.
+    def run(&block)
+      task('run').tap do |t|
+        t.enhance &block if block
+      end
+    end
+
+  end
+
+  class Project
+    include Run
+  end
+end

Added: buildr/trunk/spec/core/run_spec.rb
URL: http://svn.apache.org/viewvc/buildr/trunk/spec/core/run_spec.rb?rev=1003400&view=auto
==============================================================================
--- buildr/trunk/spec/core/run_spec.rb (added)
+++ buildr/trunk/spec/core/run_spec.rb Fri Oct  1 06:18:10 2010
@@ -0,0 +1,92 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with this
+# work for additional information regarding copyright ownership.  The ASF
+# licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helpers'))
+
+describe Project, :run do
+
+  it 'should return the project\'s run task' do
+    define('foo')
+    project('foo').run.name.should eql('foo:run')
+  end
+
+  it 'should return a RunTask' do
+    define('foo')
+    project('foo').run.should be_kind_of(Run::RunTask)
+  end
+
+  it 'should include compile and test.compile dependencies' do
+    define('foo') do
+      compile.using(:javac).with 'group:compile:jar:1.0'
+      test.compile.using(:javac).with 'group:test:jar:1.0'
+    end
+    project('foo').run.classpath.should include(artifact('group:compile:jar:1.0'))
+    project('foo').run.classpath.should include(artifact('group:test:jar:1.0'))
+  end
+
+  it 'should respond to using() and return self' do
+    define 'foo' do
+      run.using(:foo=>'Fooing').should be(run)
+    end
+  end
+
+  it 'should respond to using() and accept options' do
+    define 'foo' do
+      run.using :foo=>'Fooing'
+    end
+    project('foo').run.options[:foo].should eql('Fooing')
+  end
+
+  it 'should select runner using run.using' do
+    define 'foo' do
+      run.using :java
+    end
+    project('foo').run.runner.should be_a(Run::JavaRunner)
+  end
+
+  it 'should select runner based on compile language' do
+    write 'src/main/java/Test.java', 'class Test {}'
+    define 'foo' do
+      # compile language detected as :java
+    end
+    project('foo').run.runner.should be_a(Run::JavaRunner)
+  end
+
+  it 'should depend on project''s compile and test.compile task' do
+    define 'foo'
+    project('foo').run.prerequisites.should include(project('foo').compile)
+  end
+
+  it 'should be local task' do
+    define 'foo' do
+      define('bar')
+    end
+    project('foo:bar').run.should_receive(:invoke_prerequisites)
+    project('foo:bar').run.should_receive(:run)
+    in_original_dir(project('foo:bar').base_dir) { task('run').invoke }
+  end
+
+  it 'should not recurse' do
+    define 'foo' do
+      define('bar') { run.using :java, :main => 'foo' }
+    end
+    project('foo:bar').run.should_not_receive(:invoke_prerequisites)
+    project('foo:bar').run.should_not_receive(:run)
+    project('foo').run.should_receive(:run)
+    project('foo').run.invoke
+  end
+
+end
+

Added: buildr/trunk/spec/java/run_spec.rb
URL: http://svn.apache.org/viewvc/buildr/trunk/spec/java/run_spec.rb?rev=1003400&view=auto
==============================================================================
--- buildr/trunk/spec/java/run_spec.rb (added)
+++ buildr/trunk/spec/java/run_spec.rb Fri Oct  1 06:18:10 2010
@@ -0,0 +1,78 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with this
+# work for additional information regarding copyright ownership.  The ASF
+# licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+
+require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helpers'))
+
+
+describe Run::JavaRunner do
+
+  it 'should fail on error' do
+    define 'foo' do
+      run.using :java, :main => 'org.example.NonExistentMain' # class doesn't exist
+    end
+    lambda { project('foo').run.invoke }.should raise_error(RuntimeError, /Failed to execute
java/)
+  end
+
+  it 'should execute main class' do
+    write 'src/main/java/org/example/Main.java', <<-JAVA
+      package org.example;
+      public class Main {
+        public static void main(String[] args) {
+          System.out.println("Hello, world!");
+        }
+      }
+    JAVA
+    define 'foo' do
+      run.using :main => 'org.example.Main'
+    end
+    project('foo').run.prerequisites.should include(task("foo:compile"))
+  end
+
+  it 'should accept :main option as an array including parameters for the main class' do
+    define 'foo' do
+      run.using :java, :main => ['org.example.Main', '-t', 'input.txt']
+    end
+    Java::Commands.should_receive(:java).once.with do |*args|
+      args[0].should == ['org.example.Main', '-t', 'input.txt']
+    end
+    project('foo').run.invoke
+  end
+
+  it 'should accept :java_args and pass them to java' do
+    define 'foo' do
+      run.using :java, :main => 'foo', :java_args => ['-server']
+    end
+    Java::Commands.should_receive(:java).once.with do |*args|
+      args[0].should == 'foo'
+      args[1][:java_args].should include('-server')
+    end
+    project('foo').run.invoke
+  end
+
+  it 'should accept :properties and pass them as -Dproperty=value to java' do
+    define 'foo' do
+      run.using :java, :main => 'foo', :properties => { :foo => 'one', :bar =>
'two' }
+    end
+    Java::Commands.should_receive(:java).once.with do |*args|
+      args[0].should == 'foo'
+      args[1][:properties][:foo].should == 'one'
+      args[1][:properties][:bar].should == 'two'
+    end
+    project('foo').run.invoke
+  end
+
+end
+



Mime
View raw message