Author: vborja
Date: Tue Sep  2 20:33:06 2008
New Revision: 691494

URL: http://svn.apache.org/viewvc?rev=691494&view=rev
Log:
Nailgun running on jruby 1.1.4, using BuildfileTask

Added:
    incubator/buildr/trunk/addon/buildr/org/apache/buildr/BuildrNail$Main.class
    incubator/buildr/trunk/addon/buildr/org/apache/buildr/BuildrNail.class
    incubator/buildr/trunk/addon/buildr/org/apache/buildr/BuildrNail.java
Modified:
    incubator/buildr/trunk/addon/buildr/nailgun.rb

Modified: incubator/buildr/trunk/addon/buildr/nailgun.rb
URL: 
http://svn.apache.org/viewvc/incubator/buildr/trunk/addon/buildr/nailgun.rb?rev=691494&r1=691493&r2=691494&view=diff
==============================================================================
--- incubator/buildr/trunk/addon/buildr/nailgun.rb (original)
+++ incubator/buildr/trunk/addon/buildr/nailgun.rb Tue Sep  2 20:33:06 2008
@@ -13,7 +13,6 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
-
 require 'benchmark'
 require 'jruby'
 require 'monitor'
@@ -24,310 +23,136 @@
 
 module Buildr
 
-  #  See the nailgun_help method for documentation.
-  module Nailgun # :nodoc:
+  module Nailgun
+
     extend self
     
+    attr_reader :ng
+    @ng ||= OpenStruct.new
+
     VERSION = '0.7.1'
     NAME = "nailgun-#{VERSION}"
     URL = "http://downloads.sourceforge.net/nailgun/#{NAME}.zip";
     ARTIFACT_SPEC = "com.martiansoftware:nailgun:jar:#{VERSION}"
+
+    # Paths used to initialize a buildr runtime
     BUILDR_PATHS = [File.expand_path('../', File.dirname(__FILE__)),
                     File.expand_path('../../lib', File.dirname(__FILE__))]
+
+    private
     
-    attr_accessor :artifact
-    attr_accessor :server, :port, :jruby_queue_size, :buildr_queue_size
-    attr_accessor :jruby_home, :home
-    
-    self.jruby_home = if RUBY_PLATFORM =~ /java/
-                        Config::CONFIG['prefix']
-                      else
-                        ENV['JRUBY_HOME'] || File.join(ENV['HOME'], '.jruby')
-                      end
+    # Returns the path to JRUBY_HOME.
+    def jruby_home
+      ENV['JRUBY_HOME'] || Config::CONFIG['prefix']
+    end
     
-    self.home = ENV['NAILGUN_HOME'] || File.join(jruby_home, 'tool', 'nailgun')
-    self.server = 'localhost'
-    self.port = 2113
-    self.jruby_queue_size = 3
-    self.buildr_queue_size = 3
-
-    def namespace(&block)
-      if Object.const_defined?(:Rake)
-        Rake.application.in_namespace(:nailgun, &block)
-      end
+    # Returns the path to NAILGUN_HOME.
+    def nailgun_home
+      ENV['NAILGUN_HOME'] || File.expand_path('tool/nailgun', jruby_home)
     end
 
-    def boot(&block)
-      if block
-        @boot = block
-      else
-        @boot.call
-      end
+    def tmp_path(*paths)
+      File.join(Dir.tmpdir, 'nailgun', *paths)
     end
 
-    module Application
-      def nailgun_help
-        "  " + <<-DESC.strip.gsub(/ *\n +/, "\n  ")
-          NailGun is a client, protocol, and server for running Java 
-          programs from the command line without incurring the JVM
-          startup overhead. Nailgun integration is currently available
-          only when running Buildr with JRuby.
-
-          Buildr provides a custom nailgun server, allowing you to 
-          start a single JVM and let buildr create a queue of runtimes.
-          These JRuby runtimes can be cached (indexed by buildfile path)
-          and are automatically reloaded when the buildfile has been modified.
-          Runtime caching allows you to execute tasks without
-          spending time creating the buildr environment. Some nailgun 
-          tasks have been provided to manage the cached runtimes.
-
-          To start the buildr server execute the following task:
-
-              nailgun:start
-
-          Server output will display a message when it becomes ready, you
-          will also see messages when the JRuby runtimes are being created,
-          or when a new buildr environment is being loaded on them.
-          After the runtime queues have been populated, you can start calling
-          buildr as you normally do, by invoking the $NAILGUN_HOME/ng binary:
-
-              # on another terminal, change directory to a project.
-              # if this project is the same nailgun:start was invoked on, it's 
-              # runtime has been cached, so no loading is performed unless 
-              # the buildfile has been modified. otherwise the buildfile 
-              # will be loaded on a previously loaded fresh-buildr runtime
-              # and it will be cached.
-              cd /some/buildr/project
-              ng nailgun:help                      # display nailgun help
-              ng nailgun:tasks                     # display overview of ng 
tasks
-              ng clean compile                # just invoke those two tasks
-
-             Configuration and Environment Variables.
-
-          Before starting the server, buildr will check if you have 
-          nailgun already installed by seeking the nailgun jar under
-
-              $NAILGUN_HOME
-
-          You can override this environment variable to tell buildr where
-          to find or where to install nailgun. If missing, NAILGUN_HOME
-          defaults to the $JRUBY_HOME/tool/nailgun directory. You can 
-          also specify the nailgun_home on your buildfile with the following
-          code:
-              
-              require 'buildr/nailgun'
-              Buildr::Nailgun.home = File.expand_path('~/.jruby/tool/nailgun')
-
-          Buildr will also check that the nailgun client binary (ng.exe for 
-          Windows systems, ng otherwise) is installed on NAILGUN_HOME. 
-          If no binary is found, buildr will download nailgun and 
-          compile+install it.
-          
-          
-          The buildr server binds itself to localhost, port 2113. You can 
-          override this on your buildfile, by placing the following code:
-
-              require 'buildr/nailgun'
-              Buildr::Nailgun.server = '127.0.0.1'
-              Buildr::Nailgun.port = 2233
-
-          If you provided custom host/port settings you need
-          to tell the nailgun client where to connect to:
-
-              ng --nailgun-server 127.0.0.1 --nailgun-port 2233 nailgun:tasks
-
-          The buildr server starts a BuildrFactory responsible for providing
-          a pool of JRuby runtimes configured and ready for task execution. 
-          This BuildrFactory consists of two queues: One of pure JRuby runtimes
-          with almost nothing loaded, and another of Buildr runtimes (consumed
-          from the first queue) with the Buildr runtime preloaded but without
-          any project definition. The jruby queue is used for sandboxing code
-          like running GetoptLong, but most importantly its the place where 
-          buildr runtimes begin life, to be later added on the buildr queue.
-          By default both queues are of size 3, you can customize this with:
-
-              require 'buildr/nailgun'
-              Buildr::Nailgun.jruby_queue_size = 4 # JRuby creation is fast!
-              Buildr::Nailgun.buildr_queue_size = 5 # loading buildr takes 
longer
-
-          The buildr_queue_size is of particular importance if you expect to 
-          reload lots of buildfiles.
- 
-          Execute nailgun:tasks get an overview of available nailgun tasks.
-          
-        DESC
-      end
+    file_tasks = lambda do
       
-      def nailgun_tasks
-        tasks = {}
-        tasks['nailgun:help'] = 'Display nailgun help'
-        tasks['nailgun:start'] = 'Start the Nailgun server.'
-        tasks['nailgun:stop'] = 'Stop the Nailgun server.'
-        tasks['nailgun:tasks'] = 'Display this message'
-        tasks['nailgun:list'] = <<-DESC
-                 Display a list of builfile paths having an associated
-                 buildr runtime. Having a cached runtime reduces buidlr
-                 execution time.
-
-                 If buildr finds the current buildfile on this list, 
-                 no file loading will be performed, only execution of 
-                 specified tasks on the previously loaded environment. 
-                 However if the cached runtime is out of date (buildfile
-                 has been modified) the runtime will be reloaded.
-
-                 This feature becomes handy when performing development
-                 cycle: edit -> compile -> test -> report. 
-
-                 This task exits inmediatly after printing the file list.
-            DESC
-        tasks['nailgun:clear'] = <<-DESC
-                 Remove all cached buildr runtimes and exit
-            DESC
-        tasks['nailgun:load'] = <<-DESC
-                 Add or update a cached runtime.
-                 
-                 Use this task to create a cached buildr runtime for a 
-                 buildfile.
-            DESC
-        tasks['nailgun:delete'] = <<-DESC
-                 Delete cached runtime for a buildfile and exit.
-            DESC
-        tasks['nailgun:once [tasks]'] = <<-DESC
-                 Ignore cached runtime and perform tasks on a newly 
-                 created environment. This new runtime is dropped right
-                 after buildr completion.
-            DESC
-        
-        out = ""
-        out << "\nNailgun tasks:\n"
-        tasks.each_pair do |task, desc|
-          out << "\n"
-          out << sprintf("  %20-s\n", [task].flatten.join(' | '))
-          out << sprintf("      %s\n", desc.strip.gsub(/ *\n +/, "\n      "))
-        end
-        out
-      end
-      
-      def buildfile(dir = nil, candidates = nil)
-        dir ||= Dir.pwd
-        candidates ||= @rakefiles.dup
-        Util.find_buildfile(dir, candidates, options.nosearch)
-      end
-      
-      def clear_invoked
-        tasks.each do |task|
-          is_project = 
Project.instance_variable_get(:@projects).key?(task.name)
-          task.instance_variable_set(:@already_invoked, false) unless 
is_project
-        end
-      end
-
-      if Buildr.const_defined?(:Application)
-        class Buildr::Application
-          include Nailgun::Application
-          public :requires
-        end
+      dist_zip = Buildr.download(tmp_path(NAME + '.zip') => URL)
+      dist_dir = Buildr.unzip(tmp_path(NAME) => dist_zip)
+      
+      nailgun_jar = file(File.expand_path(NAME + '.jar', nailgun_home))
+      ng.artifact = Buildr.artifact(ARTIFACT_SPEC).from(nailgun_jar)
+      unless File.exist?(nailgun_jar.to_s)
+        nailgun_jar.enhance [dist_dir]
       end
-    end
-    
-    module ContextRunner
-      extend self
       
-      def parse_options(ctx, opts)
-        opts.requires = []
-        Buildr.const_set(:VERSION, 
ctx.server.runtime.object.const_get(:Buildr)::VERSION)
-  
-        obj = OpenStruct.new(:ctx => ctx, :opts => opts)
-        class << obj
-          include Buildr::CommandLineInterface
-          
-          def help
-            super
-            puts 
-            puts 'To get a summary of Nailgun features use'
-            puts '  nailgun:help'
-          end
-
-          def do_option(opt, value)
-            case opt
-            when '--help'
-              help
-              opts.exit = true
-            when '--version'
-              puts version
-              opts.exit = true
-            when '--environment'
-              ctx.env['BUILDR_ENV'] = value
-            when '--buildfile'
-              opts.buildfile = value
-            when '--require'
-              opts.requires << value
-            when '--nosearch'
-              opts.nosearch = true
-            end
+      compiled_bin = file(tmp_path(NAME, NAME, 'ng' + 
Config::CONFIG['EXEEXT']) => dist_dir.target) do |task|
+        unless task.to_s.pathmap('%x') == '.exe'
+          Dir.chdir(task.to_s.pathmap('%d')) do
+            info "Compiling #{task.to_s}"
+            system('make', task.to_s.pathmap('%f')) or
+              fail "Nailgun binary compilation failed."
           end
         end
-        
-        ARGV.replace(ctx.argv)
-        obj.parse_options
       end
       
-      def run(ctx)
-        ARGV.replace(ctx.argv)
-        Dir.chdir(ctx.pwd)
-        ctx.env.each { |k, v| ENV[k.to_s] = v.to_s }
-        Buildr::Application.module_eval do
-          include Nailgun::Application
-        end
-        task 'nailgun:load' do
-          puts "Buildfile #{Rake.application.buildfile} loaded"
+      ng.installed_bin = 
file(File.expand_path(compiled_bin.to_s.pathmap('%f'), nailgun_home) => 
compiled_bin) do |task|
+        mkpath task.to_s.pathmap('%d'), :verbose => false
+        cp compiled_bin.to_s, task.to_s, :verbose => false
+      end
+      
+    end # file_tasks
+
+    server_tasks = lambda do 
+
+      task('start', :port, :iface, :queue_size => [ng.artifact, 
ng.installed_bin]) do |task, args|
+        
+        iface = args[:iface].to_s.empty? ? '127.0.0.1' : args[:iface]
+        port  = args[:port].to_s.empty? ? 2113 : args[:port].to_i
+        queue_size = args[:queue_size].to_s.empty? ? 1 : args[:queue_size].to_i
+
+        if ng.server || ng.nail
+          fail "Already running on Nailgun server: #{ng.server || ng.nail}"
         end
-        if ctx.fresh
-          run_fresh(ctx)
-        else
-          run_local(ctx)
+        info 'Booting Buildr nailgun server...'
+        top_level = Buildr.application.instance_eval { @top_level_tasks.dup }
+        top_level.delete_if { |t| t[/nailgun/] }
+        unless top_level.empty?
+          raise 'Don\'t specify more targets when starting Nailgun server'
         end
+        ng.server_setup.call
+
+        factory = RuntimeFactory.new(queue_size, queue_size)
+        ng.server = NGServer.new(iface, port, factory)
+
+        ng.server.start
+      end
+
+      task('help') do
+        info "HELP"
       end
       
-      private
-      
-      def run_fresh(ctx)
-        Project.clear
-        old_app = Rake.application
-        Rake.application = Buildr::Application.new
-        Rake.application.instance_eval do
-          @tasks = old_app.instance_variable_get(:@tasks)
-          @rules = old_app.instance_variable_get(:@rules)
-          run
-        end
+    end # server_tasks
+
+    client_tasks = lambda do
+
+      task('list') do
+        info "HELLO"
       end
 
-      def run_local(ctx)
-        Rake.application.instance_eval do
-          verbose(nil)
-          options.trace = false
-          parse_options
-          collect_tasks
-          clear_invoked
-          top_level_tasks.delete('buildr:initialize')
-          Util.benchmark { top_level } 
-        end
+    end # client_tasks
+
+    # Load java classes on server side.
+    ng.server_setup = lambda do 
+
+      module Util
+        include Buildr::Util
       end
-    end
 
-    module Util
-      extend Buildr::Util
-      extend self
+      Util.add_to_sysloader ng.artifact.to_s
+      Util.add_to_sysloader File.dirname(__FILE__)
 
-      def find_buildfile(pwd, candidates, nosearch=false)
-        candidates = [candidates].flatten
-        buildfile = candidates.find { |c| File.file?(File.expand_path(c, pwd)) 
}
-        return File.expand_path(buildfile, pwd) if buildfile
-        return nil if nosearch
-        updir = File.dirname(pwd)
-        return nil if File.expand_path(updir) == File.expand_path(pwd)
-        find_buildfile(updir, candidates)
+      class Client
+        include org.apache.buildr.BuildrNail
+      end
+
+      class NGServer < com.martiansoftware.nailgun.NGServer
+        include Server
       end
+
+    end # server_setup
+    
+    module Util
+      extend self
       
+      def add_to_sysloader(path)
+        sysloader = java.lang.ClassLoader.getSystemClassLoader
+        add_url_method = java.lang.Class.forName('java.net.URLClassLoader').
+          getDeclaredMethod('addURL', 
[java.net.URL.java_class].to_java(java.lang.Class))
+        add_url_method.setAccessible(true)
+        add_url_method.invoke(sysloader, 
[java.io.File.new(path).toURI.toURL].to_java(java.net.URL))
+      end
+
       def benchmark(action = ['Completed'], verbose = true)
         result = nil
         times = Benchmark.measure do
@@ -338,11 +163,56 @@
           real << ("%ih" % (times.real / 3600)) if times.real >= 3600
           real << ("%im" % ((times.real / 60) % 60)) if times.real >= 60
           real << ("%.3fs" % (times.real % 60))
-          puts "#{[action].flatten.join(' ')} in #{real.join}"
+          trace "#{[action].flatten.join(' ')} in #{real.join}"
         end
         result
       end
 
+      def find_buildfile(pwd, candidates, nosearch=false)
+        candidates = [candidates].flatten
+        buildfile = candidates.find { |c| File.file?(File.expand_path(c, pwd)) 
}
+        return File.expand_path(buildfile, pwd) if buildfile
+        return nil if nosearch
+        updir = File.dirname(pwd)
+        return nil if File.expand_path(updir) == File.expand_path(pwd)
+        find_buildfile(updir, candidates)
+      end
+
+      def exception_handling(raise_again = true)
+        begin
+          yield
+        rescue => e
+          error "#{e.backtrace.shift}: #{e.message}"
+          e.backtrace.each { |i| error "\tfrom #{i}" }
+          raise e if raise_again
+        end
+      end
+
+      # invoke a java constructor
+      def ctor(on_class, *args)
+        parameters = []
+        classes = []
+        args.each do |obj|
+          case obj
+          when nil
+            classes.push(nil)
+            parameters.push(nil)
+          when Hash
+            vclass = obj.keys.first
+            value = obj[vclass]
+            classes.push(vclass.java_class)
+            parameters.push(value)
+          else
+            parameters.push obj
+            classes.push obj.java_class
+          end
+        end
+        on_class = [on_class.java_class].to_java(java.lang.Class)[0]
+        ctor = 
on_class.getDeclaredConstructor(classes.to_java(java.lang.Class))
+        ctor.setAccessible(true)
+        ctor.newInstance(parameters.to_java(java.lang.Object))
+      end
+
       def on_runtime(runtime, *args, &block)
         raise_error = lambda do |cls, msg, trace|
           raise RuntimeError.new(cls + ": "+ msg.to_s).tap { |e| 
e.set_backtrace(trace.map(&:to_s)) }
@@ -360,534 +230,444 @@
         raise_error.call(*result[1..-1]) if result.kind_of?(Array) && 
result.first == :error
         result
       end
+
+      def set_stdio(runtime, dev)
+        set_global = lambda do |global, constant, stream|
+          runtime.global_variables.set(global, stream)
+          runtime.object.send(:remove_const, constant)
+          runtime.object.send(:const_set, constant, stream)
+        end
+        stdin  = runtime.global_variables.get('$stdin')
+        stdout = runtime.global_variables.get('$stdout')
+        stderr = runtime.global_variables.get('$stderr')
+        #stdin.close; stdout.close; stderr.close;
+        output = Util.ctor(org.jruby.RubyIO, runtime, java.io.OutputStream => 
dev.out)
+        error = Util.ctor(org.jruby.RubyIO, runtime, java.io.OutputStream => 
dev.err)
+        input = Util.ctor(org.jruby.RubyIO, runtime, java.io.InputStream => 
dev.in)
+        #stdin.reopen(input, 'r') # not working on jruby, :(
+        #stdout.reopen(output, 'w')
+        #stderr.reopen(error, 'w')
+        set_global.call('$stdin', 'STDIN', input)
+        set_global.call('$stdout', 'STDOUT', output)
+        set_global.call('$stderr', 'STDERR', error)
+      end
+
     end # module Util
 
