Report abuse

This is what I'm using to extract a rails app in a jar to ~/.jruby


			
require 'java'
require 'fileutils'
require 'rbconfig'

ZipFile = java.util.zip.ZipFile
ZipEntry = java.util.zip.ZipEntry

# extract from jar to jruby.home/.
class ExtractFromJar
  attr_reader :path_to_jarfile, :name, :destination, :zip
  def initialize(path_to_jarfile, dir = nil)
    @path_to_jarfile = path_to_jarfile
    @name = @path_to_jarfile.split(File::SEPARATOR).last[/(.*)\.(jar$)/, 1]
    @destination = dir || File.join(Config::CONFIG['prefix'], @name)
    if need_extract?
      raise "error: can't locate enclosed archive from #{__FILE__}" if @path_to_jarfile.nil?
      @zip = ZipFile.new(java.net.URLDecoder.decode(@path_to_jarfile, "utf-8"))
    end
  end

  def need_extract?
    !File.directory?(@destination) || (File.stat(@path_to_jarfile).mtime > File.stat(@destination).mtime)
  end

  def entries
    enum = @zip.entries
    def enum.each
      while hasMoreElements
        yield nextElement
      end
    end
    enum
  end

  def extract
    return nil unless need_extract?
    entries.each do |entry|
      if entry.directory?
        FileUtils.mkdir_p("#{@destination}#{File::SEPARATOR}#{entry.name}")
      else
        path = write_entry entry, entry.name
      end
    end
  end

  def write_entry(entry, name)
    entry_path = "#{@destination.sub(%r{/$},'')}#{File::SEPARATOR}#{name}"
    puts "creating #{entry_path}"
    FileUtils.mkdir_p(File.dirname(entry_path))
    instream = @zip.getInputStream(entry)
    outstream = java.io.FileOutputStream.new(entry_path)
    buffer = java.lang.reflect.Array.newInstance(java.lang.Byte::TYPE, 8192)
    while (num_read = instream.read(buffer)) != -1
      outstream.write buffer, 0, num_read
    end
    entry_path
  ensure
    instream.close if instream
    outstream.close if outstream
  end
end

class ExtractFromResource < ExtractFromJar
  attr_reader :resource_in_jar
  def initialize(resource_in_jar, dir = nil)
    @resource_in_jar = resource_in_jar
    cl = java.lang.Class.forName('org.jruby.Ruby').classLoader
    super(cl.find_resource(@resource_in_jar).file[/file:(.*.jar)!\//, 1])
  end
end

This is what I'm running in the irb console started from web start


			
require 'jrubygems'
require 'lib/extract_from_jar.rb'
e = ExtractFromResource.new("blog/config/environment.rb")
e.extract
require "#{e.destination}/blog/config/boot.rb"
require 'commands/server'

# and here's the stack trace now (much further along!)

=> Booting WEBrick...
TypeError: can't convert nil into String
  from /Users/stephen/.jruby/lib/ruby/gems/1.8/gems/rails-2.0.2/lib/commands/servers/webrick.rb:17
  from /Users/stephen/.jruby/lib/ruby/gems/1.8/gems/rails-2.0.2/lib/commands/servers/webrick.rb:17:in `options'
  from /Users/stephen/.jruby/lib/ruby/gems/1.8/gems/rails-2.0.2/lib/commands/servers/webrick.rb:17
  from /Users/stephen/.jruby/lib/ruby/gems/1.8/gems/rails-2.0.2/lib/commands/servers/webrick.rb:17:in `require'
  from /Users/stephen/.jruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require'
  from /Users/stephen/.jruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:496:in `new_constants_in'
  from /Users/stephen/.jruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:318:in `require'
  from /Users/stephen/.jruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:496
  from /Users/stephen/.jruby/lib/ruby/gems/1.8/gems/rails-2.0.2/lib/commands/server.rb:38:in `require'
  from /Users/stephen/.jruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require'
  from (irb):7:in `puts'