mini_aether 0.0.1a-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []