lib/java/java.rb in buildr-0.18.0 vs lib/java/java.rb in buildr-0.19.0
- old
+ new
@@ -1,152 +1,310 @@
-require 'stringio'
+require "rjb"
+require "core/project"
module Buildr
+
+ # Base module for all things Java.
module Java
- JAVA_OPTIONS = [ :verbose, :noop, :cp, :classpath, :name, :java_args ]
+ # Options accepted by #java and other methods here.
+ JAVA_OPTIONS = [ :verbose, :classpath, :name, :java_args ]
+ # Classpath dependencies available when running JUnit.
JUNIT_REQUIRES = [ "junit:junit:jar:3.8.1", "jmock:jmock:jar:1.1.0" ]
- def self.java(*args)
- options = Hash === args.last ? args.pop : {}
- options[:verbose] ||= Rake.application.options.trace || false
- fu_check_options options, *JAVA_OPTIONS
+ # Returned by Java#rjb, you can use this object to set the RJB classpath, specify blocks to be invoked
+ # after loading RJB, and load RJB itself.
+ #
+ # RJB can be loaded exactly once, and once loaded, you cannot change its classpath. Of course you can
+ # call libraries that manage their own classpath, but the lazy way is to just tell RJB of all the
+ # classpath dependencies you need in advance, before loading it.
+ #
+ # For that reason, you should not load RJB until the moment you need it. You can call #load or call
+ # Java#rjb with a block. For the same reason, you may need to specify code to execute when loading
+ # (see #onload).
+ class RjbWrapper
- name = options[:name] || "java #{args.first}"
- cmd_args = []
- classpath = classpath_from(options)
- cmd_args << "-cp" << classpath.join(File::PATH_SEPARATOR) unless classpath.empty?
- cmd_args += options[:java_args].flatten if options[:java_args]
- cmd_args += args.flatten.compact
- cmd_args << { :verbose=>options[:verbose] }
- unless options[:noop]
- puts "Running #{name}" if verbose
- sh(path_to_bin("java"), *cmd_args) { |ok, res| fail "Failed to execute #{name}, see errors above" unless ok }
+ include Singleton
+
+ def initialize() #:nodoc:
+ @classpath = []
+ @onload = []
+ onload do
+ Rjb.load(artifacts(classpath).each { |task| task.invoke if task.respond_to?(:invoke) }.
+ map(&:to_s).join(File::PATH_SEPARATOR))
+ end
end
- end
- def self.apt(*args)
- options = Hash === args.last ? args.pop : {}
- options[:verbose] ||= Rake.application.options.trace || false
- fu_check_options options, :verbose, :noop, :compile, :source, :output, :cp, :classpath
+ # The classpath used when loading RJB.
+ attr_accessor :classpath
- files = args.collect { |arg| File.directory?(arg) ? FileList[File.join(arg, "**", "*.java")] : arg }.flatten
- args = [ options[:verbose] ? "-verbose" : "-nowarn" ]
- if options[:compile]
- args << "-d" << options[:output]
- else
- args << "-nocompile" << "-s" << options[:output]
+ # :call-seq:
+ # onload { ... }
+ #
+ # Adds a block to call when loading RJB and returns self.
+ #
+ # You can only load RJB once, and you may need to do some tasks after the initial load.
+ # For example, the Ant module requires Antwrap which can only be loaded after RJB.
+ def onload(&block)
+ @onload << block
+ self
end
- args << "-source" << options[:source] if options[:source]
- classpath = classpath_from(options)
- args << "-cp" << classpath.join(File::PATH_SEPARATOR) unless classpath.empty?
- args += files
- args << { :verbose=>options[:verbose] }
- unless options[:noop]
- puts "Running apt" if verbose
- sh(path_to_bin("apt"), *args) { |ok, res| fail "Failed to execute apt, see errors above" unless ok }
+
+ # :call-seq:
+ # load()
+ #
+ # Loads RJB. You can also call Java#ejb with a block to get the same effect.
+ def load()
+ @onload.each(&:call)
+ @onload.clear
end
- end
- # Gets the version of the java VM
- def self.version()
- @version ||= `java -version 2>&1`.scan(/java version "(.*)"/)[0][0]
- end
-
- def self.tools()
- unless @tools
- tools = File.join(ENV['JAVA_HOME'], "lib", "tools.jar")
- @tools = File.exist?(tools) ? tools : []
+ def method_missing(sym, *args, &block) #:nodoc:
+ Rjb.send sym, *args, &block
end
- @tools
end
- class AptTask < Rake::FileTask
+ class << self
- def initialize(*args)
- super
- enhance do |task|
- Java.apt *task.prerequisites + [options.merge(:output=>task.name)]
- end
+ # :call-seq:
+ # version() => string
+ #
+ # Returns the version number of the JVM.
+ #
+ # For example:
+ # puts Java.version
+ # => 1.5.0_10
+ def version()
+ @version ||= `#{path_to_bin("java")} -version 2>&1`.scan(/java version "(.*)"/)[0][0]
end
- def options()
- @options ||= {}
+ # :call-seq:
+ # tools_jar() => path
+ #
+ # Returns a path to tools.jar.
+ def tools_jar()
+ unless @tools
+ home = ENV["JAVA_HOME"] || File.dirname(File.dirname(`which java`.split.first))
+ tools = File.join(home, "lib/tools.jar")
+ @tools = tools if File.exist?(tools)
+ end
+ @tools
end
- def using(options)
- self.options.merge!(options)
- self
+ # :call-seq:
+ # java(class, *args, options?)
+ #
+ # Runs Java with the specified arguments.
+ #
+ # The last argument may be a Hash with additional options:
+ # * :classpath -- One or more file names, tasks or artifact specifications.
+ # These are all expanded into artifacts, and all tasks are invoked.
+ # * :java_args -- Any additional arguments to pass (e.g. -hotspot, -xms)
+ # * :name -- Shows this name, otherwise shows the first argument (the class name).
+ # * :verbose -- If true, prints the command and all its argument.
+ def java(*args)
+ options = Hash === args.last ? args.pop : {}
+ options[:verbose] ||= Rake.application.options.trace || false
+ fu_check_options options, *JAVA_OPTIONS
+
+ name = options[:name] || "java #{args.first}"
+ cmd_args = []
+ classpath = classpath_from(options)
+ cmd_args << "-cp" << classpath.join(File::PATH_SEPARATOR) unless classpath.empty?
+ cmd_args += options[:java_args].flatten if options[:java_args]
+ cmd_args += args.flatten.compact
+ cmd_args << { :verbose=>options[:verbose] }
+ unless Rake.application.options.dryrun
+ puts "Running #{name}" if verbose
+ sh(path_to_bin("java"), *cmd_args) { |ok, res| fail "Failed to execute #{name}, see errors above" unless ok }
+ end
end
- end
+ # :call-seq:
+ # apt(*files, options)
+ #
+ # Runs Apt with the specified arguments.
+ #
+ # The last argument may be a Hash with additional options:
+ # * :compile -- If true, compile source files to class files.
+ # * :source -- Specifies source compatibility with a given JVM release.
+ # * :output -- Directory where to place the generated source files, or the
+ # generated class files when compiling.
+ # * :classpath -- One or more file names, tasks or artifact specifications.
+ # These are all expanded into artifacts, and all tasks are invoked.
+ # * :verbose -- If true, prints the command and all its argument and also runs
+ # Apt in verbose mode (the default is -nowarn).
+ def apt(*args)
+ options = Hash === args.last ? args.pop : {}
+ options[:verbose] ||= Rake.application.options.trace || false
+ fu_check_options options, :verbose, :compile, :source, :output, :classpath
- def self.apt_task(args)
- output = args.keys.first
- files = args.values.first.collect { |f| File.directory?(f) ? FileList[f + "/**/*.java"] : f }.flatten
- AptTask.define_task(output=>files)
- end
+ files = args.flatten.map(&:to_s).
+ collect { |arg| File.directory?(arg) ? FileList["#{arg}/**/*.java"] : arg }.flatten
+ args = [ options[:verbose] ? "-verbose" : "-nowarn" ]
+ if options[:compile]
+ args << "-d" << options[:output].to_s
+ else
+ args << "-nocompile" << "-s" << options[:output].to_s
+ end
+ args << "-source" << options[:source] if options[:source]
+ classpath = classpath_from(options)
+ args << "-cp" << classpath.join(File::PATH_SEPARATOR) unless classpath.empty?
+ args += files
+ args << { :verbose=>options[:verbose] }
+ unless Rake.application.options.dryrun
+ puts "Running apt" if verbose
+ sh(path_to_bin("apt"), *args) { |ok, res| fail "Failed to execute apt, see errors above" unless ok }
+ end
+ end
- def self.javac(*args)
- options = Hash === args.last ? args.pop : {}
- options[:verbose] ||= Rake.application.options.trace || false
- fu_check_options options, :verbose, :noop, :cp, :classpath, :sourcepath, :output, :javac_args, :name
+ # :call-seq:
+ # javac(*files, options)
+ #
+ # Runs Javac with the specified arguments.
+ #
+ # The last argument may be a Hash with additional options:
+ # * :output -- Target directory for all compiled class files.
+ # * :classpath -- One or more file names, tasks or artifact specifications.
+ # These are all expanded into artifacts, and all tasks are invoked.
+ # * :sourcepath -- Additional source paths to use.
+ # * :javac_args -- Any additional arguments to pass (e.g. -extdirs, -encoding)
+ # * :name -- Shows this name, otherwise shows the working directory.
+ # * :verbose -- If true, prints the command and all its argument.
+ def javac(*args)
+ options = Hash === args.last ? args.pop : {}
+ options[:verbose] ||= Rake.application.options.trace || false
+ fu_check_options options, :verbose, :classpath, :sourcepath, :output, :javac_args, :name
- files = args.flatten.each { |f| f.invoke if f.respond_to?(:invoke) }.map(&:to_s).
- collect { |arg| File.directory?(arg) ? FileList[File.join(arg, "**", "*.java")] : arg }.flatten
- name = options[:name] || Dir.pwd
+ files = args.flatten.each { |f| f.invoke if f.respond_to?(:invoke) }.map(&:to_s).
+ collect { |arg| File.directory?(arg) ? FileList["#{arg}/**/*.java"] : arg }.flatten
+ name = options[:name] || Dir.pwd
- cmd_args = []
- classpath = classpath_from(options)
- #classpath += options[:output] if options[:output]
- cmd_args << "-cp" << classpath.join(File::PATH_SEPARATOR) unless classpath.empty?
- cmd_args << "-sourcepath" << options[:sourcepath].join(File::PATH_SEPARATOR) if options[:sourcepath]
- cmd_args << "-d" << options[:output] if options[:output]
- cmd_args += options[:javac_args].flatten if options[:javac_args]
- cmd_args += files
- cmd_args << { :verbose=>options[:verbose] }
- unless options[:noop] || files.empty?
- puts "Compiling #{files.size} source files in #{name}" if verbose
- sh(path_to_bin("javac"), *cmd_args) { |ok, res| fail "Failed to compile, see errors above" unless ok }
+ cmd_args = []
+ classpath = classpath_from(options)
+ #classpath += options[:output] if options[:output]
+ cmd_args << "-cp" << classpath.join(File::PATH_SEPARATOR) unless classpath.empty?
+ cmd_args << "-sourcepath" << options[:sourcepath].join(File::PATH_SEPARATOR) if options[:sourcepath]
+ cmd_args << "-d" << options[:output].to_s if options[:output]
+ cmd_args += options[:javac_args].flatten if options[:javac_args]
+ cmd_args += files
+ cmd_args << { :verbose=>options[:verbose] }
+ unless Rake.application.options.dryrun
+ puts "Compiling #{files.size} source files in #{name}" if verbose
+ sh(path_to_bin("javac"), *cmd_args) { |ok, res| fail "Failed to compile, see errors above" unless ok }
+ end
end
- end
- def self.junit(*args)
- options = Hash === args.last ? args.pop : {}
- options[:verbose] ||= Rake.application.options.trace || false
- fu_check_options options, :verbose, :noop, :cp, :classpath, :sourcepath, :output, :javac_args, :name
+ # :call-seq:
+ # junit(*classes, options) => [ passed, failed ]
+ #
+ # Runs JUnit test cases from the specified classes. Returns an array with two lists,
+ # one containing the names of all classes that passes, the other containing the names
+ # of all classes that failed.
+ #
+ # The last argument may be a Hash with additional options:
+ # * :classpath -- One or more file names, tasks or artifact specifications.
+ # These are all expanded into artifacts, and all tasks are invoked.
+ # * :verbose -- If true, prints the command and all its argument.
+ def junit(*args)
+ options = Hash === args.last ? args.pop : {}
+ options[:verbose] ||= Rake.application.options.trace || false
+ fu_check_options options, :verbose, :classpath
- classpath = classpath_from(options) + junit_artifacts
- tests = args.flatten
- failed = tests.inject([]) do |failed, test|
- begin
- java "junit.textui.TestRunner", test, :classpath=>classpath, :name=>"tests in #{test}"
- failed
- rescue
- failed << test
+ classpath = classpath_from(options) + junit_artifacts
+ tests = args.flatten
+ failed = tests.inject([]) do |failed, test|
+ begin
+ java "junit.textui.TestRunner", test, :classpath=>classpath, :name=>"tests in #{test}", :verbose=>options[:verbose]
+ failed
+ rescue
+ failed << test
+ end
end
+ [ tests - failed, failed ]
end
- [ tests - failed, failed ]
- end
+ # :call-seq:
+ # rjb() => RjbWrapper
+ # rjb() { ... }
+ #
+ # This method can be used in two ways. Without a block, returns the RjbWrapper
+ # object which you can use to configure the RJB classpath or call other RJB methods.
+ # With a block, loads RJB and yields to the block, returning its result.
+ #
+ # For example:
+ # Java.rjb.classpath += REQUIRES
+ # Java.rjb.onload { require "antwrap" }
+ # . . .
+ #
+ # def execute(name, options)
+ # options = options.merge(:name=>name, :base_dir=>Dir.pwd, :declarative=>true)
+ # Java.rjb { AntProject.new(options) }
+ # end
+ def rjb()
+ if block_given?
+ RjbWrapper.instance.load
+ yield
+ else
+ RjbWrapper.instance
+ end
+ end
+
+ # :call-seq:
+ # path_to_bin(cmd?) => path
+ #
+ # Returns the path to the specified Java command (with no argument to java itself).
+ # Uses JAVA_HOME if set, otherwise assumes the command is accessible from the path.
+ def path_to_bin(name = "java")
+ ENV["JAVA_HOME"] ? File.join(ENV["JAVA_HOME"], "bin", name) : name
+ end
+
protected
- def self.path_to_bin(name = "java")
- ENV["JAVA_HOME"] ? File.join(ENV["JAVA_HOME"], "bin", name) : name
+ # :call-seq:
+ # classpath_from(options) => files
+ #
+ # Extracts the classpath from the options, expands it by calling artifacts, invokes
+ # each of the artifacts and returns an array of paths.
+ def classpath_from(options)
+ classpath = (options[:classpath] || []).collect
+ artifacts(classpath).each { |t| t.invoke if t.respond_to?(:invoke) }.map(&:to_s)
+ end
+
+ # :call-seq:
+ # junit_artifacts() => files
+ #
+ # Returns the JUnit artifacts as paths, after downloading and installing them (if necessary).
+ def junit_artifacts()
+ @junit_artifacts ||= artifacts(JUNIT_REQUIRES).each { |task| task.invoke }.map(&:to_s)
+ end
+
end
- def self.classpath_from(options)
- classpath = (options[:classpath] || []).collect | (options[:cp] || []).collect
- artifacts(classpath).each { |t| t.invoke if t.respond_to?(:invoke) }.map(&:to_s)
+ # See Java#java.
+ def java(*args)
+ Java.java(*args)
end
- def self.junit_artifacts()
- @junit_artifacts ||= artifacts(JUNIT_REQUIRES).each { |task| task.invoke }
+ # :call-seq:
+ # apt(*sources) => task
+ #
+ # Returns a task that will use Java#apt to generate source files in target/generated/apt,
+ # from all the source directories passed as arguments. Uses the compile.sources list if
+ # on arguments supplied.
+ #
+ # For example:
+ #
+ def apt(*sources)
+ sources = compile.sources if sources.empty?
+ file(path_to("target/generated/apt")=>sources) do |task|
+ Java.apt(sources.map(&:to_s) - [task.name], :output=>task.name,
+ :classpath=>compile.classpath, :source=>compile.options.source)
+ end
end
end
- def java(*args)
- Java.java(*args)
+ class Project
+ include Java
end
-
end