-    boot do
+    class FieldAccessor
+      def initialize(obj, clazz = nil)
+        @obj = obj
+        clazz ||= obj.class
+        @cls = [clazz.java_class].to_java(java.lang.Class)[0]
+      end
+
+      def [](name)
+        field = @cls.getDeclaredField(name.to_s)
+        field.setAccessible(true)
+        field.get(@obj)
+      end
       
-      class ::ConcreteJavaProxy
-        def self.jclass(name = nil)
-          name ||= self.java_class.name
-          Nailgun::Util.class_for_name(name)
-        end
-        
-        def self.jnew(*args)
-          objs = []
-          classes = args.map do |a|
-            case a
-            when nil
-              obj << nil
-              nil
-            when Hash
-              objs << a.keys.first
-              cls = a.values.first
-              cls = Nailgun::Util.proxy_class(cls) if String == cls
-              cls
-            else
-              objs << a
-              a.java_class
-            end
-          end
-          classes = classes.to_java(java.lang.Class)
-          ctor = jclass.getDeclaredConstructor(classes)
-          ctor.setAccessible(true)
-          ctor.newInstance(objs.to_java(java.lang.Object))
+      def []=(name, value)
+        field = @cls.getDeclaredField(name.to_s)
+        field.setAccessible(true)
+        field.set(@obj, value)
+      end
+      
+      def method_missing(name, value =nil)
+        if name.to_s =~ /=$/
+          self[name.to_s.chomp('=')] = value
+        else
+          self[name]
         end
       end
+    end
 
-      module Util
-        def class_for_name(name)
-          java.lang.Class.forName(name)
-        end
+    class Client
+
+      module NailMethods
         
-        def add_to_sysloader(path)
-          sysloader = java.lang.ClassLoader.system_class_loader
-          add_url_method = class_for_name('java.net.URLClassLoader').
-            getDeclaredMethod('addURL', 
[java.net.URL].to_java(java.lang.Class))
-          add_url_method.accessible = true
-          add_url_method.invoke(sysloader, [java.io.File.new(path.to_s).
-                                            toURL].to_java(java.net.URL))
+        def self.extend_object(obj)
+          super
+          (class << obj; self; end).module_eval do
+            alias_method :pwd, :getWorkingDirectory
+            alias_method :server, :getNGServer
+          end
         end
-        add_to_sysloader Nailgun.artifact
-        
-        def proxy_class(name)
-          JavaUtilities.get_proxy_class(name)
+
+        def argv
+          [command] + args
         end
 
-        import org.jruby.RubyIO 
-        def set_stdio(runtime, dev)
-          set_global = lambda do |global, constant, stream|
-            runtime.global_variables.set(global, stream)
-            runtime.object.send(:remove_const, constant)
-            runtime.object.send(:const_set, constant, stream)
-          end
-          stdin  = runtime.global_variables.get('$stdin')
-          stdout = runtime.global_variables.get('$stdout')
-          stderr = runtime.global_variables.get('$stderr')
-          input  = RubyIO.jnew(runtime, dev.in => java.io.InputStream)
-          output = RubyIO.jnew(runtime, dev.out => java.io.OutputStream)
-          error = RubyIO.jnew(runtime, dev.err => java.io.OutputStream)
-          # stdin.reopen(input, 'r') # not working on jruby, :(
-          set_global.call('$stdin', 'STDIN', input)
-          stdout.reopen(output, 'w')
-          stderr.reopen(error, 'w')
+        def attach_runtime(runtime)
+          runtime.evalScriptlet %q{
+            require 'ostruct'
+            module Buildr
+              module Nailgun
+                extend self
+                attr_reader :ng
+                @ng = OpenStruct.new
+              end
+            end
+          }
+          runtime.object.const_get(:Buildr)::Nailgun.ng.nail = self
+          runtime.load_service.require __FILE__
+          runtime
         end
+        private :attach_runtime
 
-        def redirect_stdio(runtime, nail)
-          result = nil
-          begin 
-            set_stdio(runtime, nail)
-            result = yield
-          ensure
-            set_stdio(runtime, java.lang.System)
-          end
-          result
+        def jruby
+          @jruby ||= attach_runtime(server.runtime_factory.new_jruby)
         end
-      end
 
-      class Buildfile
-        attr_reader :path, :requires, :loaded_time
-        attr_accessor :runtime
-        
-        def initialize(path, *requires)
-          @path = File.expand_path(path)
-          @requires = requires.dup
+        def buildr
+          @buildr ||= server.runtime_factory.new_buildr
         end
 
-        def loaded!
-          @loaded_time = Time.now
+        def options
+          @options ||= OpenStruct.new
         end
 
-        def last_modification
-          Util.timestamp(path)
+      end # NailMethods
+
+      class << self
+        include Buildr::CommandLineInterface
+
+        def options
+          Nailgun.ng.nail.options
         end
-        
-        def should_be_loaded?
-          (loaded_time || Rake::EARLY) < last_modification
+
+        def rakefiles
+          Nailgun.ng.nail.options.rakefiles
+        end
+
+        def requires
+          Nailgun.ng.nail.options.requires
         end
         
-        def to_s
-          buff = path.dup
-          buff << sprintf("\n  %-25s %s", "Last Modified:", last_modification)
-          unless requires.empty?
-            buff << sprintf("\n  %-25s %s", "Requires:", requires.join(" ")) 
-          end
-          if should_be_loaded?
-            buff << sprintf("\n  %-25s %s", "Needs reload, last was:", 
loaded_time)
+        def help
+          super
+          puts 
+          puts 'To get a summary of Nailgun features use'
+          puts '  nailgun:help'        
+        end
+
+        def version
+          puts super
+        end
+
+        def do_option(opt, value)
+          case opt
+          when '--help'
+            options.exit = :help
+          when '--version'
+            options.exit = :version
+          when '--nosearch'
+            options.nosearch = true
           else
