Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

jar dependencies like old maven-gems #1451

Closed
wants to merge 4 commits into from

3 participants

@mkristian
Collaborator

this PR is meant to base for further discussion.

previously maven-gems failed mainly version resolution with maven (on version conflict the dependency tree is used to determine the right version) works totally different then rubygems (version ranges).

this patch has two parts one which loads jars and tracks versions. in case of conflicting versions ONLY the first jar is loaded and the second one just gives a warning. kind of the same you have with rubygems where it fails when a second version of a gems gets activated.

the second part is a Gem.post_install hook which uses the info from the installed Gem::Sepcification of the installed gem and looks for jar dependencies declared in the requirements section of the spec. these declared jars and its depencenies will be install using ruby-maven (which can uses the gemspec as a POM !!). it also creates a file {gemspec.name}_jars.rb file which uses the jar_dependencies to track and load the vendored jars.

to main reason to vendor the jars is that regular bundler will just work.

in case there are version conflicts jbundler can help to resolve them or do it manually. it is a matter of which version gets required first, any project should be able to ensure this.

as an example I added the jar dependencies in jruby-openssl gem.

@mkristian
Collaborator

walkthrough the example gem. you need ruby-maven installed (might need the latest version):

 cd maven/gems/jruby-openssl
 ../../../bin/jruby -S rake build
 ../../../bin/jruby -S gem install pkg/jruby-openssl-0.9.5.gem 
@kares
Collaborator

this seems obsolete by now ...

@mkristian
Collaborator

yes, that is obsolete now . . .

