Class: Warbler::Jar

Inherits:
Object
  • Object
show all
Defined in:
lib/warbler/jar.rb

Overview

Class that holds the files that will be stored in the jar file. The #files attribute contains a hash of pathnames inside the jar file to their contents. Contents can be one of:

  • nil representing a directory entry

  • Any object responding to read representing an in-memory blob

  • A String filename pointing to a file on disk

Direct Known Subclasses

War

Constant Summary collapse

DEFAULT_MANIFEST =
%{Manifest-Version: 1.0\nCreated-By: Warbler #{Warbler::VERSION}\n\n}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeJar

Returns a new instance of Jar.



25
26
27
# File 'lib/warbler/jar.rb', line 25

def initialize
  @files = {}
end

Instance Attribute Details

#app_filelistObject (readonly)

Returns the value of attribute app_filelist.



23
24
25
# File 'lib/warbler/jar.rb', line 23

def app_filelist
  @app_filelist
end

#filesObject (readonly)

Returns the value of attribute files.



22
23
24
# File 'lib/warbler/jar.rb', line 22

def files
  @files
end

Instance Method Details

#add_init_file(config) ⇒ Object

Add init.rb file to the war file.



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/warbler/jar.rb', line 166

def add_init_file(config)
  if config.init_contents
    contents = ''
    config.init_contents.each do |file|
      if file.respond_to?(:read)
        contents << file.read
      elsif File.extname(file) == '.erb'
        contents << expand_erb(file, config).read
      else
        contents << File.read(file)
      end
    end
    @files[config.init_filename] = StringIO.new(contents)
  end
end

#add_manifest(config = nil) ⇒ Object

Add a manifest file either from config or by making a default manifest.



90
91
92
93
94
95
96
97
98
# File 'lib/warbler/jar.rb', line 90

def add_manifest(config = nil)
  unless @files.keys.detect{|k| k =~ /^META-INF\/MANIFEST\.MF$/i}
    if config && config.manifest_file
      @files['META-INF/MANIFEST.MF'] = config.manifest_file
    else
      @files['META-INF/MANIFEST.MF'] = StringIO.new(DEFAULT_MANIFEST)
    end
  end
end

#add_with_pathmaps(config, f, map_type) ⇒ Object



182
183
184
# File 'lib/warbler/jar.rb', line 182

def add_with_pathmaps(config, f, map_type)
  @files[apply_pathmaps(config, f, map_type)] = f
end

#apply(config) ⇒ Object

Apply the information in a Warbler::Config object in order to look for files to put into this war file.



60
61
62
63
64
65
66
67
68
# File 'lib/warbler/jar.rb', line 60

def apply(config)
  find_application_files(config)
  find_java_libs(config)
  find_java_classes(config)
  find_gems_files(config)
  add_manifest(config)
  add_init_file(config)
  apply_traits(config)
end

#apply_pathmaps(config, file, pathmaps) ⇒ Object



197
198
199
200
201
202
203
204
# File 'lib/warbler/jar.rb', line 197

def apply_pathmaps(config, file, pathmaps)
  file = file[2..-1] if file =~ /^\.\//
  pathmaps = config.pathmaps.send(pathmaps)
  pathmaps.each do |p|
    file = file.pathmap(p)
  end if pathmaps
  file
end

#apply_traits(config) ⇒ Object

Invoke a hook to allow the project traits to add or modify the archive contents.



85
86
87
# File 'lib/warbler/jar.rb', line 85

def apply_traits(config)
  config.update_archive(self)
end

#compile(config) ⇒ Object



34
35
36
37
38
39
40
41
# File 'lib/warbler/jar.rb', line 34

def compile(config)
  # Compiling all Ruby files we can find -- do we need to allow an
  # option to configure what gets compiled?
  return if config.compiled_ruby_files.nil? || config.compiled_ruby_files.empty?

  run_javac(config, config.compiled_ruby_files)
  replace_compiled_ruby_files(config, config.compiled_ruby_files)
end

#contents(entry) ⇒ Object



29
30
31
32
# File 'lib/warbler/jar.rb', line 29

def contents(entry)
  file = files[entry]
  file.respond_to?(:read) ? file.read : File.open(file) {|f| f.read }
end

#create(config_or_path) ⇒ Object

Create the jar or war file. The single argument can either be a Warbler::Config or a filename of the file to create.



72
73
74
75
76
77
78
79
80
81
82
# File 'lib/warbler/jar.rb', line 72

def create(config_or_path)
  path = config_or_path
  if Warbler::Config === config_or_path
    path = "#{config_or_path.jar_name}.#{config_or_path.jar_extension}"
    path = File.join(config_or_path.autodeploy_dir, path) if config_or_path.autodeploy_dir
  end
  rm_f path
  ensure_directory_entries
  puts "Creating #{path}"
  create_jar path, @files
end

#create_jar(war_file, entries) ⇒ Object



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/warbler/jar.rb', line 216

def create_jar(war_file, entries)
  Zip::ZipFile.open(war_file, Zip::ZipFile::CREATE) do |zipfile|
    entries.keys.sort.each do |entry|
      src = entries[entry]
      if src.respond_to?(:read)
        zipfile.get_output_stream(entry) {|f| f << src.read }
      elsif src.nil? || File.directory?(src)
        $stderr.puts "directory symlinks are not followed unless using JRuby; #{entry} contents not in archive" \
          if File.symlink?(entry) && !defined?(JRUBY_VERSION)
        zipfile.mkdir(entry)
      elsif File.symlink?(src)
        zipfile.get_output_stream(entry) {|f| f << File.read(src) }
      else
        zipfile.add(entry, src)
      end
    end
  end
end

#ensure_directory_entriesObject



206
207
208
209
210
211
212
213
214
# File 'lib/warbler/jar.rb', line 206

def ensure_directory_entries
  files.select {|k,v| !v.nil? }.each do |k,v|
    dir = File.dirname(k)
    while dir != "." && !files.has_key?(dir)
      files[dir] = nil
      dir = File.dirname(dir)
    end
  end
end

#entry_in_jar(jar, entry) ⇒ Object



235
236
237
238
239
# File 'lib/warbler/jar.rb', line 235

def entry_in_jar(jar, entry)
  Zip::ZipFile.open(jar) do |zf|
    zf.get_input_stream(entry) {|io| StringIO.new(io.read) }
  end
end

#erb_binding(config) ⇒ Object



192
193
194
195
# File 'lib/warbler/jar.rb', line 192

def erb_binding(config)
  webxml = config.webxml
  binding
end

#expand_erb(file, config) ⇒ Object



186
187
188
189
190
# File 'lib/warbler/jar.rb', line 186

def expand_erb(file, config)
  require 'erb'
  erb = ERB.new(File.open(file) {|f| f.read })
  StringIO.new(erb.result(erb_binding(config)))
end

#find_application_files(config) ⇒ Object

Add all application directories and files to the archive.



151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/warbler/jar.rb', line 151

def find_application_files(config)
  config.dirs.select do |d|
    exists = File.directory?(d)
    $stderr.puts "warning: application directory `#{d}' does not exist or is not a directory; skipping" unless exists
    exists
  end.each do |d|
    @files[apply_pathmaps(config, d, :application)] = nil
  end
  @app_filelist = FileList[*(config.dirs.map{|d| "#{d}/**/*"})]
  @app_filelist.include *(config.includes.to_a)
  @app_filelist.exclude *(config.excludes.to_a)
  @app_filelist.map {|f| add_with_pathmaps(config, f, :application) }
end

#find_gems_files(config) ⇒ Object

Add gems to WEB-INF/gems



111
112
113
# File 'lib/warbler/jar.rb', line 111

def find_gems_files(config)
  config.gems.each {|gem, version| find_single_gem_files(config, gem, version) }
end

#find_java_classes(config) ⇒ Object

Add java classes to WEB-INF/classes.



106
107
108
# File 'lib/warbler/jar.rb', line 106

def find_java_classes(config)
  config.java_classes.map {|f| add_with_pathmaps(config, f, :java_classes) }
end

#find_java_libs(config) ⇒ Object

Add java libraries to WEB-INF/lib.



101
102
103
# File 'lib/warbler/jar.rb', line 101

def find_java_libs(config)
  config.java_libs.map {|lib| add_with_pathmaps(config, lib, :java_libs) }
end

#find_single_gem_files(config, gem_pattern, version = nil) ⇒ Object

Add a single gem to WEB-INF/gems



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/warbler/jar.rb', line 116

def find_single_gem_files(config, gem_pattern, version = nil)
  if Gem::Specification === gem_pattern
    spec = gem_pattern
  else
    gem = case gem_pattern
          when Gem::Dependency
            gem_pattern
          else
            Gem::Dependency.new(gem_pattern, Gem::Requirement.create(version))
          end

    # skip development dependencies
    return if gem.respond_to?(:type) and gem.type != :runtime

    matched = Gem.source_index.search(gem)
    fail "gem '#{gem}' not installed" if matched.empty?
    spec = matched.last
  end

  full_gem_path = Pathname.new(spec.full_gem_path)

  # skip gems whose full_gem_path does not exist
  ($stderr.puts "warning: skipping #{spec.name} (#{full_gem_path.to_s} does not exist)" ; return) unless full_gem_path.exist?

  @files[apply_pathmaps(config, "#{spec.full_name}.gemspec", :gemspecs)] = StringIO.new(spec.to_ruby)
  FileList["#{full_gem_path.to_s}/**/*"].each do |src|
    f = Pathname.new(src).relative_path_from(full_gem_path).to_s
    next if config.gem_excludes && config.gem_excludes.any? {|rx| f =~ rx }
    @files[apply_pathmaps(config, File.join(spec.full_name, f), :gems)] = src
  end

  spec.dependencies.each {|dep| find_single_gem_files(config, dep) } if config.gem_dependencies
end

#replace_compiled_ruby_files(config, compiled_ruby_files) ⇒ Object



48
49
50
51
52
53
54
55
56
# File 'lib/warbler/jar.rb', line 48

def replace_compiled_ruby_files(config, compiled_ruby_files)
  # Exclude the rb files and recreate them. This
  # prevents the original contents being used.
  config.excludes += compiled_ruby_files

  compiled_ruby_files.each do |ruby_source|
    files[apply_pathmaps(config, ruby_source, :application)] = StringIO.new("require __FILE__.sub(/\.rb$/, '.class')")
  end
end

#run_javac(config, compiled_ruby_files) ⇒ Object



43
44
45
46
# File 'lib/warbler/jar.rb', line 43

def run_javac(config, compiled_ruby_files)
  # Need to use the version of JRuby in the application to compile it
  %x{java -classpath #{config.java_libs.join(File::PATH_SEPARATOR)} org.jruby.Main -S jrubyc \"#{compiled_ruby_files.join('" "')}\"}
end