buildr 1.2.10 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +566 -268
- data/DISCLAIMER +7 -1
- data/KEYS +151 -0
- data/NOTICE +23 -8
- data/README +122 -22
- data/Rakefile +49 -229
- data/{lib → addon}/buildr/antlr.rb +23 -10
- data/addon/buildr/cobertura.rb +232 -0
- data/{lib → addon}/buildr/hibernate.rb +20 -4
- data/{lib → addon}/buildr/javacc.rb +27 -12
- data/addon/buildr/jdepend.rb +60 -0
- data/{lib → addon}/buildr/jetty.rb +34 -18
- data/addon/buildr/nailgun.rb +892 -0
- data/{lib → addon}/buildr/openjpa.rb +23 -6
- data/addon/buildr/org/apache/buildr/JettyWrapper$1.class +0 -0
- data/addon/buildr/org/apache/buildr/JettyWrapper$BuildrHandler.class +0 -0
- data/addon/buildr/org/apache/buildr/JettyWrapper.class +0 -0
- data/{lib/buildr/jetty → addon/buildr/org/apache/buildr}/JettyWrapper.java +19 -0
- data/{lib → addon}/buildr/xmlbeans.rb +39 -14
- data/bin/buildr +21 -7
- data/buildr.gemspec +50 -0
- data/doc/css/default.css +225 -0
- data/doc/css/print.css +95 -0
- data/doc/css/syntax.css +43 -0
- data/doc/images/apache-incubator-logo.png +0 -0
- data/doc/images/buildr-hires.png +0 -0
- data/doc/images/buildr.png +0 -0
- data/doc/images/note.png +0 -0
- data/doc/images/tip.png +0 -0
- data/doc/images/zbuildr.tif +0 -0
- data/doc/pages/artifacts.textile +317 -0
- data/doc/pages/building.textile +501 -0
- data/doc/pages/contributing.textile +178 -0
- data/doc/pages/download.textile +25 -0
- data/doc/pages/extending.textile +229 -0
- data/doc/pages/getting_started.textile +337 -0
- data/doc/pages/index.textile +63 -0
- data/doc/pages/mailing_lists.textile +17 -0
- data/doc/pages/more_stuff.textile +367 -0
- data/doc/pages/packaging.textile +592 -0
- data/doc/pages/projects.textile +449 -0
- data/doc/pages/recipes.textile +127 -0
- data/doc/pages/settings_profiles.textile +339 -0
- data/doc/pages/testing.textile +475 -0
- data/doc/pages/troubleshooting.textile +121 -0
- data/doc/pages/whats_new.textile +389 -0
- data/doc/print.haml +52 -0
- data/doc/print.toc.yaml +28 -0
- data/doc/scripts/buildr-git.rb +411 -0
- data/doc/scripts/install-jruby.sh +44 -0
- data/doc/scripts/install-linux.sh +64 -0
- data/doc/scripts/install-osx.sh +52 -0
- data/doc/site.haml +55 -0
- data/doc/site.toc.yaml +44 -0
- data/lib/buildr.rb +28 -45
- data/lib/buildr/core.rb +27 -0
- data/lib/buildr/core/application.rb +373 -0
- data/lib/buildr/core/application_cli.rb +134 -0
- data/lib/{core → buildr/core}/build.rb +91 -77
- data/lib/{core → buildr/core}/checks.rb +116 -95
- data/lib/buildr/core/common.rb +155 -0
- data/lib/buildr/core/compile.rb +594 -0
- data/lib/buildr/core/environment.rb +120 -0
- data/lib/buildr/core/filter.rb +258 -0
- data/lib/{core → buildr/core}/generate.rb +22 -5
- data/lib/buildr/core/help.rb +118 -0
- data/lib/buildr/core/progressbar.rb +156 -0
- data/lib/{core → buildr/core}/project.rb +468 -213
- data/lib/buildr/core/test.rb +690 -0
- data/lib/{core → buildr/core}/transports.rb +107 -127
- data/lib/buildr/core/util.rb +235 -0
- data/lib/buildr/ide.rb +19 -0
- data/lib/{java → buildr/ide}/eclipse.rb +86 -60
- data/lib/{java → buildr/ide}/idea.ipr.template +16 -0
- data/lib/buildr/ide/idea.rb +194 -0
- data/lib/buildr/ide/idea7x.ipr.template +290 -0
- data/lib/buildr/ide/idea7x.rb +210 -0
- data/lib/buildr/java.rb +26 -0
- data/lib/buildr/java/ant.rb +71 -0
- data/lib/buildr/java/bdd_frameworks.rb +267 -0
- data/lib/buildr/java/commands.rb +210 -0
- data/lib/buildr/java/compilers.rb +432 -0
- data/lib/buildr/java/deprecated.rb +141 -0
- data/lib/buildr/java/groovyc.rb +137 -0
- data/lib/buildr/java/jruby.rb +99 -0
- data/lib/buildr/java/org/apache/buildr/BuildrNail$Main.class +0 -0
- data/lib/buildr/java/org/apache/buildr/BuildrNail.class +0 -0
- data/lib/buildr/java/org/apache/buildr/BuildrNail.java +41 -0
- data/lib/buildr/java/org/apache/buildr/JavaTestFilter.class +0 -0
- data/lib/buildr/java/org/apache/buildr/JavaTestFilter.java +116 -0
- data/lib/buildr/java/packaging.rb +706 -0
- data/lib/{java → buildr/java}/pom.rb +20 -4
- data/lib/buildr/java/rjb.rb +142 -0
- data/lib/buildr/java/test_frameworks.rb +290 -0
- data/lib/buildr/java/version_requirement.rb +172 -0
- data/lib/buildr/packaging.rb +21 -0
- data/lib/{java → buildr/packaging}/artifact.rb +170 -179
- data/lib/buildr/packaging/artifact_namespace.rb +957 -0
- data/lib/buildr/packaging/artifact_search.rb +140 -0
- data/lib/buildr/packaging/gems.rb +102 -0
- data/lib/buildr/packaging/package.rb +233 -0
- data/lib/{tasks → buildr/packaging}/tar.rb +18 -1
- data/lib/{tasks → buildr/packaging}/zip.rb +153 -105
- data/rakelib/apache.rake +126 -0
- data/rakelib/changelog.rake +56 -0
- data/rakelib/doc.rake +103 -0
- data/rakelib/package.rake +44 -0
- data/rakelib/release.rake +53 -0
- data/rakelib/rspec.rake +81 -0
- data/rakelib/rubyforge.rake +45 -0
- data/rakelib/scm.rake +49 -0
- data/rakelib/setup.rake +59 -0
- data/rakelib/stage.rake +45 -0
- data/spec/application_spec.rb +316 -0
- data/spec/archive_spec.rb +494 -0
- data/spec/artifact_namespace_spec.rb +635 -0
- data/spec/artifact_spec.rb +738 -0
- data/spec/build_spec.rb +193 -0
- data/spec/checks_spec.rb +537 -0
- data/spec/common_spec.rb +579 -0
- data/spec/compile_spec.rb +561 -0
- data/spec/groovy_compilers_spec.rb +239 -0
- data/spec/java_bdd_frameworks_spec.rb +238 -0
- data/spec/java_compilers_spec.rb +446 -0
- data/spec/java_packaging_spec.rb +1042 -0
- data/spec/java_test_frameworks_spec.rb +414 -0
- data/spec/packaging_helper.rb +63 -0
- data/spec/packaging_spec.rb +589 -0
- data/spec/project_spec.rb +739 -0
- data/spec/sandbox.rb +116 -0
- data/spec/scala_compilers_spec.rb +239 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helpers.rb +283 -0
- data/spec/test_spec.rb +871 -0
- data/spec/transport_spec.rb +300 -0
- data/spec/version_requirement_spec.rb +115 -0
- metadata +188 -77
- data/lib/buildr/cobertura.rb +0 -89
- data/lib/buildr/jdepend.rb +0 -40
- data/lib/buildr/jetty/JettyWrapper$1.class +0 -0
- data/lib/buildr/jetty/JettyWrapper$BuildrHandler.class +0 -0
- data/lib/buildr/jetty/JettyWrapper.class +0 -0
- data/lib/buildr/scala.rb +0 -368
- data/lib/core/application.rb +0 -188
- data/lib/core/common.rb +0 -562
- data/lib/core/help.rb +0 -72
- data/lib/core/rake_ext.rb +0 -81
- data/lib/java/ant.rb +0 -71
- data/lib/java/compile.rb +0 -589
- data/lib/java/idea.rb +0 -159
- data/lib/java/java.rb +0 -432
- data/lib/java/packaging.rb +0 -581
- data/lib/java/test.rb +0 -795
- 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
|
Binary file
|
Binary file
|
@@ -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
|
+
*/
|
Binary file
|
@@ -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
|