# Used to map a name to a set of dependencies | |
class JavaGen < BaseGenerator | |
def build_classpath_(dep_name) | |
t = Rake::Task[dep_name.to_sym] | |
if t.nil? | |
puts "No match for #{dep_name}" | |
return [] | |
end | |
classpath = [] | |
deps = t.deps || [] | |
deps += t.prerequisites | |
deps.each do |dep| | |
if Rake::Task.task_defined?(dep.to_sym) then | |
classpath += build_classpath_(dep) | |
else | |
classpath += FileList[dep] | |
end | |
end | |
FileList[dep_name].each do |match| | |
classpath.push match if match =~ /\.jar/ | |
end | |
classpath.push t.out.to_s unless t.out.nil? | |
classpath.sort.uniq | |
end | |
def out_path_(args) | |
"build/#{args[:name]}.jar".to_sym | |
end | |
def jar(args) | |
if !jar? | |
puts "Unable to locate 'jar' command" | |
exit -1 | |
end | |
if args[:srcs].nil? | |
puts "No srcs specified for #{args[:name]}" | |
end | |
out = out_path_(args) | |
create_deps_(out_path_(args), args) | |
t = Rake::Task[args[:name].to_sym] | |
t.deps = args[:deps] | |
t.out = out | |
file out do | |
# Build the classpath from the list of dependencies | |
classpath = build_classpath_(args[:name].to_sym) | |
temp = "#{out}_classes" | |
mkdir_p temp | |
puts "Building: #{args[:name]} as #{out}" | |
if args[:srcs] | |
# Remove anything that's not a JAR from the classpath | |
classpath = classpath.collect do |path| | |
path if path.to_s =~ /.jar$/ | |
end | |
# avoid hitting Windows' command line argument limit by putting | |
# the source list in a file | |
src_file = "src.txt" | |
File.open(src_file, "w") do |file| | |
file << FileList[args[:srcs]].join(" ") | |
end | |
begin | |
# Compile | |
cmd = "javac -cp #{classpath.join(classpath_separator?)} -g -source 5 -target 5 -d #{temp} @#{src_file}" | |
sh cmd | |
ensure | |
# Delete the temporary file | |
File.delete src_file | |
end | |
end | |
# TODO(simon): make copy_resource_ handle this for us | |
# Copy resources over | |
resources = args[:resources] || [] | |
resources.each do |res| | |
if (res.kind_of? Symbol) | |
res = Rake::Task[res].out | |
end | |
if (res.kind_of? Hash) | |
res.each do |from, to| | |
Dir["#{temp}/#{to}/**.svn"].each { |file| rm_rf file } | |
dir = to.gsub(/\/.*?$/, "") | |
mkdir_p "#{temp}/#{dir}" | |
begin | |
if File.directory? from | |
mkdir_p "#{temp}/#{to}" | |
end | |
cp_r find_file(from), "#{temp}/#{to}" | |
rescue | |
Dir["#{temp}/**/.svn"].each { |file| rm_rf file } | |
cp_r find_file(from), "#{temp}/#{to}" | |
end | |
end | |
else | |
target = res.gsub(/build\//, '') | |
copy_resource_(target, temp) | |
end | |
end | |
Dir["#{temp}/**/.svn"].each { |file| rm_rf file } | |
cmd = "cd #{temp} && jar cMf ../../#{out} *" | |
sh cmd | |
rm_rf temp | |
end | |
add_zip_task_(args) | |
end | |
def add_zip_task_(args) | |
# Now to add the implicit targets | |
out = out_path_(args) | |
zip_out = out.to_s.sub(".jar", ".zip") | |
task :"#{args[:name]}_zip" => FileList[zip_out] | |
file zip_out => out do | |
puts "Building: #{args[:name]}_zip as #{zip_out}" | |
classpath = build_classpath_(args[:name].to_sym) | |
temp = "#{zip_out}_temp" | |
mkdir_p temp | |
classpath.each do |f| | |
copy_resource_(f, temp) if f =~ /\.jar/ | |
end | |
sh "cd #{temp} && jar cMf ../../#{zip_out} *" | |
rm_rf temp | |
end | |
end | |
def run_test_(args) | |
classpath = build_classpath_(args[:name]) | |
main = args[:main] || "junit.textui.TestRunner" | |
test_string = 'java -Xmx128m -Xms128m ' | |
test_string += '-cp "' + classpath.join(classpath_separator?) + '" ' if classpath.length > 1 | |
if args[:system_properties] then | |
args[:system_properties].each do |prop| | |
test_string += "-D#{prop} " | |
end | |
end | |
if ENV['REMOTE_JAVA_DEBUG_PORT'] then | |
test_string += "-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=#{ENV['REMOTE_JAVA_DEBUG_PORT']} " | |
end | |
test_string += main | |
test_string += ' ' + args[:args] if args[:args] | |
if args[:tests].length == 0 | |
result = sh test_string | |
else | |
args[:tests].each do |test| | |
puts "Running: #{test}\n" | |
test_string += " #{test} " | |
result = sh test_string | |
end | |
end | |
result | |
end | |
def test(args) | |
jar(args) | |
out = out_path_(args) | |
file "#{args[:name]}_never_there" => [ "#{out}" ] do | |
if (args[:run].nil? || args[:run]) | |
tests = `jar tvf #{out}` | |
tests = tests.split /\n/ | |
tests.map! do |clazz| | |
clazz =~ /.*\s+(.*TestSuite\.class)/ ? $1.gsub("/", ".").gsub(/\.class\s*$/, "") : nil | |
end | |
tests.compact! | |
if (!args[:test_suite].nil?) | |
tests.reject! {|clazz| clazz !~ /#{args[:test_suite]}/} | |
end | |
args[:tests] = tests | |
run_test_ args | |
else | |
puts "Skipping tests for #{args[:name]}" | |
end | |
end | |
task "#{args[:name]}" => "#{args[:name]}_never_there" | |
end | |
def uberjar(args) | |
out = out_path_(args) | |
create_deps_(out_path_(args), args) | |
file out do | |
puts "Building uber-jar: #{args[:name]} as #{out}" | |
# Take each dependency, extract and then rezip | |
temp = "#{out}_temp" | |
mkdir_p temp | |
all = [] | |
args[:deps].each do |d| | |
all += build_classpath_(d) | |
end | |
all = all.sort.uniq.collect | |
all.each do |dep| | |
next unless dep.to_s =~ /\.jar$/ | |
next if (dep.to_s =~ /\lib\// or dep.to_s =~ /^third_party\//) and args[:no_libs] == true | |
sh "cd #{temp} && jar xf ../../#{dep}" | |
end | |
excludes = args[:exclude] || [] | |
excludes.each do |to_exclude| | |
rm_rf FileList["#{temp}/#{to_exclude}"] | |
end | |
Dir["#{temp}/**/.svn"].each { |file| rm_rf file } | |
if args[:main] | |
# Read any MANIFEST.MF file into memory, ignoring the main class line | |
manifest = [] | |
manifest.push "Main-Class: #{args[:main]}\n" | |
manifest_file = "#{temp}/META-INF/MANIFEST.MF" | |
if (!File.exists? manifest_file) | |
mkdir_p "#{temp}/META-INF" | |
touch(manifest_file) | |
end | |
File.open(manifest_file, "r") do |f| | |
while (line = f.gets) | |
manifest.push line unless line =~ /^Main-Class:/ | |
end | |
end | |
File.open(manifest_file, "w") do |f| f.write(manifest.join("")) end | |
end | |
sh "cd #{temp} && jar cMf ../../#{out} *" | |
rm_rf temp | |
end | |
add_zip_task_(args) | |
t = Rake::Task[args[:name].to_sym] | |
t.deps = args[:deps] | |
t.out = out | |
end | |
def build_uberlist_(task_names, standalone) | |
all = [] | |
tasks = task_names || [] | |
tasks.each do |dep| | |
if Rake::Task.task_defined? dep.to_sym then | |
t = Rake::Task[dep.to_sym] | |
all.push t.out if t.out.to_s =~ /\.jar$/ | |
all += build_uberlist_(t.deps, standalone) | |
all += build_uberlist_(t.prerequisites, standalone) | |
elsif standalone | |
all += FileList[dep] | |
end | |
end | |
all.uniq | |
end | |
def war(args) | |
out = "build/#{args[:name]}.war" | |
deps = args[:deps] || [] | |
deps += args[:resources] || [] | |
deps.each do |dep| | |
if (dep.is_a? Symbol) | |
task args[:name] => [dep] | |
elsif (dep.is_a? String) | |
task args[:name] => FileList[dep] | |
end | |
end | |
file out do | |
temp = "#{out}_temp" | |
mkdir_p "#{temp}/WEB-INF/lib" | |
# Copy the resources. They're easy | |
copy_resource_(args[:resources], temp) unless args[:resources].nil? | |
# Now the JARs we depend on | |
jars = build_classpath_(args[:name].to_sym).collect do |jar| | |
jar.to_s =~ /\.jar/ ? jar : nil | |
end | |
copy_resource_(jars, "#{temp}/WEB-INF/lib") | |
Dir["#{temp}/**/.svn"].each { |file| rm_rf file } | |
sh "cd #{temp} && jar cMf ../../#{out} *" | |
rm_rf temp | |
end | |
task args[:name] => out | |
t = Rake::Task[args[:name]] | |
t.out = out | |
t.deps = args[:deps] | |
end | |
end | |
def walk_war_deps_(dep, dest) | |
puts "Dep: #{dep} is a #{dep.class}" | |
if (dep.is_a? Symbol) | |
t = Rake::Task[dep] | |
copy_resource_(t.out, dest) if dep.to_s =~ /\.jar/ | |
walk_war_deps_(t.deps, dest) | |
walk_war_deps_(t.prerequisites, dest) | |
elsif dep.is_a? String | |
copy_resource_(dep, dest) if dep.to_s =~ /\.jar/ | |
elsif dep.is_a? Array | |
dep.each do |child| | |
walk_war_deps_(child, dest) | |
end | |
end | |
end | |
def java_jar(args) | |
JavaGen.new().jar(args) | |
end | |
def java_test(args) | |
JavaGen.new().test(args) | |
end | |
def java_uberjar(args) | |
JavaGen.new().uberjar(args) | |
end | |
def java_war(args) | |
JavaGen.new().war(args) | |
end |