buildr 1.2.10 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. data/CHANGELOG +566 -268
  2. data/DISCLAIMER +7 -1
  3. data/KEYS +151 -0
  4. data/NOTICE +23 -8
  5. data/README +122 -22
  6. data/Rakefile +49 -229
  7. data/{lib → addon}/buildr/antlr.rb +23 -10
  8. data/addon/buildr/cobertura.rb +232 -0
  9. data/{lib → addon}/buildr/hibernate.rb +20 -4
  10. data/{lib → addon}/buildr/javacc.rb +27 -12
  11. data/addon/buildr/jdepend.rb +60 -0
  12. data/{lib → addon}/buildr/jetty.rb +34 -18
  13. data/addon/buildr/nailgun.rb +892 -0
  14. data/{lib → addon}/buildr/openjpa.rb +23 -6
  15. data/addon/buildr/org/apache/buildr/JettyWrapper$1.class +0 -0
  16. data/addon/buildr/org/apache/buildr/JettyWrapper$BuildrHandler.class +0 -0
  17. data/addon/buildr/org/apache/buildr/JettyWrapper.class +0 -0
  18. data/{lib/buildr/jetty → addon/buildr/org/apache/buildr}/JettyWrapper.java +19 -0
  19. data/{lib → addon}/buildr/xmlbeans.rb +39 -14
  20. data/bin/buildr +21 -7
  21. data/buildr.gemspec +50 -0
  22. data/doc/css/default.css +225 -0
  23. data/doc/css/print.css +95 -0
  24. data/doc/css/syntax.css +43 -0
  25. data/doc/images/apache-incubator-logo.png +0 -0
  26. data/doc/images/buildr-hires.png +0 -0
  27. data/doc/images/buildr.png +0 -0
  28. data/doc/images/note.png +0 -0
  29. data/doc/images/tip.png +0 -0
  30. data/doc/images/zbuildr.tif +0 -0
  31. data/doc/pages/artifacts.textile +317 -0
  32. data/doc/pages/building.textile +501 -0
  33. data/doc/pages/contributing.textile +178 -0
  34. data/doc/pages/download.textile +25 -0
  35. data/doc/pages/extending.textile +229 -0
  36. data/doc/pages/getting_started.textile +337 -0
  37. data/doc/pages/index.textile +63 -0
  38. data/doc/pages/mailing_lists.textile +17 -0
  39. data/doc/pages/more_stuff.textile +367 -0
  40. data/doc/pages/packaging.textile +592 -0
  41. data/doc/pages/projects.textile +449 -0
  42. data/doc/pages/recipes.textile +127 -0
  43. data/doc/pages/settings_profiles.textile +339 -0
  44. data/doc/pages/testing.textile +475 -0
  45. data/doc/pages/troubleshooting.textile +121 -0
  46. data/doc/pages/whats_new.textile +389 -0
  47. data/doc/print.haml +52 -0
  48. data/doc/print.toc.yaml +28 -0
  49. data/doc/scripts/buildr-git.rb +411 -0
  50. data/doc/scripts/install-jruby.sh +44 -0
  51. data/doc/scripts/install-linux.sh +64 -0
  52. data/doc/scripts/install-osx.sh +52 -0
  53. data/doc/site.haml +55 -0
  54. data/doc/site.toc.yaml +44 -0
  55. data/lib/buildr.rb +28 -45
  56. data/lib/buildr/core.rb +27 -0
  57. data/lib/buildr/core/application.rb +373 -0
  58. data/lib/buildr/core/application_cli.rb +134 -0
  59. data/lib/{core → buildr/core}/build.rb +91 -77
  60. data/lib/{core → buildr/core}/checks.rb +116 -95
  61. data/lib/buildr/core/common.rb +155 -0
  62. data/lib/buildr/core/compile.rb +594 -0
  63. data/lib/buildr/core/environment.rb +120 -0
  64. data/lib/buildr/core/filter.rb +258 -0
  65. data/lib/{core → buildr/core}/generate.rb +22 -5
  66. data/lib/buildr/core/help.rb +118 -0
  67. data/lib/buildr/core/progressbar.rb +156 -0
  68. data/lib/{core → buildr/core}/project.rb +468 -213
  69. data/lib/buildr/core/test.rb +690 -0
  70. data/lib/{core → buildr/core}/transports.rb +107 -127
  71. data/lib/buildr/core/util.rb +235 -0
  72. data/lib/buildr/ide.rb +19 -0
  73. data/lib/{java → buildr/ide}/eclipse.rb +86 -60
  74. data/lib/{java → buildr/ide}/idea.ipr.template +16 -0
  75. data/lib/buildr/ide/idea.rb +194 -0
  76. data/lib/buildr/ide/idea7x.ipr.template +290 -0
  77. data/lib/buildr/ide/idea7x.rb +210 -0
  78. data/lib/buildr/java.rb +26 -0
  79. data/lib/buildr/java/ant.rb +71 -0
  80. data/lib/buildr/java/bdd_frameworks.rb +267 -0
  81. data/lib/buildr/java/commands.rb +210 -0
  82. data/lib/buildr/java/compilers.rb +432 -0
  83. data/lib/buildr/java/deprecated.rb +141 -0
  84. data/lib/buildr/java/groovyc.rb +137 -0
  85. data/lib/buildr/java/jruby.rb +99 -0
  86. data/lib/buildr/java/org/apache/buildr/BuildrNail$Main.class +0 -0
  87. data/lib/buildr/java/org/apache/buildr/BuildrNail.class +0 -0
  88. data/lib/buildr/java/org/apache/buildr/BuildrNail.java +41 -0
  89. data/lib/buildr/java/org/apache/buildr/JavaTestFilter.class +0 -0
  90. data/lib/buildr/java/org/apache/buildr/JavaTestFilter.java +116 -0
  91. data/lib/buildr/java/packaging.rb +706 -0
  92. data/lib/{java → buildr/java}/pom.rb +20 -4
  93. data/lib/buildr/java/rjb.rb +142 -0
  94. data/lib/buildr/java/test_frameworks.rb +290 -0
  95. data/lib/buildr/java/version_requirement.rb +172 -0
  96. data/lib/buildr/packaging.rb +21 -0
  97. data/lib/{java → buildr/packaging}/artifact.rb +170 -179
  98. data/lib/buildr/packaging/artifact_namespace.rb +957 -0
  99. data/lib/buildr/packaging/artifact_search.rb +140 -0
  100. data/lib/buildr/packaging/gems.rb +102 -0
  101. data/lib/buildr/packaging/package.rb +233 -0
  102. data/lib/{tasks → buildr/packaging}/tar.rb +18 -1
  103. data/lib/{tasks → buildr/packaging}/zip.rb +153 -105
  104. data/rakelib/apache.rake +126 -0
  105. data/rakelib/changelog.rake +56 -0
  106. data/rakelib/doc.rake +103 -0
  107. data/rakelib/package.rake +44 -0
  108. data/rakelib/release.rake +53 -0
  109. data/rakelib/rspec.rake +81 -0
  110. data/rakelib/rubyforge.rake +45 -0
  111. data/rakelib/scm.rake +49 -0
  112. data/rakelib/setup.rake +59 -0
  113. data/rakelib/stage.rake +45 -0
  114. data/spec/application_spec.rb +316 -0
  115. data/spec/archive_spec.rb +494 -0
  116. data/spec/artifact_namespace_spec.rb +635 -0
  117. data/spec/artifact_spec.rb +738 -0
  118. data/spec/build_spec.rb +193 -0
  119. data/spec/checks_spec.rb +537 -0
  120. data/spec/common_spec.rb +579 -0
  121. data/spec/compile_spec.rb +561 -0
  122. data/spec/groovy_compilers_spec.rb +239 -0
  123. data/spec/java_bdd_frameworks_spec.rb +238 -0
  124. data/spec/java_compilers_spec.rb +446 -0
  125. data/spec/java_packaging_spec.rb +1042 -0
  126. data/spec/java_test_frameworks_spec.rb +414 -0
  127. data/spec/packaging_helper.rb +63 -0
  128. data/spec/packaging_spec.rb +589 -0
  129. data/spec/project_spec.rb +739 -0
  130. data/spec/sandbox.rb +116 -0
  131. data/spec/scala_compilers_spec.rb +239 -0
  132. data/spec/spec.opts +6 -0
  133. data/spec/spec_helpers.rb +283 -0
  134. data/spec/test_spec.rb +871 -0
  135. data/spec/transport_spec.rb +300 -0
  136. data/spec/version_requirement_spec.rb +115 -0
  137. metadata +188 -77
  138. data/lib/buildr/cobertura.rb +0 -89
  139. data/lib/buildr/jdepend.rb +0 -40
  140. data/lib/buildr/jetty/JettyWrapper$1.class +0 -0
  141. data/lib/buildr/jetty/JettyWrapper$BuildrHandler.class +0 -0
  142. data/lib/buildr/jetty/JettyWrapper.class +0 -0
  143. data/lib/buildr/scala.rb +0 -368
  144. data/lib/core/application.rb +0 -188
  145. data/lib/core/common.rb +0 -562
  146. data/lib/core/help.rb +0 -72
  147. data/lib/core/rake_ext.rb +0 -81
  148. data/lib/java/ant.rb +0 -71
  149. data/lib/java/compile.rb +0 -589
  150. data/lib/java/idea.rb +0 -159
  151. data/lib/java/java.rb +0 -432
  152. data/lib/java/packaging.rb +0 -581
  153. data/lib/java/test.rb +0 -795
  154. data/lib/tasks/concat.rb +0 -35