-            buff << sprintf("\n  %-25s %s", "Loaded at:", loaded_time)
+            super
           end
-          buff << sprintf("\n  %-25s %s", "Runtime:", runtime)
-          buff
-        end        
-      end
-      
-      class BuildrNail 
-        include org.apache.buildr.BuildrNail
-        Main = Util.proxy_class 'org.apache.buildr.BuildrNail$Main'
+        end
 
-        attr_reader :buildfile
+        def sBuildr
+          Nailgun.ng.nail.server.runtime.object.const_get(:Buildr)
+        end
         
-        def initialize
-          buildfile = Buildfile.new(Rake.application.buildfile,
-                                    *Rake.application.requires)
-          buildfile.loaded!
-          buildfile.runtime = JRuby.runtime
-          @buildfiles = { buildfile.path => buildfile }
+        def attach_runtime
+          nail = Nailgun.ng.nail
+          ARGV.replace nail.argv
+          Dir.chdir nail.pwd
+          nail.env.each { |k, v| ENV[k.to_s] = v.to_s }
+          
+          Buildr.const_set(:VERSION, sBuildr::VERSION) unless 
Buildr.const_defined?(:VERSION)
+          nail.options.rakefiles = sBuildr::Application::DEFAULT_BUILDFILES.dup
+          nail.options.requires = []
+        end
+        
+        def client(runtime, nail, &block)
+          runtime.object.const_get(:Buildr)::Nailgun.ng.nail = nail
+          runtime.object.const_get(:Buildr)::Nailgun::Client.attach_runtime
+          if block_given?
+            Util.on_runtime(runtime) do 
+               
runtime.object.const_get(:Buildr)::Nailgun::Client.instance_eval(&block)
+            end
+          end
         end
+      end
 
-        def main(nail)
-          Thread.exclusive { Thread.current.priority = 100; run(nail) }
+      module AppMixin
+        
+        def load_tasks
+          trace "Not loading tasks again"
         end
+        
+        def load_buildfile
+          trace "Not loading buildfile again"
+        end
+        
+      end
+
+      def main(nail)
+        nail.extend NailMethods
+        info "Got connection from #{nail.pwd}"
 
-        private
-        def run(nail)
-          nail.assert_loopback_client
-          nail.out.println "Using #{nail.getNGServer}"
-          ctx = context_from_nail(nail)
+        Client.client(nail.jruby, nail) do
           
-          case ctx.action
-          when :start
-            nail.out.println "Cannot start nailgun when running as client"
-            return nail.exit(0)
-          when :stop
-            puts "Stopping #{nail.getNGServer}"
-            nail.out.println "Stopping #{nail.getNGServer}"
-            return nail.getNGServer.shutdown(true)
-          when :list
-            if @buildfiles.empty?
-              nail.out.println "No defined runtimes"
-            else
-              nail.out.println "Defined runtimes:"
-              @buildfiles.each_value { |f| nail.out.println "- #{f}" }
-            end
-            return nail.exit(0)
-          when :clear
-            @buildfiles.clear
-            nail.out.println "Cleared all runtimes"
-            return nail.exit(0)
-          when :tasks
-            nail.out.println ""
-            nail.out.println Rake.application.nailgun_tasks
-            return nail.exit(0)
-          when :help
-            nail.out.println ""
-            nail.out.println Rake.application.nailgun_help
-            return nail.exit(0)
+          parse_options
+          if options.exit
+            send(options.exit)
+            nail.exit(0)
           end
-          
-          opts = OpenStruct.new
-          
-          runtime = ctx.runtime
-          #Util.set_stdio(runtime, nail)
-          
runtime.object.const_get(:Buildr)::Nailgun::ContextRunner.parse_options(ctx, 
opts)
-          return nail.exit(0) if opts.exit
 
-          candidates = Buildr::Application::DEFAULT_BUILDFILES
-          candidates = [opts.buildfile] if opts.buildfile
-          
-          path = Util.find_buildfile(ctx.pwd, candidates, opts.nosearch) ||
-            File.expand_path(candidates.first, ctx.pwd)
+          if options.project && File.directory?(options.project)
+            Dir.chdir(options.project)
+          end
           
-          if ctx.action == :delete
-            nail.out.println "Deleting runtime for #{path}"
-            @buildfiles.delete(path)
-            return nail.exit(0)
+          bf = Util.find_buildfile(Dir.pwd, options.rakefiles, 
options.nosearch)
+          unless bf
+            nail.out.println "No buildfile found at #{Dir.pwd}"
+            nail.exit(0)
           end
-
-          puts "Getting buildr runtime for #{path}"
-          buildfile = @buildfiles[path] || Buildfile.new(path, *opts.requires)
           
-          save = buildfile.should_be_loaded? || ctx.action == :load
+          rt = nail.server.cached_runtimes[bf]
+          old_stamp = nail.server.cached_stamps[bf] || Rake::EARLY
+          new_stamp = rt ? 
rt.object.const_get(:Buildr).application.buildfile.timestamp : Rake::EARLY
           
-          runtime = buildfile.runtime
-
-          if save || ctx.action == :once
-            ctx.argv.unshift 'nailgun:load'
-            ctx.fresh = true
-            runtime = ctx.buildr
-            if save
-              buildfile.runtime = runtime
-              buildfile.loaded!
-              @buildfiles[buildfile.path] = buildfile
+          if rt.nil? || new_stamp > old_stamp
+            rt = nail.buildr
+            nail.server.cached_runtimes[bf] = rt
+            Client.client(rt, nail) do
+              bldr = rt.object.const_get(:Buildr)
+              bldr.application.run
+              nail.server.cache(rt, bldr.application.buildfile)
+            end
+          else
+            Client.client(rt, nail) do
+              buildr = rt.object.const_get(:Buildr)
+              app = buildr.application.extend AppMixin
+              app.lookup('buildr:initialize').instance_eval do 
+                @already_invoked = false
+                @actions = []
+              end
+              app.instance_variable_get(:@tasks).values.each do |task|
+                task.instance_variable_set(:@already_invoked, false)
+              end
+              app.instance_variable_set(:@original_dir, nail.pwd)
+              app.parse_options
+              app.collect_tasks
+              app.run
             end
           end
