lucidimagination-warbler 1.3.2.dev

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. data/Gemfile +16 -0
  2. data/History.txt +217 -0
  3. data/LICENSE.txt +26 -0
  4. data/Manifest.txt +92 -0
  5. data/README.txt +255 -0
  6. data/Rakefile +103 -0
  7. data/bin/warble +11 -0
  8. data/ext/JarMain.java +148 -0
  9. data/ext/WarMain.java +112 -0
  10. data/ext/WarblerJar.java +182 -0
  11. data/ext/WarblerJarService.java +18 -0
  12. data/lib/warbler.rb +33 -0
  13. data/lib/warbler/application.rb +86 -0
  14. data/lib/warbler/config.rb +223 -0
  15. data/lib/warbler/gems.rb +37 -0
  16. data/lib/warbler/jar.rb +253 -0
  17. data/lib/warbler/task.rb +183 -0
  18. data/lib/warbler/templates/bundler.erb +3 -0
  19. data/lib/warbler/templates/config.erb +1 -0
  20. data/lib/warbler/templates/jar.erb +5 -0
  21. data/lib/warbler/templates/rack.erb +1 -0
  22. data/lib/warbler/templates/rails.erb +1 -0
  23. data/lib/warbler/templates/war.erb +1 -0
  24. data/lib/warbler/traits.rb +107 -0
  25. data/lib/warbler/traits/bundler.rb +104 -0
  26. data/lib/warbler/traits/gemspec.rb +59 -0
  27. data/lib/warbler/traits/jar.rb +56 -0
  28. data/lib/warbler/traits/merb.rb +35 -0
  29. data/lib/warbler/traits/nogemspec.rb +42 -0
  30. data/lib/warbler/traits/rack.rb +33 -0
  31. data/lib/warbler/traits/rails.rb +62 -0
  32. data/lib/warbler/traits/war.rb +197 -0
  33. data/lib/warbler/version.rb +10 -0
  34. data/lib/warbler/war.rb +8 -0
  35. data/lib/warbler_jar.jar +0 -0
  36. data/spec/drb_helper.rb +41 -0
  37. data/spec/sample_bundler/Gemfile.lock +10 -0
  38. data/spec/sample_bundler/config.ru +0 -0
  39. data/spec/sample_jar/History.txt +6 -0
  40. data/spec/sample_jar/Manifest.txt +8 -0
  41. data/spec/sample_jar/README.txt +30 -0
  42. data/spec/sample_jar/lib/sample_jar.rb +6 -0
  43. data/spec/sample_jar/sample_jar.gemspec +40 -0
  44. data/spec/sample_jar/test/test_sample_jar.rb +8 -0
  45. data/spec/sample_war/app/controllers/application.rb +15 -0
  46. data/spec/sample_war/app/helpers/application_helper.rb +3 -0
  47. data/spec/sample_war/config/boot.rb +109 -0
  48. data/spec/sample_war/config/database.yml +19 -0
  49. data/spec/sample_war/config/environment.rb +67 -0
  50. data/spec/sample_war/config/environments/development.rb +17 -0
  51. data/spec/sample_war/config/environments/production.rb +25 -0
  52. data/spec/sample_war/config/environments/test.rb +22 -0
  53. data/spec/sample_war/config/initializers/inflections.rb +10 -0
  54. data/spec/sample_war/config/initializers/mime_types.rb +5 -0
  55. data/spec/sample_war/config/initializers/new_rails_defaults.rb +15 -0
  56. data/spec/sample_war/config/routes.rb +41 -0
  57. data/spec/sample_war/lib/tasks/utils.rake +0 -0
  58. data/spec/sample_war/public/404.html +30 -0
  59. data/spec/sample_war/public/422.html +30 -0
  60. data/spec/sample_war/public/500.html +30 -0
  61. data/spec/sample_war/public/favicon.ico +0 -0
  62. data/spec/sample_war/public/index.html +274 -0
  63. data/spec/sample_war/public/robots.txt +5 -0
  64. data/spec/spec_helper.rb +112 -0
  65. data/spec/warbler/application_spec.rb +95 -0
  66. data/spec/warbler/bundler_spec.rb +136 -0
  67. data/spec/warbler/config_spec.rb +130 -0
  68. data/spec/warbler/gems_spec.rb +40 -0
  69. data/spec/warbler/jar_spec.rb +718 -0
  70. data/spec/warbler/task_spec.rb +170 -0
  71. data/spec/warbler/traits_spec.rb +17 -0
  72. data/spec/warbler/war_spec.rb +14 -0
  73. data/warble.rb +142 -0
  74. data/web.xml.erb +32 -0
  75. metadata +198 -0
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Copyright (c) 2010-2011 Engine Yard, Inc.
3
+ * Copyright (c) 2007-2009 Sun Microsystems, Inc.
4
+ * This source code is available under the MIT license.
5
+ * See the file LICENSE.txt for details.
6
+ */
7
+
8
+ import java.io.IOException;
9
+ import org.jruby.Ruby;
10
+ import org.jruby.runtime.load.BasicLibraryService;
11
+
12
+ public class WarblerJarService implements BasicLibraryService {
13
+ public boolean basicLoad(final Ruby runtime) throws IOException {
14
+ WarblerJar.create(runtime);
15
+ return true;
16
+ }
17
+ }
18
+
@@ -0,0 +1,33 @@
1
+ #--
2
+ # Copyright (c) 2010-2011 Engine Yard, Inc.
3
+ # Copyright (c) 2007-2009 Sun Microsystems, Inc.
4
+ # This source code is available under the MIT license.
5
+ # See the file LICENSE.txt for details.
6
+ #++
7
+
8
+ # Warbler is a lightweight, flexible, Rake-based system for packaging
9
+ # your Ruby applications into .jar or .war files.
10
+ module Warbler
11
+ WARBLER_HOME = File.expand_path(File.dirname(__FILE__) + '/..') unless defined?(WARBLER_HOME)
12
+
13
+ class << self
14
+ # An instance of Warbler::Application used by the +warble+ command.
15
+ attr_accessor :application
16
+ # Set Warbler.framework_detection to false to disable
17
+ # auto-detection based on application configuration.
18
+ attr_accessor :framework_detection
19
+ attr_writer :project_application
20
+ end
21
+
22
+ # Warbler loads the project Rakefile in a separate Rake application
23
+ # from the one where the Warbler tasks are run.
24
+ def self.project_application
25
+ application.load_project_rakefile if application
26
+ @project_application || Rake.application
27
+ end
28
+ self.framework_detection = true
29
+ end
30
+
31
+ require 'warbler/version'
32
+ require 'warbler/task'
33
+ require 'warbler/application'
@@ -0,0 +1,86 @@
1
+ #--
2
+ # Copyright (c) 2010-2011 Engine Yard, Inc.
3
+ # Copyright (c) 2007-2009 Sun Microsystems, Inc.
4
+ # This source code is available under the MIT license.
5
+ # See the file LICENSE.txt for details.
6
+ #++
7
+
8
+ require 'rake'
9
+
10
+ # Extension of Rake::Application that allows the +warble+ command to
11
+ # report its name properly and inject its own tasks without a
12
+ # Rakefile.
13
+ class Warbler::Application < Rake::Application
14
+ def initialize
15
+ super
16
+ Warbler.application = self
17
+ @project_loaded = false
18
+ end
19
+
20
+ # Sets the application name and loads Warbler's own tasks
21
+ def load_rakefile
22
+ @name = 'warble'
23
+
24
+ # Load the main warbler tasks
25
+ wt = Warbler::Task.new
26
+
27
+ task :default => wt.name
28
+
29
+ desc "Generate a configuration file to customize your archive"
30
+ task :config => "#{wt.name}:config"
31
+
32
+ desc "Install Warbler tasks in your Rails application"
33
+ task :pluginize => "#{wt.name}:pluginize"
34
+
35
+ desc "Feature: package gem repository inside a jar"
36
+ task :gemjar => "#{wt.name}:gemjar"
37
+
38
+ desc "Feature: make an executable archive"
39
+ task :executable => "#{wt.name}:executable"
40
+
41
+ desc "Feature: precompile all Ruby files"
42
+ task :compiled => "#{wt.name}:compiled"
43
+
44
+ desc "Display version of Warbler"
45
+ task :version => "#{wt.name}:version"
46
+ end
47
+
48
+ # Loads the project Rakefile in a separate application
49
+ def load_project_rakefile
50
+ return if @project_loaded
51
+ # Load any application rakefiles to aid in autodetecting applications
52
+ app = Warbler.project_application = Rake::Application.new
53
+ Rake.application = app
54
+ Rake::Application::DEFAULT_RAKEFILES.each do |rf|
55
+ if File.exist?(rf)
56
+ load rf
57
+ break
58
+ end
59
+ end
60
+ Rake.application = self
61
+ @project_loaded = true
62
+ end
63
+
64
+ # Run the application: The equivalent code for the +warble+ command
65
+ # is simply <tt>Warbler::Application.new.run</tt>.
66
+ def run
67
+ Rake.application = self
68
+ super
69
+ end
70
+
71
+ # Remap the version option to display Warbler version.
72
+ def standard_rake_options
73
+ super.map do |opt|
74
+ if opt.first == '--version'
75
+ ['--version', '-V', "Display the program version.",
76
+ lambda { |value|
77
+ puts "Warbler version #{Warbler::VERSION}"
78
+ exit
79
+ }
80
+ ]
81
+ else
82
+ opt
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,223 @@
1
+ #--
2
+ # Copyright (c) 2010-2011 Engine Yard, Inc.
3
+ # Copyright (c) 2007-2009 Sun Microsystems, Inc.
4
+ # This source code is available under the MIT license.
5
+ # See the file LICENSE.txt for details.
6
+ #++
7
+
8
+ require 'set'
9
+ require 'warbler/gems'
10
+ require 'warbler/traits'
11
+
12
+ module Warbler
13
+ # Warbler archive assembly configuration class.
14
+ class Config
15
+ TOP_DIRS = %w(app config lib log vendor)
16
+ FILE = "config/warble.rb"
17
+ BUILD_GEMS = %w(warbler rake rcov)
18
+
19
+ include Traits
20
+
21
+ # Features: additional options controlling how the jar is built.
22
+ # Currently the following features are supported:
23
+ # - gemjar: package the gem repository in a jar file in WEB-INF/lib
24
+ # - executable: embed a web server and make the war executable
25
+ # - compiled: compile .rb files to .class files
26
+ attr_accessor :features
27
+
28
+ # Traits: an array of trait classes corresponding to
29
+ # characteristics of the project that are either auto-detected or
30
+ # configured.
31
+ attr_accessor :traits
32
+
33
+ # Deprecated: No longer has any effect.
34
+ attr_accessor :staging_dir
35
+
36
+ # Directory where the war file will be written. Can be used to direct
37
+ # Warbler to place your war file directly in your application server's
38
+ # autodeploy directory. Defaults to the root of the application directory.
39
+ attr_accessor :autodeploy_dir
40
+
41
+ # Top-level directories to be copied into WEB-INF. Defaults to
42
+ # names in TOP_DIRS
43
+ attr_accessor :dirs
44
+
45
+ # Additional files beyond the top-level directories to include in the
46
+ # WEB-INF directory
47
+ attr_accessor :includes
48
+
49
+ # Files to exclude from the WEB-INF directory
50
+ attr_accessor :excludes
51
+
52
+ # Java classes and other files to copy to WEB-INF/classes
53
+ attr_accessor :java_classes
54
+
55
+ # Java libraries to copy to WEB-INF/lib
56
+ attr_accessor :java_libs
57
+
58
+ # Rubygems to install into the webapp.
59
+ attr_accessor :gems
60
+
61
+ # Whether to include dependent gems (default true)
62
+ attr_accessor :gem_dependencies
63
+
64
+ # Array of regular expressions matching relative paths in gems to
65
+ # be excluded from the war. Default contains no exclusions.
66
+ attr_accessor :gem_excludes
67
+
68
+ # Whether to exclude **/*.log files (default is true)
69
+ attr_accessor :exclude_logs
70
+
71
+ # Public HTML directory file list, to be copied into the root of the war
72
+ attr_accessor :public_html
73
+
74
+ # Container of pathmaps used for specifying source-to-destination transformations
75
+ # under various situations (<tt>public_html</tt> and <tt>java_classes</tt> are two
76
+ # entries in this structure).
77
+ attr_accessor :pathmaps
78
+
79
+ # Name of jar or war file (without the extension), defaults to the
80
+ # directory name containing the application.
81
+ attr_accessor :jar_name
82
+
83
+ # Extension of jar file. Defaults to <tt>jar</tt> or <tt>war</tt> depending on the project.
84
+ attr_accessor :jar_extension
85
+
86
+ # Name of a MANIFEST.MF template to use.
87
+ attr_accessor :manifest_file
88
+
89
+ # Files for WEB-INF directory (next to web.xml). Contains web.xml by default.
90
+ # If there are .erb files they will be processed with webxml config.
91
+ attr_accessor :webinf_files
92
+
93
+ # Use Bundler to locate gems if Gemfile is found. Default is true.
94
+ attr_accessor :bundler
95
+
96
+ # An array of Bundler groups to avoid including in the war file.
97
+ # Defaults to ["development", "test"].
98
+ attr_accessor :bundle_without
99
+
100
+ # Path to the pre-bundled gem directory inside the war file. Default is '/WEB-INF/gems'.
101
+ # This also sets 'gem.path' inside web.xml.
102
+ attr_accessor :gem_path
103
+
104
+ # List of ruby files to compile to class files. Default is to
105
+ # compile all .rb files in the application.
106
+ attr_accessor :compiled_ruby_files
107
+
108
+ # Warbler writes an "init" file into the war at this location. JRuby-Rack and possibly other
109
+ # launchers may use this to initialize the Ruby environment.
110
+ attr_accessor :init_filename
111
+
112
+ # Array containing filenames or StringIO's to be concatenated together to form the init file.
113
+ # If the filename ends in .erb the file will be expanded the same way web.xml.erb is; see below.
114
+ attr_accessor :init_contents
115
+
116
+ # Extra configuration for web.xml. Controls how the dynamically-generated web.xml
117
+ # file is generated.
118
+ #
119
+ # * <tt>webxml.jndi</tt> -- the name of one or more JNDI data sources name to be
120
+ # available to the application. Places appropriate &lt;resource-ref&gt; entries
121
+ # in the file.
122
+ # * <tt>webxml.ignored</tt> -- array of key names that will be not used to
123
+ # generate a context param. Defaults to ['jndi', 'booter']
124
+ #
125
+ # Any other key/value pair placed in the open structure will be dumped as a
126
+ # context parameter in the web.xml file. Some of the recognized values are:
127
+ #
128
+ # * <tt>webxml.rails.env</tt> -- the Rails environment to use for the
129
+ # running application, usually either development or production (the
130
+ # default).
131
+ # * <tt>webxml.gem.path</tt> -- the path to your bundled gem directory
132
+ # * <tt>webxml.jruby.min.runtimes</tt> -- minimum number of pooled runtimes to
133
+ # keep around during idle time
134
+ # * <tt>webxml.jruby.max.runtimes</tt> -- maximum number of pooled Rails
135
+ # application runtimes
136
+ #
137
+ # Note that if you attempt to access webxml configuration keys in a conditional,
138
+ # you might not obtain the result you want. For example:
139
+ # <%= webxml.maybe.present.key || 'default' %>
140
+ # doesn't yield the right result. Instead, you need to generate the context parameters:
141
+ # <%= webxml.context_params['maybe.present.key'] || 'default' %>
142
+ attr_accessor :webxml
143
+
144
+ attr_reader :warbler_templates
145
+
146
+ def initialize(warbler_home = WARBLER_HOME)
147
+ super()
148
+
149
+ @warbler_home = warbler_home
150
+ @warbler_templates = "#{WARBLER_HOME}/lib/warbler/templates"
151
+ @features = Set.new
152
+ @dirs = TOP_DIRS.select {|d| File.directory?(d)}
153
+ @includes = FileList[]
154
+ @excludes = FileList[]
155
+ @java_libs = FileList[]
156
+ @java_classes = FileList[]
157
+ @gems = Warbler::Gems.new
158
+ @gem_dependencies = true
159
+ @gem_excludes = []
160
+ @exclude_logs = true
161
+ @public_html = FileList[]
162
+ @jar_name = File.basename(Dir.getwd)
163
+ @jar_extension = 'jar'
164
+ @webinf_files = FileList[]
165
+ @init_filename = 'META-INF/init.rb'
166
+ @init_contents = ["#{@warbler_templates}/config.erb"]
167
+
168
+ before_configure
169
+ yield self if block_given?
170
+ after_configure
171
+
172
+ @compiled_ruby_files ||= FileList[*@dirs.map {|d| "#{d}/**/*.rb"}]
173
+
174
+ @excludes += ["tmp/war"] if File.directory?("tmp/war")
175
+ @excludes += warbler_vendor_excludes(warbler_home)
176
+ @excludes += FileList["**/*.log"] if @exclude_logs
177
+ end
178
+
179
+ def gems=(value)
180
+ @gems = Warbler::Gems.new(value)
181
+ end
182
+
183
+ def relative_gem_path
184
+ @gem_path[1..-1]
185
+ end
186
+
187
+ def define_tasks
188
+ task "gemjar" do
189
+ self.features << "gemjar"
190
+ end
191
+ task "executable" do
192
+ self.features << "executable"
193
+ end
194
+ end
195
+
196
+ # Deprecated
197
+ def war_name
198
+ $stderr.puts "config.war_name deprecated; replace with config.jar_name" #:nocov:
199
+ jar_name #:nocov:
200
+ end
201
+
202
+ # Deprecated
203
+ def war_name=(w)
204
+ $stderr.puts "config.war_name deprecated; replace with config.jar_name" #:nocov:
205
+ self.jar_name = w #:nocov:
206
+ end
207
+
208
+ private
209
+ def warbler_vendor_excludes(warbler_home)
210
+ warbler = File.expand_path(warbler_home)
211
+ if warbler =~ %r{^#{Dir.getwd}/(.*)}
212
+ FileList["#{$1}"]
213
+ else
214
+ []
215
+ end
216
+ end
217
+
218
+ def dump
219
+ YAML::dump(self.dup.tap{|c| c.dump_traits })
220
+ end
221
+ public :dump
222
+ end
223
+ end
@@ -0,0 +1,37 @@
1
+ #--
2
+ # Copyright (c) 2010-2011 Engine Yard, Inc.
3
+ # Copyright (c) 2007-2009 Sun Microsystems, Inc.
4
+ # This source code is available under the MIT license.
5
+ # See the file LICENSE.txt for details.
6
+ #++
7
+
8
+ module Warbler
9
+ # A set of gems. This only exists to allow expected operations
10
+ # to be used to add gems, and for backwards compatibility.
11
+ # It would be easier to just use a hash.
12
+ class Gems < Hash
13
+ ANY_VERSION = nil
14
+
15
+ def initialize(gems = nil)
16
+ if gems.is_a?(Hash)
17
+ self.merge!(gems)
18
+ elsif gems.is_a?(Array)
19
+ gems.each {|gem| self << gem }
20
+ end
21
+ end
22
+
23
+ def <<(gem)
24
+ self[gem] ||= ANY_VERSION
25
+ end
26
+
27
+ def +(other)
28
+ other.each {|g| self[g] ||= ANY_VERSION }
29
+ self
30
+ end
31
+
32
+ def -(other)
33
+ other.each {|g| self.delete(g)}
34
+ self
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,253 @@
1
+ #--
2
+ # Copyright (c) 2010-2011 Engine Yard, Inc.
3
+ # Copyright (c) 2007-2009 Sun Microsystems, Inc.
4
+ # This source code is available under the MIT license.
5
+ # See the file LICENSE.txt for details.
6
+ #++
7
+
8
+ require 'zip/zip'
9
+ require 'stringio'
10
+ require 'pathname'
11
+
12
+ module Warbler
13
+ # Class that holds the files that will be stored in the jar file.
14
+ # The #files attribute contains a hash of pathnames inside the jar
15
+ # file to their contents. Contents can be one of:
16
+ # * +nil+ representing a directory entry
17
+ # * Any object responding to +read+ representing an in-memory blob
18
+ # * A String filename pointing to a file on disk
19
+ class Jar
20
+ DEFAULT_MANIFEST = %{Manifest-Version: 1.0\nCreated-By: Warbler #{Warbler::VERSION}\n\n}
21
+
22
+ attr_reader :files
23
+ attr_reader :app_filelist
24
+
25
+ def initialize
26
+ @files = {}
27
+ end
28
+
29
+ def contents(entry)
30
+ file = files[entry]
31
+ file.respond_to?(:read) ? file.read : File.open(file) {|f| f.read }
32
+ end
33
+
34
+ def compile(config)
35
+ # Compiling all Ruby files we can find -- do we need to allow an
36
+ # option to configure what gets compiled?
37
+ return if config.compiled_ruby_files.nil? || config.compiled_ruby_files.empty?
38
+
39
+ run_javac(config, config.compiled_ruby_files)
40
+ replace_compiled_ruby_files(config, config.compiled_ruby_files)
41
+ end
42
+
43
+ def run_javac(config, compiled_ruby_files)
44
+ # Need to use the version of JRuby in the application to compile it
45
+ %x{java -classpath #{config.java_libs.join(File::PATH_SEPARATOR)} org.jruby.Main -S jrubyc \"#{compiled_ruby_files.join('" "')}\"}
46
+ end
47
+
48
+ def replace_compiled_ruby_files(config, compiled_ruby_files)
49
+ # Exclude the rb files and recreate them. This
50
+ # prevents the original contents being used.
51
+ config.excludes += compiled_ruby_files
52
+
53
+ compiled_ruby_files.each do |ruby_source|
54
+ files[apply_pathmaps(config, ruby_source, :application)] = StringIO.new("require __FILE__.sub(/\.rb$/, '.class')")
55
+ end
56
+ end
57
+
58
+ # Apply the information in a Warbler::Config object in order to
59
+ # look for files to put into this war file.
60
+ def apply(config)
61
+ find_application_files(config)
62
+ find_java_libs(config)
63
+ find_java_classes(config)
64
+ find_gems_files(config)
65
+ add_manifest(config)
66
+ add_init_file(config)
67
+ apply_traits(config)
68
+ end
69
+
70
+ # Create the jar or war file. The single argument can either be a
71
+ # Warbler::Config or a filename of the file to create.
72
+ def create(config_or_path)
73
+ path = config_or_path
74
+ if Warbler::Config === config_or_path
75
+ path = "#{config_or_path.jar_name}.#{config_or_path.jar_extension}"
76
+ path = File.join(config_or_path.autodeploy_dir, path) if config_or_path.autodeploy_dir
77
+ end
78
+ rm_f path
79
+ ensure_directory_entries
80
+ puts "Creating #{path}"
81
+ create_jar path, @files
82
+ end
83
+
84
+ # Invoke a hook to allow the project traits to add or modify the archive contents.
85
+ def apply_traits(config)
86
+ config.update_archive(self)
87
+ end
88
+
89
+ # Add a manifest file either from config or by making a default manifest.
90
+ def add_manifest(config = nil)
91
+ unless @files.keys.detect{|k| k =~ /^META-INF\/MANIFEST\.MF$/i}
92
+ if config && config.manifest_file
93
+ @files['META-INF/MANIFEST.MF'] = config.manifest_file
94
+ else
95
+ @files['META-INF/MANIFEST.MF'] = StringIO.new(DEFAULT_MANIFEST)
96
+ end
97
+ end
98
+ end
99
+
100
+ # Add java libraries to WEB-INF/lib.
101
+ def find_java_libs(config)
102
+ config.java_libs.map {|lib| add_with_pathmaps(config, lib, :java_libs) }
103
+ end
104
+
105
+ # Add java classes to WEB-INF/classes.
106
+ def find_java_classes(config)
107
+ config.java_classes.map {|f| add_with_pathmaps(config, f, :java_classes) }
108
+ end
109
+
110
+ # Add gems to WEB-INF/gems
111
+ def find_gems_files(config)
112
+ config.gems.each {|gem, version| find_single_gem_files(config, gem, version) }
113
+ end
114
+
115
+ # Add a single gem to WEB-INF/gems
116
+ def find_single_gem_files(config, gem_pattern, version = nil)
117
+ if Gem::Specification === gem_pattern
118
+ spec = gem_pattern
119
+ else
120
+ gem = case gem_pattern
121
+ when Gem::Dependency
122
+ gem_pattern
123
+ else
124
+ Gem::Dependency.new(gem_pattern, Gem::Requirement.create(version))
125
+ end
126
+
127
+ # skip development dependencies
128
+ return if gem.respond_to?(:type) and gem.type != :runtime
129
+
130
+ matched = Gem.source_index.search(gem)
131
+ fail "gem '#{gem}' not installed" if matched.empty?
132
+ spec = matched.last
133
+ end
134
+
135
+ full_gem_path = Pathname.new(spec.full_gem_path)
136
+
137
+ # skip gems whose full_gem_path does not exist
138
+ ($stderr.puts "warning: skipping #{spec.name} (#{full_gem_path.to_s} does not exist)" ; return) unless full_gem_path.exist?
139
+
140
+ @files[apply_pathmaps(config, "#{spec.full_name}.gemspec", :gemspecs)] = StringIO.new(spec.to_ruby)
141
+ FileList["#{full_gem_path.to_s}/**/*"].each do |src|
142
+ f = Pathname.new(src).relative_path_from(full_gem_path).to_s
143
+ next if config.gem_excludes && config.gem_excludes.any? {|rx| f =~ rx }
144
+ @files[apply_pathmaps(config, File.join(spec.full_name, f), :gems)] = src
145
+ end
146
+
147
+ spec.dependencies.each {|dep| find_single_gem_files(config, dep) } if config.gem_dependencies
148
+ end
149
+
150
+ # Add all application directories and files to the archive.
151
+ def find_application_files(config)
152
+ config.dirs.select do |d|
153
+ exists = File.directory?(d)
154
+ $stderr.puts "warning: application directory `#{d}' does not exist or is not a directory; skipping" unless exists
155
+ exists
156
+ end.each do |d|
157
+ @files[apply_pathmaps(config, d, :application)] = nil
158
+ end
159
+ @app_filelist = FileList[*(config.dirs.map{|d| "#{d}/**/*"})]
160
+ @app_filelist.include *(config.includes.to_a)
161
+ @app_filelist.exclude *(config.excludes.to_a)
162
+ @app_filelist.map {|f| add_with_pathmaps(config, f, :application) }
163
+ end
164
+
165
+ # Add init.rb file to the war file.
166
+ def add_init_file(config)
167
+ if config.init_contents
168
+ contents = ''
169
+ config.init_contents.each do |file|
170
+ if file.respond_to?(:read)
171
+ contents << file.read
172
+ elsif File.extname(file) == '.erb'
173
+ contents << expand_erb(file, config).read
174
+ else
175
+ contents << File.read(file)
176
+ end
177
+ end
178
+ @files[config.init_filename] = StringIO.new(contents)
179
+ end
180
+ end
181
+
182
+ def add_with_pathmaps(config, f, map_type)
183
+ @files[apply_pathmaps(config, f, map_type)] = f
184
+ end
185
+
186
+ def expand_erb(file, config)
187
+ require 'erb'
188
+ erb = ERB.new(File.open(file) {|f| f.read })
189
+ StringIO.new(erb.result(erb_binding(config)))
190
+ end
191
+
192
+ def erb_binding(config)
193
+ webxml = config.webxml
194
+ binding
195
+ end
196
+
197
+ def apply_pathmaps(config, file, pathmaps)
198
+ file = file[2..-1] if file =~ /^\.\//
199
+ pathmaps = config.pathmaps.send(pathmaps)
200
+ pathmaps.each do |p|
201
+ file = file.pathmap(p)
202
+ end if pathmaps
203
+ file
204
+ end
205
+
206
+ def ensure_directory_entries
207
+ files.select {|k,v| !v.nil? }.each do |k,v|
208
+ dir = File.dirname(k)
209
+ while dir != "." && !files.has_key?(dir)
210
+ files[dir] = nil
211
+ dir = File.dirname(dir)
212
+ end
213
+ end
214
+ end
215
+
216
+ def create_jar(war_file, entries)
217
+ Zip::ZipFile.open(war_file, Zip::ZipFile::CREATE) do |zipfile|
218
+ entries.keys.sort.each do |entry|
219
+ src = entries[entry]
220
+ if src.respond_to?(:read)
221
+ zipfile.get_output_stream(entry) {|f| f << src.read }
222
+ elsif src.nil? || File.directory?(src)
223
+ $stderr.puts "directory symlinks are not followed unless using JRuby; #{entry} contents not in archive" \
224
+ if File.symlink?(entry) && !defined?(JRUBY_VERSION)
225
+ zipfile.mkdir(entry)
226
+ elsif File.symlink?(src)
227
+ zipfile.get_output_stream(entry) {|f| f << File.read(src) }
228
+ else
229
+ zipfile.add(entry, src)
230
+ end
231
+ end
232
+ end
233
+ end
234
+
235
+ def entry_in_jar(jar, entry)
236
+ Zip::ZipFile.open(jar) do |zf|
237
+ zf.get_input_stream(entry) {|io| StringIO.new(io.read) }
238
+ end
239
+ end
240
+
241
+ # Java-boosted jar creation for JRuby; replaces #create_jar and
242
+ # #entry_in_jar with Java version
243
+ require 'warbler_jar' if defined?(JRUBY_VERSION) && JRUBY_VERSION >= "1.5"
244
+ end
245
+
246
+ # Warbler::War is Deprecated. Please use Warbler::Jar.
247
+ class War < Jar
248
+ def initialize(*)
249
+ super
250
+ $stderr.puts "Warbler::War is deprecated. Please replace all occurrences with Warbler::Jar."
251
+ end
252
+ end
253
+ end