warbler 1.2.1 → 1.3.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/Gemfile +8 -5
  2. data/History.txt +5 -0
  3. data/Manifest.txt +43 -23
  4. data/README.txt +67 -26
  5. data/Rakefile +17 -6
  6. data/ext/JarMain.java +147 -0
  7. data/ext/{Main.java → WarMain.java} +4 -4
  8. data/ext/{WarblerWar.java → WarblerJar.java} +79 -13
  9. data/ext/{WarblerWarService.java → WarblerJarService.java} +2 -2
  10. data/lib/warbler/application.rb +9 -9
  11. data/lib/warbler/config.rb +58 -204
  12. data/lib/warbler/gems.rb +2 -2
  13. data/lib/warbler/jar.rb +247 -0
  14. data/lib/warbler/task.rb +28 -60
  15. data/lib/warbler/templates/config.erb +1 -1
  16. data/lib/warbler/templates/rack.erb +1 -1
  17. data/lib/warbler/templates/rails.erb +1 -1
  18. data/lib/warbler/traits/bundler.rb +58 -0
  19. data/lib/warbler/traits/gemspec.rb +64 -0
  20. data/lib/warbler/traits/jar.rb +53 -0
  21. data/lib/warbler/traits/merb.rb +34 -0
  22. data/lib/warbler/traits/nogemspec.rb +41 -0
  23. data/lib/warbler/traits/rack.rb +31 -0
  24. data/lib/warbler/traits/rails.rb +57 -0
  25. data/lib/warbler/traits/war.rb +191 -0
  26. data/lib/warbler/traits.rb +105 -0
  27. data/lib/warbler/version.rb +1 -1
  28. data/lib/warbler/war.rb +1 -247
  29. data/lib/warbler.rb +2 -5
  30. data/lib/warbler_jar.jar +0 -0
  31. data/spec/sample_jar/History.txt +6 -0
  32. data/spec/sample_jar/Manifest.txt +8 -0
  33. data/spec/sample_jar/README.txt +30 -0
  34. data/spec/sample_jar/lib/sample_jar.rb +6 -0
  35. data/spec/sample_jar/sample_jar.gemspec +41 -0
  36. data/spec/sample_jar/test/test_sample_jar.rb +8 -0
  37. data/spec/{sample → sample_war}/app/controllers/application.rb +0 -0
  38. data/spec/{sample → sample_war}/app/helpers/application_helper.rb +0 -0
  39. data/spec/{sample → sample_war}/config/boot.rb +0 -0
  40. data/spec/{sample → sample_war}/config/database.yml +0 -0
  41. data/spec/{sample → sample_war}/config/environment.rb +0 -0
  42. data/spec/{sample → sample_war}/config/environments/development.rb +0 -0
  43. data/spec/{sample → sample_war}/config/environments/production.rb +0 -0
  44. data/spec/{sample → sample_war}/config/environments/test.rb +0 -0
  45. data/spec/{sample → sample_war}/config/initializers/inflections.rb +0 -0
  46. data/spec/{sample → sample_war}/config/initializers/mime_types.rb +0 -0
  47. data/spec/{sample → sample_war}/config/initializers/new_rails_defaults.rb +0 -0
  48. data/spec/{sample → sample_war}/config/routes.rb +0 -0
  49. data/spec/{sample → sample_war}/lib/tasks/utils.rake +0 -0
  50. data/spec/{sample → sample_war}/public/404.html +0 -0
  51. data/spec/{sample → sample_war}/public/422.html +0 -0
  52. data/spec/{sample → sample_war}/public/500.html +0 -0
  53. data/spec/{sample → sample_war}/public/favicon.ico +0 -0
  54. data/spec/{sample → sample_war}/public/index.html +0 -0
  55. data/spec/{sample → sample_war}/public/robots.txt +0 -0
  56. data/spec/spec_helper.rb +40 -0
  57. data/spec/warbler/application_spec.rb +2 -9
  58. data/spec/warbler/config_spec.rb +101 -83
  59. data/spec/warbler/jar_spec.rb +763 -0
  60. data/spec/warbler/task_spec.rb +56 -41
  61. data/spec/warbler/traits_spec.rb +16 -0
  62. data/spec/warbler/war_spec.rb +2 -492
  63. data/warble.rb +36 -32
  64. metadata +57 -35
  65. data/lib/warbler_war.jar +0 -0