@mkristian mkristian closed this
@headius headius modified the milestone: Invalid or Duplicate
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
46 lib/ruby/shared/jar_dependencies.rb
@@ -0,0 +1,46 @@
+def require_jar( groupId, artifactId, *classifier_version )
+ require_jarfile( nil, groupId, artifactId, *classifier_version )
+end
+
+def require_jarfile( file, groupId, artifactId, *classifier_version )
+ skip = java.lang.System.get_property( 'jruby.skip.jars' ) || ENV[ 'JRUBY_SKIP_JARS' ] || java.lang.System.get_property( 'jbundler.skip' ) || ENV[ 'JBUNDLER_SKIP' ]
+ return false if skip == 'true'
+
+ if classifier_version.size == 1
+ version = classifier_version[ 0 ]
+ classifier = nil
+ else
+ version = classifier_version[ 1 ]
+ classifier = classifier_version[ 0 ]
+ end
+
+ # if no file given than it is vendored
+ # if the file does not exists we assume it is vendored
+ if file.nil? || !File.exists?( file )
+ file = "#{groupId}/#{artifactId}-#{version}"
+ file += "-#{classifier}" if classifier
+ file += '.jar'
+ end
+
+ @@jars ||= {}
+ coordinate = "#{groupId}:#{artifactId}"
+ coordinate += ":#{classifier}" if classifier
+ if @@jars.key? coordinate
+ if @@jars[ coordinate ] != version
+ warn "coordinate #{coordinate} already loaded with version #{@@jars[ coordinate ]}"
+ end
+ false
+ else
+ begin
+ if require file
+ @@jars[ coordinate ] = version
+ true
+ else
+ raise LoadError.new( "coordindate #{coordinate} not found" )
+ end
+ rescue LoadError => e
+ warn 'you might need to restall that gem which needs the missing jar'
+ raise e
+ end
+ end
+end
View
100 lib/ruby/shared/jar_installer.rb
@@ -0,0 +1,100 @@
+class JarInstaller
+
+ def self.install_jars
+ new.install_jars
+ end
+
+ def initialize( spec = nil )
+ if spec.nil?
+ specs = Dir[ '*.gemspec' ]
+ raise 'more then one gemspec found. please specify one in the constructor' if specs.size > 1
+ raise 'no gemspec found' if specs.size == 0
+ spec = specs.first
+ end
+ if spec.is_a? String
+ @basedir = File.dirname( File.expand_path( spec ) )
+ @specfile = spec
+ spec = eval( File.read( spec ) )
+ else
+ @basedir = spec.gem_dir
+ @specfile = spec.spec_file
+ end
+ @spec = spec
+ end
+
+ def vendor_jars
+ return if @spec.requirements.empty?
+ _install( true )
+ end
+
+ def install_jars
+ _install( false )
+ end
+
+ private
+
+ def _install( vendor )
+ jars_file = File.join( @basedir, @spec.require_path,
+ "#{@spec.name}_jars.rb" )
+
+ return if File.exists?( jars_file ) &&
+ File.mtime( @specfile ) < File.mtime( jars_file )
+
+ deps = File.join( @basedir, 'deps.lst' )
+
+ # lazy load ruby-maven
+ begin
+ require 'maven/ruby/maven'
+
+ rescue LoadError
+ raise 'please install ruby-maven gem so the jar dependencies can be installed'
+ end
+
+ # monkey patch to NOT include gem dependencies
+ require 'maven/tools/gemspec_dependencies'
+ eval <<EOF
+ class ::Maven::Tools::GemspecDependencies
+ def runtime; []; end
+ def development; []; end
+ end
+EOF
+
+ maven = Maven::Ruby::Maven.new
+ maven.exec 'dependency:list', "-DoutputFile=#{deps}", '-DincludeScope=runtime', '-DoutputAbsoluteArtifactFilename=true', '-DincludeTypes=jar', '-DoutputScope=false', '-f', @specfile, '--quiet'
+
+ FileUtils.mkdir_p( File.dirname( jars_file ) )
+ File.open( jars_file, 'w' ) do |f|
+ f.puts "require 'jar-dependencies'"
+ f.puts
+ File.read( deps ).each_line do |line|
+ if line.match /:jar:/
+ if vendor
+ vendored = line.sub( /:jar:/, '-' )
+ vendored.sub!( /:[^:]+$/, '' )
+ vendored.sub!( /:[^:]+$/, '.jar' )
+ vendored.sub!( /:/, File::SEPARATOR )
+ vendored.sub!( /^\s+/, '' )
+ vendored = File.join( @basedir, @spec.require_path, vendored )
+ end
+
+ line.gsub!( /:jar:|:compile:|:runtime:/, ':' )
+ line.sub!( /^\s+/, '' )
+ path = line.sub( /^.*:/, '' ).strip
+ args = line.sub( /:[^:]+$/, '' ).gsub( /:/, "', '" )
+
+ if vendor
+ FileUtils.mkdir_p( File.dirname( vendored ) )
+ FileUtils.cp( path, vendored )
+
+ f.puts( "require_jarfile( '#{args}' )" )
+ else
+ f.puts( "require_jarfile( '#{path}', '#{args}' )" )
+ end
+ end
+ end
+ end
+ ensure
+ FileUtils.rm_f( deps ) if deps
+ end
+end
+
View
2  lib/ruby/shared/jopenssl/version.rb
@@ -1,5 +1,5 @@
module Jopenssl
module Version
- VERSION = "0.9.4"
+ VERSION = "0.9.5"
end
end
View
5 lib/ruby/shared/rubygems/defaults/jruby.rb
@@ -1,12 +1,17 @@
require 'rubygems/config_file'
require 'rbconfig'
require 'jruby/util'
+require 'jar_installer'
module Gem
ConfigFile::PLATFORM_DEFAULTS['install'] = '--no-rdoc --no-ri --env-shebang'
ConfigFile::PLATFORM_DEFAULTS['update'] = '--no-rdoc --no-ri --env-shebang'
+ post_install do |gem_installer|
+ ::JarInstaller.new( gem_installer.spec ).vendor_jars
+ end
+
class << self
alias_method :original_ruby, :ruby
def ruby
View
1  maven/gems/jruby-openssl/.gitignore
@@ -1,2 +1,3 @@
pkg
lib/shared/jruby-openssl.jar
+*_jars.rb
View
6 maven/gems/jruby-openssl/Rakefile
@@ -1,7 +1,13 @@
#-*- mode: ruby -*-
require 'maven/ruby/tasks'
+require 'jar_installer'
# the actual build configuration is inside the Mavenfile
task :default => :build
+
+# overwrite empty tasks
+task :maven do
+ JarInstaller.install_jars
+end
View
10 maven/gems/jruby-openssl/jruby-openssl.gemspec
@@ -1,6 +1,5 @@
#-*- mode: ruby -*-
-require 'rake'
require File.dirname(__FILE__) + "/lib/jopenssl/version.rb"
Gem::Specification.new do |s|
@@ -12,14 +11,13 @@ Gem::Specification.new do |s|
s.homepage = 'https://github.com/jruby/jruby'
s.description = File.read('README.txt').split(/\n{2,}/)[3...4].join("\n\n")
s.rubyforge_project = 'jruby/jruby'
- s.files = FileList['[A-Z]*', 'lib/**/*', 'test/**/*'].to_a
- s.add_dependency('bouncy-castle-java', '>= 1.5.0147')
+ s.files = Dir['[A-Z]*', 'lib/**/*', 'test/**/*'].to_a.reject { |f| f.match /_jars.rb$/ }
s.add_development_dependency 'rake', "~> 10.1"
- s.add_development_dependency 'ruby-maven', "~> 3.1.0.0.0"
+ s.add_development_dependency 'ruby-maven', "~> 3.1.1.0.0"
- # s.changes = File.read('History.txt').split(/\n{2,}/)[0..1].join("\n\n")
- s.require_paths = ['lib']
+ s.requirements << "jar org.bouncycastle:bcpkix-jdk15on, 1.49"
+ s.requirements << "jar org.bouncycastle:bcprov-jdk15on, 1.49"
end
# vim: syntax=Ruby
View
3  maven/gems/jruby-openssl/lib/jruby-openssl.rb
@@ -2,4 +2,5 @@
# the gem version of jruby-openssl rather than the stdlib version. JRuby 1.7.5
# and higher use the "default gems" capability of RubyGems.
-require 'jopenssl/load'
+require 'jruby-openssl_jars'
+require 'jopenssl/load'
View
27 maven/gems/jruby-openssl/pom.xml
@@ -4,41 +4,32 @@
<modelVersion>4.0.0</modelVersion>
<groupId>rubygems</groupId>
<artifactId>jruby-openssl</artifactId>
- <version>0.9.4</version>
+ <version>0.9.5</version>
<packaging>gem</packaging>
<name>OpenSSL add-on for JRuby</name>
<description>JRuby-OpenSSL is an add-on gem for JRuby that emulates the Ruby OpenSSL native library.</description>
<url>https://github.com/jruby/jruby</url>
<properties>
<tesla.dump.readonly>true</tesla.dump.readonly>
+ <jruby.plugins.version>1.0.0-rc4</jruby.plugins.version>
<tesla.dump.pom>pom.xml</tesla.dump.pom>
<project.build.sourceEncoding>utf-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
- <groupId>rubygems</groupId>
- <artifactId>bouncy-castle-java</artifactId>
- <version>[1.5.0147,)</version>
- <type>gem</type>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcpkix-jdk15on</artifactId>
+ <version>1.49</version>
</dependency>
<dependency>
- <groupId>rubygems</groupId>
- <artifactId>rake</artifactId>
- <version>[10.1,10.99999]</version>
- <type>gem</type>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>rubygems</groupId>
- <artifactId>ruby-maven</artifactId>
- <version>[3.1.0.0.0,3.1.0.0.99999]</version>
- <type>gem</type>
- <scope>test</scope>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcprov-jdk15on</artifactId>
+ <version>1.49</version>
</dependency>
<dependency>
<groupId>org.jruby</groupId>
<artifactId>openssl</artifactId>
- <version>0.9.4</version>
+ <version>0.9.5-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
Something went wrong with that request. Please try again.