-
-          Util.redirect_stdio(runtime, nail) do
-            runtime.object.send :puts
-            runtime.object.const_get(:Buildr)::Nailgun::ContextRunner.run(ctx)
-          end
-        end
-        
-        def context_from_nail(nail)
-          ctx = OpenStruct.new
-          ctx.pwd = nail.getWorkingDirectory
-          ctx.env = nail.env
-          ctx.argv = [nail.command] + nail.args.map(&:to_s)
-          ctx.server = nail.getNGServer
-          def ctx.runtime; @runtime ||= server.buildr_factory.runtime; end
-          def ctx.buildr; @buildr ||= server.buildr_factory.obtain; end
-          actions = {
-            :load   => %w{ nailgun:load },
-            :delete => %w{ nailgun:delete },
-            :clear  => %w{ nailgun:clear },
-            :list   => %w{ nailgun:list },
-            :start  => %w{ nailgun:boot nailgun:start },
-            :stop   => %w{ nailgun:stop },
-            :once   => %w{ nailgun:once },
-            :tasks  => %w{ nailgun:tasks },
-            :help   => %w{ nailgun:help help:nailgun },
-          }
-          action = actions.find { |k,v| k if v.any? { |t| ctx.argv.delete(t) } 
}
-          ctx.action = action.first if action
-          ctx
+          
         end
-        
-      end # class BuildrNail
+      end
+      
+    end # class Client
+
+    module Server
+
+      attr_reader :runtime_factory
+      attr_reader :cached_runtimes
+      attr_reader :cached_stamps
+
+      def initialize(host = 'localhost', port = 2113, buildr_factory = nil)
+        super(java.net.InetAddress.get_by_name(host), port)
+        @cached_runtimes = {}
+        @cached_stamps = {}
+        cache(runtime, Buildr.application.buildfile)
+        @runtime_factory = buildr_factory
+        @host, @port = host, port
+      end
+
+      def cache(runtime, buildfile)
+        cached_runtimes[buildfile.to_s] = runtime
+        cached_stamps[buildfile.to_s] = buildfile.timestamp
+      end
+
+      def runtime
+        JRuby.runtime
+      end
 
-      class BuildrFactory
+      def start
+        self.allow_nails_by_class_name = false
         
-        attr_accessor :buildrs_size, :runtimes_size
+        Client::Main.nail = Client.new
+        self.default_nail_class = Client::Main
+        runtime_factory.start
         
-        def initialize(buildrs_size = 1, runtimes_size = nil)
-          runtimes_size ||= buildrs_size
-          @buildrs_size = buildrs_size < 1 ? 1 : buildrs_size
-          @runtimes_size = runtimes_size < 1 ? 1 : runtimes_size
+        @thread = java.lang.Thread.new(self)
+        @thread.setName(to_s)
+        @thread.start
+        
+        sleep 1 while getPort == 0
+        info "#{self} Started."
+      end
+      
+      def stop
+        runtime_factory.stop
+        @thread.kill
+      end
 
-          @buildrs = [].extend(MonitorMixin)
-          @buildrs_ready = @buildrs.new_cond
-          @buildrs_needed = @buildrs.new_cond
-                    
-          @buildrs_creators = [].extend(MonitorMixin)
+      def to_s
+        self.class.name+'('+[Buildr.application.version, @host, @port].join(', 
')+')'
+      end
+    end # module Server
+    
+    class RuntimeFactory
+      
+      attr_accessor :buildrs_size, :jrubys_size
+      
+      def initialize(buildrs_size = 1, jrubys_size = nil)
+        jrubys_size ||= buildrs_size
+        @buildrs_size = buildrs_size < 1 ? 1 : buildrs_size
+        @jrubys_size = jrubys_size < 1 ? 1 : jrubys_size
 
-          @runtimes = [].extend(MonitorMixin)
-          @runtimes_ready = @runtimes.new_cond
-          @runtimes_needed = @runtimes.new_cond
-          
-          @runtimes_creators = [].extend(MonitorMixin)
-        end
+        @buildrs = [].extend(MonitorMixin)
+        @buildrs_ready = @buildrs.new_cond
+        @buildrs_needed = @buildrs.new_cond
         
-        def obtain
-          get(:buildr)
-        end
+        @buildrs_creators = [].extend(MonitorMixin)
 
-        def runtime
-          get(:runtime)
-        end
+        @jrubys = [].extend(MonitorMixin)
+        @jrubys_ready = @jrubys.new_cond
+        @jrubys_needed = @jrubys.new_cond
+        
+        @jrubys_creators = [].extend(MonitorMixin)
+      end
+      
+      def new_buildr
+        get(:buildr)
+      end
 
-        def start
-          debug "Starting Buildr runtime factory"
-          @runtime_creator = Thread.new { loop { create :runtime } }
-          @runtime_creator.priority = -2
-          @buildr_creator = Thread.new { loop { create :buildr } }
-          @buildr_creator.priority = 1
-        end
+      def new_jruby(&block)
+        # get(:jruby)
+        create_jruby(0, &block)
+      end
 
-        def stop
-          @buildr_creator.kill if @buildr_creator
-          @runtime_creator.kill if @runtime_creator
-        end
+      def start
+        trace "Starting Buildr runtime factory"
+        # @jruby_creator = Thread.new { loop { create :jruby } }
+        # @jruby_creator.priority = -2
+        @buildr_creator = Thread.new { loop { create :buildr } }
+        @buildr_creator.priority = 1
+      end
 
-        private
-        def debug(*msg)
-          puts *msg if Rake.application.options.trace
-        end
+      def stop
+        @buildr_creator.kill if @buildr_creator
+        # @jruby_creator.kill if @jruby_creator
+      end
 
-        def get(thing)
-          collection = instance_variable_get("@#{thing}s")
-          needs = instance_variable_get("@#{thing}s_needed")
-          ready = instance_variable_get("@#{thing}s_ready")
-          result = nil
-          collection.synchronize do 
-            if collection.empty?
-              debug "no #{thing} available, ask to create more"
-              needs.broadcast
-              debug "should be creating #{thing}"
-              ready.wait_while { collection.empty? }
-            end
-            debug "Getting my #{thing}"
-            result = collection.shift
-            debug "would need more #{thing}s"
+      private
+      def get(thing)
+        collection = instance_variable_get("@#{thing}s")
+        needs = instance_variable_get("@#{thing}s_needed")
+        ready = instance_variable_get("@#{thing}s_ready")
+        result = nil
+        collection.synchronize do 
+          if collection.empty?
+            trace "no #{thing} available, ask to create more"
             needs.broadcast
