Class: Puck::Jar

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

Overview

Creates a standalone Jar file from your application.

The Jar will contain your application code (which is assumed to be in the "lib" directory), bin files (assumed to be in the "bin" directory), all the gems in your default group (i.e. those that are not in a group block in your Gemfile), including gems loaded from git, or from a path. It will also contain a JRuby runtime so that to run it you only need a Java runtime.

The Jar file will be configured so that you can run your application's bin files by passing their name as the first argument after the Jar file (see example below).

Examples:

Creating a Jar from a Rake task

task :jar do
  Puck::Jar.new.create
end

Configuring the Jar file

task :jar do
  jar = Puck::Jar.new(
    extra_files: Dir['config/*.yml'],
    jruby_complete: 'build/custom-jruby-complete.jar'
  )
  jar.create
end

Running a bin file

java -jar path/to/application.jar my-bin-file arg1 arg2

Instance Method Summary collapse

Constructor Details

#initialize(configuration = {}) ⇒ Jar

Create a new instance with the specified configuration.

Puck tries to use sane defaults like assuming that the application name is the same as the name of the directory containing the "lib" directory.

Parameters:

  • configuration (Hash) (defaults to: {})

Options Hash (configuration):

  • :extra_files (Array<String>, Hash<String,String>)

    a list of files to include in the Jar. The option can be either an Array, in which case paths must be below the :app_dir, or a Hash, in which case the file specified by the key is included at the path specified by the corresponding value.

  • :gem_groups (String) — default: [:default]

    a list of gem groups to include in the Jar. Remember to include the default group if you override this option.

  • :jruby_complete (String)

    a path to the jruby-complete.jar that you want to use. If you don't specify this option you need to have jruby-jars in your Gemfile (it contains the equivalent of jruby-complete.jar. This option is mostly useful when you have a customized JRuby runtime that you want to use.

  • :app_dir (String) — default: Dir.pwd

    the application's base directory (i.e. the directory that contains the "lib" directory)

  • :app_name (String) — default: File.basename(configuration[:app_dir])

    the name of the application, primarily used to name the Jar

  • :build_dir (String) — default: "build"

    the directory where the Jar file will be created


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

def initialize(configuration={})
  @configuration = configuration.dup
  @configuration[:app_dir] ||= Dir.pwd
  @configuration[:app_name] ||= File.basename(@configuration[:app_dir])
  @configuration[:build_dir] ||= File.join(@configuration[:app_dir], 'build')
  @configuration[:jar_name] ||= @configuration[:app_name] + '.jar'
  @configuration[:gem_groups] ||= [:default]
  @dependency_resolver = @configuration[:dependency_resolver] || DependencyResolver.new
end

Instance Method Details

#createObject

Create the Jar file using the instance's configuration.

Returns:

  • The path to the Jar file


86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
149
150
151
152
153
# File 'lib/puck/jar.rb', line 86

def create
  FileUtils.mkdir_p(@configuration[:build_dir])

  Dir.mktmpdir do |tmp_dir|
    output_path = File.join(@configuration[:build_dir], @configuration[:jar_name])
    temporary_output_path = File.join(Dir.mktmpdir, @configuration[:jar_name])
    project_dir = Pathname.new(@configuration[:app_dir]).expand_path.cleanpath
    extra_files = @configuration[:extra_files] || []
    jruby_complete_path = @configuration[:jruby_complete]

    if !(defined? JRubyJars) && !(jruby_complete_path && File.exists?(jruby_complete_path))
      raise PuckError, 'Cannot build Jar: jruby-jars must be installed, or :jruby_complete must be specified'
    end

    gem_dependencies = @dependency_resolver.resolve_gem_dependencies(@configuration)
    create_jar_bootstrap!(tmp_dir, gem_dependencies)

    ant = Ant.new(output_level: 1)
    begin
      ant.jar(destfile: temporary_output_path) do
        manifest do
          attribute name: 'Main-Class', value: 'org.jruby.JarBootstrapMain'
          attribute name: 'Created-By', value: "Puck v#{Puck::VERSION}"
        end

        zipfileset dir: tmp_dir, includes: 'jar-bootstrap.rb'

        if jruby_complete_path
          zipfileset src: jruby_complete_path
        else
          zipfileset src: JRubyJars.core_jar_path
          zipfileset src: JRubyJars.stdlib_jar_path
        end

        %w[bin lib].each do |sub_dir|
          path = project_dir + sub_dir
          if File.exists?(path)
            zipfileset dir: path, prefix: File.join(JAR_APP_HOME, sub_dir)
          end
        end

        extra_files.each do |file, target_path|
          path = Pathname.new(file).expand_path.cleanpath
          if target_path
            zipfileset file: path, fullpath: target_path
          else
            prefix = File.join(JAR_APP_HOME, path.relative_path_from(project_dir).dirname.to_s)
            zipfileset dir: path.dirname, prefix: prefix, includes: path.basename
          end
        end

        gem_dependencies.each do |spec|
          base_path = Pathname.new(spec[:base_path]).expand_path.cleanpath
          unless project_dir == base_path
            zipfileset dir: spec[:base_path], prefix: File.join(JAR_GEM_HOME, spec[:versioned_name])
          end
        end
      end

      FileUtils.mv(temporary_output_path, output_path)
    rescue Java::OrgApacheToolsAnt::BuildException => e
      raise PuckError, sprintf('Error when building JAR: %s (%s)', e.message, e.class), e.backtrace
    ensure
      FileUtils.rm_rf(File.dirname(temporary_output_path))
    end
    output_path
  end
end

#create!Object

Deprecated.

Use #create


156
157
158
# File 'lib/puck/jar.rb', line 156

def create!
  create
end