bee_java 0.0.1

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.
@@ -0,0 +1,482 @@
1
+ # Copyright 2008-2009 Michel Casabianca <michel.casabianca@gmail.com>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'net/http'
16
+ require 'fileutils'
17
+ require 'rexml/document'
18
+ require 'rexml/xpath'
19
+ require 'bee_util'
20
+
21
+ module Bee
22
+
23
+ module Task
24
+
25
+ # Parent of all dependency resolvers.
26
+ class BaseDependencyResolver
27
+
28
+ include Bee::Util::BuildErrorMixin
29
+
30
+ # Default repository.
31
+ DEFAULT_REPOSITORY = nil
32
+ # Default cache location.
33
+ DEFAULT_CACHE = nil
34
+ # Default dependency scope.
35
+ DEFAULT_SCOPE = 'compile'
36
+
37
+ # Constructor:
38
+ # - file: dependency file (should be maven.xml).
39
+ # - scope: the scope for dependencies (compile, runtime or test).
40
+ # - verbose: tells if we should be verbose.
41
+ def initialize(file, scope, verbose=false)
42
+ @file = file
43
+ @scope = scope
44
+ @verbose = verbose
45
+ @repositories = parse_repositories
46
+ @cache = DEFAULT_CACHE
47
+ @dependencies = nil
48
+ # print information if verbose
49
+ puts "Repositories: #{@repositories.join(', ')}" if @verbose
50
+ end
51
+
52
+ # Return the classpath.
53
+ def classpath
54
+ synchronize
55
+ classpath = @dependencies.map do |dependency|
56
+ build_path(@cache, dependency)
57
+ end
58
+ return classpath.join(File::PATH_SEPARATOR)
59
+ end
60
+
61
+ # Return dependencies as a list.
62
+ def dependencies
63
+ synchronize
64
+ dependencies = @dependencies.map do |dependency|
65
+ build_path(@cache, dependency)
66
+ end
67
+ return dependencies
68
+ end
69
+
70
+ private
71
+
72
+ # Resolve dependencies.
73
+ # Returns dependencies as a list.
74
+ def resolve
75
+ @dependencies = parse_dependencies(File.read(@file)) if
76
+ not @dependencies
77
+ return @dependencies
78
+ end
79
+
80
+ # Synchronize dependencies with local cache.
81
+ def synchronize
82
+ resolve
83
+ for dependency in @dependencies
84
+ tofile = build_path(@cache, dependency)
85
+ if not File.exists?(tofile)
86
+ save_file(download(dependency), tofile)
87
+ else
88
+ puts "Dependency '#{build_name(dependency)}' already downloaded" if
89
+ @verbose
90
+ end
91
+ end
92
+ end
93
+
94
+ # Extract repository list from file.
95
+ # Return: repository list.
96
+ def parse_repositories
97
+ raise 'Not implemented'
98
+ end
99
+
100
+ # Download a given dependency.
101
+ # - dependency: dependency as a map.
102
+ # Return: dependency as a binary.
103
+ def download(dependency, log=true)
104
+ name = build_name(dependency)
105
+ puts "Downloading dependency '#{name}'..." if log or @verbose
106
+ for repository in @repositories
107
+ url = build_path(repository, dependency)
108
+ puts "Trying '#{url}'..." if @verbose
109
+ begin
110
+ return fetch(url)
111
+ rescue
112
+ end
113
+ end
114
+ error "Dependency '#{name}' not found"
115
+ end
116
+
117
+ # Build a Maven path.
118
+ # - root: the path root (root directory for repository or cache).
119
+ # - dependency: dependency as a map.
120
+ # Return: path as a string.
121
+ def build_path(root, dependency)
122
+ raise 'Not implemented'
123
+ end
124
+
125
+ # Build dependency name for display.
126
+ # - dependency: dependency as a map.
127
+ # Return: name as a string.
128
+ def build_name(dependency)
129
+ groupid = dependency[:groupid]
130
+ artifactid = dependency[:artifactid]
131
+ version = dependency[:version]
132
+ type = dependency[:type] || 'jar'
133
+ return "#{artifactid}:#{groupid}:#{version}:#{type}"
134
+ end
135
+
136
+ # Extract dependencies from a file.
137
+ # - source: file source.
138
+ # Return: dependencies as a list of maps with keys groupid, artifactid,
139
+ # version, type, optional.
140
+ def parse_dependencies(source)
141
+ raise 'Not implemented'
142
+ end
143
+
144
+ # Tells if a given dependency should be selected.
145
+ # - dependency: the dependency to consider.
146
+ def selected?(dependency)
147
+ return false if dependency[:optional] == 'true'
148
+ dep_scope = dependency[:scope] || DEFAULT_SCOPE
149
+ if @scope == 'compile'
150
+ if dep_scope == 'compile'
151
+ return true
152
+ else
153
+ return false
154
+ end
155
+ elsif @scope == 'runtime'
156
+ if dep_scope == 'compile' or dep_scope == 'runtime'
157
+ return true
158
+ else
159
+ return false
160
+ end
161
+ elsif @scope == 'test'
162
+ if dep_scope == 'compile' or dep_scope == 'runtime' or dep_scope == 'test'
163
+ return true
164
+ else
165
+ return false
166
+ end
167
+ end
168
+ end
169
+
170
+ # Save a given binary in a file and create directories as necessary.
171
+ # - binary: data to save.
172
+ # - tofile: file to save into.
173
+ def save_file(binary, tofile)
174
+ puts "Saving file '#{tofile}'..." if @verbose
175
+ directory = File.dirname(tofile)
176
+ FileUtils.makedirs(directory) if not File.exists?(directory)
177
+ File.open(tofile, 'wb') { |file| file.write(binary) }
178
+ end
179
+
180
+ # Maximum number of HTTP redirections.
181
+ HTTP_REDIRECTIONS_LIMIT = 10
182
+
183
+ # Get a given URL.
184
+ # - url: URL to get.
185
+ # - limit: redirectrion limit (defaults to HTTP_REDIRECTIONS_LIMIT).
186
+ def fetch(url, limit = HTTP_REDIRECTIONS_LIMIT)
187
+ puts "Fetching '#{url}'..." if @verbose
188
+ raise 'HTTP redirect too deep' if limit == 0
189
+ response = Net::HTTP.get_response(URI.parse(url))
190
+ case response
191
+ when Net::HTTPSuccess
192
+ response.body
193
+ when Net::HTTPRedirection
194
+ fetch(response['location'], limit - 1)
195
+ else
196
+ response.error!
197
+ end
198
+ end
199
+
200
+ end
201
+
202
+ # Bee dependency resolver.
203
+ class BeeDependencyResolver < BaseDependencyResolver
204
+
205
+ # Default repository address.
206
+ DEFAULT_REPOSITORY = 'http://repo1.maven.org/maven2'
207
+ # Default cache location.
208
+ DEFAULT_CACHE = File.expand_path('~/.java/dependencies')
209
+
210
+ # Constructor:
211
+ # - file: dependency file (should be maven.xml).
212
+ # - scope: the scope for dependencies (compile, runtime or test).
213
+ # - verbose: tells if we should be verbose.
214
+ def initialize(file, scope, verbose=false)
215
+ super(file, scope, verbose)
216
+ @cache = DEFAULT_CACHE
217
+ end
218
+
219
+ # Extract dependencies from a file.
220
+ # - source: file source.
221
+ # Return: dependencies as a list of maps with keys groupid, artifactid,
222
+ # version, type, optional.
223
+ def parse_dependencies(source)
224
+ dependencies = YAML::load(source)
225
+ new_dependencies = []
226
+ for dependency in dependencies
227
+ if dependency['group']
228
+ new_dependency = {}
229
+ for key in dependency.keys
230
+ if key != 'group' and key != 'artifact'
231
+ new_dependency[key.to_sym] = dependency[key]
232
+ elsif key == 'group'
233
+ new_dependency[:groupid] = dependency['group']
234
+ elsif key == 'artifact'
235
+ new_dependency[:artifactid] = dependency['artifact']
236
+ end
237
+ end
238
+ new_dependencies << new_dependency
239
+ end
240
+ end
241
+ return new_dependencies
242
+ end
243
+
244
+ # Extract repository list from file.
245
+ # Return: repository list.
246
+ def parse_repositories
247
+ repositories = YAML::load(File.read(@file))
248
+ new_repositories = []
249
+ for repository in repositories
250
+ if repository['repository']
251
+ new_repositories << repository['repository']
252
+ elsif repository['repositories']
253
+ new_repositories = new_repositories + repository['repositories']
254
+ end
255
+ end
256
+ return new_repositories
257
+ end
258
+
259
+ # Build a Maven path.
260
+ # - root: the path root (root directory for repository or cache).
261
+ # - dependency: dependency as a map.
262
+ # Return: path as a string.
263
+ def build_path(root, dependency)
264
+ groupid = dependency[:groupid].split('.').join('/')
265
+ artifactid = dependency[:artifactid]
266
+ version = dependency[:version]
267
+ type = dependency[:type] || 'jar'
268
+ classifier = dependency[:classifier]
269
+ if classifier
270
+ return "#{root}/#{groupid}/#{artifactid}/#{version}/#{artifactid}-#{version}-#{classifier}.#{type}"
271
+ else
272
+ return "#{root}/#{groupid}/#{artifactid}/#{version}/#{artifactid}-#{version}.#{type}"
273
+ end
274
+ end
275
+
276
+ end
277
+
278
+ # Maven 1 dependency resolver.
279
+ class MavenDependencyResolver < BaseDependencyResolver
280
+
281
+ include Bee::Util::BuildErrorMixin
282
+
283
+ # Default repository.
284
+ DEFAULT_REPOSITORY = 'http://repo1.maven.org/maven'
285
+ # Default cache location.
286
+ DEFAULT_CACHE = File.expand_path('~/.maven/repository')
287
+ # Default dependency scope.
288
+ DEFAULT_SCOPE = 'compile'
289
+
290
+ # Constructor:
291
+ # - file: dependency file (should be maven.xml).
292
+ # - scope: the scope for dependencies (compile, runtime or test).
293
+ # - verbose: tells if we should be verbose.
294
+ def initialize(file, scope, verbose=false)
295
+ super(file, scope, verbose)
296
+ @cache = DEFAULT_CACHE
297
+ end
298
+
299
+ private
300
+
301
+ # Synchronize dependencies with local cache.
302
+ def synchronize
303
+ resolve
304
+ for dependency in @dependencies
305
+ tofile = build_path(@cache, dependency)
306
+ if not File.exists?(tofile)
307
+ save_file(download(dependency), tofile)
308
+ else
309
+ puts "Dependency '#{build_name(dependency)}' already downloaded" if
310
+ @verbose
311
+ end
312
+ end
313
+ end
314
+
315
+ # Extract repository list from file.
316
+ # Return: repository list.
317
+ def parse_repositories
318
+ repositories = []
319
+ doc = REXML::Document.new(File.read(@file))
320
+ REXML::XPath.each(doc, '/project/repository') do |element|
321
+ REXML::XPath.each(element, 'url') do |entry|
322
+ repositories << entry.text.strip
323
+ end
324
+ end
325
+ repositories << DEFAULT_REPOSITORY if repositories.empty?
326
+ return repositories
327
+ end
328
+
329
+ # Build a Maven path.
330
+ # - root: the path root (root directory for repository or cache).
331
+ # - dependency: dependency as a map.
332
+ # Return: path as a string.
333
+ def build_path(root, dependency)
334
+ groupid = dependency[:groupid]
335
+ artifactid = dependency[:artifactid]
336
+ version = dependency[:version]
337
+ type = dependency[:type] || 'jar'
338
+ return "#{root}/#{groupid}/#{type}s/#{artifactid}-#{version}.#{type}"
339
+ end
340
+
341
+ # Extract dependencies from a file.
342
+ # - source: file source.
343
+ # Return: dependencies as a list of maps with keys groupid, artifactid,
344
+ # version, type, optional.
345
+ def parse_dependencies(source)
346
+ dependencies = []
347
+ doc = REXML::Document.new(source)
348
+ properties = {}
349
+ REXML::XPath.each(doc, '/project/properties/*') do |element|
350
+ name = element.name.strip
351
+ value = element.text
352
+ value = value.strip if value
353
+ properties[name] = value
354
+ end
355
+ REXML::XPath.each(doc, '/project/dependencies/dependency') do |element|
356
+ dependency = {}
357
+ REXML::XPath.each(element, '*') do |entry|
358
+ name = entry.name.downcase.to_sym
359
+ value = entry.text.strip
360
+ for key in properties.keys
361
+ value = value.gsub(/\$\{#{key}\}/, properties[key]) if
362
+ properties[key]
363
+ end
364
+ dependency[name] = value
365
+ end
366
+ dependencies << dependency if selected?(dependency)
367
+ end
368
+ return dependencies
369
+ end
370
+
371
+ end
372
+
373
+ # Maven 2 dependency resolver.
374
+ class Maven2DependencyResolver < MavenDependencyResolver
375
+
376
+ # Default repository address.
377
+ DEFAULT_REPOSITORY = 'http://repo1.maven.org/maven2'
378
+ # Default cache location.
379
+ DEFAULT_CACHE = File.expand_path('~/.m2/repository')
380
+
381
+ # Constructor:
382
+ # - file: dependency file (should be maven.xml).
383
+ # - scope: the scope for dependencies (compile, runtime or test).
384
+ # - verbose: tells if we should be verbose.
385
+ def initialize(file, scope, verbose=false)
386
+ super(file, scope, verbose)
387
+ @cache = DEFAULT_CACHE
388
+ end
389
+
390
+ private
391
+
392
+ # Resolve dependencies.
393
+ # Returns dependencies as a list.
394
+ def resolve
395
+ if not @dependencies
396
+ @dependencies = parse_dependencies(File.read(@file))
397
+ for dependency in @dependencies
398
+ @dependencies = @dependencies + recurse_dependency(dependency)
399
+ end
400
+ end
401
+ return @dependencies
402
+ end
403
+
404
+ # Recurse on a given dependency.
405
+ # - dependency: depedency to recurse over as a map.
406
+ # Return: dependencies as a list.
407
+ def recurse_dependency(dependency)
408
+ pom = dependency.clone
409
+ pom[:type] = 'pom'
410
+ new_dependencies = []
411
+ begin
412
+ pom_file = build_path(@cache, pom)
413
+ if not File.exists?(pom_file)
414
+ new_pom = download(pom, false)
415
+ save_file(new_pom, pom_file)
416
+ else
417
+ name = build_name(pom)
418
+ puts "POM file '#{name}' already downloaded" if @verbose
419
+ new_pom = File.read(pom_file)
420
+ end
421
+ new_dependencies = parse_dependencies(new_pom)
422
+ for new_dependency in new_dependencies
423
+ to_add = recurse_dependency(new_dependency)
424
+ new_dependencies = new_dependencies + to_add if not to_add.empty
425
+ end
426
+ rescue
427
+ end
428
+ return new_dependencies
429
+ end
430
+
431
+ # Extract repository list from POM file or
432
+ # Return: repository list.
433
+ def parse_repositories
434
+ repositories = []
435
+ # search for repositories in POM file
436
+ doc = REXML::Document.new(File.read(@file))
437
+ REXML::XPath.each(doc, '/project/distributionManagement/repository') do |element|
438
+ REXML::XPath.each(element, 'url') do |entry|
439
+ repositories << entry.text.strip
440
+ end
441
+ end
442
+ # search for repositories in cache repository
443
+ begin
444
+ doc = REXML::Document.new(File.read(File.expand_path('~/.m2/settings.xml')))
445
+ REXML::XPath.each(doc, '/settings/mirrors/mirror') do |element|
446
+ REXML::XPath.each(element, 'url') do |entry|
447
+ repositories << entry.text.strip
448
+ end
449
+ end
450
+ REXML::XPath.each(doc, '/settings/profiles/profile/repositories/repository') do |element|
451
+ REXML::XPath.each(element, 'url') do |entry|
452
+ repositories << entry.text.strip
453
+ end
454
+ end
455
+ rescue
456
+ end
457
+ repositories << DEFAULT_REPOSITORY if repositories.empty?
458
+ return repositories.uniq
459
+ end
460
+
461
+ # Build a Maven path.
462
+ # - root: the path root (root directory for repository or cache).
463
+ # - dependency: dependency as a map.
464
+ # Return: path as a string.
465
+ def build_path(root, dependency)
466
+ groupid = dependency[:groupid].split('.').join('/')
467
+ artifactid = dependency[:artifactid]
468
+ version = dependency[:version]
469
+ type = dependency[:type] || 'jar'
470
+ classifier = dependency[:classifier]
471
+ if classifier
472
+ return "#{root}/#{groupid}/#{artifactid}/#{version}/#{artifactid}-#{version}-#{classifier}.#{type}"
473
+ else
474
+ return "#{root}/#{groupid}/#{artifactid}/#{version}/#{artifactid}-#{version}.#{type}"
475
+ end
476
+ end
477
+
478
+ end
479
+
480
+ end
481
+
482
+ end
data/test/build.yml ADDED
@@ -0,0 +1,125 @@
1
+ # Copyright 2008-2009 Michel Casabianca <michel.casabianca@gmail.com>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ - build: test_java
16
+ default: all
17
+ description: Build file to test Java package
18
+
19
+ - properties:
20
+ - name: "test"
21
+ - src: "src"
22
+ - build: "build"
23
+ - classes: "#{build}/classes"
24
+ - javadoc: "#{build}/api"
25
+ - jar: "#{build}/#{name}.jar"
26
+ - erb: "manifest.erb"
27
+ - manifest: "#{build}/manifest"
28
+ - main: "test.Test"
29
+ - classpath: :jar
30
+ - junit: "/opt/java/junit-4.4"
31
+ - test: "test"
32
+ - test_classes: "#{build}/test-classes"
33
+ - lib: "#{build}/lib"
34
+
35
+ - target: javac
36
+ description: Test javac task
37
+ script:
38
+ - java.javac:
39
+ src: :src
40
+ dest: :classes
41
+
42
+ - target: jar
43
+ depends: javac
44
+ description: Test jar task
45
+ script:
46
+ - erb:
47
+ src: :erb
48
+ dest: :manifest
49
+ - java.jar:
50
+ src: :classes
51
+ manifest: :manifest
52
+ dest: :jar
53
+
54
+ - target: junit
55
+ depends: javac
56
+ description: Run unit tests
57
+ script:
58
+ - find:
59
+ includes: "#{junit}/junit*.jar"
60
+ excludes: "#{junit}/junit*-src.jar"
61
+ property: junit_cp
62
+ - java.javac:
63
+ src: :test
64
+ dest: :test_classes
65
+ classpath: [:junit_cp, :classes]
66
+ - java.junit:
67
+ classpath: [:classes, :test_classes, :junit_cp]
68
+ src: :test
69
+
70
+ - target: javadoc
71
+ description: Document Java source files
72
+ script:
73
+ - java.javadoc:
74
+ src: :src
75
+ dest: :javadoc
76
+
77
+ - target: java
78
+ depends: jar
79
+ description: Run java program
80
+ script:
81
+ - java.java:
82
+ main: :main
83
+ classpath: :classpath
84
+ properties: { who: World }
85
+ - java.java:
86
+ main: :main
87
+ classpath: :classes
88
+ properties: { who: World }
89
+ - java.java:
90
+ jar: :jar
91
+ properties: { who: World }
92
+
93
+ - target: deps
94
+ description: Fetch dependencies
95
+ script:
96
+ # maven 1 repository
97
+ - rmdir: :build
98
+ - java.deps:
99
+ src: dependencies.yml
100
+ dest: :lib
101
+ repos: http://www.ibiblio.org/maven
102
+ # maven 2 repository
103
+ - rmdir: :build
104
+ - java.deps:
105
+ src: dependencies.xml
106
+ dest: :lib
107
+ repos: http://repo1.maven.org/maven2
108
+ repotype: maven2
109
+
110
+ - target: classpath
111
+ description: Compute a classpath
112
+ script:
113
+ #- java.clean:
114
+ - java.classpath:
115
+ file: pom.xml
116
+ property: classpath
117
+ - print: :classpath
118
+
119
+ - target: clean
120
+ description: Clean generated files
121
+ script:
122
+ - rmdir: :build
123
+
124
+ - target: all
125
+ depends: [clean, javac, jar, junit, javadoc, java, deps]
@@ -0,0 +1,11 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+
3
+ <project>
4
+ <dependencies>
5
+ <dependency>
6
+ <groupId>junit</groupId>
7
+ <artifactId>junit</artifactId>
8
+ <version>4.3</version>
9
+ </dependency>
10
+ </dependencies>
11
+ </project>
@@ -0,0 +1,3 @@
1
+ - group: junit
2
+ artifact: junit
3
+ version: 4.3
data/test/manifest.erb ADDED
@@ -0,0 +1 @@
1
+ Main-Class: <%= main %>
data/test/pom.xml ADDED
@@ -0,0 +1,31 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+
3
+ <project>
4
+
5
+ <modelVersion>4.0.0</modelVersion>
6
+ <groupId>test</groupId>
7
+ <artifactId>test</artifactId>
8
+ <name>Test</name>
9
+ <version>1.0.0</version>
10
+
11
+ <repositories>
12
+ <repository>
13
+ <id>central</id>
14
+ <name>Maven Repository Switchboard</name>
15
+ <layout>default</layout>
16
+ <url>http://repo1.maven.org/maven2</url>
17
+ <snapshots>
18
+ <enabled>false</enabled>
19
+ </snapshots>
20
+ </repository>
21
+ </repositories>
22
+
23
+ <dependencies>
24
+ <dependency>
25
+ <groupId>ehcache</groupId>
26
+ <artifactId>ehcache</artifactId>
27
+ <version>1.2beta4</version>
28
+ </dependency>
29
+ </dependencies>
30
+
31
+ </project>
@@ -0,0 +1,28 @@
1
+ // Copyright 2008-2009 Michel Casabianca <michel.casabianca@gmail.com>
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ package test;
16
+
17
+ public class Test {
18
+
19
+ public static void main(String[] args) {
20
+ String who = System.getProperty("who");
21
+ System.out.println(hello(who));
22
+ }
23
+
24
+ public static String hello(String who) {
25
+ return "Hello "+who+"!";
26
+ }
27
+
28
+ }