-            debug "got my #{thing}: #{result.inspect}"
-            Thread.pass
+            trace "should be creating #{thing}"
+            ready.wait_while { collection.empty? }
           end
-          debug "returning #{result.inspect}"
-          result
+          trace "Getting my #{thing}"
+          result = collection.shift
+          trace "would need more #{thing}s"
+          needs.broadcast
+          trace "got my #{thing}: #{result.inspect}"
+          Thread.pass
         end
+        trace "returning #{result.inspect}"
+        result
+      end
 
-        def create(thing, *args, &prc)
+      def create(thing, *args, &block)
+        Util.exception_handling do
           creator = needed(thing)
           collection = instance_variable_get("@#{thing}s")
           ready = instance_variable_get("@#{thing}s_ready")
           needs = instance_variable_get("@#{thing}s_needed")
           unless creator
             collection.synchronize do
-              debug "awake those wanting a #{thing}"
+              trace "awake those wanting a #{thing}"
               ready.broadcast
               Thread.pass
-              debug "wait until more #{thing}s are needed"
+              trace "wait until more #{thing}s are needed"
               # needs.wait(1); return
               needs.wait_until { creator = needed(thing) }
             end
           end
-          debug "About to create #{thing} # #{creator}"
+          trace "About to create #{thing} # #{creator}"
           method = "create_#{thing}"
           creators = instance_variable_get("@#{thing}s_creators")
-          debug "registering creator for #{thing} #{creator}"
+          trace "registering creator for #{thing} #{creator}"
           creators.synchronize { creators << creator }
-          result = send(method, creator, *args, &prc)
-          debug "created #{thing}[#{creator}] => #{result.inspect}"
+          result = send(method, creator, *args, &block)
+          trace "created #{thing}[#{creator}] => #{result.inspect}"
           creators.synchronize do 
-            debug "unregistering creator for #{thing} #{creator}"
+            trace "unregistering creator for #{thing} #{creator}"
             creators.delete(creator)
             collection.synchronize do
-              debug "adding object on queue for #{thing} #{creator}"
+              trace "adding object on queue for #{thing} #{creator}"
               collection << result
             end
           end
-        rescue => e
-          puts "#{e.backtrace.shift}: #{e.message}"
-          e.backtrace.each { |i| puts "\tfrom #{i}" }
         end
-        
-        def needed(thing)
-          collection = instance_variable_get("@#{thing}s")
-          creators = instance_variable_get("@#{thing}s_creators")
-          size = instance_variable_get("@#{thing}s_size")
-          collection.synchronize do
-            count = collection.size
-            if count < size
-              count += creators.synchronize { creators.size }
-            end
-            count if count < size
-          end
+      end
+      
+      def needed(thing)
+        collection = instance_variable_get("@#{thing}s")
+        creators = instance_variable_get("@#{thing}s_creators")
+        size = instance_variable_get("@#{thing}s_size")
+        collection.synchronize do
+          count = collection.size
+          if count < size
+            count += creators.synchronize { creators.size }
+          end
+          count if count < size
         end
-
-        def create_runtime(creator)
-          debug "Creating runtime[#{creator}]"
+      end
+      
+      def create_jruby(creator, &block)
+        Util.exception_handling do
+          trace "Creating jruby[#{creator}]"
           Util.benchmark do |header|
-            runtime = org.jruby.Ruby.newInstance
-            runtime.global_variables.set('$nailgun_server', 
JRuby.reference($nailgun_server))
-            BUILDR_PATHS.each { |path| runtime.load_service.load_path.unshift 
path }
-            runtime.load_service.require 'buildr/nailgun'
-            header.replace ["Created runtime[#{creator}]", runtime]
-            runtime
+            cfg = org.jruby.RubyInstanceConfig.new
+            cfg.setOutput(java.io.PrintStream.new(java.lang.System.out))
+            cfg.setError(java.io.PrintStream.new(java.lang.System.err))
+            cfg.setInput(java.io.BufferedInputStream.new(java.lang.System.in))
+            yield cfg if block_given?
+            jruby = org.jruby.Ruby.newInstance(cfg)
+            jruby.load_service.load_path.concat BUILDR_PATHS
+            header.replace ["Created jruby[#{creator}]", jruby]
+            jruby
           end
         end
+      end
 
-        def create_buildr(creator)
-          debug "Obtaining runtime to load buildr[#{creator}] on it"
-          runtime = get(:runtime)
-          debug "Loading buildr[#{creator}] on #{runtime} ..."
-          Util.benchmark ["Loaded buildr[#{creator}] on #{runtime}"] do
-            load_service = runtime.load_service
+      def create_buildr(creator)
+        Util.exception_handling do 
+          trace "Obtaining jruby to load buildr[#{creator}] on it"
+          jruby = new_jruby
+          trace "Loading buildr[#{creator}] on #{jruby} ..."
+          Util.benchmark ["Loaded buildr[#{creator}] on #{jruby}"] do
+            load_service = jruby.load_service
             load_service.require 'rubygems'
             load_service.require 'buildr'
           end
-          runtime
+          jruby
         end
-        
-      end # BuildrFactory
-      
-      class BuildrServer < com.martiansoftware.nailgun.NGServer
-        
-        attr_reader :buildr_factory
-
-        def initialize(host = 'localhost', port = 2113, buildr_factory = nil)
-          super(java.net.InetAddress.get_by_name(host), port)
-          @buildr_factory = buildr_factory
-          @host, @port = host, port
-        end
-
-        def runtime
-          JRuby.runtime
-        end
-
-        def start_server
-          self.allow_nails_by_class_name = false
-
-          BuildrNail::Main.nail = BuildrNail.new
-          self.default_nail_class = BuildrNail::Main
-          buildr_factory.start
-          
-          @thread = java.lang.Thread.new(self)
-          @thread.setName(to_s)
-          @thread.start
-          
-          sleep 1 while getPort == 0
-          puts "#{self} Started."
-        end
-
-        def stop_server
-          buildr_factory.stop
-          @thread.kill
-        end
-
-        def to_s
-          "BuildrServer(" <<
-            [Rake.application.version, @host, @port].join(", ") <<
-            ")"
-        end
-      end # class BuildrServer
-
-    end # Nailgun boot
-    
-    namespace do
-      tmp = lambda { |*files| File.join(Dir.tmpdir, "nailgun", *files) }
-      dist_zip = Buildr.download(tmp[NAME + ".zip"] => URL)
-      dist_dir = Buildr.unzip(tmp[NAME] => dist_zip)
-      
-      if File.exist?(File.join(home, NAME + ".jar"))
-        ng_jar = file(File.join(home, NAME + ".jar"))
-      else
-        ng_jar = file(tmp[NAME, NAME, NAME+".jar"] => dist_dir)
       end
       