@@ -0,0 +1,137 @@
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
+ module Buildr
18
+ module Compiler
19
+ # Groovyc compiler:
20
+ # compile.using(:groovyc)
21
+ #
22
+ # You need to require 'buildr/java/groovyc' if you need to use this compiler.
23
+ #
24
+ # Used by default if .groovy files are found in the src/main/groovy directory (or src/test/groovy)
25
+ # and sets the target directory to target/classes (or target/test/classes).
26
+ #
27
+ # Groovyc is a joint compiler, this means that when selected for a project, this compiler is used
28
+ # to compile both groovy and java sources. It's recommended that Groovy sources are placed in the
29
+ # src/main/groovy directory, even though this compiler also looks in src/main/java
30
+ #
31
+ # Groovyc accepts the following options:
32
+ #
33
+ # * :encoding -- Encoding of source files
34
+ # * :verbose -- Asks the compiler for verbose output, true when running in verbose mode.
35
+ # * :fork -- Whether to execute groovyc using a spawned instance of the JVM; defaults to no
36
+ # * :memoryInitialSize -- The initial size of the memory for the underlying VM, if using fork mode; ignored otherwise.
37
+ # Defaults to the standard VM memory setting. (Examples: 83886080, 81920k, or 80m)
38
+ # * :memoryMaximumSize -- The maximum size of the memory for the underlying VM, if using fork mode; ignored otherwise.
39
+ # Defaults to the standard VM memory setting. (Examples: 83886080, 81920k, or 80m)
40
+ # * :listfiles -- Indicates whether the source files to be compiled will be listed; defaults to no
41
+ # * :stacktrace -- If true each compile error message will contain a stacktrace
42
+ # * :warnings -- Issue warnings when compiling. True when running in verbose mode.
43
+ # * :debug -- Generates bytecode with debugging information. Set from the debug
44
+ # environment variable/global option.
45
+ # * :deprecation -- If true, shows deprecation messages. False by default.
46
+ # * :optimise -- Generates faster bytecode by applying optimisations to the program.
47
+ # * :source -- Source code compatibility.
48
+ # * :target -- Bytecode compatibility.
49
+ # * :javac -- Hash of options passed to the ant javac task
50
+ #
51
+ class Groovyc < Base
52
+
53
+ # The groovyc compiler jars are added to classpath at load time,
54
+ # if you want to customize artifact versions, you must set them on the
55
+ #
56
+ # artifact_ns['Buildr::Compiler::Groovyc'].groovy = '1.5.4'
57
+ #
58
+ # namespace before this file is required.
59
+ REQUIRES = ArtifactNamespace.for(self) do |ns|
60
+ ns.groovy! 'org.codehaus.groovy:groovy:jar:>=1.5.3'
61
+ ns.commons_cli! 'commons-cli:commons-cli:jar:>=1.0'
62
+ ns.asm! 'asm:asm:jar:>=2.2'
63
+ ns.antlr! 'antlr:antlr:jar:>=2.7.7'
64
+ end
65
+
66
+ ANT_TASK = 'org.codehaus.groovy.ant.Groovyc'
67
+ GROOVYC_OPTIONS = [:encoding, :verbose, :fork, :memoryInitialSize, :memoryMaximumSize, :listfiles, :stacktrace]
68
+ JAVAC_OPTIONS = [:optimise, :warnings, :debug, :deprecation, :source, :target, :javac]
69
+ OPTIONS = GROOVYC_OPTIONS + JAVAC_OPTIONS
70
+
71
+ class << self
72
+ def dependencies #:nodoc:
73
+ REQUIRES.artifacts
74
+ end
75
+
76
+ def applies_to?(project, task) #:nodoc:
77
+ paths = task.sources + [sources].flatten.map { |src| Array(project.path_to(:source, task.usage, src.to_sym)) }
78
+ paths.flatten!
79
+ # Just select if we find .groovy files
80
+ paths.any? { |path| !Dir["#{path}/**/*.groovy"].empty? }
81
+ end
82
+ end
83
+
84
+ Java.classpath << dependencies
85
+
86
+ specify :language => :groovy, :sources => [:groovy, :java], :source_ext => [:groovy, :java],
87
+ :target => 'classes', :target_ext => 'class', :packaging => :jar
88
+
89
+ def initialize(project, options) #:nodoc:
90
+ super
91
+ options[:debug] = Buildr.options.debug if options[:debug].nil?
92
+ options[:deprecation] ||= false
93
+ options[:optimise] ||= false
94
+ options[:verbose] ||= Buildr.application.options.trace if options[:verbose].nil?
95
+ options[:warnings] = verbose if options[:warnings].nil?
96
+ options[:javac] = OpenObject.new if options[:javac].nil?
97
+ end
98
+
99
+ # http://groovy.codehaus.org/The+groovyc+Ant+Task
100
+ def compile(sources, target, dependencies) #:nodoc:
101
+ return if Buildr.application.options.dryrun
102
+ Buildr.ant 'groovyc' do |ant|
103
+ classpath = dependencies | self.class.dependencies.map(&:to_s)
104
+ ant.taskdef :name => 'groovyc', :classname => ANT_TASK, :classpath => classpath.join(File::PATH_SEPARATOR)
105
+ ant.groovyc groovyc_options(sources, target) do
106
+ sources.each { |src| ant.src :path => src }
107
+ ant.classpath do
108
+ classpath.each { |dep| ant.pathelement :path => dep }
109
+ end
110
+ ant.javac(javac_options)
111
+ end
112
+ end
113
+ end
114
+
115
+ private
116
+ def groovyc_options(sources, target)
117
+ check_options options, OPTIONS
118
+ groovyc_options = options.to_hash.only(*GROOVYC_OPTIONS)
119
+ groovyc_options[:destdir] = File.expand_path(target)
120
+ groovyc_options
121
+ end
122
+
123
+ def javac_options
124
+ check_options options, OPTIONS
125
+ javac_options = options.to_hash.only(*JAVAC_OPTIONS)
126
+ javac_options[:optimize] = (javac_options.delete(:optimise) || false)
127
+ javac_options[:nowarn] = (javac_options.delete(:warnings) || verbose).to_s !~ /^(true|yes|on)$/i
128
+ other = javac_options.delete(:javac) || {}
129
+ javac_options.merge!(other)
130
+ javac_options
131
+ end
132
+
133
+ end
134
+ end
135
+ end
136
+
137
+ Buildr::Compiler.compilers.unshift Buildr::Compiler::Groovyc
@@ -0,0 +1,99 @@
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 'java'
18
+ require 'jruby'
19
+
20
+
21
+ # Buildr runs along side a JVM, using either RJB or JRuby. The Java module allows
22
+ # you to access Java classes and create Java objects.
23
+ #
24
+ # Java classes are accessed as static methods on the Java module, for example:
25
+ # str = Java.java.lang.String.new('hai!')
26
+ # str.toUpperCase
27
+ # => 'HAI!'
28
+ # Java.java.lang.String.isInstance(str)
29
+ # => true
30
+ # Java.com.sun.tools.javac.Main.compile(args)
31
+ #
32
+ # The classpath attribute allows Buildr to add JARs and directories to the classpath,
33
+ # for example, we use it to load Ant and various Ant tasks, code generators, test
34
+ # frameworks, and so forth.
35
+ #
36
+ # When using an artifact specification, Buildr will automatically download and
37
+ # install the artifact before adding it to the classpath.
38
+ #
39
+ # For example, Ant is loaded as follows:
40
+ # Java.classpath << 'org.apache.ant:ant:jar:1.7.0'
41
+ #
42
+ # Artifacts can only be downloaded after the Buildfile has loaded, giving it
43
+ # a chance to specify which remote repositories to use, so adding to classpath
44
+ # does not by itself load any libraries. You must call Java.load before accessing
45
+ # any Java classes to give Buildr a chance to load the libraries specified in the
46
+ # classpath.
47
+ #
48
+ # When building an extension, make sure to follow these rules:
49
+ # 1. Add to the classpath when the extension is loaded (i.e. in module or class
50
+ # definition), so the first call to Java.load anywhere in the code will include
51
+ # the libraries you specify.
52
+ # 2. Call Java.load once before accessing any Java classes, allowing Buildr to
53
+ # set up the classpath.
54
+ # 3. Only call Java.load when invoked, otherwise you may end up loading the JVM
55
+ # with a partial classpath, or before all remote repositories are listed.
56
+ # 4. Check on a clean build with empty local repository.
57
+ module Java
58
+
59
+ class << self
60
+
61
+ # Returns the classpath, an array listing directories, JAR files and
62
+ # artifacts. Use when loading the extension to add any additional
63
+ # libraries used by that extension.
64
+ #
65
+ # For example, Ant is loaded as follows:
66
+ # Java.classpath << 'org.apache.ant:ant:jar:1.7.0'
67
+ def classpath
68
+ @classpath ||= []
69
+ end
70
+
71
+ # Loads the JVM and all the libraries listed on the classpath. Call this
72
+ # method before accessing any Java class, but only call it from methods
73
+ # used in the build, giving the Buildfile a chance to load all extensions
74
+ # that append to the classpath and specify which remote repositories to use.
75
+ def load
76
+ return self if @loaded
77
+ cp = Buildr.artifacts(classpath).map(&:to_s).each { |path| file(path).invoke }
78
+ #cp ||= java.lang.System.getProperty('java.class.path').split(':').compact
79
+ # Use system ClassLoader to add classpath.
80
+ sysloader = java.lang.ClassLoader.getSystemClassLoader
81
+ add_url_method = java.lang.Class.forName('java.net.URLClassLoader').
82
+ getDeclaredMethod('addURL', [java.net.URL].to_java(java.lang.Class))
83
+ add_url_method.setAccessible(true)
84
+ add_path = lambda { |path| add_url_method.invoke(sysloader, [java.io.File.new(path).toURI.toURL].to_java(java.net.URL)) }
85
+ # Include tools (compiler, Javadoc, etc) for all platforms except OS/X.
86
+ unless Config::CONFIG['host_os'] =~ /darwin/i
87
+ home = ENV['JAVA_HOME'] or fail 'Are we forgetting something? JAVA_HOME not set.'
88
+ tools = File.expand_path('lib/tools.jar', home)
89
+ raise "Missing #{tools}, perhaps your JAVA_HOME is not correclty set" unless File.file?(tools)
90
+ add_path[tools]
91
+ end
92
+ cp.each { |path| add_path[path] }
93
+ @loaded = true
94
+ self
95
+ end
96
+
97
+ end
98
+
99
+ end
@@ -0,0 +1,41 @@
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
14
+ * under the License.
15
+ */
16
+
17
+
18
+ package org.apache.buildr;
19
+
20
+ import com.martiansoftware.nailgun.NGContext;
21
+
22
+ public interface BuildrNail {
23
+
24
+ public void main(NGContext ctx);
25
+
26
+ public static class Main {
27
+ private static BuildrNail nail;
28
+ public static void setNail(BuildrNail _nail) { nail = _nail; }
29
+ public static void nailMain(NGContext ctx) {
30
+ nail.main(ctx);
31
+ }
32
+ }
33
+
34
+ }
35
+
36
+ /*
37
+ * Local Variables:
38
+ * indent-tabs-mode: nil
39
+ * c-basic-offset: 2
40
+ * End:
41
+ */
@@ -0,0 +1,116 @@
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
14
+ * under the License.
15
+ */
16
+
17
+
18
+ package org.apache.buildr;
19
+
20
+ import java.lang.reflect.Method;
21
+ import java.io.File;
22
+ import java.io.IOException;
23
+ import java.net.URL;
24
+ import java.net.URLClassLoader;
25
+ import java.net.MalformedURLException;
26
+ import java.util.Iterator;
27
+ import java.util.Vector;
28
+
29
+ public class JavaTestFilter {
30
+
31
+ private ClassLoader _loader;
32
+ private Vector methodAnnotations = new Vector();
33
+ private Vector classAnnotations = new Vector();
34
+ private Vector interfaces = new Vector();
35
+
36
+ public JavaTestFilter(String[] paths) throws IOException {
37
+ URL[] urls = new URL[paths.length];
38
+ for (int i = 0 ; i < paths.length ; ++i) {
39
+ File file = new File(paths[i]).getCanonicalFile();
40
+ if (file.exists())
41
+ urls[i] = file.toURL();
42
+ else
43
+ throw new IOException("No file or directory with the name " + file);
44
+ }
45
+ _loader = new URLClassLoader(urls, getClass().getClassLoader());
46
+ }
47
+
48
+ public JavaTestFilter addInterfaces(String[] names) throws ClassNotFoundException {
49
+ for (int i = names.length; i -- > 0;) {
50
+ String name = names[i];
51
+ interfaces.add(_loader.loadClass(name));
52
+ }
53
+ return this;
54
+ }
55
+
56
+ public JavaTestFilter addClassAnnotations(String[] names) throws ClassNotFoundException {
57
+ for (int i = names.length; i -- > 0;) {
58
+ String name = names[i];
59
+ classAnnotations.add(_loader.loadClass(name));
60
+ }
61
+ return this;
62
+ }
63
+
64
+ public JavaTestFilter addMethodAnnotations(String[] names) throws ClassNotFoundException {
65
+ for (int i = names.length; i -- > 0;) {
66
+ String name = names[i];
67
+ methodAnnotations.add(_loader.loadClass(name));
68
+ }
69
+ return this;
70
+ }
71
+
72
+ private boolean isTest(Class cls) {
73
+ if (interfaces != null) {
74
+ for (Iterator it = interfaces.iterator(); it.hasNext(); ) {
75
+ Class iface = (Class) it.next();
76
+ if (iface.isAssignableFrom(cls)) { return true; }
77
+ }
78
+ }
79
+ if (classAnnotations != null) {
80
+ for (Iterator it = classAnnotations.iterator(); it.hasNext(); ) {
81
+ Class annotation = (Class) it.next();
82
+ if (cls.isAnnotationPresent(annotation)) { return true; }
83
+ }
84
+ }
85
+ if (methodAnnotations != null) {
86
+ Method[] methods = cls.getMethods();
87
+ for (int j = methods.length ; j-- > 0 ;) {
88
+ for (Iterator it = methodAnnotations.iterator(); it.hasNext(); ) {
89
+ Class annotation = (Class) it.next();
90
+ if (methods[j].isAnnotationPresent(annotation)) { return true; }
91
+ }
92
+ }
93
+ }
94
+ return false;
95
+ }
96
+
97
+
98
+ public String[] filter(String[] names) throws ClassNotFoundException {
99
+ Vector testCases = new Vector();
100
+ for (int i = names.length ; i-- > 0 ;) {
101
+ Class cls = _loader.loadClass(names[i]);
102
+ if (isTest(cls)) { testCases.add(names[i]); }
103
+ }
104
+ String[] result = new String[testCases.size()];
105
+ testCases.toArray(result);
106
+ return result;
107
+ }
108
+
109
+ }
110
+
111
+ /*
112
+ * Local Variables:
113
+ * indent-tabs-mode: nil
114
+ * c-basic-offset: 2
115
+ * End:
116
+ */
@@ -0,0 +1,706 @@
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
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\nCreated-By: Buildr\n"
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[0] == 32
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::ZipFile.open(file.to_s) do |zip|
60
+ return Manifest.new unless zip.get_entry('META-INF/MANIFEST.MF')
61
+ Manifest.parse zip.read('META-INF/MANIFEST.MF')
62
+ end
63
+ end
64
+
65
+ # :call_seq:
66
+ # update_manifest(file) { |manifest| ... }
67
+ #
68
+ # Updates the MANIFEST.MF entry of a ZIP (or JAR) file. Reads the MANIFEST.MF,
69
+ # yields to the block with the Manifest object, and writes the modified object
70
+ # back to the file.
71
+ def update_manifest(file)
72
+ manifest = from_zip(file)
73
+ result = yield manifest
74
+ Zip::ZipFile.open(file.to_s) do |zip|
75
+ zip.get_output_stream('META-INF/MANIFEST.MF') do |out|
76
+ out.write manifest.to_s
77
+ out.write "\n"
78
+ end
79
+ end
80
+ result
81
+ end
82
+
83
+ end
84
+
85
+ # Returns a new Manifest object based on the argument:
86
+ # * nil -- Empty Manifest.
87
+ # * Hash -- Manifest with main section using the hash name/value pairs.
88
+ # * Array -- Manifest with one section from each entry (must be hashes).
89
+ # * String -- Parse (see Manifest#parse).
90
+ # * Proc/Method -- New Manifest from result of calling proc/method.
91
+ def initialize(arg = nil)
92
+ case arg
93
+ when nil, Hash then @sections = [arg || {}]
94
+ when Array then @sections = arg
95
+ when String then @sections = Manifest.parse(arg).sections
96
+ when Proc, Method then @sections = Manifest.new(arg.call).sections
97
+ else
98
+ fail 'Invalid manifest, expecting Hash, Array, file name/task or proc/method.'
99
+ end
100
+ end
101
+
102
+ # The sections of this manifest.
103
+ attr_reader :sections
104
+
105
+ # The main (first) section of this manifest.
106
+ def main
107
+ sections.first
108
+ end
109
+
110
+ include Enumerable
111
+
112
+ # Iterate over each section and yield to block.
113
+ def each(&block)
114
+ @sections.each(&block)
115
+ end
116
+
117
+ # Convert to MANIFEST.MF format.
118
+ def to_s
119
+ @sections.map { |section|
120
+ keys = section.keys
121
+ keys.unshift('Name') if keys.delete('Name')
122
+ lines = keys.map { |key| manifest_wrap_at_72("#{key}: #{section[key]}") }
123
+ lines + ['']
124
+ }.flatten.join("\n")
125
+ end
126
+
127
+ private
128
+
129
+ def manifest_wrap_at_72(line)
130
+ return [line] if line.size < 72
131
+ [ line[0..70] ] + manifest_wrap_at_72(' ' + line[71..-1])
132
+ end
133
+
134
+ end
135
+
136
+
137
+ # Adds support for MANIFEST.MF and other META-INF files.
138
+ module WithManifest #:nodoc:
139
+
140
+ class << self
141
+ def included(base)
142
+ base.class_eval do
143
+ alias :initialize_without_manifest :initialize
144
+ alias :initialize :initialize_with_manifest
145
+ end
146
+ end
147
+
148
+ end
149
+
150
+ # Specifies how to create the manifest file.
151
+ attr_accessor :manifest
152
+
153
+ # Specifies files to include in the META-INF directory.
154
+ attr_accessor :meta_inf
155
+
156
+ def initialize_with_manifest(*args) #:nodoc:
157
+ initialize_without_manifest *args
158
+ @manifest = false
159
+ @meta_inf = []
160
+ @dependencies = FileList[]
161
+
162
+ prepare do
163
+ @prerequisites << manifest if String === manifest || Rake::Task === manifest
164
+ [meta_inf].flatten.map { |file| file.to_s }.uniq.each { |file| path('META-INF').include file }
165
+ end
166
+
167
+ enhance do
168
+ if manifest
169
+ # Tempfiles gets deleted on garbage collection, so we're going to hold on to it
170
+ # through instance variable not closure variable.
171
+ Tempfile.open 'MANIFEST.MF' do |@manifest_tmp|
172
+ self.manifest = File.read(manifest.to_s) if String === manifest || Rake::Task === manifest
173
+ self.manifest = Manifest.new(manifest) unless Manifest === manifest
174
+ @manifest_tmp.write Manifest::STANDARD_HEADER
175
+ @manifest_tmp.write manifest.to_s
176
+ @manifest_tmp.write "\n"
177
+ path('META-INF').include @manifest_tmp.path, :as=>'MANIFEST.MF'
178
+ end
179
+ end
180
+ end
181
+ end
182
+
183
+ end
184
+
185
+ class ::Buildr::ZipTask
186
+ include WithManifest
187
+ end
188
+
189
+
190
+ # Extends the ZipTask to create a JAR file.
191
+ #
192
+ # This task supports two additional attributes: manifest and meta-inf.
193
+ #
194
+ # The manifest attribute specifies how to create the MANIFEST.MF file.
195
+ # * A hash of manifest properties (name/value pairs).
196
+ # * An array of hashes, one for each section of the manifest.
197
+ # * A string providing the name of an existing manifest file.
198
+ # * A file task can be used the same way.
199
+ # * Proc or method called to return the contents of the manifest file.
200
+ # * False to not generate a manifest file.
201
+ #
202
+ # The meta-inf attribute lists one or more files that should be copied into
203
+ # the META-INF directory.
204
+ #
205
+ # For example:
206
+ # package(:jar).with(:manifest=>'src/MANIFEST.MF')
207
+ # package(:jar).meta_inf << file('README')
208
+ class JarTask < ZipTask
209
+
210
+ def initialize(*args) #:nodoc:
211
+ super
212
+ end
213
+
214
+ # :call-seq:
215
+ # with(options) => self
216
+ #
217
+ # Additional
218
+ # Pass options to the task. Returns self. ZipTask itself does not support any options,
219
+ # but other tasks (e.g. JarTask, WarTask) do.
220
+ #
221
+ # For example:
222
+ # package(:jar).with(:manifest=>'MANIFEST_MF')
223
+ def with(*args)
224
+ super args.pop if Hash === args.last
225
+ include :from=>args
226
+ self
227
+ end
228
+
229
+ end
230
+
231
+
232
+ # Extends the JarTask to create a WAR file.
233
+ #
234
+ # Supports all the same options as JarTask, in additon to these two options:
235
+ # * :libs -- An array of files, tasks, artifact specifications, etc that will be added
236
+ # to the WEB-INF/lib directory.
237
+ # * :classes -- A directory containing class files for inclusion in the WEB-INF/classes
238
+ # directory.
239
+ #
240
+ # For example:
241
+ # package(:war).with(:libs=>'log4j:log4j:jar:1.1')
242
+ class WarTask < JarTask
243
+
244
+ # Directories with class files to include under WEB-INF/classes.
245
+ attr_accessor :classes
246
+
247
+ # Artifacts to include under WEB-INF/libs.
248
+ attr_accessor :libs
249
+
250
+ def initialize(*args) #:nodoc:
251
+ super
252
+ @classes = []
253
+ @libs = []
254
+ prepare do
255
+ @classes.to_a.flatten.each { |classes| path('WEB-INF/classes').include classes, :as=>'.' }
256
+ path('WEB-INF/lib').include Buildr.artifacts(@libs) unless @libs.nil? || @libs.empty?
257
+ end
258
+ end
259
+
260
+ def libs=(value) #:nodoc:
261
+ @libs = Buildr.artifacts(value)
262
+ end
263
+
264
+ def classes=(value) #:nodoc:
265
+ @classes = [value].flatten.map { |dir| file(dir.to_s) }
266
+ end
267
+
268
+ end
269
+
270
+
271
+ # Extends the JarTask to create an AAR file (Axis2 service archive).
272
+ #
273
+ # Supports all the same options as JarTask, with the addition of :wsdls, :services_xml and :libs.
274
+ #
275
+ # * :wsdls -- WSDL files to include (under META-INF). By default packaging will include all WSDL
276
+ # files found under src/main/axis2.
277
+ # * :services_xml -- Location of services.xml file (included under META-INF). By default packaging
278
+ # takes this from src/main/axis2/services.xml. Use a different path if you genereate the services.xml
279
+ # file as part of the build.
280
+ # * :libs -- Array of files, tasks, artifact specifications, etc that will be added to the /lib directory.
281
+ #
282
+ # For example:
283
+ # package(:aar).with(:libs=>'log4j:log4j:jar:1.1')
284
+ #
285
+ # filter.from('src/main/axis2').into('target').include('services.xml', '*.wsdl').using('http_port'=>'8080')
286
+ # package(:aar).wsdls.clear
287
+ # package(:aar).with(:services_xml=>_('target/services.xml'), :wsdls=>_('target/*.wsdl'))
288
+ class AarTask < JarTask
289
+ # Artifacts to include under /lib.
290
+ attr_accessor :libs
291
+ # WSDLs to include under META-INF (defaults to all WSDLs under src/main/axis2).
292
+ attr_accessor :wsdls
293
+ # Location of services.xml file (defaults to src/main/axis2/services.xml).
294
+ attr_accessor :services_xml
295
+
296
+ def initialize(*args) #:nodoc:
297
+ super
298
+ @libs = []
299
+ @wsdls = []
300
+ prepare do
301
+ path('META-INF').include @wsdls
302
+ path('META-INF').include @services_xml, :as=>['services.xml'] if @services_xml
303
+ path('lib').include Buildr.artifacts(@libs) unless @libs.nil? || @libs.empty?
304
+ end
305
+ end
306
+
307
+ def libs=(value) #:nodoc:
308
+ @libs = Buildr.artifacts(value)
309
+ end
310
+
311
+ def wsdls=(value) #:nodoc:
312
+ @wsdls |= Array(value)
313
+ end
314
+ end
315
+
316
+
317
+ # Extend the JarTask to create an EAR file.
318
+ #
319
+ # The following component types are supported by the EARTask:
320
+ #
321
+ # * :war -- A J2EE Web Application
322
+ # * :ejb -- An Enterprise Java Bean
323
+ # * :jar -- A J2EE Application Client.[1]
324
+ # * :lib -- An ear scoped shared library[2] (for things like logging,
325
+ # spring, etc) common to the ear components
326
+ #
327
+ # The EarTask uses the "Mechanism 2: Bundled Optional Classes" as described on [2].
328
+ # All specified libraries are added to the EAR archive and the Class-Path manifiest entry is
329
+ # modified for each EAR component. Special care is taken with WebApplications, as they can
330
+ # contain libraries on their WEB-INF/lib directory, libraries already included in a war file
331
+ # are not referenced by the Class-Path entry of the war in order to avoid class collisions
332
+ #
333
+ # EarTask supports all the same options as JarTask, in additon to these two options:
334
+ #
335
+ # * :display_name -- The displayname to for this ear on application.xml
336
+ #
337
+ # * :map -- A Hash used to map component type to paths within the EAR.
338
+ # By default each component type is mapped to a directory with the same name,
339
+ # for example, EJBs are stored in the /ejb path. To customize:
340
+ # package(:ear).map[:war] = 'web-applications'
341
+ # package(:ear).map[:lib] = nil # store shared libraries on root of archive
342
+ #
343
+ # EAR components are added by means of the EarTask#add, EarTask#<<, EarTask#push methods
344
+ # Component type is determined from the artifact's type.
345
+ #
346
+ # package(:ear) << project('coolWebService').package(:war)
347
+ #
348
+ # The << method is just an alias for push, with the later you can add multiple components
349
+ # at the same time. For example..
350
+ #
351
+ # package(:ear).push 'org.springframework:spring:jar:2.6',
352
+ # projects('reflectUtils', 'springUtils'),
353
+ # project('coolerWebService').package(:war)
354
+ #
355
+ # The add method takes a single component with an optional hash. You can use it to override
356
+ # some component attributes.
357
+ #
358
+ # You can override the component type for a particular artifact. The following example
359
+ # shows how you can tell the EarTask to treat a JAR file as an EJB:
360
+ #
361
+ # # will add an ejb entry for the-cool-ejb-2.5.jar in application.xml
362
+ # package(:ear).add 'org.coolguys:the-cool-ejb:jar:2.5', :type=>:ejb
363
+ # # A better syntax for this is:
364
+ # package(:ear).add :ejb=>'org.coolguys:the-cool-ejb:jar:2.5'
365
+ #
366
+ # By default, every JAR package is assumed to be a library component, so you need to specify
367
+ # the type when including an EJB (:ejb) or Application Client JAR (:jar).
368
+ #
369
+ # For WebApplications (:war)s, you can customize the context-root that appears in application.xml.
370
+ # The following example also specifies a different directory inside the EAR where to store the webapp.
371
+ #
372
+ # package(:ear).add project(:remoteService).package(:war),
373
+ # :path=>'web-services', :context_root=>'/Some/URL/Path'
374
+ #
375
+ # [1] http://java.sun.com/j2ee/sdk_1.2.1/techdocs/guides/ejb/html/Overview5.html#10106
376
+ # [2] http://java.sun.com/j2ee/verified/packaging.html
377
+ class EarTask < JarTask
378
+
379
+ SUPPORTED_TYPES = [:war, :ejb, :jar, :rar, :lib]
380
+
381
+ # The display-name entry for application.xml
382
+ attr_accessor :display_name
383
+ # Map from component type to path inside the EAR.
384
+ attr_accessor :dirs
385
+
386
+ def initialize(*args)
387
+ super
388
+ @dirs = Hash.new { |h, k| k.to_s }
389
+ @libs, @components = [], []
390
+ prepare do
391
+ @components.each do |component|
392
+ path(component[:path]).include(component[:clone] || component[:artifact])
393
+ end
394
+ path('META-INF').include(descriptor)
395
+ end
396
+ end
397
+
398
+ # Add an artifact to this EAR.
399
+ def add(*args)
400
+ options = Hash === args.last ? args.pop.clone : {}
401
+ args.flatten!
402
+ args.map! do |pkg|
403
+ case pkg
404
+ when Project
405
+ pkg.packages.select { |pp| JarTask === pp && SUPPORTED_TYPES.include?(pp.type) }
406
+ when Rake::FileTask
407
+ pkg # add the explicitly provided file
408
+ when Hash
409
+ Buildr.artifact(pkg)
410
+ when String
411
+ begin
412
+ Buildr.artifact(pkg)
413
+ rescue # not an artifact spec, it must me a filename
414
+ file(pkg)
415
+ end
416
+ else
417
+ raise "Invalid EAR component #{pkg.class}: #{pkg}"
418
+ end
419
+ end
420
+ args.flatten!
421
+ args.compact!
422
+ if args.empty?
423
+ raise ":type must not be specified for type=>component argument style" if options.key?(:type)
424
+ raise ":as must not be specified for type=>component argument style" if options.key?(:as)
425
+ comps = {}
426
+ options.delete_if { |k, v| comps[k] = v if SUPPORTED_TYPES.include?(k) }
427
+ raise "You must specify at least one valid component to add" if comps.empty?
428
+ comps.each { |k, v| add(v, {:as => k}.merge(options)) }
429
+ else
430
+ args.each do |artifact|
431
+ type = options[:as] || options[:type]
432
+ unless type
433
+ type = artifact.respond_to?(:type) ? artifact.type : artifact.to_s.pathmap('%x').to_sym
434
+ type = :lib if type == :jar
435
+ end
436
+ raise "Unknown EAR component type: #{type}. Perhaps you may explicity tell what component type to use." unless
437
+ SUPPORTED_TYPES.include?(type)
438
+ component = options.merge(:artifact => artifact, :type => type,
439
+ :id=>artifact.respond_to?(:to_spec) ? artifact.id : artifact.to_s.pathmap('%n'),
440
+ :path=>options[:path] || dirs[type].to_s)
441
+ component[:clone] = component_clone(component) unless :lib == type
442
+ # update_classpath(component) unless :lib == type || Artifact === artifact
443
+ @components << component
444
+ end
445
+ end
446
+ self
447
+ end
448
+
449
+ alias_method :push, :add
450
+ alias_method :<<, :push
451
+
452
+ protected
453
+
454
+ def component_clone(component)
455
+ file(path_to(component[:path], component[:artifact].to_s.pathmap('%f')) => component[:artifact]) do |task|
456
+ mkpath task.to_s.pathmap('%d'), :verbose => false
457
+ cp component[:artifact].to_s, task.to_s, :verbose => false
458
+ Manifest.update_manifest(task) do |manifest|
459
+ class_path = manifest.main['Class-Path'].to_s.split
460
+ included_libs = class_path.map { |fn| fn.pathmap('%f') }
461
+ Zip::ZipFile.foreach(task.to_s) do |entry|
462
+ included_libs << entry.name.pathmap('%f') if entry.file? && entry.name =~ /^WEB-INF\/lib\/[^\/]+$/
463
+ end
464
+ # Include all other libraries in the classpath.
465
+ class_path += libs_classpath(component).reject { |path| included_libs.include?(File.basename(path)) }
466
+ manifest.main['Class-Path'] = class_path.join(' ')
467
+ end
468
+ end
469
+ end
470
+
471
+ def associate(project)
472
+ @project = project
473
+ end
474
+
475
+ def path_to(*args) #:nodoc:
476
+ @project.path_to(:target, :ear, name.pathmap('%n'), *args)
477
+ end
478
+ alias_method :_, :path_to
479
+
480
+ def update_classpath(component)
481
+ package = file(component[:artifact].to_s)
482
+ package.manifest = (package.manifest || {}).dup # avoid mofifying parent projects manifest
483
+ package.prepare do
484
+ header = case package.manifest
485
+ when Hash then package.manifest
486
+ when Array then package.manifest.first
487
+ end
488
+ if header
489
+ # Determine which libraries are already included.
490
+ class_path = header['Class-Path'].to_s.split
491
+ included_libs = class_path.map { |fn| File.basename(fn) }
492
+ included_libs += package.path('WEB-INF/lib').sources.map { |fn| File.basename(fn) }
493
+ # Include all other libraries in the classpath.
494
+ class_path += libs_classpath(component).reject { |path| included_libs.include?(File.basename(path)) }
495
+ header['Class-Path'] = class_path.join(' ')
496
+ end
497
+ end
498
+ end
499
+
500
+ private
501
+
502
+ # Classpath of all packages included as libraries (type :lib).
503
+ def libs_classpath(component)
504
+ from = component[:path]
505
+ @classpath = @components.select { |comp| comp[:type] == :lib }.
506
+ map do |lib|
507
+ basename = lib[:artifact].to_s.pathmap('%f')
508
+ full_path = lib[:path].empty? ? basename : File.join(lib[:path], basename)
509
+ Util.relative_path(full_path, from)
510
+ end
511
+ end
512
+
513
+ def descriptor_xml
514
+ buffer = ""
515
+ xml = Builder::XmlMarkup.new(:target=>buffer, :indent => 2)
516
+ xml.declare! :DOCTYPE, :application, :PUBLIC,
517
+ "-//Sun Microsystems, Inc.//DTD J2EE Application 1.2//EN",
518
+ "http://java.sun.com/j2ee/dtds/application_1_2.dtd"
519
+ xml.application do
520
+ xml.tag! 'display-name', display_name
521
+ @components.each do |comp|
522
+ basename = comp[:artifact].to_s.pathmap('%f')
523
+ uri = comp[:path].empty? ? basename : File.join(comp[:path], basename)
524
+ case comp[:type]
525
+ when :war
526
+ xml.module :id=>comp[:id] do
527
+ xml.web do
528
+ xml.tag! 'web-uri', uri
529
+ xml.tag! 'context-root', File.join('', (comp[:context_root] || comp[:id])) unless comp[:context_root] == false
530
+ end
531
+ end
532
+ when :ejb
533
+ xml.module :id=>comp[:id] do
534
+ xml.ejb uri
535
+ end
536
+ when :jar
537
+ xml.jar uri
538
+ end
539
+ end
540
+ end
541
+ buffer
542
+ end
543
+
544
+ # return a FileTask to build the ear application.xml file
545
+ def descriptor
546
+ return @descriptor if @descriptor
547
+ descriptor_path = path_to('META-INF/application.xml')
548
+ @descriptor = file(descriptor_path) do |task|
549
+ puts "Creating EAR Descriptor: #{task.to_s}" if Buildr.application.options.trace
550
+ mkpath File.dirname(task.name), :verbose=>false
551
+ File.open(task.name, 'w') { |file| file.print task.xml }
552
+ end
553
+ class << @descriptor
554
+ attr_accessor :ear
555
+
556
+ def xml
557
+ @xml ||= ear.send :descriptor_xml
558
+ end
559
+
560
+ def needed?
561
+ super || xml != File.read(self.to_s) rescue true
562
+ end
563
+ end
564
+ @descriptor.ear = self
565
+ @descriptor
566
+ end
567
+
568
+ end
569
+
570
+
571
+ include Extension
572
+
573
+ before_define do |project|
574
+ ::Java.load
575
+ project.manifest ||= project.parent && project.parent.manifest ||
576
+ { 'Build-By'=>ENV['USER'], 'Build-Jdk'=>ENV_JAVA['java.version'],
577
+ 'Implementation-Title'=>project.comment || project.name,
578
+ 'Implementation-Version'=>project.version }
579
+ project.meta_inf ||= project.parent && project.parent.meta_inf ||
580
+ [project.file('LICENSE')].select { |file| File.exist?(file.to_s) }
581
+ end
582
+
583
+
584
+ # Manifest used for packaging. Inherited from parent project. The default value is a hash that includes
585
+ # the Build-By, Build-Jdk, Implementation-Title and Implementation-Version values.
586
+ # The later are taken from the project's comment (or name) and version number.
587
+ attr_accessor :manifest
588
+
589
+ # Files to always include in the package META-INF directory. The default value include
590
+ # the LICENSE file if one exists in the project's base directory.
591
+ attr_accessor :meta_inf
592
+
593
+ # :call-seq:
594
+ # package_with_sources(options?)
595
+ #
596
+ # Call this when you want the project (and all its sub-projects) to create a source distribution.
597
+ # You can use the source distribution in an IDE when debugging.
598
+ #
599
+ # A source distribution is a ZIP package with the classifier 'sources', which includes all the
600
+ # sources used by the compile task.
601
+ #
602
+ # Packages use the project's manifest and meta_inf properties, which you can override by passing
603
+ # different values (e.g. false to exclude the manifest) in the options.
604
+ #
605
+ # To create source distributions only for specific projects, use the :only and :except options,
606
+ # for example:
607
+ # package_with_sources :only=>['foo:bar', 'foo:baz']
608
+ #
609
+ # (Same as calling package :sources on each project/sub-project that has source directories.)
610
+ def package_with_sources(options = nil)
611
+ options ||= {}
612
+ enhance do
613
+ selected = options[:only] ? projects(options[:only]) :
614
+ options[:except] ? ([self] + projects - projects(options[:except])) :
615
+ [self] + projects
616
+ selected.reject { |project| project.compile.sources.empty? }.
617
+ each { |project| project.package(:sources) }
618
+ end
619
+ end
620
+
621
+ # :call-seq:
622
+ # package_with_javadoc(options?)
623
+ #
624
+ # Call this when you want the project (and all its sub-projects) to create a JavaDoc distribution.
625
+ # You can use the JavaDoc distribution in an IDE when coding against the API.
626
+ #
627
+ # A JavaDoc distribution is a ZIP package with the classifier 'javadoc', which includes all the
628
+ # sources used by the compile task.
629
+ #
630
+ # Packages use the project's manifest and meta_inf properties, which you can override by passing
631
+ # different values (e.g. false to exclude the manifest) in the options.
632
+ #
633
+ # To create JavaDoc distributions only for specific projects, use the :only and :except options,
634
+ # for example:
635
+ # package_with_javadoc :only=>['foo:bar', 'foo:baz']
636
+ #
637
+ # (Same as calling package :javadoc on each project/sub-project that has source directories.)
638
+ def package_with_javadoc(options = nil)
639
+ options ||= {}
640
+ enhance do
641
+ selected = options[:only] ? projects(options[:only]) :
642
+ options[:except] ? ([self] + projects - projects(options[:except])) :
643
+ [self] + projects
644
+ selected.reject { |project| project.compile.sources.empty? }.
645
+ each { |project| project.package(:javadoc) }
646
+ end
647
+ end
648
+
649
+ protected
650
+
651
+ def package_as_jar(file_name) #:nodoc:
652
+ Java::JarTask.define_task(file_name).tap do |jar|
653
+ jar.with :manifest=>manifest, :meta_inf=>meta_inf
654
+ jar.with [compile.target, resources.target].compact
655
+ end
656
+ end
657
+
658
+ def package_as_war(file_name) #:nodoc:
659
+ Java::WarTask.define_task(file_name).tap do |war|
660
+ war.with :manifest=>manifest, :meta_inf=>meta_inf
661
+ # Add libraries in WEB-INF lib, and classes in WEB-INF classes
662
+ war.with :classes=>[compile.target, resources.target].compact
663
+ war.with :libs=>compile.dependencies
664
+ # Add included files, or the webapp directory.
665
+ webapp = path_to(:source, :main, :webapp)
666
+ war.with webapp if File.exist?(webapp)
667
+ end
668
+ end
669
+
670
+ def package_as_aar(file_name) #:nodoc:
671
+ Java::AarTask.define_task(file_name).tap do |aar|
672
+ aar.with :manifest=>manifest, :meta_inf=>meta_inf
673
+ aar.with :wsdls=>path_to(:source, :main, :axis2, '*.wsdl')
674
+ aar.with :services_xml=>path_to(:source, :main, :axis2, 'services.xml')
675
+ aar.with [compile.target, resources.target].compact
676
+ aar.with :libs=>compile.dependencies
677
+ end
678
+ end
679
+
680
+ def package_as_ear(file_name) #:nodoc:
681
+ Java::EarTask.define_task(file_name).tap do |ear|
682
+ ear.send :associate, self
683
+ ear.with :display_name=>id, :manifest=>manifest, :meta_inf=>meta_inf
684
+ end
685
+ end
686
+
687
+ def package_as_javadoc_spec(spec) #:nodoc:
688
+ spec.merge(:type=>:zip, :classifier=>'javadoc')
689
+ end
690
+
691
+ def package_as_javadoc(file_name) #:nodoc:
692
+ ZipTask.define_task(file_name).tap do |zip|
693
+ zip.include :from=>javadoc.target
694
+ javadoc.options[:windowtitle] ||= project.comment || project.name
695
+ end
696
+ end
697
+
698
+ end
699
+
700
+ end
701
+ end
702
+
703
+
704
+ class Buildr::Project
705
+ include Buildr::Packaging::Java
706
+ end