Buildr C0 Coverage Information - RCov

lib/buildr/java/packaging.rb

Name Total Lines Lines of Code Total Coverage Code Coverage
lib/buildr/java/packaging.rb 734 429
15.80%
15.62%

Key

Code reported as executed by Ruby looks like this...and this: this line is also marked as covered.Lines considered as run by rcov, but not reported by Ruby, look like this,and this: these lines were inferred by rcov (using simple heuristics).Finally, here's a line marked as not executed.

Coverage Details

1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements.  See the NOTICE file distributed with this
3 # work for additional information regarding copyright ownership.  The ASF
4 # licenses this file to you under the Apache License, Version 2.0 (the
5 # "License"); you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 #    http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
13 # License for the specific language governing permissions and limitations under
14 # the License.
15 
16 
17 require 'buildr/packaging'
18 
19 
20 module Buildr
21   module Packaging #:nodoc:
22 
23     # Adds packaging for Java projects: JAR, WAR, AAR, EAR, Javadoc.
24     module Java
25 
26       class Manifest
27 
28         STANDARD_HEADER = { 'Manifest-Version'=>'1.0', 'Created-By'=>'Buildr' }
29         LINE_SEPARATOR = /\r\n|\n|\r[^\n]/ #:nodoc:
30         SECTION_SEPARATOR = /(#{LINE_SEPARATOR}){2}/ #:nodoc:
31 
32         class << self
33 
34           # :call-seq:
35           #   parse(str) => manifest
36           #
37           # Parse a string in MANIFEST.MF format and return a new Manifest.
38           def parse(str)
39             sections = str.split(SECTION_SEPARATOR).reject { |s| s.strip.empty? }
40             new sections.map { |section|
41               lines = section.split(LINE_SEPARATOR).inject([]) { |merged, line|
42                 if line[/^ /] == ' '
43                   merged.last << line[1..-1]
44                 else
45                   merged << line
46                 end
47                 merged
48               }
49               lines.map { |line| line.scan(/(.*?):\s*(.*)/).first }.
50                 inject({}) { |map, (key, value)| map.merge(key=>value) }
51             }
52           end
53 
54           # :call-seq:
55           #   from_zip(file) => manifest
56           #
57           # Parse the MANIFEST.MF entry of a ZIP (or JAR) file and return a new Manifest.
58           def from_zip(file)
59             Zip::ZipInputStream::open(file.to_s) do |zip|
60               while (entry = zip.get_next_entry)
61                 if entry.name == 'META-INF/MANIFEST.MF'
62                   return Manifest.parse zip.read
63                 end
64               end
65             end
66             Manifest.new
67           end
68 
69           # :call-seq:
70           #   update_manifest(file) { |manifest| ... }
71           #
72           # Updates the MANIFEST.MF entry of a ZIP (or JAR) file.  Reads the MANIFEST.MF,
73           # yields to the block with the Manifest object, and writes the modified object
74           # back to the file.
75           def update_manifest(file)
76             manifest = from_zip(file)
77             result = yield manifest
78             Zip::ZipFile.open(file.to_s) do |zip|
79               zip.get_output_stream('META-INF/MANIFEST.MF') do |out|
80                 out.write manifest.to_s
81                 out.write "\n"
82               end
83             end
84             result
85           end
86 
87         end
88 
89         # Returns a new Manifest object based on the argument:
90         # * nil         -- Empty Manifest.
91         # * Hash        -- Manifest with main section using the hash name/value pairs.
92         # * Array       -- Manifest with one section from each entry (must be hashes).
93         # * String      -- Parse (see Manifest#parse).
94         # * Proc/Method -- New Manifest from result of calling proc/method.
95         def initialize(arg = nil)
96           case arg
97           when nil, Hash then @sections = [arg || {}]
98           when Array then @sections = arg
99           when String then @sections = Manifest.parse(arg).sections
100           when Proc, Method then @sections = Manifest.new(arg.call).sections
101           else
102             fail 'Invalid manifest, expecting Hash, Array, file name/task or proc/method.'
103           end
104           # Add Manifest-Version and Created-By, if not specified.
105           STANDARD_HEADER.each do |name, value|
106             sections.first[name] ||= value
107           end
108         end
109 
110         # The sections of this manifest.
111         attr_reader :sections
112 
113         # The main (first) section of this manifest.
114         def main
115           sections.first
116         end
117 
118         include Enumerable
119 
120         # Iterate over each section and yield to block.
121         def each(&block)
122           @sections.each(&block)
123         end
124 
125         # Convert to MANIFEST.MF format.
126         def to_s
127           @sections.map { |section|
128             keys = section.keys
129             keys.unshift('Name') if keys.delete('Name')
130             lines = keys.map { |key| manifest_wrap_at_72("#{key}: #{section[key]}") }
131             lines + ['']
132           }.flatten.join("\n")
133         end
134 
135       private
136 
137         def manifest_wrap_at_72(line)
138           return [line] if line.size < 72
139           [ line[0..70] ] + manifest_wrap_at_72(' ' + line[71..-1])
140         end
141 
142       end
143 
144 
145       # Adds support for MANIFEST.MF and other META-INF files.
146       module WithManifest #:nodoc:
147 
148         class << self
149           def included(base)
150             base.class_eval do
151               alias :initialize_without_manifest :initialize
152               alias :initialize :initialize_with_manifest
153             end
154           end
155 
156         end
157 
158         # Specifies how to create the manifest file.
159         attr_accessor :manifest
160 
161         # Specifies files to include in the META-INF directory.
162         attr_accessor :meta_inf
163 
164         def initialize_with_manifest(*args) #:nodoc:
165           initialize_without_manifest *args
166           @manifest = false
167           @meta_inf = []
168           @dependencies = FileList[]
169 
170           prepare do
171             @prerequisites << manifest if String === manifest || Rake::Task === manifest
172             [meta_inf].flatten.map { |file| file.to_s }.uniq.each { |file| path('META-INF').include file }
173           end
174 
175           enhance do
176             if manifest
177               # Tempfiles gets deleted on garbage collection, so we're going to hold on to it
178               # through instance variable not closure variable.
179               @manifest_tmp = Tempfile.new('MANIFEST.MF')
180               File.chmod 0644, @manifest_tmp.path
181               self.manifest = File.read(manifest.to_s) if String === manifest || Rake::Task === manifest
182               self.manifest = Manifest.new(manifest) unless Manifest === manifest
183               #@manifest_tmp.write Manifest::STANDARD_HEADER
184               @manifest_tmp.write manifest.to_s
185               @manifest_tmp.write "\n"
186               @manifest_tmp.close
187               path('META-INF').include @manifest_tmp.path, :as=>'MANIFEST.MF'
188             end
189           end
190         end
191 
192       end
193 
194       class ::Buildr::ZipTask
195         include WithManifest
196       end
197 
198 
199       # Extends the ZipTask to create a JAR file.
200       #
201       # This task supports two additional attributes: manifest and meta-inf.
202       #
203       # The manifest attribute specifies how to create the MANIFEST.MF file.
204       # * A hash of manifest properties (name/value pairs).
205       # * An array of hashes, one for each section of the manifest.
206       # * A string providing the name of an existing manifest file.
207       # * A file task can be used the same way.
208       # * Proc or method called to return the contents of the manifest file.
209       # * False to not generate a manifest file.
210       #
211       # The meta-inf attribute lists one or more files that should be copied into
212       # the META-INF directory.
213       #
214       # For example:
215       #   package(:jar).with(:manifest=>'src/MANIFEST.MF')
216       #   package(:jar).meta_inf << file('README')
217       class JarTask < ZipTask
218 
219         def initialize(*args) #:nodoc:
220           super
221         end
222 
223         # :call-seq:
224         #   with(options) => self
225         #
226         # Additional
227         # Pass options to the task. Returns self. ZipTask itself does not support any options,
228         # but other tasks (e.g. JarTask, WarTask) do.
229         #
230         # For example:
231         #   package(:jar).with(:manifest=>'MANIFEST_MF')
232         def with(*args)
233           super args.pop if Hash === args.last
234           fail "package.with() should not contain nil values" if args.include? nil
235           include :from=>args if args.size > 0
236           self
237         end
238 
239       end
240 
241 
242       # Extends the JarTask to create a WAR file.
243       #
244       # Supports all the same options as JarTask, in additon to these two options:
245       # * :libs -- An array of files, tasks, artifact specifications, etc that will be added
246       #   to the WEB-INF/lib directory.
247       # * :classes -- A directory containing class files for inclusion in the WEB-INF/classes
248       #   directory.
249       #
250       # For example:
251       #   package(:war).with(:libs=>'log4j:log4j:jar:1.1')
252       class WarTask < JarTask
253 
254         # Directories with class files to include under WEB-INF/classes.
255         attr_accessor :classes
256 
257         # Artifacts to include under WEB-INF/libs.
258         attr_accessor :libs
259 
260         def initialize(*args) #:nodoc:
261           super
262           @classes = []
263           @libs = []
264           enhance do |war|
265             @libs.each {|lib| lib.invoke if lib.respond_to?(:invoke) }
266             @classes.to_a.flatten.each { |classes| include classes, :as => 'WEB-INF/classes' }
267             path('WEB-INF/lib').include Buildr.artifacts(@libs) unless @libs.nil? || @libs.empty?
268           end
269         end
270 
271         def libs=(value) #:nodoc:
272           @libs = Buildr.artifacts(value)
273         end
274 
275         def classes=(value) #:nodoc:
276           @classes = [value].flatten.map { |dir| file(dir.to_s) }
277         end
278 
279       end
280 
281 
282       # Extends the JarTask to create an AAR file (Axis2 service archive).
283       #
284       # Supports all the same options as JarTask, with the addition of :wsdls, :services_xml and :libs.
285       #
286       # * :wsdls -- WSDL files to include (under META-INF).  By default packaging will include all WSDL
287       #   files found under src/main/axis2.
288       # * :services_xml -- Location of services.xml file (included under META-INF).  By default packaging
289       #   takes this from src/main/axis2/services.xml.  Use a different path if you genereate the services.xml
290       #   file as part of the build.
291       # * :libs -- Array of files, tasks, artifact specifications, etc that will be added to the /lib directory.
292       #
293       # For example:
294       #   package(:aar).with(:libs=>'log4j:log4j:jar:1.1')
295       #
296       #   filter.from('src/main/axis2').into('target').include('services.xml', '*.wsdl').using('http_port'=>'8080')
297       #   package(:aar).wsdls.clear
298       #   package(:aar).with(:services_xml=>_('target/services.xml'), :wsdls=>_('target/*.wsdl'))
299       class AarTask < JarTask
300         # Artifacts to include under /lib.
301         attr_accessor :libs
302         # WSDLs to include under META-INF (defaults to all WSDLs under src/main/axis2).
303         attr_accessor :wsdls
304         # Location of services.xml file (defaults to src/main/axis2/services.xml).
305         attr_accessor :services_xml
306 
307         def initialize(*args) #:nodoc:
308           super
309           @libs = []
310           @wsdls = []
311           prepare do
312             path('META-INF').include @wsdls
313             path('META-INF').include @services_xml, :as=>'services.xml' if @services_xml
314             path('lib').include Buildr.artifacts(@libs) unless @libs.nil? || @libs.empty?
315           end
316         end
317 
318         def libs=(value) #:nodoc:
319           @libs = Buildr.artifacts(value)
320         end
321 
322         def wsdls=(value) #:nodoc:
323           @wsdls |= Array(value)
324         end
325       end
326 
327 
328       # Extend the JarTask to create an EAR file.
329       #
330       # The following component types are supported by the EARTask:
331       #
332       # * :war -- A J2EE Web Application
333       # * :ejb -- An Enterprise Java Bean
334       # * :jar -- A J2EE Application Client.[1]
335       # * :lib -- An ear scoped shared library[2] (for things like logging,
336       #           spring, etc) common to the ear components
337       #
338       # The EarTask uses the "Mechanism 2: Bundled Optional Classes" as described on [2].
339       # All specified libraries are added to the EAR archive and the Class-Path manifiest entry is
340       # modified for each EAR component. Special care is taken with WebApplications, as they can
341       # contain libraries on their WEB-INF/lib directory, libraries already included in a war file
342       # are not referenced by the Class-Path entry of the war in order to avoid class collisions
343       #
344       # EarTask supports all the same options as JarTask, in additon to these two options:
345       #
346       # * :display_name -- The displayname to for this ear on application.xml
347       #
348       # * :map -- A Hash used to map component type to paths within the EAR.
349       #     By default each component type is mapped to a directory with the same name,
350       #     for example, EJBs are stored in the /ejb path.  To customize:
351       #                       package(:ear).map[:war] = 'web-applications'
352       #                       package(:ear).map[:lib] = nil # store shared libraries on root of archive
353       #
354       # EAR components are added by means of the EarTask#add, EarTask#<<, EarTask#push methods
355       # Component type is determined from the artifact's type.
356       #
357       #      package(:ear) << project('coolWebService').package(:war)
358       #
359       # The << method is just an alias for push, with the later you can add multiple components
360       # at the same time. For example..
361       #
362       #      package(:ear).push 'org.springframework:spring:jar:2.6',
363       #                                   projects('reflectUtils', 'springUtils'),
364       #                                   project('coolerWebService').package(:war)
365       #
366       # The add method takes a single component with an optional hash. You can use it to override
367       # some component attributes.
368       #
369       # You can override the component type for a particular artifact. The following example
370       # shows how you can tell the EarTask to treat a JAR file as an EJB:
371       #
372       #      # will add an ejb entry for the-cool-ejb-2.5.jar in application.xml
373       #      package(:ear).add 'org.coolguys:the-cool-ejb:jar:2.5', :type=>:ejb
374       #      # A better syntax for this is:
375       #      package(:ear).add :ejb=>'org.coolguys:the-cool-ejb:jar:2.5'
376       #
377       # By default, every JAR package is assumed to be a library component, so you need to specify
378       # the type when including an EJB (:ejb) or Application Client JAR (:jar).
379       #
380       # For WebApplications (:war)s, you can customize the context-root that appears in application.xml.
381       # The following example also specifies a different directory inside the EAR where to store the webapp.
382       #
383       #      package(:ear).add project(:remoteService).package(:war),
384       #                                 :path=>'web-services', :context_root=>'/Some/URL/Path'
385       #
386       # [1] http://java.sun.com/j2ee/sdk_1.2.1/techdocs/guides/ejb/html/Overview5.html#10106
387       # [2] http://java.sun.com/j2ee/verified/packaging.html
388       class EarTask < JarTask
389 
390         SUPPORTED_TYPES = [:war, :ejb, :jar, :rar, :lib]
391 
392         # The display-name entry for application.xml
393         attr_accessor :display_name
394         # The description entry for application.xml
395         attr_accessor :description
396         # Map from component type to path inside the EAR.
397         attr_accessor :dirs
398         # Security roles entry for application.xml
399         attr_accessor :security_roles
400 
401         def initialize(*args)
402           super
403           @dirs = Hash.new { |h, k| k.to_s }
404           @libs, @components, @security_roles = [], [], []
405           prepare do
406             @components.each do |component|
407               path(component[:path]).include(component[:clone] || component[:artifact])
408             end
409             path('META-INF').include(descriptor)
410           end
411         end
412 
413         # Add an artifact to this EAR.
414         def add(*args)
415           options = Hash === args.last ? args.pop.clone : {}
416           args.flatten!
417           args.map! do |pkg|
418             case pkg
419             when Project
420               pkg.packages.select { |pp| JarTask === pp && SUPPORTED_TYPES.include?(pp.type) }
421             when Rake::FileTask
422               pkg # add the explicitly provided file
423             when Hash
424               Buildr.artifact(pkg)
425             when String
426               begin
427                 Buildr.artifact(pkg)
428               rescue # not an artifact spec, it must me a filename
429                 file(pkg)
430               end
431             else
432               raise "Invalid EAR component #{pkg.class}: #{pkg}"
433             end
434           end
435           args.flatten!
436           args.compact!
437           if args.empty?
438             raise ":type must not be specified for type=>component argument style" if options.key?(:type)
439             raise ":as must not be specified for type=>component argument style" if options.key?(:as)
440             comps = {}
441             options.delete_if { |k, v| comps[k] = v if SUPPORTED_TYPES.include?(k) }
442             raise "You must specify at least one valid component to add" if comps.empty?
443             comps.each { |k, v| add(v, {:as => k}.merge(options)) }
444           else
445             args.each do |artifact|
446               type = options[:as] || options[:type]
447               unless type
448                 type = artifact.respond_to?(:type) ? artifact.type : artifact.to_s.pathmap('%x').to_sym
449                 type = :lib if type == :jar
450               end
451               raise "Unknown EAR component type: #{type}. Perhaps you may explicity tell what component type to use." unless
452                 SUPPORTED_TYPES.include?(type)
453               component = options.merge(:artifact => artifact, :type => type,
454                 :id=>artifact.respond_to?(:to_spec) ? artifact.id : artifact.to_s.pathmap('%n'),
455                 :path=>options[:path] || dirs[type].to_s)
456               component[:clone] = component_clone(component) unless :lib == type
457               # update_classpath(component) unless :lib == type || Artifact === artifact
458               @components << component
459             end
460           end
461           self
462         end
463 
464         alias_method :push, :add
465         alias_method :<<, :push
466 
467       protected
468 
469         def component_clone(component)
470           file(path_to(component[:path], component[:artifact].to_s.pathmap('%f')) => component[:artifact]) do |task|
471             mkpath task.to_s.pathmap('%d')
472             cp component[:artifact].to_s, task.to_s
473             Manifest.update_manifest(task) do |manifest|
474               class_path = manifest.main['Class-Path'].to_s.split
475               included_libs = class_path.map { |fn| fn.pathmap('%f') }
476               Zip::ZipFile.foreach(task.to_s) do |entry|
477                 included_libs << entry.name.pathmap('%f') if entry.file? && entry.name =~ /^WEB-INF\/lib\/[^\/]+$/
478               end
479               # Include all other libraries in the classpath.
480               class_path += libs_classpath(component).reject { |path| included_libs.include?(File.basename(path)) }
481               manifest.main['Class-Path'] = class_path.join(' ')
482             end
483           end
484         end
485 
486         def associate(project)
487           @project = project
488         end
489 
490         def path_to(*args) #:nodoc:
491           @project.path_to(:target, :ear, name.pathmap('%n'), *args)
492         end
493         alias_method :_, :path_to
494 
495         def update_classpath(component)
496           package = file(component[:artifact].to_s)
497           package.manifest = (package.manifest || {}).dup # avoid mofifying parent projects manifest
498           package.prepare do
499             header = case package.manifest
500               when Hash then package.manifest
501               when Array then package.manifest.first
502             end
503             if header
504               # Determine which libraries are already included.
505               class_path = header['Class-Path'].to_s.split
506               included_libs = class_path.map { |fn| File.basename(fn) }
507               included_libs += package.path('WEB-INF/lib').sources.map { |fn| File.basename(fn) }
508               # Include all other libraries in the classpath.
509               class_path += libs_classpath(component).reject { |path| included_libs.include?(File.basename(path)) }
510               header['Class-Path'] = class_path.join(' ')
511             end
512           end
513         end
514 
515       private
516 
517         # Classpath of all packages included as libraries (type :lib).
518         def libs_classpath(component)
519           from = component[:path]
520           @classpath = @components.select { |comp| comp[:type] == :lib }.
521             map do |lib|
522             basename = lib[:artifact].to_s.pathmap('%f')
523             full_path = lib[:path].empty? ? basename : File.join(lib[:path], basename)
524             Util.relative_path(full_path, from)
525           end
526         end
527 
528         def descriptor_xml
529           buffer = ""
530           xml = Builder::XmlMarkup.new(:target=>buffer, :indent => 2)
531           xml.declare! :DOCTYPE, :application, :PUBLIC,
532           "-//Sun Microsystems, Inc.//DTD J2EE Application 1.2//EN",
533           "http://java.sun.com/j2ee/dtds/application_1_2.dtd"
534           xml.application do
535             xml.tag! 'display-name', display_name
536             desc = self.description || @project.comment
537             xml.tag! 'description', desc if desc
538             @components.each do |comp|
539               basename = comp[:artifact].to_s.pathmap('%f')
540               uri = comp[:path].empty? ? basename : File.join(comp[:path], basename)
541               case comp[:type]
542               when :war
543                 xml.module :id=>comp[:id] do
544                   xml.web do
545                     xml.tag! 'web-uri', uri
546                     xml.tag! 'context-root', File.join('', (comp[:context_root] || comp[:id])) unless comp[:context_root] == false
547                   end
548                 end
549               when :ejb
550                 xml.module :id=>comp[:id] do
551                   xml.ejb uri
552                 end
553               when :jar
554                 xml.jar uri
555               end
556             end
557             @security_roles.each do |role|
558               xml.tag! 'security-role', :id=>role[:id] do
559                 xml.description role[:description]
560                 xml.tag! 'role-name', role[:name]
561               end
562             end
563           end
564           buffer
565         end
566 
567         # return a FileTask to build the ear application.xml file
568         def descriptor
569           return @descriptor if @descriptor
570           descriptor_path = path_to('META-INF/application.xml')
571           @descriptor = file(descriptor_path) do |task|
572             trace "Creating EAR Descriptor: #{task.to_s}"
573             mkpath File.dirname(task.name)
574             File.open(task.name, 'w') { |file| file.print task.xml }
575           end
576           class << @descriptor
577             attr_accessor :ear
578 
579             def xml
580               @xml ||= ear.send :descriptor_xml
581             end
582 
583             def needed?
584               super || xml != File.read(self.to_s) rescue true
585             end
586           end
587           @descriptor.ear = self
588           @descriptor
589         end
590 
591       end
592 
593 
594       include Extension
595 
596       before_define(:package => :build) do |project|
597         if project.parent && project.parent.manifest
598           project.manifest = project.parent.manifest.dup
599         else
600           project.manifest = {
601             'Build-By'=>ENV['USER'], 'Build-Jdk'=>ENV_JAVA['java.version'],
602             'Implementation-Title'=>project.comment || project.name,
603             'Implementation-Version'=>project.version }
604         end
605         if project.parent && project.parent.meta_inf
606           project.meta_inf = project.parent.meta_inf.dup
607         else
608           project.meta_inf = [project.file('LICENSE')].select { |file| File.exist?(file.to_s) }
609         end
610       end
611 
612 
613       # Manifest used for packaging. Inherited from parent project. The default value is a hash that includes
614       # the Build-By, Build-Jdk, Implementation-Title and Implementation-Version values.
615       # The later are taken from the project's comment (or name) and version number.
616       attr_accessor :manifest
617 
618       # Files to always include in the package META-INF directory. The default value include
619       # the LICENSE file if one exists in the project's base directory.
620       attr_accessor :meta_inf
621 
622       # :call-seq:
623       #   package_with_sources(options?)
624       #
625       # Call this when you want the project (and all its sub-projects) to create a source distribution.
626       # You can use the source distribution in an IDE when debugging.
627       #
628       # A source distribution is a jar package with the classifier 'sources', which includes all the
629       # sources used by the compile task.
630       #
631       # Packages use the project's manifest and meta_inf properties, which you can override by passing
632       # different values (e.g. false to exclude the manifest) in the options.
633       #
634       # To create source distributions only for specific projects, use the :only and :except options,
635       # for example:
636       #   package_with_sources :only=>['foo:bar', 'foo:baz']
637       #
638       # (Same as calling package :sources on each project/sub-project that has source directories.)
639       def package_with_sources(options = nil)
640         options ||= {}
641         enhance do
642           selected = options[:only] ? projects(options[:only]) :
643             options[:except] ? ([self] + projects - projects(options[:except])) :
644             [self] + projects
645           selected.reject { |project| project.compile.sources.empty? && project.resources.target.nil? }.
646             each { |project| project.package(:sources) }
647         end
648       end
649 
650       # :call-seq:
651       #   package_with_javadoc(options?)
652       #
653       # Call this when you want the project (and all its sub-projects) to create a JavaDoc distribution.
654       # You can use the JavaDoc distribution in an IDE when coding against the API.
655       #
656       # A JavaDoc distribution is a ZIP package with the classifier 'javadoc', which includes all the
657       # sources used by the compile task.
658       #
659       # Packages use the project's manifest and meta_inf properties, which you can override by passing
660       # different values (e.g. false to exclude the manifest) in the options.
661       #
662       # To create JavaDoc distributions only for specific projects, use the :only and :except options,
663       # for example:
664       #   package_with_javadoc :only=>['foo:bar', 'foo:baz']
665       #
666       # (Same as calling package :javadoc on each project/sub-project that has source directories.)
667       def package_with_javadoc(options = nil)
668         options ||= {}
669         enhance do
670           selected = options[:only] ? projects(options[:only]) :
671             options[:except] ? ([self] + projects - projects(options[:except])) :
672             [self] + projects
673           selected.reject { |project| project.compile.sources.empty? }.
674             each { |project| project.package(:javadoc) }
675         end
676       end
677 
678     protected
679 
680       def package_as_jar(file_name) #:nodoc:
681         Java::JarTask.define_task(file_name).tap do |jar|
682           jar.with :manifest=>manifest, :meta_inf=>meta_inf
683           jar.with [compile.target, resources.target].compact
684         end
685       end
686 
687       def package_as_war(file_name) #:nodoc:
688         Java::WarTask.define_task(file_name).tap do |war|
689           war.with :manifest=>manifest, :meta_inf=>meta_inf
690           # Add libraries in WEB-INF lib, and classes in WEB-INF classes
691           war.with :classes=>[compile.target, resources.target].compact
692           war.with :libs=>compile.dependencies
693           # Add included files, or the webapp directory.
694           webapp = path_to(:source, :main, :webapp)
695           war.with webapp if File.exist?(webapp)
696         end
697       end
698 
699       def package_as_aar(file_name) #:nodoc:
700         Java::AarTask.define_task(file_name).tap do |aar|
701           aar.with :manifest=>manifest, :meta_inf=>meta_inf
702           aar.with :wsdls=>path_to(:source, :main, :axis2, '*.wsdl')
703           aar.with :services_xml=>path_to(:source, :main, :axis2, 'services.xml')
704           aar.with [compile.target, resources.target].compact
705           aar.with :libs=>compile.dependencies
706         end
707       end
708 
709       def package_as_ear(file_name) #:nodoc:
710         Java::EarTask.define_task(file_name).tap do |ear|
711           ear.send :associate, self
712           ear.with :display_name=>id, :manifest=>manifest, :meta_inf=>meta_inf
713         end
714       end
715 
716       def package_as_javadoc_spec(spec) #:nodoc:
717         spec.merge(:type=>:jar, :classifier=>'javadoc')
718       end
719 
720       def package_as_javadoc(file_name) #:nodoc:
721         ZipTask.define_task(file_name).tap do |zip|
722           zip.include :from=>doc.target
723         end
724       end
725 
726     end
727 
728   end
729 end
730 
731 
732 class Buildr::Project
733   include Buildr::Packaging::Java
734 end

Generated on 2011-07-06 23:35:37 -0700 with rcov 0.9.8