-      self.artifact = Buildr.artifact(ARTIFACT_SPEC).from(ng_jar)
-      
-      compiled_bin = tmp[NAME, NAME, "ng"+Config::CONFIG['EXEEXT']]
-      compiled_bin = file(compiled_bin => dist_dir.target) do |task|
-        unless task.to_s.pathmap('%x') == '.exe'
-          Dir.chdir(task.to_s.pathmap('%d')) do
-            puts "Compiling #{task.to_s}"
-            system('make', task.to_s.pathmap('%f')) or
-              fail "Nailgun binary compilation failed."
-          end
-        end
-      end
+    end # RuntimeFactory
 
-      installed_bin = file(File.join(home, 
-          compiled_bin.to_s.pathmap('%f')) => compiled_bin) do |task|
-        mkpath task.to_s.pathmap('%d'), :verbose => false
-        cp compiled_bin.to_s, task.to_s, :verbose => false
-      end
-
-      task :boot => artifact do |task|
-        if $nailgun_server
-          raise "Already nunning on Nailgun server: #{$nailgun_server}"
-        end
-        tasks = Rake.application.instance_eval { @top_level_tasks.dup }
-        tasks.delete_if do |t| 
-          t =~ /^(buildr:initialize|(ng|nailgun):.+)$/
-        end
-        unless tasks.empty?
-          raise "Don't specify more targets when starting Nailgun server"
-        end
-        boot
-      end
+    if Buildr.respond_to?(:application) && ng.nail.nil?
+      Buildr.application.in_namespace(:nailgun, &file_tasks)
+      Buildr.application.in_namespace(:nailgun, &server_tasks)
+    elsif ng.nail
       
-      task :start => [installed_bin, :boot] do
-        factory = BuildrFactory.new(buildr_queue_size, jruby_queue_size)
-        $nailgun_server = BuildrServer.new(server, port, factory)
-        puts "Starting #{$nailgun_server}"
-        $nailgun_server.start_server
-
-        is_win = Util.win_os?
-        bin_path = File.expand_path(installed_bin.to_s.pathmap("%d"))
-        bin_name = installed_bin.to_s.pathmap("%f")
-
-        puts <<-NOTICE
-
-        Buildr server has been started, you may need to update your PATH
-        variable in order to execute the #{bin_name} binary.
-
-          #{ is_win ?
-             "> set NAILGUN_HOME=#{bin_path}" :
-             "$ export NAILGUN_HOME=#{bin_path}"
-           }
-          #{ is_win ?
-             "> set PATH=%NAILGUN_HOME%;%PATH%" :
-             "$ export PATH=${NAILGUN_HOME}:${PATH}"
-           }
-           
-        Runtime for #{Rake.application.buildfile} has been cached, this 
-        means you can open a terminal inside 
-
-              #{Rake.application.buildfile.pathmap("%d")}
-
-        Invoke tasks by executing the #{bin_name} program, it takes the
-        same parameters you normally use for ``buildr''. 
-
-        To display Nailgun related help, execute the command:
-            ``#{bin_name} nailgun:help''
-
-        To get an overview of Nailgun tasks, execute the command:
-            ``#{bin_name} nailgun:tasks''
-
-        NOTICE
-      end
-
-      task :help do 
-        puts Rake.application.nailgun_help
-      end
+    end
 
-      task :tasks do 
-        puts Rake.application.nailgun_tasks
-      end
-      
-    end # namespace :nailgun
-    
   end # module Nailgun
-
+  
 end
 

Added: 
incubator/buildr/trunk/addon/buildr/org/apache/buildr/BuildrNail$Main.class
URL: 
http://svn.apache.org/viewvc/incubator/buildr/trunk/addon/buildr/org/apache/buildr/BuildrNail%24Main.class?rev=691494&view=auto
==============================================================================
Files 
incubator/buildr/trunk/addon/buildr/org/apache/buildr/BuildrNail$Main.class 
(added) and 
incubator/buildr/trunk/addon/buildr/org/apache/buildr/BuildrNail$Main.class Tue 
Sep  2 20:33:06 2008 differ

Added: incubator/buildr/trunk/addon/buildr/org/apache/buildr/BuildrNail.class
URL: 
http://svn.apache.org/viewvc/incubator/buildr/trunk/addon/buildr/org/apache/buildr/BuildrNail.class?rev=691494&view=auto
==============================================================================
Files incubator/buildr/trunk/addon/buildr/org/apache/buildr/BuildrNail.class 
(added) and 
incubator/buildr/trunk/addon/buildr/org/apache/buildr/BuildrNail.class Tue Sep  
2 20:33:06 2008 differ

Added: incubator/buildr/trunk/addon/buildr/org/apache/buildr/BuildrNail.java
URL: 
http://svn.apache.org/viewvc/incubator/buildr/trunk/addon/buildr/org/apache/buildr/BuildrNail.java?rev=691494&view=auto
==============================================================================
--- incubator/buildr/trunk/addon/buildr/org/apache/buildr/BuildrNail.java 
(added)
+++ incubator/buildr/trunk/addon/buildr/org/apache/buildr/BuildrNail.java Tue 
Sep  2 20:33:06 2008
@@ -0,0 +1,41 @@
+/* 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.
+ */
+
+
+package org.apache.buildr;
+
+import com.martiansoftware.nailgun.NGContext;
+
+public interface BuildrNail {
+  
+  public void main(NGContext ctx);
+
+  public static class Main {
+     private static BuildrNail nail;
+     public static void  setNail(BuildrNail _nail) { nail = _nail; }
+     public static void nailMain(NGContext ctx) {
+       nail.main(ctx);
+     }
+  }
+
+}
+
+/* 
+ * Local Variables:
+ * indent-tabs-mode: nil
+ * c-basic-offset: 2
+ * End:
+ */


Reply via email to