@@ -22,27 +22,27 @@ class Warbler::Application < Rake::Application
22
22
  @name = 'warble'
23
23
 
24
24
  # Load the main warbler tasks
25
- Warbler::Task.new
25
+ wt = Warbler::Task.new
26
26
 
27
- task :default => :war
27
+ task :default => wt.name
28
28
 
29
- desc "Generate a configuration file to customize your war"
30
- task :config => "war:config"
29
+ desc "Generate a configuration file to customize your archive"
30
+ task :config => "#{wt.name}:config"
31
31
 
32
32
  desc "Install Warbler tasks in your Rails application"
33
- task :pluginize => "war:pluginize"
33
+ task :pluginize => "#{wt.name}:pluginize"
34
34
 
35
35
  desc "Feature: package gem repository inside a jar"
36
- task :gemjar => "war:gemjar"
36
+ task :gemjar => "#{wt.name}:gemjar"
37
37
 
38
38
  desc "Feature: make an executable archive"
39
- task :executable => "war:executable"
39
+ task :executable => "#{wt.name}:executable"
40
40
 
41
41
  desc "Feature: precompile all Ruby files"
42
- task :compiled => "war:compiled"
42
+ task :compiled => "#{wt.name}:compiled"
43
43
 
44
44
  desc "Display version of Warbler"
45
- task :version => "war:version"
45
+ task :version => "#{wt.name}:version"
46
46
  end
47
47
 
48
48
  # Loads the project Rakefile in a separate application
@@ -5,16 +5,19 @@
5
5
  # See the file LICENSE.txt for details.
6
6
  #++
7
7
 
8
- require 'ostruct'
8
+ require 'set'
9
+ require 'warbler/gems'
10
+ require 'warbler/traits'
9
11
 
10
12
  module Warbler
11
- # Warbler war file assembly configuration class.
13
+ # Warbler archive assembly configuration class.
12
14
  class Config
13
15
  TOP_DIRS = %w(app config lib log vendor)
14
16
  FILE = "config/warble.rb"
15
- DEFAULT_GEM_PATH = '/WEB-INF/gems'
16
17
  BUILD_GEMS = %w(warbler rake rcov)
17
18
 
19
+ include Traits
20
+
18
21
  # Features: additional options controlling how the jar is built.
19
22
  # Currently the following features are supported:
20
23
  # - gemjar: package the gem repository in a jar file in WEB-INF/lib
@@ -22,6 +25,11 @@ module Warbler
22
25
  # - compiled: compile .rb files to .class files
23
26
  attr_accessor :features
24
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
+
25
33
  # Deprecated: No longer has any effect.
26
34
  attr_accessor :staging_dir
27
35
 
@@ -68,9 +76,12 @@ module Warbler
68
76
  # entries in this structure).
69
77
  attr_accessor :pathmaps
70
78
 
71
- # Name of war file (without the .war), defaults to the directory name containing
72
- # the Rails application
73
- attr_accessor :war_name
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
74
85
 
75
86
  # Name of a MANIFEST.MF template to use.
76
87
  attr_accessor :manifest_file
@@ -130,39 +141,36 @@ module Warbler
130
141
  # <%= webxml.context_params['maybe.present.key'] || 'default' %>
131
142
  attr_accessor :webxml
132
143
 
144
+ attr_reader :warbler_templates
145
+
133
146
  def initialize(warbler_home = WARBLER_HOME)
134
- @warbler_home = warbler_home
147
+ super()
148
+
149
+ @warbler_home = warbler_home
135
150
  @warbler_templates = "#{WARBLER_HOME}/lib/warbler/templates"
