module Buildr module Java module Packaging MANIFEST_HEADER = "Manifest-Version: 1.0\nCreated-By: Buildr\n" class JarTask < ZipTask attr_accessor :manifest attr_accessor :meta_inf def initialize(*args) super @manifest = true end def []=(key, value) if key.to_sym == :manifest self.manifest = value elsif key.to_sym == :meta_inf self.meta_inf = value else super key, value end value end protected def create(zip) zip.mkdir "META-INF" meta_inf.each { |file| zip.add "META-INF/#{File.basename(file)}", file } if meta_inf unless manifest == false zip.file.open("META-INF/MANIFEST.MF", "w") do |output| output.write MANIFEST_HEADER if manifest case manifest when Hash output.write manifest.map { |pair| pair.join(": ") }.sort.join("\n") when Array manifest.each do |section| output.write "\n" output.write section.map { |pair| pair.join(": ") }.sort.join("\n") end when Proc, Method output.write manifest.call when String output.write File.read(manifest) end end output.write "\n" end end super zip end end class WarTask < JarTask def []=(key, value) case key.to_sym when :libs self.include artifacts(value), :path=>"WEB-INF/lib" when :classes self.include value, :path=>"WEB-INF/classes" else super key, value end value end end end end # Create a JAR from all the pre-requisites. # # For example: # jar "lib-1.0.jar"=>["target/classes", "MANIFEST,MF"] def jar(file) Packaging::JarTask.define_task(file) end class Project # Group used for packaging. Inherited from parent project. inherited_attr :group # Version used for packaging. Inherited from parent project. inherited_attr :version # Manifest used for packaging. Inherited from parent project. inherited_attr :manifest do |project| manifest = { "Build-By"=>ENV['USER'], "Build-Jdk"=>Java.version } manifest["Implementation-Version"] = project.version if project.version manifest end # Files to always include in the package META-INF directory. inherited_attr :meta_inf do |project| meta_inf = ["DISCLAIMER", "LICENSE", "NOTICE"].map { |f| path_to(f) if File.exist?(path_to(f)) }.compact end # The project ID is the project name, and for a sub-project the # parent project ID followed by the project name, separated with a # hyphen. For example, "foo" and "foo-bar". def id() name.gsub(":", "-") end inherited_attr :webapp_src_dir do File.join(src_dir, "main", "webapp") end def package(*args) if Hash === args.last options = args.pop.dup else options = {} end options[:type] = args.shift.to_s if Symbol === args.first fail "No packaging type specified" unless options[:type] options[:group] ||= self.group options[:version] ||= self.version options[:id] ||= self.id if String === args.first file = args.shift else file = options.delete(:file) || path_to(:target_dir, Artifact.hash_to_file_name(options)) end fail "One argument too many; expecting at most type, file name, and hash of options" unless args.empty? packager = method("package_as_#{options[:type]}") rescue fail("Do not know how to create a package of type #{options[:type]}") package = packager.call(file, options) or fail("Do not know how to create a package of type #{options[:type]}") task "package"=>package package.enhance [ task("build")] task "install"=>(file(repositories.locate(package)=>package) { |task| mkpath File.dirname(task.name), :verbose=>false cp package.name, task.name }) task "install"=>package.pom task "uninstall" do |task| verbose(Rake.application.options.trace) do [ package, package.pom ].map { |artifact| repositories.locate(artifact) }. each { |file| rm file if File.exist?(file) } end end task("deploy") { deploy(package, package.pom) } packages << package Artifact.register package, package.pom package end def packages() @packages ||= [] end protected def package_as_jar(file, options) unless Rake::Task.task_defined?(file) returning(Java::Packaging::JarTask.define_task(file)) do |task| package_extend task, options task.enhance [path_to(:java_target_dir)] task.include path_to(:java_target_dir, "*") task.manifest = manifest.merge("Implementation-Title"=>self.comment) task.meta_inf = meta_inf end end returning(Java::Packaging::JarTask.define_task(file)) do |task| task.include options[:include] if options[:include] task.manifest = options[:manifest] if options[:manifest] end end def package_as_war(file, options) unless Rake::Task.task_defined?(file) returning(Java::Packaging::WarTask.define_task(file)) do |task| package_extend task, options task.include path_to(:webapp_src_dir, "*") task.with :classes=>path_to(:java_target_dir, "**") task.manifest = manifest.merge("Implementation-Title"=>self.comment) task.meta_inf = meta_inf end end # Add anything we find in webapp sources directory. returning(Java::Packaging::WarTask.define_task(file)) do |task| task.include options[:include] if options[:include] # Add libraries in WEB-INF lib, and classes in WEB-INF classes task.with :libs=>options[:libs].collect if options[:libs] task.with :classes=>options[:classes] if options[:classes] task.manifest = options[:manifest] if options[:manifest] end end def package_as_zip(file, options) unless Rake::Task.task_defined?(file) returning(ZipTask.define_task(file)) do |task| package_extend task, options task.include path_to(:java_target_dir, "*") end end returning(ZipTask.define_task(file)) do |task| task.include options[:include] if options[:include] end end def package_extend(task, spec) task.extend ActsAsArtifact task.apply_spec spec task.pom.enhance do |task| mkpath File.dirname(task.name), :verbose=>false File.open(task.name, "w") do |file| xml = Builder::XmlMarkup.new(:target=>file, :indent=>2) xml.instruct! xml.project do xml.modelVersion "4.0.0." xml.groupId spec[:group] xml.artifactId spec[:id] xml.version spec[:version] xml.classifier spec[:classifier] if spec[:classifier] end end end end end end