mini_aether 0.0.1a-java

Sign up to get free protection for your applications and to get access to all the features.
data/COPYING ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2012 Patrick Mahoney
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -0,0 +1,60 @@
1
+ MiniAether
2
+ ----------
3
+
4
+ JRuby wrapper around some parts of
5
+ [Aether](http://eclipse.org/aether/), the library underlying the
6
+ [Maven](http://maven.apache.org/) build and dependency management
7
+ tool.
8
+
9
+ * Bootstraps itself by downloading Aether components directly from the
10
+ Maven Central repository.
11
+ * Installs JARs into the standard Maven location `~/.m2/repository`.
12
+ * Loads Aether libs in separate JRuby with own classloader to avoid
13
+ contaminating the primary classloader.
14
+
15
+ I feel that JRuby/maven/rubygems integration is lacking in many areas.
16
+ There are various attempts to improve this. See
17
+ [JBunder](https://github.com/mkristian/jbundler) for example. So I'm
18
+ not sure what role MiniAether will play, if any.
19
+
20
+ require 'mini_aether'
21
+
22
+ MiniAether.setup do
23
+ group 'org.sonatype.aether' do
24
+ version '1.13.1' do
25
+ jar 'aether-api'
26
+ jar 'aether-connector-asynchttpclient'
27
+ jar 'aether-connector-file'
28
+ jar 'aether-impl'
29
+ jar 'aether-spi'
30
+ jar 'aether-util'
31
+ end
32
+ end
33
+
34
+ jar 'com.ning:async-http-client:1.6.5'
35
+ jar 'org.jboss.netty:netty:3.2.5.Final'
36
+
37
+ # alternate syntax
38
+ dep(:group_id => 'org.slf4j',
39
+ :artifact_id => 'slf4j-api',
40
+ :version => '1.6.2',
41
+ :extension => 'jar') # 'jar' is the default if none is given
42
+
43
+ group 'org.apache.maven' do
44
+ version '3.0.4' do
45
+ jar 'maven-aether-provider'
46
+ jar 'maven-model'
47
+ jar 'maven-model-builder'
48
+ jar 'maven-repository-metadata'
49
+ end
50
+ end
51
+
52
+ group 'org.codehaus.plexus' do
53
+ jar 'plexus-interpolation:1.14'
54
+ jar 'plexus-component-annotations:1.5.5'
55
+ jar 'plexus-utils:2.0.6'
56
+ end
57
+ end
58
+
59
+ At this point, all those jars and their dependencies will be loaded
60
+ into the current JRuby.
@@ -0,0 +1,57 @@
1
+ require 'java'
2
+ require 'mini_aether/spec'
3
+
4
+ module MiniAether
5
+ MAVEN_CENTRAL_REPO = 'http://repo1.maven.org/maven2'.freeze
6
+
7
+ M2_SETTINGS = File.join(ENV['HOME'], '.m2', 'settings.xml').freeze
8
+
9
+ class << self
10
+ # Create a new ScriptingContainer (Java object interface to a
11
+ # JRuby runtime) in SINGLETHREAD mode, and yield it to the block.
12
+ # Ensure the runtime is terminated after the block returns.
13
+ def with_ruby_container
14
+ scope = Java::OrgJrubyEmbed::LocalContextScope::SINGLETHREAD
15
+ c = Java::OrgJrubyEmbed::ScriptingContainer.new(scope)
16
+ begin
17
+ yield c
18
+ ensure
19
+ c.terminate
20
+ end
21
+ end
22
+
23
+ # Resolve +dependencies+, downloading from +sources+.
24
+ #
25
+ # Uses a separate JRuby runtime to avoid polluting the classpath
26
+ # with Aether and SLF4J classes.
27
+ #
28
+ # @param [Array<Hash>] dependencies
29
+ #
30
+ # @option dependency [String] :group_id the groupId of the artifact
31
+ # @option dependency [String] :artifact_id the artifactId of the artifact
32
+ # @option dependency [String] :version the version (or range of versions) of the artifact
33
+ # @option dependency [String] :extension default to 'jar'
34
+ #
35
+ # @param [Array<String>] repos urls to maven2 repositories
36
+ #
37
+ # @return [Array<String>] an array of paths to artifact files
38
+ # (likely jar files) satisfying the dependencies
39
+ def resolve(dependencies, sources)
40
+ with_ruby_container do |c|
41
+ c.put 'path', File.dirname(__FILE__).to_java
42
+ c.put 'deps', Marshal.dump(dependencies).to_java
43
+ c.put 'repos', Marshal.dump(sources).to_java
44
+ files = c.runScriptlet <<-EOF
45
+ $LOAD_PATH.push path
46
+ require 'mini_aether/resolver'
47
+ MiniAether::Resolver.new.resolve_foreign(deps, repos)
48
+ EOF
49
+ files.map { |f| f.to_s }
50
+ end
51
+ end
52
+
53
+ def setup(&block)
54
+ MiniAether::Spec.new(&block).require
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,169 @@
1
+ require 'mini_aether/spec'
2
+ require 'mini_aether/xml_parser'
3
+ require 'fileutils'
4
+ require 'net/http'
5
+ require 'strscan'
6
+ require 'tmpdir'
7
+ require 'uri'
8
+
9
+ module MiniAether
10
+ module Bootstrap
11
+ System = Java::JavaLang::System
12
+
13
+ # Pre-resolved dependencies of mini_aether.
14
+ def dependencies
15
+ spec = Spec.new do
16
+ group 'org.sonatype.aether' do
17
+ version '1.13.1' do
18
+ jar 'aether-api'
19
+ jar 'aether-connector-asynchttpclient'
20
+ jar 'aether-connector-file'
21
+ jar 'aether-impl'
22
+ jar 'aether-spi'
23
+ jar 'aether-util'
24
+ end
25
+ end
26
+
27
+ jar 'com.ning:async-http-client:1.6.5'
28
+ jar 'org.jboss.netty:netty:3.2.5.Final'
29
+ jar 'org.slf4j:slf4j-api:1.6.2'
30
+
31
+ begin
32
+ Java::OrgSlf4jImpl::StaticLoggerBinder
33
+ rescue NameError
34
+ # use logback when no slf4j backend exists
35
+ jar 'ch.qos.logback:logback-core:1.0.6'
36
+ jar 'ch.qos.logback:logback-classic:1.0.6'
37
+ # add dir to classpath since it contains logback.xml
38
+ $CLASSPATH << File.dirname(__FILE__)
39
+ end
40
+
41
+ group 'org.apache.maven' do
42
+ version '3.0.4' do
43
+ jar 'maven-aether-provider'
44
+ jar 'maven-model'
45
+ jar 'maven-model-builder'
46
+ jar 'maven-repository-metadata'
47
+ end
48
+ end
49
+
50
+ group 'org.codehaus.plexus' do
51
+ jar 'plexus-interpolation:1.14'
52
+ jar 'plexus-component-annotations:1.5.5'
53
+ jar 'plexus-utils:2.0.6'
54
+ end
55
+ end
56
+
57
+ spec.dependencies
58
+ end
59
+
60
+ # Interpolate variables like +${user.home}+ and +${env.HOME}+ from
61
+ # system properties and environment variables respectively.
62
+ def interpolate(str)
63
+ ret = ''
64
+
65
+ s = StringScanner.new(str)
66
+ pos = s.pos
67
+
68
+ while s.scan_until(/\$\{[^\s}]+\}/) # match ${stuff}
69
+ # add the pre_match, but only starting from previous position
70
+ ret << str.slice(pos, (s.pos - pos - s.matched.size))
71
+
72
+ # interpolate
73
+ var = s.matched.slice(2..-2)
74
+ ret << case var
75
+ when /^env\.(.*)/
76
+ ENV[$1] || ''
77
+ else
78
+ System.getProperty(var) || ''
79
+ end
80
+
81
+ pos = s.pos
82
+ end
83
+ ret << s.rest
84
+
85
+ ret
86
+ end
87
+
88
+ def local_repository_path
89
+ default_local_repo_path =
90
+ File.join(System.getProperty('user.home'), '.m2', 'repository')
91
+
92
+ if File.exists? M2_SETTINGS
93
+ xml = File.read M2_SETTINGS
94
+ begin
95
+ parser = XmlParser.new(xml)
96
+ parser.pull_to_path(:settings, :localRepository)
97
+ interpolate(parser.pull_text_until_end.strip)
98
+ rescue XmlParser::NotFoundError
99
+ default_local_repo_path
100
+ end
101
+ else
102
+ default_local_repo_path
103
+ end
104
+ end
105
+
106
+ def ensure_dependency(dep)
107
+ path = jar_path(dep)
108
+ local_file = File.join(local_repository_path, path)
109
+ install(path, local_file) unless File.exists?(local_file)
110
+ local_file
111
+ end
112
+
113
+ # Load the required jar files, downloading them if necessary.
114
+ #
115
+ # Ignores any maven config regarding repositories and attempts a
116
+ # direct download from repo1.maven.org using Net::HTTP.
117
+ def bootstrap!
118
+ dependencies.each do |dep|
119
+ require ensure_dependency(dep)
120
+ end
121
+ end
122
+
123
+ def install(path, file, repo = MAVEN_CENTRAL_REPO)
124
+ print "installing #{File.basename(path)}... "
125
+ $stdout.flush
126
+
127
+ remote_base = File.dirname(path) + '/' + File.basename(path, File.extname(path))
128
+ local_dir = File.dirname(file)
129
+ local_base = File.join(local_dir, File.basename(file, File.extname(file)))
130
+
131
+ exts = [File.extname(path), '.pom', '.pom.sha1']
132
+ exts.each do |ext|
133
+ uri = URI("#{repo}/#{remote_base}#{ext}")
134
+ local_file = local_base + ext
135
+
136
+ Net::HTTP.start(uri.host, uri.port) do |http|
137
+ request = Net::HTTP::Get.new uri.request_uri
138
+
139
+ http.request request do |response|
140
+ unless response.code == '200'
141
+ raise "#{response.code} #{response.message}: #{uri}"
142
+ end
143
+
144
+ FileUtils.mkdir_p local_dir
145
+ open local_file, 'w' do |io|
146
+ response.read_body do |chunk|
147
+ io.write chunk
148
+ end
149
+ end
150
+ end
151
+ end
152
+
153
+ print "#{ext} "
154
+ $stdout.flush
155
+ end
156
+ puts
157
+ end
158
+
159
+ def jar_path(dep)
160
+ group_id = dep[:group_id]
161
+ group_path = group_id.gsub('.', '/')
162
+ artifact_id = dep[:artifact_id]
163
+ version = dep[:version]
164
+
165
+ file_name = "#{artifact_id}-#{version}.jar"
166
+ "#{group_path}/#{artifact_id}/#{version}/#{file_name}"
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,142 @@
1
+ # This file should typically not be required by user code. Requiring
2
+ # this file pulls in many jars onto the classpath (by running
3
+ # bootstrap!). MiniAether.resolve creates a separate ruby runtime in
4
+ # a separate classloader which is uses to load this resolver file and
5
+ # perform the bootstrapping operation.
6
+
7
+ require 'mini_aether'
8
+ require 'mini_aether/bootstrap'
9
+
10
+ MiniAether.extend(MiniAether::Bootstrap)
11
+ MiniAether.bootstrap!
12
+
13
+ module MiniAether
14
+ class Resolver
15
+ RepositorySystem =
16
+ Java::OrgSonatypeAether::RepositorySystem
17
+
18
+ MavenRepositorySystemSession =
19
+ Java::OrgApacheMavenRepositoryInternal::MavenRepositorySystemSession
20
+
21
+ LocalRepository =
22
+ Java::OrgSonatypeAetherRepository::LocalRepository
23
+
24
+ DefaultServiceLocator =
25
+ Java::OrgApacheMavenRepositoryInternal::DefaultServiceLocator
26
+
27
+ RepositoryConnectorFactory =
28
+ Java::OrgSonatypeAetherSpiConnector::RepositoryConnectorFactory
29
+
30
+ AsyncRepositoryConnectorFactory =
31
+ Java::OrgSonatypeAetherConnectorAsync::AsyncRepositoryConnectorFactory
32
+
33
+ FileRepositoryConnectorFactory =
34
+ Java::OrgSonatypeAetherConnectorFile::FileRepositoryConnectorFactory
35
+
36
+ Artifact = Java::OrgSonatypeAetherUtilArtifact::DefaultArtifact
37
+
38
+ Dependency = Java::OrgSonatypeAetherGraph::Dependency
39
+
40
+ RemoteRepository = Java::OrgSonatypeAetherRepository::RemoteRepository
41
+
42
+ CollectRequest = Java::OrgSonatypeAetherCollection::CollectRequest
43
+
44
+ DependencyRequest = Java::OrgSonatypeAetherResolution::DependencyRequest
45
+
46
+ PreorderNodeListGenerator = Java::OrgSonatypeAetherUtilGraph::PreorderNodeListGenerator
47
+
48
+ # set up connectors for service locator
49
+ LOCATOR = DefaultServiceLocator.new
50
+
51
+ MiB_PER_BYTE = 1024.0*1024.0
52
+
53
+
54
+ services =
55
+ [AsyncRepositoryConnectorFactory,
56
+ FileRepositoryConnectorFactory].map do |klass|
57
+ obj = klass.new
58
+ obj.initService LOCATOR
59
+ obj
60
+ end
61
+ LOCATOR.setServices(RepositoryConnectorFactory.java_class, *services)
62
+
63
+ def initialize
64
+ @logger = Java::OrgSlf4j::LoggerFactory.getLogger(self.class.to_s)
65
+ @system = LOCATOR.getService(RepositorySystem.java_class)
66
+ @session = MavenRepositorySystemSession.new
67
+ local_repo = LocalRepository.new(MiniAether.local_repository_path)
68
+ local_manager = @system.newLocalRepositoryManager(local_repo)
69
+ @session.setLocalRepositoryManager(local_manager)
70
+ end
71
+
72
+ def new_artifact(hash)
73
+ Artifact.new(hash[:group_id],
74
+ hash[:artifact_id],
75
+ hash[:extension] || 'jar',
76
+ hash[:version])
77
+ end
78
+
79
+ # Load dumps of the +dep_hashes+ and +repos+ args using
80
+ # +Marshal.load+ and then call #resolve. Useful for when the
81
+ # dependencies and repositories are constructed under a different
82
+ # Java classloader.
83
+ def resolve_foreign(deps_data, repos_data)
84
+ resolve(Marshal.load(deps_data), Marshal.load(repos_data))
85
+ end
86
+
87
+ # Resolve a set of dependencies +dep_hashes+ from repositories
88
+ # +repos+.
89
+ #
90
+ # @param [Array<Hash>] dep_hashes
91
+ #
92
+ # @option dep_hash [String] :group_id the groupId of the artifact
93
+ # @option dep_hash [String] :artifact_id the artifactId of the artifact
94
+ # @option dep_hash [String] :version the version (or range of versions) of the artifact
95
+ # @option dep_hash [String] :extension default to 'jar'
96
+ #
97
+ # @param [Array<String>] repos urls to maven2 repositories
98
+ #
99
+ # @return [Java::JavaUtil::List<Java::JavaIo::File>]
100
+ def resolve(dep_hashes, repos)
101
+ @logger.info 'resolving dependencies ({})', dep_hashes.size
102
+ collect_req = CollectRequest.new
103
+
104
+ dep_hashes.each do |hash|
105
+ dep = Dependency.new new_artifact(hash), 'compile'
106
+ collect_req.addDependency dep
107
+ @logger.info 'requested {}', dep
108
+ end
109
+
110
+ repos.each do |uri|
111
+ repo = RemoteRepository.new(uri.object_id.to_s, 'default', uri)
112
+ collect_req.addRepository repo
113
+ @logger.info 'added repository {}', repo
114
+ end
115
+
116
+ node = @system.collectDependencies(@session, collect_req).getRoot
117
+
118
+ dependency_req = DependencyRequest.new(node, nil)
119
+ @system.resolveDependencies(@session, dependency_req)
120
+
121
+ nlg = PreorderNodeListGenerator.new
122
+ node.accept nlg
123
+ files = nlg.getFiles
124
+
125
+ @logger.info "resolved with #{files.size} artifacts"
126
+
127
+ if @logger.isDebugEnabled
128
+ total_size = 0
129
+ nlg.getArtifacts(false).each do |artifact|
130
+ file = artifact.file
131
+ size = File.stat(artifact.file.absolute_path).size
132
+ total_size += size
133
+
134
+ @logger.debug("%0.2fMiB %s (%s)" % [size/MiB_PER_BYTE, artifact, file.name])
135
+ end
136
+ @logger.debug("%0.3f MiB total" % [total_size/MiB_PER_BYTE])
137
+ end
138
+
139
+ files
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,125 @@
1
+ require 'mini_aether'
2
+
3
+ module MiniAether
4
+ # A DSL to define and resolve dependencies. The Maven central
5
+ # repository is included by default.
6
+ #
7
+ # Example:
8
+ #
9
+ #
10
+ class Spec
11
+ class << self
12
+ def attr(*syms)
13
+ syms.each do |sym|
14
+ _attr(sym)
15
+ end
16
+ end
17
+
18
+ def _attr(sym)
19
+ define_method(sym) do |*args, &block|
20
+ value = if args && args.size > 0
21
+ args[0]
22
+ else
23
+ nil
24
+ end
25
+
26
+ iv = "@#{sym}".to_sym
27
+ if value
28
+ raise ArgumentError 'no effect without block' unless block
29
+ orig = instance_variable_get iv
30
+ instance_variable_set iv, value
31
+ begin
32
+ block.call
33
+ ensure
34
+ instance_variable_set iv, orig
35
+ end
36
+ else
37
+ instance_variable_get iv
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ attr_reader :dependencies, :sources
44
+
45
+ attr :group, :version
46
+
47
+ def initialize(&block)
48
+ @sources = [MAVEN_CENTRAL_REPO]
49
+ @dependencies = []
50
+
51
+ if block_given?
52
+ instance_eval &block
53
+ end
54
+ end
55
+
56
+ # Add a maven repository URL to the list of sources.
57
+ def source(uri)
58
+ sources << uri
59
+ end
60
+
61
+ # Declare a dependency using an explicit hash of parameters.
62
+ #
63
+ # @param [Hash] dependency
64
+ # @option dependency [String] :group_id the groupId of the artifact
65
+ # @option dependency [String] :artifact_id the artifactId of the artifact
66
+ # @option dependency [String] :version the version (or range of versions) of the artifact
67
+ # @option dependency [String] :extension defaults to 'jar'
68
+ def dep(dep_hash)
69
+ dependencies << dep_hash
70
+ end
71
+
72
+ def jar(coords)
73
+ dependencies << to_hash(coords)
74
+ end
75
+
76
+ def to_hash(coords)
77
+ components = coords.split(':')
78
+ case components.size
79
+ when 1
80
+ {
81
+ :group_id => group,
82
+ :artifact_id => components[0],
83
+ :version => version
84
+ }
85
+ when 2
86
+ if components[1] =~ /^\d/
87
+ {
88
+ :group_id => group,
89
+ :artifact_id => components[0],
90
+ :version => components[1]
91
+ }
92
+ else
93
+ {
94
+ :group_id => components[0],
95
+ :artifact_id => components[1],
96
+ :version => version
97
+ }
98
+ end
99
+ when 3
100
+ {
101
+ :group_id => components[0],
102
+ :artifact_id => components[1],
103
+ :version => components[2]
104
+ }
105
+ else
106
+ raise ArgumentError, "don't understand '#{coords}'"
107
+ end
108
+ end
109
+
110
+ # Resolve the dependencies using +MiniAether.resolve+.
111
+ #
112
+ # @return [Array<String>] an array of paths to artifact files
113
+ # (likely jar files) satisfying the dependencies
114
+ def resolve
115
+ MiniAether.resolve(dependencies, sources)
116
+ end
117
+
118
+ # Resolve the dependencies using +MiniAether.resolve+ and then
119
+ # require each of them (assumes each is a JAR file that may be
120
+ # required into JRuby).
121
+ def require
122
+ resolve.each { |jar| Kernel.require jar }
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,39 @@
1
+ require 'rexml/parsers/pullparser'
2
+
3
+ module MiniAether
4
+ # Simple helper methods around REXML pull parser.
5
+ #
6
+ # @author Patrick Mahoney <pat@polycrystal.org>
7
+ # @since 0.0.1, 1-June-2012
8
+ class XmlParser < REXML::Parsers::PullParser
9
+ class NotFoundError < RuntimeError; end
10
+
11
+ # Pull events until the start of an element of tag name +name+ is
12
+ # reached.
13
+ def pull_to_start(name)
14
+ loop do
15
+ res = pull
16
+ raise NotFoundError if res.event_type == :end_document
17
+ next if res.start_element? && res[0] == name.to_s
18
+ end
19
+ end
20
+
21
+ # Pull events to the start of each name, following a path of
22
+ # +name1/name2/...+.
23
+ def pull_to_path(*names)
24
+ names.each { |name| pull_to_start name }
25
+ end
26
+
27
+ # Pull all text nodes until the next +end_element+ event. Return
28
+ # the concatenation of text nodes.
29
+ def pull_text_until_end
30
+ texts = []
31
+ loop do
32
+ res = pull
33
+ break unless res.text?
34
+ texts << res[0]
35
+ end
36
+ texts.join
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,67 @@
1
+ require 'test_helper'
2
+
3
+ require 'mini_aether/bootstrap'
4
+
5
+ module MiniAether
6
+ class BootstrapTest < MiniTest::Unit::TestCase
7
+ class InterpolateTest < MiniTest::Unit::TestCase
8
+ def setup
9
+ @bootstrap = Object.new
10
+ @bootstrap.extend(Bootstrap)
11
+ end
12
+
13
+ def test_passes_through_plain_string
14
+ strs = [
15
+ 'hello',
16
+ '$ { nope } ',
17
+ 'text${text',
18
+ 'a a a a'
19
+ ]
20
+ strs.each do |str|
21
+ assert_equal str, @bootstrap.interpolate(str)
22
+ end
23
+ end
24
+
25
+ def test_interpolates_env_vars
26
+ key = '__AETHER_INTERPOLATE_TEST__'
27
+ ENV[key] = 'value'
28
+ assert_equal 'value', @bootstrap.interpolate("${env.#{key}}")
29
+ assert_equal 'aaa value', @bootstrap.interpolate("aaa ${env.#{key}}")
30
+ assert_equal 'value aaa', @bootstrap.interpolate("${env.#{key}} aaa")
31
+ assert_equal 'value}', @bootstrap.interpolate("${env.#{key}}}")
32
+ assert_equal 'avaluea', @bootstrap.interpolate("a${env.#{key}}a")
33
+
34
+ assert_equal 'a value a value a', @bootstrap.interpolate("a ${env.#{key}} a ${env.#{key}} a")
35
+ ensure
36
+ ENV[key] = nil
37
+ end
38
+
39
+ def test_empty_string_when_no_env_var
40
+ assert_nil ENV['NO_SUCH_ENV_VAR']
41
+ assert_equal '', @bootstrap.interpolate("${env.NO_SUCH_ENV_VAR}")
42
+ end
43
+
44
+ def test_interpolates_system_props
45
+ key = '__AETHER_INTERPOLATE_TEST__'
46
+ sys = Java::JavaLang::System
47
+ sys.setProperty(key, 'value')
48
+
49
+ assert_equal 'value', @bootstrap.interpolate("${#{key}}")
50
+ assert_equal 'aaa value', @bootstrap.interpolate("aaa ${#{key}}")
51
+ assert_equal 'value aaa', @bootstrap.interpolate("${#{key}} aaa")
52
+ assert_equal 'value}', @bootstrap.interpolate("${#{key}}}")
53
+ assert_equal 'avaluea', @bootstrap.interpolate("a${#{key}}a")
54
+
55
+ assert_equal 'a value a value a', @bootstrap.interpolate("a ${#{key}} a ${#{key}} a")
56
+ ensure
57
+ sys.clearProperty(key)
58
+ end
59
+
60
+ def test_empty_string_when_no_sys_prop
61
+ sys = Java::JavaLang::System
62
+ assert_nil sys.getProperty 'NO_SUCH_ENV_VAR'
63
+ assert_equal '', @bootstrap.interpolate("${NO_SUCH_ENV_VAR}")
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,74 @@
1
+ require 'test_helper'
2
+
3
+ module MiniAether
4
+ class SpecTest < MiniTest::Unit::TestCase
5
+ def test_hash_arg
6
+ spec = Spec.new do
7
+ dep(:group_id => 'group',
8
+ :artifact_id => 'artifact',
9
+ :version => '1')
10
+ end
11
+
12
+ hash = {
13
+ :group_id => 'group',
14
+ :artifact_id => 'artifact',
15
+ :version => '1'
16
+ }
17
+ assert_equal hash, spec.dependencies.first
18
+ end
19
+
20
+ def assert_deps(spec)
21
+ hash = {
22
+ :group_id => 'group',
23
+ :artifact_id => 'artifact',
24
+ :version => '1'
25
+ }
26
+
27
+ spec.dependencies.each do |dep|
28
+ assert_equal hash, dep
29
+ end
30
+ end
31
+
32
+ def test_full_coords
33
+ assert_deps(Spec.new do
34
+ jar 'group:artifact:1'
35
+ end)
36
+ end
37
+
38
+ def test_default_group
39
+ assert_deps(Spec.new do
40
+ group 'group' do
41
+ jar 'artifact:1'
42
+ end
43
+ end)
44
+ end
45
+
46
+ def test_default_group_and_version
47
+ assert_deps(Spec.new do
48
+ group 'group' do
49
+ version '1' do
50
+ jar 'artifact'
51
+ end
52
+ end
53
+ end)
54
+ end
55
+
56
+ def test_default_version
57
+ assert_deps(Spec.new do
58
+ version '1' do
59
+ jar 'group:artifact'
60
+ end
61
+ end)
62
+ end
63
+
64
+ def test_default_version2
65
+ assert_deps(Spec.new do
66
+ group 'bad' do
67
+ version '1' do
68
+ jar 'group:artifact'
69
+ end
70
+ end
71
+ end)
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,43 @@
1
+ require 'test_helper'
2
+
3
+ require 'tmpdir'
4
+
5
+ class MiniAetherTest < MiniTest::Unit::TestCase
6
+ System = Java::JavaLang::System
7
+
8
+ def test_bootstrap
9
+ orig_home = System.getProperty('user.home')
10
+ begin
11
+ Dir.mktmpdir do |dir|
12
+ System.setProperty('user.home', dir)
13
+
14
+ deps = [{
15
+ :group_id => 'net.jcip',
16
+ :artifact_id => 'jcip-annotations',
17
+ :version => '1.0'
18
+ }]
19
+ sources = [MiniAether::MAVEN_CENTRAL_REPO]
20
+ MiniAether.resolve(deps, sources)
21
+
22
+ files = Dir["#{dir}/.m2/**/*.jar"].map{|file| File.basename(file, '.jar')}
23
+ assert_includes files, 'aether-api-1.13.1'
24
+ end
25
+ ensure
26
+ System.setProperty('user.home', orig_home)
27
+ end
28
+ end
29
+
30
+ def test_resolves_dependencies
31
+ deps = [{
32
+ :group_id => 'org.jboss.resteasy',
33
+ :artifact_id => 'resteasy-jaxrs',
34
+ :version => '2.3.4.Final'
35
+ }]
36
+ sources = [MiniAether::MAVEN_CENTRAL_REPO]
37
+ jars = MiniAether.resolve(deps, sources).map{|file| File.basename(file, '.jar')}
38
+
39
+ assert_equal 12, jars.size
40
+ assert_includes jars, 'resteasy-jaxrs-2.3.4.Final'
41
+ assert_includes jars, 'httpclient-4.1.2'
42
+ end
43
+ end
@@ -0,0 +1,3 @@
1
+ require 'minitest/autorun'
2
+
3
+ require 'mini_aether'
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mini_aether
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: 5
5
+ version: 0.0.1a
6
+ platform: java
7
+ authors:
8
+ - Patrick Mahoney
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-10-01 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: minitest
16
+ version_requirements: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ! '>='
19
+ - !ruby/object:Gem::Version
20
+ version: !binary |-
21
+ MA==
22
+ none: false
23
+ requirement: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ! '>='
26
+ - !ruby/object:Gem::Version
27
+ version: !binary |-
28
+ MA==
29
+ none: false
30
+ prerelease: false
31
+ type: :development
32
+ - !ruby/object:Gem::Dependency
33
+ name: rake
34
+ version_requirements: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: !binary |-
39
+ MA==
40
+ none: false
41
+ requirement: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: !binary |-
46
+ MA==
47
+ none: false
48
+ prerelease: false
49
+ type: :development
50
+ - !ruby/object:Gem::Dependency
51
+ name: version
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: !binary |-
57
+ MA==
58
+ none: false
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: !binary |-
64
+ MA==
65
+ none: false
66
+ prerelease: false
67
+ type: :development
68
+ description: Resolves Aether artifact dependencies, downloads, and requires them.
69
+ email: pat@polycrystal.org
70
+ executables: []
71
+ extensions: []
72
+ extra_rdoc_files:
73
+ - README.md
74
+ - COPYING
75
+ files:
76
+ - !binary |-
77
+ bGliL21pbmlfYWV0aGVyLnJi
78
+ - !binary |-
79
+ bGliL21pbmlfYWV0aGVyL2Jvb3RzdHJhcC5yYg==
80
+ - !binary |-
81
+ bGliL21pbmlfYWV0aGVyL3Jlc29sdmVyLnJi
82
+ - !binary |-
83
+ bGliL21pbmlfYWV0aGVyL3NwZWMucmI=
84
+ - !binary |-
85
+ bGliL21pbmlfYWV0aGVyL3htbF9wYXJzZXIucmI=
86
+ - !binary |-
87
+ dGVzdC90ZXN0X2hlbHBlci5yYg==
88
+ - !binary |-
89
+ dGVzdC9taW5pX2FldGhlcl90ZXN0LnJi
90
+ - !binary |-
91
+ dGVzdC9taW5pX2FldGhlci9zcGVjX3Rlc3QucmI=
92
+ - !binary |-
93
+ dGVzdC9taW5pX2FldGhlci9ib290c3RyYXBfdGVzdC5yYg==
94
+ - README.md
95
+ - COPYING
96
+ homepage: https://github.com/pmahoney/mini_aether
97
+ licenses: []
98
+ post_install_message:
99
+ rdoc_options: []
100
+ require_paths:
101
+ - lib
102
+ required_ruby_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ! '>='
105
+ - !ruby/object:Gem::Version
106
+ segments:
107
+ - 0
108
+ hash: 2
109
+ version: !binary |-
110
+ MA==
111
+ none: false
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - !binary |-
115
+ Pg==
116
+ - !ruby/object:Gem::Version
117
+ version: 1.3.1
118
+ none: false
119
+ requirements: []
120
+ rubyforge_project:
121
+ rubygems_version: 1.8.24
122
+ signing_key:
123
+ specification_version: 3
124
+ summary: wrapper around some parts of aether
125
+ test_files: []