136
- @features = []
137
- @dirs = TOP_DIRS.select {|d| File.directory?(d)}
138
- @includes = FileList[]
139
- @excludes = FileList[]
140
- @java_libs = default_jar_files
141
- @java_classes = FileList[]
142
- @gems = Warbler::Gems.new
143
- @gem_path = DEFAULT_GEM_PATH
144
- @gem_dependencies = true
145
- @gem_excludes = []
146
- @exclude_logs = true
147
- @public_html = FileList["public/**/*"]
148
- @pathmaps = default_pathmaps
149
- @webxml = default_webxml_config
150
- @rails_root = default_rails_root
151
- @war_name = File.basename(@rails_root)
152
- @bundler = true
153
- @bundle_without = ["development", "test"]
154
- @webinf_files = default_webinf_files
155
- @init_filename = 'META-INF/init.rb'
156
- @init_contents = ["#{@warbler_templates}/config.erb"]
157
-
158
- auto_detect_frameworks
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
159
169
  yield self if block_given?
160
- update_gem_path
161
- detect_bundler_gems
170
+ after_configure
162
171
 
163
- framework_init = "#{@warbler_templates}/#{@webxml.booter}.erb"
164
- @init_contents << framework_init if File.exist?(framework_init)
165
172
  @compiled_ruby_files ||= FileList[*@dirs.map {|d| "#{d}/**/*.rb"}]
173
+
166
174
  @excludes += ["tmp/war"] if File.directory?("tmp/war")
167
175
  @excludes += warbler_vendor_excludes(warbler_home)
168
176
  @excludes += FileList["**/*.log"] if @exclude_logs
@@ -176,185 +184,31 @@ module Warbler
176
184
  @gem_path[1..-1]
177
185
  end
178
186
 
187
+ # Deprecated
188
+ def war_name
189
+ warn "config.war_name deprecated; replace with config.jar_name" #:nocov:
190
+ jar_name #:nocov:
191
+ end
192
+
193
+ # Deprecated
194
+ def war_name=(w)
195
+ warn "config.war_name deprecated; replace with config.jar_name" #:nocov:
196
+ self.jar_name = w #:nocov:
197
+ end
198
+
179
199
  private
180
200
  def warbler_vendor_excludes(warbler_home)
181
201
  warbler = File.expand_path(warbler_home)
