class Buildr::Packaging::Java::EarTask

Extend the JarTask to create an EAR file.

The following component types are supported by the EARTask:

The EarTask uses the “Mechanism 2: Bundled Optional Classes” as described on [2]. All specified libraries are added to the EAR archive and the Class-Path manifiest entry is modified for each EAR component. Special care is taken with WebApplications, as they can contain libraries on their WEB-INF/lib directory, libraries already included in a war file are not referenced by the Class-Path entry of the war in order to avoid class collisions

EarTask supports all the same options as JarTask, in additon to these two options:

EAR components are added by means of the #add, #<<, #push methods Component type is determined from the artifact's type.

package(:ear) << project('coolWebService').package(:war)

The << method is just an alias for push, with the later you can add multiple components at the same time. For example..

package(:ear).push 'org.springframework:spring:jar:2.6',
                             projects('reflectUtils', 'springUtils'),
                             project('coolerWebService').package(:war)

The add method takes a single component with an optional hash. You can use it to override some component attributes.

You can override the component type for a particular artifact. The following example shows how you can tell the EarTask to treat a JAR file as an EJB:

# will add an ejb entry for the-cool-ejb-2.5.jar in application.xml
package(:ear).add 'org.coolguys:the-cool-ejb:jar:2.5', :type=>:ejb
# A better syntax for this is:
package(:ear).add :ejb=>'org.coolguys:the-cool-ejb:jar:2.5'

By default, every JAR package is assumed to be a library component, so you need to specify the type when including an EJB (:ejb) or Application Client JAR (:jar).

For WebApplications (:war)s, you can customize the context-root that appears in application.xml. The following example also specifies a different directory inside the EAR where to store the webapp.

package(:ear).add project(:remoteService).package(:war),
                           :path=>'web-services', :context_root=>'/Some/URL/Path'
1

java.sun.com/j2ee/sdk_1.2.1/techdocs/guides/ejb/html/Overview5.html#10106

2

java.sun.com/j2ee/verified/packaging.html

Constants

SUPPORTED_TYPES

Attributes

description[RW]

The description entry for application.xml

dirs[RW]

Map from component type to path inside the EAR.

display_name[RW]

The display-name entry for application.xml

security_roles[RW]

Security roles entry for application.xml

Public Class Methods

new(*args) click to toggle source
Calls superclass method
# File lib/buildr/java/packaging.rb, line 395
def initialize(*args)
  super
  @dirs = Hash.new { |h, k| k.to_s }
  @libs, @components, @security_roles = [], [], []
  prepare do
    @components.each do |component|
      path(component[:path]).include(component[:clone] || component[:artifact])
    end
    path('META-INF').include(descriptor)
  end
end

Public Instance Methods

<<(*args)
Alias for: push
add(*args) click to toggle source

Add an artifact to this EAR.

# File lib/buildr/java/packaging.rb, line 408
def add(*args)
  options = Hash === args.last ? args.pop.clone : {}
  args.flatten!
  args.map! do |pkg|
    case pkg
    when Project
      pkg.packages.select { |pp| JarTask === pp && SUPPORTED_TYPES.include?(pp.type) }
    when Rake::FileTask
      pkg # add the explicitly provided file
    when Hash
      Buildr.artifact(pkg)
    when String
      begin
        Buildr.artifact(pkg)
      rescue # not an artifact spec, it must me a filename
        file(pkg)
      end
    else
      raise "Invalid EAR component #{pkg.class}: #{pkg}"
    end
  end
  args.flatten!
  args.compact!
  if args.empty?
    raise ":type must not be specified for type=>component argument style" if options.key?(:type)
    raise ":as must not be specified for type=>component argument style" if options.key?(:as)
    comps = {}
    options.delete_if { |k, v| comps[k] = v if SUPPORTED_TYPES.include?(k) }
    raise "You must specify at least one valid component to add" if comps.empty?
    comps.each { |k, v| add(v, {:as => k}.merge(options)) }
  else
    args.each do |artifact|
      type = options[:as] || options[:type]
      unless type
        type = artifact.respond_to?(:type) ? artifact.type : artifact.to_s.pathmap('%x').to_sym
        type = :lib if type == :jar
      end
      raise "Unknown EAR component type: #{type}. Perhaps you may explicity tell what component type to use." unless
        SUPPORTED_TYPES.include?(type)
      component = options.merge(:artifact => artifact, :type => type,
        :id=>artifact.respond_to?(:to_spec) ? artifact.id : artifact.to_s.pathmap('%n'),
        :path=>options[:path] || dirs[type].to_s)
      component[:clone] = component_clone(component) unless :lib == type
      # update_classpath(component) unless :lib == type || Artifact === artifact
      @components << component
    end
  end
  self
end
Also aliased as: push
push(*args)
Also aliased as: <<
Alias for: add

Protected Instance Methods

associate(project) click to toggle source
# File lib/buildr/java/packaging.rb, line 480
def associate(project)
  @project = project
end
component_clone(component) click to toggle source
# File lib/buildr/java/packaging.rb, line 463
def component_clone(component)
  file(path_to(component[:path], component[:artifact].to_s.pathmap('%f')) => component[:artifact]) do |task|
    mkpath task.to_s.pathmap('%d')
    cp component[:artifact].to_s, task.to_s
    Manifest.update_manifest(task) do |manifest|
      class_path = manifest.main['Class-Path'].to_s.split
      included_libs = class_path.map { |fn| fn.pathmap('%f') }
      Zip::File.foreach(task.to_s) do |entry|
        included_libs << entry.name.pathmap('%f') if entry.file? && entry.name =~ /^WEB-INF\/lib\/[^\/]+$/
      end
      # Include all other libraries in the classpath.
      class_path += libs_classpath(component).reject { |path| included_libs.include?(File.basename(path)) }
      manifest.main['Class-Path'] = class_path.join(' ')
    end
  end
end
update_classpath(component) click to toggle source
# File lib/buildr/java/packaging.rb, line 489
def update_classpath(component)
  package = file(component[:artifact].to_s)
  package.manifest = (package.manifest || {}).dup # avoid mofifying parent projects manifest
  package.prepare do
    header = case package.manifest
      when Hash then package.manifest
      when Array then package.manifest.first
    end
    if header
      # Determine which libraries are already included.
      class_path = header['Class-Path'].to_s.split
      included_libs = class_path.map { |fn| File.basename(fn) }
      included_libs += package.path('WEB-INF/lib').sources.map { |fn| File.basename(fn) }
      # Include all other libraries in the classpath.
      class_path += libs_classpath(component).reject { |path| included_libs.include?(File.basename(path)) }
      header['Class-Path'] = class_path.join(' ')
    end
  end
end