182
- if warbler =~ %r{^#{@rails_root}/(.*)}
202
+ if warbler =~ %r{^#{Dir.getwd}/(.*)}
183
203
  FileList["#{$1}"]
184
204
  else
185
205
  []
186
206
  end
187
207
  end
188
208
 
189
- def default_pathmaps
190
- p = OpenStruct.new
191
- p.public_html = ["%{public/,}p"]
192
- p.java_libs = ["WEB-INF/lib/%f"]
193
- p.java_classes = ["WEB-INF/classes/%p"]
194
- p.application = ["WEB-INF/%p"]
195
- p.webinf = ["WEB-INF/%{.erb$,}f"]
196
- p.gemspecs = ["#{relative_gem_path}/specifications/%f"]
197
- p.gems = ["#{relative_gem_path}/gems/%p"]
198
- p
199
- end
200
-
201
- def default_webxml_config
202
- c = WebxmlOpenStruct.new
203
- c.rails.env = ENV['RAILS_ENV'] || 'production'
204
- c.public.root = '/'
205
- c.jndi = nil
206
- c.ignored = %w(jndi booter)
207
- c
208
- end
209
-
210
- def default_rails_root
211
- File.expand_path(defined?(Rails.root) ? Rails.root : (defined?(RAILS_ROOT) ? RAILS_ROOT : Dir.getwd))
212
- end
213
-
214
- def default_webinf_files
215
- webxml = if File.exist?("config/web.xml")
216
- "config/web.xml"
217
- elsif File.exist?("config/web.xml.erb")
218
- "config/web.xml.erb"
219
- else
220
- "#{WARBLER_HOME}/web.xml.erb"
221
- end
222
- FileList[webxml]
223
- end
224
-
225
- def update_gem_path
226
- if @gem_path != DEFAULT_GEM_PATH
227
- @gem_path = "/#{@gem_path}" unless @gem_path =~ %r{^/}
228
- sub_gem_path = @gem_path[1..-1]
229
- @pathmaps.gemspecs.each {|p| p.sub!(DEFAULT_GEM_PATH[1..-1], sub_gem_path)}
230
- @pathmaps.gems.each {|p| p.sub!(DEFAULT_GEM_PATH[1..-1], sub_gem_path)}
231
- @webxml["gem"]["path"] = @gem_path
232
- end
233
- end
234
-
235
- def detect_bundler_gems
236
- if @bundler && File.exist?("Gemfile")
237
- @gems.clear
238
- @gem_dependencies = false # Bundler takes care of these
239
- require 'bundler'
240
- gemfile = Pathname.new("Gemfile").expand_path
241
- root = gemfile.dirname
242
- lockfile = root.join('Gemfile.lock')
243
- definition = Bundler::Definition.build(gemfile, lockfile, nil)
244
- groups = definition.groups - @bundle_without.map {|g| g.to_sym}
245
- definition.specs_for(groups).each {|spec| @gems << spec }
246
- @init_contents << StringIO.new("ENV['BUNDLE_WITHOUT'] = '#{@bundle_without.join(':')}'\n")
247
- else
248
- @bundler = false
249
- end
250
- end
251
-
252
- def default_jar_files
253
- require 'jruby-jars'
254
- require 'jruby-rack'
255
- FileList[JRubyJars.core_jar_path, JRubyJars.stdlib_jar_path, JRubyJars.jruby_rack_jar_path]
256
- end
257
-
258
- def auto_detect_frameworks
259
- return unless Warbler.framework_detection
260
- auto_detect_rails || auto_detect_merb || auto_detect_rackup
261
- end
262
-
263
- def auto_detect_rails
264
- return false unless task = Warbler.project_application.lookup("environment")
265
- task.invoke rescue nil
266
- return false unless defined?(::Rails)
267
- @dirs << "tmp" if File.directory?("tmp")
268
- @webxml.booter = :rails
269
- unless (defined?(Rails.vendor_rails?) && Rails.vendor_rails?) || File.directory?("vendor/rails")
270
- @gems["rails"] = Rails::VERSION::STRING
271
- end
272
- if defined?(Rails.configuration.gems)
273
- Rails.configuration.gems.each do |g|
274
- @gems << Gem::Dependency.new(g.name, g.requirement) if Dir["vendor/gems/#{g.name}*"].empty?
275
- end
276
- end
277
- if defined?(Rails.configuration.threadsafe!) &&
278
- (defined?(Rails.configuration.allow_concurrency) && # Rails 3
279
- Rails.configuration.allow_concurrency && Rails.configuration.preload_frameworks) ||
280
- (defined?(Rails.configuration.action_controller.allow_concurrency) && # Rails 2
281
- Rails.configuration.action_controller.allow_concurrency && Rails.configuration.action_controller.preload_frameworks)
282
- @webxml.jruby.max.runtimes = 1
283
- end
284
- true
285
- end
286
-
287
- def auto_detect_merb
288
- return false unless task = Warbler.project_application.lookup("merb_env")
289
- task.invoke rescue nil
290
- return false unless defined?(::Merb)
291
- @webxml.booter = :merb
292
- if defined?(Merb::BootLoader::Dependencies.dependencies)
293
- Merb::BootLoader::Dependencies.dependencies.each {|g| @gems << g }
294
- else
295
- warn "unable to auto-detect Merb dependencies; upgrade to Merb 1.0 or greater"
296
- end
297
- true
298
- end
299
-
300
- def auto_detect_rackup
301
- return false unless File.exist?("config.ru") || !Dir['*/config.ru'].empty?
302
- @webxml.booter = :rack
303
- @webinf_files += [FileList['config.ru', '*/config.ru'].detect {|f| File.exist?(f)}]
304
- true
305
- end
306
- end
307
-
308
- # Helper class for holding arbitrary config.webxml values for injecting into +web.xml+.
309
- class WebxmlOpenStruct < OpenStruct
310
- %w(java com org javax gem).each {|name| undef_method name if Object.methods.include?(name) }
311
-
312
- def initialize(key = 'webxml')
313
- @key = key
314
- @table = Hash.new {|h,k| h[k] = WebxmlOpenStruct.new(k) }
315
- end
316
-
317
- def servlet_context_listener
318
- case self.booter
319
- when :rack
320
- "org.jruby.rack.RackServletContextListener"
321
- when :merb
322
- "org.jruby.rack.merb.MerbServletContextListener"
323
- else # :rails, default
324
- "org.jruby.rack.rails.RailsServletContextListener"
325
- end
326
- end
327
-
328
- def [](key)
329
- new_ostruct_member(key)
330
- send(key)
331
- end
332
-
333
- def []=(key, value)
334
- new_ostruct_member(key)
335
- send("#{key}=", value)
336
- end
337
-
338
- def context_params(escape = true)
339
- require 'cgi'
340
- params = {}
341
- @table.each do |k,v|
342
- case v
343
- when WebxmlOpenStruct
344
- nested_params = v.context_params
345
- nested_params.each do |nk,nv|
346
- params["#{escape ? CGI::escapeHTML(k.to_s) : k.to_s}.#{nk}"] = nv
347
- end
348
- else
349
- params[escape ? CGI::escapeHTML(k.to_s) : k.to_s] = escape ? CGI::escapeHTML(v.to_s) : v.to_s
350
- end
351
- end
352
- params.delete_if {|k,v| ['ignored', *ignored].include?(k.to_s) }
353
- params
354
- end
355
-
356
- def to_s
357
- "No value for '#@key' found"
209
+ def dump
210
+ YAML::dump(self.dup.tap{|c| c.dump_traits })
358
211
  end
212
+ public :dump
359
213
  end
360
214
  end
data/lib/warbler/gems.rb CHANGED
@@ -11,7 +11,7 @@ module Warbler
11
11
  # It would be easier to just use a hash.
12
12
  class Gems < Hash
13
13
  ANY_VERSION = nil
14
-
14
+
15
15
  def initialize(gems = nil)
16
16
  if gems.is_a?(Hash)
17
17
  self.merge!(gems)
@@ -19,7 +19,7 @@ module Warbler
19
19
  gems.each {|gem| self << gem }
20
20
  end
21
21
  end
22
-
22
+
23
23
  def <<(gem)
24
24
  self[gem] ||= ANY_VERSION
25
25
  end
@@ -0,0 +1,247 @@
1
+ #--
2
+ # Copyright (c) 2010 Engine Yard, Inc.
3
+ # This source code is available under the MIT license.
4
+ # See the file LICENSE.txt for details.
5
+ #++
6
+
7
+ require 'zip/zip'
8
+ require 'stringio'
9
+
10
+ module Warbler
11
+ # Class that holds the files that will be stored in the jar file.
12
+ # The #files attribute contains a hash of pathnames inside the jar
13
+ # file to their contents. Contents can be one of:
14
+ # * +nil+ representing a directory entry
15
+ # * Any object responding to +read+ representing an in-memory blob
16
+ # * A String filename pointing to a file on disk
17
+ class Jar
18
+ DEFAULT_MANIFEST = %{Manifest-Version: 1.0\nCreated-By: Warbler #{Warbler::VERSION}\n\n}
19
+
20
+ attr_reader :files
21
+ attr_reader :app_filelist
22
+
23
+ def initialize
24
+ @files = {}
25
+ end
26
+
27
+ def compile(config)
28
+ # Compiling all Ruby files we can find -- do we need to allow an
29
+ # option to configure what gets compiled?
30
+ return if config.compiled_ruby_files.nil? || config.compiled_ruby_files.empty?
31
+
32
+ run_javac(config, config.compiled_ruby_files)
33
+ replace_compiled_ruby_files(config, config.compiled_ruby_files)
34
+ end
35
+
36
+ def run_javac(config, compiled_ruby_files)
37
+ # Need to use the version of JRuby in the application to compile it
38
+ %x{java -classpath #{config.java_libs.join(File::PATH_SEPARATOR)} org.jruby.Main -S jrubyc \"#{compiled_ruby_files.join('" "')}\"}
39
+ end
40
+
41
+ def replace_compiled_ruby_files(config, compiled_ruby_files)
42
+ # Exclude the rb files and recreate them. This
43
+ # prevents the original contents being used.
44
+ config.excludes += compiled_ruby_files
45
+
46
+ compiled_ruby_files.each do |ruby_source|
47
+ files[apply_pathmaps(config, ruby_source, :application)] = StringIO.new("require __FILE__.sub(/\.rb$/, '.class')")
48
+ end
49
+ end
50
+
51
+ # Apply the information in a Warbler::Config object in order to
52
+ # look for files to put into this war file.
53
+ def apply(config)
54
+ find_application_files(config)
55
+ find_java_libs(config)
56
+ find_java_classes(config)
57
+ find_gems_files(config)
58
+ add_manifest(config)
59
+ add_init_file(config)
60
+ apply_traits(config)
61
+ end
62
+
63
+ # Create the jar or war file. The single argument can either be a
64
+ # Warbler::Config or a filename of the file to create.
65
+ def create(config_or_path)
66
+ path = config_or_path
67
+ if Warbler::Config === config_or_path
68
+ path = "#{config_or_path.jar_name}.#{config_or_path.jar_extension}"
69
+ path = File.join(config_or_path.autodeploy_dir, path) if config_or_path.autodeploy_dir
70
+ end
71
+ rm_f path
72
+ ensure_directory_entries
73
+ puts "Creating #{path}"
74
+ create_jar path, @files
75
+ end
76
+
77
+ # Invoke a hook to allow the project traits to add or modify the archive contents.
78
+ def apply_traits(config)
79
+ config.update_archive(self)
80
+ end
81
+
82
+ # Add a manifest file either from config or by making a default manifest.
83
+ def add_manifest(config = nil)
84
+ unless @files.keys.detect{|k| k =~ /^META-INF\/MANIFEST\.MF$/i}
85
+ if config && config.manifest_file
86
+ @files['META-INF/MANIFEST.MF'] = config.manifest_file
87
+ else
88
+ @files['META-INF/MANIFEST.MF'] = StringIO.new(DEFAULT_MANIFEST)
89
+ end
90
+ end
91
+ end
92
+
93
+ # Add java libraries to WEB-INF/lib.
94
+ def find_java_libs(config)
95
+ config.java_libs.map {|lib| add_with_pathmaps(config, lib, :java_libs) }
96
+ end
97
+
98
+ # Add java classes to WEB-INF/classes.
99
+ def find_java_classes(config)
100
+ config.java_classes.map {|f| add_with_pathmaps(config, f, :java_classes) }
101
+ end
102
+
103
+ # Add gems to WEB-INF/gems
104
+ def find_gems_files(config)
105
+ config.gems.each {|gem, version| find_single_gem_files(config, gem, version) }
106
+ end
107
+
108
+ # Add a single gem to WEB-INF/gems
109
+ def find_single_gem_files(config, gem_pattern, version = nil)
110
+ if Gem::Specification === gem_pattern
111
+ spec = gem_pattern
112
+ else
113
+ gem = case gem_pattern
114
+ when Gem::Dependency
115
+ gem_pattern
116
+ else
117
+ Gem::Dependency.new(gem_pattern, Gem::Requirement.create(version))
118
+ end
119
+
120
+ # skip development dependencies
121
+ return if gem.respond_to?(:type) and gem.type != :runtime
122
+
123
+ matched = Gem.source_index.search(gem)
124
+ fail "gem '#{gem}' not installed" if matched.empty?
125
+ spec = matched.last
126
+ end
127
+
128
+ # skip gems with no load path
129
+ return if spec.loaded_from == ""
130
+
131
+ add_with_pathmaps(config, spec.loaded_from, :gemspecs)
132
+ spec.files.each do |f|
133
+ f = f[2..-1] if f =~ /^\.\//
134
+ next if config.gem_excludes && config.gem_excludes.any? {|rx| f =~ rx }
135
+ src = File.join(spec.full_gem_path, f)
136
+ # some gemspecs may have incorrect file listings
137
+ next unless File.exist?(src)
138
+ @files[apply_pathmaps(config, File.join(spec.full_name, f), :gems)] = src
139
+ end
140
+
141
+ spec.dependencies.each {|dep| find_single_gem_files(config, dep) } if config.gem_dependencies
142
+ end
143
+
144
+ # Add all application directories and files to the archive.
145
+ def find_application_files(config)
146
+ config.dirs.select do |d|
147
+ exists = File.directory?(d)
148
+ warn "warning: application directory `#{d}' does not exist or is not a directory; skipping" unless exists
149
+ exists
150
+ end.each do |d|
151
+ @files[apply_pathmaps(config, d, :application)] = nil
152
+ end
153
+ @app_filelist = FileList[*(config.dirs.map{|d| "#{d}/**/*"})]
154
+ @app_filelist.include *(config.includes.to_a)
155
+ @app_filelist.exclude *(config.excludes.to_a)
156
+ @app_filelist.map {|f| add_with_pathmaps(config, f, :application) }
157
+ end
158
+
159
+ # Add init.rb file to the war file.
160
+ def add_init_file(config)
161
+ if config.init_contents
162
+ contents = ''
163
+ config.init_contents.each do |file|
164
+ if file.respond_to?(:read)
165
+ contents << file.read
166
+ elsif File.extname(file) == '.erb'
167
+ contents << expand_erb(file, config).read
168
+ else
169
+ contents << File.read(file)
170
+ end
171
+ end
172
+ @files[config.init_filename] = StringIO.new(contents)
173
+ end
174
+ end
175
+
176
+ def add_with_pathmaps(config, f, map_type)
177
+ @files[apply_pathmaps(config, f, map_type)] = f
178
+ end
179
+
180
+ def expand_erb(file, config)
181
+ require 'erb'
182
+ erb = ERB.new(File.open(file) {|f| f.read })
183
+ StringIO.new(erb.result(erb_binding(config)))
184
+ end
185
+
186
+ def erb_binding(config)
187
+ webxml = config.webxml
188
+ binding
189
+ end
190
+
191
+ def apply_pathmaps(config, file, pathmaps)
192
+ file = file[2..-1] if file =~ /^\.\//
193
+ pathmaps = config.pathmaps.send(pathmaps)
194
+ pathmaps.each do |p|
195
+ file = file.pathmap(p)
196
+ end if pathmaps
197
+ file
198
+ end
199
+
200
+ def ensure_directory_entries
201
+ files.select {|k,v| !v.nil? }.each do |k,v|
202
+ dir = File.dirname(k)
203
+ while dir != "." && !files.has_key?(dir)
204
+ files[dir] = nil
205
+ dir = File.dirname(dir)
206
+ end
207
+ end
208
+ end
209
+
210
+ def create_jar(war_file, entries)
211
+ Zip::ZipFile.open(war_file, Zip::ZipFile::CREATE) do |zipfile|
212
+ entries.keys.sort.each do |entry|
213
+ src = entries[entry]
214
+ if src.respond_to?(:read)
215
+ zipfile.get_output_stream(entry) {|f| f << src.read }
216
+ elsif src.nil? || File.directory?(src)
217
+ warn "directory symlinks are not followed unless using JRuby; #{entry} contents not in archive" \
218
+ if File.symlink?(entry) && !defined?(JRUBY_VERSION)
219
+ zipfile.mkdir(entry)
220
+ elsif File.symlink?(src)
221
+ zipfile.get_output_stream(entry) {|f| f << File.read(src) }
222
+ else
223
+ zipfile.add(entry, src)
224
+ end
225
+ end
226
+ end
227
+ end
228
+
229
+ def entry_in_jar(jar, entry)
230
+ Zip::ZipFile.open(jar) do |zf|
231
+ zf.get_input_stream(entry) {|io| StringIO.new(io.read) }
232
+ end
233
+ end
234
+
235
+ # Java-boosted jar creation for JRuby; replaces #create_jar and
236
+ # #entry_in_jar with Java version
237
+ require 'warbler_jar' if defined?(JRUBY_VERSION) && JRUBY_VERSION >= "1.5"
238
+ end
239
+
240
+ # Warbler::War is Deprecated. Please use Warbler::Jar.
241
+ class War < Jar
242
+ def initialize(*)
243
+ super
244
+ warn "Warbler::War is deprecated. Please replace all occurrences with Warbler::Jar."
245
+ end
246
+ end
247
+ end